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) 2022-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"""6Test encrypted v2 p2p proposed in BIP 3247"""8from test_framework.blocktools import (9create_block,10)11from test_framework.p2p import (12P2PDataStore,13P2PInterface,14)15from test_framework.test_framework import BitcoinTestFramework16from test_framework.util import (17assert_equal,18assert_greater_than,19check_node_connections,20)21from test_framework.crypto.chacha20 import REKEY_INTERVAL24class P2PEncrypted(BitcoinTestFramework):25def set_test_params(self):26self.num_nodes = 227self.extra_args = [["-v2transport=1"], ["-v2transport=1"]]29def setup_network(self):30self.setup_nodes()32def generate_blocks(self, node, number):33test_blocks = []34last_block = node.getbestblockhash()35tip = int(last_block, 16)36tipheight = node.getblockcount()37last_block_time = node.getblock(last_block)['time']38for _ in range(number):39# Create some blocks40block = create_block(tip, height=tipheight + 1, ntime=last_block_time + 1)41block.solve()42test_blocks.append(block)43tip = block.hash_int44tipheight += 145last_block_time += 146return test_blocks48def create_test_block(self, txs):49block = create_block(self.tip, height=self.tipheight + 1, ntime=self.last_block_time + 600, txlist=txs)50block.solve()51return block53def run_test(self):54node0, node1 = self.nodes[0], self.nodes[1]55self.log.info("Check inbound connection to v2 TestNode from v2 P2PConnection is v2")56peer1 = node0.add_p2p_connection(P2PInterface(), wait_for_verack=True, supports_v2_p2p=True)57assert peer1.supports_v2_p2p58assert_equal(node0.getpeerinfo()[-1]["transport_protocol_type"], "v2")60self.log.info("Check inbound connection to v2 TestNode from v1 P2PConnection is v1")61peer2 = node0.add_p2p_connection(P2PInterface(), wait_for_verack=True, supports_v2_p2p=False)62assert not peer2.supports_v2_p2p63assert_equal(node0.getpeerinfo()[-1]["transport_protocol_type"], "v1")65self.log.info("Check outbound connection from v2 TestNode to v1 P2PConnection advertised as v1 is v1")66peer3 = node0.add_outbound_p2p_connection(P2PInterface(), p2p_idx=0, supports_v2_p2p=False, advertise_v2_p2p=False)67assert not peer3.supports_v2_p2p68assert_equal(node0.getpeerinfo()[-1]["transport_protocol_type"], "v1")70# v2 TestNode performs downgrading here71self.log.info("Check outbound connection from v2 TestNode to v1 P2PConnection advertised as v2 is v1")72peer4 = node0.add_outbound_p2p_connection(P2PInterface(), p2p_idx=1, supports_v2_p2p=False, advertise_v2_p2p=True)73assert not peer4.supports_v2_p2p74assert_equal(node0.getpeerinfo()[-1]["transport_protocol_type"], "v1")76self.log.info("Check outbound connection from v2 TestNode to v2 P2PConnection advertised as v2 is v2")77peer5 = node0.add_outbound_p2p_connection(P2PInterface(), p2p_idx=2, supports_v2_p2p=True, advertise_v2_p2p=True)78assert peer5.supports_v2_p2p79assert_equal(node0.getpeerinfo()[-1]["transport_protocol_type"], "v2")81self.log.info("Check if version is sent and verack is received in inbound/outbound connections")82assert_equal(len(node0.getpeerinfo()), 5) # check if above 5 connections are present in node0's getpeerinfo()83for peer in node0.getpeerinfo():84assert_greater_than(peer['bytessent_per_msg']['version'], 0)85assert_greater_than(peer['bytesrecv_per_msg']['verack'], 0)87self.log.info("Testing whether blocks propagate - check if tips sync when number of blocks >= REKEY_INTERVAL")88# tests whether rekeying (which happens every REKEY_INTERVAL packets) works correctly89test_blocks = self.generate_blocks(node0, REKEY_INTERVAL+1)91for i in range(2):92peer6 = node0.add_p2p_connection(P2PDataStore(), supports_v2_p2p=True)93assert peer6.supports_v2_p2p94assert_equal(node0.getpeerinfo()[-1]["transport_protocol_type"], "v2")96# Consider: node0 <-- peer6. node0 and node1 aren't connected here.97# Construct the following topology: node1 <--> node0 <-- peer698# and test that blocks produced by peer6 will be received by node1 if sent normally99# and won't be received by node1 if sent as decoy messages101# First, check whether blocks produced be peer6 are received by node0 if sent normally102# and not received by node0 if sent as decoy messages.103if i:104# check that node0 receives blocks produced by peer6105self.log.info("Check if blocks produced by node0's p2p connection is received by node0")106peer6.send_blocks_and_test(test_blocks, node0, success=True) # node0's tip advances107else:108# check that node0 doesn't receive blocks produced by peer6 since they are sent as decoy messages109self.log.info("Check if blocks produced by node0's p2p connection sent as decoys aren't received by node0")110peer6.send_blocks_and_test(test_blocks, node0, success=False, is_decoy=True) # node0's tip doesn't advance112# Then, connect node0 and node1 using v2 and check whether the blocks are received by node1113self.connect_nodes(0, 1, peer_advertises_v2=True)114self.log.info("Wait for node1 to receive all the blocks from node0")115self.sync_all()116self.log.info("Make sure node0 and node1 have same block tips")117assert_equal(node0.getbestblockhash(), node1.getbestblockhash())119self.disconnect_nodes(0, 1)121self.log.info("Check the connections opened as expected")122check_node_connections(node=node0, num_in=4, num_out=3)124self.log.info("Check inbound connection to v1 TestNode from v2 P2PConnection is v1")125self.restart_node(0, ["-v2transport=0"])126peer1 = node0.add_p2p_connection(P2PInterface(), wait_for_verack=True, supports_v2_p2p=True)127assert not peer1.supports_v2_p2p128assert_equal(node0.getpeerinfo()[-1]["transport_protocol_type"], "v1")129check_node_connections(node=node0, num_in=1, num_out=0)132if __name__ == '__main__':133P2PEncrypted(__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.