mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-04-29 14:59:39 -04:00
Merge 763be0ac98
into 65714c162c
This commit is contained in:
commit
0a06dfeb9d
5 changed files with 19 additions and 25 deletions
|
@ -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) {
|
||||||
|
|
12
src/coins.h
12
src/coins.h
|
@ -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_sentinel(sentinel), m_map(map), m_will_erase(will_erase) {}
|
||||||
: m_usage(usage), 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;
|
||||||
|
|
|
@ -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, {}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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/
|
||||||
|
|
Loading…
Add table
Reference in a new issue