Bitcoin ABC  0.22.12
P2P Digital Currency
scriptcache.cpp
Go to the documentation of this file.
1 // Copyright (c) 2017-2020 The Bitcoin developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include <script/scriptcache.h>
6 
7 #include <crypto/sha256.h>
8 #include <cuckoocache.h>
10 #include <random.h>
11 #include <script/sigcache.h>
12 #include <sync.h>
13 #include <util/system.h>
14 #include <validation.h>
15 
27 
30 
31  ScriptCacheElement() = default;
32 
33  ScriptCacheElement(const KeyType &keyIn, int nSigChecksIn)
34  : key(keyIn), nSigChecks(nSigChecksIn) {}
35 
36  const KeyType &getKey() const { return key; }
37 };
38 
39 static_assert(sizeof(ScriptCacheElement) == 32,
40  "ScriptCacheElement should be 32 bytes");
41 
43 public:
44  template <uint8_t hash_select>
45  uint32_t operator()(const ScriptCacheKey &k) const {
46  static_assert(hash_select < 8, "only has 8 hashes available.");
47 
48  const auto &d = k.data;
49 
50  static_assert(sizeof(d) == 28,
51  "modify the following if key size changes");
52 
53  uint32_t u;
54  static_assert(sizeof(u) == 4 && sizeof(d[0]) == 1, "basic assumptions");
55  if (hash_select < 7) {
56  std::memcpy(&u, d.data() + 4 * hash_select, 4);
57  } else {
58  // We are required to produce 8 subhashes, and all bytes have
59  // been used once. We re-use the bytes but mix together different
60  // entries (and flip the order) to get a new, distinct value.
61  uint8_t arr[4];
62  arr[0] = d[3] ^ d[7] ^ d[11] ^ d[15];
63  arr[1] = d[6] ^ d[10] ^ d[14] ^ d[18];
64  arr[2] = d[9] ^ d[13] ^ d[17] ^ d[21];
65  arr[3] = d[12] ^ d[16] ^ d[20] ^ d[24];
66  std::memcpy(&u, arr, 4);
67  }
68  return u;
69  }
70 };
71 
75 
77  // nMaxCacheSize is unsigned. If -maxscriptcachesize is set to zero,
78  // setup_bytes creates the minimum possible cache (2 elements).
79  size_t nMaxCacheSize =
80  std::min(
81  std::max(int64_t(0), gArgs.GetArg("-maxscriptcachesize",
84  (size_t(1) << 20);
85  size_t nElems = scriptExecutionCache.setup_bytes(nMaxCacheSize);
86  LogPrintf("Using %zu MiB out of %zu requested for script execution cache, "
87  "able to store %zu elements\n",
88  (nElems * sizeof(uint256)) >> 20, nMaxCacheSize >> 20, nElems);
89 }
90 
92  std::array<uint8_t, 32> hash;
93  // We only use the first 19 bytes of nonce to avoid a second SHA round -
94  // giving us 19 + 32 + 4 = 55 bytes (+ 8 + 1 = 64)
95  static_assert(55 - sizeof(flags) - 32 >= 128 / 8,
96  "Want at least 128 bits of nonce for script execution cache");
97  CSHA256()
98  .Write(scriptExecutionCacheNonce.begin(), 55 - sizeof(flags) - 32)
99  .Write(tx.GetHash().begin(), 32)
100  .Write((uint8_t *)&flags, sizeof(flags))
101  .Finalize(hash.begin());
102 
103  assert(data.size() < hash.size());
104  std::copy(hash.begin(), hash.begin() + data.size(), data.begin());
105 }
106 
107 bool IsKeyInScriptCache(ScriptCacheKey key, bool erase, int &nSigChecksOut) {
108  // TODO: Remove this requirement by making CuckooCache not require external
109  // locks
111 
112  ScriptCacheElement elem(key, 0);
113  bool ret = scriptExecutionCache.get(elem, erase);
114  nSigChecksOut = elem.nSigChecks;
115  return ret;
116 }
117 
119  // TODO: Remove this requirement by making CuckooCache not require external
120  // locks
122 
123  ScriptCacheElement elem(key, nSigChecks);
124  scriptExecutionCache.insert(elem);
125 }
static const int64_t MAX_MAX_SCRIPT_CACHE_SIZE
Definition: scriptcache.h:42
static uint256 scriptExecutionCacheNonce(GetRandHash())
ScriptCacheElement(const KeyType &keyIn, int nSigChecksIn)
Definition: scriptcache.cpp:33
void InitScriptExecutionCache()
Initializes the script-execution cache.
Definition: scriptcache.cpp:76
const KeyType & getKey() const
Definition: scriptcache.cpp:36
uint256 GetRandHash() noexcept
Definition: random.cpp:654
static CuckooCache::cache< ScriptCacheElement, ScriptCacheHasher > scriptExecutionCache
Definition: scriptcache.cpp:73
std::array< uint8_t, 28 > data
Definition: scriptcache.h:23
cache implements a cache with properties similar to a cuckoo-set.
Definition: cuckoocache.h:162
static void LogPrintf(const char *fmt, const Args &... args)
Definition: logging.h:171
const TxHash GetHash() const
Definition: transaction.h:262
In future if many more values are added, it should be considered to expand the element size to 64 byt...
Definition: scriptcache.cpp:25
The script cache is a map using a key/value element, that caches the success of executing a specific ...
Definition: scriptcache.h:22
bool IsKeyInScriptCache(ScriptCacheKey key, bool erase, int &nSigChecksOut)
Check if a given key is in the cache, and if so, return its values.
ScriptCacheKey()=default
void Finalize(uint8_t hash[OUTPUT_SIZE])
Definition: sha256.cpp:844
RecursiveMutex cs_main
Global state.
Definition: validation.cpp:90
uint8_t * begin()
Definition: uint256.h:76
static const unsigned int DEFAULT_MAX_SCRIPT_CACHE_SIZE
Definition: scriptcache.h:40
int flags
Definition: bitcoin-tx.cpp:529
256-bit opaque blob.
Definition: uint256.h:120
void AddKeyInScriptCache(ScriptCacheKey key, int nSigChecks)
Add an entry in the cache.
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: system.cpp:479
CSHA256 & Write(const uint8_t *data, size_t len)
Definition: sha256.cpp:819
ArgsManager gArgs
Definition: system.cpp:76
The basic transaction that is broadcasted on the network and contained in blocks. ...
Definition: transaction.h:211
ScriptCacheElement()=default
AssertLockHeld(g_cs_orphans)
A hasher class for SHA-256.
Definition: sha256.h:13
uint32_t operator()(const ScriptCacheKey &k) const
Definition: scriptcache.cpp:45