Skip to content

Commit

Permalink
merge bitcoin#27011: Add simulation-based CCoinsViewCache fuzzer
Browse files Browse the repository at this point in the history
  • Loading branch information
kwvg committed Aug 23, 2024
1 parent 1d0e410 commit b658637
Show file tree
Hide file tree
Showing 7 changed files with 497 additions and 7 deletions.
1 change: 1 addition & 0 deletions src/Makefile.test.include
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ test_fuzz_fuzz_SOURCES = \
test/fuzz/chain.cpp \
test/fuzz/checkqueue.cpp \
test/fuzz/coins_view.cpp \
test/fuzz/coinscache_sim.cpp \
test/fuzz/connman.cpp \
test/fuzz/crypto.cpp \
test/fuzz/crypto_aes256.cpp \
Expand Down
24 changes: 22 additions & 2 deletions src/coins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock,
std::unique_ptr<CCoinsViewCursor> CCoinsViewBacked::Cursor() const { return base->Cursor(); }
size_t CCoinsViewBacked::EstimateSize() const { return base->EstimateSize(); }

CCoinsViewCache::CCoinsViewCache(CCoinsView *baseIn) : CCoinsViewBacked(baseIn), cachedCoinsUsage(0) {}
CCoinsViewCache::CCoinsViewCache(CCoinsView* baseIn, bool deterministic) :
CCoinsViewBacked(baseIn), m_deterministic(deterministic),
cacheCoins(0, SaltedOutpointHasher(/*deterministic=*/deterministic))
{}

size_t CCoinsViewCache::DynamicMemoryUsage() const {
return memusage::DynamicUsage(cacheCoins) + cachedCoinsUsage;
Expand Down Expand Up @@ -292,7 +295,24 @@ void CCoinsViewCache::ReallocateCache()
// Cache should be empty when we're calling this.
assert(cacheCoins.size() == 0);
cacheCoins.~CCoinsMap();
::new (&cacheCoins) CCoinsMap();
::new (&cacheCoins) CCoinsMap(0, SaltedOutpointHasher(/*deterministic=*/m_deterministic));
}

void CCoinsViewCache::SanityCheck() const
{
size_t recomputed_usage = 0;
for (const auto& [_, entry] : cacheCoins) {
unsigned attr = 0;
if (entry.flags & CCoinsCacheEntry::DIRTY) attr |= 1;
if (entry.flags & CCoinsCacheEntry::FRESH) attr |= 2;
if (entry.coin.IsSpent()) attr |= 4;
// Only 5 combinations are possible.
assert(attr != 2 && attr != 4 && attr != 7);

// Recompute cachedCoinsUsage.
recomputed_usage += entry.coin.DynamicMemoryUsage();
}
assert(recomputed_usage == cachedCoinsUsage);
}

static const size_t MAX_OUTPUTS_PER_BLOCK = MaxBlockSize() / ::GetSerializeSize(CTxOut(), PROTOCOL_VERSION);
Expand Down
10 changes: 8 additions & 2 deletions src/coins.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,9 @@ class CCoinsViewBacked : public CCoinsView
/** CCoinsView that adds a memory cache for transactions to another CCoinsView */
class CCoinsViewCache : public CCoinsViewBacked
{
private:
const bool m_deterministic;

protected:
/**
* Make mutable so that we can "fill the cache" even from Get-methods
Expand All @@ -221,10 +224,10 @@ class CCoinsViewCache : public CCoinsViewBacked
mutable CCoinsMap cacheCoins;

/* Cached dynamic memory usage for the inner Coin objects. */
mutable size_t cachedCoinsUsage;
mutable size_t cachedCoinsUsage{0};

public:
CCoinsViewCache(CCoinsView *baseIn);
CCoinsViewCache(CCoinsView *baseIn, bool deterministic = false);

/**
* By deleting the copy constructor, we prevent accidentally using it when one intends to create a cache on top of a base cache.
Expand Down Expand Up @@ -321,6 +324,9 @@ class CCoinsViewCache : public CCoinsViewBacked
//! See: https://stackoverflow.com/questions/42114044/how-to-release-unordered-map-memory
void ReallocateCache();

//! Run an internal sanity check on the cache data structure. */
void SanityCheck() const;

private:
/**
* @note this is marked const, but may actually append to `cacheCoins`, increasing
Expand Down
2 changes: 1 addition & 1 deletion src/test/fuzz/coins_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ FUZZ_TARGET_INIT(coins_view, initialize_coins_view)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
CCoinsView backend_coins_view;
CCoinsViewCache coins_view_cache{&backend_coins_view};
CCoinsViewCache coins_view_cache{&backend_coins_view, /*deterministic=*/true};
COutPoint random_out_point;
Coin random_coin;
CMutableTransaction random_mutable_transaction;
Expand Down
Loading

0 comments on commit b658637

Please sign in to comment.