Browse Source

[tests] fix flake8 warnings in sendheaders.py

0.16
John Newbery 7 years ago
parent
commit
2613c545f5
  1. 92
      test/functional/sendheaders.py

92
test/functional/sendheaders.py

@ -4,7 +4,7 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php. # file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test behavior of headers messages to announce blocks. """Test behavior of headers messages to announce blocks.
Setup: Setup:
- Two nodes, two p2p connections to node0. One p2p connection should only ever - Two nodes, two p2p connections to node0. One p2p connection should only ever
receive inv's (omitted from testing description below, this is our control). receive inv's (omitted from testing description below, this is our control).
@ -83,16 +83,32 @@ d. Announce 49 headers that don't connect.
e. Announce one more that doesn't connect. e. Announce one more that doesn't connect.
Expect: disconnect. Expect: disconnect.
""" """
from test_framework.mininode import *
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
from test_framework.blocktools import create_block, create_coinbase from test_framework.blocktools import create_block, create_coinbase
from test_framework.mininode import (
CBlockHeader,
CInv,
NODE_WITNESS,
NetworkThread,
NodeConnCB,
mininode_lock,
msg_block,
msg_getblocks,
msg_getdata,
msg_getheaders,
msg_headers,
msg_inv,
msg_sendheaders,
)
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
sync_blocks,
wait_until,
)
DIRECT_FETCH_RESPONSE_TIME = 0.05
direct_fetch_response_time = 0.05 class BaseNode(NodeConnCB):
class TestNode(NodeConnCB):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.block_announced = False self.block_announced = False
@ -136,8 +152,8 @@ class TestNode(NodeConnCB):
# right header or the right inv # right header or the right inv
# inv and headers should be lists of block hashes # inv and headers should be lists of block hashes
def check_last_announcement(self, headers=None, inv=None): def check_last_announcement(self, headers=None, inv=None):
expect_headers = headers if headers != None else [] expect_headers = headers if headers is not None else []
expect_inv = inv if inv != None else [] expect_inv = inv if inv is not None else []
test_function = lambda: self.block_announced test_function = lambda: self.block_announced
wait_until(test_function, timeout=60, lock=mininode_lock) wait_until(test_function, timeout=60, lock=mininode_lock)
with mininode_lock: with mininode_lock:
@ -153,7 +169,7 @@ class TestNode(NodeConnCB):
hash_headers = [] hash_headers = []
if "headers" in self.last_message: if "headers" in self.last_message:
# treat headers as a list of block hashes # treat headers as a list of block hashes
hash_headers = [ x.sha256 for x in self.last_message["headers"].headers ] hash_headers = [x.sha256 for x in self.last_message["headers"].headers]
if hash_headers != expect_headers: if hash_headers != expect_headers:
success = False success = False
@ -176,7 +192,7 @@ class TestNode(NodeConnCB):
def send_header_for_blocks(self, new_blocks): def send_header_for_blocks(self, new_blocks):
headers_message = msg_headers() headers_message = msg_headers()
headers_message.headers = [ CBlockHeader(b) for b in new_blocks ] headers_message.headers = [CBlockHeader(b) for b in new_blocks]
self.send_message(headers_message) self.send_message(headers_message)
def send_getblocks(self, locator): def send_getblocks(self, locator):
@ -202,27 +218,27 @@ class SendHeadersTest(BitcoinTestFramework):
# to-be-reorged-out blocks are mined, so that we don't break later tests. # to-be-reorged-out blocks are mined, so that we don't break later tests.
# return the list of block hashes newly mined # return the list of block hashes newly mined
def mine_reorg(self, length): def mine_reorg(self, length):
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:
x.wait_for_block_announcement(int(self.nodes[0].getbestblockhash(), 16)) x.wait_for_block_announcement(int(self.nodes[0].getbestblockhash(), 16))
x.clear_last_announcement() x.clear_last_announcement()
tip_height = self.nodes[1].getblockcount() tip_height = self.nodes[1].getblockcount()
hash_to_invalidate = self.nodes[1].getblockhash(tip_height-(length-1)) hash_to_invalidate = self.nodes[1].getblockhash(tip_height - (length - 1))
self.nodes[1].invalidateblock(hash_to_invalidate) self.nodes[1].invalidateblock(hash_to_invalidate)
all_hashes = self.nodes[1].generate(length+1) # Must be longer than the orig chain all_hashes = self.nodes[1].generate(length + 1) # Must be longer than the orig chain
sync_blocks(self.nodes, wait=0.1) sync_blocks(self.nodes, wait=0.1)
return [int(x, 16) for x in all_hashes] return [int(x, 16) for x in all_hashes]
def run_test(self): def run_test(self):
# Setup the p2p connections and start up the network thread. # Setup the p2p connections and start up the network thread.
inv_node = self.nodes[0].add_p2p_connection(TestNode()) inv_node = self.nodes[0].add_p2p_connection(BaseNode())
# Set nServices to 0 for test_node, so no block download will occur outside of # Set nServices to 0 for test_node, so no block download will occur outside of
# direct fetching # direct fetching
test_node = self.nodes[0].add_p2p_connection(TestNode(), services=NODE_WITNESS) test_node = self.nodes[0].add_p2p_connection(BaseNode(), services=NODE_WITNESS)
NetworkThread().start() # Start up network handling in another thread NetworkThread().start() # Start up network handling in another thread
# Test logic begins here # Test logic begins here
inv_node.wait_for_verack() inv_node.wait_for_verack()
@ -275,18 +291,18 @@ class SendHeadersTest(BitcoinTestFramework):
test_node.get_headers(locator=[old_tip], hashstop=tip) test_node.get_headers(locator=[old_tip], hashstop=tip)
test_node.get_data([tip]) test_node.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:
# this time announce own block via headers # this time announce own block via headers
height = self.nodes[0].getblockcount() height = self.nodes[0].getblockcount()
last_time = self.nodes[0].getblock(self.nodes[0].getbestblockhash())['time'] last_time = self.nodes[0].getblock(self.nodes[0].getbestblockhash())['time']
block_time = last_time + 1 block_time = last_time + 1
new_block = create_block(tip, create_coinbase(height+1), block_time) new_block = create_block(tip, create_coinbase(height + 1), block_time)
new_block.solve() new_block.solve()
test_node.send_header_for_blocks([new_block]) test_node.send_header_for_blocks([new_block])
test_node.wait_for_getdata([new_block.sha256]) test_node.wait_for_getdata([new_block.sha256])
test_node.send_message(msg_block(new_block)) test_node.send_message(msg_block(new_block))
test_node.sync_with_ping() # make sure this block is processed test_node.sync_with_ping() # make sure this block is processed
inv_node.clear_last_announcement() inv_node.clear_last_announcement()
test_node.clear_last_announcement() test_node.clear_last_announcement()
@ -305,7 +321,7 @@ class SendHeadersTest(BitcoinTestFramework):
assert_equal(inv_node.check_last_announcement(inv=[tip]), True) assert_equal(inv_node.check_last_announcement(inv=[tip]), True)
assert_equal(test_node.check_last_announcement(headers=[tip]), True) assert_equal(test_node.check_last_announcement(headers=[tip]), True)
height = self.nodes[0].getblockcount()+1 height = self.nodes[0].getblockcount() + 1
block_time += 10 # Advance far enough ahead block_time += 10 # Advance far enough ahead
for i in range(10): for i in range(10):
# Mine i blocks, and alternate announcing either via # Mine i blocks, and alternate announcing either via
@ -314,7 +330,7 @@ class SendHeadersTest(BitcoinTestFramework):
# with block header, even though the blocks are never requested # with block header, even though the blocks are never requested
for j in range(2): for j in range(2):
blocks = [] blocks = []
for b in range(i+1): for b in range(i + 1):
blocks.append(create_block(tip, create_coinbase(height), block_time)) blocks.append(create_block(tip, create_coinbase(height), block_time))
blocks[-1].solve() blocks[-1].solve()
tip = blocks[-1].sha256 tip = blocks[-1].sha256
@ -328,7 +344,7 @@ class SendHeadersTest(BitcoinTestFramework):
test_node.send_header_for_blocks(blocks) test_node.send_header_for_blocks(blocks)
# Test that duplicate inv's won't result in duplicate # Test that duplicate inv's won't result in duplicate
# getdata requests, or duplicate headers announcements # getdata requests, or duplicate headers announcements
[ inv_node.send_block_inv(x.sha256) for x in blocks ] [inv_node.send_block_inv(x.sha256) for x in blocks]
test_node.wait_for_getdata([x.sha256 for x in blocks]) test_node.wait_for_getdata([x.sha256 for x in blocks])
inv_node.sync_with_ping() inv_node.sync_with_ping()
else: else:
@ -339,7 +355,7 @@ class SendHeadersTest(BitcoinTestFramework):
# getdata requests (the check is further down) # getdata requests (the check is further down)
inv_node.send_header_for_blocks(blocks) inv_node.send_header_for_blocks(blocks)
inv_node.sync_with_ping() inv_node.sync_with_ping()
[ test_node.send_message(msg_block(x)) for x in blocks ] [test_node.send_message(msg_block(x)) for x in blocks]
test_node.sync_with_ping() test_node.sync_with_ping()
inv_node.sync_with_ping() inv_node.sync_with_ping()
# This block should not be announced to the inv node (since it also # This block should not be announced to the inv node (since it also
@ -365,7 +381,7 @@ class SendHeadersTest(BitcoinTestFramework):
assert_equal(inv_node.check_last_announcement(inv=[tip]), True) assert_equal(inv_node.check_last_announcement(inv=[tip]), True)
assert_equal(test_node.check_last_announcement(headers=new_block_hashes), True) assert_equal(test_node.check_last_announcement(headers=new_block_hashes), True)
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)
@ -379,7 +395,7 @@ class SendHeadersTest(BitcoinTestFramework):
fork_point = int(fork_point, 16) fork_point = int(fork_point, 16)
# 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.get_data(new_block_hashes)
test_node.wait_for_block(new_block_hashes[-1]) test_node.wait_for_block(new_block_hashes[-1])
@ -403,7 +419,7 @@ class SendHeadersTest(BitcoinTestFramework):
test_node.get_data([tip]) test_node.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.get_headers(locator=[tip], hashstop=0)
@ -434,7 +450,7 @@ class SendHeadersTest(BitcoinTestFramework):
height += 1 height += 1
inv_node.send_message(msg_block(blocks[-1])) inv_node.send_message(msg_block(blocks[-1]))
inv_node.sync_with_ping() # Make sure blocks are processed inv_node.sync_with_ping() # Make sure blocks are processed
test_node.last_message.pop("getdata", None) test_node.last_message.pop("getdata", None)
test_node.send_header_for_blocks(blocks) test_node.send_header_for_blocks(blocks)
test_node.sync_with_ping() test_node.sync_with_ping()
@ -453,9 +469,9 @@ class SendHeadersTest(BitcoinTestFramework):
test_node.send_header_for_blocks(blocks) test_node.send_header_for_blocks(blocks)
test_node.sync_with_ping() test_node.sync_with_ping()
test_node.wait_for_getdata([x.sha256 for x in blocks], timeout=direct_fetch_response_time) test_node.wait_for_getdata([x.sha256 for x in blocks], timeout=DIRECT_FETCH_RESPONSE_TIME)
[ test_node.send_message(msg_block(x)) for x in blocks ] [test_node.send_message(msg_block(x)) for x in blocks]
test_node.sync_with_ping() test_node.sync_with_ping()
@ -484,13 +500,13 @@ class SendHeadersTest(BitcoinTestFramework):
# both blocks (same work as tip) # both blocks (same work as tip)
test_node.send_header_for_blocks(blocks[1:2]) test_node.send_header_for_blocks(blocks[1:2])
test_node.sync_with_ping() test_node.sync_with_ping()
test_node.wait_for_getdata([x.sha256 for x in blocks[0:2]], timeout=direct_fetch_response_time) test_node.wait_for_getdata([x.sha256 for x in blocks[0:2]], timeout=DIRECT_FETCH_RESPONSE_TIME)
# Announcing 16 more headers should trigger direct fetch for 14 more # Announcing 16 more headers should trigger direct fetch for 14 more
# blocks # blocks
test_node.send_header_for_blocks(blocks[2:18]) test_node.send_header_for_blocks(blocks[2:18])
test_node.sync_with_ping() test_node.sync_with_ping()
test_node.wait_for_getdata([x.sha256 for x in blocks[2:16]], timeout=direct_fetch_response_time) 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 # Announcing 1 more header should not trigger any response
test_node.last_message.pop("getdata", None) test_node.last_message.pop("getdata", None)
@ -502,7 +518,7 @@ class SendHeadersTest(BitcoinTestFramework):
self.log.info("Part 4: success!") self.log.info("Part 4: success!")
# Now deliver all those blocks we announced. # Now deliver all those blocks we announced.
[ test_node.send_message(msg_block(x)) for x in blocks ] [test_node.send_message(msg_block(x)) for x in blocks]
self.log.info("Part 5: Testing handling of unconnecting headers") self.log.info("Part 5: Testing handling of unconnecting headers")
# First we test that receipt of an unconnecting header doesn't prevent # First we test that receipt of an unconnecting header doesn't prevent
@ -524,7 +540,7 @@ class SendHeadersTest(BitcoinTestFramework):
test_node.wait_for_getheaders() test_node.wait_for_getheaders()
test_node.send_header_for_blocks(blocks) test_node.send_header_for_blocks(blocks)
test_node.wait_for_getdata([x.sha256 for x in blocks]) test_node.wait_for_getdata([x.sha256 for x in blocks])
[ test_node.send_message(msg_block(x)) for x in blocks ] [test_node.send_message(msg_block(x)) for x in blocks]
test_node.sync_with_ping() test_node.sync_with_ping()
assert_equal(int(self.nodes[0].getbestblockhash(), 16), blocks[1].sha256) assert_equal(int(self.nodes[0].getbestblockhash(), 16), blocks[1].sha256)
@ -532,7 +548,7 @@ class SendHeadersTest(BitcoinTestFramework):
# Now we test that if we repeatedly don't send connecting headers, we # Now we test that if we repeatedly don't send connecting headers, we
# don't go into an infinite loop trying to get them to connect. # don't go into an infinite loop trying to get them to connect.
MAX_UNCONNECTING_HEADERS = 10 MAX_UNCONNECTING_HEADERS = 10
for j in range(MAX_UNCONNECTING_HEADERS+1): for j in range(MAX_UNCONNECTING_HEADERS + 1):
blocks.append(create_block(tip, create_coinbase(height), block_time)) blocks.append(create_block(tip, create_coinbase(height), block_time))
blocks[-1].solve() blocks[-1].solve()
tip = blocks[-1].sha256 tip = blocks[-1].sha256
@ -554,11 +570,11 @@ class SendHeadersTest(BitcoinTestFramework):
# 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.

Loading…
Cancel
Save