aboutsummaryrefslogtreecommitdiff
path: root/test/functional/test_framework
diff options
context:
space:
mode:
authorVasil Dimov <vd@FreeBSD.org>2021-08-13 10:33:24 +0200
committerVasil Dimov <vd@FreeBSD.org>2024-07-02 14:17:51 +0200
commitbca346a97056748f1e3fb899f336d56d9fd45a64 (patch)
tree5be42978181c13a4ae0534c4d646920dbf04a20f /test/functional/test_framework
parentaf552534ab83c572d3bc3f93ccaee5c1961ccab5 (diff)
net: require P2P binds to succeed
In the Tor case, this prevents us from telling the Tor daemon to send our incoming connections from the Tor network to an address where we do not listen (we tried to listen but failed probably because another application is already listening). In the other cases (IPv4/IPv6 binds) this also prevents unpleasant surprises caused by continuing operations even on bind failure. For example, another application may be listening on portX, bitcoind tries to bind on portX and portY, only succeeds with portY and continues operation leaving the user thinking that his bitcoind is listening on portX whereas another application is listening (the error message in the log could easily be missed). Avoid having the functional testing framework start multiple `bitcoind`s that try to listen on the same `127.0.0.1:18445` (Tor listen for regtest) if `bind_to_localhost_only` is set to `False`. Also fix a typo in `test-shell.md` related to `bind_to_localhost_only`. Fixes https://github.com/bitcoin/bitcoin/issues/22727
Diffstat (limited to 'test/functional/test_framework')
-rwxr-xr-xtest/functional/test_framework/test_node.py15
-rw-r--r--test/functional/test_framework/util.py10
2 files changed, 22 insertions, 3 deletions
diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py
index 0ac0af27d5..216de9c309 100755
--- a/test/functional/test_framework/test_node.py
+++ b/test/functional/test_framework/test_node.py
@@ -39,6 +39,7 @@ from .util import (
rpc_url,
wait_until_helper_internal,
p2p_port,
+ tor_port,
)
BITCOIND_PROC_WAIT_TIMEOUT = 60
@@ -88,8 +89,11 @@ class TestNode():
self.coverage_dir = coverage_dir
self.cwd = cwd
self.descriptors = descriptors
+ self.has_explicit_bind = False
if extra_conf is not None:
append_config(self.datadir_path, extra_conf)
+ # Remember if there is bind=... in the config file.
+ self.has_explicit_bind = any(e.startswith("bind=") for e in extra_conf)
# Most callers will just need to add extra args to the standard list below.
# For those callers that need more flexibility, they can just set the args property directly.
# Note that common args are set in the config file (see initialize_datadir)
@@ -210,6 +214,17 @@ class TestNode():
if extra_args is None:
extra_args = self.extra_args
+ # If listening and no -bind is given, then bitcoind would bind P2P ports on
+ # 0.0.0.0:P and 127.0.0.1:18445 (for incoming Tor connections), where P is
+ # a unique port chosen by the test framework and configured as port=P in
+ # bitcoin.conf. To avoid collisions on 127.0.0.1:18445, change it to
+ # 127.0.0.1:tor_port().
+ will_listen = all(e != "-nolisten" and e != "-listen=0" for e in extra_args)
+ has_explicit_bind = self.has_explicit_bind or any(e.startswith("-bind=") for e in extra_args)
+ if will_listen and not has_explicit_bind:
+ extra_args.append(f"-bind=0.0.0.0:{p2p_port(self.index)}")
+ extra_args.append(f"-bind=127.0.0.1:{tor_port(self.index)}=onion")
+
self.use_v2transport = "-v2transport=1" in extra_args or (self.default_to_v2 and "-v2transport=0" not in extra_args)
# Add a new stdout and stderr file each time bitcoind is started
diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py
index c5b69a3954..7be1a35d4d 100644
--- a/test/functional/test_framework/util.py
+++ b/test/functional/test_framework/util.py
@@ -309,9 +309,9 @@ def sha256sum_file(filename):
# The maximum number of nodes a single test can spawn
MAX_NODES = 12
-# Don't assign rpc or p2p ports lower than this
+# Don't assign p2p, rpc or tor ports lower than this
PORT_MIN = int(os.getenv('TEST_RUNNER_PORT_MIN', default=11000))
-# The number of ports to "reserve" for p2p and rpc, each
+# The number of ports to "reserve" for p2p, rpc and tor, each
PORT_RANGE = 5000
@@ -351,7 +351,11 @@ def p2p_port(n):
def rpc_port(n):
- return PORT_MIN + PORT_RANGE + n + (MAX_NODES * PortSeed.n) % (PORT_RANGE - 1 - MAX_NODES)
+ return p2p_port(n) + PORT_RANGE
+
+
+def tor_port(n):
+ return p2p_port(n) + PORT_RANGE * 2
def rpc_url(datadir, i, chain, rpchost):