Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/policy/policy.h
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down
7 changes: 7 additions & 0 deletions src/script/interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1694,6 +1694,7 @@ bool GenericTransactionSignatureChecker<T>::CheckSchnorrSignature(Span<const uns
return set_error(serror, SCRIPT_ERR_SCHNORR_SIG_HASHTYPE);
}
if (!VerifySchnorrSignature(sig, pubkey, sighash)) return set_error(serror, SCRIPT_ERR_SCHNORR_SIG);
execdata.m_annex_unsigned = false;
return true;
}

Expand Down Expand Up @@ -1788,6 +1789,7 @@ template class GenericTransactionSignatureChecker<CMutableTransaction>;
static bool ExecuteWitnessScript(const Span<const valtype>& stack_span, const CScript& exec_script, unsigned int flags, SigVersion sigversion, const BaseSignatureChecker& checker, ScriptExecutionData& execdata, ScriptError* serror)
{
std::vector<valtype> 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
Expand Down Expand Up @@ -1819,6 +1821,11 @@ static bool ExecuteWitnessScript(const Span<const valtype>& 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);
Expand Down
6 changes: 6 additions & 0 deletions src/script/interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, since Bitcoin Core does not have this patch, let's use a totally different bit number for this to avoid merge conflicts in the future.

Maybe the highest bit?


// Constants to point to the highest flag in use. Add new flags above this line.
//
SCRIPT_VERIFY_END_MARKER
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions src/script/script_error.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions src/script/script_error.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions src/test/transaction_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ static std::map<std::string, unsigned int> 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},
};
Expand Down