mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-04-08 22:57:56 +02:00
Merge bitcoin/bitcoin#34164: validation: add reusable coins view for ConnectBlock
3e0fd0e4ddrefactor: rename will_reuse_cache to reallocate_cache (Andrew Toth)44b4ee194dvalidation: reuse same CCoinsViewCache for every ConnectBlock call (Andrew Toth)8fb6043231coins: introduce CCoinsViewCache::ResetGuard (Andrew Toth)041758f5edcoins: use hashBlock setter internally for CCoinsViewCache methods (Andrew Toth)8dd9200fc9coins: add Reset on CCoinsViewCache (Andrew Toth) Pull request description: This is the first commit of #31132, which can be merged as an independent change. It has a small benefit on its own, but will help in moving the parent PR forward. Add a `Reset()` method to `CCoinsViewCache` that clears `cacheCoins`, `cachedCoinsUsage`, and `hashBlock` without flushing to the `base` view. This allows efficiently reusing a cache instance across multiple blocks. Add `CCoinsViewCache::CreateResetGuard` method to return a `CCoinsViewCache::ResetGuard`. The `ResetGuard` automatically calls `Reset()` on destruction. This RAII pattern ensures the cache is always properly reset between blocks. Add `m_connect_block_view` as a persistent `CCoinsViewCache` for `ConnectBlock`, avoiding repeated memory allocations. ACKs for top commit: l0rinc: ACK3e0fd0e4ddachow101: ACK3e0fd0e4ddsedited: ACK3e0fd0e4ddTree-SHA512: a95feaa062a9eb7cf7514425a7e7adffd347cd1f7b32b4c1fefcde30002141757c184174702b3104a029dcd33194f8bd734159deebb2e668716089305b42cb00
This commit is contained in:
@@ -1116,4 +1116,47 @@ BOOST_AUTO_TEST_CASE(ccoins_emplace_duplicate_keeps_usage_balanced)
|
||||
BOOST_CHECK(cache.AccessCoin(outpoint) == coin1);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ccoins_reset_guard)
|
||||
{
|
||||
CCoinsViewTest root{m_rng};
|
||||
CCoinsViewCache root_cache{&root};
|
||||
uint256 base_best_block{m_rng.rand256()};
|
||||
root_cache.SetBestBlock(base_best_block);
|
||||
root_cache.Flush();
|
||||
|
||||
CCoinsViewCache cache{&root};
|
||||
|
||||
const COutPoint outpoint{Txid::FromUint256(m_rng.rand256()), m_rng.rand32()};
|
||||
|
||||
const Coin coin{CTxOut{m_rng.randrange(10), CScript{} << m_rng.randbytes(CScriptBase::STATIC_SIZE + 1)}, 1, false};
|
||||
cache.EmplaceCoinInternalDANGER(COutPoint{outpoint}, Coin{coin});
|
||||
|
||||
uint256 cache_best_block{m_rng.rand256()};
|
||||
cache.SetBestBlock(cache_best_block);
|
||||
|
||||
{
|
||||
const auto reset_guard{cache.CreateResetGuard()};
|
||||
BOOST_CHECK(cache.AccessCoin(outpoint) == coin);
|
||||
BOOST_CHECK(!cache.AccessCoin(outpoint).IsSpent());
|
||||
BOOST_CHECK_EQUAL(cache.GetCacheSize(), 1);
|
||||
BOOST_CHECK_EQUAL(cache.GetBestBlock(), cache_best_block);
|
||||
BOOST_CHECK(!root_cache.HaveCoinInCache(outpoint));
|
||||
}
|
||||
|
||||
BOOST_CHECK(cache.AccessCoin(outpoint).IsSpent());
|
||||
BOOST_CHECK_EQUAL(cache.GetCacheSize(), 0);
|
||||
BOOST_CHECK_EQUAL(cache.GetBestBlock(), base_best_block);
|
||||
BOOST_CHECK(!root_cache.HaveCoinInCache(outpoint));
|
||||
|
||||
// Using a reset guard again is idempotent
|
||||
{
|
||||
const auto reset_guard{cache.CreateResetGuard()};
|
||||
}
|
||||
|
||||
BOOST_CHECK(cache.AccessCoin(outpoint).IsSpent());
|
||||
BOOST_CHECK_EQUAL(cache.GetCacheSize(), 0);
|
||||
BOOST_CHECK_EQUAL(cache.GetBestBlock(), base_best_block);
|
||||
BOOST_CHECK(!root_cache.HaveCoinInCache(outpoint));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
@@ -74,7 +74,7 @@ void TestCoinsView(FuzzedDataProvider& fuzzed_data_provider, CCoinsView& backend
|
||||
}
|
||||
},
|
||||
[&] {
|
||||
coins_view_cache.Flush(/*will_reuse_cache=*/fuzzed_data_provider.ConsumeBool());
|
||||
coins_view_cache.Flush(/*reallocate_cache=*/fuzzed_data_provider.ConsumeBool());
|
||||
},
|
||||
[&] {
|
||||
coins_view_cache.Sync();
|
||||
@@ -85,6 +85,20 @@ void TestCoinsView(FuzzedDataProvider& fuzzed_data_provider, CCoinsView& backend
|
||||
if (is_db && best_block.IsNull()) best_block = uint256::ONE;
|
||||
coins_view_cache.SetBestBlock(best_block);
|
||||
},
|
||||
[&] {
|
||||
{
|
||||
const auto reset_guard{coins_view_cache.CreateResetGuard()};
|
||||
}
|
||||
// Set best block hash to non-null to satisfy the assertion in CCoinsViewDB::BatchWrite().
|
||||
if (is_db) {
|
||||
const uint256 best_block{ConsumeUInt256(fuzzed_data_provider)};
|
||||
if (best_block.IsNull()) {
|
||||
good_data = false;
|
||||
return;
|
||||
}
|
||||
coins_view_cache.SetBestBlock(best_block);
|
||||
}
|
||||
},
|
||||
[&] {
|
||||
Coin move_to;
|
||||
(void)coins_view_cache.SpendCoin(random_out_point, fuzzed_data_provider.ConsumeBool() ? &move_to : nullptr);
|
||||
|
||||
@@ -388,7 +388,7 @@ FUZZ_TARGET(coinscache_sim)
|
||||
// Apply to simulation data.
|
||||
flush();
|
||||
// Apply to real caches.
|
||||
caches.back()->Flush(/*will_reuse_cache=*/provider.ConsumeBool());
|
||||
caches.back()->Flush(/*reallocate_cache=*/provider.ConsumeBool());
|
||||
},
|
||||
|
||||
[&]() { // Sync.
|
||||
@@ -398,6 +398,14 @@ FUZZ_TARGET(coinscache_sim)
|
||||
caches.back()->Sync();
|
||||
},
|
||||
|
||||
[&]() { // Reset.
|
||||
sim_caches[caches.size()].Wipe();
|
||||
// Apply to real caches.
|
||||
{
|
||||
const auto reset_guard{caches.back()->CreateResetGuard()};
|
||||
}
|
||||
},
|
||||
|
||||
[&]() { // GetCacheSize
|
||||
(void)caches.back()->GetCacheSize();
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user