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.
1#!/usr/bin/env python32# Copyright (c) 2017-present The Bitcoin Core developers3# Distributed under the MIT software license, see the accompanying4# file COPYING or http://www.opensource.org/licenses/mit-license.php.5"""Test logic for setting nMinimumChainWork on command line.7Nodes don't consider themselves out of "initial block download" until8their active chain has more work than nMinimumChainWork.10Nodes don't download blocks from a peer unless the peer's best known block11has more work than nMinimumChainWork.13While in initial block download, nodes won't relay blocks to their peers, so14test that this parameter functions as intended by verifying that block relay15only succeeds past a given node once its nMinimumChainWork has been exceeded.16"""18import time20from test_framework.p2p import P2PInterface, msg_getheaders21from test_framework.test_framework import BitcoinTestFramework22from test_framework.util import (23assert_equal,24ensure_for,25assert_not_equal,26)28# 2 hashes required per regtest block (with no difficulty adjustment)29REGTEST_WORK_PER_BLOCK = 231class MinimumChainWorkTest(BitcoinTestFramework):32def set_test_params(self):33self.setup_clean_chain = True34self.num_nodes = 336self.extra_args = [[], ["-minimumchainwork=0x65"], ["-minimumchainwork=0x65"]]37self.node_min_work = [0, 101, 101]39def setup_network(self):40# This test relies on the chain setup being:41# node0 <- node1 <- node242# Before leaving IBD, nodes prefer to download blocks from outbound43# peers, so ensure that we're mining on an outbound peer and testing44# block relay to inbound peers.45self.setup_nodes()46for i in range(self.num_nodes-1):47self.connect_nodes(i+1, i)49# Set clock of node2 2 days ahead, to keep it in IBD during this test.50self.nodes[2].setmocktime(int(time.time()) + 48*60*60)52def run_test(self):53# Start building a chain on node0. node2 shouldn't be able to sync until node1's54# minchainwork is exceeded55starting_chain_work = REGTEST_WORK_PER_BLOCK # Genesis block's work56self.log.info(f"Testing relay across node 1 (minChainWork = {self.node_min_work[1]})")58starting_blockcount = self.nodes[2].getblockcount()60num_blocks_to_generate = int((self.node_min_work[1] - starting_chain_work) / REGTEST_WORK_PER_BLOCK)61self.log.info(f"Generating {num_blocks_to_generate} blocks on node0")62hashes = self.generate(self.nodes[0], num_blocks_to_generate, sync_fun=self.no_op)64self.log.info(f"Node0 current chain work: {self.nodes[0].getblockheader(hashes[-1])['chainwork']}")65self.log.info("Verifying node 2 has no more blocks than before")66self.log.info(f"Blockcounts: {[n.getblockcount() for n in self.nodes]}")67# Node2 shouldn't have any new headers yet, because node1 should not68# have relayed anything.69# We wait 3 seconds, rather than sync_blocks(node0, node1) because70# it's reasonable either way for node1 to get the blocks, or not get71# them (since they're below node1's minchainwork).72ensure_for(duration=3, f=lambda: len(self.nodes[2].getchaintips()) == 1)73assert_equal(self.nodes[2].getchaintips()[0]['height'], 0)75assert_not_equal(self.nodes[1].getbestblockhash(), self.nodes[0].getbestblockhash())76assert_equal(self.nodes[2].getblockcount(), starting_blockcount)78self.log.info("Check that getheaders requests to node2 are ignored")79peer = self.nodes[2].add_p2p_connection(P2PInterface())80msg = msg_getheaders()81msg.locator.vHave = [int(self.nodes[2].getbestblockhash(), 16)]82msg.hashstop = 083peer.send_and_ping(msg)84ensure_for(duration=5, f=lambda: "headers" not in peer.last_message or len(peer.last_message["headers"].headers) == 0)86self.log.info("Generating one more block")87self.generate(self.nodes[0], 1)89self.log.info("Verifying nodes are all synced")91# Because nodes in regtest are all manual connections (eg using92# addnode), node1 should not have disconnected node0. If not for that,93# we'd expect node1 to have disconnected node0 for serving an94# insufficient work chain, in which case we'd need to reconnect them to95# continue the test.97self.sync_all()98self.log.info(f"Blockcounts: {[n.getblockcount() for n in self.nodes]}")100self.log.info("Test that getheaders requests to node2 are not ignored")101peer.send_and_ping(msg)102assert "headers" in peer.last_message104# Verify that node2 is in fact still in IBD (otherwise this test may105# not be exercising the logic we want!)106assert_equal(self.nodes[2].getblockchaininfo()['initialblockdownload'], True)108self.log.info("Test -minimumchainwork with a non-hex value")109self.stop_node(0)110self.nodes[0].assert_start_raises_init_error(111["-minimumchainwork=test"],112expected_msg='Error: Invalid minimum work specified (test), must be up to 64 hex digits',113)116if __name__ == '__main__':117MinimumChainWorkTest(__file__).main()
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.