Skip to content

Commit d735e2e

Browse files
committed
Merge bitcoin/bitcoin#32998: Bump SCRIPT_VERIFY flags to 64 bit
652424a test: additional test coverage for script_verify_flags (Anthony Towns) 417437e script/verify_flags: extend script_verify_flags to 64 bits (Anthony Towns) 3cbbcb6 script/interpreter: make script_verify_flag_name an ordinary enum (Anthony Towns) bddcade script/verify_flags: make script_verify_flags type safe (Anthony Towns) a5ead12 script/interpreter: introduce script_verify_flags typename (Anthony Towns) 4577fb2 rpc: have getdeploymentinfo report script verify flags (Anthony Towns) a398693 validation: export GetBlockScriptFlags() (Anthony Towns) 5db8cd2 Move mapFlagNames and FormatScriptFlags logic to script/interpreter.h (Anthony Towns) Pull request description: We currently use 21 of 32 possible bits for `SCRIPT_VERIFY_*` flags, with open PRs that may use 8 more (#29247, #31989, #32247, #32453). The mutinynet fork that has included many experimental soft fork features is [already reusing bits here](https://github.com/benthecarman/bitcoin/blob/d4a86277ed8a0712e03fbbce290e9209165e049c/src/script/interpreter.h#L175-L195). Therefore, bump this to 64 bits. In order to make it easier to update this logic in future, this PR also introduces a dedicated type for the script flags, and disables implicit conversion between that type and the underlying integer type. To make verifying that this change doesn't cause flags to disappear, this PR also resurrects the changes from #28806 so that the script flags that are consensus enforced on each block can be queried via getdeploymentinfo. ACKs for top commit: instagibbs: reACK bitcoin/bitcoin@652424a achow101: ACK 652424a darosior: ACK 652424a theStack: Code-review ACK 652424a 🎏 Tree-SHA512: 7b30152196cdfdef8b9700b571b7d7d4e94d28fbc5c26ea7532788037efc02e4b1d8de392b0b20507badfdc26f5c125f8356a479604a9149b8aae23a7cf5549f
2 parents de1dc6b + 652424a commit d735e2e

28 files changed

+310
-170
lines changed

src/bench/verify_script.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ static void VerifyScriptBench(benchmark::Bench& bench)
2424
{
2525
ECC_Context ecc_context{};
2626

27-
const uint32_t flags{SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH};
27+
const script_verify_flags flags{SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH};
2828
const int witnessversion = 0;
2929

3030
// Key pair.

src/consensus/params.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#ifndef BITCOIN_CONSENSUS_PARAMS_H
77
#define BITCOIN_CONSENSUS_PARAMS_H
88

9+
#include <script/verify_flags.h>
910
#include <uint256.h>
1011

1112
#include <array>
@@ -89,7 +90,7 @@ struct Params {
8990
* - buried in the chain, and
9091
* - fail if the default script verify flags are applied.
9192
*/
92-
std::map<uint256, uint32_t> script_flag_exceptions;
93+
std::map<uint256, script_verify_flags> script_flag_exceptions;
9394
/** Block height and hash at which BIP34 becomes active */
9495
int BIP34Height;
9596
uint256 BIP34Hash;

src/consensus/tx_verify.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& in
140140
return nSigOps;
141141
}
142142

143-
int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, uint32_t flags)
143+
int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, script_verify_flags flags)
144144
{
145145
int64_t nSigOps = GetLegacySigOpCount(tx) * WITNESS_SCALE_FACTOR;
146146

src/consensus/tx_verify.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#define BITCOIN_CONSENSUS_TX_VERIFY_H
77

88
#include <consensus/amount.h>
9+
#include <script/verify_flags.h>
910

1011
#include <cstdint>
1112
#include <vector>
@@ -52,7 +53,7 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& ma
5253
* @param[in] flags Script verification flags
5354
* @return Total signature operation cost of tx
5455
*/
55-
int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, uint32_t flags);
56+
int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, script_verify_flags flags);
5657

5758
/**
5859
* Check if transaction is final and can be included in a block with the

src/deploymentinfo.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
#include <consensus/params.h>
99

1010
#include <array>
11+
#include <cassert>
1112
#include <optional>
1213
#include <string>
14+
#include <string_view>
1315

1416
struct VBDeploymentInfo {
1517
/** Deployment name */

src/policy/policy.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ static constexpr unsigned int MAX_DUST_OUTPUTS_PER_TX{1};
9898
* Note that this does not affect consensus validity; see GetBlockScriptFlags()
9999
* for that.
100100
*/
101-
static constexpr unsigned int MANDATORY_SCRIPT_VERIFY_FLAGS{SCRIPT_VERIFY_P2SH |
101+
static constexpr script_verify_flags MANDATORY_SCRIPT_VERIFY_FLAGS{SCRIPT_VERIFY_P2SH |
102102
SCRIPT_VERIFY_DERSIG |
103103
SCRIPT_VERIFY_NULLDUMMY |
104104
SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY |
@@ -112,7 +112,7 @@ static constexpr unsigned int MANDATORY_SCRIPT_VERIFY_FLAGS{SCRIPT_VERIFY_P2SH |
112112
* the additional (non-mandatory) rules here, to improve forwards and
113113
* backwards compatibility.
114114
*/
115-
static constexpr unsigned int STANDARD_SCRIPT_VERIFY_FLAGS{MANDATORY_SCRIPT_VERIFY_FLAGS |
115+
static constexpr script_verify_flags STANDARD_SCRIPT_VERIFY_FLAGS{MANDATORY_SCRIPT_VERIFY_FLAGS |
116116
SCRIPT_VERIFY_STRICTENC |
117117
SCRIPT_VERIFY_MINIMALDATA |
118118
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS |
@@ -128,7 +128,7 @@ static constexpr unsigned int STANDARD_SCRIPT_VERIFY_FLAGS{MANDATORY_SCRIPT_VERI
128128
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE};
129129

130130
/** For convenience, standard but not mandatory verify flags. */
131-
static constexpr unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS{STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS};
131+
static constexpr script_verify_flags STANDARD_NOT_MANDATORY_VERIFY_FLAGS{STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS};
132132

133133
/** Used as the flags parameter to sequence and nLocktime checks in non-consensus code. */
134134
static constexpr unsigned int STANDARD_LOCKTIME_VERIFY_FLAGS{LOCKTIME_VERIFY_SEQUENCE};

src/rpc/blockchain.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1469,6 +1469,9 @@ RPCHelpMan getdeploymentinfo()
14691469
RPCResult::Type::OBJ, "", "", {
14701470
{RPCResult::Type::STR, "hash", "requested block hash (or tip)"},
14711471
{RPCResult::Type::NUM, "height", "requested block height (or tip)"},
1472+
{RPCResult::Type::ARR, "script_flags", "script verify flags for the block", {
1473+
{RPCResult::Type::STR, "flag", "a script verify flag"},
1474+
}},
14721475
{RPCResult::Type::OBJ_DYN, "deployments", "", {
14731476
{RPCResult::Type::OBJ, "xxxx", "name of the deployment", RPCHelpForDeployment}
14741477
}},
@@ -1495,6 +1498,12 @@ RPCHelpMan getdeploymentinfo()
14951498
UniValue deploymentinfo(UniValue::VOBJ);
14961499
deploymentinfo.pushKV("hash", blockindex->GetBlockHash().ToString());
14971500
deploymentinfo.pushKV("height", blockindex->nHeight);
1501+
{
1502+
const auto flagnames = GetScriptFlagNames(GetBlockScriptFlags(*blockindex, chainman));
1503+
UniValue uv_flagnames(UniValue::VARR);
1504+
uv_flagnames.push_backV(flagnames.begin(), flagnames.end());
1505+
deploymentinfo.pushKV("script_flags", uv_flagnames);
1506+
}
14981507
deploymentinfo.pushKV("deployments", DeploymentInfo(blockindex, chainman));
14991508
return deploymentinfo;
15001509
},

src/script/interpreter.cpp

Lines changed: 57 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <crypto/sha256.h>
1111
#include <pubkey.h>
1212
#include <script/script.h>
13+
#include <tinyformat.h>
1314
#include <uint256.h>
1415

1516
typedef std::vector<unsigned char> valtype;
@@ -197,7 +198,7 @@ bool static IsDefinedHashtypeSignature(const valtype &vchSig) {
197198
return true;
198199
}
199200

200-
bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, unsigned int flags, ScriptError* serror) {
201+
bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, script_verify_flags flags, ScriptError* serror) {
201202
// Empty signature. Not strictly DER encoded, but allowed to provide a
202203
// compact way to provide an invalid signature for use with CHECK(MULTI)SIG
203204
if (vchSig.size() == 0) {
@@ -214,7 +215,7 @@ bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, unsigned i
214215
return true;
215216
}
216217

217-
bool static CheckPubKeyEncoding(const valtype &vchPubKey, unsigned int flags, const SigVersion &sigversion, ScriptError* serror) {
218+
bool static CheckPubKeyEncoding(const valtype &vchPubKey, script_verify_flags flags, const SigVersion &sigversion, ScriptError* serror) {
218219
if ((flags & SCRIPT_VERIFY_STRICTENC) != 0 && !IsCompressedOrUncompressedPubKey(vchPubKey)) {
219220
return set_error(serror, SCRIPT_ERR_PUBKEYTYPE);
220221
}
@@ -317,7 +318,7 @@ class ConditionStack {
317318
};
318319
}
319320

320-
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)
321+
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)
321322
{
322323
assert(sigversion == SigVersion::BASE || sigversion == SigVersion::WITNESS_V0);
323324

@@ -343,7 +344,7 @@ static bool EvalChecksigPreTapscript(const valtype& vchSig, const valtype& vchPu
343344
return true;
344345
}
345346

346-
static bool EvalChecksigTapscript(const valtype& sig, const valtype& pubkey, ScriptExecutionData& execdata, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror, bool& success)
347+
static bool EvalChecksigTapscript(const valtype& sig, const valtype& pubkey, ScriptExecutionData& execdata, script_verify_flags flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror, bool& success)
347348
{
348349
assert(sigversion == SigVersion::TAPSCRIPT);
349350

@@ -388,7 +389,7 @@ static bool EvalChecksigTapscript(const valtype& sig, const valtype& pubkey, Scr
388389
* A return value of false means the script fails entirely. When true is returned, the
389390
* success variable indicates whether the signature check itself succeeded.
390391
*/
391-
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)
392+
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)
392393
{
393394
switch (sigversion) {
394395
case SigVersion::BASE:
@@ -403,7 +404,7 @@ static bool EvalChecksig(const valtype& sig, const valtype& pubkey, CScript::con
403404
assert(false);
404405
}
405406

406-
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptExecutionData& execdata, ScriptError* serror)
407+
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)
407408
{
408409
static const CScriptNum bnZero(0);
409410
static const CScriptNum bnOne(1);
@@ -1233,7 +1234,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
12331234
return set_success(serror);
12341235
}
12351236

1236-
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror)
1237+
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, script_verify_flags flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror)
12371238
{
12381239
ScriptExecutionData execdata;
12391240
return EvalScript(stack, script, flags, checker, sigversion, execdata, serror);
@@ -1824,7 +1825,7 @@ bool GenericTransactionSignatureChecker<T>::CheckSequence(const CScriptNum& nSeq
18241825
template class GenericTransactionSignatureChecker<CTransaction>;
18251826
template class GenericTransactionSignatureChecker<CMutableTransaction>;
18261827

1827-
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)
1828+
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)
18281829
{
18291830
std::vector<valtype> stack{stack_span.begin(), stack_span.end()};
18301831

@@ -1909,7 +1910,7 @@ static bool VerifyTaprootCommitment(const std::vector<unsigned char>& control, c
19091910
return q.CheckTapTweak(p, merkle_root, control[0] & 1);
19101911
}
19111912

1912-
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)
1913+
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)
19131914
{
19141915
CScript exec_script; //!< Actually executed script (last stack item in P2WSH; implied P2PKH script in P2WPKH; leaf script in P2TR)
19151916
std::span stack{witness.stack};
@@ -1994,7 +1995,7 @@ static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion,
19941995
// 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.
19951996
}
19961997

1997-
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
1998+
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, script_verify_flags flags, const BaseSignatureChecker& checker, ScriptError* serror)
19981999
{
19992000
static const CScriptWitness emptyWitness;
20002001
if (witness == nullptr) {
@@ -2131,7 +2132,7 @@ size_t static WitnessSigOps(int witversion, const std::vector<unsigned char>& wi
21312132
return 0;
21322133
}
21332134

2134-
size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags)
2135+
size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, script_verify_flags flags)
21352136
{
21362137
static const CScriptWitness witnessEmpty;
21372138

@@ -2161,3 +2162,48 @@ size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey,
21612162

21622163
return 0;
21632164
}
2165+
2166+
#define FLAG_NAME(flag) {std::string(#flag), SCRIPT_VERIFY_##flag}
2167+
const std::map<std::string, script_verify_flag_name> g_verify_flag_names{
2168+
FLAG_NAME(P2SH),
2169+
FLAG_NAME(STRICTENC),
2170+
FLAG_NAME(DERSIG),
2171+
FLAG_NAME(LOW_S),
2172+
FLAG_NAME(SIGPUSHONLY),
2173+
FLAG_NAME(MINIMALDATA),
2174+
FLAG_NAME(NULLDUMMY),
2175+
FLAG_NAME(DISCOURAGE_UPGRADABLE_NOPS),
2176+
FLAG_NAME(CLEANSTACK),
2177+
FLAG_NAME(MINIMALIF),
2178+
FLAG_NAME(NULLFAIL),
2179+
FLAG_NAME(CHECKLOCKTIMEVERIFY),
2180+
FLAG_NAME(CHECKSEQUENCEVERIFY),
2181+
FLAG_NAME(WITNESS),
2182+
FLAG_NAME(DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM),
2183+
FLAG_NAME(WITNESS_PUBKEYTYPE),
2184+
FLAG_NAME(CONST_SCRIPTCODE),
2185+
FLAG_NAME(TAPROOT),
2186+
FLAG_NAME(DISCOURAGE_UPGRADABLE_PUBKEYTYPE),
2187+
FLAG_NAME(DISCOURAGE_OP_SUCCESS),
2188+
FLAG_NAME(DISCOURAGE_UPGRADABLE_TAPROOT_VERSION),
2189+
};
2190+
#undef FLAG_NAME
2191+
2192+
std::vector<std::string> GetScriptFlagNames(script_verify_flags flags)
2193+
{
2194+
std::vector<std::string> res;
2195+
if (flags == SCRIPT_VERIFY_NONE) {
2196+
return res;
2197+
}
2198+
script_verify_flags leftover = flags;
2199+
for (const auto& [name, flag] : g_verify_flag_names) {
2200+
if ((flags & flag) != 0) {
2201+
res.push_back(name);
2202+
leftover &= ~flag;
2203+
}
2204+
}
2205+
if (leftover != 0) {
2206+
res.push_back(strprintf("0x%08x", leftover.as_int()));
2207+
}
2208+
return res;
2209+
}

0 commit comments

Comments
 (0)