1717from test_framework .test_framework import BitcoinTestFramework
1818from test_framework .util import (
1919 assert_equal ,
20+ assert_greater_than_or_equal ,
2021)
22+ import os
23+ import random
2124import 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
212292if __name__ == '__main__' :
213293 AddrTest ().main ()
0 commit comments