Repository: bitcoin/bitcoin
File: test/functional/test_framework/test_framework.py (Python)

Code before:
                bins_missing = True
        if bins_missing:
            raise AssertionError("At least one release binary is missing. "
                                 "Previous releases binaries can be downloaded via `test/get_previous_releases.py -b`.")
        assert_equal(len(extra_confs), num_nodes)
        assert_equal(len(extra_args), num_nodes)
        assert_equal(len(versions), num_nodes)
        assert_equal(len(bin_dirs), num_nodes)
        for i in range(num_nodes):
            args = list(extra_args[i])
            test_node_i = TestNode(
                i,
                get_datadir_path(self.options.tmpdir, i),
                chain=self.chain,
                rpchost=rpchost,
                timewait=self.rpc_timeout,
                timeout_factor=self.options.timeout_factor,
                binaries=self.get_binaries(bin_dirs[i]),
                version=versions[i],
                coverage_dir=self.options.coveragedir,
                cwd=self.options.tmpdir,
                extra_conf=extra_confs[i],
                extra_args=args,
                use_cli=self.options.usecli,
                start_perf=self.options.perf,
                use_valgrind=self.options.valgrind,
                v2transport=self.options.v2transport,
                uses_wallet=self.uses_wallet,
            )
            self.nodes.append(test_node_i)
            if not test_node_i.version_is_at_least(170000):
                # adjust conf for pre 17
                test_node_i.replace_in_config([('[regtest]', '')])

    def start_node(self, i, *args, **kwargs):
        """Start a bitcoind"""

        node = self.nodes[i]

        node.start(*args, **kwargs)
        node.wait_for_rpc_connection()

        if self.options.coveragedir is not None:
            coverage.write_all_rpc_commands(self.options.coveragedir, node.rpc)

    def start_nodes(self, extra_args=None, *args, **kwargs):
        """Start multiple bitcoinds"""

        if extra_args is None:
            extra_args = [None] * self.num_nodes
        assert_equal(len(extra_args), self.num_nodes)

Review comment (bug):
coming from the conflicting pull, I don't think this call should exist in the first place for two reasons:

* It doesn't work in most cases, because a failure to start any node likely means the RPC isn't up for the other nodes either, so the call will just fail in most cases. Effectively just using the kill fallback.
* It doesn't make sense to special case startup. Nodes can at any time fail to start (not only in start_nodes), or crash, and adding this exception handling to all places isn't useful nor trivially possible.

So I removed it in https://github.com/bitcoin/bitcoin/pull/31620.

(Just leaving a comment here to document the merge conflict between the two changes. Should be trivial to solve either way, so nothing to be done here, I think.)

Code after:
                        (version % 1000000) // 10000,
                        (version % 10000) // 100,
                        (version % 100) // 1,
                    ),
                ),
                'bin',
            )

        if self.bind_to_localhost_only:
            extra_confs = [["bind=127.0.0.1"]] * num_nodes
        else:
            extra_confs = [[]] * num_nodes
        if extra_args is None:
            extra_args = [[]] * num_nodes
        # Whitelist peers to speed up tx relay / mempool sync. Don't use it if testing tx relay or timing.
        if self.noban_tx_relay:
            for i in range(len(extra_args)):
                extra_args[i] = extra_args[i] + ["-whitelist=noban,in,out@127.0.0.1"]
        if versions is None:
            versions = [None] * num_nodes
        bin_dirs = [bin_dir_from_version(v) for v in versions]
        # Fail test if any of the needed release binaries is missing
        bins_missing = False
        for bin_path in (argv[0] for bin_dir in bin_dirs
                                 for binaries in (self.get_binaries(bin_dir),)
                                 for argv in (binaries.daemon_argv(), binaries.rpc_argv())):
            if shutil.which(bin_path) is None:
                self.log.error(f"Binary not found: {bin_path}")
                bins_missing = True
        if bins_missing:
            raise AssertionError("At least one release binary is missing. "
                                 "Previous releases binaries can be downloaded via `test/get_previous_releases.py -b`.")
        assert_equal(len(extra_confs), num_nodes)
        assert_equal(len(extra_args), num_nodes)
        assert_equal(len(versions), num_nodes)
        assert_equal(len(bin_dirs), num_nodes)
        for i in range(num_nodes):
            args = list(extra_args[i])
            test_node_i = TestNode(
                i,
                get_datadir_path(self.options.tmpdir, i),
                chain=self.chain,
                rpchost=rpchost,
                timewait=self.rpc_timeout,
                timeout_factor=self.options.timeout_factor,
                binaries=self.get_binaries(bin_dirs[i]),
                version=versions[i],
                coverage_dir=self.options.coveragedir,
                cwd=self.options.tmpdir,
                extra_conf=extra_confs[i],
                extra_args=args,