LCOV - code coverage report
Current view: top level - src/script - sigcache.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 37 37 100.0 %
Date: 2026-06-25 07:23:43 Functions: 9 11 81.8 %

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2021 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 <mutex>
      16             : #include <shared_mutex>
      17             : #include <vector>
      18             : 
      19             : namespace {
      20             : /**
      21             :  * Valid signature cache, to avoid doing expensive ECDSA signature checking
      22             :  * twice for every transaction (once when accepted into memory pool, and
      23             :  * again when accepted into the block chain)
      24             :  */
      25             : class CSignatureCache
      26             : {
      27             : private:
      28             :      //! Entries are SHA256(nonce || signature hash || public key || signature):
      29             :     CSHA256 m_salted_hasher;
      30             :     typedef CuckooCache::cache<uint256, SignatureCacheHasher> map_type;
      31             :     map_type setValid;
      32             :     std::shared_mutex cs_sigcache;
      33             : 
      34             : public:
      35        6616 :     CSignatureCache()
      36        3308 :     {
      37        3308 :         uint256 nonce = GetRandHash();
      38             :         // We want the nonce to be 64 bytes long to force the hasher to process
      39             :         // this chunk, which makes later hash computations more efficient. We
      40             :         // just write our 32-byte entropy twice to fill the 64 bytes.
      41        3308 :         m_salted_hasher.Write(nonce.begin(), 32);
      42        3308 :         m_salted_hasher.Write(nonce.begin(), 32);
      43        6616 :     }
      44             : 
      45             :     void
      46      288859 :     ComputeEntry(uint256& entry, const uint256 &hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubkey)
      47             :     {
      48      288859 :         CSHA256 hasher = m_salted_hasher;
      49      288859 :         hasher.Write(hash.begin(), 32).Write(pubkey.data(), pubkey.size()).Write(vchSig.data(), vchSig.size()).Finalize(entry.begin());
      50      288859 :     }
      51             : 
      52             :     bool
      53      289070 :     Get(const uint256& entry, const bool erase)
      54             :     {
      55      289070 :         std::shared_lock<std::shared_mutex> lock(cs_sigcache);
      56      289070 :         return setValid.contains(entry, erase);
      57      289070 :     }
      58             : 
      59       37746 :     void Set(const uint256& entry)
      60             :     {
      61       37746 :         std::unique_lock<std::shared_mutex> lock(cs_sigcache);
      62       37746 :         setValid.insert(entry);
      63       37746 :     }
      64        3650 :     uint32_t setup_bytes(size_t n)
      65             :     {
      66        3650 :         return setValid.setup_bytes(n);
      67             :     }
      68             : };
      69             : 
      70             : /* In previous versions of this code, signatureCache was a local static variable
      71             :  * in CachingTransactionSignatureChecker::VerifySignature.  We initialize
      72             :  * signatureCache outside of VerifySignature to avoid the atomic operation per
      73             :  * call overhead associated with local static variables even though
      74             :  * signatureCache could be made local to VerifySignature.
      75             : */
      76        3308 : static CSignatureCache signatureCache;
      77             : } // namespace
      78             : 
      79             : // To be called once in AppInitMain/BasicTestingSetup to initialize the
      80             : // signatureCache.
      81        3650 : void InitSignatureCache()
      82             : {
      83             :     // nMaxCacheSize is unsigned. If -maxsigcachesize is set to zero,
      84             :     // setup_bytes creates the minimum possible cache (2 elements).
      85        3650 :     size_t nMaxCacheSize = std::min(std::max((int64_t)0, gArgs.GetIntArg("-maxsigcachesize", DEFAULT_MAX_SIG_CACHE_SIZE) / 2), MAX_MAX_SIG_CACHE_SIZE) * ((size_t) 1 << 20);
      86        3650 :     size_t nElems = signatureCache.setup_bytes(nMaxCacheSize);
      87        3650 :     LogPrintf("Using %zu MiB out of %zu/2 requested for signature cache, able to store %zu elements\n",
      88             :             (nElems*sizeof(uint256)) >>20, (nMaxCacheSize*2)>>20, nElems);
      89        3650 : }
      90             : 
      91      289009 : bool CachingTransactionSignatureChecker::VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const
      92             : {
      93      289009 :     uint256 entry;
      94      289009 :     signatureCache.ComputeEntry(entry, sighash, vchSig, pubkey);
      95      289009 :     if (signatureCache.Get(entry, !store))
      96      103721 :         return true;
      97      185288 :     if (!TransactionSignatureChecker::VerifySignature(vchSig, pubkey, sighash))
      98          96 :         return false;
      99      185192 :     if (store)
     100       37746 :         signatureCache.Set(entry);
     101      185192 :     return true;
     102      289009 : }

Generated by: LCOV version 1.16