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) 2015-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 the preciousblock RPC."""7from test_framework.test_framework import BitcoinTestFramework8from test_framework.util import (9assert_not_equal,10assert_equal,11)13def unidirectional_node_sync_via_rpc(node_src, node_dest):14blocks_to_copy = []15blockhash = node_src.getbestblockhash()16while True:17try:18assert len(node_dest.getblock(blockhash, False)) > 019break20except Exception:21blocks_to_copy.append(blockhash)22blockhash = node_src.getblockheader(blockhash, True)['previousblockhash']23blocks_to_copy.reverse()24for blockhash in blocks_to_copy:25blockdata = node_src.getblock(blockhash, False)26assert node_dest.submitblock(blockdata) in (None, 'inconclusive')28def node_sync_via_rpc(nodes):29for node_src in nodes:30for node_dest in nodes:31if node_src is node_dest:32continue33unidirectional_node_sync_via_rpc(node_src, node_dest)35class PreciousTest(BitcoinTestFramework):36def set_test_params(self):37self.setup_clean_chain = True38self.num_nodes = 340def setup_network(self):41self.setup_nodes()43def run_test(self):44self.log.info("Ensure submitblock can in principle reorg to a competing chain")45self.generate(self.nodes[0], 1, sync_fun=self.no_op)46assert_equal(self.nodes[0].getblockcount(), 1)47hashZ = self.generate(self.nodes[1], 2, sync_fun=self.no_op)[-1]48assert_equal(self.nodes[1].getblockcount(), 2)49node_sync_via_rpc(self.nodes[0:3])50assert_equal(self.nodes[0].getbestblockhash(), hashZ)52self.log.info("Mine blocks A-B-C on Node 0")53hashC = self.generate(self.nodes[0], 3, sync_fun=self.no_op)[-1]54assert_equal(self.nodes[0].getblockcount(), 5)55self.log.info("Mine competing blocks E-F-G on Node 1")56hashG = self.generate(self.nodes[1], 3, sync_fun=self.no_op)[-1]57assert_equal(self.nodes[1].getblockcount(), 5)58assert_not_equal(hashC, hashG)59self.log.info("Connect nodes and check no reorg occurs")60# Submit competing blocks via RPC so any reorg should occur before we proceed (no way to wait on inaction for p2p sync)61node_sync_via_rpc(self.nodes[0:2])62self.connect_nodes(0, 1)63assert_equal(self.nodes[0].getbestblockhash(), hashC)64assert_equal(self.nodes[1].getbestblockhash(), hashG)65self.log.info("Make Node0 prefer block G")66self.nodes[0].preciousblock(hashG)67assert_equal(self.nodes[0].getbestblockhash(), hashG)68self.log.info("Make Node0 prefer block C again")69self.nodes[0].preciousblock(hashC)70assert_equal(self.nodes[0].getbestblockhash(), hashC)71self.log.info("Make Node1 prefer block C")72self.nodes[1].preciousblock(hashC)73self.sync_blocks(self.nodes[0:2]) # wait because node 1 may not have downloaded hashC74assert_equal(self.nodes[1].getbestblockhash(), hashC)75self.log.info("Make Node1 prefer block G again")76self.nodes[1].preciousblock(hashG)77assert_equal(self.nodes[1].getbestblockhash(), hashG)78self.log.info("Make Node0 prefer block G again")79self.nodes[0].preciousblock(hashG)80assert_equal(self.nodes[0].getbestblockhash(), hashG)81self.log.info("Make Node1 prefer block C again")82self.nodes[1].preciousblock(hashC)83assert_equal(self.nodes[1].getbestblockhash(), hashC)84self.log.info("Mine another block (E-F-G-)H on Node 0 and reorg Node 1")85self.generate(self.nodes[0], 1, sync_fun=self.no_op)86assert_equal(self.nodes[0].getblockcount(), 6)87self.sync_blocks(self.nodes[0:2])88hashH = self.nodes[0].getbestblockhash()89assert_equal(self.nodes[1].getbestblockhash(), hashH)90self.log.info("Node1 should not be able to prefer block C anymore")91self.nodes[1].preciousblock(hashC)92assert_equal(self.nodes[1].getbestblockhash(), hashH)93self.log.info("Mine competing blocks I-J-K-L on Node 2")94self.generate(self.nodes[2], 4, sync_fun=self.no_op)95assert_equal(self.nodes[2].getblockcount(), 6)96hashL = self.nodes[2].getbestblockhash()97self.log.info("Connect nodes and check no reorg occurs")98node_sync_via_rpc(self.nodes[1:3])99self.connect_nodes(1, 2)100self.connect_nodes(0, 2)101assert_equal(self.nodes[0].getbestblockhash(), hashH)102assert_equal(self.nodes[1].getbestblockhash(), hashH)103assert_equal(self.nodes[2].getbestblockhash(), hashL)104self.log.info("Make Node1 prefer block L")105self.nodes[1].preciousblock(hashL)106assert_equal(self.nodes[1].getbestblockhash(), hashL)107self.log.info("Make Node2 prefer block H")108self.nodes[2].preciousblock(hashH)109assert_equal(self.nodes[2].getbestblockhash(), hashH)111if __name__ == '__main__':112PreciousTest(__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.