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.
251BasicTestingSetup::~BasicTestingSetup()252{253m_node.ecc_context.reset();254m_node.kernel.reset();255if (!EnableFuzzDeterminism()) {256SetMockTime(0s); // Reset mocktime for following tests257}258LogInstance().DisconnectTestLogger();259if (m_has_custom_datadir) {260// Only remove the lock file, preserve the data directory.261UnlockDirectory(m_path_lock, ".lock");262fs::remove(m_path_lock / ".lock");263} else {264fs::remove_all(m_path_root);265}266// Clear all arguments except for -datadir, which GUI tests currently rely267// on to be set even after the testing setup is destroyed.268gArgs.ClearArgs();269gArgs.ForceSetArg("-datadir", fs::PathToString(m_path_root));270}272ChainTestingSetup::ChainTestingSetup(const ChainType chainType, TestOpts opts)273: BasicTestingSetup(chainType, opts)274{275const CChainParams& chainparams = Params();277// A task runner is required to prevent ActivateBestChain278// from blocking due to queue overrun.279if (opts.setup_validation_interface) {280m_node.scheduler = std::make_unique<CScheduler>();281m_node.scheduler->m_service_thread = std::thread(util::TraceThread, "scheduler", [&] { m_node.scheduler->serviceQueue(); });282m_node.validation_signals =283// Use synchronous task runner while fuzzing to avoid non-determinism284EnableFuzzDeterminism() ?285std::make_unique<ValidationSignals>(std::make_unique<util::ImmediateTaskRunner>()) :286std::make_unique<ValidationSignals>(std::make_unique<SerialTaskRunner>(*m_node.scheduler));287{288// Ensure deterministic coverage by waiting for m_service_thread to be running289std::promise<void> promise;290m_node.scheduler->scheduleFromNow([&promise] { promise.set_value(); }, 0ms);291promise.get_future().wait();292}293}295bilingual_str error{};296m_node.mempool = std::make_unique<CTxMemPool>(MemPoolOptionsForTest(m_node), error);297Assert(error.empty());298m_node.warnings = std::make_unique<node::Warnings>();300m_node.notifications = std::make_unique<KernelNotifications>(Assert(m_node.shutdown_request), m_node.exit_status, *Assert(m_node.warnings));302m_make_chainman = [this, &chainparams, opts] {303Assert(!m_node.chainman);304ChainstateManager::Options chainman_opts{305.chainparams = chainparams,306.datadir = m_args.GetDataDirNet(),307.check_block_index = 1,308.notifications = *m_node.notifications,309.signals = m_node.validation_signals.get(),310// Use no worker threads while fuzzing to avoid racy non-determinism311// and dangling thread handles if AFL forks after initialization.312.worker_threads_num = EnableFuzzDeterminism() ? 0 : 2,313.prevoutfetch_threads_num = EnableFuzzDeterminism() ? 0 : 2,314};315if (opts.min_validation_cache) {316chainman_opts.script_execution_cache_bytes = 0;317chainman_opts.signature_cache_bytes = 0;318}319const BlockManager::Options blockman_opts{320.chainparams = chainman_opts.chainparams,321.blocks_dir = m_args.GetBlocksDirPath(),322.notifications = chainman_opts.notifications,323.block_tree_db_params = DBParams{324.path = m_args.GetDataDirNet() / "blocks" / "index",325.cache_bytes = m_kernel_cache_sizes.block_tree_db,326.memory_only = opts.block_tree_db_in_memory,327.wipe_data = m_args.GetBoolArg("-reindex", false),328},329};330m_node.chainman = std::make_unique<ChainstateManager>(*Assert(m_node.shutdown_signal), chainman_opts, blockman_opts);331};332m_make_chainman();333}335ChainTestingSetup::~ChainTestingSetup()336{337if (m_node.scheduler) m_node.scheduler->stop();338if (m_node.validation_signals) m_node.validation_signals->FlushBackgroundCallbacks();339m_node.connman.reset();340m_node.banman.reset();341m_node.addrman.reset();342m_node.netgroupman.reset();343m_node.args = nullptr;344m_node.mempool.reset();345Assert(!m_node.fee_estimator_man); // Each test must create a local object, if they wish to use the fee_estimator_man346m_node.chainman.reset();347m_node.validation_signals.reset();348m_node.scheduler.reset();349}351void ChainTestingSetup::LoadVerifyActivateChainstate()352{353auto& chainman{*Assert(m_node.chainman)};354node::ChainstateLoadOptions options;355options.mempool = Assert(m_node.mempool.get());356options.coins_db_in_memory = m_coins_db_in_memory;357options.wipe_chainstate_db = m_args.GetBoolArg("-reindex", false) || m_args.GetBoolArg("-reindex-chainstate", false);358options.prune = chainman.m_blockman.IsPruneMode();359options.check_blocks = m_args.GetIntArg("-checkblocks", DEFAULT_CHECKBLOCKS);360options.check_level = m_args.GetIntArg("-checklevel", DEFAULT_CHECKLEVEL);361options.require_full_verification = m_args.IsArgSet("-checkblocks") || m_args.IsArgSet("-checklevel");362auto [status, error] = LoadChainstate(chainman, m_kernel_cache_sizes, options);363assert(status == node::ChainstateLoadStatus::SUCCESS);365std::tie(status, error) = VerifyLoadedChainstate(chainman, options);366assert(status == node::ChainstateLoadStatus::SUCCESS);368m_node.notifications->setChainstateLoaded(true);370BlockValidationState state;371if (!chainman.ActiveChainstate().ActivateBestChain(state)) {372throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)", state.ToString()));373}374}376TestingSetup::TestingSetup(377const ChainType chainType,378TestOpts opts)379: ChainTestingSetup(chainType, opts)380{381m_coins_db_in_memory = opts.coins_db_in_memory;382m_block_tree_db_in_memory = opts.block_tree_db_in_memory;383// Ideally we'd move all the RPC tests to the functional testing framework384// instead of unit tests, but for now we need these here.385RegisterAllCoreRPCCommands(tableRPC);387LoadVerifyActivateChainstate();389if (!opts.setup_net) return;391m_node.netgroupman = std::make_unique<NetGroupManager>(NetGroupManager::NoAsmap());392m_node.addrman = std::make_unique<AddrMan>(*m_node.netgroupman,393/*deterministic=*/false,394m_node.args->GetIntArg("-checkaddrman", 0));395m_node.banman = std::make_unique<BanMan>(m_args.GetDataDirBase() / "banlist", nullptr, DEFAULT_MISBEHAVING_BANTIME);396m_node.connman = std::make_unique<ConnmanTestMsg>(0x1337, 0x1337, *m_node.addrman, *m_node.netgroupman, Params()); // Deterministic randomness for tests.397auto mining_args{node::ReadMiningArgs(*m_node.args)};398Assert(mining_args);399m_node.mining_args = std::move(*mining_args);400PeerManager::Options peerman_opts;401ApplyArgsManOptions(*m_node.args, peerman_opts);402peerman_opts.deterministic_rng = true;403m_node.peerman = PeerManager::make(*m_node.connman, *m_node.addrman,404m_node.banman.get(), *m_node.chainman,405*m_node.mempool, *m_node.warnings,406peerman_opts);408{409CConnman::Options options;410options.m_msgproc = m_node.peerman.get();411m_node.connman->Init(options);412}413}415TestChain100Setup::TestChain100Setup(416const ChainType chain_type,417TestOpts opts)418: TestingSetup{ChainType::REGTEST, opts}419{420constexpr std::array<unsigned char, 32> vchKey = {421{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}};422coinbaseKey.Set(vchKey.begin(), vchKey.end(), true);424// Generate a 100-block chain:425this->mineBlocks(COINBASE_MATURITY);427{428LOCK(::cs_main);429assert(430m_node.chainman->ActiveChain().Tip()->GetBlockHash().ToString() ==431"0ee6e270d6594249e548110619f7bd690695beb219b915da4a2e84e2b61ed60f");432}433}435void TestChain100Setup::mineBlocks(int num_blocks)436{437CScript scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;438for (int i = 0; i < num_blocks; i++) {439std::vector<CMutableTransaction> noTxns;440CBlock b = CreateAndProcessBlock(noTxns, scriptPubKey);441m_clock += 1s;442m_coinbase_txns.push_back(b.vtx[0]);443}444}446CBlock TestChain100Setup::CreateBlock(447const std::vector<CMutableTransaction>& txns,448const CScript& scriptPubKey)449{450auto mining{interfaces::MakeMining(m_node)};451auto block_template{mining->createNewBlock({452.use_mempool = false,453.coinbase_output_script = scriptPubKey,454}, /*cooldown=*/false)};455Assert(block_template);456CBlock block{block_template->getBlock()};458Assert(block.vtx.size() == 1);459for (const CMutableTransaction& tx : txns) {460block.vtx.push_back(MakeTransactionRef(tx));461}462RegenerateCommitments(block, *Assert(m_node.chainman));464while (!CheckProofOfWork(block.GetHash(), block.nBits, m_node.chainman->GetConsensus())) ++block.nNonce;466return block;467}469CBlock TestChain100Setup::CreateAndProcessBlock(470const std::vector<CMutableTransaction>& txns,471const CScript& scriptPubKey)472{473CBlock block = this->CreateBlock(txns, scriptPubKey);474std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(block);475Assert(m_node.chainman)->ProcessNewBlock(shared_pblock, true, true, nullptr);477return block;478}480std::pair<CMutableTransaction, CAmount> TestChain100Setup::CreateValidTransaction(const std::vector<CTransactionRef>& input_transactions,481const std::vector<COutPoint>& inputs,482int input_height,483const std::vector<CKey>& input_signing_keys,484const std::vector<CTxOut>& outputs,485const std::optional<CFeeRate>& feerate,486const std::optional<uint32_t>& fee_output)487{488CMutableTransaction mempool_txn;489mempool_txn.vin.reserve(inputs.size());490mempool_txn.vout.reserve(outputs.size());492for (const auto& outpoint : inputs) {493mempool_txn.vin.emplace_back(outpoint, CScript(), MAX_BIP125_RBF_SEQUENCE);494}495mempool_txn.vout = outputs;497// - Add the signing key to a keystore498FillableSigningProvider keystore;499for (const auto& input_signing_key : input_signing_keys) {500keystore.AddKey(input_signing_key);
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.