diff options
Diffstat (limited to 'src/script/interpreter.cpp')
-rw-r--r-- | src/script/interpreter.cpp | 33 |
1 files changed, 25 insertions, 8 deletions
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index ecac3b9e7e..dc0f165be0 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -225,7 +225,7 @@ bool static CheckPubKeyEncoding(const valtype &vchPubKey, unsigned int flags, co return true; } -bool static CheckMinimalPush(const valtype& data, opcodetype opcode) { +bool CheckMinimalPush(const valtype& data, opcodetype opcode) { // Excludes OP_1NEGATE, OP_1-16 since they are by definition minimal assert(0 <= opcode && opcode <= OP_PUSHDATA4); if (data.size() == 0) { @@ -1488,8 +1488,20 @@ static const CHashWriter HASHER_TAPLEAF = TaggedHash("TapLeaf"); static const CHashWriter HASHER_TAPBRANCH = TaggedHash("TapBranch"); static const CHashWriter HASHER_TAPTWEAK = TaggedHash("TapTweak"); +static bool HandleMissingData(MissingDataBehavior mdb) +{ + switch (mdb) { + case MissingDataBehavior::ASSERT_FAIL: + assert(!"Missing data"); + break; + case MissingDataBehavior::FAIL: + return false; + } + assert(!"Unknown MissingDataBehavior value"); +} + template<typename T> -bool SignatureHashSchnorr(uint256& hash_out, const ScriptExecutionData& execdata, const T& tx_to, uint32_t in_pos, uint8_t hash_type, SigVersion sigversion, const PrecomputedTransactionData& cache) +bool SignatureHashSchnorr(uint256& hash_out, const ScriptExecutionData& execdata, const T& tx_to, uint32_t in_pos, uint8_t hash_type, SigVersion sigversion, const PrecomputedTransactionData& cache, MissingDataBehavior mdb) { uint8_t ext_flag, key_version; switch (sigversion) { @@ -1509,7 +1521,9 @@ bool SignatureHashSchnorr(uint256& hash_out, const ScriptExecutionData& execdata assert(false); } assert(in_pos < tx_to.vin.size()); - assert(cache.m_bip341_taproot_ready && cache.m_spent_outputs_ready); + if (!(cache.m_bip341_taproot_ready && cache.m_spent_outputs_ready)) { + return HandleMissingData(mdb); + } CHashWriter ss = HASHER_TAPSIGHASH; @@ -1667,6 +1681,9 @@ bool GenericTransactionSignatureChecker<T>::CheckECDSASignature(const std::vecto int nHashType = vchSig.back(); vchSig.pop_back(); + // Witness sighashes need the amount. + if (sigversion == SigVersion::WITNESS_V0 && amount < 0) return HandleMissingData(m_mdb); + uint256 sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion, this->txdata); if (!VerifyECDSASignature(vchSig, pubkey, sighash)) @@ -1696,7 +1713,7 @@ bool GenericTransactionSignatureChecker<T>::CheckSchnorrSignature(Span<const uns } uint256 sighash; assert(this->txdata); - if (!SignatureHashSchnorr(sighash, execdata, *txTo, nIn, hashtype, sigversion, *this->txdata)) { + if (!SignatureHashSchnorr(sighash, execdata, *txTo, nIn, hashtype, sigversion, *this->txdata, m_mdb)) { return set_error(serror, SCRIPT_ERR_SCHNORR_SIG_HASHTYPE); } if (!VerifySchnorrSignature(sig, pubkey, sighash)) return set_error(serror, SCRIPT_ERR_SCHNORR_SIG); @@ -1834,7 +1851,7 @@ static bool ExecuteWitnessScript(const Span<const valtype>& stack_span, const CS static bool VerifyTaprootCommitment(const std::vector<unsigned char>& control, const std::vector<unsigned char>& program, const CScript& script, uint256& tapleaf_hash) { const int path_len = (control.size() - TAPROOT_CONTROL_BASE_SIZE) / TAPROOT_CONTROL_NODE_SIZE; - //! The inner pubkey (x-only, so no Y coordinate parity). + //! The internal pubkey (x-only, so no Y coordinate parity). const XOnlyPubKey p{uint256(std::vector<unsigned char>(control.begin() + 1, control.begin() + TAPROOT_CONTROL_BASE_SIZE))}; //! The output pubkey (taken from the scriptPubKey). const XOnlyPubKey q{uint256(program)}; @@ -1852,9 +1869,9 @@ static bool VerifyTaprootCommitment(const std::vector<unsigned char>& control, c } k = ss_branch.GetSHA256(); } - // Compute the tweak from the Merkle root and the inner pubkey. + // Compute the tweak from the Merkle root and the internal pubkey. k = (CHashWriter(HASHER_TAPTWEAK) << MakeSpan(p) << k).GetSHA256(); - // Verify that the output pubkey matches the tweaked inner pubkey, after correcting for parity. + // Verify that the output pubkey matches the tweaked internal pubkey, after correcting for parity. return q.CheckPayToContract(p, k, control[0] & 1); } @@ -1873,7 +1890,7 @@ static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion, const valtype& script_bytes = SpanPopBack(stack); exec_script = CScript(script_bytes.begin(), script_bytes.end()); uint256 hash_exec_script; - CSHA256().Write(&exec_script[0], exec_script.size()).Finalize(hash_exec_script.begin()); + CSHA256().Write(exec_script.data(), exec_script.size()).Finalize(hash_exec_script.begin()); if (memcmp(hash_exec_script.begin(), program.data(), 32)) { return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH); } |