Changeset View
Changeset View
Standalone View
Standalone View
test/functional/p2p_sendheaders.py
Show First 20 Lines • Show All 158 Lines • ▼ Show 20 Lines | def on_inv(self, message): | ||||
self.block_announced = True | self.block_announced = True | ||||
self.last_blockhash_announced = message.inv[-1].hash | self.last_blockhash_announced = message.inv[-1].hash | ||||
def on_headers(self, message): | def on_headers(self, message): | ||||
if len(message.headers): | if len(message.headers): | ||||
self.block_announced = True | self.block_announced = True | ||||
for x in message.headers: | for x in message.headers: | ||||
x.calc_sha256() | x.calc_sha256() | ||||
# append because headers may be announced over multiple messages. | # append because headers may be announced over multiple | ||||
# messages. | |||||
self.recent_headers_announced.append(x.sha256) | self.recent_headers_announced.append(x.sha256) | ||||
self.last_blockhash_announced = message.headers[-1].sha256 | self.last_blockhash_announced = message.headers[-1].sha256 | ||||
def clear_block_announcements(self): | def clear_block_announcements(self): | ||||
with mininode_lock: | with mininode_lock: | ||||
self.block_announced = False | self.block_announced = False | ||||
self.last_message.pop("inv", None) | self.last_message.pop("inv", None) | ||||
self.last_message.pop("headers", None) | self.last_message.pop("headers", None) | ||||
▲ Show 20 Lines • Show All 117 Lines • ▼ Show 20 Lines | def test_nonnull_locators(self, test_node, inv_node): | ||||
self.log.info( | self.log.info( | ||||
"Part 1: headers don't start before sendheaders message...") | "Part 1: headers don't start before sendheaders message...") | ||||
for i in range(4): | for i in range(4): | ||||
self.log.debug("Part 1.{}: starting...".format(i)) | self.log.debug("Part 1.{}: starting...".format(i)) | ||||
old_tip = tip | old_tip = tip | ||||
tip = self.mine_blocks(1) | tip = self.mine_blocks(1) | ||||
inv_node.check_last_inv_announcement(inv=[tip]) | inv_node.check_last_inv_announcement(inv=[tip]) | ||||
test_node.check_last_inv_announcement(inv=[tip]) | test_node.check_last_inv_announcement(inv=[tip]) | ||||
# Try a few different responses; none should affect next announcement | # Try a few different responses; none should affect next | ||||
# announcement | |||||
if i == 0: | if i == 0: | ||||
# first request the block | # first request the block | ||||
test_node.send_get_data([tip]) | test_node.send_get_data([tip]) | ||||
test_node.wait_for_block(tip) | test_node.wait_for_block(tip) | ||||
elif i == 1: | elif i == 1: | ||||
# next try requesting header and block | # next try requesting header and block | ||||
test_node.send_get_headers(locator=[old_tip], hashstop=tip) | test_node.send_get_headers(locator=[old_tip], hashstop=tip) | ||||
test_node.send_get_data([tip]) | test_node.send_get_data([tip]) | ||||
▲ Show 20 Lines • Show All 89 Lines • ▼ Show 20 Lines | def test_nonnull_locators(self, test_node, inv_node): | ||||
self.log.info( | self.log.info( | ||||
"Part 3: headers announcements can stop after large reorg, and resume after headers/inv from peer...") | "Part 3: headers announcements can stop after large reorg, and resume after headers/inv from peer...") | ||||
# PART 3. Headers announcements can stop after large reorg, and resume after | # PART 3. Headers announcements can stop after large reorg, and resume after | ||||
# getheaders or inv from peer. | # getheaders or inv from peer. | ||||
for j in range(2): | for j in range(2): | ||||
self.log.debug("Part 3.{}: starting...".format(j)) | self.log.debug("Part 3.{}: starting...".format(j)) | ||||
# First try mining a reorg that can propagate with header announcement | # First try mining a reorg that can propagate with header | ||||
# announcement | |||||
new_block_hashes = self.mine_reorg(length=7) | new_block_hashes = self.mine_reorg(length=7) | ||||
tip = new_block_hashes[-1] | tip = new_block_hashes[-1] | ||||
inv_node.check_last_inv_announcement(inv=[tip]) | inv_node.check_last_inv_announcement(inv=[tip]) | ||||
test_node.check_last_headers_announcement(headers=new_block_hashes) | test_node.check_last_headers_announcement(headers=new_block_hashes) | ||||
block_time += 8 | block_time += 8 | ||||
# Mine a too-large reorg, which should be announced with a single inv | # Mine a too-large reorg, which should be announced with a single | ||||
# inv | |||||
new_block_hashes = self.mine_reorg(length=8) | new_block_hashes = self.mine_reorg(length=8) | ||||
tip = new_block_hashes[-1] | tip = new_block_hashes[-1] | ||||
inv_node.check_last_inv_announcement(inv=[tip]) | inv_node.check_last_inv_announcement(inv=[tip]) | ||||
test_node.check_last_inv_announcement(inv=[tip]) | test_node.check_last_inv_announcement(inv=[tip]) | ||||
block_time += 9 | block_time += 9 | ||||
fork_point = self.nodes[0].getblock("{:02x}".format( | fork_point = self.nodes[0].getblock("{:02x}".format( | ||||
Show All 9 Lines | def test_nonnull_locators(self, test_node, inv_node): | ||||
for i in range(3): | for i in range(3): | ||||
self.log.debug("Part 3.{}.{}: starting...".format(j, i)) | self.log.debug("Part 3.{}.{}: starting...".format(j, i)) | ||||
# Mine another block, still should get only an inv | # Mine another block, still should get only an inv | ||||
tip = self.mine_blocks(1) | tip = self.mine_blocks(1) | ||||
inv_node.check_last_inv_announcement(inv=[tip]) | inv_node.check_last_inv_announcement(inv=[tip]) | ||||
test_node.check_last_inv_announcement(inv=[tip]) | test_node.check_last_inv_announcement(inv=[tip]) | ||||
if i == 0: | if i == 0: | ||||
# Just get the data -- shouldn't cause headers announcements to resume | # Just get the data -- shouldn't cause headers | ||||
# announcements to resume | |||||
test_node.send_get_data([tip]) | test_node.send_get_data([tip]) | ||||
test_node.wait_for_block(tip) | test_node.wait_for_block(tip) | ||||
elif i == 1: | elif i == 1: | ||||
# Send a getheaders message that shouldn't trigger headers announcements | # Send a getheaders message that shouldn't trigger headers announcements | ||||
# to resume (best header sent will be too old) | # to resume (best header sent will be too old) | ||||
test_node.send_get_headers( | test_node.send_get_headers( | ||||
locator=[fork_point], hashstop=new_block_hashes[1]) | locator=[fork_point], hashstop=new_block_hashes[1]) | ||||
test_node.send_get_data([tip]) | test_node.send_get_data([tip]) | ||||
▲ Show 20 Lines • Show All 145 Lines • ▼ Show 20 Lines | def test_nonnull_locators(self, test_node, inv_node): | ||||
blocks.append(create_block( | blocks.append(create_block( | ||||
tip, create_coinbase(height), block_time)) | tip, create_coinbase(height), block_time)) | ||||
blocks[-1].solve() | blocks[-1].solve() | ||||
tip = blocks[-1].sha256 | tip = blocks[-1].sha256 | ||||
block_time += 1 | block_time += 1 | ||||
height += 1 | height += 1 | ||||
for i in range(1, MAX_UNCONNECTING_HEADERS): | for i in range(1, MAX_UNCONNECTING_HEADERS): | ||||
# Send a header that doesn't connect, check that we get a getheaders. | # Send a header that doesn't connect, check that we get a | ||||
# getheaders. | |||||
with mininode_lock: | with mininode_lock: | ||||
test_node.last_message.pop("getheaders", None) | test_node.last_message.pop("getheaders", None) | ||||
test_node.send_header_for_blocks([blocks[i]]) | test_node.send_header_for_blocks([blocks[i]]) | ||||
test_node.wait_for_getheaders() | test_node.wait_for_getheaders() | ||||
# Next header will connect, should re-set our count: | # Next header will connect, should re-set our count: | ||||
test_node.send_header_for_blocks([blocks[0]]) | test_node.send_header_for_blocks([blocks[0]]) | ||||
# Remove the first two entries (blocks[1] would connect): | # Remove the first two entries (blocks[1] would connect): | ||||
blocks = blocks[2:] | blocks = blocks[2:] | ||||
# Now try to see how many unconnecting headers we can send | # Now try to see how many unconnecting headers we can send | ||||
# before we get disconnected. Should be 5*MAX_UNCONNECTING_HEADERS | # before we get disconnected. Should be 5*MAX_UNCONNECTING_HEADERS | ||||
for i in range(5 * MAX_UNCONNECTING_HEADERS - 1): | for i in range(5 * MAX_UNCONNECTING_HEADERS - 1): | ||||
# Send a header that doesn't connect, check that we get a getheaders. | # Send a header that doesn't connect, check that we get a | ||||
# getheaders. | |||||
with mininode_lock: | with mininode_lock: | ||||
test_node.last_message.pop("getheaders", None) | test_node.last_message.pop("getheaders", None) | ||||
test_node.send_header_for_blocks([blocks[i % len(blocks)]]) | test_node.send_header_for_blocks([blocks[i % len(blocks)]]) | ||||
test_node.wait_for_getheaders() | test_node.wait_for_getheaders() | ||||
# Eventually this stops working. | # Eventually this stops working. | ||||
test_node.send_header_for_blocks([blocks[-1]]) | test_node.send_header_for_blocks([blocks[-1]]) | ||||
Show All 12 Lines |