4
4
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
5
"""Test behavior of headers messages to announce blocks.
6
6
7
- Setup:
7
+ Setup:
8
8
9
9
- Two nodes, two p2p connections to node0. One p2p connection should only ever
10
10
receive inv's (omitted from testing description below, this is our control).
83
83
e. Announce one more that doesn't connect.
84
84
Expect: disconnect.
85
85
"""
86
-
87
- from test_framework .mininode import *
88
- from test_framework .test_framework import BitcoinTestFramework
89
- from test_framework .util import *
90
86
from test_framework .blocktools import create_block , create_coinbase
87
+ from test_framework .mininode import (
88
+ CBlockHeader ,
89
+ CInv ,
90
+ NODE_WITNESS ,
91
+ NetworkThread ,
92
+ NodeConnCB ,
93
+ mininode_lock ,
94
+ msg_block ,
95
+ msg_getblocks ,
96
+ msg_getdata ,
97
+ msg_getheaders ,
98
+ msg_headers ,
99
+ msg_inv ,
100
+ msg_sendheaders ,
101
+ )
102
+ from test_framework .test_framework import BitcoinTestFramework
103
+ from test_framework .util import (
104
+ assert_equal ,
105
+ sync_blocks ,
106
+ wait_until ,
107
+ )
91
108
109
+ DIRECT_FETCH_RESPONSE_TIME = 0.05
92
110
93
- direct_fetch_response_time = 0.05
94
-
95
- class TestNode (NodeConnCB ):
111
+ class BaseNode (NodeConnCB ):
96
112
def __init__ (self ):
97
113
super ().__init__ ()
98
114
self .block_announced = False
@@ -136,8 +152,8 @@ def on_headers(self, conn, message):
136
152
# right header or the right inv
137
153
# inv and headers should be lists of block hashes
138
154
def check_last_announcement (self , headers = None , inv = None ):
139
- expect_headers = headers if headers != None else []
140
- expect_inv = inv if inv != None else []
155
+ expect_headers = headers if headers is not None else []
156
+ expect_inv = inv if inv is not None else []
141
157
test_function = lambda : self .block_announced
142
158
wait_until (test_function , timeout = 60 , lock = mininode_lock )
143
159
with mininode_lock :
@@ -153,7 +169,7 @@ def check_last_announcement(self, headers=None, inv=None):
153
169
hash_headers = []
154
170
if "headers" in self .last_message :
155
171
# treat headers as a list of block hashes
156
- hash_headers = [ x .sha256 for x in self .last_message ["headers" ].headers ]
172
+ hash_headers = [x .sha256 for x in self .last_message ["headers" ].headers ]
157
173
if hash_headers != expect_headers :
158
174
success = False
159
175
@@ -176,7 +192,7 @@ def wait_for_block_announcement(self, block_hash, timeout=60):
176
192
177
193
def send_header_for_blocks (self , new_blocks ):
178
194
headers_message = msg_headers ()
179
- headers_message .headers = [ CBlockHeader (b ) for b in new_blocks ]
195
+ headers_message .headers = [CBlockHeader (b ) for b in new_blocks ]
180
196
self .send_message (headers_message )
181
197
182
198
def send_getblocks (self , locator ):
@@ -202,27 +218,27 @@ def mine_blocks(self, count):
202
218
# to-be-reorged-out blocks are mined, so that we don't break later tests.
203
219
# return the list of block hashes newly mined
204
220
def mine_reorg (self , length ):
205
- self .nodes [0 ].generate (length ) # make sure all invalidated blocks are node0's
221
+ self .nodes [0 ].generate (length ) # make sure all invalidated blocks are node0's
206
222
sync_blocks (self .nodes , wait = 0.1 )
207
223
for x in self .nodes [0 ].p2ps :
208
224
x .wait_for_block_announcement (int (self .nodes [0 ].getbestblockhash (), 16 ))
209
225
x .clear_last_announcement ()
210
226
211
227
tip_height = self .nodes [1 ].getblockcount ()
212
- hash_to_invalidate = self .nodes [1 ].getblockhash (tip_height - (length - 1 ))
228
+ hash_to_invalidate = self .nodes [1 ].getblockhash (tip_height - (length - 1 ))
213
229
self .nodes [1 ].invalidateblock (hash_to_invalidate )
214
- all_hashes = self .nodes [1 ].generate (length + 1 ) # Must be longer than the orig chain
230
+ all_hashes = self .nodes [1 ].generate (length + 1 ) # Must be longer than the orig chain
215
231
sync_blocks (self .nodes , wait = 0.1 )
216
232
return [int (x , 16 ) for x in all_hashes ]
217
233
218
234
def run_test (self ):
219
235
# Setup the p2p connections and start up the network thread.
220
- inv_node = self .nodes [0 ].add_p2p_connection (TestNode ())
236
+ inv_node = self .nodes [0 ].add_p2p_connection (BaseNode ())
221
237
# Set nServices to 0 for test_node, so no block download will occur outside of
222
238
# direct fetching
223
- test_node = self .nodes [0 ].add_p2p_connection (TestNode (), services = NODE_WITNESS )
239
+ test_node = self .nodes [0 ].add_p2p_connection (BaseNode (), services = NODE_WITNESS )
224
240
225
- NetworkThread ().start () # Start up network handling in another thread
241
+ NetworkThread ().start () # Start up network handling in another thread
226
242
227
243
# Test logic begins here
228
244
inv_node .wait_for_verack ()
@@ -275,18 +291,18 @@ def test_nonnull_locators(self, test_node, inv_node):
275
291
test_node .get_headers (locator = [old_tip ], hashstop = tip )
276
292
test_node .get_data ([tip ])
277
293
test_node .wait_for_block (tip )
278
- test_node .clear_last_announcement () # since we requested headers...
294
+ test_node .clear_last_announcement () # since we requested headers...
279
295
elif i == 2 :
280
296
# this time announce own block via headers
281
297
height = self .nodes [0 ].getblockcount ()
282
298
last_time = self .nodes [0 ].getblock (self .nodes [0 ].getbestblockhash ())['time' ]
283
299
block_time = last_time + 1
284
- new_block = create_block (tip , create_coinbase (height + 1 ), block_time )
300
+ new_block = create_block (tip , create_coinbase (height + 1 ), block_time )
285
301
new_block .solve ()
286
302
test_node .send_header_for_blocks ([new_block ])
287
303
test_node .wait_for_getdata ([new_block .sha256 ])
288
304
test_node .send_message (msg_block (new_block ))
289
- test_node .sync_with_ping () # make sure this block is processed
305
+ test_node .sync_with_ping () # make sure this block is processed
290
306
inv_node .clear_last_announcement ()
291
307
test_node .clear_last_announcement ()
292
308
@@ -305,7 +321,7 @@ def test_nonnull_locators(self, test_node, inv_node):
305
321
assert_equal (inv_node .check_last_announcement (inv = [tip ]), True )
306
322
assert_equal (test_node .check_last_announcement (headers = [tip ]), True )
307
323
308
- height = self .nodes [0 ].getblockcount ()+ 1
324
+ height = self .nodes [0 ].getblockcount () + 1
309
325
block_time += 10 # Advance far enough ahead
310
326
for i in range (10 ):
311
327
# Mine i blocks, and alternate announcing either via
@@ -314,7 +330,7 @@ def test_nonnull_locators(self, test_node, inv_node):
314
330
# with block header, even though the blocks are never requested
315
331
for j in range (2 ):
316
332
blocks = []
317
- for b in range (i + 1 ):
333
+ for b in range (i + 1 ):
318
334
blocks .append (create_block (tip , create_coinbase (height ), block_time ))
319
335
blocks [- 1 ].solve ()
320
336
tip = blocks [- 1 ].sha256
@@ -328,7 +344,7 @@ def test_nonnull_locators(self, test_node, inv_node):
328
344
test_node .send_header_for_blocks (blocks )
329
345
# Test that duplicate inv's won't result in duplicate
330
346
# getdata requests, or duplicate headers announcements
331
- [ inv_node .send_block_inv (x .sha256 ) for x in blocks ]
347
+ [inv_node .send_block_inv (x .sha256 ) for x in blocks ]
332
348
test_node .wait_for_getdata ([x .sha256 for x in blocks ])
333
349
inv_node .sync_with_ping ()
334
350
else :
@@ -339,7 +355,7 @@ def test_nonnull_locators(self, test_node, inv_node):
339
355
# getdata requests (the check is further down)
340
356
inv_node .send_header_for_blocks (blocks )
341
357
inv_node .sync_with_ping ()
342
- [ test_node .send_message (msg_block (x )) for x in blocks ]
358
+ [test_node .send_message (msg_block (x )) for x in blocks ]
343
359
test_node .sync_with_ping ()
344
360
inv_node .sync_with_ping ()
345
361
# This block should not be announced to the inv node (since it also
@@ -365,7 +381,7 @@ def test_nonnull_locators(self, test_node, inv_node):
365
381
assert_equal (inv_node .check_last_announcement (inv = [tip ]), True )
366
382
assert_equal (test_node .check_last_announcement (headers = new_block_hashes ), True )
367
383
368
- block_time += 8
384
+ block_time += 8
369
385
370
386
# Mine a too-large reorg, which should be announced with a single inv
371
387
new_block_hashes = self .mine_reorg (length = 8 )
@@ -379,7 +395,7 @@ def test_nonnull_locators(self, test_node, inv_node):
379
395
fork_point = int (fork_point , 16 )
380
396
381
397
# Use getblocks/getdata
382
- test_node .send_getblocks (locator = [fork_point ])
398
+ test_node .send_getblocks (locator = [fork_point ])
383
399
assert_equal (test_node .check_last_announcement (inv = new_block_hashes ), True )
384
400
test_node .get_data (new_block_hashes )
385
401
test_node .wait_for_block (new_block_hashes [- 1 ])
@@ -403,7 +419,7 @@ def test_nonnull_locators(self, test_node, inv_node):
403
419
test_node .get_data ([tip ])
404
420
test_node .wait_for_block (tip )
405
421
# This time, try sending either a getheaders to trigger resumption
406
- # of headers announcements, or mine a new block and inv it, also
422
+ # of headers announcements, or mine a new block and inv it, also
407
423
# triggering resumption of headers announcements.
408
424
if j == 0 :
409
425
test_node .get_headers (locator = [tip ], hashstop = 0 )
@@ -434,7 +450,7 @@ def test_nonnull_locators(self, test_node, inv_node):
434
450
height += 1
435
451
inv_node .send_message (msg_block (blocks [- 1 ]))
436
452
437
- inv_node .sync_with_ping () # Make sure blocks are processed
453
+ inv_node .sync_with_ping () # Make sure blocks are processed
438
454
test_node .last_message .pop ("getdata" , None )
439
455
test_node .send_header_for_blocks (blocks )
440
456
test_node .sync_with_ping ()
@@ -453,9 +469,9 @@ def test_nonnull_locators(self, test_node, inv_node):
453
469
454
470
test_node .send_header_for_blocks (blocks )
455
471
test_node .sync_with_ping ()
456
- test_node .wait_for_getdata ([x .sha256 for x in blocks ], timeout = direct_fetch_response_time )
472
+ test_node .wait_for_getdata ([x .sha256 for x in blocks ], timeout = DIRECT_FETCH_RESPONSE_TIME )
457
473
458
- [ test_node .send_message (msg_block (x )) for x in blocks ]
474
+ [test_node .send_message (msg_block (x )) for x in blocks ]
459
475
460
476
test_node .sync_with_ping ()
461
477
@@ -484,13 +500,13 @@ def test_nonnull_locators(self, test_node, inv_node):
484
500
# both blocks (same work as tip)
485
501
test_node .send_header_for_blocks (blocks [1 :2 ])
486
502
test_node .sync_with_ping ()
487
- test_node .wait_for_getdata ([x .sha256 for x in blocks [0 :2 ]], timeout = direct_fetch_response_time )
503
+ test_node .wait_for_getdata ([x .sha256 for x in blocks [0 :2 ]], timeout = DIRECT_FETCH_RESPONSE_TIME )
488
504
489
505
# Announcing 16 more headers should trigger direct fetch for 14 more
490
506
# blocks
491
507
test_node .send_header_for_blocks (blocks [2 :18 ])
492
508
test_node .sync_with_ping ()
493
- test_node .wait_for_getdata ([x .sha256 for x in blocks [2 :16 ]], timeout = direct_fetch_response_time )
509
+ test_node .wait_for_getdata ([x .sha256 for x in blocks [2 :16 ]], timeout = DIRECT_FETCH_RESPONSE_TIME )
494
510
495
511
# Announcing 1 more header should not trigger any response
496
512
test_node .last_message .pop ("getdata" , None )
@@ -502,7 +518,7 @@ def test_nonnull_locators(self, test_node, inv_node):
502
518
self .log .info ("Part 4: success!" )
503
519
504
520
# Now deliver all those blocks we announced.
505
- [ test_node .send_message (msg_block (x )) for x in blocks ]
521
+ [test_node .send_message (msg_block (x )) for x in blocks ]
506
522
507
523
self .log .info ("Part 5: Testing handling of unconnecting headers" )
508
524
# First we test that receipt of an unconnecting header doesn't prevent
@@ -524,15 +540,15 @@ def test_nonnull_locators(self, test_node, inv_node):
524
540
test_node .wait_for_getheaders ()
525
541
test_node .send_header_for_blocks (blocks )
526
542
test_node .wait_for_getdata ([x .sha256 for x in blocks ])
527
- [ test_node .send_message (msg_block (x )) for x in blocks ]
543
+ [test_node .send_message (msg_block (x )) for x in blocks ]
528
544
test_node .sync_with_ping ()
529
545
assert_equal (int (self .nodes [0 ].getbestblockhash (), 16 ), blocks [1 ].sha256 )
530
546
531
547
blocks = []
532
548
# Now we test that if we repeatedly don't send connecting headers, we
533
549
# don't go into an infinite loop trying to get them to connect.
534
550
MAX_UNCONNECTING_HEADERS = 10
535
- for j in range (MAX_UNCONNECTING_HEADERS + 1 ):
551
+ for j in range (MAX_UNCONNECTING_HEADERS + 1 ):
536
552
blocks .append (create_block (tip , create_coinbase (height ), block_time ))
537
553
blocks [- 1 ].solve ()
538
554
tip = blocks [- 1 ].sha256
@@ -554,11 +570,11 @@ def test_nonnull_locators(self, test_node, inv_node):
554
570
555
571
# Now try to see how many unconnecting headers we can send
556
572
# before we get disconnected. Should be 5*MAX_UNCONNECTING_HEADERS
557
- for i in range (5 * MAX_UNCONNECTING_HEADERS - 1 ):
573
+ for i in range (5 * MAX_UNCONNECTING_HEADERS - 1 ):
558
574
# Send a header that doesn't connect, check that we get a getheaders.
559
575
with mininode_lock :
560
576
test_node .last_message .pop ("getheaders" , None )
561
- test_node .send_header_for_blocks ([blocks [i % len (blocks )]])
577
+ test_node .send_header_for_blocks ([blocks [i % len (blocks )]])
562
578
test_node .wait_for_getheaders ()
563
579
564
580
# Eventually this stops working.
0 commit comments