Skip to content

Commit c4f857c

Browse files
committed
test: Extends wait_for_getheaders so a specific block hash can be checked
Previously, `wait_for_getheaders` would check whether a node had received **any** getheaders message. This implied that, if a test needed to check for a specific block hash within a headers message, it had to make sure that it was checking the desired message. This normally involved having to manually clear `last_message`. This method, apart from being too verbose, was error prone, given an undesired `getheaders` would make tests pass. This adds the ability to check for a specific block_hash within the last `getheaders` message.
1 parent 71c51c1 commit c4f857c

File tree

6 files changed

+28
-31
lines changed

6 files changed

+28
-31
lines changed

test/functional/mining_basic.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ def chain_tip(b_hash, *, status='headers-only', branchlen=1):
308308

309309
# Should ask for the block from a p2p node, if they announce the header as well:
310310
peer = node.add_p2p_connection(P2PDataStore())
311-
peer.wait_for_getheaders(timeout=5) # Drop the first getheaders
311+
peer.wait_for_getheaders(timeout=5, block_hash=block.hashPrevBlock)
312312
peer.send_blocks_and_test(blocks=[block], node=node)
313313
# Must be active now:
314314
assert chain_tip(block.hash, status='active', branchlen=0) in node.getchaintips()

test/functional/p2p_compactblocks.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ def test_compactblock_requests(self, test_node):
387387

388388
if announce == "inv":
389389
test_node.send_message(msg_inv([CInv(MSG_BLOCK, block.sha256)]))
390-
test_node.wait_until(lambda: "getheaders" in test_node.last_message, timeout=30)
390+
test_node.wait_for_getheaders(timeout=30)
391391
test_node.send_header_for_blocks([block])
392392
else:
393393
test_node.send_header_for_blocks([block])

test/functional/p2p_initial_headers_sync.py

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,10 @@ def announce_random_block(self, peers):
3838
def run_test(self):
3939
self.log.info("Adding a peer to node0")
4040
peer1 = self.nodes[0].add_p2p_connection(P2PInterface())
41+
best_block_hash = int(self.nodes[0].getbestblockhash(), 16)
4142

4243
# Wait for peer1 to receive a getheaders
43-
peer1.wait_for_getheaders()
44+
peer1.wait_for_getheaders(block_hash=best_block_hash)
4445
# An empty reply will clear the outstanding getheaders request,
4546
# allowing additional getheaders requests to be sent to this peer in
4647
# the future.
@@ -60,17 +61,12 @@ def run_test(self):
6061
assert "getheaders" not in peer2.last_message
6162
assert "getheaders" not in peer3.last_message
6263

63-
with p2p_lock:
64-
peer1.last_message.pop("getheaders", None)
65-
6664
self.log.info("Have all peers announce a new block")
6765
self.announce_random_block(all_peers)
6866

6967
self.log.info("Check that peer1 receives a getheaders in response")
70-
peer1.wait_for_getheaders()
68+
peer1.wait_for_getheaders(block_hash=best_block_hash)
7169
peer1.send_message(msg_headers()) # Send empty response, see above
72-
with p2p_lock:
73-
peer1.last_message.pop("getheaders", None)
7470

7571
self.log.info("Check that exactly 1 of {peer2, peer3} received a getheaders in response")
7672
count = 0
@@ -80,7 +76,6 @@ def run_test(self):
8076
if "getheaders" in p.last_message:
8177
count += 1
8278
peer_receiving_getheaders = p
83-
p.last_message.pop("getheaders", None)
8479
p.send_message(msg_headers()) # Send empty response, see above
8580

8681
assert_equal(count, 1)
@@ -89,14 +84,14 @@ def run_test(self):
8984
self.announce_random_block(all_peers)
9085

9186
self.log.info("Check that peer1 receives a getheaders in response")
92-
peer1.wait_for_getheaders()
87+
peer1.wait_for_getheaders(block_hash=best_block_hash)
9388

9489
self.log.info("Check that the remaining peer received a getheaders as well")
9590
expected_peer = peer2
9691
if peer2 == peer_receiving_getheaders:
9792
expected_peer = peer3
9893

99-
expected_peer.wait_for_getheaders()
94+
expected_peer.wait_for_getheaders(block_hash=best_block_hash)
10095

10196
self.log.info("Success!")
10297

test/functional/p2p_segwit.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,14 +191,13 @@ def announce_tx_and_wait_for_getdata(self, tx, success=True, use_wtxid=False):
191191
def announce_block_and_wait_for_getdata(self, block, use_header, timeout=60):
192192
with p2p_lock:
193193
self.last_message.pop("getdata", None)
194-
self.last_message.pop("getheaders", None)
195194
msg = msg_headers()
196195
msg.headers = [CBlockHeader(block)]
197196
if use_header:
198197
self.send_message(msg)
199198
else:
200199
self.send_message(msg_inv(inv=[CInv(MSG_BLOCK, block.sha256)]))
201-
self.wait_for_getheaders(timeout=timeout)
200+
self.wait_for_getheaders(block_hash=block.hashPrevBlock, timeout=timeout)
202201
self.send_message(msg)
203202
self.wait_for_getdata([block.sha256], timeout=timeout)
204203

test/functional/p2p_sendheaders.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,7 @@ def test_nonnull_locators(self, test_node, inv_node):
311311

312312
# Now that we've synced headers, headers announcements should work
313313
tip = self.mine_blocks(1)
314+
expected_hash = tip
314315
inv_node.check_last_inv_announcement(inv=[tip])
315316
test_node.check_last_headers_announcement(headers=[tip])
316317

@@ -334,7 +335,10 @@ def test_nonnull_locators(self, test_node, inv_node):
334335
if j == 0:
335336
# Announce via inv
336337
test_node.send_block_inv(tip)
337-
test_node.wait_for_getheaders()
338+
if i == 0:
339+
test_node.wait_for_getheaders(block_hash=expected_hash)
340+
else:
341+
assert "getheaders" not in test_node.last_message
338342
# Should have received a getheaders now
339343
test_node.send_header_for_blocks(blocks)
340344
# Test that duplicate inv's won't result in duplicate
@@ -521,6 +525,7 @@ def test_nonnull_locators(self, test_node, inv_node):
521525
self.log.info("Part 5: Testing handling of unconnecting headers")
522526
# First we test that receipt of an unconnecting header doesn't prevent
523527
# chain sync.
528+
expected_hash = tip
524529
for i in range(10):
525530
self.log.debug("Part 5.{}: starting...".format(i))
526531
test_node.last_message.pop("getdata", None)
@@ -533,15 +538,14 @@ def test_nonnull_locators(self, test_node, inv_node):
533538
block_time += 1
534539
height += 1
535540
# Send the header of the second block -> this won't connect.
536-
with p2p_lock:
537-
test_node.last_message.pop("getheaders", None)
538541
test_node.send_header_for_blocks([blocks[1]])
539-
test_node.wait_for_getheaders()
542+
test_node.wait_for_getheaders(block_hash=expected_hash)
540543
test_node.send_header_for_blocks(blocks)
541544
test_node.wait_for_getdata([x.sha256 for x in blocks])
542545
[test_node.send_message(msg_block(x)) for x in blocks]
543546
test_node.sync_with_ping()
544547
assert_equal(int(self.nodes[0].getbestblockhash(), 16), blocks[1].sha256)
548+
expected_hash = blocks[1].sha256
545549

546550
blocks = []
547551
# Now we test that if we repeatedly don't send connecting headers, we
@@ -556,13 +560,12 @@ def test_nonnull_locators(self, test_node, inv_node):
556560

557561
for i in range(1, MAX_NUM_UNCONNECTING_HEADERS_MSGS):
558562
# Send a header that doesn't connect, check that we get a getheaders.
559-
with p2p_lock:
560-
test_node.last_message.pop("getheaders", None)
561563
test_node.send_header_for_blocks([blocks[i]])
562-
test_node.wait_for_getheaders()
564+
test_node.wait_for_getheaders(block_hash=expected_hash)
563565

564566
# Next header will connect, should re-set our count:
565567
test_node.send_header_for_blocks([blocks[0]])
568+
expected_hash = blocks[0].sha256
566569

567570
# Remove the first two entries (blocks[1] would connect):
568571
blocks = blocks[2:]
@@ -571,10 +574,8 @@ def test_nonnull_locators(self, test_node, inv_node):
571574
# before we get disconnected. Should be 5*MAX_NUM_UNCONNECTING_HEADERS_MSGS
572575
for i in range(5 * MAX_NUM_UNCONNECTING_HEADERS_MSGS - 1):
573576
# Send a header that doesn't connect, check that we get a getheaders.
574-
with p2p_lock:
575-
test_node.last_message.pop("getheaders", None)
576577
test_node.send_header_for_blocks([blocks[i % len(blocks)]])
577-
test_node.wait_for_getheaders()
578+
test_node.wait_for_getheaders(block_hash=expected_hash)
578579

579580
# Eventually this stops working.
580581
test_node.send_header_for_blocks([blocks[-1]])

test/functional/test_framework/p2p.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -644,15 +644,17 @@ def test_function():
644644

645645
self.wait_until(test_function, timeout=timeout)
646646

647-
def wait_for_getheaders(self, *, timeout=60):
648-
"""Waits for a getheaders message.
647+
def wait_for_getheaders(self, block_hash=None, *, timeout=60):
648+
"""Waits for a getheaders message containing a specific block hash.
649649
650-
Receiving any getheaders message will satisfy the predicate. the last_message["getheaders"]
651-
value must be explicitly cleared before calling this method, or this will return
652-
immediately with success. TODO: change this method to take a hash value and only
653-
return true if the correct block header has been requested."""
650+
If no block hash is provided, checks whether any getheaders message has been received by the node."""
654651
def test_function():
655-
return self.last_message.get("getheaders")
652+
last_getheaders = self.last_message.pop("getheaders", None)
653+
if block_hash is None:
654+
return last_getheaders
655+
if last_getheaders is None:
656+
return False
657+
return block_hash == last_getheaders.locator.vHave[0]
656658

657659
self.wait_until(test_function, timeout=timeout)
658660

0 commit comments

Comments
 (0)