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