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.
251size_t count_stale = 0;252/** elements that were most recently inserted */253size_t count_fresh = 0;255for (uint32_t i = 0; i < (n_insert / 4); ++i)256count_erased_but_contained += set.contains(hashes[i], false);257for (uint32_t i = (n_insert / 4); i < (n_insert / 2); ++i)258count_stale += set.contains(hashes[i], false);259for (uint32_t i = (n_insert / 2); i < n_insert; ++i)260count_fresh += set.contains(hashes[i], false);262double hit_rate_erased_but_contained = double(count_erased_but_contained) / (double(n_insert) / 4.0);263double hit_rate_stale = double(count_stale) / (double(n_insert) / 4.0);264double hit_rate_fresh = double(count_fresh) / (double(n_insert) / 2.0);266// Check that our hit_rate_fresh is perfect267BOOST_CHECK_EQUAL(hit_rate_fresh, 1.0);268// Check that we have a more than 2x better hit rate on stale elements than269// erased elements.270BOOST_CHECK(hit_rate_stale > 2 * hit_rate_erased_but_contained);271}272}; // struct EraseParallelTest273BOOST_FIXTURE_TEST_CASE(cuckoocache_erase_parallel_ok, EraseParallelTest)274{275test_cache_erase_parallel<CuckooCache::cache<uint256, SignatureCacheHasher>>(4_MiB);276}279struct GenerationsTest : BasicTestingSetup {280template <typename Cache>281void test_cache_generations()282{283// This test checks that for a simulation of network activity, the fresh hit284// rate is never below 99%, and the number of times that it is worse than285// 99.9% are less than 1% of the time.286double min_hit_rate = 0.99;287double tight_hit_rate = 0.999;288double max_rate_less_than_tight_hit_rate = 0.01;289// A cache that meets this specification is therefore shown to have a hit290// rate of at least tight_hit_rate * (1 - max_rate_less_than_tight_hit_rate) +291// min_hit_rate*max_rate_less_than_tight_hit_rate = 0.999*99%+0.99*1% == 99.89%292// hit rate with low variance.294// We use deterministic values, but this test has also passed on many295// iterations with non-deterministic values, so it isn't "overfit" to the296// specific entropy in FastRandomContext(true) and implementation of the297// cache.298SeedRandomForTest(SeedRand::ZEROS);300// block_activity models a chunk of network activity. n_insert elements are301// added to the cache. The first and last n/4 are stored for removal later302// and the middle n/2 are not stored. This models a network which uses half303// the signatures of recently (since the last block) added transactions304// immediately and never uses the other half.305struct block_activity {306std::vector<uint256> reads;307block_activity(uint32_t n_insert, FastRandomContext& rng, Cache& c)308{309std::vector<uint256> inserts;310inserts.resize(n_insert);311reads.reserve(n_insert / 2);312for (uint32_t i = 0; i < n_insert; ++i) {313uint32_t* ptr = (uint32_t*)inserts[i].begin();314for (uint8_t j = 0; j < 8; ++j)315*(ptr++) = rng.rand32();316}317for (uint32_t i = 0; i < n_insert / 4; ++i)318reads.push_back(inserts[i]);319for (uint32_t i = n_insert - (n_insert / 4); i < n_insert; ++i)320reads.push_back(inserts[i]);321for (const auto& h : inserts)322c.insert(h);323}324};326const uint32_t BLOCK_SIZE = 1000;327// We expect window size 60 to perform reasonably given that each epoch328// stores 45% of the cache size (~472k).329const uint32_t WINDOW_SIZE = 60;330const uint32_t POP_AMOUNT = (BLOCK_SIZE / WINDOW_SIZE) / 2;331const double load = 10;332const size_t bytes{4_MiB};333const uint32_t n_insert = static_cast<uint32_t>(load * (bytes / sizeof(uint256)));335std::vector<block_activity> hashes;336Cache set{};337set.setup_bytes(bytes);338hashes.reserve(n_insert / BLOCK_SIZE);339std::deque<block_activity> last_few;340uint32_t out_of_tight_tolerance = 0;341uint32_t total = n_insert / BLOCK_SIZE;342// we use the deque last_few to model a sliding window of blocks. at each343// step, each of the last WINDOW_SIZE block_activities checks the cache for344// POP_AMOUNT of the hashes that they inserted, and marks these erased.345for (uint32_t i = 0; i < total; ++i) {346if (last_few.size() == WINDOW_SIZE)347last_few.pop_front();348last_few.emplace_back(BLOCK_SIZE, m_rng, set);349uint32_t count = 0;350for (auto& act : last_few)351for (uint32_t k = 0; k < POP_AMOUNT; ++k) {352count += set.contains(act.reads.back(), true);353act.reads.pop_back();354}355// We use last_few.size() rather than WINDOW_SIZE for the correct356// behavior on the first WINDOW_SIZE iterations where the deque is not357// full yet.358double hit = (double(count)) / (last_few.size() * POP_AMOUNT);359// Loose Check that hit rate is above min_hit_rate360BOOST_CHECK(hit > min_hit_rate);361// Tighter check, count number of times we are less than tight_hit_rate362// (and implicitly, greater than min_hit_rate)363out_of_tight_tolerance += hit < tight_hit_rate;364}365// Check that being out of tolerance happens less than366// max_rate_less_than_tight_hit_rate of the time367BOOST_CHECK(double(out_of_tight_tolerance) / double(total) < max_rate_less_than_tight_hit_rate);368}369}; // struct GenerationsTest370BOOST_FIXTURE_TEST_CASE(cuckoocache_generations, GenerationsTest)371{372test_cache_generations<CuckooCache::cache<uint256, SignatureCacheHasher>>();373}375BOOST_AUTO_TEST_SUITE_END();
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.