diff --git a/src/policy/policy.h b/src/policy/policy.h index d1c81488004cf..7fdefa9f17128 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -113,7 +113,8 @@ static constexpr unsigned int STANDARD_SCRIPT_VERIFY_FLAGS{MANDATORY_SCRIPT_VERI SCRIPT_VERIFY_CONST_SCRIPTCODE | SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION | SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS | - SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE}; + SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE | + SCRIPT_VERIFY_ANYPREVOUT}; /** For convenience, standard but not mandatory verify flags. */ static constexpr unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS{STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS}; diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 5f4a1aceb2ced..bc7dbca68916c 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -346,6 +346,7 @@ static bool EvalChecksigPreTapscript(const valtype& vchSig, const valtype& vchPu static bool EvalChecksigTapscript(const valtype& sig, const valtype& pubkey, ScriptExecutionData& execdata, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror, bool& success) { assert(sigversion == SigVersion::TAPSCRIPT); + assert(execdata.m_internal_key); // caller must provide the internal key /* * The following validation sequence is consensus critical. Please note how -- @@ -366,9 +367,23 @@ static bool EvalChecksigTapscript(const valtype& sig, const valtype& pubkey, Scr if (pubkey.size() == 0) { return set_error(serror, SCRIPT_ERR_PUBKEYTYPE); } else if (pubkey.size() == 32) { - if (success && !checker.CheckSchnorrSignature(sig, pubkey, sigversion, execdata, serror)) { + if (success && !checker.CheckSchnorrSignature(sig, KeyVersion::TAPROOT, pubkey, sigversion, execdata, serror)) { return false; // serror is set } + } else if ((pubkey.size() == 1 || pubkey.size() == 33) && pubkey[0] == BIP118_PUBKEY_PREFIX) { + if ((flags & SCRIPT_VERIFY_DISCOURAGE_ANYPREVOUT) != 0) { + return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_PUBKEYTYPE); + } else if ((flags & SCRIPT_VERIFY_ANYPREVOUT) == 0) { + return true; + } else if (pubkey.size() == 1) { + if (success && !checker.CheckSchnorrSignature(sig, KeyVersion::ANYPREVOUT, *execdata.m_internal_key, sigversion, execdata, serror)) { + return false; // serror is set + } + } else { // pubkey.size() == 33 + if (success && !checker.CheckSchnorrSignature(sig, KeyVersion::ANYPREVOUT, Span(pubkey).subspan(1), sigversion, execdata, serror)) { + return false; // serror is set + } + } } else { /* * New public key version softforks should be defined before this `else` block. @@ -1475,21 +1490,18 @@ static bool HandleMissingData(MissingDataBehavior mdb) } template -bool SignatureHashSchnorr(uint256& hash_out, ScriptExecutionData& execdata, const T& tx_to, uint32_t in_pos, uint8_t hash_type, SigVersion sigversion, const PrecomputedTransactionData& cache, MissingDataBehavior mdb) +bool SignatureHashSchnorr(uint256& hash_out, ScriptExecutionData& execdata, const T& tx_to, uint32_t in_pos, uint8_t hash_type, SigVersion sigversion, KeyVersion keyversion, const PrecomputedTransactionData& cache, MissingDataBehavior mdb) { - uint8_t ext_flag, key_version; + uint8_t ext_flag; + assert(keyversion == KeyVersion::TAPROOT || keyversion == KeyVersion::ANYPREVOUT); + assert(keyversion == KeyVersion::ANYPREVOUT ? sigversion == SigVersion::TAPSCRIPT : true); switch (sigversion) { case SigVersion::TAPROOT: ext_flag = 0; - // key_version is not used and left uninitialized. + // key_version is not used break; case SigVersion::TAPSCRIPT: ext_flag = 1; - // key_version must be 0 for now, representing the current version of - // 32-byte public keys in the tapscript signature opcode execution. - // An upgradable public key version (with a size not 32-byte) may - // request a different key_version with a new sigversion. - key_version = 0; break; default: assert(false); @@ -1508,13 +1520,26 @@ bool SignatureHashSchnorr(uint256& hash_out, ScriptExecutionData& execdata, cons // Hash type const uint8_t output_type = (hash_type == SIGHASH_DEFAULT) ? SIGHASH_ALL : (hash_type & SIGHASH_OUTPUT_MASK); // Default (no sighash byte) is equivalent to SIGHASH_ALL const uint8_t input_type = hash_type & SIGHASH_INPUT_MASK; - if (!(hash_type <= 0x03 || (hash_type >= 0x81 && hash_type <= 0x83))) return false; + switch(hash_type) { + case 0: case 1: case 2: case 3: + case 0x81: case 0x82: case 0x83: + break; + case 0x41: case 0x42: case 0x43: + case 0xc1: case 0xc2: case 0xc3: + if (keyversion == KeyVersion::ANYPREVOUT) { + break; + } else { + return false; + } + default: + return false; + } ss << hash_type; // Transaction level data ss << tx_to.nVersion; ss << tx_to.nLockTime; - if (input_type != SIGHASH_ANYONECANPAY) { + if (input_type != SIGHASH_ANYONECANPAY && input_type != SIGHASH_ANYPREVOUT && input_type != SIGHASH_ANYPREVOUTANYSCRIPT) { ss << cache.m_prevouts_single_hash; ss << cache.m_spent_amounts_single_hash; ss << cache.m_spent_scripts_single_hash; @@ -1533,6 +1558,13 @@ bool SignatureHashSchnorr(uint256& hash_out, ScriptExecutionData& execdata, cons ss << tx_to.vin[in_pos].prevout; ss << cache.m_spent_outputs[in_pos]; ss << tx_to.vin[in_pos].nSequence; + } else if (input_type == SIGHASH_ANYPREVOUT) { + assert(keyversion == KeyVersion::ANYPREVOUT); + ss << cache.m_spent_outputs[in_pos]; + ss << tx_to.vin[in_pos].nSequence; + } else if (input_type == SIGHASH_ANYPREVOUTANYSCRIPT) { + assert(keyversion == KeyVersion::ANYPREVOUT); + ss << tx_to.vin[in_pos].nSequence; } else { ss << in_pos; } @@ -1554,8 +1586,12 @@ bool SignatureHashSchnorr(uint256& hash_out, ScriptExecutionData& execdata, cons // Additional data for BIP 342 signatures if (sigversion == SigVersion::TAPSCRIPT) { assert(execdata.m_tapleaf_hash_init); - ss << execdata.m_tapleaf_hash; - ss << key_version; + if (input_type != SIGHASH_ANYPREVOUTANYSCRIPT) { + ss << execdata.m_tapleaf_hash; + } else { + assert(keyversion == KeyVersion::ANYPREVOUT); + } + ss << uint8_t(keyversion); assert(execdata.m_codeseparator_pos_init); ss << execdata.m_codeseparator_pos; } @@ -1670,18 +1706,16 @@ bool GenericTransactionSignatureChecker::CheckECDSASignature(const std::vecto } template -bool GenericTransactionSignatureChecker::CheckSchnorrSignature(Span sig, Span pubkey_in, SigVersion sigversion, ScriptExecutionData& execdata, ScriptError* serror) const +bool GenericTransactionSignatureChecker::CheckSchnorrSignature(Span sig, KeyVersion pubkeyver, Span pubkey_in, SigVersion sigversion, ScriptExecutionData& execdata, ScriptError* serror) const { assert(sigversion == SigVersion::TAPROOT || sigversion == SigVersion::TAPSCRIPT); - // Schnorr signatures have 32-byte public keys. The caller is responsible for enforcing this. - assert(pubkey_in.size() == 32); // Note that in Tapscript evaluation, empty signatures are treated specially (invalid signature that does not // abort script execution). This is implemented in EvalChecksigTapscript, which won't invoke // CheckSchnorrSignature in that case. In other contexts, they are invalid like every other signature with // size different from 64 or 65. if (sig.size() != 64 && sig.size() != 65) return set_error(serror, SCRIPT_ERR_SCHNORR_SIG_SIZE); - XOnlyPubKey pubkey{pubkey_in}; + XOnlyPubKey pubkey_xonly{pubkey_in}; uint8_t hashtype = SIGHASH_DEFAULT; if (sig.size() == 65) { @@ -1690,10 +1724,10 @@ bool GenericTransactionSignatureChecker::CheckSchnorrSignature(Spantxdata) return HandleMissingData(m_mdb); - if (!SignatureHashSchnorr(sighash, execdata, *txTo, nIn, hashtype, sigversion, *this->txdata, m_mdb)) { + if (!SignatureHashSchnorr(sighash, execdata, *txTo, nIn, hashtype, sigversion, pubkeyver, *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); + if (!VerifySchnorrSignature(sig, pubkey_xonly, sighash)) return set_error(serror, SCRIPT_ERR_SCHNORR_SIG); return true; } @@ -1856,12 +1890,13 @@ uint256 ComputeTaprootMerkleRoot(Span control, const uint25 return k; } -static bool VerifyTaprootCommitment(const std::vector& control, const std::vector& program, const uint256& tapleaf_hash) +static bool VerifyTaprootCommitment(const std::vector& control, const std::vector& program, const uint256& tapleaf_hash, std::optional& internal_key) { assert(control.size() >= TAPROOT_CONTROL_BASE_SIZE); assert(program.size() >= uint256::size()); //! The internal pubkey (x-only, so no Y coordinate parity). const XOnlyPubKey p{Span{control}.subspan(1, TAPROOT_CONTROL_BASE_SIZE - 1)}; + internal_key = p; //! The output pubkey (taken from the scriptPubKey). const XOnlyPubKey q{program}; // Compute the Merkle root from the leaf and the provided path. @@ -1915,7 +1950,7 @@ static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion, execdata.m_annex_init = true; if (stack.size() == 1) { // Key path spending (stack size is 1 after removing optional annex) - if (!checker.CheckSchnorrSignature(stack.front(), program, SigVersion::TAPROOT, execdata, serror)) { + if (!checker.CheckSchnorrSignature(stack.front(), KeyVersion::TAPROOT, program, SigVersion::TAPROOT, execdata, serror)) { return false; // serror is set } return set_success(serror); @@ -1927,7 +1962,7 @@ static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion, return set_error(serror, SCRIPT_ERR_TAPROOT_WRONG_CONTROL_SIZE); } execdata.m_tapleaf_hash = ComputeTapleafHash(control[0] & TAPROOT_LEAF_MASK, script); - if (!VerifyTaprootCommitment(control, program, execdata.m_tapleaf_hash)) { + if (!VerifyTaprootCommitment(control, program, execdata.m_tapleaf_hash, execdata.m_internal_key)) { return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH); } execdata.m_tapleaf_hash_init = true; diff --git a/src/script/interpreter.h b/src/script/interpreter.h index ac1013302d40e..50e7f69e3c8e9 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -10,6 +10,7 @@ #include