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{252std::vector<FixedCheck> vChecks;253vChecks.resize(100, FixedCheck(std::nullopt));254vChecks[99] = FixedCheck(end_fails ? std::make_optional<int>(2) : std::nullopt);255control.Add(std::move(vChecks));256}257bool r = !control.Complete().has_value();258BOOST_REQUIRE(r != end_fails);259}260}261}263// Test that unique checks are actually all called individually, rather than264// just one check being called repeatedly. Test that checks are not called265// more than once as well266BOOST_AUTO_TEST_CASE(test_CheckQueue_UniqueCheck)267{268auto queue = std::make_unique<Unique_Queue>(QUEUE_BATCH_SIZE, SCRIPT_CHECK_THREADS);269size_t COUNT = 100000;270size_t total = COUNT;271{272CCheckQueueControl<UniqueCheck> control(*queue);273while (total) {274size_t r = m_rng.randrange(10);275std::vector<UniqueCheck> vChecks;276for (size_t k = 0; k < r && total; k++)277vChecks.emplace_back(--total);278control.Add(std::move(vChecks));279}280}281{282LOCK(UniqueCheck::m);283bool r = true;284BOOST_REQUIRE_EQUAL(UniqueCheck::results.size(), COUNT);285for (size_t i = 0; i < COUNT; ++i) {286r = r && UniqueCheck::results.count(i) == 1;287}288BOOST_REQUIRE(r);289}290}293// Test that blocks which might allocate lots of memory free their memory aggressively.294//295// This test attempts to catch a pathological case where by lazily freeing296// checks might mean leaving a check un-swapped out, and decreasing by 1 each297// time could leave the data hanging across a sequence of blocks.298BOOST_AUTO_TEST_CASE(test_CheckQueue_Memory)299{300auto queue = std::make_unique<Memory_Queue>(QUEUE_BATCH_SIZE, SCRIPT_CHECK_THREADS);301for (size_t i = 0; i < 1000; ++i) {302size_t total = i;303{304CCheckQueueControl<MemoryCheck> control(*queue);305while (total) {306size_t r = m_rng.randrange(10);307std::vector<MemoryCheck> vChecks;308for (size_t k = 0; k < r && total; k++) {309total--;310// Each iteration leaves data at the front, back, and middle311// to catch any sort of deallocation failure312vChecks.emplace_back(total == 0 || total == i || total == i/2);313}314control.Add(std::move(vChecks));315}316}317BOOST_REQUIRE_EQUAL(MemoryCheck::fake_allocated_memory, 0U);318}319}321// Test that a new verification cannot occur until all checks322// have been destructed323BOOST_AUTO_TEST_CASE(test_CheckQueue_FrozenCleanup)324{325auto queue = std::make_unique<FrozenCleanup_Queue>(QUEUE_BATCH_SIZE, SCRIPT_CHECK_THREADS);326bool fails = false;327std::thread t0([&]() {328CCheckQueueControl<FrozenCleanupCheck> control(*queue);329std::vector<FrozenCleanupCheck> vChecks(1);330control.Add(std::move(vChecks));331auto result = control.Complete(); // Hangs here332assert(!result);333});334{335std::unique_lock<std::mutex> l(FrozenCleanupCheck::m);336// Wait until the queue has finished all jobs and frozen337FrozenCleanupCheck::cv.wait(l, [](){return FrozenCleanupCheck::nFrozen == 1;});338}339// Try to get control of the queue a bunch of times340for (auto x = 0; x < 100 && !fails; ++x) {341fails = queue->m_control_mutex.try_lock();342}343{344// Unfreeze (we need lock n case of spurious wakeup)345std::unique_lock<std::mutex> l(FrozenCleanupCheck::m);346FrozenCleanupCheck::nFrozen = 0;347}348// Awaken frozen destructor349FrozenCleanupCheck::cv.notify_one();350// Wait for control to finish351t0.join();352BOOST_REQUIRE(!fails);353}356/** Test that CCheckQueueControl is threadsafe */357BOOST_AUTO_TEST_CASE(test_CheckQueueControl_Locks)358{359auto queue = std::make_unique<Standard_Queue>(QUEUE_BATCH_SIZE, SCRIPT_CHECK_THREADS);360{361std::vector<std::thread> tg;362tg.reserve(3);363std::atomic<int> nThreads {0};364std::atomic<int> fails {0};365for (size_t i = 0; i < 3; ++i) {366tg.emplace_back(367[&]{368CCheckQueueControl<FakeCheck> control(*queue);369// While sleeping, no other thread should execute to this point370auto observed = ++nThreads;371UninterruptibleSleep(std::chrono::milliseconds{10});372fails += observed != nThreads;373});374}375for (auto& thread: tg) {376if (thread.joinable()) thread.join();377}378BOOST_REQUIRE_EQUAL(fails, 0);379}380{381std::vector<std::thread> tg;382std::mutex m;383std::condition_variable cv;384bool has_lock{false};385bool has_tried{false};386bool done{false};387bool done_ack{false};388{389std::unique_lock<std::mutex> l(m);390tg.emplace_back([&]{391CCheckQueueControl<FakeCheck> control(*queue);392std::unique_lock<std::mutex> ll(m);393has_lock = true;394cv.notify_one();395cv.wait(ll, [&]{return has_tried;});396done = true;397cv.notify_one();398// Wait until the done is acknowledged399//400cv.wait(ll, [&]{return done_ack;});401});402// Wait for thread to get the lock403cv.wait(l, [&](){return has_lock;});404bool fails = false;405for (auto x = 0; x < 100 && !fails; ++x) {406fails = queue->m_control_mutex.try_lock();407}408has_tried = true;409cv.notify_one();410cv.wait(l, [&](){return done;});411// Acknowledge the done412done_ack = true;413cv.notify_one();414BOOST_REQUIRE(!fails);415}416for (auto& thread: tg) {417if (thread.joinable()) thread.join();418}419}420}421BOOST_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.