mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-06-11 07:09:29 +02:00
fuzz: keep coinscache_sim backend free of spent coins
`CoinsViewBottom` roughly simulates a memory-backed `CCoinsViewDB`, which never stores spent coins. Stop returning spent coins from `GetCoin()`, erase spent entries in `BatchWrite()`, and tighten comparisons to expect `std::nullopt` when the simulator has no coin. Co-authored-by: Lőrinc <pap.lorinc@gmail.com>
This commit is contained in:
@@ -138,8 +138,6 @@ struct CacheLevel
|
|||||||
/** Class for the base of the hierarchy (roughly simulating a memory-backed CCoinsViewDB).
|
/** Class for the base of the hierarchy (roughly simulating a memory-backed CCoinsViewDB).
|
||||||
*
|
*
|
||||||
* The initial state consists of the empty UTXO set.
|
* The initial state consists of the empty UTXO set.
|
||||||
* Coins whose output index is 4 (mod 5) have GetCoin() always succeed after being spent.
|
|
||||||
* This exercises code paths with spent, non-DIRTY cache entries.
|
|
||||||
*/
|
*/
|
||||||
class CoinsViewBottom final : public CCoinsView
|
class CoinsViewBottom final : public CCoinsView
|
||||||
{
|
{
|
||||||
@@ -148,16 +146,13 @@ class CoinsViewBottom final : public CCoinsView
|
|||||||
public:
|
public:
|
||||||
std::optional<Coin> GetCoin(const COutPoint& outpoint) const final
|
std::optional<Coin> GetCoin(const COutPoint& outpoint) const final
|
||||||
{
|
{
|
||||||
// TODO GetCoin shouldn't return spent coins
|
if (auto it{m_data.find(outpoint)}; it != m_data.end()) {
|
||||||
if (auto it = m_data.find(outpoint); it != m_data.end()) return it->second;
|
assert(!it->second.IsSpent());
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HaveCoin(const COutPoint& outpoint) const final
|
|
||||||
{
|
|
||||||
return m_data.contains(outpoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint256 GetBestBlock() const final { return {}; }
|
uint256 GetBestBlock() const final { return {}; }
|
||||||
std::vector<uint256> GetHeadBlocks() const final { return {}; }
|
std::vector<uint256> GetHeadBlocks() const final { return {}; }
|
||||||
std::unique_ptr<CCoinsViewCursor> Cursor() const final { return {}; }
|
std::unique_ptr<CCoinsViewCursor> Cursor() const final { return {}; }
|
||||||
@@ -167,18 +162,20 @@ public:
|
|||||||
{
|
{
|
||||||
for (auto it{cursor.Begin()}; it != cursor.End(); it = cursor.NextAndMaybeErase(*it)) {
|
for (auto it{cursor.Begin()}; it != cursor.End(); it = cursor.NextAndMaybeErase(*it)) {
|
||||||
if (it->second.IsDirty()) {
|
if (it->second.IsDirty()) {
|
||||||
if (it->second.coin.IsSpent() && (it->first.n % 5) != 4) {
|
if (it->second.coin.IsSpent()) {
|
||||||
m_data.erase(it->first);
|
m_data.erase(it->first);
|
||||||
} else if (cursor.WillErase(*it)) {
|
|
||||||
m_data[it->first] = std::move(it->second.coin);
|
|
||||||
} else {
|
} else {
|
||||||
m_data[it->first] = it->second.coin;
|
if (cursor.WillErase(*it)) {
|
||||||
|
m_data[it->first] = std::move(it->second.coin);
|
||||||
|
} else {
|
||||||
|
m_data[it->first] = it->second.coin;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* For non-dirty entries being written, compare them with what we have. */
|
/* For non-dirty entries being written, compare them with what we have. */
|
||||||
auto it2 = m_data.find(it->first);
|
auto it2 = m_data.find(it->first);
|
||||||
if (it->second.coin.IsSpent()) {
|
if (it->second.coin.IsSpent()) {
|
||||||
assert(it2 == m_data.end() || it2->second.IsSpent());
|
assert(it2 == m_data.end());
|
||||||
} else {
|
} else {
|
||||||
assert(it2 != m_data.end());
|
assert(it2 != m_data.end());
|
||||||
assert(it->second.coin.out == it2->second.out);
|
assert(it->second.coin.out == it2->second.out);
|
||||||
@@ -263,7 +260,7 @@ FUZZ_TARGET(coinscache_sim)
|
|||||||
auto realcoin = caches.back()->GetCoin(data.outpoints[outpointidx]);
|
auto realcoin = caches.back()->GetCoin(data.outpoints[outpointidx]);
|
||||||
// Compare results.
|
// Compare results.
|
||||||
if (!sim.has_value()) {
|
if (!sim.has_value()) {
|
||||||
assert(!realcoin || realcoin->IsSpent());
|
assert(!realcoin);
|
||||||
} else {
|
} else {
|
||||||
assert(realcoin && !realcoin->IsSpent());
|
assert(realcoin && !realcoin->IsSpent());
|
||||||
const auto& simcoin = data.coins[sim->first];
|
const auto& simcoin = data.coins[sim->first];
|
||||||
@@ -449,7 +446,7 @@ FUZZ_TARGET(coinscache_sim)
|
|||||||
auto realcoin = bottom.GetCoin(data.outpoints[outpointidx]);
|
auto realcoin = bottom.GetCoin(data.outpoints[outpointidx]);
|
||||||
auto sim = lookup(outpointidx, 0);
|
auto sim = lookup(outpointidx, 0);
|
||||||
if (!sim.has_value()) {
|
if (!sim.has_value()) {
|
||||||
assert(!realcoin || realcoin->IsSpent());
|
assert(!realcoin);
|
||||||
} else {
|
} else {
|
||||||
assert(realcoin && !realcoin->IsSpent());
|
assert(realcoin && !realcoin->IsSpent());
|
||||||
assert(realcoin->out == data.coins[sim->first].out);
|
assert(realcoin->out == data.coins[sim->first].out);
|
||||||
|
|||||||
Reference in New Issue
Block a user