fuzz: move backend mutating block to end of coins_view

Refactor TestCoinsView() to move code that directly modifies
backend_coins_view to the end of the function.
This prepares for a CoinsViewOverlay fuzz target that asserts
the backend_coins_view is not mutated by any methods before
BatchWrite is called.

Co-authored-by: l0rinc <pap.lorinc@gmail.com>
This commit is contained in:
Andrew Toth 2026-02-03 17:58:24 -05:00
parent 89824fb27b
commit 86eda88c8e
No known key found for this signature in database
GPG Key ID: 60007AFC8938B018

View File

@ -177,31 +177,6 @@ void TestCoinsView(FuzzedDataProvider& fuzzed_data_provider, CCoinsViewCache& co
});
}
{
const Coin& coin_using_access_coin = coins_view_cache.AccessCoin(random_out_point);
const bool exists_using_access_coin = !(coin_using_access_coin == EMPTY_COIN);
const bool exists_using_have_coin = coins_view_cache.HaveCoin(random_out_point);
const bool exists_using_have_coin_in_cache = coins_view_cache.HaveCoinInCache(random_out_point);
if (auto coin{coins_view_cache.GetCoin(random_out_point)}) {
assert(*coin == coin_using_access_coin);
assert(exists_using_access_coin && exists_using_have_coin_in_cache && exists_using_have_coin);
} else {
assert(!exists_using_access_coin && !exists_using_have_coin_in_cache && !exists_using_have_coin);
}
// If HaveCoin on the backend is true, it must also be on the cache if the coin wasn't spent.
const bool exists_using_have_coin_in_backend = backend_coins_view.HaveCoin(random_out_point);
if (!coin_using_access_coin.IsSpent() && exists_using_have_coin_in_backend) {
assert(exists_using_have_coin);
}
if (auto coin{backend_coins_view.GetCoin(random_out_point)}) {
assert(exists_using_have_coin_in_backend);
// Note we can't assert that `coin_using_get_coin == *coin` because the coin in
// the cache may have been modified but not yet flushed.
} else {
assert(!exists_using_have_coin_in_backend);
}
}
{
bool expected_code_path = false;
try {
@ -305,6 +280,31 @@ void TestCoinsView(FuzzedDataProvider& fuzzed_data_provider, CCoinsViewCache& co
(void)IsWitnessStandard(CTransaction{random_mutable_transaction}, coins_view_cache);
});
}
{
const Coin& coin_using_access_coin = coins_view_cache.AccessCoin(random_out_point);
const bool exists_using_access_coin = !(coin_using_access_coin == EMPTY_COIN);
const bool exists_using_have_coin = coins_view_cache.HaveCoin(random_out_point);
const bool exists_using_have_coin_in_cache = coins_view_cache.HaveCoinInCache(random_out_point);
if (auto coin{coins_view_cache.GetCoin(random_out_point)}) {
assert(*coin == coin_using_access_coin);
assert(exists_using_access_coin && exists_using_have_coin_in_cache && exists_using_have_coin);
} else {
assert(!exists_using_access_coin && !exists_using_have_coin_in_cache && !exists_using_have_coin);
}
// If HaveCoin on the backend is true, it must also be on the cache if the coin wasn't spent.
const bool exists_using_have_coin_in_backend = backend_coins_view.HaveCoin(random_out_point);
if (!coin_using_access_coin.IsSpent() && exists_using_have_coin_in_backend) {
assert(exists_using_have_coin);
}
if (auto coin{backend_coins_view.GetCoin(random_out_point)}) {
assert(exists_using_have_coin_in_backend);
// Note we can't assert that `coin_using_get_coin == *coin` because the coin in
// the cache may have been modified but not yet flushed.
} else {
assert(!exists_using_have_coin_in_backend);
}
}
}
FUZZ_TARGET(coins_view, .init = initialize_coins_view)