Bitcoin ABC  0.29.2
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 
76 bool InitScriptExecutionCache(size_t max_size_bytes) {
77  // Setup the salted hasher
78  uint256 nonce = GetRandHash();
79  // We want the nonce to be 64 bytes long to force the hasher to process
80  // this chunk, which makes later hash computations more efficient. We
81  // just write our 32-byte entropy twice to fill the 64 bytes.
84 
85  auto setup_results = g_scriptExecutionCache.setup_bytes(max_size_bytes);
86  if (!setup_results) {
87  return false;
88  }
89 
90  const auto [num_elems, approx_size_bytes] = *setup_results;
91  LogPrintf("Using %zu MiB out of %zu MiB requested for script execution "
92  "cache, able to store %zu elements\n",
93  approx_size_bytes >> 20, max_size_bytes >> 20, num_elems);
94  return true;
95 }
96 
98  std::array<uint8_t, 32> hash;
100  hasher.Write(tx.GetHash().begin(), 32)
101  .Write((uint8_t *)&flags, sizeof(flags))
102  .Finalize(hash.begin());
103 
104  assert(data.size() < hash.size());
105  std::copy(hash.begin(), hash.begin() + data.size(), data.begin());
106 }
107 
108 bool IsKeyInScriptCache(ScriptCacheKey key, bool erase, int &nSigChecksOut) {
109  // TODO: Remove this requirement by making CuckooCache not require external
110  // locks
112 
113  ScriptCacheElement elem(key, 0);
114  bool ret = g_scriptExecutionCache.get(elem, erase);
115  nSigChecksOut = elem.nSigChecks;
116  return ret;
117 }
118 
120  // TODO: Remove this requirement by making CuckooCache not require external
121  // locks
123 
124  ScriptCacheElement elem(key, nSigChecks);
125  g_scriptExecutionCache.insert(elem);
126 }
int flags
Definition: bitcoin-tx.cpp:533
A hasher class for SHA-256.
Definition: sha256.h:13
CSHA256 & Write(const uint8_t *data, size_t len)
Definition: sha256.cpp:819
void Finalize(uint8_t hash[OUTPUT_SIZE])
Definition: sha256.cpp:844
The basic transaction that is broadcasted on the network and contained in blocks.
Definition: transaction.h:192
const TxHash GetHash() const
Definition: transaction.h:241
cache implements a cache with properties similar to a cuckoo-set.
Definition: cuckoocache.h:167
uint32_t operator()(const ScriptCacheKey &k) const
Definition: scriptcache.cpp:45
The script cache is a map using a key/value element, that caches the success of executing a specific ...
Definition: scriptcache.h:25
std::array< uint8_t, 28 > data
Definition: scriptcache.h:26
ScriptCacheKey()=default
uint8_t * begin()
Definition: uint256.h:85
256-bit opaque blob.
Definition: uint256.h:129
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
Definition: cs_main.cpp:7
#define LogPrintf(...)
Definition: logging.h:206
unsigned int nSigChecks
uint256 GetRandHash() noexcept
Definition: random.cpp:659
static CSHA256 g_scriptExecutionCacheHasher
Definition: scriptcache.cpp:74
static CuckooCache::cache< ScriptCacheElement, ScriptCacheHasher > g_scriptExecutionCache
Definition: scriptcache.cpp:73
bool InitScriptExecutionCache(size_t max_size_bytes)
Initializes the script-execution cache.
Definition: scriptcache.cpp:76
void AddKeyInScriptCache(ScriptCacheKey key, int nSigChecks)
Add an entry in the cache.
bool IsKeyInScriptCache(ScriptCacheKey key, bool erase, int &nSigChecksOut)
Check if a given key is in the cache, and if so, return its values.
In future if many more values are added, it should be considered to expand the element size to 64 byt...
Definition: scriptcache.cpp:25
const KeyType & getKey() const
Definition: scriptcache.cpp:36
ScriptCacheElement(const KeyType &keyIn, int nSigChecksIn)
Definition: scriptcache.cpp:33
ScriptCacheElement()=default
AssertLockHeld(pool.cs)
assert(!tx.IsCoinBase())