Changeset View
Changeset View
Standalone View
Standalone View
src/script/scriptcache.h
// Copyright (c) 2017 - The Bitcoin Developers | // Copyright (c) 2017 - The Bitcoin Developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#ifndef BITCOIN_SCRIPT_SCRIPTCACHE_H | #ifndef BITCOIN_SCRIPT_SCRIPTCACHE_H | ||||
#define BITCOIN_SCRIPT_SCRIPTCACHE_H | #define BITCOIN_SCRIPT_SCRIPTCACHE_H | ||||
#include <uint256.h> | #include <script/script_metrics.h> | ||||
#include <array> | |||||
#include <cstdint> | #include <cstdint> | ||||
class CTransaction; | class CTransaction; | ||||
/** | |||||
* The script cache is a map using a key/value element, that caches the | |||||
* success of executing a specific transaction's input scripts under a | |||||
* specific set of flags, along with any associated information learned | |||||
* during execution. | |||||
* | |||||
* The key is slightly shorter than a power-of-two size to make room for | |||||
* the value. | |||||
*/ | |||||
class ScriptCacheKey { | |||||
std::array<uint8_t, 30> data; | |||||
public: | |||||
ScriptCacheKey() = default; | |||||
ScriptCacheKey(const ScriptCacheKey &rhs) = default; | |||||
ScriptCacheKey(const CTransaction &tx, uint32_t flags); | |||||
bool operator==(const ScriptCacheKey &rhs) const { | |||||
return rhs.data == data; | |||||
} | |||||
friend class ScriptCacheHasher; | |||||
}; | |||||
// DoS prevention: limit cache size to 32MB (over 1000000 entries on 64-bit | // DoS prevention: limit cache size to 32MB (over 1000000 entries on 64-bit | ||||
// systems). Due to how we count cache size, actual memory usage is slightly | // systems). Due to how we count cache size, actual memory usage is slightly | ||||
// more (~32.25 MB) | // more (~32.25 MB) | ||||
static const unsigned int DEFAULT_MAX_SCRIPT_CACHE_SIZE = 32; | static const unsigned int DEFAULT_MAX_SCRIPT_CACHE_SIZE = 32; | ||||
// Maximum sig cache size allowed | // Maximum sig cache size allowed | ||||
static const int64_t MAX_MAX_SCRIPT_CACHE_SIZE = 16384; | static const int64_t MAX_MAX_SCRIPT_CACHE_SIZE = 16384; | ||||
/** Initializes the script-execution cache */ | /** Initializes the script-execution cache */ | ||||
void InitScriptExecutionCache(); | void InitScriptExecutionCache(); | ||||
/** Compute the cache key for a given transaction and flags. */ | /** | ||||
uint256 GetScriptCacheKey(const CTransaction &tx, uint32_t flags); | * Check if a given key is in the cache, and if so, return its values. | ||||
* (if not found, metricsOut may or may not be set to an arbitrary value) | |||||
/** Check if a given key is in the cache. */ | */ | ||||
bool IsKeyInScriptCache(uint256 key, bool erase); | bool IsKeyInScriptCache(ScriptCacheKey key, bool erase, | ||||
ScriptExecutionMetrics &metricsOut); | |||||
/** Add an entry in the cache. */ | |||||
void AddKeyInScriptCache(uint256 key); | constexpr int SCRIPT_CACHE_MAX_SIGCHECKS = UINT16_MAX; | ||||
deadalnix: Is this intended to be part of the public API? | |||||
markblundebergAuthorUnsubmitted Done Inline ActionsYes. See where it is used in this diff. markblundeberg: Yes. See where it is used in this diff. | |||||
deadalnixUnsubmitted Not Done Inline ActionsIt seems like this is exclusively used in the test, and if value mismatch in the test, the test will break anyways, so I'm not sure. DO youe xpect your user to be aware of this value and check against it? If so, then why SCRIPT_CACHE_MAX_SIGCHECKS ? Who's responsibility is it to check? deadalnix: It seems like this is exclusively used in the test, and if value mismatch in the test, the test… | |||||
/** | |||||
* Try to store a given key with values in the cache. Due to limited storage | |||||
* bits, the cache can only store values in certain ranges: | |||||
* | |||||
* 0 <= metricsIn.nSigChecks <= SCRIPT_CACHE_MAX_SIGCHECKS | |||||
* | |||||
* If any value is out of range, this will return false rather than storing this | |||||
* item into the cache. Otherwise it returns true. | |||||
*/ | |||||
bool TryAddKeyInScriptCache(ScriptCacheKey key, ScriptExecutionMetrics metrics); | |||||
/** | |||||
* Add an entry in the cache. | |||||
*/ | |||||
static inline void AddKeyInScriptCache(ScriptCacheKey key, | |||||
ScriptExecutionMetrics metrics) { | |||||
if (!TryAddKeyInScriptCache(key, metrics)) { | |||||
throw std::range_error("metrics out of range"); | |||||
} | |||||
} | |||||
#endif // BITCOIN_SCRIPT_SCRIPTCACHE_H | #endif // BITCOIN_SCRIPT_SCRIPTCACHE_H |
Is this intended to be part of the public API?