Changeset View
Changeset View
Standalone View
Standalone View
src/script/interpreter.cpp
Show First 20 Lines • Show All 1,686 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
// explicit instantiation | // explicit instantiation | ||||
template class GenericTransactionSignatureChecker<CTransaction>; | template class GenericTransactionSignatureChecker<CTransaction>; | ||||
template class GenericTransactionSignatureChecker<CMutableTransaction>; | template class GenericTransactionSignatureChecker<CMutableTransaction>; | ||||
bool VerifyScript(const CScript &scriptSig, const CScript &scriptPubKey, | bool VerifyScript(const CScript &scriptSig, const CScript &scriptPubKey, | ||||
uint32_t flags, const BaseSignatureChecker &checker, | uint32_t flags, const BaseSignatureChecker &checker, | ||||
ScriptError *serror) { | ScriptExecutionMetrics &metricsOut, ScriptError *serror) { | ||||
set_error(serror, ScriptError::UNKNOWN); | set_error(serror, ScriptError::UNKNOWN); | ||||
// If FORKID is enabled, we also ensure strict encoding. | // If FORKID is enabled, we also ensure strict encoding. | ||||
if (flags & SCRIPT_ENABLE_SIGHASH_FORKID) { | if (flags & SCRIPT_ENABLE_SIGHASH_FORKID) { | ||||
flags |= SCRIPT_VERIFY_STRICTENC; | flags |= SCRIPT_VERIFY_STRICTENC; | ||||
} | } | ||||
if ((flags & SCRIPT_VERIFY_SIGPUSHONLY) != 0 && !scriptSig.IsPushOnly()) { | if ((flags & SCRIPT_VERIFY_SIGPUSHONLY) != 0 && !scriptSig.IsPushOnly()) { | ||||
return set_error(serror, ScriptError::SIG_PUSHONLY); | return set_error(serror, ScriptError::SIG_PUSHONLY); | ||||
} | } | ||||
ScriptExecutionMetrics metrics = {}; | |||||
std::vector<valtype> stack, stackCopy; | std::vector<valtype> stack, stackCopy; | ||||
if (!EvalScript(stack, scriptSig, flags, checker, serror)) { | if (!EvalScript(stack, scriptSig, flags, checker, metrics, serror)) { | ||||
// serror is set | // serror is set | ||||
return false; | return false; | ||||
} | } | ||||
if (flags & SCRIPT_VERIFY_P2SH) { | if (flags & SCRIPT_VERIFY_P2SH) { | ||||
stackCopy = stack; | stackCopy = stack; | ||||
} | } | ||||
if (!EvalScript(stack, scriptPubKey, flags, checker, serror)) { | if (!EvalScript(stack, scriptPubKey, flags, checker, metrics, serror)) { | ||||
// serror is set | // serror is set | ||||
return false; | return false; | ||||
} | } | ||||
if (stack.empty()) { | if (stack.empty()) { | ||||
return set_error(serror, ScriptError::EVAL_FALSE); | return set_error(serror, ScriptError::EVAL_FALSE); | ||||
} | } | ||||
if (CastToBool(stack.back()) == false) { | if (CastToBool(stack.back()) == false) { | ||||
return set_error(serror, ScriptError::EVAL_FALSE); | return set_error(serror, ScriptError::EVAL_FALSE); | ||||
Show All 18 Lines | if ((flags & SCRIPT_VERIFY_P2SH) && scriptPubKey.IsPayToScriptHash()) { | ||||
CScript pubKey2(pubKeySerialized.begin(), pubKeySerialized.end()); | CScript pubKey2(pubKeySerialized.begin(), pubKeySerialized.end()); | ||||
popstack(stack); | popstack(stack); | ||||
// Bail out early if SCRIPT_DISALLOW_SEGWIT_RECOVERY is not set, the | // Bail out early if SCRIPT_DISALLOW_SEGWIT_RECOVERY is not set, the | ||||
// redeem script is a p2sh segwit program, and it was the only item | // redeem script is a p2sh segwit program, and it was the only item | ||||
// pushed onto the stack. | // pushed onto the stack. | ||||
if ((flags & SCRIPT_DISALLOW_SEGWIT_RECOVERY) == 0 && stack.empty() && | if ((flags & SCRIPT_DISALLOW_SEGWIT_RECOVERY) == 0 && stack.empty() && | ||||
pubKey2.IsWitnessProgram()) { | pubKey2.IsWitnessProgram()) { | ||||
// must set metricsOut for all successful returns | |||||
metricsOut = metrics; | |||||
return set_success(serror); | return set_success(serror); | ||||
} | } | ||||
if (!EvalScript(stack, pubKey2, flags, checker, serror)) { | if (!EvalScript(stack, pubKey2, flags, checker, metrics, serror)) { | ||||
// serror is set | // serror is set | ||||
return false; | return false; | ||||
} | } | ||||
if (stack.empty()) { | if (stack.empty()) { | ||||
return set_error(serror, ScriptError::EVAL_FALSE); | return set_error(serror, ScriptError::EVAL_FALSE); | ||||
} | } | ||||
if (!CastToBool(stack.back())) { | if (!CastToBool(stack.back())) { | ||||
return set_error(serror, ScriptError::EVAL_FALSE); | return set_error(serror, ScriptError::EVAL_FALSE); | ||||
Show All 9 Lines | if ((flags & SCRIPT_VERIFY_CLEANSTACK) != 0) { | ||||
// CLEANSTACK->P2SH+CLEANSTACK would be possible, which is not a | // CLEANSTACK->P2SH+CLEANSTACK would be possible, which is not a | ||||
// softfork (and P2SH should be one). | // softfork (and P2SH should be one). | ||||
assert((flags & SCRIPT_VERIFY_P2SH) != 0); | assert((flags & SCRIPT_VERIFY_P2SH) != 0); | ||||
if (stack.size() != 1) { | if (stack.size() != 1) { | ||||
return set_error(serror, ScriptError::CLEANSTACK); | return set_error(serror, ScriptError::CLEANSTACK); | ||||
} | } | ||||
} | } | ||||
metricsOut = metrics; | |||||
return set_success(serror); | return set_success(serror); | ||||
} | } |