nit: I’d prefer avoiding having this dual state. Here are 2 variations which do that:
Preserving behavior:
0diff --git a/src/validation.cpp b/src/validation.cpp
1index 7e82c3bbad..008bfe4d71 100644
2--- a/src/validation.cpp
3+++ b/src/validation.cpp
4@@ -2423,8 +2423,7 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
5 return true;
6 }
7
8- auto fScriptChecks{true};
9- std::string script_check_reason;
10+ const char* script_check_reason{nullptr};
11 if (!m_chainman.AssumedValidBlock().IsNull()) {
12 constexpr int64_t TWO_WEEKS_IN_SECONDS{60 * 60 * 24 * 7 * 2};
13 // We've been configured with the hash of a block which has been externally verified to have a valid history.
14@@ -2458,7 +2457,6 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
15 // artificially set the default assumed verified block further back.
16 // The test against the minimum chain work prevents the skipping when denied access to any chain at
17 // least as good as the expected chain.
18- fScriptChecks = false;
19 }
20 } else {
21 script_check_reason = "assumevalid=0 (always verify)";
22@@ -2573,16 +2571,15 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
23 Ticks<SecondsDouble>(m_chainman.time_forks),
24 Ticks<MillisecondsDouble>(m_chainman.time_forks) / m_chainman.num_blocks_total);
25
26- if (fScriptChecks != m_prev_script_checks_logged && GetRole() == ChainstateRole::NORMAL) {
27- if (fScriptChecks) {
28- Assume(!script_check_reason.empty());
29+ if ((script_check_reason != nullptr) != m_prev_script_checks_logged && GetRole() == ChainstateRole::NORMAL) {
30+ if (script_check_reason) {
31 LogInfo("Enabling script verification at block #%d (%s): %s.",
32 pindex->nHeight, block_hash.ToString(), script_check_reason);
33 } else {
34 LogInfo("Disabling script verification at block #%d (%s).",
35 pindex->nHeight, block_hash.ToString());
36 }
37- m_prev_script_checks_logged = fScriptChecks;
38+ m_prev_script_checks_logged = script_check_reason != nullptr;
39 }
40
41 CBlockUndo blockundo;
42@@ -2593,7 +2590,7 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
43 // doesn't invalidate pointers into the vector, and keep txsdata in scope
44 // for as long as `control`.
45 std::optional<CCheckQueueControl<CScriptCheck>> control;
46- if (auto& queue = m_chainman.GetCheckQueue(); queue.HasThreads() && fScriptChecks) control.emplace(queue);
47+ if (auto& queue = m_chainman.GetCheckQueue(); queue.HasThreads() && script_check_reason != nullptr) control.emplace(queue);
48
49 std::vector<PrecomputedTransactionData> txsdata(block.vtx.size());
50
51@@ -2652,7 +2649,7 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
52 break;
53 }
54
55- if (!tx.IsCoinBase() && fScriptChecks)
56+ if (!tx.IsCoinBase() && script_check_reason != nullptr)
57 {
58 bool fCacheResults = fJustCheck; /* Don't cache results if we're actually connecting blocks (still consult the cache, though) */
59 bool tx_ok;
0diff --git a/src/validation.cpp b/src/validation.cpp
1index 7e82c3bbad..79ad71b64c 100644
2--- a/src/validation.cpp
3+++ b/src/validation.cpp
4@@ -2423,8 +2423,7 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
5 return true;
6 }
7
8- auto fScriptChecks{true};
9- std::string script_check_reason;
10+ const char* script_check_reason{nullptr};
11 if (!m_chainman.AssumedValidBlock().IsNull()) {
12 constexpr int64_t TWO_WEEKS_IN_SECONDS{60 * 60 * 24 * 7 * 2};
13 // We've been configured with the hash of a block which has been externally verified to have a valid history.
14@@ -2458,7 +2457,6 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
15 // artificially set the default assumed verified block further back.
16 // The test against the minimum chain work prevents the skipping when denied access to any chain at
17 // least as good as the expected chain.
18- fScriptChecks = false;
19 }
20 } else {
21 script_check_reason = "assumevalid=0 (always verify)";
22@@ -2573,16 +2571,15 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
23 Ticks<SecondsDouble>(m_chainman.time_forks),
24 Ticks<MillisecondsDouble>(m_chainman.time_forks) / m_chainman.num_blocks_total);
25
26- if (fScriptChecks != m_prev_script_checks_logged && GetRole() == ChainstateRole::NORMAL) {
27- if (fScriptChecks) {
28- Assume(!script_check_reason.empty());
29+ if (script_check_reason != m_prev_script_check_reason && GetRole() == ChainstateRole::NORMAL) {
30+ if (script_check_reason) {
31 LogInfo("Enabling script verification at block #%d (%s): %s.",
32 pindex->nHeight, block_hash.ToString(), script_check_reason);
33 } else {
34 LogInfo("Disabling script verification at block #%d (%s).",
35 pindex->nHeight, block_hash.ToString());
36 }
37- m_prev_script_checks_logged = fScriptChecks;
38+ m_prev_script_check_reason = script_check_reason;
39 }
40
41 CBlockUndo blockundo;
42@@ -2593,7 +2590,7 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
43 // doesn't invalidate pointers into the vector, and keep txsdata in scope
44 // for as long as `control`.
45 std::optional<CCheckQueueControl<CScriptCheck>> control;
46- if (auto& queue = m_chainman.GetCheckQueue(); queue.HasThreads() && fScriptChecks) control.emplace(queue);
47+ if (auto& queue = m_chainman.GetCheckQueue(); queue.HasThreads() && script_check_reason) control.emplace(queue);
48
49 std::vector<PrecomputedTransactionData> txsdata(block.vtx.size());
50
51@@ -2652,7 +2649,7 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
52 break;
53 }
54
55- if (!tx.IsCoinBase() && fScriptChecks)
56+ if (!tx.IsCoinBase() && script_check_reason)
57 {
58 bool fCacheResults = fJustCheck; /* Don't cache results if we're actually connecting blocks (still consult the cache, though) */
59 bool tx_ok;
60diff --git a/src/validation.h b/src/validation.h
61index fea11c5515..6e426a4660 100644
62--- a/src/validation.h
63+++ b/src/validation.h
64@@ -560,7 +560,7 @@ protected:
65 //! Cached result of LookupBlockIndex(*m_from_snapshot_blockhash)
66 mutable const CBlockIndex* m_cached_snapshot_base GUARDED_BY(::cs_main){nullptr};
67
68- std::optional<bool> m_prev_script_checks_logged GUARDED_BY(::cs_main){};
69+ std::optional<const char*> m_prev_script_check_reason GUARDED_BY(::cs_main){};
70
71 public:
72 //! Reference to a BlockManager instance which itself is shared across all