Skip to content

Commit

Permalink
Fix broken sendcmpct test in p2p-compactblocks.py
Browse files Browse the repository at this point in the history
Python lambda use was incorrect.

sendcmpct messages need to be synchronized with RPC calls to generate().

Headers need to be synced (eg with getheaders) for cmpctblock announcements
to start.

Last test omitted sending a sendcmpct message.
  • Loading branch information
sdaftuar committed Sep 15, 2016
1 parent a82e5d8 commit 157254a
Showing 1 changed file with 37 additions and 21 deletions.
58 changes: 37 additions & 21 deletions qa/rpc-tests/p2p-compactblocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,13 @@ def send_header_for_blocks(self, new_blocks):
headers_message.headers = [CBlockHeader(b) for b in new_blocks]
self.send_message(headers_message)

def request_headers_and_sync(self, locator, hashstop=0):
self.clear_block_announcement()
self.get_headers(locator, hashstop)
assert(wait_until(self.received_block_announcement, timeout=30))
assert(self.received_block_announcement())
self.clear_block_announcement()


class CompactBlocksTest(BitcoinTestFramework):
def __init__(self):
Expand Down Expand Up @@ -130,7 +137,7 @@ def make_utxos(self):
# Test "sendcmpct":
# - No compact block announcements or getdata(MSG_CMPCT_BLOCK) unless
# sendcmpct is sent.
# - If sendcmpct is sent with version > 0, the message is ignored.
# - If sendcmpct is sent with version > 1, the message is ignored.
# - If sendcmpct is sent with boolean 0, then block announcements are not
# made with compact blocks.
# - If sendcmpct is then sent with boolean 1, then new block announcements
Expand All @@ -142,57 +149,66 @@ def test_sendcmpct(self):
def received_sendcmpct():
return (self.test_node.last_sendcmpct is not None)
got_message = wait_until(received_sendcmpct, timeout=30)
assert(received_sendcmpct())
assert(got_message)
assert_equal(self.test_node.last_sendcmpct.version, 1)

tip = int(self.nodes[0].getbestblockhash(), 16)

def check_announcement_of_new_block(node, peer, predicate):
self.test_node.clear_block_announcement()
peer.clear_block_announcement()
node.generate(1)
got_message = wait_until(peer.received_block_announcement, timeout=30)
got_message = wait_until(lambda: peer.block_announced, timeout=30)
assert(peer.block_announced)
assert(got_message)
with mininode_lock:
assert(predicate)
assert(predicate(peer))

# We shouldn't get any block announcements via cmpctblock yet.
check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is None)
check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is None)

# Try one more time, this time after requesting headers.
self.test_node.clear_block_announcement()
self.test_node.get_headers(locator=[tip], hashstop=0)
wait_until(self.test_node.received_block_announcement, timeout=30)
self.test_node.clear_block_announcement()
self.test_node.request_headers_and_sync(locator=[tip])
check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is None and p.last_inv is not None)

check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is None and self.test_node.last_inv is not None)
# Test a few ways of using sendcmpct that should NOT
# result in compact block announcements.
# Before each test, sync the headers chain.
self.test_node.request_headers_and_sync(locator=[tip])

# Now try a SENDCMPCT message with too-high version
sendcmpct = msg_sendcmpct()
sendcmpct.version = 2
self.test_node.send_message(sendcmpct)
self.test_node.send_and_ping(sendcmpct)
check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is None)

check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is None)
# Headers sync before next test.
self.test_node.request_headers_and_sync(locator=[tip])

# Now try a SENDCMPCT message with valid version, but announce=False
self.test_node.send_message(msg_sendcmpct())
check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is None)
self.test_node.send_and_ping(msg_sendcmpct())
check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is None)

# Headers sync before next test.
self.test_node.request_headers_and_sync(locator=[tip])

# Finally, try a SENDCMPCT message with announce=True
sendcmpct.version = 1
sendcmpct.announce = True
self.test_node.send_message(sendcmpct)
check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is not None)
self.test_node.send_and_ping(sendcmpct)
check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is not None)

# Try one more time
check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is not None)
# Try one more time (no headers sync should be needed!)
check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is not None)

# Try one more time, after turning on sendheaders
self.test_node.send_message(msg_sendheaders())
check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is not None)
self.test_node.send_and_ping(msg_sendheaders())
check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is not None)

# Now turn off announcements
sendcmpct.announce = False
check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is None and self.test_node.last_headers is not None)
self.test_node.send_and_ping(sendcmpct)
check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is None and p.last_headers is not None)

# This test actually causes bitcoind to (reasonably!) disconnect us, so do this last.
def test_invalid_cmpctblock_message(self):
Expand Down

0 comments on commit 157254a

Please sign in to comment.