Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto
2 : // Copyright (c) 2009-2014 The Bitcoin Core developers
3 : // Distributed under the MIT software license, see the accompanying
4 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 :
6 : #include "sigcache.h"
7 :
8 : #include "pubkey.h"
9 : #include "random.h"
10 : #include "uint256.h"
11 : #include "util.h"
12 :
13 : #include <boost/thread.hpp>
14 : #include <boost/tuple/tuple_comparison.hpp>
15 :
16 : namespace {
17 :
18 : /**
19 : * Valid signature cache, to avoid doing expensive ECDSA signature checking
20 : * twice for every transaction (once when accepted into memory pool, and
21 : * again when accepted into the block chain)
22 : */
23 228 : class CSignatureCache
24 : {
25 : private:
26 : //! sigdata_type is (signature hash, signature, public key):
27 : typedef boost::tuple<uint256, std::vector<unsigned char>, CPubKey> sigdata_type;
28 : std::set< sigdata_type> setValid;
29 : boost::shared_mutex cs_sigcache;
30 :
31 : public:
32 : bool
33 3777 : Get(const uint256 &hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubKey)
34 : {
35 3777 : boost::shared_lock<boost::shared_mutex> lock(cs_sigcache);
36 :
37 3778 : sigdata_type k(hash, vchSig, pubKey);
38 7552 : std::set<sigdata_type>::iterator mi = setValid.find(k);
39 7548 : if (mi != setValid.end())
40 : return true;
41 1138 : return false;
42 : }
43 :
44 951 : void Set(const uint256 &hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubKey)
45 : {
46 : // DoS prevention: limit cache size to less than 10MB
47 : // (~200 bytes per cache entry times 50,000 entries)
48 : // Since there are a maximum of 20,000 signature operations per block
49 : // 50,000 is a reasonable default.
50 2853 : int64_t nMaxCacheSize = GetArg("-maxsigcachesize", 50000);
51 951 : if (nMaxCacheSize <= 0) return;
52 :
53 951 : boost::unique_lock<boost::shared_mutex> lock(cs_sigcache);
54 :
55 1902 : while (static_cast<int64_t>(setValid.size()) > nMaxCacheSize)
56 : {
57 : // Evict a random entry. Random because that helps
58 : // foil would-be DoS attackers who might try to pre-generate
59 : // and re-use a set of valid signatures just-slightly-greater
60 : // than our cache size.
61 0 : uint256 randomHash = GetRandHash();
62 : std::vector<unsigned char> unused;
63 : std::set<sigdata_type>::iterator it =
64 0 : setValid.lower_bound(sigdata_type(randomHash, unused, unused));
65 0 : if (it == setValid.end())
66 0 : it = setValid.begin();
67 0 : setValid.erase(*it);
68 : }
69 :
70 951 : sigdata_type k(hash, vchSig, pubKey);
71 951 : setValid.insert(k);
72 : }
73 : };
74 :
75 : }
76 :
77 3778 : bool CachingTransactionSignatureChecker::VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const
78 : {
79 3778 : static CSignatureCache signatureCache;
80 :
81 3778 : if (signatureCache.Get(sighash, vchSig, pubkey))
82 : return true;
83 :
84 1139 : if (!TransactionSignatureChecker::VerifySignature(vchSig, pubkey, sighash))
85 : return false;
86 :
87 1123 : if (store)
88 951 : signatureCache.Set(sighash, vchSig, pubkey);
89 : return true;
90 288 : }
|