diff --git a/src/script/sigcache.cpp b/src/script/sigcache.cpp index 4c18e9832e..2dda6984c6 100644 --- a/src/script/sigcache.cpp +++ b/src/script/sigcache.cpp @@ -1,112 +1,119 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "sigcache.h" +#include "cuckoocache.h" #include "memusage.h" #include "pubkey.h" #include "random.h" #include "uint256.h" #include "util.h" -#include "cuckoocache.h" #include namespace { /** * We're hashing a nonce into the entries themselves, so we don't need extra * blinding in the set hash computation. * * This may exhibit platform endian dependent behavior but because these are * nonced hashes (random) and this state is only ever used locally it is safe. * All that matters is local consistency. */ class SignatureCacheHasher { public: template uint32_t operator()(const uint256 &key) const { static_assert(hash_select < 8, "SignatureCacheHasher only has 8 hashes available."); uint32_t u; std::memcpy(&u, key.begin() + 4 * hash_select, 4); return u; } }; /** * Valid signature cache, to avoid doing expensive ECDSA signature checking * twice for every transaction (once when accepted into memory pool, and * again when accepted into the block chain) */ class CSignatureCache { private: //! Entries are SHA256(nonce || signature hash || public key || signature): uint256 nonce; typedef CuckooCache::cache map_type; map_type setValid; boost::shared_mutex cs_sigcache; public: CSignatureCache() { GetRandBytes(nonce.begin(), 32); } void ComputeEntry(uint256 &entry, const uint256 &hash, const std::vector &vchSig, const CPubKey &pubkey) { CSHA256() .Write(nonce.begin(), 32) .Write(hash.begin(), 32) .Write(&pubkey[0], pubkey.size()) .Write(&vchSig[0], vchSig.size()) .Finalize(entry.begin()); } bool Get(const uint256 &entry, const bool erase) { boost::shared_lock lock(cs_sigcache); return setValid.contains(entry, erase); } void Set(uint256 &entry) { boost::unique_lock lock(cs_sigcache); setValid.insert(entry); } uint32_t setup_bytes(size_t n) { return setValid.setup_bytes(n); } }; -/* In previous versions of this code, signatureCache was a local static variable - * in CachingTransactionSignatureChecker::VerifySignature. We initialize +/** + * In previous versions of this code, signatureCache was a local static variable + * in CachingTransactionSignatureChecker::VerifySignature. We initialize * signatureCache outside of VerifySignature to avoid the atomic operation per * call overhead associated with local static variables even though * signatureCache could be made local to VerifySignature. -*/ + */ static CSignatureCache signatureCache; } // To be called once in AppInit2/TestingSetup to initialize the signatureCache void InitSignatureCache() { // nMaxCacheSize is unsigned. If -maxsigcachesize is set to zero, // setup_bytes creates the minimum possible cache (2 elements). size_t nMaxCacheSize = - std::min(std::max((int64_t)0, GetArg("-maxsigcachesize", + std::min(std::max(int64_t(0), GetArg("-maxsigcachesize", DEFAULT_MAX_SIG_CACHE_SIZE)), MAX_MAX_SIG_CACHE_SIZE) * - ((size_t)1 << 20); + (size_t(1) << 20); size_t nElems = signatureCache.setup_bytes(nMaxCacheSize); LogPrintf("Using %zu MiB out of %zu requested for signature cache, able to " "store %zu elements\n", (nElems * sizeof(uint256)) >> 20, nMaxCacheSize >> 20, nElems); } bool CachingTransactionSignatureChecker::VerifySignature( const std::vector &vchSig, const CPubKey &pubkey, const uint256 &sighash) const { uint256 entry; signatureCache.ComputeEntry(entry, sighash, vchSig, pubkey); - if (signatureCache.Get(entry, !store)) return true; - if (!TransactionSignatureChecker::VerifySignature(vchSig, pubkey, sighash)) + if (signatureCache.Get(entry, !store)) { + return true; + } + if (!TransactionSignatureChecker::VerifySignature(vchSig, pubkey, + sighash)) { return false; - if (store) signatureCache.Set(entry); + } + if (store) { + signatureCache.Set(entry); + } return true; }