Merge bitcoin/bitcoin#33600: refactor: Construct g_verify_flag_names on first use

faa9d10c84 refactor: Construct g_verify_flag_names on first use (MarcoFalke)

Pull request description:

  The current usage of the `g_verify_flag_names` map seems fine and I can not see a static initialization order fiasco here.

  However, it seems brittle to hope this remains the case in the future. Also, it triggers a msan false-positive in the fuzz CI task. (C.f https://github.com/bitcoin-core/qa-assets/actions/runs/18352815555/job/52413137315?pr=241#step:7:5245)

  So just apply the "Construct on first use" idiom.

ACKs for top commit:
  kevkevinpal:
    ACK [faa9d10](faa9d10c84)
  ajtowns:
    ACK faa9d10c84
  janb84:
    lgtm ACK faa9d10c84
  stickies-v:
    ACK faa9d10c84

Tree-SHA512: 6685dfc91c99a8245722e07fac99a7a6d58586c30964be7ccd74a176dfbf00c6255c8594621e2909640763924f51d3efd4ce65ed65eaeeb1d05c2fd01fe63604
This commit is contained in:
merge-script
2025-10-23 05:55:55 -04:00
3 changed files with 30 additions and 26 deletions

View File

@@ -2163,31 +2163,35 @@ size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey,
return 0;
}
const std::map<std::string, script_verify_flag_name>& ScriptFlagNamesToEnum()
{
#define FLAG_NAME(flag) {std::string(#flag), SCRIPT_VERIFY_##flag}
const std::map<std::string, script_verify_flag_name> g_verify_flag_names{
FLAG_NAME(P2SH),
FLAG_NAME(STRICTENC),
FLAG_NAME(DERSIG),
FLAG_NAME(LOW_S),
FLAG_NAME(SIGPUSHONLY),
FLAG_NAME(MINIMALDATA),
FLAG_NAME(NULLDUMMY),
FLAG_NAME(DISCOURAGE_UPGRADABLE_NOPS),
FLAG_NAME(CLEANSTACK),
FLAG_NAME(MINIMALIF),
FLAG_NAME(NULLFAIL),
FLAG_NAME(CHECKLOCKTIMEVERIFY),
FLAG_NAME(CHECKSEQUENCEVERIFY),
FLAG_NAME(WITNESS),
FLAG_NAME(DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM),
FLAG_NAME(WITNESS_PUBKEYTYPE),
FLAG_NAME(CONST_SCRIPTCODE),
FLAG_NAME(TAPROOT),
FLAG_NAME(DISCOURAGE_UPGRADABLE_PUBKEYTYPE),
FLAG_NAME(DISCOURAGE_OP_SUCCESS),
FLAG_NAME(DISCOURAGE_UPGRADABLE_TAPROOT_VERSION),
};
static const std::map<std::string, script_verify_flag_name> g_names_to_enum{
FLAG_NAME(P2SH),
FLAG_NAME(STRICTENC),
FLAG_NAME(DERSIG),
FLAG_NAME(LOW_S),
FLAG_NAME(SIGPUSHONLY),
FLAG_NAME(MINIMALDATA),
FLAG_NAME(NULLDUMMY),
FLAG_NAME(DISCOURAGE_UPGRADABLE_NOPS),
FLAG_NAME(CLEANSTACK),
FLAG_NAME(MINIMALIF),
FLAG_NAME(NULLFAIL),
FLAG_NAME(CHECKLOCKTIMEVERIFY),
FLAG_NAME(CHECKSEQUENCEVERIFY),
FLAG_NAME(WITNESS),
FLAG_NAME(DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM),
FLAG_NAME(WITNESS_PUBKEYTYPE),
FLAG_NAME(CONST_SCRIPTCODE),
FLAG_NAME(TAPROOT),
FLAG_NAME(DISCOURAGE_UPGRADABLE_PUBKEYTYPE),
FLAG_NAME(DISCOURAGE_OP_SUCCESS),
FLAG_NAME(DISCOURAGE_UPGRADABLE_TAPROOT_VERSION),
};
#undef FLAG_NAME
return g_names_to_enum;
}
std::vector<std::string> GetScriptFlagNames(script_verify_flags flags)
{
@@ -2196,7 +2200,7 @@ std::vector<std::string> GetScriptFlagNames(script_verify_flags flags)
return res;
}
script_verify_flags leftover = flags;
for (const auto& [name, flag] : g_verify_flag_names) {
for (const auto& [name, flag] : ScriptFlagNamesToEnum()) {
if ((flags & flag) != 0) {
res.push_back(name);
leftover &= ~flag;

View File

@@ -381,7 +381,7 @@ size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey,
int FindAndDelete(CScript& script, const CScript& b);
extern const std::map<std::string, script_verify_flag_name> g_verify_flag_names;
const std::map<std::string, script_verify_flag_name>& ScriptFlagNamesToEnum();
std::vector<std::string> GetScriptFlagNames(script_verify_flags flags);

View File

@@ -50,7 +50,7 @@ typedef std::vector<unsigned char> valtype;
static CFeeRate g_dust{DUST_RELAY_TX_FEE};
static bool g_bare_multi{DEFAULT_PERMIT_BAREMULTISIG};
static const std::map<std::string, script_verify_flag_name>& mapFlagNames = g_verify_flag_names;
static const std::map<std::string, script_verify_flag_name>& mapFlagNames = ScriptFlagNamesToEnum();
script_verify_flags ParseScriptFlags(std::string strFlags)
{