Skip to content

Commit b4ece8a

Browse files
committed
Functional tests for addr rate limiting
1 parent 5648138 commit b4ece8a

File tree

1 file changed

+80
-0
lines changed

1 file changed

+80
-0
lines changed

test/functional/p2p_addr_relay.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@
1717
from test_framework.test_framework import BitcoinTestFramework
1818
from test_framework.util import (
1919
assert_equal,
20+
assert_greater_than_or_equal,
2021
)
22+
import os
23+
import random
2124
import time
2225

2326

@@ -60,6 +63,7 @@ def run_test(self):
6063
self.relay_tests()
6164
self.getaddr_tests()
6265
self.blocksonly_mode_tests()
66+
self.rate_limit_tests()
6367

6468
def setup_addr_msg(self, num):
6569
addrs = []
@@ -76,6 +80,19 @@ def setup_addr_msg(self, num):
7680
msg.addrs = addrs
7781
return msg
7882

83+
def setup_rand_addr_msg(self, num):
84+
addrs = []
85+
for i in range(num):
86+
addr = CAddress()
87+
addr.time = self.mocktime + i
88+
addr.nServices = NODE_NETWORK | NODE_WITNESS
89+
addr.ip = f"{random.randrange(128,169)}.{random.randrange(1,255)}.{random.randrange(1,255)}.{random.randrange(1,255)}"
90+
addr.port = 8333
91+
addrs.append(addr)
92+
msg = msg_addr()
93+
msg.addrs = addrs
94+
return msg
95+
7996
def send_addr_msg(self, source, msg, receivers):
8097
source.send_and_ping(msg)
8198
# pop m_next_addr_send timer
@@ -208,6 +225,69 @@ def blocksonly_mode_tests(self):
208225

209226
self.nodes[0].disconnect_p2ps()
210227

228+
def rate_limit_tests(self):
229+
230+
for contype, tokens, no_relay in [("outbound-full-relay", 1001, False), ("block-relay-only", 0, True), ("inbound", 1, False)]:
231+
self.log.info(f'Test rate limiting of addr processing for {contype} peers')
232+
self.stop_node(0)
233+
os.remove(os.path.join(self.nodes[0].datadir, "regtest", "peers.dat"))
234+
self.start_node(0, [])
235+
self.mocktime = int(time.time())
236+
self.nodes[0].setmocktime(self.mocktime)
237+
if contype == "inbound":
238+
peer = self.nodes[0].add_p2p_connection(AddrReceiver())
239+
else:
240+
peer = self.nodes[0].add_outbound_p2p_connection(AddrReceiver(), p2p_idx=0, connection_type=contype)
241+
242+
# Check that we start off with empty addrman
243+
addr_count_0 = len(self.nodes[0].getnodeaddresses(0))
244+
assert_equal(addr_count_0, 0)
245+
246+
# Send 600 addresses. For all but the block-relay-only peer this should result in at least 1 address.
247+
peer.send_and_ping(self.setup_rand_addr_msg(600))
248+
addr_count_1 = len(self.nodes[0].getnodeaddresses(0))
249+
assert_greater_than_or_equal(tokens, addr_count_1)
250+
assert_greater_than_or_equal(addr_count_0 + 600, addr_count_1)
251+
assert_equal(addr_count_1 > addr_count_0, tokens > 0)
252+
253+
# Send 600 more addresses. For the outbound-full-relay peer (which we send a GETADDR, and thus will
254+
# process up to 1001 incoming addresses), this means more entries will appear.
255+
peer.send_and_ping(self.setup_rand_addr_msg(600))
256+
addr_count_2 = len(self.nodes[0].getnodeaddresses(0))
257+
assert_greater_than_or_equal(tokens, addr_count_2)
258+
assert_greater_than_or_equal(addr_count_1 + 600, addr_count_2)
259+
assert_equal(addr_count_2 > addr_count_1, tokens > 600)
260+
261+
# Send 10 more. As we reached the processing limit for all nodes, this should have no effect.
262+
peer.send_and_ping(self.setup_rand_addr_msg(10))
263+
addr_count_3 = len(self.nodes[0].getnodeaddresses(0))
264+
assert_greater_than_or_equal(tokens, addr_count_3)
265+
assert_equal(addr_count_2, addr_count_3)
266+
267+
# Advance the time by 100 seconds, permitting the processing of 10 more addresses. Send 200,
268+
# but verify that no more than 10 are processed.
269+
self.mocktime += 100
270+
self.nodes[0].setmocktime(self.mocktime)
271+
new_tokens = 0 if no_relay else 10
272+
tokens += new_tokens
273+
peer.send_and_ping(self.setup_rand_addr_msg(200))
274+
addr_count_4 = len(self.nodes[0].getnodeaddresses(0))
275+
assert_greater_than_or_equal(tokens, addr_count_4)
276+
assert_greater_than_or_equal(addr_count_3 + new_tokens, addr_count_4)
277+
278+
# Advance the time by 1000 seconds, permitting the processing of 100 more addresses. Send 200,
279+
# but verify that no more than 100 are processed (and at least some).
280+
self.mocktime += 1000
281+
self.nodes[0].setmocktime(self.mocktime)
282+
new_tokens = 0 if no_relay else 100
283+
tokens += new_tokens
284+
peer.send_and_ping(self.setup_rand_addr_msg(200))
285+
addr_count_5 = len(self.nodes[0].getnodeaddresses(0))
286+
assert_greater_than_or_equal(tokens, addr_count_5)
287+
assert_greater_than_or_equal(addr_count_4 + new_tokens, addr_count_5)
288+
assert_equal(addr_count_5 > addr_count_4, not no_relay)
289+
290+
self.nodes[0].disconnect_p2ps()
211291

212292
if __name__ == '__main__':
213293
AddrTest().main()

0 commit comments

Comments
 (0)