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) 2023-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.6from test_framework.test_framework import BitcoinTestFramework7from test_framework.messages import (8msg_version,9msg_filterload10)11from test_framework.p2p import (12P2PInterface,13P2P_SERVICES,14P2P_SUBVERSION,15P2P_VERSION,16)19class P2PConnectionLimits(BitcoinTestFramework):20def set_test_params(self):21self.num_nodes = 122# scenario : we have 2 inbound slots and allow a maximum of 1 tx-relaying inbound peer23self.extra_args = [['-maxconnections=13']] # 11 slots are reserved for outbounds, leaving 2 inbound slots25def run_test(self):26self.test_inbound_limits()28def create_blocks_only_version(self):29no_txrelay_version_msg = msg_version()30no_txrelay_version_msg.nVersion = P2P_VERSION31no_txrelay_version_msg.strSubVer = P2P_SUBVERSION32no_txrelay_version_msg.nServices = P2P_SERVICES33no_txrelay_version_msg.relay = 034return no_txrelay_version_msg36def create_no_services_blocks_only_version(self):37"""VERSION with relay=0 and nServices=0 to avoid block-relay eviction protection."""38version_msg = msg_version()39version_msg.nVersion = P2P_VERSION40version_msg.strSubVer = P2P_SUBVERSION41version_msg.nServices = 042version_msg.relay = 043return version_msg45def test_inbound_limits(self):46node = self.nodes[0]48self.log.info('Test with 2 inbound slots, one of which allows tx-relay')49node.add_p2p_connection(P2PInterface())51self.log.info('Connect a full-relay inbound peer - test that eviction is triggered')52# Since there is no unprotected peer to evict here, the new peer is dropped instead.53with node.assert_debug_log(['failed to find a tx-relaying eviction candidate - connection dropped'], timeout=2):54self.nodes[0].add_p2p_connection(P2PInterface(), expect_success=False, wait_for_verack=False)55self.wait_until(lambda: len(node.getpeerinfo()) == 1)56node.disconnect_p2ps()58self.log.info('Connect a block-relay inbound peer - test that second full relay peer is accepted')59peer1 = self.nodes[0].add_p2p_connection(P2PInterface(), send_version=False, wait_for_verack=False)60peer1.send_without_ping(self.create_blocks_only_version())61peer1.wait_for_verack()63node.add_p2p_connection(P2PInterface())64self.wait_until(lambda: len(node.getpeerinfo()) == 2)66self.log.info('Connecting another full-relay peer triggers non-specific eviction')67with node.assert_debug_log(['failed to find an eviction candidate - connection dropped (full)'], timeout=2):68self.nodes[0].add_p2p_connection(P2PInterface(), send_version=False, wait_for_verack=False, expect_success=False)69self.wait_until(lambda: len(node.getpeerinfo()) == 2)71self.log.info('Run with bloom filter support and check that a switch to tx relay during runtime can trigger eviction')72self.restart_node(0, ['-maxconnections=13', '-peerbloomfilters'])73peer1 = self.nodes[0].add_p2p_connection(P2PInterface(), send_version=False, wait_for_verack=False)74peer1.send_without_ping(self.create_blocks_only_version())75peer1.wait_for_verack()77node.add_p2p_connection(P2PInterface())78self.wait_until(lambda: len(node.getpeerinfo()) == 2)79with node.assert_debug_log(['connection dropped after filterload message'], timeout=2):80peer1.send_without_ping(msg_filterload(data=b'\xbb'*(100)))81self.wait_until(lambda: len(node.getpeerinfo()) == 1)83self.log.info('Test different values of inboundrelaypercent')84self.restart_node(0, ['-maxconnections=13', '-inboundrelaypercent=0'])85with node.assert_debug_log(['failed to find a tx-relaying eviction candidate - connection dropped'], timeout=2):86self.nodes[0].add_p2p_connection(P2PInterface(), expect_success=False, wait_for_verack=False)88self.restart_node(0, ['-maxconnections=13', '-inboundrelaypercent=100'])89node.add_p2p_connection(P2PInterface())90node.add_p2p_connection(P2PInterface())91self.wait_until(lambda: len(node.getpeerinfo()) == 2)93self.log.info('Test that EvictTxPeerIfFull only evicts tx-relaying peers')94NUM_BLOCK_RELAY_PEERS = 2195self.restart_node(0, ['-maxconnections=33', '-inboundrelaypercent=0'])96for _ in range(NUM_BLOCK_RELAY_PEERS):97p = self.nodes[0].add_p2p_connection(P2PInterface(), send_version=False, wait_for_verack=False)98p.send_without_ping(self.create_no_services_blocks_only_version())99p.wait_for_verack()100self.wait_until(lambda: len(node.getpeerinfo()) == NUM_BLOCK_RELAY_PEERS)102with node.assert_debug_log(['failed to find a tx-relaying eviction candidate - connection dropped'], timeout=5):103self.nodes[0].add_p2p_connection(P2PInterface(), expect_success=False, wait_for_verack=False)104self.wait_until(lambda: len(node.getpeerinfo()) == NUM_BLOCK_RELAY_PEERS)106if __name__ == '__main__':107P2PConnectionLimits(__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.