From 07961a6767cc6dd7a1abf08510bbdb22a6f9e823 Mon Sep 17 00:00:00 2001 From: Josh Doman Date: Fri, 2 May 2025 09:55:08 -0400 Subject: [PATCH 1/3] make unsigned / uncommitted annex non-standard --- src/policy/policy.h | 3 ++- src/script/interpreter.cpp | 6 ++++++ src/script/interpreter.h | 6 ++++++ src/script/script_error.cpp | 2 ++ src/script/script_error.h | 1 + src/test/transaction_tests.cpp | 1 + 6 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/policy/policy.h b/src/policy/policy.h index c5fbfcd2aa0ec..aedbfc2789555 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_UNCOMMITTED_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 9d0e9b5e3cfb2..f96bba8b2ff02 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1694,6 +1694,7 @@ bool GenericTransactionSignatureChecker::CheckSchnorrSignature(Span& stack_span, const CS // Run the script interpreter. if (!EvalScript(stack, exec_script, flags, checker, sigversion, execdata, serror)) return false; + // Discourage uncommitted / unsigned annexes + if (execdata.m_annex_present && !execdata.m_annex_committed && (flags & SCRIPT_VERIFY_DISCOURAGE_UNCOMMITTED_ANNEX)) { + return set_error(serror, SCRIPT_ERR_DISCOURAGE_UNCOMMITTED_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 8ba0018c23ca5..8d2e50889d6d2 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 uncommitted annexes non-standard + // + SCRIPT_VERIFY_DISCOURAGE_UNCOMMITTED_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 the annex has been committed to. + bool m_annex_committed = 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 fadc04262c314..adbb04f84ae96 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_UNCOMMITTED_ANNEX: + return "Uncommitted 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 44e68fe0fae30..62ea5ced0bc36 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_UNCOMMITTED_ANNEX, /* segregated witness */ SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH, diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index d305b2193905d..1f0a0d4eb00e4 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_UNCOMMITTED_ANNEX"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UNCOMMITTED_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}, }; From 3eeeed52a2b0a10c77c1e564468d74ebb81395d5 Mon Sep 17 00:00:00 2001 From: Josh Doman Date: Wed, 4 Jun 2025 15:44:59 -0400 Subject: [PATCH 2/3] renamed unsigned annex --- src/policy/policy.h | 2 +- src/script/interpreter.cpp | 8 ++++---- src/script/interpreter.h | 8 ++++---- src/script/script_error.cpp | 4 ++-- src/script/script_error.h | 2 +- src/test/transaction_tests.cpp | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/policy/policy.h b/src/policy/policy.h index aedbfc2789555..d073bae9c06a7 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -114,7 +114,7 @@ static constexpr unsigned int STANDARD_SCRIPT_VERIFY_FLAGS{MANDATORY_SCRIPT_VERI SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION | SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS | SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE | - SCRIPT_VERIFY_DISCOURAGE_UNCOMMITTED_ANNEX}; + 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 f96bba8b2ff02..5d8f2e28af6e9 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1694,7 +1694,7 @@ bool GenericTransactionSignatureChecker::CheckSchnorrSignature(Span& stack_span, const CS // Run the script interpreter. if (!EvalScript(stack, exec_script, flags, checker, sigversion, execdata, serror)) return false; - // Discourage uncommitted / unsigned annexes - if (execdata.m_annex_present && !execdata.m_annex_committed && (flags & SCRIPT_VERIFY_DISCOURAGE_UNCOMMITTED_ANNEX)) { - return set_error(serror, SCRIPT_ERR_DISCOURAGE_UNCOMMITTED_ANNEX); + // Discourage unsigned annexes + if (execdata.m_annex_present && !execdata.m_annex_signed && (flags & SCRIPT_VERIFY_DISCOURAGE_UNSIGNED_ANNEX)) { + return set_error(serror, SCRIPT_ERR_DISCOURAGE_UNSIGNED_ANNEX); } // Scripts inside witness implicitly require cleanstack behaviour diff --git a/src/script/interpreter.h b/src/script/interpreter.h index 8d2e50889d6d2..bde223a1ac205 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -143,9 +143,9 @@ enum : uint32_t { // Making unknown public key versions (in BIP 342 scripts) non-standard SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE = (1U << 20), - // Making uncommitted annexes non-standard + // Making unsigned annexes non-standard // - SCRIPT_VERIFY_DISCOURAGE_UNCOMMITTED_ANNEX = (1U << 21), + SCRIPT_VERIFY_DISCOURAGE_UNSIGNED_ANNEX = (1U << 21), // Constants to point to the highest flag in use. Add new flags above this line. // @@ -217,8 +217,8 @@ struct ScriptExecutionData bool m_annex_present; //! Hash of the annex data. uint256 m_annex_hash; - //! Whether the annex has been committed to. - bool m_annex_committed = false; + //! Whether the annex has been signed. + bool m_annex_signed = 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 adbb04f84ae96..aeef50e0419a1 100644 --- a/src/script/script_error.cpp +++ b/src/script/script_error.cpp @@ -79,8 +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_UNCOMMITTED_ANNEX: - return "Uncommitted annex"; + 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 62ea5ced0bc36..f288766ee83ba 100644 --- a/src/script/script_error.h +++ b/src/script/script_error.h @@ -59,7 +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_UNCOMMITTED_ANNEX, + 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 1f0a0d4eb00e4..f6b6fad4bb209 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -67,7 +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_UNCOMMITTED_ANNEX"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UNCOMMITTED_ANNEX}, + {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}, }; From 648029352b2ade0e456c6cbc203286a4f3693276 Mon Sep 17 00:00:00 2001 From: Josh Doman Date: Fri, 6 Jun 2025 10:06:24 -0400 Subject: [PATCH 3/3] renamed m_annex_unsigned --- src/script/interpreter.cpp | 5 +++-- src/script/interpreter.h | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 5d8f2e28af6e9..3b60a3571d4ec 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1694,7 +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 @@ -1821,7 +1822,7 @@ static bool ExecuteWitnessScript(const Span& stack_span, const CS if (!EvalScript(stack, exec_script, flags, checker, sigversion, execdata, serror)) return false; // Discourage unsigned annexes - if (execdata.m_annex_present && !execdata.m_annex_signed && (flags & SCRIPT_VERIFY_DISCOURAGE_UNSIGNED_ANNEX)) { + if (execdata.m_annex_unsigned && (flags & SCRIPT_VERIFY_DISCOURAGE_UNSIGNED_ANNEX)) { return set_error(serror, SCRIPT_ERR_DISCOURAGE_UNSIGNED_ANNEX); } diff --git a/src/script/interpreter.h b/src/script/interpreter.h index bde223a1ac205..29f19a03a7440 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -217,8 +217,8 @@ struct ScriptExecutionData bool m_annex_present; //! Hash of the annex data. uint256 m_annex_hash; - //! Whether the annex has been signed. - bool m_annex_signed = false; + //! 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;