Skip to content

Commit ba8ab4f

Browse files
committed
test: cover addrv2 support in anchors.dat with a TorV3 address
1 parent b4bee4b commit ba8ab4f

File tree

1 file changed

+59
-4
lines changed

1 file changed

+59
-4
lines changed

test/functional/feature_anchors.py

+59-4
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,15 @@
66

77
import os
88

9-
from test_framework.p2p import P2PInterface
9+
from test_framework.p2p import P2PInterface, P2P_SERVICES
10+
from test_framework.socks5 import Socks5Configuration, Socks5Server
11+
from test_framework.messages import CAddress, hash256
1012
from test_framework.test_framework import BitcoinTestFramework
11-
from test_framework.util import check_node_connections
13+
from test_framework.util import check_node_connections, assert_equal, p2p_port
1214

1315
INBOUND_CONNECTIONS = 5
1416
BLOCK_RELAY_CONNECTIONS = 2
17+
ONION_ADDR = "pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion:8333"
1518

1619

1720
class AnchorsTest(BitcoinTestFramework):
@@ -54,7 +57,7 @@ def run_test(self):
5457
else:
5558
inbound_nodes_port.append(hex(int(addr_split[1]))[2:])
5659

57-
self.log.info("Stop node 0")
60+
self.log.debug("Stop node")
5861
self.stop_node(0)
5962

6063
# It should contain only the block-relay-only addresses
@@ -78,12 +81,64 @@ def run_test(self):
7881
tweaked_contents[20:20] = b'1'
7982
out_file_handler.write(bytes(tweaked_contents))
8083

81-
self.log.info("Start node")
84+
self.log.debug("Start node")
8285
self.start_node(0)
8386

8487
self.log.info("When node starts, check if anchors.dat doesn't exist anymore")
8588
assert not os.path.exists(node_anchors_path)
8689

90+
self.log.info("Ensure addrv2 support")
91+
# Use proxies to catch outbound connections to networks with 256-bit addresses
92+
onion_conf = Socks5Configuration()
93+
onion_conf.auth = True
94+
onion_conf.unauth = True
95+
onion_conf.addr = ('127.0.0.1', p2p_port(self.num_nodes))
96+
onion_conf.keep_alive = True
97+
onion_proxy = Socks5Server(onion_conf)
98+
onion_proxy.start()
99+
self.restart_node(0, extra_args=[f"-onion={onion_conf.addr[0]}:{onion_conf.addr[1]}"])
100+
101+
self.log.info("Add 256-bit-address block-relay-only connections to node")
102+
self.nodes[0].addconnection(ONION_ADDR, 'block-relay-only')
103+
104+
self.log.debug("Stop node")
105+
with self.nodes[0].assert_debug_log([f"DumpAnchors: Flush 1 outbound block-relay-only peer addresses to anchors.dat"]):
106+
self.stop_node(0)
107+
# Manually close keep_alive proxy connection
108+
onion_proxy.stop()
109+
110+
self.log.info("Check for addrv2 addresses in anchors.dat")
111+
caddr = CAddress()
112+
caddr.net = CAddress.NET_TORV3
113+
caddr.ip, port_str = ONION_ADDR.split(":")
114+
caddr.port = int(port_str)
115+
# TorV3 addrv2 serialization:
116+
# time(4) | services(1) | networkID(1) | address length(1) | address(32)
117+
expected_pubkey = caddr.serialize_v2()[7:39].hex()
118+
119+
# position of services byte of first addr in anchors.dat
120+
# network magic, vector length, version, nTime
121+
services_index = 4 + 1 + 4 + 4
122+
data = bytes()
123+
with open(node_anchors_path, "rb") as file_handler:
124+
data = file_handler.read()
125+
assert_equal(data[services_index], 0x00) # services == NONE
126+
anchors2 = data.hex()
127+
assert expected_pubkey in anchors2
128+
129+
with open(node_anchors_path, "wb") as file_handler:
130+
# Modify service flags for this address even though we never connected to it.
131+
# This is necessary because on restart we will not attempt an anchor connection
132+
# to a host without our required services, even if its address is in the anchors.dat file
133+
new_data = bytearray(data)[:-32]
134+
new_data[services_index] = P2P_SERVICES
135+
new_data_hash = hash256(new_data)
136+
file_handler.write(new_data + new_data_hash)
137+
138+
self.log.info("Restarting node attempts to reconnect to anchors")
139+
with self.nodes[0].assert_debug_log([f"Trying to make an anchor connection to {ONION_ADDR}"]):
140+
self.start_node(0, extra_args=[f"-onion={onion_conf.addr[0]}:{onion_conf.addr[1]}"])
141+
87142

88143
if __name__ == "__main__":
89144
AnchorsTest().main()

0 commit comments

Comments
 (0)