LCOV - code coverage report
Current view: top level - src/script - sigcache.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 21 26 80.8 %
Date: 2015-10-12 22:39:14 Functions: 7 7 100.0 %
Legend: Lines: hit not hit

          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 : }

Generated by: LCOV version 1.11