|
|
@ -19,64 +19,31 @@ class TestNode(NodeConnCB): |
|
|
|
def __init__(self): |
|
|
|
def __init__(self): |
|
|
|
super().__init__() |
|
|
|
super().__init__() |
|
|
|
self.last_sendcmpct = [] |
|
|
|
self.last_sendcmpct = [] |
|
|
|
self.last_headers = None |
|
|
|
|
|
|
|
self.last_inv = None |
|
|
|
|
|
|
|
self.last_cmpctblock = None |
|
|
|
|
|
|
|
self.block_announced = False |
|
|
|
self.block_announced = False |
|
|
|
self.last_getdata = None |
|
|
|
|
|
|
|
self.last_getheaders = None |
|
|
|
|
|
|
|
self.last_getblocktxn = None |
|
|
|
|
|
|
|
self.last_block = None |
|
|
|
|
|
|
|
self.last_blocktxn = None |
|
|
|
|
|
|
|
# Store the hashes of blocks we've seen announced. |
|
|
|
# Store the hashes of blocks we've seen announced. |
|
|
|
# This is for synchronizing the p2p message traffic, |
|
|
|
# This is for synchronizing the p2p message traffic, |
|
|
|
# so we can eg wait until a particular block is announced. |
|
|
|
# so we can eg wait until a particular block is announced. |
|
|
|
self.set_announced_blockhashes = set() |
|
|
|
self.announced_blockhashes = set() |
|
|
|
self.connected = False |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def on_open(self, conn): |
|
|
|
|
|
|
|
self.connected = True |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def on_close(self, conn): |
|
|
|
|
|
|
|
self.connected = False |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def on_sendcmpct(self, conn, message): |
|
|
|
def on_sendcmpct(self, conn, message): |
|
|
|
self.last_sendcmpct.append(message) |
|
|
|
self.last_sendcmpct.append(message) |
|
|
|
|
|
|
|
|
|
|
|
def on_block(self, conn, message): |
|
|
|
|
|
|
|
self.last_block = message |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def on_cmpctblock(self, conn, message): |
|
|
|
def on_cmpctblock(self, conn, message): |
|
|
|
self.last_cmpctblock = message |
|
|
|
|
|
|
|
self.block_announced = True |
|
|
|
self.block_announced = True |
|
|
|
self.last_cmpctblock.header_and_shortids.header.calc_sha256() |
|
|
|
self.last_message["cmpctblock"].header_and_shortids.header.calc_sha256() |
|
|
|
self.set_announced_blockhashes.add(self.last_cmpctblock.header_and_shortids.header.sha256) |
|
|
|
self.announced_blockhashes.add(self.last_message["cmpctblock"].header_and_shortids.header.sha256) |
|
|
|
|
|
|
|
|
|
|
|
def on_headers(self, conn, message): |
|
|
|
def on_headers(self, conn, message): |
|
|
|
self.last_headers = message |
|
|
|
|
|
|
|
self.block_announced = True |
|
|
|
self.block_announced = True |
|
|
|
for x in self.last_headers.headers: |
|
|
|
for x in self.last_message["headers"].headers: |
|
|
|
x.calc_sha256() |
|
|
|
x.calc_sha256() |
|
|
|
self.set_announced_blockhashes.add(x.sha256) |
|
|
|
self.announced_blockhashes.add(x.sha256) |
|
|
|
|
|
|
|
|
|
|
|
def on_inv(self, conn, message): |
|
|
|
def on_inv(self, conn, message): |
|
|
|
self.last_inv = message |
|
|
|
for x in self.last_message["inv"].inv: |
|
|
|
for x in self.last_inv.inv: |
|
|
|
|
|
|
|
if x.type == 2: |
|
|
|
if x.type == 2: |
|
|
|
self.block_announced = True |
|
|
|
self.block_announced = True |
|
|
|
self.set_announced_blockhashes.add(x.hash) |
|
|
|
self.announced_blockhashes.add(x.hash) |
|
|
|
|
|
|
|
|
|
|
|
def on_getdata(self, conn, message): |
|
|
|
|
|
|
|
self.last_getdata = message |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def on_getheaders(self, conn, message): |
|
|
|
|
|
|
|
self.last_getheaders = message |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def on_getblocktxn(self, conn, message): |
|
|
|
|
|
|
|
self.last_getblocktxn = message |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def on_blocktxn(self, conn, message): |
|
|
|
|
|
|
|
self.last_blocktxn = message |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Requires caller to hold mininode_lock |
|
|
|
# Requires caller to hold mininode_lock |
|
|
|
def received_block_announcement(self): |
|
|
|
def received_block_announcement(self): |
|
|
@ -85,9 +52,9 @@ class TestNode(NodeConnCB): |
|
|
|
def clear_block_announcement(self): |
|
|
|
def clear_block_announcement(self): |
|
|
|
with mininode_lock: |
|
|
|
with mininode_lock: |
|
|
|
self.block_announced = False |
|
|
|
self.block_announced = False |
|
|
|
self.last_inv = None |
|
|
|
self.last_message.pop("inv", None) |
|
|
|
self.last_headers = None |
|
|
|
self.last_message.pop("headers", None) |
|
|
|
self.last_cmpctblock = None |
|
|
|
self.last_message.pop("cmpctblock", None) |
|
|
|
|
|
|
|
|
|
|
|
def get_headers(self, locator, hashstop): |
|
|
|
def get_headers(self, locator, hashstop): |
|
|
|
msg = msg_getheaders() |
|
|
|
msg = msg_getheaders() |
|
|
@ -103,15 +70,14 @@ class TestNode(NodeConnCB): |
|
|
|
def request_headers_and_sync(self, locator, hashstop=0): |
|
|
|
def request_headers_and_sync(self, locator, hashstop=0): |
|
|
|
self.clear_block_announcement() |
|
|
|
self.clear_block_announcement() |
|
|
|
self.get_headers(locator, hashstop) |
|
|
|
self.get_headers(locator, hashstop) |
|
|
|
assert(wait_until(self.received_block_announcement, timeout=30)) |
|
|
|
assert wait_until(self.received_block_announcement, timeout=30) |
|
|
|
assert(self.received_block_announcement()) |
|
|
|
|
|
|
|
self.clear_block_announcement() |
|
|
|
self.clear_block_announcement() |
|
|
|
|
|
|
|
|
|
|
|
# Block until a block announcement for a particular block hash is |
|
|
|
# Block until a block announcement for a particular block hash is |
|
|
|
# received. |
|
|
|
# received. |
|
|
|
def wait_for_block_announcement(self, block_hash, timeout=30): |
|
|
|
def wait_for_block_announcement(self, block_hash, timeout=30): |
|
|
|
def received_hash(): |
|
|
|
def received_hash(): |
|
|
|
return (block_hash in self.set_announced_blockhashes) |
|
|
|
return (block_hash in self.announced_blockhashes) |
|
|
|
return wait_until(received_hash, timeout=timeout) |
|
|
|
return wait_until(received_hash, timeout=timeout) |
|
|
|
|
|
|
|
|
|
|
|
def send_await_disconnect(self, message, timeout=30): |
|
|
|
def send_await_disconnect(self, message, timeout=30): |
|
|
@ -214,14 +180,14 @@ class CompactBlocksTest(BitcoinTestFramework): |
|
|
|
with mininode_lock: |
|
|
|
with mininode_lock: |
|
|
|
assert predicate(peer), ( |
|
|
|
assert predicate(peer), ( |
|
|
|
"block_hash={!r}, cmpctblock={!r}, inv={!r}".format( |
|
|
|
"block_hash={!r}, cmpctblock={!r}, inv={!r}".format( |
|
|
|
block_hash, peer.last_cmpctblock, peer.last_inv)) |
|
|
|
block_hash, peer.last_message.get("cmpctblock", None), peer.last_message.get("inv", None))) |
|
|
|
|
|
|
|
|
|
|
|
# We shouldn't get any block announcements via cmpctblock yet. |
|
|
|
# We shouldn't get any block announcements via cmpctblock yet. |
|
|
|
check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is None) |
|
|
|
check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" not in p.last_message) |
|
|
|
|
|
|
|
|
|
|
|
# Try one more time, this time after requesting headers. |
|
|
|
# Try one more time, this time after requesting headers. |
|
|
|
test_node.request_headers_and_sync(locator=[tip]) |
|
|
|
test_node.request_headers_and_sync(locator=[tip]) |
|
|
|
check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is None and p.last_inv is not None) |
|
|
|
check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" not in p.last_message and "inv" in p.last_message) |
|
|
|
|
|
|
|
|
|
|
|
# Test a few ways of using sendcmpct that should NOT |
|
|
|
# Test a few ways of using sendcmpct that should NOT |
|
|
|
# result in compact block announcements. |
|
|
|
# result in compact block announcements. |
|
|
@ -233,7 +199,7 @@ class CompactBlocksTest(BitcoinTestFramework): |
|
|
|
sendcmpct.version = preferred_version+1 |
|
|
|
sendcmpct.version = preferred_version+1 |
|
|
|
sendcmpct.announce = True |
|
|
|
sendcmpct.announce = True |
|
|
|
test_node.send_and_ping(sendcmpct) |
|
|
|
test_node.send_and_ping(sendcmpct) |
|
|
|
check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is None) |
|
|
|
check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" not in p.last_message) |
|
|
|
|
|
|
|
|
|
|
|
# Headers sync before next test. |
|
|
|
# Headers sync before next test. |
|
|
|
test_node.request_headers_and_sync(locator=[tip]) |
|
|
|
test_node.request_headers_and_sync(locator=[tip]) |
|
|
@ -242,7 +208,7 @@ class CompactBlocksTest(BitcoinTestFramework): |
|
|
|
sendcmpct.version = preferred_version |
|
|
|
sendcmpct.version = preferred_version |
|
|
|
sendcmpct.announce = False |
|
|
|
sendcmpct.announce = False |
|
|
|
test_node.send_and_ping(sendcmpct) |
|
|
|
test_node.send_and_ping(sendcmpct) |
|
|
|
check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is None) |
|
|
|
check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" not in p.last_message) |
|
|
|
|
|
|
|
|
|
|
|
# Headers sync before next test. |
|
|
|
# Headers sync before next test. |
|
|
|
test_node.request_headers_and_sync(locator=[tip]) |
|
|
|
test_node.request_headers_and_sync(locator=[tip]) |
|
|
@ -251,26 +217,26 @@ class CompactBlocksTest(BitcoinTestFramework): |
|
|
|
sendcmpct.version = preferred_version |
|
|
|
sendcmpct.version = preferred_version |
|
|
|
sendcmpct.announce = True |
|
|
|
sendcmpct.announce = True |
|
|
|
test_node.send_and_ping(sendcmpct) |
|
|
|
test_node.send_and_ping(sendcmpct) |
|
|
|
check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is not None) |
|
|
|
check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" in p.last_message) |
|
|
|
|
|
|
|
|
|
|
|
# Try one more time (no headers sync should be needed!) |
|
|
|
# Try one more time (no headers sync should be needed!) |
|
|
|
check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is not None) |
|
|
|
check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" in p.last_message) |
|
|
|
|
|
|
|
|
|
|
|
# Try one more time, after turning on sendheaders |
|
|
|
# Try one more time, after turning on sendheaders |
|
|
|
test_node.send_and_ping(msg_sendheaders()) |
|
|
|
test_node.send_and_ping(msg_sendheaders()) |
|
|
|
check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is not None) |
|
|
|
check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" in p.last_message) |
|
|
|
|
|
|
|
|
|
|
|
# Try one more time, after sending a version-1, announce=false message. |
|
|
|
# Try one more time, after sending a version-1, announce=false message. |
|
|
|
sendcmpct.version = preferred_version-1 |
|
|
|
sendcmpct.version = preferred_version-1 |
|
|
|
sendcmpct.announce = False |
|
|
|
sendcmpct.announce = False |
|
|
|
test_node.send_and_ping(sendcmpct) |
|
|
|
test_node.send_and_ping(sendcmpct) |
|
|
|
check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is not None) |
|
|
|
check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" in p.last_message) |
|
|
|
|
|
|
|
|
|
|
|
# Now turn off announcements |
|
|
|
# Now turn off announcements |
|
|
|
sendcmpct.version = preferred_version |
|
|
|
sendcmpct.version = preferred_version |
|
|
|
sendcmpct.announce = False |
|
|
|
sendcmpct.announce = False |
|
|
|
test_node.send_and_ping(sendcmpct) |
|
|
|
test_node.send_and_ping(sendcmpct) |
|
|
|
check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is None and p.last_headers is not None) |
|
|
|
check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" not in p.last_message and "headers" in p.last_message) |
|
|
|
|
|
|
|
|
|
|
|
if old_node is not None: |
|
|
|
if old_node is not None: |
|
|
|
# Verify that a peer using an older protocol version can receive |
|
|
|
# Verify that a peer using an older protocol version can receive |
|
|
@ -280,7 +246,7 @@ class CompactBlocksTest(BitcoinTestFramework): |
|
|
|
old_node.send_and_ping(sendcmpct) |
|
|
|
old_node.send_and_ping(sendcmpct) |
|
|
|
# Header sync |
|
|
|
# Header sync |
|
|
|
old_node.request_headers_and_sync(locator=[tip]) |
|
|
|
old_node.request_headers_and_sync(locator=[tip]) |
|
|
|
check_announcement_of_new_block(node, old_node, lambda p: p.last_cmpctblock is not None) |
|
|
|
check_announcement_of_new_block(node, old_node, lambda p: "cmpctblock" in p.last_message) |
|
|
|
|
|
|
|
|
|
|
|
# This test actually causes bitcoind to (reasonably!) disconnect us, so do this last. |
|
|
|
# This test actually causes bitcoind to (reasonably!) disconnect us, so do this last. |
|
|
|
def test_invalid_cmpctblock_message(self): |
|
|
|
def test_invalid_cmpctblock_message(self): |
|
|
@ -345,9 +311,9 @@ class CompactBlocksTest(BitcoinTestFramework): |
|
|
|
# Now fetch and check the compact block |
|
|
|
# Now fetch and check the compact block |
|
|
|
header_and_shortids = None |
|
|
|
header_and_shortids = None |
|
|
|
with mininode_lock: |
|
|
|
with mininode_lock: |
|
|
|
assert(test_node.last_cmpctblock is not None) |
|
|
|
assert("cmpctblock" in test_node.last_message) |
|
|
|
# Convert the on-the-wire representation to absolute indexes |
|
|
|
# Convert the on-the-wire representation to absolute indexes |
|
|
|
header_and_shortids = HeaderAndShortIDs(test_node.last_cmpctblock.header_and_shortids) |
|
|
|
header_and_shortids = HeaderAndShortIDs(test_node.last_message["cmpctblock"].header_and_shortids) |
|
|
|
self.check_compactblock_construction_from_block(version, header_and_shortids, block_hash, block) |
|
|
|
self.check_compactblock_construction_from_block(version, header_and_shortids, block_hash, block) |
|
|
|
|
|
|
|
|
|
|
|
# Now fetch the compact block using a normal non-announce getdata |
|
|
|
# Now fetch the compact block using a normal non-announce getdata |
|
|
@ -362,9 +328,9 @@ class CompactBlocksTest(BitcoinTestFramework): |
|
|
|
# Now fetch and check the compact block |
|
|
|
# Now fetch and check the compact block |
|
|
|
header_and_shortids = None |
|
|
|
header_and_shortids = None |
|
|
|
with mininode_lock: |
|
|
|
with mininode_lock: |
|
|
|
assert(test_node.last_cmpctblock is not None) |
|
|
|
assert("cmpctblock" in test_node.last_message) |
|
|
|
# Convert the on-the-wire representation to absolute indexes |
|
|
|
# Convert the on-the-wire representation to absolute indexes |
|
|
|
header_and_shortids = HeaderAndShortIDs(test_node.last_cmpctblock.header_and_shortids) |
|
|
|
header_and_shortids = HeaderAndShortIDs(test_node.last_message["cmpctblock"].header_and_shortids) |
|
|
|
self.check_compactblock_construction_from_block(version, header_and_shortids, block_hash, block) |
|
|
|
self.check_compactblock_construction_from_block(version, header_and_shortids, block_hash, block) |
|
|
|
|
|
|
|
|
|
|
|
def check_compactblock_construction_from_block(self, version, header_and_shortids, block_hash, block): |
|
|
|
def check_compactblock_construction_from_block(self, version, header_and_shortids, block_hash, block): |
|
|
@ -424,20 +390,20 @@ class CompactBlocksTest(BitcoinTestFramework): |
|
|
|
for announce in ["inv", "header"]: |
|
|
|
for announce in ["inv", "header"]: |
|
|
|
block = self.build_block_on_tip(node, segwit=segwit) |
|
|
|
block = self.build_block_on_tip(node, segwit=segwit) |
|
|
|
with mininode_lock: |
|
|
|
with mininode_lock: |
|
|
|
test_node.last_getdata = None |
|
|
|
test_node.last_message.pop("getdata", None) |
|
|
|
|
|
|
|
|
|
|
|
if announce == "inv": |
|
|
|
if announce == "inv": |
|
|
|
test_node.send_message(msg_inv([CInv(2, block.sha256)])) |
|
|
|
test_node.send_message(msg_inv([CInv(2, block.sha256)])) |
|
|
|
success = wait_until(lambda: test_node.last_getheaders is not None, timeout=30) |
|
|
|
success = wait_until(lambda: "getheaders" in test_node.last_message, timeout=30) |
|
|
|
assert(success) |
|
|
|
assert(success) |
|
|
|
test_node.send_header_for_blocks([block]) |
|
|
|
test_node.send_header_for_blocks([block]) |
|
|
|
else: |
|
|
|
else: |
|
|
|
test_node.send_header_for_blocks([block]) |
|
|
|
test_node.send_header_for_blocks([block]) |
|
|
|
success = wait_until(lambda: test_node.last_getdata is not None, timeout=30) |
|
|
|
success = wait_until(lambda: "getdata" in test_node.last_message, timeout=30) |
|
|
|
assert(success) |
|
|
|
assert(success) |
|
|
|
assert_equal(len(test_node.last_getdata.inv), 1) |
|
|
|
assert_equal(len(test_node.last_message["getdata"].inv), 1) |
|
|
|
assert_equal(test_node.last_getdata.inv[0].type, 4) |
|
|
|
assert_equal(test_node.last_message["getdata"].inv[0].type, 4) |
|
|
|
assert_equal(test_node.last_getdata.inv[0].hash, block.sha256) |
|
|
|
assert_equal(test_node.last_message["getdata"].inv[0].hash, block.sha256) |
|
|
|
|
|
|
|
|
|
|
|
# Send back a compactblock message that omits the coinbase |
|
|
|
# Send back a compactblock message that omits the coinbase |
|
|
|
comp_block = HeaderAndShortIDs() |
|
|
|
comp_block = HeaderAndShortIDs() |
|
|
@ -453,8 +419,8 @@ class CompactBlocksTest(BitcoinTestFramework): |
|
|
|
assert_equal(int(node.getbestblockhash(), 16), block.hashPrevBlock) |
|
|
|
assert_equal(int(node.getbestblockhash(), 16), block.hashPrevBlock) |
|
|
|
# Expect a getblocktxn message. |
|
|
|
# Expect a getblocktxn message. |
|
|
|
with mininode_lock: |
|
|
|
with mininode_lock: |
|
|
|
assert(test_node.last_getblocktxn is not None) |
|
|
|
assert("getblocktxn" in test_node.last_message) |
|
|
|
absolute_indexes = test_node.last_getblocktxn.block_txn_request.to_absolute() |
|
|
|
absolute_indexes = test_node.last_message["getblocktxn"].block_txn_request.to_absolute() |
|
|
|
assert_equal(absolute_indexes, [0]) # should be a coinbase request |
|
|
|
assert_equal(absolute_indexes, [0]) # should be a coinbase request |
|
|
|
|
|
|
|
|
|
|
|
# Send the coinbase, and verify that the tip advances. |
|
|
|
# Send the coinbase, and verify that the tip advances. |
|
|
@ -493,8 +459,8 @@ class CompactBlocksTest(BitcoinTestFramework): |
|
|
|
msg = msg_cmpctblock(compact_block.to_p2p()) |
|
|
|
msg = msg_cmpctblock(compact_block.to_p2p()) |
|
|
|
peer.send_and_ping(msg) |
|
|
|
peer.send_and_ping(msg) |
|
|
|
with mininode_lock: |
|
|
|
with mininode_lock: |
|
|
|
assert(peer.last_getblocktxn is not None) |
|
|
|
assert("getblocktxn" in peer.last_message) |
|
|
|
absolute_indexes = peer.last_getblocktxn.block_txn_request.to_absolute() |
|
|
|
absolute_indexes = peer.last_message["getblocktxn"].block_txn_request.to_absolute() |
|
|
|
assert_equal(absolute_indexes, expected_result) |
|
|
|
assert_equal(absolute_indexes, expected_result) |
|
|
|
|
|
|
|
|
|
|
|
def test_tip_after_message(node, peer, msg, tip): |
|
|
|
def test_tip_after_message(node, peer, msg, tip): |
|
|
@ -558,14 +524,14 @@ class CompactBlocksTest(BitcoinTestFramework): |
|
|
|
|
|
|
|
|
|
|
|
# Clear out last request. |
|
|
|
# Clear out last request. |
|
|
|
with mininode_lock: |
|
|
|
with mininode_lock: |
|
|
|
test_node.last_getblocktxn = None |
|
|
|
test_node.last_message.pop("getblocktxn", None) |
|
|
|
|
|
|
|
|
|
|
|
# Send compact block |
|
|
|
# Send compact block |
|
|
|
comp_block.initialize_from_block(block, prefill_list=[0], use_witness=with_witness) |
|
|
|
comp_block.initialize_from_block(block, prefill_list=[0], use_witness=with_witness) |
|
|
|
test_tip_after_message(node, test_node, msg_cmpctblock(comp_block.to_p2p()), block.sha256) |
|
|
|
test_tip_after_message(node, test_node, msg_cmpctblock(comp_block.to_p2p()), block.sha256) |
|
|
|
with mininode_lock: |
|
|
|
with mininode_lock: |
|
|
|
# Shouldn't have gotten a request for any transaction |
|
|
|
# Shouldn't have gotten a request for any transaction |
|
|
|
assert(test_node.last_getblocktxn is None) |
|
|
|
assert("getblocktxn" not in test_node.last_message) |
|
|
|
|
|
|
|
|
|
|
|
# Incorrectly responding to a getblocktxn shouldn't cause the block to be |
|
|
|
# Incorrectly responding to a getblocktxn shouldn't cause the block to be |
|
|
|
# permanently failed. |
|
|
|
# permanently failed. |
|
|
@ -591,8 +557,8 @@ class CompactBlocksTest(BitcoinTestFramework): |
|
|
|
test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p())) |
|
|
|
test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p())) |
|
|
|
absolute_indexes = [] |
|
|
|
absolute_indexes = [] |
|
|
|
with mininode_lock: |
|
|
|
with mininode_lock: |
|
|
|
assert(test_node.last_getblocktxn is not None) |
|
|
|
assert("getblocktxn" in test_node.last_message) |
|
|
|
absolute_indexes = test_node.last_getblocktxn.block_txn_request.to_absolute() |
|
|
|
absolute_indexes = test_node.last_message["getblocktxn"].block_txn_request.to_absolute() |
|
|
|
assert_equal(absolute_indexes, [6, 7, 8, 9, 10]) |
|
|
|
assert_equal(absolute_indexes, [6, 7, 8, 9, 10]) |
|
|
|
|
|
|
|
|
|
|
|
# Now give an incorrect response. |
|
|
|
# Now give an incorrect response. |
|
|
@ -613,11 +579,11 @@ class CompactBlocksTest(BitcoinTestFramework): |
|
|
|
assert_equal(int(node.getbestblockhash(), 16), block.hashPrevBlock) |
|
|
|
assert_equal(int(node.getbestblockhash(), 16), block.hashPrevBlock) |
|
|
|
|
|
|
|
|
|
|
|
# We should receive a getdata request |
|
|
|
# We should receive a getdata request |
|
|
|
success = wait_until(lambda: test_node.last_getdata is not None, timeout=10) |
|
|
|
success = wait_until(lambda: "getdata" in test_node.last_message, timeout=10) |
|
|
|
assert(success) |
|
|
|
assert(success) |
|
|
|
assert_equal(len(test_node.last_getdata.inv), 1) |
|
|
|
assert_equal(len(test_node.last_message["getdata"].inv), 1) |
|
|
|
assert(test_node.last_getdata.inv[0].type == 2 or test_node.last_getdata.inv[0].type == 2|MSG_WITNESS_FLAG) |
|
|
|
assert(test_node.last_message["getdata"].inv[0].type == 2 or test_node.last_message["getdata"].inv[0].type == 2|MSG_WITNESS_FLAG) |
|
|
|
assert_equal(test_node.last_getdata.inv[0].hash, block.sha256) |
|
|
|
assert_equal(test_node.last_message["getdata"].inv[0].hash, block.sha256) |
|
|
|
|
|
|
|
|
|
|
|
# Deliver the block |
|
|
|
# Deliver the block |
|
|
|
if version==2: |
|
|
|
if version==2: |
|
|
@ -641,15 +607,15 @@ class CompactBlocksTest(BitcoinTestFramework): |
|
|
|
num_to_request = random.randint(1, len(block.vtx)) |
|
|
|
num_to_request = random.randint(1, len(block.vtx)) |
|
|
|
msg.block_txn_request.from_absolute(sorted(random.sample(range(len(block.vtx)), num_to_request))) |
|
|
|
msg.block_txn_request.from_absolute(sorted(random.sample(range(len(block.vtx)), num_to_request))) |
|
|
|
test_node.send_message(msg) |
|
|
|
test_node.send_message(msg) |
|
|
|
success = wait_until(lambda: test_node.last_blocktxn is not None, timeout=10) |
|
|
|
success = wait_until(lambda: "blocktxn" in test_node.last_message, timeout=10) |
|
|
|
assert(success) |
|
|
|
assert(success) |
|
|
|
|
|
|
|
|
|
|
|
[tx.calc_sha256() for tx in block.vtx] |
|
|
|
[tx.calc_sha256() for tx in block.vtx] |
|
|
|
with mininode_lock: |
|
|
|
with mininode_lock: |
|
|
|
assert_equal(test_node.last_blocktxn.block_transactions.blockhash, int(block_hash, 16)) |
|
|
|
assert_equal(test_node.last_message["blocktxn"].block_transactions.blockhash, int(block_hash, 16)) |
|
|
|
all_indices = msg.block_txn_request.to_absolute() |
|
|
|
all_indices = msg.block_txn_request.to_absolute() |
|
|
|
for index in all_indices: |
|
|
|
for index in all_indices: |
|
|
|
tx = test_node.last_blocktxn.block_transactions.transactions.pop(0) |
|
|
|
tx = test_node.last_message["blocktxn"].block_transactions.transactions.pop(0) |
|
|
|
tx.calc_sha256() |
|
|
|
tx.calc_sha256() |
|
|
|
assert_equal(tx.sha256, block.vtx[index].sha256) |
|
|
|
assert_equal(tx.sha256, block.vtx[index].sha256) |
|
|
|
if version == 1: |
|
|
|
if version == 1: |
|
|
@ -658,7 +624,7 @@ class CompactBlocksTest(BitcoinTestFramework): |
|
|
|
else: |
|
|
|
else: |
|
|
|
# Check that the witness matches |
|
|
|
# Check that the witness matches |
|
|
|
assert_equal(tx.calc_sha256(True), block.vtx[index].calc_sha256(True)) |
|
|
|
assert_equal(tx.calc_sha256(True), block.vtx[index].calc_sha256(True)) |
|
|
|
test_node.last_blocktxn = None |
|
|
|
test_node.last_message.pop("blocktxn", None) |
|
|
|
current_height -= 1 |
|
|
|
current_height -= 1 |
|
|
|
|
|
|
|
|
|
|
|
# Next request should send a full block response, as we're past the |
|
|
|
# Next request should send a full block response, as we're past the |
|
|
@ -666,13 +632,13 @@ class CompactBlocksTest(BitcoinTestFramework): |
|
|
|
block_hash = node.getblockhash(current_height) |
|
|
|
block_hash = node.getblockhash(current_height) |
|
|
|
msg.block_txn_request = BlockTransactionsRequest(int(block_hash, 16), [0]) |
|
|
|
msg.block_txn_request = BlockTransactionsRequest(int(block_hash, 16), [0]) |
|
|
|
with mininode_lock: |
|
|
|
with mininode_lock: |
|
|
|
test_node.last_block = None |
|
|
|
test_node.last_message.pop("block", None) |
|
|
|
test_node.last_blocktxn = None |
|
|
|
test_node.last_message.pop("blocktxn", None) |
|
|
|
test_node.send_and_ping(msg) |
|
|
|
test_node.send_and_ping(msg) |
|
|
|
with mininode_lock: |
|
|
|
with mininode_lock: |
|
|
|
test_node.last_block.block.calc_sha256() |
|
|
|
test_node.last_message["block"].block.calc_sha256() |
|
|
|
assert_equal(test_node.last_block.block.sha256, int(block_hash, 16)) |
|
|
|
assert_equal(test_node.last_message["block"].block.sha256, int(block_hash, 16)) |
|
|
|
assert_equal(test_node.last_blocktxn, None) |
|
|
|
assert "blocktxn" not in test_node.last_message |
|
|
|
|
|
|
|
|
|
|
|
def test_compactblocks_not_at_tip(self, node, test_node): |
|
|
|
def test_compactblocks_not_at_tip(self, node, test_node): |
|
|
|
# Test that requesting old compactblocks doesn't work. |
|
|
|
# Test that requesting old compactblocks doesn't work. |
|
|
@ -685,7 +651,7 @@ class CompactBlocksTest(BitcoinTestFramework): |
|
|
|
|
|
|
|
|
|
|
|
test_node.clear_block_announcement() |
|
|
|
test_node.clear_block_announcement() |
|
|
|
test_node.send_message(msg_getdata([CInv(4, int(new_blocks[0], 16))])) |
|
|
|
test_node.send_message(msg_getdata([CInv(4, int(new_blocks[0], 16))])) |
|
|
|
success = wait_until(lambda: test_node.last_cmpctblock is not None, timeout=30) |
|
|
|
success = wait_until(lambda: "cmpctblock" in test_node.last_message, timeout=30) |
|
|
|
assert(success) |
|
|
|
assert(success) |
|
|
|
|
|
|
|
|
|
|
|
test_node.clear_block_announcement() |
|
|
|
test_node.clear_block_announcement() |
|
|
@ -693,13 +659,13 @@ class CompactBlocksTest(BitcoinTestFramework): |
|
|
|
wait_until(test_node.received_block_announcement, timeout=30) |
|
|
|
wait_until(test_node.received_block_announcement, timeout=30) |
|
|
|
test_node.clear_block_announcement() |
|
|
|
test_node.clear_block_announcement() |
|
|
|
with mininode_lock: |
|
|
|
with mininode_lock: |
|
|
|
test_node.last_block = None |
|
|
|
test_node.last_message.pop("block", None) |
|
|
|
test_node.send_message(msg_getdata([CInv(4, int(new_blocks[0], 16))])) |
|
|
|
test_node.send_message(msg_getdata([CInv(4, int(new_blocks[0], 16))])) |
|
|
|
success = wait_until(lambda: test_node.last_block is not None, timeout=30) |
|
|
|
success = wait_until(lambda: "block" in test_node.last_message, timeout=30) |
|
|
|
assert(success) |
|
|
|
assert(success) |
|
|
|
with mininode_lock: |
|
|
|
with mininode_lock: |
|
|
|
test_node.last_block.block.calc_sha256() |
|
|
|
test_node.last_message["block"].block.calc_sha256() |
|
|
|
assert_equal(test_node.last_block.block.sha256, int(new_blocks[0], 16)) |
|
|
|
assert_equal(test_node.last_message["block"].block.sha256, int(new_blocks[0], 16)) |
|
|
|
|
|
|
|
|
|
|
|
# Generate an old compactblock, and verify that it's not accepted. |
|
|
|
# Generate an old compactblock, and verify that it's not accepted. |
|
|
|
cur_height = node.getblockcount() |
|
|
|
cur_height = node.getblockcount() |
|
|
@ -726,10 +692,10 @@ class CompactBlocksTest(BitcoinTestFramework): |
|
|
|
msg = msg_getblocktxn() |
|
|
|
msg = msg_getblocktxn() |
|
|
|
msg.block_txn_request = BlockTransactionsRequest(block.sha256, [0]) |
|
|
|
msg.block_txn_request = BlockTransactionsRequest(block.sha256, [0]) |
|
|
|
with mininode_lock: |
|
|
|
with mininode_lock: |
|
|
|
test_node.last_blocktxn = None |
|
|
|
test_node.last_message.pop("blocktxn", None) |
|
|
|
test_node.send_and_ping(msg) |
|
|
|
test_node.send_and_ping(msg) |
|
|
|
with mininode_lock: |
|
|
|
with mininode_lock: |
|
|
|
assert(test_node.last_blocktxn is None) |
|
|
|
assert "blocktxn" not in test_node.last_message |
|
|
|
|
|
|
|
|
|
|
|
def activate_segwit(self, node): |
|
|
|
def activate_segwit(self, node): |
|
|
|
node.generate(144*3) |
|
|
|
node.generate(144*3) |
|
|
@ -750,9 +716,9 @@ class CompactBlocksTest(BitcoinTestFramework): |
|
|
|
wait_until(lambda: l.received_block_announcement(), timeout=30) |
|
|
|
wait_until(lambda: l.received_block_announcement(), timeout=30) |
|
|
|
with mininode_lock: |
|
|
|
with mininode_lock: |
|
|
|
for l in listeners: |
|
|
|
for l in listeners: |
|
|
|
assert(l.last_cmpctblock is not None) |
|
|
|
assert "cmpctblock" in l.last_message |
|
|
|
l.last_cmpctblock.header_and_shortids.header.calc_sha256() |
|
|
|
l.last_message["cmpctblock"].header_and_shortids.header.calc_sha256() |
|
|
|
assert_equal(l.last_cmpctblock.header_and_shortids.header.sha256, block.sha256) |
|
|
|
assert_equal(l.last_message["cmpctblock"].header_and_shortids.header.sha256, block.sha256) |
|
|
|
|
|
|
|
|
|
|
|
# Test that we don't get disconnected if we relay a compact block with valid header, |
|
|
|
# Test that we don't get disconnected if we relay a compact block with valid header, |
|
|
|
# but invalid transactions. |
|
|
|
# but invalid transactions. |
|
|
@ -804,7 +770,7 @@ class CompactBlocksTest(BitcoinTestFramework): |
|
|
|
msg = msg_cmpctblock(cmpct_block.to_p2p()) |
|
|
|
msg = msg_cmpctblock(cmpct_block.to_p2p()) |
|
|
|
peer.send_and_ping(msg) |
|
|
|
peer.send_and_ping(msg) |
|
|
|
with mininode_lock: |
|
|
|
with mininode_lock: |
|
|
|
assert(peer.last_getblocktxn is not None) |
|
|
|
assert "getblocktxn" in peer.last_message |
|
|
|
return block, cmpct_block |
|
|
|
return block, cmpct_block |
|
|
|
|
|
|
|
|
|
|
|
block, cmpct_block = announce_cmpct_block(node, stalling_peer) |
|
|
|
block, cmpct_block = announce_cmpct_block(node, stalling_peer) |
|
|
|