Browse Source
0.10e790c37
Replace SCRIPT_VERIFY_NOCACHE by flag directly to checker (Pieter Wuille)5c1e798
Make signature cache optional (Pieter Wuille)c7829ea
Abstract out SignatureChecker (Pieter Wuille)
Wladimir J. van der Laan
10 years ago
15 changed files with 215 additions and 135 deletions
@ -0,0 +1,88 @@
@@ -0,0 +1,88 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2013 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "sigcache.h" |
||||
|
||||
#include "key.h" |
||||
#include "random.h" |
||||
#include "uint256.h" |
||||
#include "util.h" |
||||
|
||||
#include <boost/thread.hpp> |
||||
#include <boost/tuple/tuple_comparison.hpp> |
||||
|
||||
namespace { |
||||
|
||||
// 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: |
||||
// 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); |
||||
} |
||||
}; |
||||
|
||||
} |
||||
|
||||
bool CachingSignatureChecker::VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const |
||||
{ |
||||
static CSignatureCache signatureCache; |
||||
|
||||
if (signatureCache.Get(sighash, vchSig, pubkey)) |
||||
return true; |
||||
|
||||
if (!SignatureChecker::VerifySignature(vchSig, pubkey, sighash)) |
||||
return false; |
||||
|
||||
if (store) |
||||
signatureCache.Set(sighash, vchSig, pubkey); |
||||
return true; |
||||
} |
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2013 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef H_BITCOIN_SCRIPT_SIGCACHE |
||||
#define H_BITCOIN_SCRIPT_SIGCACHE |
||||
|
||||
#include "script/interpreter.h" |
||||
|
||||
#include <vector> |
||||
|
||||
class CPubKey; |
||||
|
||||
class CachingSignatureChecker : public SignatureChecker |
||||
{ |
||||
private: |
||||
bool store; |
||||
|
||||
public: |
||||
CachingSignatureChecker(const CTransaction& txToIn, unsigned int nInIn, bool storeIn=true) : SignatureChecker(txToIn, nInIn), store(storeIn) {} |
||||
|
||||
bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const; |
||||
}; |
||||
|
||||
#endif |
Loading…
Reference in new issue