aboutsummaryrefslogtreecommitdiff
path: root/src/script/interpreter.cpp
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2014-09-10 16:16:09 +0200
committerPieter Wuille <pieter.wuille@gmail.com>2014-10-02 20:26:17 +0200
commit5c1e798a8e9df15f8fbd120e57fc67e585f13843 (patch)
tree2b9cd1acc9565a7946683b50b237c332484de5e4 /src/script/interpreter.cpp
parentc7829ea797c840dda7888ee860a50b7a3308069d (diff)
downloadbitcoin-5c1e798a8e9df15f8fbd120e57fc67e585f13843.tar.xz
Make signature cache optional
Diffstat (limited to 'src/script/interpreter.cpp')
-rw-r--r--src/script/interpreter.cpp74
1 files changed, 6 insertions, 68 deletions
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 <boost/thread.hpp>
-#include <boost/tuple/tuple_comparison.hpp>
-
using namespace std;
typedef vector<unsigned char> valtype;
@@ -132,7 +128,7 @@ bool IsCanonicalSignature(const valtype &vchSig, unsigned int flags) {
return true;
}
-bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const SignatureChecker& checker)
+bool EvalScript(vector<vector<unsigned char> >& 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<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash, int flags) const
{
-private:
- // sigdata_type is (signature hash, signature, public key):
- typedef boost::tuple<uint256, std::vector<unsigned char>, CPubKey> sigdata_type;
- std::set< sigdata_type> setValid;
- boost::shared_mutex cs_sigcache;
-
-public:
- bool
- Get(const uint256 &hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubKey)
- {
- boost::shared_lock<boost::shared_mutex> lock(cs_sigcache);
-
- sigdata_type k(hash, vchSig, pubKey);
- std::set<sigdata_type>::iterator mi = setValid.find(k);
- if (mi != setValid.end())
- return true;
- return false;
- }
-
- void Set(const uint256 &hash, const std::vector<unsigned char>& 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<boost::shared_mutex> lock(cs_sigcache);
-
- while (static_cast<int64_t>(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<unsigned char> unused;
- std::set<sigdata_type>::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<unsigned char>& vchSigIn, const vector<unsigned char>& 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<unsigned char>& 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<vector<unsigned char> > stack, stackCopy;
if (!EvalScript(stack, scriptSig, flags, checker))