Bitcoin ABC  0.26.3
P2P Digital Currency
sigcache.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2016 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include <script/sigcache.h>
7 
8 #include <common/system.h>
9 #include <cuckoocache.h>
10 #include <logging.h>
11 #include <pubkey.h>
12 #include <random.h>
13 #include <uint256.h>
14 
15 #include <algorithm>
16 #include <mutex>
17 #include <optional>
18 #include <shared_mutex>
19 #include <vector>
20 
21 namespace {
22 
28 class CSignatureCache {
29 private:
31  CSHA256 m_salted_hasher;
34  map_type;
35  map_type setValid;
36  std::shared_mutex cs_sigcache;
37 
38 public:
39  CSignatureCache() {
40  uint256 nonce = GetRandHash();
41  // We want the nonce to be 64 bytes long to force the hasher to process
42  // this chunk, which makes later hash computations more efficient. We
43  // just write our 32-byte entropy twice to fill the 64 bytes.
44  m_salted_hasher.Write(nonce.begin(), 32);
45  m_salted_hasher.Write(nonce.begin(), 32);
46  }
47 
48  void ComputeEntry(uint256 &entry, const uint256 &hash,
49  const std::vector<uint8_t> &vchSig,
50  const CPubKey &pubkey) {
51  CSHA256 hasher = m_salted_hasher;
52  hasher.Write(hash.begin(), 32)
53  .Write(pubkey.data(), pubkey.size())
54  .Write(vchSig.data(), vchSig.size())
55  .Finalize(entry.begin());
56  }
57 
58  bool Get(const uint256 &entry, const bool erase) {
59  std::shared_lock<std::shared_mutex> lock(cs_sigcache);
60  return setValid.contains(entry, erase);
61  }
62 
63  void Set(const uint256 &entry) {
64  std::unique_lock<std::shared_mutex> lock(cs_sigcache);
65  setValid.insert(entry);
66  }
67  std::optional<std::pair<uint32_t, size_t>> setup_bytes(size_t n) {
68  return setValid.setup_bytes(n);
69  }
70 };
71 
79 static CSignatureCache signatureCache;
80 } // namespace
81 
82 // To be called once in AppInitMain/BasicTestingSetup to initialize the
83 // signatureCache.
84 
85 bool InitSignatureCache(size_t max_size_bytes) {
86  auto setup_results = signatureCache.setup_bytes(max_size_bytes);
87  if (!setup_results) {
88  return false;
89  }
90 
91  const auto [num_elems, approx_size_bytes] = *setup_results;
92  LogPrintf("Using %zu MiB out of %zu MiB requested for signature cache, "
93  "able to store %zu elements\n",
94  approx_size_bytes >> 20, max_size_bytes >> 20, num_elems);
95  return true;
96 }
97 
98 template <typename F>
99 bool RunMemoizedCheck(const std::vector<uint8_t> &vchSig, const CPubKey &pubkey,
100  const uint256 &sighash, bool storeOrErase, const F &fun) {
101  uint256 entry;
102  signatureCache.ComputeEntry(entry, sighash, vchSig, pubkey);
103  if (signatureCache.Get(entry, !storeOrErase)) {
104  return true;
105  }
106  if (!fun()) {
107  return false;
108  }
109  if (storeOrErase) {
110  signatureCache.Set(entry);
111  }
112  return true;
113 }
114 
116  const std::vector<uint8_t> &vchSig, const CPubKey &pubkey,
117  const uint256 &sighash) const {
118  return RunMemoizedCheck(vchSig, pubkey, sighash, true,
119  [] { return false; });
120 }
121 
123  const std::vector<uint8_t> &vchSig, const CPubKey &pubkey,
124  const uint256 &sighash) const {
125  return RunMemoizedCheck(vchSig, pubkey, sighash, store, [&] {
126  return TransactionSignatureChecker::VerifySignature(vchSig, pubkey,
127  sighash);
128  });
129 }
virtual bool VerifySignature(const std::vector< uint8_t > &vchSig, const CPubKey &vchPubKey, const uint256 &sighash) const
An encapsulated public key.
Definition: pubkey.h:31
const uint8_t * data() const
Definition: pubkey.h:99
unsigned int size() const
Simple read-only vector-like interface to the pubkey data.
Definition: pubkey.h:98
A hasher class for SHA-256.
Definition: sha256.h:13
CSHA256 & Write(const uint8_t *data, size_t len)
Definition: sha256.cpp:819
void Finalize(uint8_t hash[OUTPUT_SIZE])
Definition: sha256.cpp:844
bool VerifySignature(const std::vector< uint8_t > &vchSig, const CPubKey &vchPubKey, const uint256 &sighash) const override
Definition: sigcache.cpp:122
bool IsCached(const std::vector< uint8_t > &vchSig, const CPubKey &vchPubKey, const uint256 &sighash) const
Definition: sigcache.cpp:115
cache implements a cache with properties similar to a cuckoo-set.
Definition: cuckoocache.h:167
We're hashing a nonce into the entries themselves, so we don't need extra blinding in the set hash co...
Definition: hasher.h:80
uint8_t * begin()
Definition: uint256.h:85
256-bit opaque blob.
Definition: uint256.h:129
#define LogPrintf(...)
Definition: logging.h:207
uint256 GetRandHash() noexcept
Definition: random.cpp:659
bool RunMemoizedCheck(const std::vector< uint8_t > &vchSig, const CPubKey &pubkey, const uint256 &sighash, bool storeOrErase, const F &fun)
Definition: sigcache.cpp:99
bool InitSignatureCache(size_t max_size_bytes)
Definition: sigcache.cpp:85