[tests] tidy up BaseNode in sendheaders.py

pull/11707/head
John Newbery 7 years ago
parent 2613c545f5
commit f39d4bbd1e

@ -114,20 +114,14 @@ class BaseNode(NodeConnCB):
self.block_announced = False self.block_announced = False
self.last_blockhash_announced = None self.last_blockhash_announced = None
def clear_last_announcement(self): def send_get_data(self, block_hashes):
with mininode_lock: """Request data for a list of block hashes."""
self.block_announced = False
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):
msg = msg_getdata() msg = msg_getdata()
for x in block_hashes: for x in block_hashes:
msg.inv.append(CInv(2, x)) msg.inv.append(CInv(2, x))
self.connection.send_message(msg) self.connection.send_message(msg)
def get_headers(self, locator, hashstop): def send_get_headers(self, locator, hashstop):
msg = msg_getheaders() msg = msg_getheaders()
msg.locator.vHave = locator msg.locator.vHave = locator
msg.hashstop = hashstop msg.hashstop = hashstop
@ -138,6 +132,25 @@ class BaseNode(NodeConnCB):
msg.inv = [CInv(2, blockhash)] msg.inv = [CInv(2, blockhash)]
self.connection.send_message(msg) self.connection.send_message(msg)
def send_header_for_blocks(self, new_blocks):
headers_message = msg_headers()
headers_message.headers = [CBlockHeader(b) for b in new_blocks]
self.send_message(headers_message)
def send_getblocks(self, locator):
getblocks_message = msg_getblocks()
getblocks_message.locator.vHave = locator
self.send_message(getblocks_message)
def wait_for_getdata(self, hash_list, timeout=60):
if hash_list != []:
test_function = lambda: "getdata" in self.last_message and [x.hash for x in self.last_message["getdata"].inv] == hash_list
wait_until(test_function, timeout=timeout, lock=mininode_lock)
def wait_for_block_announcement(self, block_hash, timeout=60):
test_function = lambda: self.last_blockhash_announced == block_hash
wait_until(test_function, timeout=timeout, lock=mininode_lock)
def on_inv(self, conn, message): def on_inv(self, conn, 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
@ -148,10 +161,16 @@ class BaseNode(NodeConnCB):
message.headers[-1].calc_sha256() message.headers[-1].calc_sha256()
self.last_blockhash_announced = message.headers[-1].sha256 self.last_blockhash_announced = message.headers[-1].sha256
# Test whether the last announcement we received had the def clear_last_announcement(self):
# right header or the right inv with mininode_lock:
# inv and headers should be lists of block hashes self.block_announced = False
self.last_message.pop("inv", None)
self.last_message.pop("headers", None)
def check_last_announcement(self, headers=None, inv=None): def check_last_announcement(self, headers=None, inv=None):
"""Test whether the last announcement received had the right header or the right inv.
inv and headers should be lists of block hashes."""
expect_headers = headers if headers is not None else [] expect_headers = headers if headers is not None else []
expect_inv = inv if inv is not None else [] expect_inv = inv if inv is not None else []
test_function = lambda: self.block_announced test_function = lambda: self.block_announced
@ -177,47 +196,26 @@ class BaseNode(NodeConnCB):
self.last_message.pop("headers", None) self.last_message.pop("headers", None)
return success return success
def wait_for_getdata(self, hash_list, timeout=60):
if hash_list == []:
return
test_function = lambda: "getdata" in self.last_message and [x.hash for x in self.last_message["getdata"].inv] == hash_list
wait_until(test_function, timeout=timeout, lock=mininode_lock)
return
def wait_for_block_announcement(self, block_hash, timeout=60):
test_function = lambda: self.last_blockhash_announced == block_hash
wait_until(test_function, timeout=timeout, lock=mininode_lock)
return
def send_header_for_blocks(self, new_blocks):
headers_message = msg_headers()
headers_message.headers = [CBlockHeader(b) for b in new_blocks]
self.send_message(headers_message)
def send_getblocks(self, locator):
getblocks_message = msg_getblocks()
getblocks_message.locator.vHave = locator
self.send_message(getblocks_message)
class SendHeadersTest(BitcoinTestFramework): class SendHeadersTest(BitcoinTestFramework):
def set_test_params(self): def set_test_params(self):
self.setup_clean_chain = True self.setup_clean_chain = True
self.num_nodes = 2 self.num_nodes = 2
# mine count blocks and return the new tip
def mine_blocks(self, count): def mine_blocks(self, count):
"""Mine count blocks and return the new tip."""
# Clear out last block announcement from each p2p listener # Clear out last block announcement from each p2p listener
[x.clear_last_announcement() for x in self.nodes[0].p2ps] [x.clear_last_announcement() for x in self.nodes[0].p2ps]
self.nodes[0].generate(count) self.nodes[0].generate(count)
return int(self.nodes[0].getbestblockhash(), 16) return int(self.nodes[0].getbestblockhash(), 16)
# mine a reorg that invalidates length blocks (replacing them with
# length+1 blocks).
# Note: we clear the state of our p2p connections after the
# to-be-reorged-out blocks are mined, so that we don't break later tests.
# return the list of block hashes newly mined
def mine_reorg(self, length): def mine_reorg(self, length):
"""Mine a reorg that invalidates length blocks (replacing them with # length+1 blocks).
Note: we clear the state of our p2p connections after the
to-be-reorged-out blocks are mined, so that we don't break later tests.
return the list of block hashes newly mined."""
self.nodes[0].generate(length) # make sure all invalidated blocks are node0's self.nodes[0].generate(length) # make sure all invalidated blocks are node0's
sync_blocks(self.nodes, wait=0.1) sync_blocks(self.nodes, wait=0.1)
for x in self.nodes[0].p2ps: for x in self.nodes[0].p2ps:
@ -257,7 +255,7 @@ class SendHeadersTest(BitcoinTestFramework):
self.log.info("Verify getheaders with null locator and valid hashstop returns headers.") self.log.info("Verify getheaders with null locator and valid hashstop returns headers.")
test_node.clear_last_announcement() test_node.clear_last_announcement()
test_node.get_headers(locator=[], hashstop=tip_hash) test_node.send_get_headers(locator=[], hashstop=tip_hash)
assert_equal(test_node.check_last_announcement(headers=[tip_hash]), True) assert_equal(test_node.check_last_announcement(headers=[tip_hash]), True)
self.log.info("Verify getheaders with null locator and invalid hashstop does not return headers.") self.log.info("Verify getheaders with null locator and invalid hashstop does not return headers.")
@ -265,7 +263,7 @@ class SendHeadersTest(BitcoinTestFramework):
block.solve() block.solve()
test_node.send_header_for_blocks([block]) test_node.send_header_for_blocks([block])
test_node.clear_last_announcement() test_node.clear_last_announcement()
test_node.get_headers(locator=[], hashstop=int(block.hash, 16)) test_node.send_get_headers(locator=[], hashstop=int(block.hash, 16))
test_node.sync_with_ping() test_node.sync_with_ping()
assert_equal(test_node.block_announced, False) assert_equal(test_node.block_announced, False)
test_node.send_message(msg_block(block)) test_node.send_message(msg_block(block))
@ -284,12 +282,12 @@ class SendHeadersTest(BitcoinTestFramework):
# 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.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.get_headers(locator=[old_tip], hashstop=tip) test_node.send_get_headers(locator=[old_tip], hashstop=tip)
test_node.get_data([tip]) test_node.send_get_data([tip])
test_node.wait_for_block(tip) test_node.wait_for_block(tip)
test_node.clear_last_announcement() # since we requested headers... test_node.clear_last_announcement() # since we requested headers...
elif i == 2: elif i == 2:
@ -313,7 +311,7 @@ class SendHeadersTest(BitcoinTestFramework):
# commence and keep working. # commence and keep working.
test_node.send_message(msg_sendheaders()) test_node.send_message(msg_sendheaders())
prev_tip = int(self.nodes[0].getbestblockhash(), 16) prev_tip = int(self.nodes[0].getbestblockhash(), 16)
test_node.get_headers(locator=[prev_tip], hashstop=0) test_node.send_get_headers(locator=[prev_tip], hashstop=0)
test_node.sync_with_ping() test_node.sync_with_ping()
# Now that we've synced headers, headers announcements should work # Now that we've synced headers, headers announcements should work
@ -397,7 +395,7 @@ class SendHeadersTest(BitcoinTestFramework):
# Use getblocks/getdata # Use getblocks/getdata
test_node.send_getblocks(locator=[fork_point]) test_node.send_getblocks(locator=[fork_point])
assert_equal(test_node.check_last_announcement(inv=new_block_hashes), True) assert_equal(test_node.check_last_announcement(inv=new_block_hashes), True)
test_node.get_data(new_block_hashes) test_node.send_get_data(new_block_hashes)
test_node.wait_for_block(new_block_hashes[-1]) test_node.wait_for_block(new_block_hashes[-1])
for i in range(3): for i in range(3):
@ -407,22 +405,22 @@ class SendHeadersTest(BitcoinTestFramework):
assert_equal(test_node.check_last_announcement(inv=[tip]), True) assert_equal(test_node.check_last_announcement(inv=[tip]), True)
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.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.get_headers(locator=[fork_point], hashstop=new_block_hashes[1]) test_node.send_get_headers(locator=[fork_point], hashstop=new_block_hashes[1])
test_node.get_data([tip]) test_node.send_get_data([tip])
test_node.wait_for_block(tip) test_node.wait_for_block(tip)
elif i == 2: elif i == 2:
test_node.get_data([tip]) test_node.send_get_data([tip])
test_node.wait_for_block(tip) test_node.wait_for_block(tip)
# This time, try sending either a getheaders to trigger resumption # This time, try sending either a getheaders to trigger resumption
# of headers announcements, or mine a new block and inv it, also # of headers announcements, or mine a new block and inv it, also
# triggering resumption of headers announcements. # triggering resumption of headers announcements.
if j == 0: if j == 0:
test_node.get_headers(locator=[tip], hashstop=0) test_node.send_get_headers(locator=[tip], hashstop=0)
test_node.sync_with_ping() test_node.sync_with_ping()
else: else:
test_node.send_block_inv(tip) test_node.send_block_inv(tip)

Loading…
Cancel
Save