Bitcoin Core  0.20.99
P2P Digital Currency
sigcache.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2019 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 <pubkey.h>
9 #include <random.h>
10 #include <uint256.h>
11 #include <util/system.h>
12 
13 #include <cuckoocache.h>
14 #include <boost/thread/shared_mutex.hpp>
15 
16 namespace {
22 class CSignatureCache
23 {
24 private:
26  CSHA256 m_salted_hasher_ecdsa;
27  CSHA256 m_salted_hasher_schnorr;
29  map_type setValid;
30  boost::shared_mutex cs_sigcache;
31 
32 public:
33  CSignatureCache()
34  {
35  uint256 nonce = GetRandHash();
36  // We want the nonce to be 64 bytes long to force the hasher to process
37  // this chunk, which makes later hash computations more efficient. We
38  // just write our 32-byte entropy, and then pad with 'E' for ECDSA and
39  // 'S' for Schnorr (followed by 0 bytes).
40  static constexpr unsigned char PADDING_ECDSA[32] = {'E'};
41  static constexpr unsigned char PADDING_SCHNORR[32] = {'S'};
42  m_salted_hasher_ecdsa.Write(nonce.begin(), 32);
43  m_salted_hasher_ecdsa.Write(PADDING_ECDSA, 32);
44  m_salted_hasher_schnorr.Write(nonce.begin(), 32);
45  m_salted_hasher_schnorr.Write(PADDING_SCHNORR, 32);
46  }
47 
48  void
49  ComputeEntryECDSA(uint256& entry, const uint256 &hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubkey) const
50  {
51  CSHA256 hasher = m_salted_hasher_ecdsa;
52  hasher.Write(hash.begin(), 32).Write(&pubkey[0], pubkey.size()).Write(&vchSig[0], vchSig.size()).Finalize(entry.begin());
53  }
54 
55  void
56  ComputeEntrySchnorr(uint256& entry, const uint256 &hash, Span<const unsigned char> sig, const XOnlyPubKey& pubkey) const
57  {
58  CSHA256 hasher = m_salted_hasher_schnorr;
59  hasher.Write(hash.begin(), 32).Write(&pubkey[0], pubkey.size()).Write(sig.data(), sig.size()).Finalize(entry.begin());
60  }
61 
62  bool
63  Get(const uint256& entry, const bool erase)
64  {
65  boost::shared_lock<boost::shared_mutex> lock(cs_sigcache);
66  return setValid.contains(entry, erase);
67  }
68 
69  void Set(uint256& entry)
70  {
71  boost::unique_lock<boost::shared_mutex> lock(cs_sigcache);
72  setValid.insert(entry);
73  }
74  uint32_t setup_bytes(size_t n)
75  {
76  return setValid.setup_bytes(n);
77  }
78 };
79 
80 /* In previous versions of this code, signatureCache was a local static variable
81  * in CachingTransactionSignatureChecker::VerifySignature. We initialize
82  * signatureCache outside of VerifySignature to avoid the atomic operation per
83  * call overhead associated with local static variables even though
84  * signatureCache could be made local to VerifySignature.
85 */
86 static CSignatureCache signatureCache;
87 } // namespace
88 
89 // To be called once in AppInitMain/BasicTestingSetup to initialize the
90 // signatureCache.
92 {
93  // nMaxCacheSize is unsigned. If -maxsigcachesize is set to zero,
94  // setup_bytes creates the minimum possible cache (2 elements).
95  size_t nMaxCacheSize = std::min(std::max((int64_t)0, gArgs.GetArg("-maxsigcachesize", DEFAULT_MAX_SIG_CACHE_SIZE) / 2), MAX_MAX_SIG_CACHE_SIZE) * ((size_t) 1 << 20);
96  size_t nElems = signatureCache.setup_bytes(nMaxCacheSize);
97  LogPrintf("Using %zu MiB out of %zu/2 requested for signature cache, able to store %zu elements\n",
98  (nElems*sizeof(uint256)) >>20, (nMaxCacheSize*2)>>20, nElems);
99 }
100 
101 bool CachingTransactionSignatureChecker::VerifyECDSASignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const
102 {
103  uint256 entry;
104  signatureCache.ComputeEntryECDSA(entry, sighash, vchSig, pubkey);
105  if (signatureCache.Get(entry, !store))
106  return true;
107  if (!TransactionSignatureChecker::VerifyECDSASignature(vchSig, pubkey, sighash))
108  return false;
109  if (store)
110  signatureCache.Set(entry);
111  return true;
112 }
113 
115 {
116  uint256 entry;
117  signatureCache.ComputeEntrySchnorr(entry, sighash, sig, pubkey);
118  if (signatureCache.Get(entry, !store)) return true;
119  if (!TransactionSignatureChecker::VerifySchnorrSignature(sig, pubkey, sighash)) return false;
120  if (store) signatureCache.Set(entry);
121  return true;
122 }
peer m_getdata_requests erase(peer.m_getdata_requests.begin(), it)
CSHA256 & Write(const unsigned char *data, size_t len)
Definition: sha256.cpp:637
bool VerifySchnorrSignature(Span< const unsigned char > sig, const XOnlyPubKey &pubkey, const uint256 &sighash) const override
Definition: sigcache.cpp:114
virtual bool VerifySchnorrSignature(Span< const unsigned char > sig, const XOnlyPubKey &pubkey, const uint256 &sighash) const
static const unsigned int DEFAULT_MAX_SIG_CACHE_SIZE
Definition: sigcache.h:17
uint256 GetRandHash() noexcept
Definition: random.cpp:602
constexpr std::size_t size() const noexcept
Definition: span.h:153
cache implements a cache with properties similar to a cuckoo-set.
Definition: cuckoocache.h:158
static void LogPrintf(const char *fmt, const Args &... args)
Definition: logging.h:166
unsigned char * begin()
Definition: uint256.h:58
virtual bool VerifyECDSASignature(const std::vector< unsigned char > &vchSig, const CPubKey &vchPubKey, const uint256 &sighash) const
size_t size() const
Definition: pubkey.h:228
An encapsulated public key.
Definition: pubkey.h:31
void InitSignatureCache()
Definition: sigcache.cpp:91
unsigned int size() const
Simple read-only vector-like interface to the pubkey data.
Definition: pubkey.h:110
256-bit opaque blob.
Definition: uint256.h:124
static const int64_t MAX_MAX_SIG_CACHE_SIZE
Definition: sigcache.h:19
constexpr C * data() const noexcept
Definition: span.h:140
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: system.cpp:466
ArgsManager gArgs
Definition: system.cpp:76
bool VerifyECDSASignature(const std::vector< unsigned char > &vchSig, const CPubKey &vchPubKey, const uint256 &sighash) const override
Definition: sigcache.cpp:101
A Span is an object that can refer to a contiguous sequence of objects.
Definition: span.h:82
A hasher class for SHA-256.
Definition: sha256.h:13