LCOV - code coverage report
Current view: top level - src/script - sigcache.cpp (source / functions) Hit Total Coverage
Test: test_dash_coverage.info Lines: 37 37 100.0 %
Date: 2026-06-25 07:23:51 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         292 :     CSignatureCache()
      36         146 :     {
      37         146 :         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         146 :         m_salted_hasher.Write(nonce.begin(), 32);
      42         146 :         m_salted_hasher.Write(nonce.begin(), 32);
      43         292 :     }
      44             : 
      45             :     void
      46       29598 :     ComputeEntry(uint256& entry, const uint256 &hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubkey)
      47             :     {
      48       29598 :         CSHA256 hasher = m_salted_hasher;
      49       29598 :         hasher.Write(hash.begin(), 32).Write(pubkey.data(), pubkey.size()).Write(vchSig.data(), vchSig.size()).Finalize(entry.begin());
      50       29598 :     }
      51             : 
      52             :     bool
      53       29602 :     Get(const uint256& entry, const bool erase)
      54             :     {
      55       29602 :         std::shared_lock<std::shared_mutex> lock(cs_sigcache);
      56       29602 :         return setValid.contains(entry, erase);
      57       29602 :     }
      58             : 
      59          15 :     void Set(const uint256& entry)
      60             :     {
      61          15 :         std::unique_lock<std::shared_mutex> lock(cs_sigcache);
      62          15 :         setValid.insert(entry);
      63          15 :     }
      64         627 :     uint32_t setup_bytes(size_t n)
      65             :     {
      66         627 :         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         146 : static CSignatureCache signatureCache;
      77             : } // namespace
      78             : 
      79             : // To be called once in AppInitMain/BasicTestingSetup to initialize the
      80             : // signatureCache.
      81         627 : void InitSignatureCache()
      82             : {
      83             :     // nMaxCacheSize is unsigned. If -maxsigcachesize is set to zero,
      84             :     // setup_bytes creates the minimum possible cache (2 elements).
      85         627 :     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         627 :     size_t nElems = signatureCache.setup_bytes(nMaxCacheSize);
      87         627 :     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         627 : }
      90             : 
      91       29602 : bool CachingTransactionSignatureChecker::VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const
      92             : {
      93       29602 :     uint256 entry;
      94       29602 :     signatureCache.ComputeEntry(entry, sighash, vchSig, pubkey);
      95       29602 :     if (signatureCache.Get(entry, !store))
      96       29431 :         return true;
      97         171 :     if (!TransactionSignatureChecker::VerifySignature(vchSig, pubkey, sighash))
      98           2 :         return false;
      99         169 :     if (store)
     100          15 :         signatureCache.Set(entry);
     101         169 :     return true;
     102       29602 : }

Generated by: LCOV version 1.16