If I understand correctly, m_script_execution_cache_hasher
is a pre-initialized hasher that we want to copy every time we use it, and we definitely don’t want to modify in-place. I think having it as a public struct member is not very robust to enforce that, perhaps better to use a getter here? E.g. something like:
0diff --git a/src/validation.cpp b/src/validation.cpp
1index 39ab7b56ab..600c427c93 100644
2--- a/src/validation.cpp
3+++ b/src/validation.cpp
4@@ -2095,17 +2095,22 @@ bool CScriptCheck::operator()() {
5 return VerifyScript(scriptSig, m_tx_out.scriptPubKey, witness, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, m_tx_out.nValue, cacheStore, *m_signature_cache, *txdata), &error);
6 }
7
8-ValidationCache::ValidationCache(size_t script_execution_cache_bytes, size_t signature_cache_bytes)
9- : m_signature_cache{signature_cache_bytes / 2}
10+CSHA256 ValidationCache::CreateScriptExecutionCacheHasher()
11 {
12 // Setup the salted hasher
13 uint256 nonce = GetRandHash();
14 // We want the nonce to be 64 bytes long to force the hasher to process
15 // this chunk, which makes later hash computations more efficient. We
16 // just write our 32-byte entropy twice to fill the 64 bytes.
17- m_script_execution_cache_hasher.Write(nonce.begin(), 32);
18- m_script_execution_cache_hasher.Write(nonce.begin(), 32);
19+ CSHA256 hasher;
20+ hasher.Write(nonce.begin(), 32);
21+ hasher.Write(nonce.begin(), 32);
22+ return hasher;
23+}
24
25+ValidationCache::ValidationCache(size_t script_execution_cache_bytes, size_t signature_cache_bytes)
26+ : m_signature_cache{signature_cache_bytes / 2}
27+{
28 const auto [num_elems, approx_size_bytes] = m_script_execution_cache.setup_bytes(script_execution_cache_bytes);
29 LogPrintf("Using %zu MiB out of %zu MiB requested for script execution cache, able to store %zu elements\n",
30 approx_size_bytes >> 20, script_execution_cache_bytes >> 20, num_elems);
31@@ -2148,7 +2153,7 @@ bool CheckInputScripts(const CTransaction& tx, TxValidationState& state,
32 // properly commits to the scriptPubKey in the inputs view of that
33 // transaction).
34 uint256 hashCacheEntry;
35- CSHA256 hasher = validation_cache.m_script_execution_cache_hasher;
36+ auto hasher{validation_cache.ScriptExecutionCacheHasher()};
37 hasher.Write(UCharCast(tx.GetWitnessHash().begin()), 32).Write((unsigned char*)&flags, sizeof(flags)).Finalize(hashCacheEntry.begin());
38 AssertLockHeld(cs_main); //TODO: Remove this requirement by making CuckooCache not require external locks
39 if (validation_cache.m_script_execution_cache.contains(hashCacheEntry, !cacheFullScriptStore)) {
40diff --git a/src/validation.h b/src/validation.h
41index c4b49ec3e8..1e48f6b4a4 100644
42--- a/src/validation.h
43+++ b/src/validation.h
44@@ -369,11 +369,16 @@ static_assert(std::is_nothrow_destructible_v<CScriptCheck>);
45 * Convenience struct for initializing and passing the script execution cache
46 * and signature cache.
47 */
48-struct ValidationCache {
49+class ValidationCache {
50+public:
51 ScriptCache m_script_execution_cache;
52- CSHA256 m_script_execution_cache_hasher;
53+ CSHA256 ScriptExecutionCacheHasher() { return m_script_execution_cache_hasher; }
54 CSignatureCache m_signature_cache;
55 ValidationCache(size_t script_execution_cache_bytes, size_t signature_cache_bytes);
56+private:
57+ static CSHA256 CreateScriptExecutionCacheHasher();
58+ //! Pre-initialized hasher to avoid having to recreate it for every hash calculation
59+ const CSHA256 m_script_execution_cache_hasher{CreateScriptExecutionCacheHasher()};
60 };
61
62 /** Functions for validating blocks and updating the block tree */
It seems this is quite brittle on master too, so not a regression, but probably something to address here?