diff options
Diffstat (limited to 'test/functional/sendheaders.py')
-rwxr-xr-x | test/functional/sendheaders.py | 122 |
1 files changed, 34 insertions, 88 deletions
diff --git a/test/functional/sendheaders.py b/test/functional/sendheaders.py index de7f5e0849..44c357c6db 100755 --- a/test/functional/sendheaders.py +++ b/test/functional/sendheaders.py @@ -81,23 +81,17 @@ from test_framework.blocktools import create_block, create_coinbase direct_fetch_response_time = 0.05 -class BaseNode(SingleNodeConnCB): +class TestNode(NodeConnCB): def __init__(self): - SingleNodeConnCB.__init__(self) - self.last_inv = None - self.last_headers = None - self.last_block = None - self.last_getdata = None + super().__init__() self.block_announced = False - self.last_getheaders = None - self.disconnected = False self.last_blockhash_announced = None def clear_last_announcement(self): with mininode_lock: self.block_announced = False - self.last_inv = None - self.last_headers = None + self.last_message.pop("inv", None) + self.last_message.pop("headers", None) # Request data for a list of block hashes def get_data(self, block_hashes): @@ -118,29 +112,17 @@ class BaseNode(SingleNodeConnCB): self.connection.send_message(msg) def on_inv(self, conn, message): - self.last_inv = message self.block_announced = True self.last_blockhash_announced = message.inv[-1].hash def on_headers(self, conn, message): - self.last_headers = message if len(message.headers): self.block_announced = True message.headers[-1].calc_sha256() self.last_blockhash_announced = message.headers[-1].sha256 def on_block(self, conn, message): - self.last_block = message.block - self.last_block.calc_sha256() - - def on_getdata(self, conn, message): - self.last_getdata = message - - def on_getheaders(self, conn, message): - self.last_getheaders = message - - def on_close(self, conn): - self.disconnected = True + self.last_message["block"].calc_sha256() # Test whether the last announcement we received had the # right header or the right inv @@ -155,43 +137,27 @@ class BaseNode(SingleNodeConnCB): success = True compare_inv = [] - if self.last_inv != None: - compare_inv = [x.hash for x in self.last_inv.inv] + if "inv" in self.last_message: + compare_inv = [x.hash for x in self.last_message["inv"].inv] if compare_inv != expect_inv: success = False hash_headers = [] - if self.last_headers != None: + if "headers" in self.last_message: # treat headers as a list of block hashes - hash_headers = [ x.sha256 for x in self.last_headers.headers ] + hash_headers = [ x.sha256 for x in self.last_message["headers"].headers ] if hash_headers != expect_headers: success = False - self.last_inv = None - self.last_headers = None + self.last_message.pop("inv", None) + self.last_message.pop("headers", None) return success - # Syncing helpers - def wait_for_block(self, blockhash, timeout=60): - test_function = lambda: self.last_block != None and self.last_block.sha256 == blockhash - assert(wait_until(test_function, timeout=timeout)) - return - - def wait_for_getheaders(self, timeout=60): - test_function = lambda: self.last_getheaders != None - assert(wait_until(test_function, timeout=timeout)) - return - def wait_for_getdata(self, hash_list, timeout=60): if hash_list == []: return - test_function = lambda: self.last_getdata != None and [x.hash for x in self.last_getdata.inv] == hash_list - assert(wait_until(test_function, timeout=timeout)) - return - - def wait_for_disconnect(self, timeout=60): - test_function = lambda: self.disconnected + test_function = lambda: "getdata" in self.last_message and [x.hash for x in self.last_message["getdata"].inv] == hash_list assert(wait_until(test_function, timeout=timeout)) return @@ -210,28 +176,12 @@ class BaseNode(SingleNodeConnCB): getblocks_message.locator.vHave = locator self.send_message(getblocks_message) -# InvNode: This peer should only ever receive inv's, because it doesn't ever send a -# "sendheaders" message. -class InvNode(BaseNode): - def __init__(self): - BaseNode.__init__(self) - -# TestNode: This peer is the one we use for most of the testing. -class TestNode(BaseNode): - def __init__(self): - BaseNode.__init__(self) - class SendHeadersTest(BitcoinTestFramework): def __init__(self): super().__init__() self.setup_clean_chain = True self.num_nodes = 2 - def setup_network(self): - self.nodes = [] - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) - connect_nodes(self.nodes[0], 1) - # mine count blocks and return the new tip def mine_blocks(self, count): # Clear out last block announcement from each p2p listener @@ -260,7 +210,7 @@ class SendHeadersTest(BitcoinTestFramework): def run_test(self): # Setup the p2p connections and start up the network thread. - inv_node = InvNode() + inv_node = TestNode() test_node = TestNode() self.p2p_connections = [inv_node, test_node] @@ -293,7 +243,7 @@ class SendHeadersTest(BitcoinTestFramework): if i == 0: # first request the block test_node.get_data([tip]) - test_node.wait_for_block(tip, timeout=5) + test_node.wait_for_block(tip) elif i == 1: # next try requesting header and block test_node.get_headers(locator=[old_tip], hashstop=tip) @@ -308,7 +258,7 @@ class SendHeadersTest(BitcoinTestFramework): new_block = create_block(tip, create_coinbase(height+1), block_time) new_block.solve() test_node.send_header_for_blocks([new_block]) - test_node.wait_for_getdata([new_block.sha256], timeout=5) + test_node.wait_for_getdata([new_block.sha256]) test_node.send_message(msg_block(new_block)) test_node.sync_with_ping() # make sure this block is processed inv_node.clear_last_announcement() @@ -347,18 +297,18 @@ class SendHeadersTest(BitcoinTestFramework): if j == 0: # Announce via inv test_node.send_block_inv(tip) - test_node.wait_for_getheaders(timeout=5) + test_node.wait_for_getheaders() # Should have received a getheaders now test_node.send_header_for_blocks(blocks) # Test that duplicate inv's won't result in duplicate # getdata requests, or duplicate headers announcements [ inv_node.send_block_inv(x.sha256) for x in blocks ] - test_node.wait_for_getdata([x.sha256 for x in blocks], timeout=5) + test_node.wait_for_getdata([x.sha256 for x in blocks]) inv_node.sync_with_ping() else: # Announce via headers test_node.send_header_for_blocks(blocks) - test_node.wait_for_getdata([x.sha256 for x in blocks], timeout=5) + test_node.wait_for_getdata([x.sha256 for x in blocks]) # Test that duplicate headers won't result in duplicate # getdata requests (the check is further down) inv_node.send_header_for_blocks(blocks) @@ -368,8 +318,8 @@ class SendHeadersTest(BitcoinTestFramework): inv_node.sync_with_ping() # This block should not be announced to the inv node (since it also # broadcast it) - assert_equal(inv_node.last_inv, None) - assert_equal(inv_node.last_headers, None) + assert "inv" not in inv_node.last_message + assert "headers" not in inv_node.last_message tip = self.mine_blocks(1) assert_equal(inv_node.check_last_announcement(inv=[tip]), True) assert_equal(test_node.check_last_announcement(headers=[tip]), True) @@ -459,12 +409,12 @@ class SendHeadersTest(BitcoinTestFramework): inv_node.send_message(msg_block(blocks[-1])) inv_node.sync_with_ping() # Make sure blocks are processed - test_node.last_getdata = None + test_node.last_message.pop("getdata", None) test_node.send_header_for_blocks(blocks) test_node.sync_with_ping() # should not have received any getdata messages with mininode_lock: - assert_equal(test_node.last_getdata, None) + assert "getdata" not in test_node.last_message # This time, direct fetch should work blocks = [] @@ -498,11 +448,11 @@ class SendHeadersTest(BitcoinTestFramework): # Announcing one block on fork should not trigger direct fetch # (less work than tip) - test_node.last_getdata = None + test_node.last_message.pop("getdata", None) test_node.send_header_for_blocks(blocks[0:1]) test_node.sync_with_ping() with mininode_lock: - assert_equal(test_node.last_getdata, None) + assert "getdata" not in test_node.last_message # Announcing one more block on fork should trigger direct fetch for # both blocks (same work as tip) @@ -517,11 +467,11 @@ class SendHeadersTest(BitcoinTestFramework): test_node.wait_for_getdata([x.sha256 for x in blocks[2:16]], timeout=direct_fetch_response_time) # Announcing 1 more header should not trigger any response - test_node.last_getdata = None + test_node.last_message.pop("getdata", None) test_node.send_header_for_blocks(blocks[18:19]) test_node.sync_with_ping() with mininode_lock: - assert_equal(test_node.last_getdata, None) + assert "getdata" not in test_node.last_message self.log.info("Part 4: success!") @@ -532,7 +482,7 @@ class SendHeadersTest(BitcoinTestFramework): # First we test that receipt of an unconnecting header doesn't prevent # chain sync. for i in range(10): - test_node.last_getdata = None + test_node.last_message.pop("getdata", None) blocks = [] # Create two more blocks. for j in range(2): @@ -543,9 +493,9 @@ class SendHeadersTest(BitcoinTestFramework): height += 1 # Send the header of the second block -> this won't connect. with mininode_lock: - test_node.last_getheaders = None + test_node.last_message.pop("getheaders", None) test_node.send_header_for_blocks([blocks[1]]) - test_node.wait_for_getheaders(timeout=1) + test_node.wait_for_getheaders() test_node.send_header_for_blocks(blocks) test_node.wait_for_getdata([x.sha256 for x in blocks]) [ test_node.send_message(msg_block(x)) for x in blocks ] @@ -566,9 +516,9 @@ class SendHeadersTest(BitcoinTestFramework): for i in range(1, MAX_UNCONNECTING_HEADERS): # Send a header that doesn't connect, check that we get a getheaders. with mininode_lock: - test_node.last_getheaders = None + test_node.last_message.pop("getheaders", None) test_node.send_header_for_blocks([blocks[i]]) - test_node.wait_for_getheaders(timeout=1) + test_node.wait_for_getheaders() # Next header will connect, should re-set our count: test_node.send_header_for_blocks([blocks[0]]) @@ -581,25 +531,21 @@ class SendHeadersTest(BitcoinTestFramework): for i in range(5*MAX_UNCONNECTING_HEADERS - 1): # Send a header that doesn't connect, check that we get a getheaders. with mininode_lock: - test_node.last_getheaders = None + test_node.last_message.pop("getheaders", None) test_node.send_header_for_blocks([blocks[i%len(blocks)]]) - test_node.wait_for_getheaders(timeout=1) + test_node.wait_for_getheaders() # Eventually this stops working. - with mininode_lock: - self.last_getheaders = None test_node.send_header_for_blocks([blocks[-1]]) # Should get disconnected test_node.wait_for_disconnect() - with mininode_lock: - self.last_getheaders = True self.log.info("Part 5: success!") # Finally, check that the inv node never received a getdata request, # throughout the test - assert_equal(inv_node.last_getdata, None) + assert "getdata" not in inv_node.last_message if __name__ == '__main__': SendHeadersTest().main() |