coins: set all inserted spent coins to fresh

A spent coins must be DIRTY, so remove
references to spent but not DIRTY coins.
The only way a spent coin can be not DIRTY
is when creating the CCoinsCacheEntry with
an empty coin. This can be made more clear
by setting fresh if inserted, instead of
checking if an unspent coin is not DIRTY.
This commit is contained in:
Andrew Toth 2024-08-31 15:11:21 -04:00
parent 4c9c30eda3
commit 6956ee9cc7
No known key found for this signature in database
GPG key ID: 60007AFC8938B018
2 changed files with 6 additions and 8 deletions

View file

@ -79,20 +79,18 @@ void CCoinsViewCache::AddCoin(const COutPoint &outpoint, Coin&& coin, bool possi
if (!it->second.coin.IsSpent()) { if (!it->second.coin.IsSpent()) {
throw std::logic_error("Attempted to overwrite an unspent coin (when possible_overwrite is false)"); throw std::logic_error("Attempted to overwrite an unspent coin (when possible_overwrite is false)");
} }
// If the coin exists in this cache as a spent coin and is DIRTY, then // If the coin exists in this cache as a spent coin, then
// its spentness hasn't been flushed to the parent cache. We're // its spentness hasn't been flushed to the parent cache. We're
// re-adding the coin to this cache now but we can't mark it as FRESH. // re-adding the coin to this cache now but we can't mark it as FRESH.
// If we mark it FRESH and then spend it before the cache is flushed // A spent FRESH coin cannot exist in the cache because a FRESH coin
// we would remove it from this cache and would never flush spentness // is simply erased when it is spent.
// to the parent cache.
// //
// Re-adding a spent coin can happen in the case of a re-org (the coin // Re-adding a spent coin can happen in the case of a re-org (the coin
// is 'spent' when the block adding it is disconnected and then // is 'spent' when the block adding it is disconnected and then
// re-added when it is also added in a newly connected block). // re-added when it is also added in a newly connected block).
// //
// If the coin doesn't exist in the current cache, or is spent but not // If the coin doesn't exist in the current cache then it can be marked FRESH.
// DIRTY, then it can be marked FRESH. fresh = inserted;
fresh = !it->second.IsDirty();
} }
it->second.coin = std::move(coin); it->second.coin = std::move(coin);
CCoinsCacheEntry::SetDirty(*it, m_sentinel); CCoinsCacheEntry::SetDirty(*it, m_sentinel);

View file

@ -756,7 +756,7 @@ BOOST_AUTO_TEST_CASE(ccoins_add)
CheckAddCoin(base_value, MISSING, VALUE3, VALUE3_DIRTY_FRESH, false); CheckAddCoin(base_value, MISSING, VALUE3, VALUE3_DIRTY_FRESH, false);
CheckAddCoin(base_value, MISSING, VALUE3, VALUE3_DIRTY, true ); CheckAddCoin(base_value, MISSING, VALUE3, VALUE3_DIRTY, true );
CheckAddCoin(base_value, SPENT_CLEAN, VALUE3, VALUE3_DIRTY_FRESH, false); CheckAddCoin(base_value, SPENT_CLEAN, VALUE3, VALUE3_DIRTY, false);
CheckAddCoin(base_value, SPENT_CLEAN, VALUE3, VALUE3_DIRTY, true ); CheckAddCoin(base_value, SPENT_CLEAN, VALUE3, VALUE3_DIRTY, true );
CheckAddCoin(base_value, SPENT_FRESH, VALUE3, VALUE3_DIRTY_FRESH, false); CheckAddCoin(base_value, SPENT_FRESH, VALUE3, VALUE3_DIRTY_FRESH, false);
CheckAddCoin(base_value, SPENT_FRESH, VALUE3, VALUE3_DIRTY_FRESH, true ); CheckAddCoin(base_value, SPENT_FRESH, VALUE3, VALUE3_DIRTY_FRESH, true );