diff --git a/src/policy/policy.h b/src/policy/policy.h index c5fbfcd2aa0e..d073bae9c06a 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_DISCOURAGE_UNSIGNED_ANNEX}; /** 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 9d0e9b5e3cfb..3b60a3571d4e 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1694,6 +1694,7 @@ bool GenericTransactionSignatureChecker::CheckSchnorrSignature(Span; static bool ExecuteWitnessScript(const Span& stack_span, const CScript& exec_script, unsigned int flags, SigVersion sigversion, const BaseSignatureChecker& checker, ScriptExecutionData& execdata, ScriptError* serror) { std::vector stack{stack_span.begin(), stack_span.end()}; + execdata.m_annex_unsigned = execdata.m_annex_present; if (sigversion == SigVersion::TAPSCRIPT) { // OP_SUCCESSx processing overrides everything, including stack element size limits @@ -1819,6 +1821,11 @@ static bool ExecuteWitnessScript(const Span& stack_span, const CS // Run the script interpreter. if (!EvalScript(stack, exec_script, flags, checker, sigversion, execdata, serror)) return false; + // Discourage unsigned annexes + if (execdata.m_annex_unsigned && (flags & SCRIPT_VERIFY_DISCOURAGE_UNSIGNED_ANNEX)) { + return set_error(serror, SCRIPT_ERR_DISCOURAGE_UNSIGNED_ANNEX); + } + // Scripts inside witness implicitly require cleanstack behaviour if (stack.size() != 1) return set_error(serror, SCRIPT_ERR_CLEANSTACK); if (!CastToBool(stack.back())) return set_error(serror, SCRIPT_ERR_EVAL_FALSE); diff --git a/src/script/interpreter.h b/src/script/interpreter.h index 8ba0018c23ca..29f19a03a744 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -143,6 +143,10 @@ enum : uint32_t { // Making unknown public key versions (in BIP 342 scripts) non-standard SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE = (1U << 20), + // Making unsigned annexes non-standard + // + SCRIPT_VERIFY_DISCOURAGE_UNSIGNED_ANNEX = (1U << 21), + // Constants to point to the highest flag in use. Add new flags above this line. // SCRIPT_VERIFY_END_MARKER @@ -213,6 +217,8 @@ struct ScriptExecutionData bool m_annex_present; //! Hash of the annex data. uint256 m_annex_hash; + //! Whether an unsigned annex is present. + bool m_annex_unsigned = false; //! Whether m_validation_weight_left is initialized. bool m_validation_weight_left_init = false; diff --git a/src/script/script_error.cpp b/src/script/script_error.cpp index fadc04262c31..aeef50e0419a 100644 --- a/src/script/script_error.cpp +++ b/src/script/script_error.cpp @@ -79,6 +79,8 @@ std::string ScriptErrorString(const ScriptError serror) return "OP_SUCCESSx reserved for soft-fork upgrades"; case SCRIPT_ERR_DISCOURAGE_UPGRADABLE_PUBKEYTYPE: return "Public key version reserved for soft-fork upgrades"; + case SCRIPT_ERR_DISCOURAGE_UNSIGNED_ANNEX: + return "Unsigned annex"; case SCRIPT_ERR_PUBKEYTYPE: return "Public key is neither compressed or uncompressed"; case SCRIPT_ERR_CLEANSTACK: diff --git a/src/script/script_error.h b/src/script/script_error.h index 44e68fe0fae3..f288766ee83b 100644 --- a/src/script/script_error.h +++ b/src/script/script_error.h @@ -59,6 +59,7 @@ typedef enum ScriptError_t SCRIPT_ERR_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION, SCRIPT_ERR_DISCOURAGE_OP_SUCCESS, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_PUBKEYTYPE, + SCRIPT_ERR_DISCOURAGE_UNSIGNED_ANNEX, /* segregated witness */ SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH, diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index d305b2193905..f6b6fad4bb20 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -67,6 +67,7 @@ static std::map mapFlagNames = { {std::string("CONST_SCRIPTCODE"), (unsigned int)SCRIPT_VERIFY_CONST_SCRIPTCODE}, {std::string("TAPROOT"), (unsigned int)SCRIPT_VERIFY_TAPROOT}, {std::string("DISCOURAGE_UPGRADABLE_PUBKEYTYPE"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE}, + {std::string("DISCOURAGE_UNSIGNED_ANNEX"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UNSIGNED_ANNEX}, {std::string("DISCOURAGE_OP_SUCCESS"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS}, {std::string("DISCOURAGE_UPGRADABLE_TAPROOT_VERSION"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION}, };