From 5c1e798a8e9df15f8fbd120e57fc67e585f13843 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 10 Sep 2014 16:16:09 +0200 Subject: Make signature cache optional --- src/script/interpreter.cpp | 74 ++++------------------------------------------ 1 file changed, 6 insertions(+), 68 deletions(-) (limited to 'src/script/interpreter.cpp') diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 048d298f0b..f0b4268390 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -9,14 +9,10 @@ #include "crypto/ripemd160.h" #include "crypto/sha1.h" #include "crypto/sha2.h" -#include "random.h" #include "script/script.h" #include "uint256.h" #include "util.h" -#include -#include - using namespace std; typedef vector valtype; @@ -132,7 +128,7 @@ bool IsCanonicalSignature(const valtype &vchSig, unsigned int flags) { return true; } -bool EvalScript(vector >& stack, const CScript& script, unsigned int flags, const SignatureChecker& checker) +bool EvalScript(vector >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker) { CScript::const_iterator pc = script.begin(); CScript::const_iterator pend = script.end(); @@ -921,65 +917,13 @@ uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsig return ss.GetHash(); } -// 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 +bool SignatureChecker::VerifySignature(const std::vector& vchSig, const CPubKey& pubkey, const uint256& sighash, int flags) const { -private: - // sigdata_type is (signature hash, signature, public key): - typedef boost::tuple, CPubKey> sigdata_type; - std::set< sigdata_type> setValid; - boost::shared_mutex cs_sigcache; - -public: - bool - Get(const uint256 &hash, const std::vector& vchSig, const CPubKey& pubKey) - { - boost::shared_lock lock(cs_sigcache); - - sigdata_type k(hash, vchSig, pubKey); - std::set::iterator mi = setValid.find(k); - if (mi != setValid.end()) - return true; - return false; - } - - void Set(const uint256 &hash, const std::vector& vchSig, const CPubKey& pubKey) - { - // DoS prevention: limit cache size to less than 10MB - // (~200 bytes per cache entry times 50,000 entries) - // Since there are a maximum of 20,000 signature operations per block - // 50,000 is a reasonable default. - int64_t nMaxCacheSize = GetArg("-maxsigcachesize", 50000); - if (nMaxCacheSize <= 0) return; - - boost::unique_lock lock(cs_sigcache); - - while (static_cast(setValid.size()) > nMaxCacheSize) - { - // Evict a random entry. Random because that helps - // foil would-be DoS attackers who might try to pre-generate - // and re-use a set of valid signatures just-slightly-greater - // than our cache size. - uint256 randomHash = GetRandHash(); - std::vector unused; - std::set::iterator it = - setValid.lower_bound(sigdata_type(randomHash, unused, unused)); - if (it == setValid.end()) - it = setValid.begin(); - setValid.erase(*it); - } - - sigdata_type k(hash, vchSig, pubKey); - setValid.insert(k); - } -}; + return pubkey.Verify(sighash, vchSig); +} bool SignatureChecker::CheckSig(const vector& vchSigIn, const vector& vchPubKey, const CScript& scriptCode, int flags) const { - static CSignatureCache signatureCache; - CPubKey pubkey(vchPubKey); if (!pubkey.IsValid()) return false; @@ -993,19 +937,13 @@ bool SignatureChecker::CheckSig(const vector& vchSigIn, const vec uint256 sighash = SignatureHash(scriptCode, txTo, nIn, nHashType); - if (signatureCache.Get(sighash, vchSig, pubkey)) - return true; - - if (!pubkey.Verify(sighash, vchSig)) + if (!VerifySignature(vchSig, pubkey, sighash, flags)) return false; - if (!(flags & SCRIPT_VERIFY_NOCACHE)) - signatureCache.Set(sighash, vchSig, pubkey); - return true; } -bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const SignatureChecker& checker) +bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker) { vector > stack, stackCopy; if (!EvalScript(stack, scriptSig, flags, checker)) -- cgit v1.2.3