Skip to content

Commit 606a7ab

Browse files
kernel: De-globalize signature cache
Move its ownership to the ChainstateManager class. Next to simplifying usage of the kernel library by no longer requiring manual setup of the cache prior to using validation code, it also slims down the amount of memory allocated by BasicTestingSetup. Use this opportunity to make SignatureCache RAII styled Co-authored-by: Ryan Ofsky <[email protected]>
1 parent 66d74bf commit 606a7ab

17 files changed

+54
-153
lines changed

src/Makefile.am

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,6 @@ BITCOIN_CORE_H = \
195195
kernel/mempool_removal_reason.h \
196196
kernel/messagestartchars.h \
197197
kernel/notifications_interface.h \
198-
kernel/validation_cache_sizes.h \
199198
kernel/warning.h \
200199
key.h \
201200
key_io.h \
@@ -240,7 +239,6 @@ BITCOIN_CORE_H = \
240239
node/txreconciliation.h \
241240
node/types.h \
242241
node/utxo_snapshot.h \
243-
node/validation_cache_args.h \
244242
node/warnings.h \
245243
noui.h \
246244
outputtype.h \
@@ -445,7 +443,6 @@ libbitcoin_node_a_SOURCES = \
445443
node/transaction.cpp \
446444
node/txreconciliation.cpp \
447445
node/utxo_snapshot.cpp \
448-
node/validation_cache_args.cpp \
449446
node/warnings.cpp \
450447
noui.cpp \
451448
policy/v3_policy.cpp \

src/bitcoin-chainstate.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
#include <kernel/chainstatemanager_opts.h>
1616
#include <kernel/checks.h>
1717
#include <kernel/context.h>
18-
#include <kernel/validation_cache_sizes.h>
1918
#include <kernel/warning.h>
2019

2120
#include <consensus/validation.h>
@@ -63,12 +62,6 @@ int main(int argc, char* argv[])
6362
// properly
6463
assert(kernel::SanityChecks(kernel_context));
6564

66-
// Necessary for CheckInputScripts (eventually called by ProcessNewBlock),
67-
// which will try the script cache first and fall back to actually
68-
// performing the check with the signature cache.
69-
kernel::ValidationCacheSizes validation_cache_sizes{};
70-
Assert(InitSignatureCache(validation_cache_sizes.signature_cache_bytes));
71-
7265
ValidationSignals validation_signals{std::make_unique<util::ImmediateTaskRunner>()};
7366

7467
class KernelNotifications : public kernel::Notifications

src/init.cpp

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
#include <init.h>
99

1010
#include <kernel/checks.h>
11-
#include <kernel/validation_cache_sizes.h>
1211

1312
#include <addrman.h>
1413
#include <banman.h>
@@ -54,7 +53,6 @@
5453
#include <node/mempool_persist_args.h>
5554
#include <node/miner.h>
5655
#include <node/peerman_args.h>
57-
#include <node/validation_cache_args.h>
5856
#include <policy/feerate.h>
5957
#include <policy/fees.h>
6058
#include <policy/fees_args.h>
@@ -119,7 +117,6 @@
119117
using common::AmountErrMsg;
120118
using common::InvalidPortErrMsg;
121119
using common::ResolveErrMsg;
122-
using kernel::ValidationCacheSizes;
123120

124121
using node::ApplyArgsManOptions;
125122
using node::BlockManager;
@@ -619,7 +616,7 @@ void SetupServerArgs(ArgsManager& argsman)
619616
argsman.AddArg("-test=<option>", "Pass a test-only option. Options include : " + Join(TEST_OPTIONS_DOC, ", ") + ".", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
620617
argsman.AddArg("-capturemessages", "Capture all P2P messages to disk", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
621618
argsman.AddArg("-mocktime=<n>", "Replace actual time with " + UNIX_EPOCH_TIME + " (default: 0)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
622-
argsman.AddArg("-maxsigcachesize=<n>", strprintf("Limit sum of signature cache and script execution cache sizes to <n> MiB (default: %u)", DEFAULT_MAX_SIG_CACHE_BYTES >> 20), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
619+
argsman.AddArg("-maxsigcachesize=<n>", strprintf("Limit sum of signature cache and script execution cache sizes to <n> MiB (default: %u)", DEFAULT_VALIDATION_CACHE_BYTES >> 20), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
623620
argsman.AddArg("-maxtipage=<n>",
624621
strprintf("Maximum tip age in seconds to consider node in initial block download (default: %u)",
625622
Ticks<std::chrono::seconds>(DEFAULT_MAX_TIP_AGE)),
@@ -1154,10 +1151,6 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
11541151
args.GetArg("-datadir", ""), fs::PathToString(fs::current_path()));
11551152
}
11561153

1157-
ValidationCacheSizes validation_cache_sizes{};
1158-
ApplyArgsManOptions(args, validation_cache_sizes);
1159-
(void)InitSignatureCache(validation_cache_sizes.signature_cache_bytes);
1160-
11611154
assert(!node.scheduler);
11621155
node.scheduler = std::make_unique<CScheduler>();
11631156
auto& scheduler = *node.scheduler;

src/kernel/chainstatemanager_opts.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ struct ChainstateManagerOpts {
5050
//! Number of script check worker threads. Zero means no parallel verification.
5151
int worker_threads_num{0};
5252
size_t script_execution_cache_bytes{DEFAULT_SCRIPT_EXECUTION_CACHE_BYTES};
53+
size_t signature_cache_bytes{DEFAULT_SIGNATURE_CACHE_BYTES};
5354
};
5455

5556
} // namespace kernel

src/kernel/validation_cache_sizes.h

Lines changed: 0 additions & 19 deletions
This file was deleted.

src/node/chainstatemanager_args.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ util::Result<void> ApplyArgsManOptions(const ArgsManager& args, ChainstateManage
6363
// 2. Multiply first, divide after to avoid integer truncation.
6464
size_t clamped_size_each = std::max<int64_t>(*max_size, 0) * (1 << 20) / 2;
6565
opts.script_execution_cache_bytes = clamped_size_each;
66+
opts.signature_cache_bytes = clamped_size_each;
6667
}
6768

6869
return {};

src/node/validation_cache_args.cpp

Lines changed: 0 additions & 33 deletions
This file was deleted.

src/node/validation_cache_args.h

Lines changed: 0 additions & 17 deletions
This file was deleted.

src/script/sigcache.cpp

Lines changed: 11 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#include <shared_mutex>
1818
#include <vector>
1919

20-
SignatureCache::SignatureCache()
20+
SignatureCache::SignatureCache(const size_t max_size_bytes)
2121
{
2222
uint256 nonce = GetRandHash();
2323
// We want the nonce to be 64 bytes long to force the hasher to process
@@ -30,6 +30,10 @@ SignatureCache::SignatureCache()
3030
m_salted_hasher_ecdsa.Write(PADDING_ECDSA, 32);
3131
m_salted_hasher_schnorr.Write(nonce.begin(), 32);
3232
m_salted_hasher_schnorr.Write(PADDING_SCHNORR, 32);
33+
34+
const auto [num_elems, approx_size_bytes] = setValid.setup_bytes(max_size_bytes);
35+
LogPrintf("Using %zu MiB out of %zu MiB requested for signature cache, able to store %zu elements\n",
36+
approx_size_bytes >> 20, max_size_bytes >> 20, num_elems);
3337
}
3438

3539
void SignatureCache::ComputeEntryECDSA(uint256& entry, const uint256& hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubkey) const
@@ -56,48 +60,25 @@ void SignatureCache::Set(const uint256& entry)
5660
setValid.insert(entry);
5761
}
5862

59-
std::pair<uint32_t, size_t> SignatureCache::setup_bytes(size_t n)
60-
{
61-
return setValid.setup_bytes(n);
62-
}
63-
64-
/* In previous versions of this code, signatureCache was a local static variable
65-
* in CachingTransactionSignatureChecker::VerifySignature. We initialize
66-
* signatureCache outside of VerifySignature to avoid the atomic operation per
67-
* call overhead associated with local static variables even though
68-
* signatureCache could be made local to VerifySignature.
69-
*/
70-
static SignatureCache signatureCache;
71-
72-
// To be called once in AppInitMain/BasicTestingSetup to initialize the
73-
// signatureCache.
74-
bool InitSignatureCache(size_t max_size_bytes)
75-
{
76-
const auto [num_elems, approx_size_bytes] = signatureCache.setup_bytes(max_size_bytes);
77-
LogPrintf("Using %zu MiB out of %zu MiB requested for signature cache, able to store %zu elements\n",
78-
approx_size_bytes >> 20, max_size_bytes >> 20, num_elems);
79-
return true;
80-
}
81-
8263
bool CachingTransactionSignatureChecker::VerifyECDSASignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const
8364
{
8465
uint256 entry;
85-
signatureCache.ComputeEntryECDSA(entry, sighash, vchSig, pubkey);
86-
if (signatureCache.Get(entry, !store))
66+
m_signature_cache.ComputeEntryECDSA(entry, sighash, vchSig, pubkey);
67+
if (m_signature_cache.Get(entry, !store))
8768
return true;
8869
if (!TransactionSignatureChecker::VerifyECDSASignature(vchSig, pubkey, sighash))
8970
return false;
9071
if (store)
91-
signatureCache.Set(entry);
72+
m_signature_cache.Set(entry);
9273
return true;
9374
}
9475

9576
bool CachingTransactionSignatureChecker::VerifySchnorrSignature(Span<const unsigned char> sig, const XOnlyPubKey& pubkey, const uint256& sighash) const
9677
{
9778
uint256 entry;
98-
signatureCache.ComputeEntrySchnorr(entry, sighash, sig, pubkey);
99-
if (signatureCache.Get(entry, !store)) return true;
79+
m_signature_cache.ComputeEntrySchnorr(entry, sighash, sig, pubkey);
80+
if (m_signature_cache.Get(entry, !store)) return true;
10081
if (!TransactionSignatureChecker::VerifySchnorrSignature(sig, pubkey, sighash)) return false;
101-
if (store) signatureCache.Set(entry);
82+
if (store) m_signature_cache.Set(entry);
10283
return true;
10384
}

src/script/sigcache.h

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,20 @@
1515
#include <util/hasher.h>
1616

1717
#include <cstddef>
18-
#include <cstdint>
1918
#include <shared_mutex>
20-
#include <utility>
2119
#include <vector>
2220

21+
class CPubKey;
2322
class CTransaction;
2423
class XOnlyPubKey;
2524

2625
// DoS prevention: limit cache size to 32MiB (over 1000000 entries on 64-bit
2726
// systems). Due to how we count cache size, actual memory usage is slightly
2827
// more (~32.25 MiB)
29-
static constexpr size_t DEFAULT_MAX_SIG_CACHE_BYTES{32 << 20};
30-
static constexpr size_t DEFAULT_SCRIPT_EXECUTION_CACHE_BYTES{DEFAULT_MAX_SIG_CACHE_BYTES / 2};
31-
32-
class CPubKey;
28+
static constexpr size_t DEFAULT_VALIDATION_CACHE_BYTES{32 << 20};
29+
static constexpr size_t DEFAULT_SIGNATURE_CACHE_BYTES{DEFAULT_VALIDATION_CACHE_BYTES / 2};
30+
static constexpr size_t DEFAULT_SCRIPT_EXECUTION_CACHE_BYTES{DEFAULT_VALIDATION_CACHE_BYTES / 2};
31+
static_assert(DEFAULT_VALIDATION_CACHE_BYTES == DEFAULT_SIGNATURE_CACHE_BYTES + DEFAULT_SCRIPT_EXECUTION_CACHE_BYTES);
3332

3433
/**
3534
* Valid signature cache, to avoid doing expensive ECDSA signature checking
@@ -47,7 +46,10 @@ class SignatureCache
4746
std::shared_mutex cs_sigcache;
4847

4948
public:
50-
SignatureCache();
49+
SignatureCache(size_t max_size_bytes);
50+
51+
SignatureCache(const SignatureCache&) = delete;
52+
SignatureCache& operator=(const SignatureCache&) = delete;
5153

5254
void ComputeEntryECDSA(uint256& entry, const uint256 &hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubkey) const;
5355

@@ -56,22 +58,19 @@ class SignatureCache
5658
bool Get(const uint256& entry, const bool erase);
5759

5860
void Set(const uint256& entry);
59-
60-
std::pair<uint32_t, size_t> setup_bytes(size_t n);
6161
};
6262

6363
class CachingTransactionSignatureChecker : public TransactionSignatureChecker
6464
{
6565
private:
6666
bool store;
67+
SignatureCache& m_signature_cache;
6768

6869
public:
69-
CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, bool storeIn, PrecomputedTransactionData& txdataIn) : TransactionSignatureChecker(txToIn, nInIn, amountIn, txdataIn, MissingDataBehavior::ASSERT_FAIL), store(storeIn) {}
70+
CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, bool storeIn, SignatureCache& signature_cache, PrecomputedTransactionData& txdataIn) : TransactionSignatureChecker(txToIn, nInIn, amountIn, txdataIn, MissingDataBehavior::ASSERT_FAIL), store(storeIn), m_signature_cache(signature_cache) {}
7071

7172
bool VerifyECDSASignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const override;
7273
bool VerifySchnorrSignature(Span<const unsigned char> sig, const XOnlyPubKey& pubkey, const uint256& sighash) const override;
7374
};
7475

75-
[[nodiscard]] bool InitSignatureCache(size_t max_size_bytes);
76-
7776
#endif // BITCOIN_SCRIPT_SIGCACHE_H

0 commit comments

Comments
 (0)