aboutsummaryrefslogtreecommitdiff
path: root/test/functional
diff options
context:
space:
mode:
Diffstat (limited to 'test/functional')
-rwxr-xr-xtest/functional/feature_assumeutxo.py39
-rwxr-xr-xtest/functional/feature_proxy.py88
-rw-r--r--test/functional/test_framework/netutil.py9
-rwxr-xr-xtest/functional/wallet_assumeutxo.py2
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")