From 6b3f6eae70bbf61a8a57764d60b1c34c9fd227d6 Mon Sep 17 00:00:00 2001
From: Vasil Dimov <vd@FreeBSD.org>
Date: Mon, 25 Nov 2024 15:36:38 +0100
Subject: [PATCH 1/3] test: avoid generating non-loopback traffic from
 p2p_seednode.py

`p2p_seednode.py` would try to connect to `0.0.0.1` and `0.0.0.2` as
seed nodes. This sends outbound TCP packets on a non-loopback interface
to the default router.

Configure an unavailable proxy for all executions of `bitcoind` during
this test. Also change `0.0.0.1` and `0.0.0.2` because connecting to
them would skip the `-proxy=` setting because for such an address:
* `CNetAddr::IsLocal()` is true, thus
* `CNetAddr::IsRoutable()` is false, thus
* `CNetAddr::GetNetwork()` is `NET_UNROUTABLE`, even though
  `CNetAddr::m_net` is `NET_IPV4`.

This speeds up the execution time of `p2p_seednode.py`
from 12.5s to 2.5s.
---
 test/functional/p2p_seednode.py           | 15 +++++++++------
 test/functional/test_framework/netutil.py |  4 ++++
 2 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/test/functional/p2p_seednode.py b/test/functional/p2p_seednode.py
index 5a9fca3278a..ceefe1aa9b9 100755
--- a/test/functional/p2p_seednode.py
+++ b/test/functional/p2p_seednode.py
@@ -9,6 +9,7 @@ Test seednode interaction with the AddrMan
 import random
 import time
 
+from test_framework.netutil import UNREACHABLE_PROXY_ARG
 from test_framework.test_framework import BitcoinTestFramework
 
 ADD_NEXT_SEEDNODE = 10
@@ -17,22 +18,24 @@ ADD_NEXT_SEEDNODE = 10
 class P2PSeedNodes(BitcoinTestFramework):
     def set_test_params(self):
         self.num_nodes = 1
+        # Specify a non-working proxy to make sure no actual connections to random IPs are attempted.
+        self.extra_args = [[UNREACHABLE_PROXY_ARG]]
         self.disable_autoconnect = False
 
     def test_no_seednode(self):
         self.log.info("Check that if no seednode is provided, the node proceeds as usual (without waiting)")
         with self.nodes[0].assert_debug_log(expected_msgs=[], unexpected_msgs=["Empty addrman, adding seednode", f"Couldn't connect to peers from addrman after {ADD_NEXT_SEEDNODE} seconds. Adding seednode"], timeout=ADD_NEXT_SEEDNODE):
-            self.restart_node(0)
+            self.restart_node(0, extra_args=self.nodes[0].extra_args)
 
     def test_seednode_empty_addrman(self):
-        seed_node = "0.0.0.1"
+        seed_node = "25.0.0.1"
         self.log.info("Check that the seednode is immediately added on bootstrap on an empty addrman")
         with self.nodes[0].assert_debug_log(expected_msgs=[f"Empty addrman, adding seednode ({seed_node}) to addrfetch"], timeout=ADD_NEXT_SEEDNODE):
-            self.restart_node(0, extra_args=[f'-seednode={seed_node}'])
+            self.restart_node(0, extra_args=self.nodes[0].extra_args + [f'-seednode={seed_node}'])
 
     def test_seednode_non_empty_addrman(self):
         self.log.info("Check that if addrman is non-empty, seednodes are queried with a delay")
-        seed_node = "0.0.0.2"
+        seed_node = "25.0.0.2"
         node = self.nodes[0]
         # Fill the addrman with unreachable nodes
         for i in range(10):
@@ -40,9 +43,9 @@ class P2PSeedNodes(BitcoinTestFramework):
             port = 8333 + i
             node.addpeeraddress(ip, port)
 
-        # Restart the node so seednode is processed again. Specify a non-working proxy to make sure no actual connections to random IPs are attempted.
+        # Restart the node so seednode is processed again.
         with node.assert_debug_log(expected_msgs=["trying v1 connection"], timeout=ADD_NEXT_SEEDNODE):
-            self.restart_node(0, extra_args=[f'-seednode={seed_node}', '-proxy=127.0.0.1:1'])
+            self.restart_node(0, extra_args=self.nodes[0].extra_args + [f'-seednode={seed_node}'])
 
         with node.assert_debug_log(expected_msgs=[f"Couldn't connect to peers from addrman after {ADD_NEXT_SEEDNODE} seconds. Adding seednode ({seed_node}) to addrfetch"], unexpected_msgs=["Empty addrman, adding seednode"], timeout=ADD_NEXT_SEEDNODE * 1.5):
             node.setmocktime(int(time.time()) + ADD_NEXT_SEEDNODE + 1)
diff --git a/test/functional/test_framework/netutil.py b/test/functional/test_framework/netutil.py
index f6acf926fa8..6fa8a8156de 100644
--- a/test/functional/test_framework/netutil.py
+++ b/test/functional/test_framework/netutil.py
@@ -13,6 +13,10 @@ import struct
 import array
 import os
 
+# Easily unreachable address. Attempts to connect to it will stay within the machine.
+# Used to avoid non-loopback traffic or DNS queries.
+UNREACHABLE_PROXY_ARG = '-proxy=127.0.0.1:1'
+
 # STATE_ESTABLISHED = '01'
 # STATE_SYN_SENT  = '02'
 # STATE_SYN_RECV = '03'

From a5746dc559c2a0909018be6ca2f3869e237a49b7 Mon Sep 17 00:00:00 2001
From: Vasil Dimov <vd@FreeBSD.org>
Date: Mon, 25 Nov 2024 17:01:17 +0100
Subject: [PATCH 2/3] test: avoid generating non-loopback traffic from
 feature_config_args.py

`feature_config_args.py` uses a proxy address of `1.2.3.4`. This results
in actually trying to open TCP connections over the internet to
`1.2.3.4:9050`.

The test does not need those to succeed so use `127.0.0.1:1` instead.

Also avoid `-noconnect=0` because that is interpreted as `-connect=1`
which is interpreted as `-connect=0.0.0.1` and a connection to
`0.0.0.1:18444` is attempted.
---
 test/functional/feature_config_args.py | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/test/functional/feature_config_args.py b/test/functional/feature_config_args.py
index 31847b3fbfc..b2462be951a 100755
--- a/test/functional/feature_config_args.py
+++ b/test/functional/feature_config_args.py
@@ -11,6 +11,7 @@ import re
 import tempfile
 import time
 
+from test_framework.netutil import UNREACHABLE_PROXY_ARG
 from test_framework.test_framework import BitcoinTestFramework
 from test_framework.test_node import ErrorMatch
 from test_framework import util
@@ -227,8 +228,8 @@ class ConfArgsTest(BitcoinTestFramework):
                 )
 
     def test_log_buffer(self):
-        with self.nodes[0].assert_debug_log(expected_msgs=['Warning: parsed potentially confusing double-negative -connect=0\n']):
-            self.start_node(0, extra_args=['-noconnect=0'])
+        with self.nodes[0].assert_debug_log(expected_msgs=['Warning: parsed potentially confusing double-negative -listen=0\n']):
+            self.start_node(0, extra_args=['-nolisten=0'])
         self.stop_node(0)
 
     def test_args_log(self):
@@ -259,6 +260,7 @@ class ConfArgsTest(BitcoinTestFramework):
                 '-rpcpassword=',
                 '-rpcuser=secret-rpcuser',
                 '-torpassword=secret-torpassword',
+                UNREACHABLE_PROXY_ARG,
             ])
         self.stop_node(0)
 
@@ -307,7 +309,7 @@ class ConfArgsTest(BitcoinTestFramework):
                 ],
                 timeout=10,
         ):
-            self.start_node(0, extra_args=['-dnsseed=1', '-fixedseeds=1', f'-mocktime={start}'])
+            self.start_node(0, extra_args=['-dnsseed=1', '-fixedseeds=1', f'-mocktime={start}', UNREACHABLE_PROXY_ARG])
 
         # Only regtest has no fixed seeds. To avoid connections to random
         # nodes, regtest is the only network where it is safe to enable
@@ -355,7 +357,7 @@ class ConfArgsTest(BitcoinTestFramework):
                 ],
                 timeout=10,
         ):
-            self.start_node(0, extra_args=['-dnsseed=0', '-fixedseeds=1', '-addnode=fakenodeaddr', f'-mocktime={start}'])
+            self.start_node(0, extra_args=['-dnsseed=0', '-fixedseeds=1', '-addnode=fakenodeaddr', f'-mocktime={start}', UNREACHABLE_PROXY_ARG])
         with self.nodes[0].assert_debug_log(expected_msgs=[
                 "Adding fixed seeds as 60 seconds have passed and addrman is empty",
         ]):
@@ -371,18 +373,18 @@ class ConfArgsTest(BitcoinTestFramework):
         # When -connect is supplied, expanding addrman via getaddr calls to ADDR_FETCH(-seednode)
         # nodes is irrelevant and -seednode is ignored.
         with self.nodes[0].assert_debug_log(expected_msgs=seednode_ignored):
-            self.start_node(0, extra_args=['-connect=fakeaddress1', '-seednode=fakeaddress2'])
+            self.start_node(0, extra_args=['-connect=fakeaddress1', '-seednode=fakeaddress2', UNREACHABLE_PROXY_ARG])
 
         # With -proxy, an ADDR_FETCH connection is made to a peer that the dns seed resolves to.
         # ADDR_FETCH connections are not used when -connect is used.
         with self.nodes[0].assert_debug_log(expected_msgs=dnsseed_ignored):
-            self.restart_node(0, extra_args=['-connect=fakeaddress1', '-dnsseed=1', '-proxy=1.2.3.4'])
+            self.restart_node(0, extra_args=['-connect=fakeaddress1', '-dnsseed=1', UNREACHABLE_PROXY_ARG])
 
         # If the user did not disable -dnsseed, but it was soft-disabled because they provided -connect,
         # they shouldn't see a warning about -dnsseed being ignored.
         with self.nodes[0].assert_debug_log(expected_msgs=addcon_thread_started,
                 unexpected_msgs=dnsseed_ignored):
-            self.restart_node(0, extra_args=['-connect=fakeaddress1', '-proxy=1.2.3.4'])
+            self.restart_node(0, extra_args=['-connect=fakeaddress1', UNREACHABLE_PROXY_ARG])
 
         # We have to supply expected_msgs as it's a required argument
         # The expected_msg must be something we are confident will be logged after the unexpected_msg

From 2ed161c5ce648cb66ec3d2941b02d68b6ca4c390 Mon Sep 17 00:00:00 2001
From: Vasil Dimov <vd@FreeBSD.org>
Date: Tue, 26 Nov 2024 15:14:41 +0100
Subject: [PATCH 3/3] test: avoid generating non-loopback traffic from
 p2p_dns_seeds.py

`p2p_dns_seeds.py` would try to connect to the DNS server configured on
the machine and resolve `dummySeed.invalid`.

To block that configure an unavailable proxy which will be used also to
connect to the name server. The test needs 2 successful connections to
other peers (two Python `P2PInterface`s) and they work in spite of the
unavailable proxy because they are on `127.0.0.1` (`NET_UNROUTABLE`) and
the proxy is not used for that.
---
 test/functional/p2p_dns_seeds.py | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/test/functional/p2p_dns_seeds.py b/test/functional/p2p_dns_seeds.py
index a2d4ea110f7..89a29c0ebdf 100755
--- a/test/functional/p2p_dns_seeds.py
+++ b/test/functional/p2p_dns_seeds.py
@@ -6,6 +6,7 @@
 
 import itertools
 
+from test_framework.netutil import UNREACHABLE_PROXY_ARG
 from test_framework.p2p import P2PInterface
 from test_framework.test_framework import BitcoinTestFramework
 
@@ -14,7 +15,7 @@ class P2PDNSSeeds(BitcoinTestFramework):
     def set_test_params(self):
         self.setup_clean_chain = True
         self.num_nodes = 1
-        self.extra_args = [["-dnsseed=1"]]
+        self.extra_args = [["-dnsseed=1", UNREACHABLE_PROXY_ARG]]
 
     def run_test(self):
         self.init_arg_tests()
@@ -29,11 +30,11 @@ class P2PDNSSeeds(BitcoinTestFramework):
         self.log.info("Check that setting -connect disables -dnsseed by default")
         self.nodes[0].stop_node()
         with self.nodes[0].assert_debug_log(expected_msgs=["DNS seeding disabled"]):
-            self.start_node(0, [f"-connect={fakeaddr}"])
+            self.start_node(0, extra_args=[f"-connect={fakeaddr}", UNREACHABLE_PROXY_ARG])
 
         self.log.info("Check that running -connect and -dnsseed means DNS logic runs.")
         with self.nodes[0].assert_debug_log(expected_msgs=["Loading addresses from DNS seed"], timeout=12):
-            self.restart_node(0, [f"-connect={fakeaddr}", "-dnsseed=1"])
+            self.restart_node(0, extra_args=[f"-connect={fakeaddr}", "-dnsseed=1", UNREACHABLE_PROXY_ARG])
 
         self.log.info("Check that running -forcednsseed and -dnsseed=0 throws an error.")
         self.nodes[0].stop_node()
@@ -88,7 +89,7 @@ class P2PDNSSeeds(BitcoinTestFramework):
         with self.nodes[0].assert_debug_log(expected_msgs=["Loading addresses from DNS seed"], timeout=12):
             # -dnsseed defaults to 1 in bitcoind, but 0 in the test framework,
             # so pass it explicitly here
-            self.restart_node(0, ["-forcednsseed", "-dnsseed=1"])
+            self.restart_node(0, ["-forcednsseed", "-dnsseed=1", UNREACHABLE_PROXY_ARG])
 
         # Restore default for subsequent tests
         self.restart_node(0)