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 : }