This commit is contained in:
l0rinc 2025-04-29 01:15:45 +02:00 committed by GitHub
commit 0a06dfeb9d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 19 additions and 25 deletions

View file

@ -76,9 +76,6 @@ void CCoinsViewCache::AddCoin(const COutPoint &outpoint, Coin&& coin, bool possi
bool inserted; bool inserted;
std::tie(it, inserted) = cacheCoins.emplace(std::piecewise_construct, std::forward_as_tuple(outpoint), std::tuple<>()); std::tie(it, inserted) = cacheCoins.emplace(std::piecewise_construct, std::forward_as_tuple(outpoint), std::tuple<>());
bool fresh = false; bool fresh = false;
if (!inserted) {
cachedCoinsUsage -= it->second.coin.DynamicMemoryUsage();
}
if (!possible_overwrite) { if (!possible_overwrite) {
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)");
@ -98,6 +95,9 @@ void CCoinsViewCache::AddCoin(const COutPoint &outpoint, Coin&& coin, bool possi
// DIRTY, then it can be marked FRESH. // DIRTY, then it can be marked FRESH.
fresh = !it->second.IsDirty(); fresh = !it->second.IsDirty();
} }
if (!inserted) {
cachedCoinsUsage -= it->second.coin.DynamicMemoryUsage();
}
it->second.coin = std::move(coin); it->second.coin = std::move(coin);
CCoinsCacheEntry::SetDirty(*it, m_sentinel); CCoinsCacheEntry::SetDirty(*it, m_sentinel);
if (fresh) CCoinsCacheEntry::SetFresh(*it, m_sentinel); if (fresh) CCoinsCacheEntry::SetFresh(*it, m_sentinel);
@ -111,9 +111,11 @@ 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();
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 += it->second.coin.DynamicMemoryUsage();
}
} }
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) {
@ -195,6 +197,7 @@ bool CCoinsViewCache::BatchWrite(CoinsViewCacheCursor& cursor, const uint256 &ha
// and mark it as dirty. // and mark it as dirty.
itUs = cacheCoins.try_emplace(it->first).first; itUs = cacheCoins.try_emplace(it->first).first;
CCoinsCacheEntry& entry{itUs->second}; CCoinsCacheEntry& entry{itUs->second};
assert(entry.coin.DynamicMemoryUsage() == 0);
if (cursor.WillErase(*it)) { if (cursor.WillErase(*it)) {
// Since this entry will be erased, // Since this entry will be erased,
// we can move the coin into us instead of copying it // we can move the coin into us instead of copying it
@ -248,19 +251,19 @@ bool CCoinsViewCache::BatchWrite(CoinsViewCacheCursor& cursor, const uint256 &ha
} }
bool CCoinsViewCache::Flush() { bool CCoinsViewCache::Flush() {
auto cursor{CoinsViewCacheCursor(cachedCoinsUsage, m_sentinel, cacheCoins, /*will_erase=*/true)}; auto cursor{CoinsViewCacheCursor(m_sentinel, cacheCoins, /*will_erase=*/true)};
bool fOk = base->BatchWrite(cursor, hashBlock); bool fOk = base->BatchWrite(cursor, hashBlock);
if (fOk) { if (fOk) {
cacheCoins.clear(); cacheCoins.clear();
ReallocateCache(); ReallocateCache();
}
cachedCoinsUsage = 0; cachedCoinsUsage = 0;
}
return fOk; return fOk;
} }
bool CCoinsViewCache::Sync() bool CCoinsViewCache::Sync()
{ {
auto cursor{CoinsViewCacheCursor(cachedCoinsUsage, m_sentinel, cacheCoins, /*will_erase=*/false)}; auto cursor{CoinsViewCacheCursor(m_sentinel, cacheCoins, /*will_erase=*/false)};
bool fOk = base->BatchWrite(cursor, hashBlock); bool fOk = base->BatchWrite(cursor, hashBlock);
if (fOk) { if (fOk) {
if (m_sentinel.second.Next() != &m_sentinel) { if (m_sentinel.second.Next() != &m_sentinel) {

View file

@ -271,11 +271,10 @@ struct CoinsViewCacheCursor
//! This is an optimization compared to erasing all entries as the cursor iterates them when will_erase is set. //! This is an optimization compared to erasing all entries as the cursor iterates them when will_erase is set.
//! Calling CCoinsMap::clear() afterwards is faster because a CoinsCachePair cannot be coerced back into a //! Calling CCoinsMap::clear() afterwards is faster because a CoinsCachePair cannot be coerced back into a
//! CCoinsMap::iterator to be erased, and must therefore be looked up again by key in the CCoinsMap before being erased. //! CCoinsMap::iterator to be erased, and must therefore be looked up again by key in the CCoinsMap before being erased.
CoinsViewCacheCursor(size_t& usage LIFETIMEBOUND, CoinsViewCacheCursor(CoinsCachePair& sentinel LIFETIMEBOUND,
CoinsCachePair& sentinel LIFETIMEBOUND,
CCoinsMap& map LIFETIMEBOUND, CCoinsMap& map LIFETIMEBOUND,
bool will_erase) noexcept bool will_erase) noexcept
: m_usage(usage), m_sentinel(sentinel), m_map(map), m_will_erase(will_erase) {} : m_sentinel(sentinel), m_map(map), m_will_erase(will_erase) {}
inline CoinsCachePair* Begin() const noexcept { return m_sentinel.second.Next(); } inline CoinsCachePair* Begin() const noexcept { return m_sentinel.second.Next(); }
inline CoinsCachePair* End() const noexcept { return &m_sentinel; } inline CoinsCachePair* End() const noexcept { return &m_sentinel; }
@ -288,7 +287,7 @@ struct CoinsViewCacheCursor
// Otherwise, clear the state of the entry. // Otherwise, clear the state of the entry.
if (!m_will_erase) { if (!m_will_erase) {
if (current.second.coin.IsSpent()) { if (current.second.coin.IsSpent()) {
m_usage -= current.second.coin.DynamicMemoryUsage(); assert(current.second.coin.DynamicMemoryUsage() == 0); // scriptPubKey was already cleared in SpendCoin
m_map.erase(current.first); m_map.erase(current.first);
} else { } else {
current.second.SetClean(); current.second.SetClean();
@ -299,7 +298,6 @@ struct CoinsViewCacheCursor
inline bool WillErase(CoinsCachePair& current) const noexcept { return m_will_erase || current.second.coin.IsSpent(); } inline bool WillErase(CoinsCachePair& current) const noexcept { return m_will_erase || current.second.coin.IsSpent(); }
private: private:
size_t& m_usage;
CoinsCachePair& m_sentinel; CoinsCachePair& m_sentinel;
CCoinsMap& m_map; CCoinsMap& m_map;
bool m_will_erase; bool m_will_erase;

View file

@ -651,8 +651,8 @@ static void WriteCoinsViewEntry(CCoinsView& view, const MaybeCoin& cache_coin)
sentinel.second.SelfRef(sentinel); sentinel.second.SelfRef(sentinel);
CCoinsMapMemoryResource resource; CCoinsMapMemoryResource resource;
CCoinsMap map{0, CCoinsMap::hasher{}, CCoinsMap::key_equal{}, &resource}; CCoinsMap map{0, CCoinsMap::hasher{}, CCoinsMap::key_equal{}, &resource};
auto usage{cache_coin ? InsertCoinsMapEntry(map, sentinel, *cache_coin) : 0}; if (cache_coin) InsertCoinsMapEntry(map, sentinel, *cache_coin);
auto cursor{CoinsViewCacheCursor(usage, sentinel, map, /*will_erase=*/true)}; auto cursor{CoinsViewCacheCursor(sentinel, map, /*will_erase=*/true)};
BOOST_CHECK(view.BatchWrite(cursor, {})); BOOST_CHECK(view.BatchWrite(cursor, {}));
} }

View file

@ -122,7 +122,6 @@ FUZZ_TARGET(coins_view, .init = initialize_coins_view)
[&] { [&] {
CoinsCachePair sentinel{}; CoinsCachePair sentinel{};
sentinel.second.SelfRef(sentinel); sentinel.second.SelfRef(sentinel);
size_t usage{0};
CCoinsMapMemoryResource resource; CCoinsMapMemoryResource resource;
CCoinsMap coins_map{0, SaltedOutpointHasher{/*deterministic=*/true}, CCoinsMap::key_equal{}, &resource}; CCoinsMap coins_map{0, SaltedOutpointHasher{/*deterministic=*/true}, CCoinsMap::key_equal{}, &resource};
LIMITED_WHILE(good_data && fuzzed_data_provider.ConsumeBool(), 10'000) LIMITED_WHILE(good_data && fuzzed_data_provider.ConsumeBool(), 10'000)
@ -143,11 +142,10 @@ FUZZ_TARGET(coins_view, .init = initialize_coins_view)
auto it{coins_map.emplace(random_out_point, std::move(coins_cache_entry)).first}; auto it{coins_map.emplace(random_out_point, std::move(coins_cache_entry)).first};
if (dirty) CCoinsCacheEntry::SetDirty(*it, sentinel); if (dirty) CCoinsCacheEntry::SetDirty(*it, sentinel);
if (fresh) CCoinsCacheEntry::SetFresh(*it, sentinel); if (fresh) CCoinsCacheEntry::SetFresh(*it, sentinel);
usage += it->second.coin.DynamicMemoryUsage();
} }
bool expected_code_path = false; bool expected_code_path = false;
try { try {
auto cursor{CoinsViewCacheCursor(usage, sentinel, coins_map, /*will_erase=*/true)}; auto cursor{CoinsViewCacheCursor(sentinel, coins_map, /*will_erase=*/true)};
coins_view_cache.BatchWrite(cursor, fuzzed_data_provider.ConsumeBool() ? ConsumeUInt256(fuzzed_data_provider) : coins_view_cache.GetBestBlock()); coins_view_cache.BatchWrite(cursor, fuzzed_data_provider.ConsumeBool() ? ConsumeUInt256(fuzzed_data_provider) : coins_view_cache.GetBestBlock());
expected_code_path = true; expected_code_path = true;
} catch (const std::logic_error& e) { } catch (const std::logic_error& e) {

View file

@ -44,11 +44,6 @@ unsigned-integer-overflow:arith_uint256.h
unsigned-integer-overflow:CBloomFilter::Hash unsigned-integer-overflow:CBloomFilter::Hash
unsigned-integer-overflow:CRollingBloomFilter::insert unsigned-integer-overflow:CRollingBloomFilter::insert
unsigned-integer-overflow:RollingBloomHash unsigned-integer-overflow:RollingBloomHash
unsigned-integer-overflow:CCoinsViewCache::AddCoin
unsigned-integer-overflow:CCoinsViewCache::BatchWrite
unsigned-integer-overflow:CCoinsViewCache::DynamicMemoryUsage
unsigned-integer-overflow:CCoinsViewCache::SpendCoin
unsigned-integer-overflow:CCoinsViewCache::Uncache
unsigned-integer-overflow:CompressAmount unsigned-integer-overflow:CompressAmount
unsigned-integer-overflow:DecompressAmount unsigned-integer-overflow:DecompressAmount
unsigned-integer-overflow:crypto/ unsigned-integer-overflow:crypto/