Skip to content

Commit 2ff8f4d

Browse files
naumenkogsjonatack
andcommitted
Add tests for addr destination rotation
Check that within 24h addr of a given node is forwarded to the same peer(s), and then the destination is rotated every 24h. Co-authored-by: Jon Atack <[email protected]>
1 parent 77ccb7f commit 2ff8f4d

File tree

1 file changed

+65
-1
lines changed

1 file changed

+65
-1
lines changed

test/functional/p2p_addr_relay.py

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,19 @@
2121
P2P_SERVICES,
2222
)
2323
from test_framework.test_framework import BitcoinTestFramework
24-
from test_framework.util import assert_equal, assert_greater_than
24+
from test_framework.util import (
25+
assert_equal,
26+
assert_greater_than,
27+
assert_greater_than_or_equal
28+
)
29+
30+
ONE_MINUTE = 60
31+
TEN_MINUTES = 10 * ONE_MINUTE
32+
ONE_HOUR = 60 * ONE_MINUTE
33+
TWO_HOURS = 2 * ONE_HOUR
34+
ONE_DAY = 24 * ONE_HOUR
2535

36+
ADDR_DESTINATIONS_THRESHOLD = 4
2637

2738
class AddrReceiver(P2PInterface):
2839
num_ipv4_received = 0
@@ -85,6 +96,9 @@ def run_test(self):
8596
self.relay_tests()
8697
self.inbound_blackhole_tests()
8798

99+
self.destination_rotates_once_in_24_hours_test()
100+
self.destination_rotates_more_than_once_over_several_days_test()
101+
88102
# This test populates the addrman, which can impact the node's behavior
89103
# in subsequent tests
90104
self.getaddr_tests()
@@ -362,6 +376,56 @@ def rate_limit_tests(self):
362376

363377
self.nodes[0].disconnect_p2ps()
364378

379+
def get_nodes_that_received_addr(self, peer, receiver_peer, addr_receivers,
380+
time_interval_1, time_interval_2):
381+
382+
# Clean addr response related to the initial getaddr. There is no way to avoid initial
383+
# getaddr because the peer won't self-announce then.
384+
for addr_receiver in addr_receivers:
385+
addr_receiver.num_ipv4_received = 0
386+
387+
for _ in range(10):
388+
self.mocktime += time_interval_1
389+
self.msg.addrs[0].time = self.mocktime + TEN_MINUTES
390+
self.nodes[0].setmocktime(self.mocktime)
391+
with self.nodes[0].assert_debug_log(['received: addr (31 bytes) peer=0']):
392+
peer.send_and_ping(self.msg)
393+
self.mocktime += time_interval_2
394+
self.nodes[0].setmocktime(self.mocktime)
395+
receiver_peer.sync_with_ping()
396+
return [node for node in addr_receivers if node.addr_received()]
397+
398+
def destination_rotates_once_in_24_hours_test(self):
399+
self.restart_node(0, [])
400+
401+
self.log.info('Test within 24 hours an addr relay destination is rotated at most once')
402+
self.mocktime = int(time.time())
403+
self.msg = self.setup_addr_msg(1)
404+
self.addr_receivers = []
405+
peer = self.nodes[0].add_p2p_connection(P2PInterface())
406+
receiver_peer = self.nodes[0].add_p2p_connection(AddrReceiver())
407+
addr_receivers = [self.nodes[0].add_p2p_connection(AddrReceiver()) for _ in range(20)]
408+
nodes_received_addr = self.get_nodes_that_received_addr(peer, receiver_peer, addr_receivers, 0, TWO_HOURS) # 10 intervals of 2 hours
409+
# Per RelayAddress, we would announce these addrs to 2 destinations per day.
410+
# Since it's at most one rotation, at most 4 nodes can receive ADDR.
411+
assert_greater_than_or_equal(ADDR_DESTINATIONS_THRESHOLD, len(nodes_received_addr))
412+
self.nodes[0].disconnect_p2ps()
413+
414+
def destination_rotates_more_than_once_over_several_days_test(self):
415+
self.restart_node(0, [])
416+
417+
self.log.info('Test after several days an addr relay destination is rotated more than once')
418+
self.msg = self.setup_addr_msg(1)
419+
peer = self.nodes[0].add_p2p_connection(P2PInterface())
420+
receiver_peer = self.nodes[0].add_p2p_connection(AddrReceiver())
421+
addr_receivers = [self.nodes[0].add_p2p_connection(AddrReceiver()) for _ in range(20)]
422+
# 10 intervals of 1 day (+ 1 hour, which should be enough to cover 30-min Poisson in most cases)
423+
nodes_received_addr = self.get_nodes_that_received_addr(peer, receiver_peer, addr_receivers, ONE_DAY, ONE_HOUR)
424+
# Now that there should have been more than one rotation, more than
425+
# ADDR_DESTINATIONS_THRESHOLD nodes should have received ADDR.
426+
assert_greater_than(len(nodes_received_addr), ADDR_DESTINATIONS_THRESHOLD)
427+
self.nodes[0].disconnect_p2ps()
428+
365429

366430
if __name__ == '__main__':
367431
AddrTest().main()

0 commit comments

Comments
 (0)