13
13
msg_addr ,
14
14
msg_getaddr
15
15
)
16
- from test_framework .p2p import P2PInterface
17
- from test_framework .test_framework import BitcoinTestFramework
18
- from test_framework .util import (
19
- assert_equal ,
20
- assert_greater_than_or_equal ,
16
+ from test_framework .p2p import (
17
+ P2PInterface ,
18
+ p2p_lock ,
21
19
)
22
- import os
20
+ from test_framework .test_framework import BitcoinTestFramework
21
+ from test_framework .util import assert_equal
23
22
import random
24
23
import time
25
24
26
25
27
26
class AddrReceiver (P2PInterface ):
28
27
num_ipv4_received = 0
29
28
test_addr_contents = False
29
+ _tokens = 1
30
30
31
31
def __init__ (self , test_addr_contents = False ):
32
32
super ().__init__ ()
@@ -43,6 +43,20 @@ def on_addr(self, message):
43
43
raise AssertionError ("Invalid addr.port of {} (8333-8342 expected)" .format (addr .port ))
44
44
assert addr .ip .startswith ('123.123.123.' )
45
45
46
+ def on_getaddr (self , message ):
47
+ # When the node sends us a getaddr, it increments the addr relay tokens for the connection by 1000
48
+ self ._tokens += 1000
49
+
50
+ @property
51
+ def tokens (self ):
52
+ with p2p_lock :
53
+ return self ._tokens
54
+
55
+ def increment_tokens (self , n ):
56
+ # When we move mocktime forward, the node increments the addr relay tokens for its peers
57
+ with p2p_lock :
58
+ self ._tokens += n
59
+
46
60
def addr_received (self ):
47
61
return self .num_ipv4_received != 0
48
62
@@ -225,67 +239,61 @@ def blocksonly_mode_tests(self):
225
239
226
240
self .nodes [0 ].disconnect_p2ps ()
227
241
242
+ def send_addrs_and_test_rate_limiting (self , peer , no_relay , new_addrs , total_addrs ):
243
+ """Send an addr message and check that the number of addresses processed and rate-limited is as expected"""
244
+
245
+ peer .send_and_ping (self .setup_rand_addr_msg (new_addrs ))
246
+
247
+ peerinfo = self .nodes [0 ].getpeerinfo ()[0 ]
248
+ addrs_processed = peerinfo ['addr_processed' ]
249
+ addrs_rate_limited = peerinfo ['addr_rate_limited' ]
250
+ self .log .debug (f"addrs_processed = { addrs_processed } , addrs_rate_limited = { addrs_rate_limited } " )
251
+
252
+ if no_relay :
253
+ assert_equal (addrs_processed , 0 )
254
+ assert_equal (addrs_rate_limited , 0 )
255
+ else :
256
+ assert_equal (addrs_processed , min (total_addrs , peer .tokens ))
257
+ assert_equal (addrs_rate_limited , max (0 , total_addrs - peer .tokens ))
258
+
228
259
def rate_limit_tests (self ):
229
260
230
- for contype , tokens , no_relay in [("outbound-full-relay" , 1001 , False ), ("block-relay-only" , 0 , True ), ("inbound" , 1 , False )]:
261
+ self .mocktime = int (time .time ())
262
+ self .restart_node (0 , [])
263
+ self .nodes [0 ].setmocktime (self .mocktime )
264
+
265
+ for contype , no_relay in [("outbound-full-relay" , False ), ("block-relay-only" , True ), ("inbound" , False )]:
231
266
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
267
if contype == "inbound" :
238
268
peer = self .nodes [0 ].add_p2p_connection (AddrReceiver ())
239
269
else :
240
270
peer = self .nodes [0 ].add_outbound_p2p_connection (AddrReceiver (), p2p_idx = 0 , connection_type = contype )
241
271
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 )
272
+ # Send 600 addresses. For all but the block-relay-only peer this should result in addresses being processed.
273
+ self .send_addrs_and_test_rate_limiting (peer , no_relay , 600 , 600 )
252
274
253
275
# 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.
276
+ # process up to 1001 incoming addresses), this means more addresses will be processed.
277
+ self .send_addrs_and_test_rate_limiting (peer , no_relay , 600 , 1200 )
278
+
279
+ # Send 10 more. As we reached the processing limit for all nodes, no more addresses should be procesesd.
280
+ self .send_addrs_and_test_rate_limiting (peer , no_relay , 10 , 1210 )
281
+
282
+ # Advance the time by 100 seconds, permitting the processing of 10 more addresses.
283
+ # Send 200 and verify that 10 are processed.
269
284
self .mocktime += 100
270
285
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).
286
+ peer .increment_tokens (10 )
287
+
288
+ self .send_addrs_and_test_rate_limiting (peer , no_relay , 200 , 1410 )
289
+
290
+ # Advance the time by 1000 seconds, permitting the processing of 100 more addresses.
291
+ # Send 200 and verify that 100 are processed.
280
292
self .mocktime += 1000
281
293
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 )
294
+ peer .increment_tokens (100 )
295
+
296
+ self .send_addrs_and_test_rate_limiting (peer , no_relay , 200 , 1610 )
289
297
290
298
self .nodes [0 ].disconnect_p2ps ()
291
299
0 commit comments