Changeset View
Changeset View
Standalone View
Standalone View
src/script/sigcache.cpp
Show All 17 Lines | |||||
/** | /** | ||||
* 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 &= | |||||
~CachingTransactionSignatureChecker::invariantFlagsVerifySignature; | |||||
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)) | |||||
deadalnix: It should be possible to push the flags directly. This is also this piece of code that seems to… | |||||
markblundebergAuthorUnsubmitted Done Inline ActionsIf I just put &flags, it complains with "no known conversion for argument 1 from ‘uint32_t* {aka unsigned int*}’ to ‘const uint8_t* {aka const unsigned char*}". Perhaps Write() should take void * instead of uint8_t * but I'm not going to make that change in this diff. :-) markblundeberg: If I just put &flags, it complains with "no known conversion for argument 1 from ‘uint32_t*… | |||||
.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; | ||||
} | } |
It should be possible to push the flags directly. This is also this piece of code that seems to be in charge of picking and choosing the relevant flags to compute the key from.