mirror of https://github.com/bitcoin/bitcoin.git
coins: Only update `cachedCoinsUsage` when entry is inserted in `EmplaceCoinInternalDANGER`
The `EmplaceCoinInternalDANGER` method was unconditionally adding to `cachedCoinsUsage`, but should only do so when `try_emplace` actually inserts a new entry. If the entry already exists, no memory is allocated and usage should not change. Adds test coverage by randomly calling `EmplaceCoinInternalDANGER` in `SimulationTest` to verify it remains correct. Co-authored-by: Pieter Wuille <pieter@wuille.net> Co-authored-by: Andrew Toth <andrewstoth@gmail.com>
This commit is contained in:
parent
b510893d00
commit
f377bd7468
|
@ -111,9 +111,12 @@ void CCoinsViewCache::AddCoin(const COutPoint &outpoint, Coin&& coin, bool possi
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCoinsViewCache::EmplaceCoinInternalDANGER(COutPoint&& outpoint, Coin&& coin) {
|
void CCoinsViewCache::EmplaceCoinInternalDANGER(COutPoint&& outpoint, Coin&& coin) {
|
||||||
cachedCoinsUsage += coin.DynamicMemoryUsage();
|
const auto mem_usage{coin.DynamicMemoryUsage()};
|
||||||
auto [it, inserted] = cacheCoins.try_emplace(std::move(outpoint), std::move(coin));
|
auto [it, inserted] = cacheCoins.try_emplace(std::move(outpoint), std::move(coin));
|
||||||
if (inserted) CCoinsCacheEntry::SetDirty(*it, m_sentinel);
|
if (inserted) {
|
||||||
|
CCoinsCacheEntry::SetDirty(*it, m_sentinel);
|
||||||
|
cachedCoinsUsage += mem_usage;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddCoins(CCoinsViewCache& cache, const CTransaction &tx, int nHeight, bool check_for_overwrite) {
|
void AddCoins(CCoinsViewCache& cache, const CTransaction &tx, int nHeight, bool check_for_overwrite) {
|
||||||
|
|
|
@ -194,8 +194,11 @@ void SimulationTest(CCoinsView* base, bool fake_best_block)
|
||||||
(coin.IsSpent() ? added_an_entry : updated_an_entry) = true;
|
(coin.IsSpent() ? added_an_entry : updated_an_entry) = true;
|
||||||
coin = newcoin;
|
coin = newcoin;
|
||||||
}
|
}
|
||||||
bool is_overwrite = !coin.IsSpent() || m_rng.rand32() & 1;
|
if (COutPoint op(txid, 0); !stack.back()->map().contains(op) && !coin.IsSpent() && m_rng.randbool()) {
|
||||||
stack.back()->AddCoin(COutPoint(txid, 0), std::move(newcoin), is_overwrite);
|
stack.back()->EmplaceCoinInternalDANGER(std::move(op), std::move(newcoin));
|
||||||
|
} else {
|
||||||
|
stack.back()->AddCoin(std::move(op), std::move(newcoin), /*possible_overwrite=*/!coin.IsSpent() || m_rng.randbool());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Spend the coin.
|
// Spend the coin.
|
||||||
removed_an_entry = true;
|
removed_an_entry = true;
|
||||||
|
|
Loading…
Reference in New Issue