#!/usr/bin/env python3 # Copyright (c) 2020-present The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """ Test that the proper port is used for -externalip= """ from test_framework.test_framework import BitcoinTestFramework, SkipTest from test_framework.test_node import ( FailedToStartError, ) from test_framework.util import assert_equal, p2p_port # We need to bind to a routable address for this test to exercise the relevant # code. Those addresses must be on an interface that is UP and is not a loopback # interface (IFF_LOOPBACK). # To set these routable addresses on the machine, use: # Linux: # First find your interfaces: ip addr show # Then use your actual interface names (replace INTERFACE_NAME with yours): # ip addr add 1.1.1.5/32 dev INTERFACE_NAME # to set up # ip addr del 1.1.1.5/32 dev INTERFACE_NAME # to remove it # FreeBSD and MacOS: # ifconfig INTERFACE_NAME 1.1.1.5/32 alias # to set up # ifconfig INTERFACE_NAME 1.1.1.5 -alias # to remove it, after the test ADDR = '1.1.1.5' # This is set in the CI environment, don't change it just here (keep them in sync). # array of tuples [arguments, expected port in localaddresses] EXPECTED = [ [['-externalip=2.2.2.2', '-port=30001'], 30001], [['-externalip=2.2.2.2', '-port=30002', f'-bind={ADDR}'], 30002], [['-externalip=2.2.2.2', f'-bind={ADDR}'], 'default_p2p_port'], [['-externalip=2.2.2.2', '-port=30003', f'-bind={ADDR}:30004'], 30004], [['-externalip=2.2.2.2', f'-bind={ADDR}:30005'], 30005], [['-externalip=2.2.2.2:30006', '-port=30007'], 30006], [['-externalip=2.2.2.2:30008', '-port=30009', f'-bind={ADDR}'], 30008], [['-externalip=2.2.2.2:30010', f'-bind={ADDR}'], 30010], [['-externalip=2.2.2.2:30011', '-port=30012', f'-bind={ADDR}:30013'], 30011], [['-externalip=2.2.2.2:30014', f'-bind={ADDR}:30015'], 30014], [['-externalip=2.2.2.2', '-port=30016', f'-bind={ADDR}:30017', f'-whitebind={ADDR}:30018'], 30017], [['-externalip=2.2.2.2', '-port=30019', f'-whitebind={ADDR}:30020'], 30020], ] class BindPortExternalIPTest(BitcoinTestFramework): def set_test_params(self): # Avoid any -bind= on the command line. Force the framework to avoid adding -bind=127.0.0.1. self.setup_clean_chain = True self.bind_to_localhost_only = False self.num_nodes = len(EXPECTED) self.extra_args = list(map(lambda e: e[0], EXPECTED)) def setup_network(self): self.setup_nodes() def setup_nodes(self): self.add_nodes(self.num_nodes, self.extra_args) # TestNode.start() will add -bind= to extra_args if has_explicit_bind is # False. We do not want any -bind= thus set has_explicit_bind to True. for node in self.nodes: node.has_explicit_bind = True try: self.start_nodes() except FailedToStartError as e: self.cleanup_partially_started_nodes() if 'Unable to bind to ' in str(e): raise SkipTest( f'To run this test make sure that {ADDR} ' '(routable address) is assigned to non-loopback ' 'interface on this machine') raise def run_test(self): self.log.info("Test the proper port is used for -externalip=") for i in range(len(EXPECTED)): expected_port = EXPECTED[i][1] if expected_port == 'default_p2p_port': expected_port = p2p_port(i) found = False for local in self.nodes[i].getnetworkinfo()['localaddresses']: if local['address'] == '2.2.2.2': assert_equal(local['port'], expected_port) found = True break assert found if __name__ == '__main__': BindPortExternalIPTest(__file__).main()