From fa37c6a529f4725dd9b5ef84c901e0ffc96f0f6b Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Thu, 26 Mar 2026 18:24:59 +0100 Subject: [PATCH 1/7] test: [move-only] Extract create_new_rpc_connection Re-using the same rpc connection on multiple threads is obviously unsafe, so this helper can be used to create one connection per thread. This refactor does not change any behavior and can be reviewed with the git options: --color-moved=dimmed-zebra --color-moved-ws=ignore-all-space --- test/functional/test_framework/test_node.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py index 1ba2e09b221..c3384007b36 100755 --- a/test/functional/test_framework/test_node.py +++ b/test/functional/test_framework/test_node.py @@ -301,6 +301,17 @@ class TestNode(): if self.start_perf: self._start_perf() + def create_new_rpc_connection(self): + """Create an additional RPC connection, likely to be used in a new thread.""" + rpc = get_rpc_proxy( + rpc_url(self.datadir_path, self.index, self.chain, self.rpchost), + self.index, + timeout=self.rpc_timeout // 2, # Shorter timeout to allow for one retry in case of ETIMEDOUT + coveragedir=self.coverage_dir, + ) + rpc.auth_service_proxy_instance.reuse_http_connections = self.reuse_http_connections + return rpc + def wait_for_rpc_connection(self, *, wait_for_import=True): """Sets up an RPC connection to the bitcoind process. Returns False if unable to connect.""" # Poll at a rate of four times per second @@ -322,13 +333,7 @@ class TestNode(): raise FailedToStartError(self._node_msg( f'bitcoind exited with status {self.process.returncode} during initialization. {str_error}')) try: - rpc = get_rpc_proxy( - rpc_url(self.datadir_path, self.index, self.chain, self.rpchost), - self.index, - timeout=self.rpc_timeout // 2, # Shorter timeout to allow for one retry in case of ETIMEDOUT - coveragedir=self.coverage_dir, - ) - rpc.auth_service_proxy_instance.reuse_http_connections = self.reuse_http_connections + rpc = self.create_new_rpc_connection() rpc.getblockcount() # If the call to getblockcount() succeeds then the RPC connection is up if self.version_is_at_least(190000) and wait_for_import: From fa2a3683d519f0711860e9411aa19b353a738819 Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Wed, 20 May 2026 14:00:25 +0200 Subject: [PATCH 2/7] test: Allow mining_getblocktemplate_longpoll.py --usecli Part of the diff can be reviewed with --ignore-all-space --- .../mining_getblocktemplate_longpoll.py | 8 ++--- test/functional/test_framework/test_node.py | 30 ++++++++++++------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/test/functional/mining_getblocktemplate_longpoll.py b/test/functional/mining_getblocktemplate_longpoll.py index e36396b352a..e2293f96e18 100755 --- a/test/functional/mining_getblocktemplate_longpoll.py +++ b/test/functional/mining_getblocktemplate_longpoll.py @@ -8,7 +8,7 @@ import random import threading from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import assert_equal, get_rpc_proxy +from test_framework.util import assert_equal from test_framework.wallet import MiniWallet @@ -18,9 +18,8 @@ class LongpollThread(threading.Thread): # query current longpollid template = node.getblocktemplate({'rules': ['segwit']}) self.longpollid = template['longpollid'] - # create a new connection to the node, we can't use the same - # connection from two threads - self.node = get_rpc_proxy(node.url, 1, timeout=600, coveragedir=node.coverage_dir) + # create a new connection to the node for this thread + self.node = node.create_new_rpc_connection(client_timeout=600) def run(self): self.node.getblocktemplate({'longpollid': self.longpollid, 'rules': ['segwit']}) @@ -28,7 +27,6 @@ class LongpollThread(threading.Thread): class GetBlockTemplateLPTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 - self.supports_cli = False def run_test(self): self.log.info("Warning: this test will take about 70 seconds in the best case. Be patient.") diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py index c3384007b36..6254e5f063c 100755 --- a/test/functional/test_framework/test_node.py +++ b/test/functional/test_framework/test_node.py @@ -76,6 +76,9 @@ class ErrorMatch(Enum): PARTIAL_REGEX = 3 +RPCConnectionType = Enum("RPCConnectionType", ["AUTO", "AUTHPROXY", "CLI"]) + + class TestNode(): """A class for representing a bitcoind node under test. @@ -301,16 +304,23 @@ class TestNode(): if self.start_perf: self._start_perf() - def create_new_rpc_connection(self): + def create_new_rpc_connection(self, *, mode="AUTO", client_timeout=None): """Create an additional RPC connection, likely to be used in a new thread.""" - rpc = get_rpc_proxy( - rpc_url(self.datadir_path, self.index, self.chain, self.rpchost), - self.index, - timeout=self.rpc_timeout // 2, # Shorter timeout to allow for one retry in case of ETIMEDOUT - coveragedir=self.coverage_dir, - ) - rpc.auth_service_proxy_instance.reuse_http_connections = self.reuse_http_connections - return rpc + mode = RPCConnectionType[mode] + if mode == RPCConnectionType.AUTO: + mode = RPCConnectionType.CLI if self.use_cli else RPCConnectionType.AUTHPROXY + client_timeout = client_timeout or (self.rpc_timeout // 2) # Shorter timeout to allow for one retry in case of ETIMEDOUT + if mode == RPCConnectionType.AUTHPROXY: + rpc = get_rpc_proxy( + rpc_url(self.datadir_path, self.index, self.chain, self.rpchost), + self.index, + timeout=client_timeout, + coveragedir=self.coverage_dir, + ) + rpc.auth_service_proxy_instance.reuse_http_connections = self.reuse_http_connections + return rpc + else: # mode==CLI + return self.cli(f"-rpcclienttimeout={client_timeout}") def wait_for_rpc_connection(self, *, wait_for_import=True): """Sets up an RPC connection to the bitcoind process. Returns False if unable to connect.""" @@ -333,7 +343,7 @@ class TestNode(): raise FailedToStartError(self._node_msg( f'bitcoind exited with status {self.process.returncode} during initialization. {str_error}')) try: - rpc = self.create_new_rpc_connection() + rpc = self.create_new_rpc_connection(mode="AUTHPROXY") rpc.getblockcount() # If the call to getblockcount() succeeds then the RPC connection is up if self.version_is_at_least(190000) and wait_for_import: From fa3ae6c7d3cd89a498598aeca9b99d097e6c86a6 Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Wed, 20 May 2026 14:16:31 +0200 Subject: [PATCH 3/7] test: Allow feature_shutdown.py --usecli --- test/functional/feature_shutdown.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/functional/feature_shutdown.py b/test/functional/feature_shutdown.py index 3b4c35cb306..50ae234e2b4 100755 --- a/test/functional/feature_shutdown.py +++ b/test/functional/feature_shutdown.py @@ -5,7 +5,7 @@ """Test bitcoind shutdown.""" from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import assert_equal, get_rpc_proxy +from test_framework.util import assert_equal from threading import Thread def test_long_call(node): @@ -17,10 +17,9 @@ class ShutdownTest(BitcoinTestFramework): def set_test_params(self): self.setup_clean_chain = True self.num_nodes = 1 - self.supports_cli = False def run_test(self): - node = get_rpc_proxy(self.nodes[0].url, 1, timeout=600, coveragedir=self.nodes[0].coverage_dir) + node = self.nodes[0].create_new_rpc_connection() # Force connection establishment by executing a dummy command. node.getblockcount() Thread(target=test_long_call, args=(node,)).start() From fa8f25118c021c272abe91a911f0cfdcf40da254 Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Wed, 20 May 2026 14:25:42 +0200 Subject: [PATCH 4/7] refactor: Use create_new_rpc_connection in wallet_multiwallet.py --- test/functional/wallet_multiwallet.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py index 6240126ccba..4f855ee0cf9 100755 --- a/test/functional/wallet_multiwallet.py +++ b/test/functional/wallet_multiwallet.py @@ -20,7 +20,6 @@ from test_framework.util import ( assert_equal, assert_raises_rpc_error, ensure_for, - get_rpc_proxy, ) got_loading_error = False @@ -328,7 +327,7 @@ class MultiWalletTest(BitcoinTestFramework): self.log.info("Concurrent wallet loading") threads = [] for _ in range(3): - n = node.cli if self.options.usecli else get_rpc_proxy(node.url, 1, timeout=600, coveragedir=node.coverage_dir) + n = node.create_new_rpc_connection() t = Thread(target=test_load_unload, args=(n, wallet_names[2])) t.start() threads.append(t) From fa00c7c7a415406d21c665ecda01b217351d0b40 Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Wed, 20 May 2026 14:30:34 +0200 Subject: [PATCH 5/7] test: Allow rpc_bind.py --usecli This allows to run the test under bitcoin-cli, except for one small part, which is skipped for now. This also inlines rpc_url directly into create_new_rpc_connection, because this is the only place where it is needed. --- test/functional/rpc_bind.py | 10 +++++++--- test/functional/test_framework/test_node.py | 15 ++++++++++++--- test/functional/test_framework/util.py | 13 ------------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/test/functional/rpc_bind.py b/test/functional/rpc_bind.py index bff8ec244d6..672db9b8b3c 100755 --- a/test/functional/rpc_bind.py +++ b/test/functional/rpc_bind.py @@ -7,14 +7,13 @@ from test_framework.netutil import all_interfaces, addr_to_hex, get_bind_addrs, test_ipv6_local from test_framework.test_framework import BitcoinTestFramework, SkipTest from test_framework.test_node import ErrorMatch -from test_framework.util import assert_equal, assert_raises_rpc_error, get_rpc_proxy, rpc_port, rpc_url +from test_framework.util import assert_equal, assert_raises_rpc_error, rpc_port class RPCBindTest(BitcoinTestFramework): def set_test_params(self): self.setup_clean_chain = True self.bind_to_localhost_only = False self.num_nodes = 1 - self.supports_cli = False def skip_test_if_missing_module(self): self.skip_if_platform_not_posix() @@ -40,6 +39,7 @@ class RPCBindTest(BitcoinTestFramework): base_args += ['-rpcallowip=' + x for x in allow_ips] binds = ['-rpcbind='+addr for addr in addresses] self.nodes[0].rpchost = connect_to + self.nodes[0].cli = self.nodes[0].create_new_rpc_connection(mode="CLI") # Pass `connect_to` to cli. self.start_node(0, base_args + binds) pid = self.nodes[0].process.pid assert_equal(set(get_bind_addrs(pid)), set(expected)) @@ -70,8 +70,9 @@ class RPCBindTest(BitcoinTestFramework): ['-rpcbind='+addr for addr in ['127.0.0.1', "%s:%d" % (rpchost, rpcport)]] # Bind to localhost as well so start_nodes doesn't hang self.nodes[0].rpchost = None self.start_nodes([node_args]) + self.nodes[0].rpchost = f"{rpchost}:{rpcport}" # connect to node through non-loopback interface - node = get_rpc_proxy(rpc_url(self.nodes[0].datadir_path, 0, self.chain, "%s:%d" % (rpchost, rpcport)), 0, coveragedir=self.options.coveragedir) + node = self.nodes[0].create_new_rpc_connection() node.getnetworkinfo() self.stop_nodes() @@ -164,6 +165,9 @@ class RPCBindTest(BitcoinTestFramework): # Check that with invalid rpcallowip, we are denied self.run_allowip_test([self.non_loopback_ip], self.non_loopback_ip, self.defaultport) + if self.options.usecli: + self.log.info("Skip negative IP test with CLI, because the CLI can not throw the tested exception type") + return assert_raises_rpc_error(-342, "non-JSON HTTP response with '403 Forbidden' from server", self.run_allowip_test, ['1.1.1.1'], self.non_loopback_ip, self.defaultport) if __name__ == '__main__': diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py index 6254e5f063c..cef14a678b1 100755 --- a/test/functional/test_framework/test_node.py +++ b/test/functional/test_framework/test_node.py @@ -37,7 +37,7 @@ from .util import ( delete_cookie_file, get_auth_cookie, get_rpc_proxy, - rpc_url, + rpc_port, wait_until_helper_internal, p2p_port, tor_port, @@ -310,9 +310,18 @@ class TestNode(): if mode == RPCConnectionType.AUTO: mode = RPCConnectionType.CLI if self.use_cli else RPCConnectionType.AUTHPROXY client_timeout = client_timeout or (self.rpc_timeout // 2) # Shorter timeout to allow for one retry in case of ETIMEDOUT + host = "127.0.0.1" + port = rpc_port(self.index) + if self.rpchost: + parts = self.rpchost.split(":") + if len(parts) == 2: + host, port = parts + else: + host = self.rpchost if mode == RPCConnectionType.AUTHPROXY: + rpc_u, rpc_p = get_auth_cookie(self.datadir_path, self.chain) rpc = get_rpc_proxy( - rpc_url(self.datadir_path, self.index, self.chain, self.rpchost), + f"http://{rpc_u}:{rpc_p}@{host}:{port}", self.index, timeout=client_timeout, coveragedir=self.coverage_dir, @@ -320,7 +329,7 @@ class TestNode(): rpc.auth_service_proxy_instance.reuse_http_connections = self.reuse_http_connections return rpc else: # mode==CLI - return self.cli(f"-rpcclienttimeout={client_timeout}") + return self.cli(f"-rpcclienttimeout={client_timeout}", f"-rpcconnect={host}", f"-rpcport={port}") def wait_for_rpc_connection(self, *, wait_for_import=True): """Sets up an RPC connection to the bitcoind process. Returns False if unable to connect.""" diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py index 4918a7f4d5e..aa3cdf36c1f 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -517,19 +517,6 @@ def tor_port(n): return p2p_port(n) + PORT_RANGE * 2 -def rpc_url(datadir, i, chain, rpchost): - rpc_u, rpc_p = get_auth_cookie(datadir, chain) - host = '127.0.0.1' - port = rpc_port(i) - if rpchost: - parts = rpchost.split(':') - if len(parts) == 2: - host, port = parts - else: - host = rpchost - return "http://%s:%s@%s:%d" % (rpc_u, rpc_p, host, int(port)) - - # Node functions ################ From fae376cafb0bea811daafc7db1a729dc298a1519 Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Wed, 20 May 2026 16:32:55 +0200 Subject: [PATCH 6/7] refactor: Inline get_rpc_proxy This is only used and needed in a single place. --- test/functional/test_framework/test_node.py | 15 +++++------ test/functional/test_framework/util.py | 29 +-------------------- 2 files changed, 8 insertions(+), 36 deletions(-) diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py index cef14a678b1..dbf2e6f0639 100755 --- a/test/functional/test_framework/test_node.py +++ b/test/functional/test_framework/test_node.py @@ -24,9 +24,11 @@ from collections.abc import Iterable from pathlib import Path from .authproxy import ( + AuthServiceProxy, JSONRPCException, serialization_fallback, ) +from . import coverage from .messages import NODE_P2P_V2 from .p2p import P2P_SERVICES, P2P_SUBVERSION from .util import ( @@ -36,7 +38,6 @@ from .util import ( append_config, delete_cookie_file, get_auth_cookie, - get_rpc_proxy, rpc_port, wait_until_helper_internal, p2p_port, @@ -200,7 +201,7 @@ class TestNode(): self.process = None self.rpc_connected = False self._rpc = None # Should usually not be accessed directly in tests to allow for --usecli mode - self.reuse_http_connections = True # Must be set before calling get_rpc_proxy() i.e. before restarting node + self.reuse_http_connections = True # Must be set before create_new_rpc_connection(), i.e. before restarting node self.url = None self.log = logging.getLogger('TestFramework.node%d' % i) # Cache perf subprocesses here by their data output filename. @@ -320,12 +321,10 @@ class TestNode(): host = self.rpchost if mode == RPCConnectionType.AUTHPROXY: rpc_u, rpc_p = get_auth_cookie(self.datadir_path, self.chain) - rpc = get_rpc_proxy( - f"http://{rpc_u}:{rpc_p}@{host}:{port}", - self.index, - timeout=client_timeout, - coveragedir=self.coverage_dir, - ) + url = f"http://{rpc_u}:{rpc_p}@{host}:{port}" + proxy = AuthServiceProxy(url, timeout=int(client_timeout)) + coverage_logfile = coverage.get_filename(self.coverage_dir, self.index) if self.coverage_dir else None + rpc = coverage.AuthServiceProxyWrapper(proxy, url, coverage_logfile) rpc.auth_service_proxy_instance.reuse_http_connections = self.reuse_http_connections return rpc else: # mode==CLI diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py index aa3cdf36c1f..d225f18e740 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -20,8 +20,7 @@ import shlex import time import types -from . import coverage -from .authproxy import AuthServiceProxy, JSONRPCException +from .authproxy import JSONRPCException from .descriptors import descsum_create from collections.abc import Callable from typing import Optional, Union @@ -478,32 +477,6 @@ class PortSeed: # Must be initialized with a unique integer for each process n = None - -def get_rpc_proxy(url: str, node_number: int, *, timeout: Optional[int]=None, coveragedir: Optional[str]=None) -> coverage.AuthServiceProxyWrapper: - """ - Args: - url: URL of the RPC server to call - node_number: the node number (or id) that this calls to - - Kwargs: - timeout: HTTP timeout in seconds - coveragedir: Directory - - Returns: - AuthServiceProxy. convenience object for making RPC calls. - - """ - proxy_kwargs = {} - if timeout is not None: - proxy_kwargs['timeout'] = int(timeout) - - proxy = AuthServiceProxy(url, **proxy_kwargs) - - coverage_logfile = coverage.get_filename(coveragedir, node_number) if coveragedir else None - - return coverage.AuthServiceProxyWrapper(proxy, url, coverage_logfile) - - def p2p_port(n): assert n <= MAX_NODES return PORT_MIN + n + (MAX_NODES * PortSeed.n) % (PORT_RANGE - 1 - MAX_NODES) From faf02674b3623c3cbaa2aec0ab02b5859d19b022 Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Thu, 21 May 2026 11:49:24 +0200 Subject: [PATCH 7/7] refactor: Set TestNode.cli only after RPC is connected The cli can only be called after the RPC is connected, so the cli field should only be set after that. This is similar to the _rpc field. This change has also other benefits: * Manually overwriting the cli with a new rpchost is no longer needed, so one cli-specific line can be removed from the rpc_bind.py test. * The datadir and rpc_timeout fields are removed from the TestNodeCLI struct. They were redundant with the -datadir and -rpcclienttimeout command line options. Any command line option can be overwritten by appending it with a new value, if needed. --- test/functional/rpc_bind.py | 1 - test/functional/test_framework/test_node.py | 27 +++++++++------------ test/functional/tool_signet_miner.py | 4 +-- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/test/functional/rpc_bind.py b/test/functional/rpc_bind.py index 672db9b8b3c..422783510be 100755 --- a/test/functional/rpc_bind.py +++ b/test/functional/rpc_bind.py @@ -39,7 +39,6 @@ class RPCBindTest(BitcoinTestFramework): base_args += ['-rpcallowip=' + x for x in allow_ips] binds = ['-rpcbind='+addr for addr in addresses] self.nodes[0].rpchost = connect_to - self.nodes[0].cli = self.nodes[0].create_new_rpc_connection(mode="CLI") # Pass `connect_to` to cli. self.start_node(0, base_args + binds) pid = self.nodes[0].process.pid assert_equal(set(get_bind_addrs(pid)), set(expected)) diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py index dbf2e6f0639..6b7f2648fee 100755 --- a/test/functional/test_framework/test_node.py +++ b/test/functional/test_framework/test_node.py @@ -189,11 +189,7 @@ class TestNode(): self.args.append("-v2transport=0") # if v2transport is requested via global flag but not supported for node version, ignore it - self.cli = TestNodeCLI( - binaries, - self.datadir_path, - self.rpc_timeout // 2, # timeout identical to the one used in self._rpc - ) + self.cli = None self.use_cli = use_cli self.start_perf = start_perf @@ -328,7 +324,12 @@ class TestNode(): rpc.auth_service_proxy_instance.reuse_http_connections = self.reuse_http_connections return rpc else: # mode==CLI - return self.cli(f"-rpcclienttimeout={client_timeout}", f"-rpcconnect={host}", f"-rpcport={port}") + return TestNodeCLI(self.binaries)( + f"-datadir={self.datadir_path}", + f"-rpcclienttimeout={client_timeout}", + f"-rpcconnect={host}", + f"-rpcport={port}", + ) def wait_for_rpc_connection(self, *, wait_for_import=True): """Sets up an RPC connection to the bitcoind process. Returns False if unable to connect.""" @@ -378,6 +379,7 @@ class TestNode(): self.log.debug("RPC successfully started") # Set rpc_connected even if we are in use_cli mode so that we know we can call self.stop() if needed. self.rpc_connected = True + self.cli = self.create_new_rpc_connection(mode="CLI") if self.use_cli: return self._rpc = rpc @@ -977,18 +979,16 @@ def arg_to_cli(arg): class TestNodeCLI(): """Interface to bitcoin-cli for an individual node""" - def __init__(self, binaries, datadir, rpc_timeout): + def __init__(self, binaries): self.options = [] self.binaries = binaries - self.datadir = datadir - self.rpc_timeout = rpc_timeout self.input = None self.log = logging.getLogger('TestFramework.bitcoincli') def __call__(self, *options, input=None): # TestNodeCLI is callable with bitcoin-cli command-line options - cli = TestNodeCLI(self.binaries, self.datadir, self.rpc_timeout) - cli.options = [str(o) for o in options] + cli = TestNodeCLI(self.binaries) + cli.options = self.options + [str(o) for o in options] cli.input = input return cli @@ -1008,10 +1008,7 @@ class TestNodeCLI(): """Run bitcoin-cli command. Deserializes returned string as python object.""" pos_args = [arg_to_cli(arg) for arg in args] named_args = [key + "=" + arg_to_cli(value) for (key, value) in kwargs.items() if value is not None] - p_args = self.binaries.rpc_argv() + [ - f"-datadir={self.datadir}", - f"-rpcclienttimeout={int(self.rpc_timeout)}", - ] + self.options + p_args = self.binaries.rpc_argv() + self.options if named_args: p_args += ["-named"] base_arg_pos = len(p_args) diff --git a/test/functional/tool_signet_miner.py b/test/functional/tool_signet_miner.py index 2be47332390..cb22dd927e3 100755 --- a/test/functional/tool_signet_miner.py +++ b/test/functional/tool_signet_miner.py @@ -69,7 +69,7 @@ class SignetMinerTest(BitcoinTestFramework): n_blocks = node.getblockcount() base_dir = self.config["environment"]["SRCDIR"] signet_miner_path = os.path.join(base_dir, "contrib", "signet", "miner") - rpc_argv = node.binaries.rpc_argv() + [f"-datadir={node.cli.datadir}"] + rpc_argv = node.binaries.rpc_argv() + [f"-datadir={node.datadir_path}"] util_argv = node.binaries.util_argv() + ["grind"] subprocess.run([ sys.executable, @@ -89,7 +89,7 @@ class SignetMinerTest(BitcoinTestFramework): n_blocks = node.getblockcount() base_dir = self.config["environment"]["SRCDIR"] signet_miner_path = os.path.join(base_dir, "contrib", "signet", "miner") - rpc_argv = node.binaries.rpc_argv() + [f"-datadir={node.cli.datadir}"] + rpc_argv = node.binaries.rpc_argv() + [f"-datadir={node.datadir_path}"] util_argv = node.binaries.util_argv() + ["grind"] base_cmd = [ sys.executable,