script/interpreter: introduce script_verify_flags typename

Previously the SCRIPT_VERIFY_* flags were specified as either uint32_t,
unsigned int, or unsigned. This converts them to a common type alias in
preparation for changing the underlying type.
This commit is contained in:
Anthony Towns 2025-07-16 11:24:58 +10:00
parent 4577fb2b1e
commit a5ead122fe
24 changed files with 114 additions and 96 deletions

View File

@ -24,7 +24,7 @@ static void VerifyScriptBench(benchmark::Bench& bench)
{ {
ECC_Context ecc_context{}; ECC_Context ecc_context{};
const uint32_t flags{SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH}; const script_verify_flags flags{SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH};
const int witnessversion = 0; const int witnessversion = 0;
// Key pair. // Key pair.

View File

@ -6,6 +6,7 @@
#ifndef BITCOIN_CONSENSUS_PARAMS_H #ifndef BITCOIN_CONSENSUS_PARAMS_H
#define BITCOIN_CONSENSUS_PARAMS_H #define BITCOIN_CONSENSUS_PARAMS_H
#include <script/verify_flags.h>
#include <uint256.h> #include <uint256.h>
#include <array> #include <array>
@ -89,7 +90,7 @@ struct Params {
* - buried in the chain, and * - buried in the chain, and
* - fail if the default script verify flags are applied. * - fail if the default script verify flags are applied.
*/ */
std::map<uint256, uint32_t> script_flag_exceptions; std::map<uint256, script_verify_flags> script_flag_exceptions;
/** Block height and hash at which BIP34 becomes active */ /** Block height and hash at which BIP34 becomes active */
int BIP34Height; int BIP34Height;
uint256 BIP34Hash; uint256 BIP34Hash;

View File

@ -140,7 +140,7 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& in
return nSigOps; return nSigOps;
} }
int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, uint32_t flags) int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, script_verify_flags flags)
{ {
int64_t nSigOps = GetLegacySigOpCount(tx) * WITNESS_SCALE_FACTOR; int64_t nSigOps = GetLegacySigOpCount(tx) * WITNESS_SCALE_FACTOR;

View File

@ -6,6 +6,7 @@
#define BITCOIN_CONSENSUS_TX_VERIFY_H #define BITCOIN_CONSENSUS_TX_VERIFY_H
#include <consensus/amount.h> #include <consensus/amount.h>
#include <script/verify_flags.h>
#include <cstdint> #include <cstdint>
#include <vector> #include <vector>
@ -52,7 +53,7 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& ma
* @param[in] flags Script verification flags * @param[in] flags Script verification flags
* @return Total signature operation cost of tx * @return Total signature operation cost of tx
*/ */
int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, uint32_t flags); int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, script_verify_flags flags);
/** /**
* Check if transaction is final and can be included in a block with the * Check if transaction is final and can be included in a block with the

View File

@ -98,7 +98,7 @@ static constexpr unsigned int MAX_DUST_OUTPUTS_PER_TX{1};
* Note that this does not affect consensus validity; see GetBlockScriptFlags() * Note that this does not affect consensus validity; see GetBlockScriptFlags()
* for that. * for that.
*/ */
static constexpr unsigned int MANDATORY_SCRIPT_VERIFY_FLAGS{SCRIPT_VERIFY_P2SH | static constexpr script_verify_flags MANDATORY_SCRIPT_VERIFY_FLAGS{SCRIPT_VERIFY_P2SH |
SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_DERSIG |
SCRIPT_VERIFY_NULLDUMMY | SCRIPT_VERIFY_NULLDUMMY |
SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY | SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY |
@ -112,7 +112,7 @@ static constexpr unsigned int MANDATORY_SCRIPT_VERIFY_FLAGS{SCRIPT_VERIFY_P2SH |
* the additional (non-mandatory) rules here, to improve forwards and * the additional (non-mandatory) rules here, to improve forwards and
* backwards compatibility. * backwards compatibility.
*/ */
static constexpr unsigned int STANDARD_SCRIPT_VERIFY_FLAGS{MANDATORY_SCRIPT_VERIFY_FLAGS | static constexpr script_verify_flags STANDARD_SCRIPT_VERIFY_FLAGS{MANDATORY_SCRIPT_VERIFY_FLAGS |
SCRIPT_VERIFY_STRICTENC | SCRIPT_VERIFY_STRICTENC |
SCRIPT_VERIFY_MINIMALDATA | SCRIPT_VERIFY_MINIMALDATA |
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS | SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS |
@ -128,7 +128,7 @@ static constexpr unsigned int STANDARD_SCRIPT_VERIFY_FLAGS{MANDATORY_SCRIPT_VERI
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE}; SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE};
/** For convenience, standard but not mandatory verify flags. */ /** 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}; static constexpr script_verify_flags STANDARD_NOT_MANDATORY_VERIFY_FLAGS{STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS};
/** Used as the flags parameter to sequence and nLocktime checks in non-consensus code. */ /** Used as the flags parameter to sequence and nLocktime checks in non-consensus code. */
static constexpr unsigned int STANDARD_LOCKTIME_VERIFY_FLAGS{LOCKTIME_VERIFY_SEQUENCE}; static constexpr unsigned int STANDARD_LOCKTIME_VERIFY_FLAGS{LOCKTIME_VERIFY_SEQUENCE};

View File

@ -198,7 +198,7 @@ bool static IsDefinedHashtypeSignature(const valtype &vchSig) {
return true; return true;
} }
bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, unsigned int flags, ScriptError* serror) { bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, script_verify_flags flags, ScriptError* serror) {
// Empty signature. Not strictly DER encoded, but allowed to provide a // Empty signature. Not strictly DER encoded, but allowed to provide a
// compact way to provide an invalid signature for use with CHECK(MULTI)SIG // compact way to provide an invalid signature for use with CHECK(MULTI)SIG
if (vchSig.size() == 0) { if (vchSig.size() == 0) {
@ -215,7 +215,7 @@ bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, unsigned i
return true; return true;
} }
bool static CheckPubKeyEncoding(const valtype &vchPubKey, unsigned int flags, const SigVersion &sigversion, ScriptError* serror) { bool static CheckPubKeyEncoding(const valtype &vchPubKey, script_verify_flags flags, const SigVersion &sigversion, ScriptError* serror) {
if ((flags & SCRIPT_VERIFY_STRICTENC) != 0 && !IsCompressedOrUncompressedPubKey(vchPubKey)) { if ((flags & SCRIPT_VERIFY_STRICTENC) != 0 && !IsCompressedOrUncompressedPubKey(vchPubKey)) {
return set_error(serror, SCRIPT_ERR_PUBKEYTYPE); return set_error(serror, SCRIPT_ERR_PUBKEYTYPE);
} }
@ -318,7 +318,7 @@ public:
}; };
} }
static bool EvalChecksigPreTapscript(const valtype& vchSig, const valtype& vchPubKey, CScript::const_iterator pbegincodehash, CScript::const_iterator pend, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror, bool& fSuccess) static bool EvalChecksigPreTapscript(const valtype& vchSig, const valtype& vchPubKey, CScript::const_iterator pbegincodehash, CScript::const_iterator pend, script_verify_flags flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror, bool& fSuccess)
{ {
assert(sigversion == SigVersion::BASE || sigversion == SigVersion::WITNESS_V0); assert(sigversion == SigVersion::BASE || sigversion == SigVersion::WITNESS_V0);
@ -344,7 +344,7 @@ static bool EvalChecksigPreTapscript(const valtype& vchSig, const valtype& vchPu
return true; return true;
} }
static bool EvalChecksigTapscript(const valtype& sig, const valtype& pubkey, ScriptExecutionData& execdata, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror, bool& success) static bool EvalChecksigTapscript(const valtype& sig, const valtype& pubkey, ScriptExecutionData& execdata, script_verify_flags flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror, bool& success)
{ {
assert(sigversion == SigVersion::TAPSCRIPT); assert(sigversion == SigVersion::TAPSCRIPT);
@ -389,7 +389,7 @@ static bool EvalChecksigTapscript(const valtype& sig, const valtype& pubkey, Scr
* A return value of false means the script fails entirely. When true is returned, the * A return value of false means the script fails entirely. When true is returned, the
* success variable indicates whether the signature check itself succeeded. * success variable indicates whether the signature check itself succeeded.
*/ */
static bool EvalChecksig(const valtype& sig, const valtype& pubkey, CScript::const_iterator pbegincodehash, CScript::const_iterator pend, ScriptExecutionData& execdata, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror, bool& success) static bool EvalChecksig(const valtype& sig, const valtype& pubkey, CScript::const_iterator pbegincodehash, CScript::const_iterator pend, ScriptExecutionData& execdata, script_verify_flags flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror, bool& success)
{ {
switch (sigversion) { switch (sigversion) {
case SigVersion::BASE: case SigVersion::BASE:
@ -404,7 +404,7 @@ static bool EvalChecksig(const valtype& sig, const valtype& pubkey, CScript::con
assert(false); assert(false);
} }
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptExecutionData& execdata, ScriptError* serror) bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, script_verify_flags flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptExecutionData& execdata, ScriptError* serror)
{ {
static const CScriptNum bnZero(0); static const CScriptNum bnZero(0);
static const CScriptNum bnOne(1); static const CScriptNum bnOne(1);
@ -1234,7 +1234,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
return set_success(serror); return set_success(serror);
} }
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror) bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, script_verify_flags flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror)
{ {
ScriptExecutionData execdata; ScriptExecutionData execdata;
return EvalScript(stack, script, flags, checker, sigversion, execdata, serror); return EvalScript(stack, script, flags, checker, sigversion, execdata, serror);
@ -1825,7 +1825,7 @@ bool GenericTransactionSignatureChecker<T>::CheckSequence(const CScriptNum& nSeq
template class GenericTransactionSignatureChecker<CTransaction>; template class GenericTransactionSignatureChecker<CTransaction>;
template class GenericTransactionSignatureChecker<CMutableTransaction>; template class GenericTransactionSignatureChecker<CMutableTransaction>;
static bool ExecuteWitnessScript(const std::span<const valtype>& stack_span, const CScript& exec_script, unsigned int flags, SigVersion sigversion, const BaseSignatureChecker& checker, ScriptExecutionData& execdata, ScriptError* serror) static bool ExecuteWitnessScript(const std::span<const valtype>& stack_span, const CScript& exec_script, script_verify_flags flags, SigVersion sigversion, const BaseSignatureChecker& checker, ScriptExecutionData& execdata, ScriptError* serror)
{ {
std::vector<valtype> stack{stack_span.begin(), stack_span.end()}; std::vector<valtype> stack{stack_span.begin(), stack_span.end()};
@ -1910,7 +1910,7 @@ static bool VerifyTaprootCommitment(const std::vector<unsigned char>& control, c
return q.CheckTapTweak(p, merkle_root, control[0] & 1); return q.CheckTapTweak(p, merkle_root, control[0] & 1);
} }
static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion, const std::vector<unsigned char>& program, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror, bool is_p2sh) static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion, const std::vector<unsigned char>& program, script_verify_flags flags, const BaseSignatureChecker& checker, ScriptError* serror, bool is_p2sh)
{ {
CScript exec_script; //!< Actually executed script (last stack item in P2WSH; implied P2PKH script in P2WPKH; leaf script in P2TR) CScript exec_script; //!< Actually executed script (last stack item in P2WSH; implied P2PKH script in P2WPKH; leaf script in P2TR)
std::span stack{witness.stack}; std::span stack{witness.stack};
@ -1995,7 +1995,7 @@ static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion,
// There is intentionally no return statement here, to be able to use "control reaches end of non-void function" warnings to detect gaps in the logic above. // There is intentionally no return statement here, to be able to use "control reaches end of non-void function" warnings to detect gaps in the logic above.
} }
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror) bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, script_verify_flags flags, const BaseSignatureChecker& checker, ScriptError* serror)
{ {
static const CScriptWitness emptyWitness; static const CScriptWitness emptyWitness;
if (witness == nullptr) { if (witness == nullptr) {
@ -2132,7 +2132,7 @@ size_t static WitnessSigOps(int witversion, const std::vector<unsigned char>& wi
return 0; return 0;
} }
size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags) size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, script_verify_flags flags)
{ {
static const CScriptWitness witnessEmpty; static const CScriptWitness witnessEmpty;
@ -2189,13 +2189,13 @@ const std::map<std::string, uint32_t> g_verify_flag_names{
}; };
#undef FLAG_NAME #undef FLAG_NAME
std::vector<std::string> GetScriptFlagNames(uint32_t flags) std::vector<std::string> GetScriptFlagNames(script_verify_flags flags)
{ {
std::vector<std::string> res; std::vector<std::string> res;
if (flags == SCRIPT_VERIFY_NONE) { if (flags == SCRIPT_VERIFY_NONE) {
return res; return res;
} }
uint32_t leftover = flags; script_verify_flags leftover = flags;
for (const auto& [name, flag] : g_verify_flag_names) { for (const auto& [name, flag] : g_verify_flag_names) {
if ((flags & flag) != 0) { if ((flags & flag) != 0) {
res.push_back(name); res.push_back(name);

View File

@ -10,6 +10,7 @@
#include <hash.h> #include <hash.h>
#include <primitives/transaction.h> #include <primitives/transaction.h>
#include <script/script_error.h> // IWYU pragma: export #include <script/script_error.h> // IWYU pragma: export
#include <script/verify_flags.h> // IWYU pragma: export
#include <span.h> #include <span.h>
#include <uint256.h> #include <uint256.h>
@ -148,7 +149,7 @@ enum : uint32_t {
SCRIPT_VERIFY_END_MARKER SCRIPT_VERIFY_END_MARKER
}; };
bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, unsigned int flags, ScriptError* serror); bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, script_verify_flags flags, ScriptError* serror);
struct PrecomputedTransactionData struct PrecomputedTransactionData
{ {
@ -363,16 +364,16 @@ uint256 ComputeTapbranchHash(std::span<const unsigned char> a, std::span<const u
* Requires control block to have valid length (33 + k*32, with k in {0,1,..,128}). */ * Requires control block to have valid length (33 + k*32, with k in {0,1,..,128}). */
uint256 ComputeTaprootMerkleRoot(std::span<const unsigned char> control, const uint256& tapleaf_hash); uint256 ComputeTaprootMerkleRoot(std::span<const unsigned char> control, const uint256& tapleaf_hash);
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptExecutionData& execdata, ScriptError* error = nullptr); bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, script_verify_flags flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptExecutionData& execdata, ScriptError* error = nullptr);
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* error = nullptr); bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, script_verify_flags flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* error = nullptr);
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror = nullptr); bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, script_verify_flags flags, const BaseSignatureChecker& checker, ScriptError* serror = nullptr);
size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags); size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, script_verify_flags flags);
int FindAndDelete(CScript& script, const CScript& b); int FindAndDelete(CScript& script, const CScript& b);
extern const std::map<std::string, uint32_t> g_verify_flag_names; extern const std::map<std::string, uint32_t> g_verify_flag_names;
std::vector<std::string> GetScriptFlagNames(uint32_t flags); std::vector<std::string> GetScriptFlagNames(script_verify_flags flags);
#endif // BITCOIN_SCRIPT_INTERPRETER_H #endif // BITCOIN_SCRIPT_INTERPRETER_H

13
src/script/verify_flags.h Normal file
View File

@ -0,0 +1,13 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-present The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_SCRIPT_VERIFY_FLAGS_H
#define BITCOIN_SCRIPT_VERIFY_FLAGS_H
#include <cstdint>
using script_verify_flags = uint32_t;
#endif // BITCOIN_SCRIPT_VERIFY_FLAGS_H

View File

@ -26,7 +26,7 @@
static constexpr uint8_t SIGNET_HEADER[4] = {0xec, 0xc7, 0xda, 0xa2}; static constexpr uint8_t SIGNET_HEADER[4] = {0xec, 0xc7, 0xda, 0xa2};
static constexpr unsigned int BLOCK_SCRIPT_VERIFY_FLAGS = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_NULLDUMMY; static constexpr script_verify_flags BLOCK_SCRIPT_VERIFY_FLAGS = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_NULLDUMMY;
static bool FetchAndClearCommitmentSection(const std::span<const uint8_t> header, CScript& witness_commitment, std::vector<uint8_t>& result) static bool FetchAndClearCommitmentSection(const std::span<const uint8_t> header, CScript& witness_commitment, std::vector<uint8_t>& result)
{ {

View File

@ -12,7 +12,7 @@
FUZZ_TARGET(eval_script) FUZZ_TARGET(eval_script)
{ {
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const unsigned int flags = fuzzed_data_provider.ConsumeIntegral<unsigned int>(); const script_verify_flags flags = fuzzed_data_provider.ConsumeIntegral<unsigned int>();
const std::vector<uint8_t> script_bytes = [&] { const std::vector<uint8_t> script_bytes = [&] {
if (fuzzed_data_provider.remaining_bytes() != 0) { if (fuzzed_data_provider.remaining_bytes() != 0) {
return fuzzed_data_provider.ConsumeRemainingBytes<uint8_t>(); return fuzzed_data_provider.ConsumeRemainingBytes<uint8_t>();

View File

@ -119,7 +119,7 @@ FUZZ_TARGET(script, .init = initialize_script)
} }
const std::vector<std::string> random_string_vector = ConsumeRandomLengthStringVector(fuzzed_data_provider); const std::vector<std::string> random_string_vector = ConsumeRandomLengthStringVector(fuzzed_data_provider);
const uint32_t u32{fuzzed_data_provider.ConsumeIntegral<uint32_t>()}; const uint32_t u32{fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
const uint32_t flags{u32 | SCRIPT_VERIFY_P2SH}; const script_verify_flags flags{u32 | SCRIPT_VERIFY_P2SH};
{ {
CScriptWitness wit; CScriptWitness wit;
for (const auto& s : random_string_vector) { for (const auto& s : random_string_vector) {

View File

@ -90,22 +90,22 @@ CScriptWitness ScriptWitnessFromJSON(const UniValue& univalue)
return scriptwitness; return scriptwitness;
} }
const std::map<std::string, unsigned int> FLAG_NAMES = { const std::map<std::string, uint32_t> FLAG_NAMES = {
{std::string("P2SH"), (unsigned int)SCRIPT_VERIFY_P2SH}, {std::string("P2SH"), SCRIPT_VERIFY_P2SH},
{std::string("DERSIG"), (unsigned int)SCRIPT_VERIFY_DERSIG}, {std::string("DERSIG"), SCRIPT_VERIFY_DERSIG},
{std::string("NULLDUMMY"), (unsigned int)SCRIPT_VERIFY_NULLDUMMY}, {std::string("NULLDUMMY"), SCRIPT_VERIFY_NULLDUMMY},
{std::string("CHECKLOCKTIMEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY}, {std::string("CHECKLOCKTIMEVERIFY"), SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY},
{std::string("CHECKSEQUENCEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKSEQUENCEVERIFY}, {std::string("CHECKSEQUENCEVERIFY"), SCRIPT_VERIFY_CHECKSEQUENCEVERIFY},
{std::string("WITNESS"), (unsigned int)SCRIPT_VERIFY_WITNESS}, {std::string("WITNESS"), SCRIPT_VERIFY_WITNESS},
{std::string("TAPROOT"), (unsigned int)SCRIPT_VERIFY_TAPROOT}, {std::string("TAPROOT"), SCRIPT_VERIFY_TAPROOT},
}; };
std::vector<unsigned int> AllFlags() std::vector<script_verify_flags> AllFlags()
{ {
std::vector<unsigned int> ret; std::vector<script_verify_flags> ret;
for (unsigned int i = 0; i < 128; ++i) { for (unsigned int i = 0; i < 128; ++i) {
unsigned int flag = 0; script_verify_flags flag = 0;
if (i & 1) flag |= SCRIPT_VERIFY_P2SH; if (i & 1) flag |= SCRIPT_VERIFY_P2SH;
if (i & 2) flag |= SCRIPT_VERIFY_DERSIG; if (i & 2) flag |= SCRIPT_VERIFY_DERSIG;
if (i & 4) flag |= SCRIPT_VERIFY_NULLDUMMY; if (i & 4) flag |= SCRIPT_VERIFY_NULLDUMMY;
@ -125,13 +125,13 @@ std::vector<unsigned int> AllFlags()
return ret; return ret;
} }
const std::vector<unsigned int> ALL_FLAGS = AllFlags(); const std::vector<script_verify_flags> ALL_FLAGS = AllFlags();
unsigned int ParseScriptFlags(const std::string& str) script_verify_flags ParseScriptFlags(const std::string& str)
{ {
if (str.empty()) return 0; if (str.empty()) return 0;
unsigned int flags = 0; script_verify_flags flags = 0;
std::vector<std::string> words = SplitString(str, ','); std::vector<std::string> words = SplitString(str, ',');
for (const std::string& word : words) { for (const std::string& word : words) {
@ -153,7 +153,7 @@ void Test(const std::string& str)
if (prevouts.size() != tx.vin.size()) throw std::runtime_error("Incorrect number of prevouts"); if (prevouts.size() != tx.vin.size()) throw std::runtime_error("Incorrect number of prevouts");
size_t idx = test["index"].getInt<int64_t>(); size_t idx = test["index"].getInt<int64_t>();
if (idx >= tx.vin.size()) throw std::runtime_error("Invalid index"); if (idx >= tx.vin.size()) throw std::runtime_error("Invalid index");
unsigned int test_flags = ParseScriptFlags(test["flags"].get_str()); script_verify_flags test_flags = ParseScriptFlags(test["flags"].get_str());
bool final = test.exists("final") && test["final"].get_bool(); bool final = test.exists("final") && test["final"].get_bool();
if (test.exists("success")) { if (test.exists("success")) {

View File

@ -22,12 +22,12 @@ FUZZ_TARGET(script_flags)
try { try {
const CTransaction tx(deserialize, TX_WITH_WITNESS, ds); const CTransaction tx(deserialize, TX_WITH_WITNESS, ds);
unsigned int verify_flags; script_verify_flags verify_flags;
ds >> verify_flags; ds >> verify_flags;
if (!IsValidFlagCombination(verify_flags)) return; if (!IsValidFlagCombination(verify_flags)) return;
unsigned int fuzzed_flags; script_verify_flags fuzzed_flags;
ds >> fuzzed_flags; ds >> fuzzed_flags;
std::vector<CTxOut> spent_outputs; std::vector<CTxOut> spent_outputs;

View File

@ -51,7 +51,7 @@ public:
FUZZ_TARGET(signature_checker) FUZZ_TARGET(signature_checker)
{ {
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const unsigned int flags = fuzzed_data_provider.ConsumeIntegral<unsigned int>(); const script_verify_flags flags = fuzzed_data_provider.ConsumeIntegral<unsigned int>();
const SigVersion sig_version = fuzzed_data_provider.PickValueInArray({SigVersion::BASE, SigVersion::WITNESS_V0}); const SigVersion sig_version = fuzzed_data_provider.PickValueInArray({SigVersion::BASE, SigVersion::WITNESS_V0});
const auto script_1{ConsumeScript(fuzzed_data_provider)}; const auto script_1{ConsumeScript(fuzzed_data_provider)};
const auto script_2{ConsumeScript(fuzzed_data_provider)}; const auto script_2{ConsumeScript(fuzzed_data_provider)};

View File

@ -38,7 +38,7 @@ sign_multisig(const CScript& scriptPubKey, const std::vector<CKey>& keys, const
BOOST_AUTO_TEST_CASE(multisig_verify) BOOST_AUTO_TEST_CASE(multisig_verify)
{ {
unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC; script_verify_flags flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC;
ScriptError err; ScriptError err;
CKey key[4]; CKey key[4];

View File

@ -25,7 +25,7 @@
#include <univalue.h> #include <univalue.h>
unsigned int ParseScriptFlags(std::string strFlags); script_verify_flags ParseScriptFlags(std::string strFlags);
BOOST_AUTO_TEST_SUITE(script_assets_tests) BOOST_AUTO_TEST_SUITE(script_assets_tests)
@ -71,12 +71,12 @@ static CScriptWitness ScriptWitnessFromJSON(const UniValue& univalue)
return scriptwitness; return scriptwitness;
} }
static std::vector<unsigned int> AllConsensusFlags() static std::vector<script_verify_flags> AllConsensusFlags()
{ {
std::vector<unsigned int> ret; std::vector<script_verify_flags> ret;
for (unsigned int i = 0; i < 128; ++i) { for (unsigned int i = 0; i < 128; ++i) {
unsigned int flag = 0; script_verify_flags flag = 0;
if (i & 1) flag |= SCRIPT_VERIFY_P2SH; if (i & 1) flag |= SCRIPT_VERIFY_P2SH;
if (i & 2) flag |= SCRIPT_VERIFY_DERSIG; if (i & 2) flag |= SCRIPT_VERIFY_DERSIG;
if (i & 4) flag |= SCRIPT_VERIFY_NULLDUMMY; if (i & 4) flag |= SCRIPT_VERIFY_NULLDUMMY;
@ -97,7 +97,7 @@ static std::vector<unsigned int> AllConsensusFlags()
} }
/** Precomputed list of all valid combinations of consensus-relevant script validation flags. */ /** Precomputed list of all valid combinations of consensus-relevant script validation flags. */
static const std::vector<unsigned int> ALL_CONSENSUS_FLAGS = AllConsensusFlags(); static const std::vector<script_verify_flags> ALL_CONSENSUS_FLAGS = AllConsensusFlags();
static void AssetTest(const UniValue& test, SignatureCache& signature_cache) static void AssetTest(const UniValue& test, SignatureCache& signature_cache)
{ {
@ -107,7 +107,7 @@ static void AssetTest(const UniValue& test, SignatureCache& signature_cache)
const std::vector<CTxOut> prevouts = TxOutsFromJSON(test["prevouts"]); const std::vector<CTxOut> prevouts = TxOutsFromJSON(test["prevouts"]);
BOOST_CHECK(prevouts.size() == mtx.vin.size()); BOOST_CHECK(prevouts.size() == mtx.vin.size());
size_t idx = test["index"].getInt<int64_t>(); size_t idx = test["index"].getInt<int64_t>();
uint32_t test_flags{ParseScriptFlags(test["flags"].get_str())}; script_verify_flags test_flags{ParseScriptFlags(test["flags"].get_str())};
bool fin = test.exists("final") && test["final"].get_bool(); bool fin = test.exists("final") && test["final"].get_bool();
if (test.exists("success")) { if (test.exists("success")) {

View File

@ -40,9 +40,9 @@
using namespace util::hex_literals; using namespace util::hex_literals;
static const unsigned int gFlags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC; static const script_verify_flags gFlags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC;
unsigned int ParseScriptFlags(std::string strFlags); script_verify_flags ParseScriptFlags(std::string strFlags);
struct ScriptErrorDesc struct ScriptErrorDesc
{ {
@ -120,7 +120,7 @@ static ScriptError_t ParseScriptError(const std::string& name)
} }
struct ScriptTest : BasicTestingSetup { struct ScriptTest : BasicTestingSetup {
void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, const CScriptWitness& scriptWitness, uint32_t flags, const std::string& message, int scriptError, CAmount nValue = 0) void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, const CScriptWitness& scriptWitness, script_verify_flags flags, const std::string& message, int scriptError, CAmount nValue = 0)
{ {
bool expect = (scriptError == SCRIPT_ERR_OK); bool expect = (scriptError == SCRIPT_ERR_OK);
if (flags & SCRIPT_VERIFY_CLEANSTACK) { if (flags & SCRIPT_VERIFY_CLEANSTACK) {
@ -232,7 +232,7 @@ private:
bool havePush{false}; bool havePush{false};
std::vector<unsigned char> push; std::vector<unsigned char> push;
std::string comment; std::string comment;
uint32_t flags; script_verify_flags flags;
int scriptError{SCRIPT_ERR_OK}; int scriptError{SCRIPT_ERR_OK};
CAmount nValue; CAmount nValue;
@ -252,7 +252,7 @@ private:
} }
public: public:
TestBuilder(const CScript& script_, const std::string& comment_, uint32_t flags_, bool P2SH = false, WitnessMode wm = WitnessMode::NONE, int witnessversion = 0, CAmount nValue_ = 0) : script(script_), comment(comment_), flags(flags_), nValue(nValue_) TestBuilder(const CScript& script_, const std::string& comment_, script_verify_flags flags_, bool P2SH = false, WitnessMode wm = WitnessMode::NONE, int witnessversion = 0, CAmount nValue_ = 0) : script(script_), comment(comment_), flags(flags_), nValue(nValue_)
{ {
CScript scriptPubKey = script; CScript scriptPubKey = script;
if (wm == WitnessMode::PKH) { if (wm == WitnessMode::PKH) {
@ -969,7 +969,7 @@ BOOST_AUTO_TEST_CASE(script_json_test)
} else { } else {
scriptPubKey = ParseScript(scriptPubKeyString); scriptPubKey = ParseScript(scriptPubKeyString);
} }
unsigned int scriptflags = ParseScriptFlags(test[pos++].get_str()); script_verify_flags scriptflags = ParseScriptFlags(test[pos++].get_str());
int scriptError = ParseScriptError(test[pos++].get_str()); int scriptError = ParseScriptError(test[pos++].get_str());
DoTest(scriptPubKey, scriptSig, witness, scriptflags, strTest, scriptError, nValue); DoTest(scriptPubKey, scriptSig, witness, scriptflags, strTest, scriptError, nValue);

View File

@ -69,7 +69,7 @@ BOOST_AUTO_TEST_CASE(GetSigOpCount)
* Verifies script execution of the zeroth scriptPubKey of tx output and * Verifies script execution of the zeroth scriptPubKey of tx output and
* zeroth scriptSig and witness of tx input. * zeroth scriptSig and witness of tx input.
*/ */
static ScriptError VerifyWithFlag(const CTransaction& output, const CMutableTransaction& input, uint32_t flags) static ScriptError VerifyWithFlag(const CTransaction& output, const CMutableTransaction& input, script_verify_flags flags)
{ {
ScriptError error; ScriptError error;
CTransaction inputi(input); CTransaction inputi(input);
@ -122,7 +122,7 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
CKey key = GenerateRandomKey(); CKey key = GenerateRandomKey();
CPubKey pubkey = key.GetPubKey(); CPubKey pubkey = key.GetPubKey();
// Default flags // Default flags
const uint32_t flags{SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH}; const script_verify_flags flags{SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH};
// Multisig script (legacy counting) // Multisig script (legacy counting)
{ {

View File

@ -52,9 +52,9 @@ static bool g_bare_multi{DEFAULT_PERMIT_BAREMULTISIG};
static const std::map<std::string, unsigned int>& mapFlagNames = g_verify_flag_names; static const std::map<std::string, unsigned int>& mapFlagNames = g_verify_flag_names;
unsigned int ParseScriptFlags(std::string strFlags) script_verify_flags ParseScriptFlags(std::string strFlags)
{ {
unsigned int flags = SCRIPT_VERIFY_NONE; script_verify_flags flags = SCRIPT_VERIFY_NONE;
if (strFlags.empty() || strFlags == "NONE") return flags; if (strFlags.empty() || strFlags == "NONE") return flags;
std::vector<std::string> words = SplitString(strFlags, ','); std::vector<std::string> words = SplitString(strFlags, ',');
@ -72,7 +72,7 @@ unsigned int ParseScriptFlags(std::string strFlags)
// Check that all flags in STANDARD_SCRIPT_VERIFY_FLAGS are present in mapFlagNames. // Check that all flags in STANDARD_SCRIPT_VERIFY_FLAGS are present in mapFlagNames.
bool CheckMapFlagNames() bool CheckMapFlagNames()
{ {
unsigned int standard_flags_missing{STANDARD_SCRIPT_VERIFY_FLAGS}; script_verify_flags standard_flags_missing{STANDARD_SCRIPT_VERIFY_FLAGS};
for (const auto& pair : mapFlagNames) { for (const auto& pair : mapFlagNames) {
standard_flags_missing &= ~(pair.second); standard_flags_missing &= ~(pair.second);
} }
@ -83,7 +83,7 @@ bool CheckMapFlagNames()
* Check that the input scripts of a transaction are valid/invalid as expected. * Check that the input scripts of a transaction are valid/invalid as expected.
*/ */
bool CheckTxScripts(const CTransaction& tx, const std::map<COutPoint, CScript>& map_prevout_scriptPubKeys, bool CheckTxScripts(const CTransaction& tx, const std::map<COutPoint, CScript>& map_prevout_scriptPubKeys,
const std::map<COutPoint, int64_t>& map_prevout_values, unsigned int flags, const std::map<COutPoint, int64_t>& map_prevout_values, script_verify_flags flags,
const PrecomputedTransactionData& txdata, const std::string& strTest, bool expect_valid) const PrecomputedTransactionData& txdata, const std::string& strTest, bool expect_valid)
{ {
bool tx_valid = true; bool tx_valid = true;
@ -117,18 +117,18 @@ bool CheckTxScripts(const CTransaction& tx, const std::map<COutPoint, CScript>&
* CLEANSTACK must be used WITNESS and P2SH * CLEANSTACK must be used WITNESS and P2SH
*/ */
unsigned int TrimFlags(unsigned int flags) script_verify_flags TrimFlags(script_verify_flags flags)
{ {
// WITNESS requires P2SH // WITNESS requires P2SH
if (!(flags & SCRIPT_VERIFY_P2SH)) flags &= ~(unsigned int)SCRIPT_VERIFY_WITNESS; if (!(flags & SCRIPT_VERIFY_P2SH)) flags &= ~SCRIPT_VERIFY_WITNESS;
// CLEANSTACK requires WITNESS (and transitively CLEANSTACK requires P2SH) // CLEANSTACK requires WITNESS (and transitively CLEANSTACK requires P2SH)
if (!(flags & SCRIPT_VERIFY_WITNESS)) flags &= ~(unsigned int)SCRIPT_VERIFY_CLEANSTACK; if (!(flags & SCRIPT_VERIFY_WITNESS)) flags &= ~SCRIPT_VERIFY_CLEANSTACK;
Assert(IsValidFlagCombination(flags)); Assert(IsValidFlagCombination(flags));
return flags; return flags;
} }
unsigned int FillFlags(unsigned int flags) script_verify_flags FillFlags(script_verify_flags flags)
{ {
// CLEANSTACK implies WITNESS // CLEANSTACK implies WITNESS
if (flags & SCRIPT_VERIFY_CLEANSTACK) flags |= SCRIPT_VERIFY_WITNESS; if (flags & SCRIPT_VERIFY_CLEANSTACK) flags |= SCRIPT_VERIFY_WITNESS;
@ -143,11 +143,11 @@ unsigned int FillFlags(unsigned int flags)
// that are valid and without duplicates. For example: if flags=1111 and the 4 possible flags are // that are valid and without duplicates. For example: if flags=1111 and the 4 possible flags are
// 0001, 0010, 0100, and 1000, this should return the set {0111, 1011, 1101, 1110}. // 0001, 0010, 0100, and 1000, this should return the set {0111, 1011, 1101, 1110}.
// Assumes that mapFlagNames contains all script verify flags. // Assumes that mapFlagNames contains all script verify flags.
std::set<unsigned int> ExcludeIndividualFlags(unsigned int flags) std::set<script_verify_flags> ExcludeIndividualFlags(script_verify_flags flags)
{ {
std::set<unsigned int> flags_combos; std::set<script_verify_flags> flags_combos;
for (const auto& pair : mapFlagNames) { for (const auto& pair : mapFlagNames) {
const unsigned int flags_excluding_one = TrimFlags(flags & ~(pair.second)); script_verify_flags flags_excluding_one = TrimFlags(flags & ~(pair.second));
if (flags != flags_excluding_one) { if (flags != flags_excluding_one) {
flags_combos.insert(flags_excluding_one); flags_combos.insert(flags_excluding_one);
} }
@ -212,7 +212,7 @@ BOOST_AUTO_TEST_CASE(tx_valid)
BOOST_CHECK(state.IsValid()); BOOST_CHECK(state.IsValid());
PrecomputedTransactionData txdata(tx); PrecomputedTransactionData txdata(tx);
unsigned int verify_flags = ParseScriptFlags(test[2].get_str()); script_verify_flags verify_flags = ParseScriptFlags(test[2].get_str());
// Check that the test gives a valid combination of flags (otherwise VerifyScript will throw). Don't edit the flags. // Check that the test gives a valid combination of flags (otherwise VerifyScript will throw). Don't edit the flags.
if (~verify_flags != FillFlags(~verify_flags)) { if (~verify_flags != FillFlags(~verify_flags)) {
@ -225,7 +225,7 @@ BOOST_AUTO_TEST_CASE(tx_valid)
// Backwards compatibility of script verification flags: Removing any flag(s) should not invalidate a valid transaction // Backwards compatibility of script verification flags: Removing any flag(s) should not invalidate a valid transaction
for (const auto& [name, flag] : mapFlagNames) { for (const auto& [name, flag] : mapFlagNames) {
// Removing individual flags // Removing individual flags
unsigned int flags = TrimFlags(~(verify_flags | flag)); script_verify_flags flags = TrimFlags(~(verify_flags | flag));
if (!CheckTxScripts(tx, mapprevOutScriptPubKeys, mapprevOutValues, flags, txdata, strTest, /*expect_valid=*/true)) { if (!CheckTxScripts(tx, mapprevOutScriptPubKeys, mapprevOutValues, flags, txdata, strTest, /*expect_valid=*/true)) {
BOOST_ERROR("Tx unexpectedly failed with flag " << name << " unset: " << strTest); BOOST_ERROR("Tx unexpectedly failed with flag " << name << " unset: " << strTest);
} }
@ -302,7 +302,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
} }
PrecomputedTransactionData txdata(tx); PrecomputedTransactionData txdata(tx);
unsigned int verify_flags = ParseScriptFlags(test[2].get_str()); script_verify_flags verify_flags = ParseScriptFlags(test[2].get_str());
// Check that the test gives a valid combination of flags (otherwise VerifyScript will throw). Don't edit the flags. // Check that the test gives a valid combination of flags (otherwise VerifyScript will throw). Don't edit the flags.
if (verify_flags != FillFlags(verify_flags)) { if (verify_flags != FillFlags(verify_flags)) {
@ -315,7 +315,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
// Backwards compatibility of script verification flags: Adding any flag(s) should not validate an invalid transaction // Backwards compatibility of script verification flags: Adding any flag(s) should not validate an invalid transaction
for (const auto& [name, flag] : mapFlagNames) { for (const auto& [name, flag] : mapFlagNames) {
unsigned int flags = FillFlags(verify_flags | flag); script_verify_flags flags = FillFlags(verify_flags | flag);
// Adding individual flags // Adding individual flags
if (!CheckTxScripts(tx, mapprevOutScriptPubKeys, mapprevOutValues, flags, txdata, strTest, /*expect_valid=*/false)) { if (!CheckTxScripts(tx, mapprevOutScriptPubKeys, mapprevOutValues, flags, txdata, strTest, /*expect_valid=*/false)) {
BOOST_ERROR("Tx unexpectedly passed with flag " << name << " set: " << strTest); BOOST_ERROR("Tx unexpectedly passed with flag " << name << " set: " << strTest);
@ -453,7 +453,7 @@ static void CreateCreditAndSpend(const FillableSigningProvider& keystore, const
assert(input.vin[0].scriptWitness.stack == inputm.vin[0].scriptWitness.stack); assert(input.vin[0].scriptWitness.stack == inputm.vin[0].scriptWitness.stack);
} }
static void CheckWithFlag(const CTransactionRef& output, const CMutableTransaction& input, uint32_t flags, bool success) static void CheckWithFlag(const CTransactionRef& output, const CMutableTransaction& input, script_verify_flags flags, bool success)
{ {
ScriptError error; ScriptError error;
CTransaction inputi(input); CTransaction inputi(input);

View File

@ -21,7 +21,7 @@ struct Dersig100Setup : public TestChain100Setup {
}; };
bool CheckInputScripts(const CTransaction& tx, TxValidationState& state, bool CheckInputScripts(const CTransaction& tx, TxValidationState& state,
const CCoinsViewCache& inputs, unsigned int flags, bool cacheSigStore, const CCoinsViewCache& inputs, script_verify_flags flags, bool cacheSigStore,
bool cacheFullScriptStore, PrecomputedTransactionData& txdata, bool cacheFullScriptStore, PrecomputedTransactionData& txdata,
ValidationCache& validation_cache, ValidationCache& validation_cache,
std::vector<CScriptCheck>* pvChecks) EXCLUSIVE_LOCKS_REQUIRED(cs_main); std::vector<CScriptCheck>* pvChecks) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
@ -120,7 +120,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, Dersig100Setup)
// should fail. // should fail.
// Capture this interaction with the upgraded_nop argument: set it when evaluating // Capture this interaction with the upgraded_nop argument: set it when evaluating
// any script flag that is implemented as an upgraded NOP code. // any script flag that is implemented as an upgraded NOP code.
static void ValidateCheckInputsForAllFlags(const CTransaction &tx, uint32_t failing_flags, bool add_to_cache, CCoinsViewCache& active_coins_tip, ValidationCache& validation_cache) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) static void ValidateCheckInputsForAllFlags(const CTransaction &tx, script_verify_flags failing_flags, bool add_to_cache, CCoinsViewCache& active_coins_tip, ValidationCache& validation_cache) EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
{ {
PrecomputedTransactionData txdata; PrecomputedTransactionData txdata;
@ -130,7 +130,7 @@ static void ValidateCheckInputsForAllFlags(const CTransaction &tx, uint32_t fail
TxValidationState state; TxValidationState state;
// Randomly selects flag combinations // Randomly selects flag combinations
uint32_t test_flags = (uint32_t) insecure_rand.randrange((SCRIPT_VERIFY_END_MARKER - 1) << 1); script_verify_flags test_flags = (uint32_t) insecure_rand.randrange((SCRIPT_VERIFY_END_MARKER - 1) << 1);
// Filter out incompatible flag choices // Filter out incompatible flag choices
if ((test_flags & SCRIPT_VERIFY_CLEANSTACK)) { if ((test_flags & SCRIPT_VERIFY_CLEANSTACK)) {

View File

@ -5,7 +5,7 @@
#include <script/interpreter.h> #include <script/interpreter.h>
#include <test/util/script.h> #include <test/util/script.h>
bool IsValidFlagCombination(unsigned flags) bool IsValidFlagCombination(script_verify_flags flags)
{ {
if (flags & SCRIPT_VERIFY_CLEANSTACK && ~flags & (SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS)) return false; if (flags & SCRIPT_VERIFY_CLEANSTACK && ~flags & (SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS)) return false;
if (flags & SCRIPT_VERIFY_WITNESS && ~flags & SCRIPT_VERIFY_P2SH) return false; if (flags & SCRIPT_VERIFY_WITNESS && ~flags & SCRIPT_VERIFY_P2SH) return false;

View File

@ -7,6 +7,7 @@
#include <crypto/sha256.h> #include <crypto/sha256.h>
#include <script/script.h> #include <script/script.h>
#include <script/verify_flags.h>
static const std::vector<uint8_t> WITNESS_STACK_ELEM_OP_TRUE{uint8_t{OP_TRUE}}; static const std::vector<uint8_t> WITNESS_STACK_ELEM_OP_TRUE{uint8_t{OP_TRUE}};
static const CScript P2WSH_OP_TRUE{ static const CScript P2WSH_OP_TRUE{
@ -31,6 +32,6 @@ static const std::vector<std::vector<uint8_t>> P2WSH_EMPTY_TRUE_STACK{{static_ca
static const std::vector<std::vector<uint8_t>> P2WSH_EMPTY_TWO_STACK{{static_cast<uint8_t>(OP_2)}, {}}; static const std::vector<std::vector<uint8_t>> P2WSH_EMPTY_TWO_STACK{{static_cast<uint8_t>(OP_2)}, {}};
/** Flags that are not forbidden by an assert in script validation */ /** Flags that are not forbidden by an assert in script validation */
bool IsValidFlagCombination(unsigned flags); bool IsValidFlagCombination(script_verify_flags flags);
#endif // BITCOIN_TEST_UTIL_SCRIPT_H #endif // BITCOIN_TEST_UTIL_SCRIPT_H

View File

@ -139,7 +139,7 @@ const CBlockIndex* Chainstate::FindForkInGlobalIndex(const CBlockLocator& locato
} }
bool CheckInputScripts(const CTransaction& tx, TxValidationState& state, bool CheckInputScripts(const CTransaction& tx, TxValidationState& state,
const CCoinsViewCache& inputs, unsigned int flags, bool cacheSigStore, const CCoinsViewCache& inputs, script_verify_flags flags, bool cacheSigStore,
bool cacheFullScriptStore, PrecomputedTransactionData& txdata, bool cacheFullScriptStore, PrecomputedTransactionData& txdata,
ValidationCache& validation_cache, ValidationCache& validation_cache,
std::vector<CScriptCheck>* pvChecks = nullptr) std::vector<CScriptCheck>* pvChecks = nullptr)
@ -395,7 +395,7 @@ void Chainstate::MaybeUpdateMempoolForReorg(
* */ * */
static bool CheckInputsFromMempoolAndCache(const CTransaction& tx, TxValidationState& state, static bool CheckInputsFromMempoolAndCache(const CTransaction& tx, TxValidationState& state,
const CCoinsViewCache& view, const CTxMemPool& pool, const CCoinsViewCache& view, const CTxMemPool& pool,
unsigned int flags, PrecomputedTransactionData& txdata, CCoinsViewCache& coins_tip, script_verify_flags flags, PrecomputedTransactionData& txdata, CCoinsViewCache& coins_tip,
ValidationCache& validation_cache) ValidationCache& validation_cache)
EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs)
{ {
@ -1246,7 +1246,7 @@ bool MemPoolAccept::PolicyScriptChecks(const ATMPArgs& args, Workspace& ws)
const CTransaction& tx = *ws.m_ptx; const CTransaction& tx = *ws.m_ptx;
TxValidationState& state = ws.m_state; TxValidationState& state = ws.m_state;
constexpr unsigned int scriptVerifyFlags = STANDARD_SCRIPT_VERIFY_FLAGS; constexpr script_verify_flags scriptVerifyFlags = STANDARD_SCRIPT_VERIFY_FLAGS;
// Check input scripts and signatures. // Check input scripts and signatures.
// This is done last to help prevent CPU exhaustion denial-of-service attacks. // This is done last to help prevent CPU exhaustion denial-of-service attacks.
@ -1285,7 +1285,7 @@ bool MemPoolAccept::ConsensusScriptChecks(const ATMPArgs& args, Workspace& ws)
// There is a similar check in CreateNewBlock() to prevent creating // There is a similar check in CreateNewBlock() to prevent creating
// invalid blocks (using TestBlockValidity), however allowing such // invalid blocks (using TestBlockValidity), however allowing such
// transactions into the mempool can be exploited as a DoS attack. // transactions into the mempool can be exploited as a DoS attack.
unsigned int currentBlockScriptVerifyFlags{GetBlockScriptFlags(*m_active_chainstate.m_chain.Tip(), m_active_chainstate.m_chainman)}; script_verify_flags currentBlockScriptVerifyFlags{GetBlockScriptFlags(*m_active_chainstate.m_chain.Tip(), m_active_chainstate.m_chainman)};
if (!CheckInputsFromMempoolAndCache(tx, state, m_view, m_pool, currentBlockScriptVerifyFlags, if (!CheckInputsFromMempoolAndCache(tx, state, m_view, m_pool, currentBlockScriptVerifyFlags,
ws.m_precomputed_txdata, m_active_chainstate.CoinsTip(), GetValidationCache())) { ws.m_precomputed_txdata, m_active_chainstate.CoinsTip(), GetValidationCache())) {
LogPrintf("BUG! PLEASE REPORT THIS! CheckInputScripts failed against latest-block but not STANDARD flags %s, %s\n", hash.ToString(), state.ToString()); LogPrintf("BUG! PLEASE REPORT THIS! CheckInputScripts failed against latest-block but not STANDARD flags %s, %s\n", hash.ToString(), state.ToString());
@ -2093,7 +2093,7 @@ std::optional<std::pair<ScriptError, std::string>> CScriptCheck::operator()() {
const CScript &scriptSig = ptxTo->vin[nIn].scriptSig; const CScript &scriptSig = ptxTo->vin[nIn].scriptSig;
const CScriptWitness *witness = &ptxTo->vin[nIn].scriptWitness; const CScriptWitness *witness = &ptxTo->vin[nIn].scriptWitness;
ScriptError error{SCRIPT_ERR_UNKNOWN_ERROR}; ScriptError error{SCRIPT_ERR_UNKNOWN_ERROR};
if (VerifyScript(scriptSig, m_tx_out.scriptPubKey, witness, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, m_tx_out.nValue, cacheStore, *m_signature_cache, *txdata), &error)) { if (VerifyScript(scriptSig, m_tx_out.scriptPubKey, witness, m_flags, CachingTransactionSignatureChecker(ptxTo, nIn, m_tx_out.nValue, cacheStore, *m_signature_cache, *txdata), &error)) {
return std::nullopt; return std::nullopt;
} else { } else {
auto debug_str = strprintf("input %i of %s (wtxid %s), spending %s:%i", nIn, ptxTo->GetHash().ToString(), ptxTo->GetWitnessHash().ToString(), ptxTo->vin[nIn].prevout.hash.ToString(), ptxTo->vin[nIn].prevout.n); auto debug_str = strprintf("input %i of %s (wtxid %s), spending %s:%i", nIn, ptxTo->GetHash().ToString(), ptxTo->GetWitnessHash().ToString(), ptxTo->vin[nIn].prevout.hash.ToString(), ptxTo->vin[nIn].prevout.n);
@ -2137,7 +2137,7 @@ ValidationCache::ValidationCache(const size_t script_execution_cache_bytes, cons
* Non-static (and redeclared) in src/test/txvalidationcache_tests.cpp * Non-static (and redeclared) in src/test/txvalidationcache_tests.cpp
*/ */
bool CheckInputScripts(const CTransaction& tx, TxValidationState& state, bool CheckInputScripts(const CTransaction& tx, TxValidationState& state,
const CCoinsViewCache& inputs, unsigned int flags, bool cacheSigStore, const CCoinsViewCache& inputs, script_verify_flags flags, bool cacheSigStore,
bool cacheFullScriptStore, PrecomputedTransactionData& txdata, bool cacheFullScriptStore, PrecomputedTransactionData& txdata,
ValidationCache& validation_cache, ValidationCache& validation_cache,
std::vector<CScriptCheck>* pvChecks) std::vector<CScriptCheck>* pvChecks)
@ -2325,7 +2325,7 @@ DisconnectResult Chainstate::DisconnectBlock(const CBlock& block, const CBlockIn
return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN; return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN;
} }
unsigned int GetBlockScriptFlags(const CBlockIndex& block_index, const ChainstateManager& chainman) script_verify_flags GetBlockScriptFlags(const CBlockIndex& block_index, const ChainstateManager& chainman)
{ {
const Consensus::Params& consensusparams = chainman.GetConsensus(); const Consensus::Params& consensusparams = chainman.GetConsensus();
@ -2337,7 +2337,7 @@ unsigned int GetBlockScriptFlags(const CBlockIndex& block_index, const Chainstat
// mainnet. // mainnet.
// For simplicity, always leave P2SH+WITNESS+TAPROOT on except for the two // For simplicity, always leave P2SH+WITNESS+TAPROOT on except for the two
// violating blocks. // violating blocks.
uint32_t flags{SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_TAPROOT}; script_verify_flags flags{SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_TAPROOT};
const auto it{consensusparams.script_flag_exceptions.find(*Assert(block_index.phashBlock))}; const auto it{consensusparams.script_flag_exceptions.find(*Assert(block_index.phashBlock))};
if (it != consensusparams.script_flag_exceptions.end()) { if (it != consensusparams.script_flag_exceptions.end()) {
flags = it->second; flags = it->second;
@ -2551,7 +2551,7 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
} }
// Get the script flags for this block // Get the script flags for this block
unsigned int flags{GetBlockScriptFlags(*pindex, m_chainman)}; script_verify_flags flags{GetBlockScriptFlags(*pindex, m_chainman)};
const auto time_2{SteadyClock::now()}; const auto time_2{SteadyClock::now()};
m_chainman.time_forks += time_2 - time_1; m_chainman.time_forks += time_2 - time_1;

View File

@ -23,6 +23,7 @@
#include <policy/policy.h> #include <policy/policy.h>
#include <script/script_error.h> #include <script/script_error.h>
#include <script/sigcache.h> #include <script/sigcache.h>
#include <script/verify_flags.h>
#include <sync.h> #include <sync.h>
#include <txdb.h> #include <txdb.h>
#include <txmempool.h> #include <txmempool.h>
@ -336,14 +337,14 @@ private:
CTxOut m_tx_out; CTxOut m_tx_out;
const CTransaction *ptxTo; const CTransaction *ptxTo;
unsigned int nIn; unsigned int nIn;
unsigned int nFlags; script_verify_flags m_flags;
bool cacheStore; bool cacheStore;
PrecomputedTransactionData *txdata; PrecomputedTransactionData *txdata;
SignatureCache* m_signature_cache; SignatureCache* m_signature_cache;
public: public:
CScriptCheck(const CTxOut& outIn, const CTransaction& txToIn, SignatureCache& signature_cache, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn, PrecomputedTransactionData* txdataIn) : CScriptCheck(const CTxOut& outIn, const CTransaction& txToIn, SignatureCache& signature_cache, unsigned int nInIn, script_verify_flags flags, bool cacheIn, PrecomputedTransactionData* txdataIn) :
m_tx_out(outIn), ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), txdata(txdataIn), m_signature_cache(&signature_cache) { } m_tx_out(outIn), ptxTo(&txToIn), nIn(nInIn), m_flags(flags), cacheStore(cacheIn), txdata(txdataIn), m_signature_cache(&signature_cache) { }
CScriptCheck(const CScriptCheck&) = delete; CScriptCheck(const CScriptCheck&) = delete;
CScriptCheck& operator=(const CScriptCheck&) = delete; CScriptCheck& operator=(const CScriptCheck&) = delete;
@ -1359,6 +1360,6 @@ bool IsBIP30Repeat(const CBlockIndex& block_index);
bool IsBIP30Unspendable(const uint256& block_hash, int block_height); bool IsBIP30Unspendable(const uint256& block_hash, int block_height);
// Returns the script flags which should be checked for a given block // Returns the script flags which should be checked for a given block
unsigned int GetBlockScriptFlags(const CBlockIndex& block_index, const ChainstateManager& chainman); script_verify_flags GetBlockScriptFlags(const CBlockIndex& block_index, const ChainstateManager& chainman);
#endif // BITCOIN_VALIDATION_H #endif // BITCOIN_VALIDATION_H