aboutsummaryrefslogtreecommitdiff
path: root/src/coins.cpp
diff options
context:
space:
mode:
authorJohn Newbery <john@johnnewbery.com>2020-01-30 15:52:36 -0500
committerJohn Newbery <john@johnnewbery.com>2020-04-21 14:18:03 -0400
commitc205979031ff4e8e32a5f05bae813405f233fccd (patch)
tree332dd712955d4e2eb8aa9a4fc8d9676637fc67a7 /src/coins.cpp
parent646f0ada0205ae4b3952107e3b1542f06adda32b (diff)
[docs] Improve commenting in coins.cpp|h
Remove references to 'pruned' coins, which don't exist since the move to per-txout coins db.
Diffstat (limited to 'src/coins.cpp')
-rw-r--r--src/coins.cpp49
1 files changed, 30 insertions, 19 deletions
diff --git a/src/coins.cpp b/src/coins.cpp
index b71362c6a0..9e0dd6cd9f 100644
--- a/src/coins.cpp
+++ b/src/coins.cpp
@@ -77,8 +77,21 @@ void CCoinsViewCache::AddCoin(const COutPoint &outpoint, Coin&& coin, bool possi
}
if (!possible_overwrite) {
if (!it->second.coin.IsSpent()) {
- throw std::logic_error("Adding new coin that replaces non-pruned entry");
+ 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
+ // 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.
+ // If we mark it FRESH and then spend it before the cache is flushed
+ // we would remove it from this cache and would never flush spentness
+ // to the parent cache.
+ //
+ // 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
+ // 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
+ // DIRTY, then it can be marked FRESH.
fresh = !(it->second.flags & CCoinsCacheEntry::DIRTY);
}
it->second.coin = std::move(coin);
@@ -152,11 +165,11 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn
}
CCoinsMap::iterator itUs = cacheCoins.find(it->first);
if (itUs == cacheCoins.end()) {
- // The parent cache does not have an entry, while the child does
- // We can ignore it if it's both FRESH and pruned in the child
+ // The parent cache does not have an entry, while the child cache does.
+ // We can ignore it if it's both spent and FRESH in the child
if (!(it->second.flags & CCoinsCacheEntry::FRESH && it->second.coin.IsSpent())) {
- // Otherwise we will need to create it in the parent
- // and move the data up and mark it as dirty
+ // Create the coin in the parent cache, move the data up
+ // and mark it as dirty.
CCoinsCacheEntry& entry = cacheCoins[it->first];
entry.coin = std::move(it->second.coin);
cachedCoinsUsage += entry.coin.DynamicMemoryUsage();
@@ -169,19 +182,18 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn
}
}
} else {
- // Assert that the child cache entry was not marked FRESH if the
- // parent cache entry has unspent outputs. If this ever happens,
- // it means the FRESH flag was misapplied and there is a logic
- // error in the calling code.
+ // Found the entry in the parent cache
if ((it->second.flags & CCoinsCacheEntry::FRESH) && !itUs->second.coin.IsSpent()) {
- throw std::logic_error("FRESH flag misapplied to cache entry for base transaction with spendable outputs");
+ // The coin was marked FRESH in the child cache, but the coin
+ // exists in the parent cache. If this ever happens, it means
+ // the FRESH flag was misapplied and there is a logic error in
+ // the calling code.
+ throw std::logic_error("FRESH flag misapplied to coin that exists in parent cache");
}
- // Found the entry in the parent cache
if ((itUs->second.flags & CCoinsCacheEntry::FRESH) && it->second.coin.IsSpent()) {
- // The grandparent does not have an entry, and the child is
- // modified and being pruned. This means we can just delete
- // it from the parent.
+ // The grandparent cache does not have an entry, and the coin
+ // has been spent. We can just delete it from the parent cache.
cachedCoinsUsage -= itUs->second.coin.DynamicMemoryUsage();
cacheCoins.erase(itUs);
} else {
@@ -190,11 +202,10 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn
itUs->second.coin = std::move(it->second.coin);
cachedCoinsUsage += itUs->second.coin.DynamicMemoryUsage();
itUs->second.flags |= CCoinsCacheEntry::DIRTY;
- // NOTE: It is possible the child has a FRESH flag here in
- // the event the entry we found in the parent is pruned. But
- // we must not copy that FRESH flag to the parent as that
- // pruned state likely still needs to be communicated to the
- // grandparent.
+ // NOTE: It isn't safe to mark the coin as FRESH in the parent
+ // cache. If it already existed and was spent in the parent
+ // cache then marking it FRESH would prevent that spentness
+ // from being flushed to the grandparent.
}
}
}