Add deterministic mode to CCoinsViewCache

This commit is contained in:
Pieter Wuille 2023-02-01 18:52:11 -05:00
parent b0ff310840
commit 59e6828bb5
6 changed files with 17 additions and 8 deletions

View file

@ -32,7 +32,10 @@ bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock,
std::unique_ptr<CCoinsViewCursor> CCoinsViewBacked::Cursor() const { return base->Cursor(); } std::unique_ptr<CCoinsViewCursor> CCoinsViewBacked::Cursor() const { return base->Cursor(); }
size_t CCoinsViewBacked::EstimateSize() const { return base->EstimateSize(); } size_t CCoinsViewBacked::EstimateSize() const { return base->EstimateSize(); }
CCoinsViewCache::CCoinsViewCache(CCoinsView* baseIn) : CCoinsViewBacked(baseIn) {} CCoinsViewCache::CCoinsViewCache(CCoinsView* baseIn, bool deterministic) :
CCoinsViewBacked(baseIn), m_deterministic(deterministic),
cacheCoins(0, SaltedOutpointHasher(/*deterministic=*/deterministic))
{}
size_t CCoinsViewCache::DynamicMemoryUsage() const { size_t CCoinsViewCache::DynamicMemoryUsage() const {
return memusage::DynamicUsage(cacheCoins) + cachedCoinsUsage; return memusage::DynamicUsage(cacheCoins) + cachedCoinsUsage;
@ -311,7 +314,7 @@ void CCoinsViewCache::ReallocateCache()
// Cache should be empty when we're calling this. // Cache should be empty when we're calling this.
assert(cacheCoins.size() == 0); assert(cacheCoins.size() == 0);
cacheCoins.~CCoinsMap(); cacheCoins.~CCoinsMap();
::new (&cacheCoins) CCoinsMap(); ::new (&cacheCoins) CCoinsMap(0, SaltedOutpointHasher(/*deterministic=*/m_deterministic));
} }
void CCoinsViewCache::SanityCheck() const void CCoinsViewCache::SanityCheck() const

View file

@ -211,6 +211,9 @@ public:
/** CCoinsView that adds a memory cache for transactions to another CCoinsView */ /** CCoinsView that adds a memory cache for transactions to another CCoinsView */
class CCoinsViewCache : public CCoinsViewBacked class CCoinsViewCache : public CCoinsViewBacked
{ {
private:
const bool m_deterministic;
protected: protected:
/** /**
* Make mutable so that we can "fill the cache" even from Get-methods * Make mutable so that we can "fill the cache" even from Get-methods
@ -223,7 +226,7 @@ protected:
mutable size_t cachedCoinsUsage{0}; mutable size_t cachedCoinsUsage{0};
public: public:
CCoinsViewCache(CCoinsView *baseIn); CCoinsViewCache(CCoinsView *baseIn, bool deterministic = false);
/** /**
* By deleting the copy constructor, we prevent accidentally using it when one intends to create a cache on top of a base cache. * By deleting the copy constructor, we prevent accidentally using it when one intends to create a cache on top of a base cache.

View file

@ -46,7 +46,7 @@ FUZZ_TARGET_INIT(coins_view, initialize_coins_view)
{ {
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
CCoinsView backend_coins_view; CCoinsView backend_coins_view;
CCoinsViewCache coins_view_cache{&backend_coins_view}; CCoinsViewCache coins_view_cache{&backend_coins_view, /*deterministic=*/true};
COutPoint random_out_point; COutPoint random_out_point;
Coin random_coin; Coin random_coin;
CMutableTransaction random_mutable_transaction; CMutableTransaction random_mutable_transaction;

View file

@ -245,7 +245,7 @@ FUZZ_TARGET(coinscache_sim)
++current_height; ++current_height;
// Make sure there is always at least one CCoinsViewCache. // Make sure there is always at least one CCoinsViewCache.
if (caches.empty()) { if (caches.empty()) {
caches.emplace_back(new CCoinsViewCache(&bottom)); caches.emplace_back(new CCoinsViewCache(&bottom, /*deterministic=*/true));
sim_caches[caches.size()].Wipe(); sim_caches[caches.size()].Wipe();
} }
@ -374,7 +374,7 @@ FUZZ_TARGET(coinscache_sim)
[&]() { // Add a cache level (if not already at the max). [&]() { // Add a cache level (if not already at the max).
if (caches.size() != MAX_CACHES) { if (caches.size() != MAX_CACHES) {
// Apply to real caches. // Apply to real caches.
caches.emplace_back(new CCoinsViewCache(&*caches.back())); caches.emplace_back(new CCoinsViewCache(&*caches.back(), /*deterministic=*/true));
// Apply to simulation data. // Apply to simulation data.
sim_caches[caches.size()].Wipe(); sim_caches[caches.size()].Wipe();
} }

View file

@ -9,7 +9,10 @@
SaltedTxidHasher::SaltedTxidHasher() : k0(GetRand<uint64_t>()), k1(GetRand<uint64_t>()) {} SaltedTxidHasher::SaltedTxidHasher() : k0(GetRand<uint64_t>()), k1(GetRand<uint64_t>()) {}
SaltedOutpointHasher::SaltedOutpointHasher() : k0(GetRand<uint64_t>()), k1(GetRand<uint64_t>()) {} SaltedOutpointHasher::SaltedOutpointHasher(bool deterministic) :
k0(deterministic ? 0x8e819f2607a18de6 : GetRand<uint64_t>()),
k1(deterministic ? 0xf4020d2e3983b0eb : GetRand<uint64_t>())
{}
SaltedSipHasher::SaltedSipHasher() : m_k0(GetRand<uint64_t>()), m_k1(GetRand<uint64_t>()) {} SaltedSipHasher::SaltedSipHasher() : m_k0(GetRand<uint64_t>()), m_k1(GetRand<uint64_t>()) {}

View file

@ -36,7 +36,7 @@ private:
const uint64_t k0, k1; const uint64_t k0, k1;
public: public:
SaltedOutpointHasher(); SaltedOutpointHasher(bool deterministic = false);
/** /**
* Having the hash noexcept allows libstdc++'s unordered_map to recalculate * Having the hash noexcept allows libstdc++'s unordered_map to recalculate