Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
251}252coins_cache_entry.coin = *opt_coin;253}254// Avoid setting FRESH for an outpoint that already exists unspent in the parent view.255bool fresh{!coins_view_cache.PeekCoin(random_out_point) && fuzzed_data_provider.ConsumeBool()};256bool dirty{fresh || fuzzed_data_provider.ConsumeBool()};257auto it{coins_map.emplace(random_out_point, std::move(coins_cache_entry)).first};258if (dirty) CCoinsCacheEntry::SetDirty(*it, sentinel);259if (fresh) CCoinsCacheEntry::SetFresh(*it, sentinel);260dirty_count += dirty;261}262auto cursor{CoinsViewCacheCursor(dirty_count, sentinel, coins_map, /*will_erase=*/true)};263uint256 best_block{coins_view_cache.GetBestBlock()};264if (fuzzed_data_provider.ConsumeBool()) best_block = ConsumeUInt256(fuzzed_data_provider);265// Set best block hash to non-null to satisfy the assertion in CCoinsViewDB::BatchWrite().266if (is_db && best_block.IsNull()) best_block = uint256::ONE;267coins_view_cache.BatchWrite(cursor, best_block);268});269}271{272(void)coins_view_cache.DynamicMemoryUsage();273(void)coins_view_cache.EstimateSize();274(void)coins_view_cache.GetBestBlock();275(void)coins_view_cache.GetCacheSize();276(void)coins_view_cache.GetHeadBlocks();277(void)coins_view_cache.HaveInputs(CTransaction{random_mutable_transaction});278}280{281if (is_db && backend_coins_view == original_backend) {282assert(db->Cursor());283}284(void)backend_coins_view->EstimateSize();285(void)backend_coins_view->GetBestBlock();286(void)backend_coins_view->GetHeadBlocks();287}289if (fuzzed_data_provider.ConsumeBool()) {290CallOneOf(291fuzzed_data_provider,292[&] {293const CTransaction transaction{random_mutable_transaction};294bool is_spent = false;295for (const CTxOut& tx_out : transaction.vout) {296if (Coin{tx_out, 0, transaction.IsCoinBase()}.IsSpent()) {297is_spent = true;298}299}300if (is_spent) {301// Avoid:302// coins.cpp:69: void CCoinsViewCache::AddCoin(const COutPoint &, Coin &&, bool): Assertion `!coin.IsSpent()' failed.303return;304}305const int height{int(fuzzed_data_provider.ConsumeIntegral<uint32_t>() >> 1)};306const bool check_for_overwrite{transaction.IsCoinBase() || [&] {307for (uint32_t i{0}; i < transaction.vout.size(); ++i) {308if (coins_view_cache.PeekCoin(COutPoint{transaction.GetHash(), i})) return true;309}310return fuzzed_data_provider.ConsumeBool();311}()}; // We can only skip the check if the current txid has no unspent outputs312AddCoins(coins_view_cache, transaction, height, check_for_overwrite);313},314[&] {315(void)ValidateInputsStandardness(CTransaction{random_mutable_transaction}, coins_view_cache);316},317[&] {318TxValidationState state;319CAmount tx_fee_out;320const CTransaction transaction{random_mutable_transaction};321if (ContainsSpentInput(transaction, coins_view_cache)) {322// Avoid:323// consensus/tx_verify.cpp:171: bool Consensus::CheckTxInputs(const CTransaction &, TxValidationState &, const CCoinsViewCache &, int, CAmount &): Assertion `!coin.IsSpent()' failed.324return;325}326TxValidationState dummy;327if (!CheckTransaction(transaction, dummy)) {328// It is not allowed to call CheckTxInputs if CheckTransaction failed329return;330}331if (Consensus::CheckTxInputs(transaction, state, coins_view_cache, fuzzed_data_provider.ConsumeIntegralInRange<int>(0, std::numeric_limits<int>::max()), tx_fee_out)) {332assert(MoneyRange(tx_fee_out));333}334},335[&] {336const CTransaction transaction{random_mutable_transaction};337if (ContainsSpentInput(transaction, coins_view_cache)) {338// Avoid:339// consensus/tx_verify.cpp:130: unsigned int GetP2SHSigOpCount(const CTransaction &, const CCoinsViewCache &): Assertion `!coin.IsSpent()' failed.340return;341}342(void)GetP2SHSigOpCount(transaction, coins_view_cache);343},344[&] {345const CTransaction transaction{random_mutable_transaction};346if (ContainsSpentInput(transaction, coins_view_cache)) {347// Avoid:348// consensus/tx_verify.cpp:130: unsigned int GetP2SHSigOpCount(const CTransaction &, const CCoinsViewCache &): Assertion `!coin.IsSpent()' failed.349return;350}351const auto flags = script_verify_flags::from_int(fuzzed_data_provider.ConsumeIntegral<script_verify_flags::value_type>());352if (!transaction.vin.empty() && (flags & SCRIPT_VERIFY_WITNESS) != 0 && (flags & SCRIPT_VERIFY_P2SH) == 0) {353// Avoid:354// script/interpreter.cpp:1705: size_t CountWitnessSigOps(const CScript &, const CScript &, const CScriptWitness &, unsigned int): Assertion `(flags & SCRIPT_VERIFY_P2SH) != 0' failed.355return;356}357(void)GetTransactionSigOpCost(transaction, coins_view_cache, flags);358},359[&] {360(void)IsWitnessStandard(CTransaction{random_mutable_transaction}, coins_view_cache);361});362}364{365const Coin& coin_using_access_coin = coins_view_cache.AccessCoin(random_out_point);366const bool exists_using_access_coin = !coin_using_access_coin.IsSpent();367const bool exists_using_have_coin = coins_view_cache.HaveCoin(random_out_point);368const bool exists_using_have_coin_in_cache = coins_view_cache.HaveCoinInCache(random_out_point);369if (auto coin{coins_view_cache.GetCoin(random_out_point)}) {370assert(*coin == coin_using_access_coin);371assert(exists_using_access_coin && exists_using_have_coin_in_cache && exists_using_have_coin);372} else {373assert(!exists_using_access_coin && !exists_using_have_coin_in_cache && !exists_using_have_coin);374}375// If HaveCoin on the backend is true, it must also be on the cache if the coin wasn't spent.376std::optional<Coin> coin_in_backend;377bool exists_using_have_coin_in_backend;378if (overlay) {379// PeekCoin does not mutate cacheCoins, so async workers can keep running.380coin_in_backend = backend_coins_view->PeekCoin(random_out_point);381exists_using_have_coin_in_backend = coin_in_backend.has_value();382} else {383exists_using_have_coin_in_backend = backend_coins_view->HaveCoin(random_out_point);384coin_in_backend = backend_coins_view->GetCoin(random_out_point);385}386if (!coin_using_access_coin.IsSpent() && exists_using_have_coin_in_backend) {387assert(exists_using_have_coin);388}389if (coin_in_backend) {390assert(exists_using_have_coin_in_backend);391// Note we can't assert that `coin_using_get_coin == *coin` because the coin in392// the cache may have been modified but not yet flushed.393} else {394assert(!exists_using_have_coin_in_backend);395}396}397}399FUZZ_TARGET(coins_view, .init = initialize_coins_view)400{401FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};402CCoinsViewCache coins_view_cache{&CoinsViewEmpty::Get(), /*deterministic=*/true};403TestCoinsView(fuzzed_data_provider, coins_view_cache, &CoinsViewEmpty::Get());404}406FUZZ_TARGET(coins_view_db, .init = initialize_coins_view)407{408FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};409auto db_params = DBParams{410.path = "",411.cache_bytes = 1_MiB,412.memory_only = true,413};414CCoinsViewDB backend_coins_view{std::move(db_params), CoinsViewOptions{}};415CCoinsViewCache coins_view_cache{&backend_coins_view, /*deterministic=*/true};416TestCoinsView(fuzzed_data_provider, coins_view_cache, &backend_coins_view);417}419// Creates a CoinsViewOverlay and a MutationGuardCoinsViewCache as the base.420// This allows us to exercise all methods on a CoinsViewOverlay, while also421// ensuring that nothing can mutate the underlying cache until Flush or Sync is422// called.423FUZZ_TARGET(coins_view_overlay, .init = initialize_coins_view)424{425SeedRandomStateForTest(SeedRand::ZEROS); // for SaltedCoinsCacheHasher426StartPoolIfNeeded();427FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};428MutationGuardCoinsViewCache backend_cache{&CoinsViewEmpty::Get(), /*deterministic=*/true};429CoinsViewOverlay coins_view_cache{&backend_cache, g_thread_pool, /*deterministic=*/true};430CBlock block{BuildRandomBlock(fuzzed_data_provider, backend_cache)};431const auto reset_guard{coins_view_cache.StartFetching(block)};432TestCoinsView(fuzzed_data_provider, coins_view_cache, &backend_cache);433}435FUZZ_TARGET(coins_view_stacked, .init = initialize_coins_view)436{437SeedRandomStateForTest(SeedRand::ZEROS); // for SaltedCoinsCacheHasher438StartPoolIfNeeded();439FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};440auto db_params = DBParams{441.path = "",442.cache_bytes = 1_MiB,443.memory_only = true,444};445CCoinsViewDB backend_base_coins_view{std::move(db_params), CoinsViewOptions{}};446CCoinsViewCache backend_cache{&backend_base_coins_view, /*deterministic=*/true};447TestCoinsView(fuzzed_data_provider, backend_cache, &backend_base_coins_view);448CoinsViewOverlay coins_view_cache{&backend_cache, g_thread_pool, /*deterministic=*/true};449CBlock block{BuildRandomBlock(fuzzed_data_provider, backend_base_coins_view)};450{451const auto reset_guard{coins_view_cache.StartFetching(block)};452TestCoinsView(fuzzed_data_provider, coins_view_cache, &backend_cache);453}454TestCoinsView(fuzzed_data_provider, backend_cache, &backend_base_coins_view);455}
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.