From 59e6828bb5b56a2354a80059d3f660f551f3e207 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 1 Feb 2023 18:52:11 -0500 Subject: Add deterministic mode to CCoinsViewCache --- src/coins.cpp | 7 +++++-- src/coins.h | 5 ++++- src/test/fuzz/coins_view.cpp | 2 +- src/test/fuzz/coinscache_sim.cpp | 4 ++-- src/util/hasher.cpp | 5 ++++- src/util/hasher.h | 2 +- 6 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/coins.cpp b/src/coins.cpp index 8d99019bb0..5a6ae525a7 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -32,7 +32,10 @@ bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, std::unique_ptr CCoinsViewBacked::Cursor() const { return base->Cursor(); } 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 { return memusage::DynamicUsage(cacheCoins) + cachedCoinsUsage; @@ -311,7 +314,7 @@ void CCoinsViewCache::ReallocateCache() // Cache should be empty when we're calling this. assert(cacheCoins.size() == 0); cacheCoins.~CCoinsMap(); - ::new (&cacheCoins) CCoinsMap(); + ::new (&cacheCoins) CCoinsMap(0, SaltedOutpointHasher(/*deterministic=*/m_deterministic)); } void CCoinsViewCache::SanityCheck() const diff --git a/src/coins.h b/src/coins.h index a2764d32bb..dd336b210a 100644 --- a/src/coins.h +++ b/src/coins.h @@ -211,6 +211,9 @@ public: /** CCoinsView that adds a memory cache for transactions to another CCoinsView */ class CCoinsViewCache : public CCoinsViewBacked { +private: + const bool m_deterministic; + protected: /** * Make mutable so that we can "fill the cache" even from Get-methods @@ -223,7 +226,7 @@ protected: mutable size_t cachedCoinsUsage{0}; 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. diff --git a/src/test/fuzz/coins_view.cpp b/src/test/fuzz/coins_view.cpp index e75dc3ce91..e80c772aa4 100644 --- a/src/test/fuzz/coins_view.cpp +++ b/src/test/fuzz/coins_view.cpp @@ -46,7 +46,7 @@ FUZZ_TARGET_INIT(coins_view, initialize_coins_view) { FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; CCoinsView backend_coins_view; - CCoinsViewCache coins_view_cache{&backend_coins_view}; + CCoinsViewCache coins_view_cache{&backend_coins_view, /*deterministic=*/true}; COutPoint random_out_point; Coin random_coin; CMutableTransaction random_mutable_transaction; diff --git a/src/test/fuzz/coinscache_sim.cpp b/src/test/fuzz/coinscache_sim.cpp index b794888ca2..02575f2731 100644 --- a/src/test/fuzz/coinscache_sim.cpp +++ b/src/test/fuzz/coinscache_sim.cpp @@ -245,7 +245,7 @@ FUZZ_TARGET(coinscache_sim) ++current_height; // Make sure there is always at least one CCoinsViewCache. if (caches.empty()) { - caches.emplace_back(new CCoinsViewCache(&bottom)); + caches.emplace_back(new CCoinsViewCache(&bottom, /*deterministic=*/true)); sim_caches[caches.size()].Wipe(); } @@ -374,7 +374,7 @@ FUZZ_TARGET(coinscache_sim) [&]() { // Add a cache level (if not already at the max). if (caches.size() != MAX_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. sim_caches[caches.size()].Wipe(); } diff --git a/src/util/hasher.cpp b/src/util/hasher.cpp index a3a3f7a429..81e9b990e1 100644 --- a/src/util/hasher.cpp +++ b/src/util/hasher.cpp @@ -9,7 +9,10 @@ SaltedTxidHasher::SaltedTxidHasher() : k0(GetRand()), k1(GetRand()) {} -SaltedOutpointHasher::SaltedOutpointHasher() : k0(GetRand()), k1(GetRand()) {} +SaltedOutpointHasher::SaltedOutpointHasher(bool deterministic) : + k0(deterministic ? 0x8e819f2607a18de6 : GetRand()), + k1(deterministic ? 0xf4020d2e3983b0eb : GetRand()) +{} SaltedSipHasher::SaltedSipHasher() : m_k0(GetRand()), m_k1(GetRand()) {} diff --git a/src/util/hasher.h b/src/util/hasher.h index 82d278b086..506ae9415d 100644 --- a/src/util/hasher.h +++ b/src/util/hasher.h @@ -36,7 +36,7 @@ private: const uint64_t k0, k1; public: - SaltedOutpointHasher(); + SaltedOutpointHasher(bool deterministic = false); /** * Having the hash noexcept allows libstdc++'s unordered_map to recalculate -- cgit v1.2.3