Changeset View
Changeset View
Standalone View
Standalone View
src/script/sigcache.cpp
Show All 11 Lines | |||||
#include "uint256.h" | #include "uint256.h" | ||||
#include "util.h" | #include "util.h" | ||||
#include <boost/thread/shared_mutex.hpp> | #include <boost/thread/shared_mutex.hpp> | ||||
namespace { | namespace { | ||||
/** | /** | ||||
* Declare which flags absolutely do not affect VerifySignature() result. | |||||
* The caching code in sighash.cpp uses this to reduce unnecessary cache | |||||
* misses (such as when policy and consensus flags differ on unrelated | |||||
* aspects). | |||||
*/ | |||||
static const uint32_t INVARIANT_FLAGS = | |||||
SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC | SCRIPT_VERIFY_DERSIG | | |||||
SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_NULLDUMMY | SCRIPT_VERIFY_SIGPUSHONLY | | |||||
SCRIPT_VERIFY_MINIMALDATA | SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS | | |||||
SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY | | |||||
SCRIPT_VERIFY_CHECKSEQUENCEVERIFY | SCRIPT_VERIFY_MINIMALIF | | |||||
SCRIPT_VERIFY_NULLFAIL | SCRIPT_VERIFY_COMPRESSED_PUBKEYTYPE | | |||||
SCRIPT_ENABLE_SIGHASH_FORKID | SCRIPT_ENABLE_REPLAY_PROTECTION | | |||||
SCRIPT_ENABLE_CHECKDATASIG; | |||||
/** | |||||
* Valid signature cache, to avoid doing expensive ECDSA signature checking | * Valid signature cache, to avoid doing expensive ECDSA signature checking | ||||
* twice for every transaction (once when accepted into memory pool, and | * twice for every transaction (once when accepted into memory pool, and | ||||
* again when accepted into the block chain) | * again when accepted into the block chain) | ||||
*/ | */ | ||||
class CSignatureCache { | class CSignatureCache { | ||||
private: | private: | ||||
//! Entries are SHA256(nonce || signature hash || public key || signature): | //! Entries are SHA256(nonce || signature || public key || signature hash || | ||||
//! flags): | |||||
uint256 nonce; | uint256 nonce; | ||||
typedef CuckooCache::cache<uint256, SignatureCacheHasher> map_type; | typedef CuckooCache::cache<uint256, SignatureCacheHasher> map_type; | ||||
map_type setValid; | map_type setValid; | ||||
boost::shared_mutex cs_sigcache; | boost::shared_mutex cs_sigcache; | ||||
public: | public: | ||||
CSignatureCache() { GetRandBytes(nonce.begin(), 32); } | CSignatureCache() { GetRandBytes(nonce.begin(), 32); } | ||||
void ComputeEntry(uint256 &entry, const uint256 &hash, | void ComputeEntry(uint256 &entry, const std::vector<uint8_t> &vchSig, | ||||
const std::vector<uint8_t> &vchSig, | const CPubKey &pubkey, const uint256 &hash, | ||||
const CPubKey &pubkey) { | uint32_t flags) { | ||||
flags &= ~INVARIANT_FLAGS; | |||||
CSHA256() | CSHA256() | ||||
.Write(nonce.begin(), 32) | .Write(nonce.begin(), 32) | ||||
.Write(hash.begin(), 32) | |||||
.Write(&pubkey[0], pubkey.size()) | |||||
.Write(&vchSig[0], vchSig.size()) | .Write(&vchSig[0], vchSig.size()) | ||||
.Write(&pubkey[0], pubkey.size()) | |||||
.Write(hash.begin(), 32) | |||||
.Write(reinterpret_cast<uint8_t *>(&flags), sizeof(flags)) | |||||
.Finalize(entry.begin()); | .Finalize(entry.begin()); | ||||
} | } | ||||
bool Get(const uint256 &entry, const bool erase) { | bool Get(const uint256 &entry, const bool erase) { | ||||
boost::shared_lock<boost::shared_mutex> lock(cs_sigcache); | boost::shared_lock<boost::shared_mutex> lock(cs_sigcache); | ||||
return setValid.contains(entry, erase); | return setValid.contains(entry, erase); | ||||
} | } | ||||
Show All 26 Lines | void InitSignatureCache() { | ||||
size_t nElems = signatureCache.setup_bytes(nMaxCacheSize); | size_t nElems = signatureCache.setup_bytes(nMaxCacheSize); | ||||
LogPrintf("Using %zu MiB out of %zu requested for signature cache, able to " | LogPrintf("Using %zu MiB out of %zu requested for signature cache, able to " | ||||
"store %zu elements\n", | "store %zu elements\n", | ||||
(nElems * sizeof(uint256)) >> 20, nMaxCacheSize >> 20, nElems); | (nElems * sizeof(uint256)) >> 20, nMaxCacheSize >> 20, nElems); | ||||
} | } | ||||
bool CachingTransactionSignatureChecker::VerifySignature( | bool CachingTransactionSignatureChecker::VerifySignature( | ||||
const std::vector<uint8_t> &vchSig, const CPubKey &pubkey, | const std::vector<uint8_t> &vchSig, const CPubKey &pubkey, | ||||
const uint256 &sighash) const { | const uint256 &sighash, uint32_t flags) const { | ||||
uint256 entry; | uint256 entry; | ||||
signatureCache.ComputeEntry(entry, sighash, vchSig, pubkey); | signatureCache.ComputeEntry(entry, vchSig, pubkey, sighash, flags); | ||||
if (signatureCache.Get(entry, !store)) { | if (signatureCache.Get(entry, !store)) { | ||||
return true; | return true; | ||||
} | } | ||||
if (!TransactionSignatureChecker::VerifySignature(vchSig, pubkey, | if (!TransactionSignatureChecker::VerifySignature(vchSig, pubkey, sighash, | ||||
sighash)) { | flags)) { | ||||
return false; | return false; | ||||
} | } | ||||
if (store) { | if (store) { | ||||
signatureCache.Set(entry); | signatureCache.Set(entry); | ||||
} | } | ||||
return true; | return true; | ||||
} | } |