diff options
Diffstat (limited to 'test/functional')
-rwxr-xr-x | test/functional/feature_assumeutxo.py | 39 | ||||
-rwxr-xr-x | test/functional/feature_proxy.py | 88 | ||||
-rw-r--r-- | test/functional/test_framework/netutil.py | 9 | ||||
-rwxr-xr-x | test/functional/wallet_assumeutxo.py | 2 |
4 files changed, 113 insertions, 25 deletions
diff --git a/test/functional/feature_assumeutxo.py b/test/functional/feature_assumeutxo.py index 60dd751ff8..a9ed4a09ce 100755 --- a/test/functional/feature_assumeutxo.py +++ b/test/functional/feature_assumeutxo.py @@ -113,6 +113,12 @@ class AssumeutxoTest(BitcoinTestFramework): f.write(valid_snapshot_contents[(32 + 8 + offset + len(content)):]) expected_error(log_msg=f"[snapshot] bad snapshot content hash: expected a4bf3407ccb2cc0145c49ebba8fa91199f8a3903daf0883875941497d2493c27, got {wrong_hash}") + def test_headers_not_synced(self, valid_snapshot_path): + for node in self.nodes[1:]: + assert_raises_rpc_error(-32603, "The base block header (3bb7ce5eba0be48939b7a521ac1ba9316afee2c7bada3a0cca24188e6d7d96c0) must appear in the headers chain. Make sure all headers are syncing, and call this RPC again.", + node.loadtxoutset, + valid_snapshot_path) + def test_invalid_chainstate_scenarios(self): self.log.info("Test different scenarios of invalid snapshot chainstate in datadir") @@ -166,26 +172,12 @@ class AssumeutxoTest(BitcoinTestFramework): for n in self.nodes: n.setmocktime(n.getblockheader(n.getbestblockhash())['time']) - self.sync_blocks() - # Generate a series of blocks that `n0` will have in the snapshot, - # but that n1 doesn't yet see. In order for the snapshot to activate, - # though, we have to ferry over the new headers to n1 so that it - # isn't waiting forever to see the header of the snapshot's base block - # while disconnected from n0. + # but that n1 and n2 don't yet see. for i in range(100): if i % 3 == 0: self.mini_wallet.send_self_transfer(from_node=n0) self.generate(n0, nblocks=1, sync_fun=self.no_op) - newblock = n0.getblock(n0.getbestblockhash(), 0) - - # make n1 aware of the new header, but don't give it the block. - n1.submitheader(newblock) - n2.submitheader(newblock) - - # Ensure everyone is seeing the same headers. - for n in self.nodes: - assert_equal(n.getblockchaininfo()["headers"], SNAPSHOT_BASE_HEIGHT) self.log.info("-- Testing assumeutxo + some indexes + pruning") @@ -195,6 +187,23 @@ class AssumeutxoTest(BitcoinTestFramework): self.log.info(f"Creating a UTXO snapshot at height {SNAPSHOT_BASE_HEIGHT}") dump_output = n0.dumptxoutset('utxos.dat') + self.log.info("Test loading snapshot when headers are not synced") + self.test_headers_not_synced(dump_output['path']) + + # In order for the snapshot to activate, we have to ferry over the new + # headers to n1 and n2 so that they see the header of the snapshot's + # base block while disconnected from n0. + for i in range(1, 300): + block = n0.getblock(n0.getblockhash(i), 0) + # make n1 and n2 aware of the new header, but don't give them the + # block. + n1.submitheader(block) + n2.submitheader(block) + + # Ensure everyone is seeing the same headers. + for n in self.nodes: + assert_equal(n.getblockchaininfo()["headers"], SNAPSHOT_BASE_HEIGHT) + assert_equal( dump_output['txoutset_hash'], "a4bf3407ccb2cc0145c49ebba8fa91199f8a3903daf0883875941497d2493c27") diff --git a/test/functional/feature_proxy.py b/test/functional/feature_proxy.py index 662007d65e..7a6f639021 100755 --- a/test/functional/feature_proxy.py +++ b/test/functional/feature_proxy.py @@ -17,6 +17,7 @@ Test plan: - support no authentication (other proxy) - support no authentication + user/pass authentication (Tor) - proxy on IPv6 + - proxy over unix domain sockets - Create various proxies (as threads) - Create nodes that connect to them @@ -39,7 +40,9 @@ addnode connect to a CJDNS address - Test passing unknown -onlynet """ +import os import socket +import tempfile from test_framework.socks5 import Socks5Configuration, Socks5Command, Socks5Server, AddressType from test_framework.test_framework import BitcoinTestFramework @@ -47,7 +50,7 @@ from test_framework.util import ( assert_equal, p2p_port, ) -from test_framework.netutil import test_ipv6_local +from test_framework.netutil import test_ipv6_local, test_unix_socket # Networks returned by RPC getpeerinfo. NET_UNROUTABLE = "not_publicly_routable" @@ -60,14 +63,17 @@ NET_CJDNS = "cjdns" # Networks returned by RPC getnetworkinfo, defined in src/rpc/net.cpp::GetNetworksInfo() NETWORKS = frozenset({NET_IPV4, NET_IPV6, NET_ONION, NET_I2P, NET_CJDNS}) +# Use the shortest temp path possible since UNIX sockets may have as little as 92-char limit +socket_path = tempfile.NamedTemporaryFile().name class ProxyTest(BitcoinTestFramework): def set_test_params(self): - self.num_nodes = 5 + self.num_nodes = 7 self.setup_clean_chain = True def setup_nodes(self): self.have_ipv6 = test_ipv6_local() + self.have_unix_sockets = test_unix_socket() # Create two proxies on different ports # ... one unauthenticated self.conf1 = Socks5Configuration() @@ -89,6 +95,15 @@ class ProxyTest(BitcoinTestFramework): else: self.log.warning("Testing without local IPv6 support") + if self.have_unix_sockets: + self.conf4 = Socks5Configuration() + self.conf4.af = socket.AF_UNIX + self.conf4.addr = socket_path + self.conf4.unauth = True + self.conf4.auth = True + else: + self.log.warning("Testing without local unix domain sockets support") + self.serv1 = Socks5Server(self.conf1) self.serv1.start() self.serv2 = Socks5Server(self.conf2) @@ -96,6 +111,9 @@ class ProxyTest(BitcoinTestFramework): if self.have_ipv6: self.serv3 = Socks5Server(self.conf3) self.serv3.start() + if self.have_unix_sockets: + self.serv4 = Socks5Server(self.conf4) + self.serv4.start() # We will not try to connect to this. self.i2p_sam = ('127.0.0.1', 7656) @@ -109,10 +127,15 @@ class ProxyTest(BitcoinTestFramework): ['-listen', f'-proxy={self.conf2.addr[0]}:{self.conf2.addr[1]}','-proxyrandomize=1'], [], ['-listen', f'-proxy={self.conf1.addr[0]}:{self.conf1.addr[1]}','-proxyrandomize=1', - '-cjdnsreachable'] + '-cjdnsreachable'], + [], + [] ] if self.have_ipv6: args[3] = ['-listen', f'-proxy=[{self.conf3.addr[0]}]:{self.conf3.addr[1]}','-proxyrandomize=0', '-noonion'] + if self.have_unix_sockets: + args[5] = ['-listen', f'-proxy=unix:{socket_path}'] + args[6] = ['-listen', f'-onion=unix:{socket_path}'] self.add_nodes(self.num_nodes, extra_args=args) self.start_nodes() @@ -124,7 +147,7 @@ class ProxyTest(BitcoinTestFramework): def node_test(self, node, *, proxies, auth, test_onion, test_cjdns): rv = [] addr = "15.61.23.23:1234" - self.log.debug(f"Test: outgoing IPv4 connection through node for address {addr}") + self.log.debug(f"Test: outgoing IPv4 connection through node {node.index} for address {addr}") node.addnode(addr, "onetry") cmd = proxies[0].queue.get() assert isinstance(cmd, Socks5Command) @@ -140,7 +163,7 @@ class ProxyTest(BitcoinTestFramework): if self.have_ipv6: addr = "[1233:3432:2434:2343:3234:2345:6546:4534]:5443" - self.log.debug(f"Test: outgoing IPv6 connection through node for address {addr}") + self.log.debug(f"Test: outgoing IPv6 connection through node {node.index} for address {addr}") node.addnode(addr, "onetry") cmd = proxies[1].queue.get() assert isinstance(cmd, Socks5Command) @@ -156,7 +179,7 @@ class ProxyTest(BitcoinTestFramework): if test_onion: addr = "pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion:8333" - self.log.debug(f"Test: outgoing onion connection through node for address {addr}") + self.log.debug(f"Test: outgoing onion connection through node {node.index} for address {addr}") node.addnode(addr, "onetry") cmd = proxies[2].queue.get() assert isinstance(cmd, Socks5Command) @@ -171,7 +194,7 @@ class ProxyTest(BitcoinTestFramework): if test_cjdns: addr = "[fc00:1:2:3:4:5:6:7]:8888" - self.log.debug(f"Test: outgoing CJDNS connection through node for address {addr}") + self.log.debug(f"Test: outgoing CJDNS connection through node {node.index} for address {addr}") node.addnode(addr, "onetry") cmd = proxies[1].queue.get() assert isinstance(cmd, Socks5Command) @@ -185,7 +208,7 @@ class ProxyTest(BitcoinTestFramework): self.network_test(node, addr, network=NET_CJDNS) addr = "node.noumenon:8333" - self.log.debug(f"Test: outgoing DNS name connection through node for address {addr}") + self.log.debug(f"Test: outgoing DNS name connection through node {node.index} for address {addr}") node.addnode(addr, "onetry") cmd = proxies[3].queue.get() assert isinstance(cmd, Socks5Command) @@ -230,6 +253,12 @@ class ProxyTest(BitcoinTestFramework): proxies=[self.serv1, self.serv1, self.serv1, self.serv1], auth=False, test_onion=True, test_cjdns=True) + if self.have_unix_sockets: + self.node_test(self.nodes[5], + proxies=[self.serv4, self.serv4, self.serv4, self.serv4], + auth=True, test_onion=True, test_cjdns=False) + + def networks_dict(d): r = {} for x in d['networks']: @@ -315,6 +344,37 @@ class ProxyTest(BitcoinTestFramework): assert_equal(n4['i2p']['reachable'], False) assert_equal(n4['cjdns']['reachable'], True) + if self.have_unix_sockets: + n5 = networks_dict(nodes_network_info[5]) + assert_equal(NETWORKS, n5.keys()) + for net in NETWORKS: + if net == NET_I2P: + expected_proxy = '' + expected_randomize = False + else: + expected_proxy = 'unix:' + self.conf4.addr # no port number + expected_randomize = True + assert_equal(n5[net]['proxy'], expected_proxy) + assert_equal(n5[net]['proxy_randomize_credentials'], expected_randomize) + assert_equal(n5['onion']['reachable'], True) + assert_equal(n5['i2p']['reachable'], False) + assert_equal(n5['cjdns']['reachable'], False) + + n6 = networks_dict(nodes_network_info[6]) + assert_equal(NETWORKS, n6.keys()) + for net in NETWORKS: + if net != NET_ONION: + expected_proxy = '' + expected_randomize = False + else: + expected_proxy = 'unix:' + self.conf4.addr # no port number + expected_randomize = True + assert_equal(n6[net]['proxy'], expected_proxy) + assert_equal(n6[net]['proxy_randomize_credentials'], expected_randomize) + assert_equal(n6['onion']['reachable'], True) + assert_equal(n6['i2p']['reachable'], False) + assert_equal(n6['cjdns']['reachable'], False) + self.stop_node(1) self.log.info("Test passing invalid -proxy hostname raises expected init error") @@ -383,6 +443,18 @@ class ProxyTest(BitcoinTestFramework): msg = "Error: Unknown network specified in -onlynet: 'abc'" self.nodes[1].assert_start_raises_init_error(expected_msg=msg) + self.log.info("Test passing too-long unix path to -proxy raises init error") + self.nodes[1].extra_args = [f"-proxy=unix:{'x' * 1000}"] + if self.have_unix_sockets: + msg = f"Error: Invalid -proxy address or hostname: 'unix:{'x' * 1000}'" + else: + # If unix sockets are not supported, the file path is incorrectly interpreted as host:port + msg = f"Error: Invalid port specified in -proxy: 'unix:{'x' * 1000}'" + self.nodes[1].assert_start_raises_init_error(expected_msg=msg) + + # Cleanup socket path we established outside the individual test directory. + if self.have_unix_sockets: + os.unlink(socket_path) if __name__ == '__main__': ProxyTest().main() diff --git a/test/functional/test_framework/netutil.py b/test/functional/test_framework/netutil.py index 30a4a58d6f..08d41fe97f 100644 --- a/test/functional/test_framework/netutil.py +++ b/test/functional/test_framework/netutil.py @@ -158,3 +158,12 @@ def test_ipv6_local(): except socket.error: have_ipv6 = False return have_ipv6 + +def test_unix_socket(): + '''Return True if UNIX sockets are available on this platform.''' + try: + socket.AF_UNIX + except AttributeError: + return False + else: + return True diff --git a/test/functional/wallet_assumeutxo.py b/test/functional/wallet_assumeutxo.py index 3c1a997bd1..30396da015 100755 --- a/test/functional/wallet_assumeutxo.py +++ b/test/functional/wallet_assumeutxo.py @@ -62,8 +62,6 @@ class AssumeutxoTest(BitcoinTestFramework): for n in self.nodes: n.setmocktime(n.getblockheader(n.getbestblockhash())['time']) - self.sync_blocks() - n0.createwallet('w') w = n0.get_wallet_rpc("w") |