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 p2p permission message.7Test that permissions are correctly calculated and applied8"""10from test_framework.messages import (11SEQUENCE_FINAL,12)13from test_framework.p2p import P2PDataStore14from test_framework.test_node import ErrorMatch15from test_framework.test_framework import BitcoinTestFramework16from test_framework.util import (17append_config,18assert_equal,19p2p_port,20tor_port,21)22from test_framework.wallet import MiniWallet25class P2PPermissionsTests(BitcoinTestFramework):26def set_test_params(self):27self.num_nodes = 229def run_test(self):30self.wallet = MiniWallet(self.nodes[0])32self.check_tx_relay()34self.checkpermission(35# default permissions (no specific permissions)36["-whitelist=127.0.0.1"],37# Make sure the default values in the command line documentation match the ones here38["relay", "noban", "mempool", "download"])40self.checkpermission(41# no permission (even with forcerelay)42["[email protected]", "-whitelistforcerelay=1"],43[])45self.checkpermission(46# relay permission removed (no specific permissions)47["-whitelist=127.0.0.1", "-whitelistrelay=0"],48["noban", "mempool", "download"])50self.checkpermission(51# forcerelay and relay permission added52# Legacy parameter interaction which set whitelistrelay to true53# if whitelistforcerelay is true54["-whitelist=127.0.0.1", "-whitelistforcerelay"],55["forcerelay", "relay", "noban", "mempool", "download"])57# Let's make sure permissions are merged correctly58# For this, we need to use whitebind instead of bind59# by modifying the configuration file.60ip_port = "127.0.0.1:{}".format(p2p_port(1))61self.nodes[1].replace_in_config([("bind=127.0.0.1", "whitebind=bloomfilter,forcerelay@" + ip_port)])62# Explicitly bind the tor port to prevent collisions with the default tor port63append_config(self.nodes[1].datadir_path, [f"bind=127.0.0.1:{tor_port(self.nodes[1].index)}=onion"])64self.checkpermission(65["[email protected]"],66# Check parameter interaction forcerelay should activate relay67["noban", "bloomfilter", "forcerelay", "relay", "download"])68self.nodes[1].replace_in_config([("whitebind=bloomfilter,forcerelay@" + ip_port, "bind=127.0.0.1")])69self.nodes[1].replace_in_config([(f"bind=127.0.0.1:{tor_port(self.nodes[1].index)}=onion", "")])71self.checkpermission(72# legacy whitelistrelay should be ignored73["-whitelist=noban,[email protected]", "-whitelistrelay"],74["noban", "mempool", "download"])76self.checkpermission(77# legacy whitelistforcerelay should be ignored78["-whitelist=noban,[email protected]", "-whitelistforcerelay"],79["noban", "mempool", "download"])81self.checkpermission(82# missing mempool permission to be considered legacy whitelisted83["[email protected]"],84["noban", "download"])86self.checkpermission(87# all permission added88["[email protected]"],89["forcerelay", "noban", "mempool", "bloomfilter", "relay", "download", "addr"])91for flag, permissions in [(["-whitelist=noban,[email protected]"], ["noban", "download"]), (["[email protected]"], [])]:92self.restart_node(0, flag)93self.connect_nodes(0, 1)94peerinfo = self.nodes[0].getpeerinfo()[0]95assert_equal(peerinfo['permissions'], permissions)97self.stop_node(1)98self.nodes[1].assert_start_raises_init_error(["-whitelist=in,[email protected]"], "Only direction was set, no permissions", match=ErrorMatch.PARTIAL_REGEX)99self.nodes[1].assert_start_raises_init_error(["[email protected]"], "Invalid P2P permission", match=ErrorMatch.PARTIAL_REGEX)100self.nodes[1].assert_start_raises_init_error(["[email protected]:230"], "Invalid netmask specified in", match=ErrorMatch.PARTIAL_REGEX)101self.nodes[1].assert_start_raises_init_error(["[email protected]/10"], "Cannot resolve -whitebind address", match=ErrorMatch.PARTIAL_REGEX)102self.nodes[1].assert_start_raises_init_error(["[email protected]", "-bind=127.0.0.1", "-listen=0"], "Cannot set -bind or -whitebind together with -listen=0", match=ErrorMatch.PARTIAL_REGEX)104def check_tx_relay(self):105self.log.debug("Create a connection from a forcerelay peer that rebroadcasts raw txs")106# A test framework p2p connection is needed to send the raw transaction directly. If a full node was used, it could only107# rebroadcast via the inv-getdata mechanism. However, even for forcerelay connections, a full node would108# currently not request a txid that is already in the mempool.109self.restart_node(1, extra_args=["[email protected]"])110p2p_rebroadcast_wallet = self.nodes[1].add_p2p_connection(P2PDataStore())112self.log.debug("Send a tx from the wallet initially")113tx = self.wallet.create_self_transfer(sequence=SEQUENCE_FINAL)['tx']114txid = tx.txid_hex116self.log.debug("Wait until tx is in node[1]'s mempool")117p2p_rebroadcast_wallet.send_txs_and_test([tx], self.nodes[1])119self.log.debug("Check that node[1] will send the tx to node[0] even though it is already in the mempool")120self.connect_nodes(1, 0)121with self.nodes[1].assert_debug_log(["Force relaying tx {} (wtxid={}) from peer=0".format(txid, tx.wtxid_hex)]):122p2p_rebroadcast_wallet.send_txs_and_test([tx], self.nodes[1])123self.wait_until(lambda: txid in self.nodes[0].getrawmempool())125self.log.debug("Check that node[1] will not send an invalid tx to node[0]")126tx.vout[0].nValue += 1127# add dust to cause policy rejection but no disconnection128tx.vout.append(tx.vout[0])129tx.vout[-1].nValue = 0130txid = tx.txid_hex131# Send the transaction twice. The first time, it'll be rejected by ATMP because it conflicts132# with a mempool transaction. The second time, it'll be in the m_lazy_recent_rejects filter.133p2p_rebroadcast_wallet.send_txs_and_test(134[tx],135self.nodes[1],136success=False,137reject_reason='{} (wtxid={}) from peer=0 was not accepted: dust'.format(txid, tx.wtxid_hex)138)140p2p_rebroadcast_wallet.send_txs_and_test(141[tx],142self.nodes[1],143success=False,144reject_reason='Not relaying non-mempool transaction {} (wtxid={}) from forcerelay peer=0'.format(txid, tx.wtxid_hex)145)147def checkpermission(self, args, expectedPermissions):148self.restart_node(1, args)149self.connect_nodes(0, 1)150peerinfo = self.nodes[1].getpeerinfo()[0]151assert_equal(len(expectedPermissions), len(peerinfo['permissions']))152for p in expectedPermissions:153if p not in peerinfo['permissions']:154raise AssertionError("Expected permissions %r is not granted." % p)157if __name__ == '__main__':158P2PPermissionsTests(__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.