Changeset View
Changeset View
Standalone View
Standalone View
test/functional/p2p_compactblocks.py
Show First 20 Lines • Show All 145 Lines • ▼ Show 20 Lines | def build_block_on_tip(self, node): | ||||
block.solve() | block.solve() | ||||
return block | return block | ||||
# Create 10 more anyone-can-spend utxo's for testing. | # Create 10 more anyone-can-spend utxo's for testing. | ||||
def make_utxos(self): | def make_utxos(self): | ||||
# Doesn't matter which node we use, just use node0. | # Doesn't matter which node we use, just use node0. | ||||
block = self.build_block_on_tip(self.nodes[0]) | block = self.build_block_on_tip(self.nodes[0]) | ||||
self.test_node.send_and_ping(msg_block(block)) | self.test_node.send_and_ping(msg_block(block)) | ||||
assert(int(self.nodes[0].getbestblockhash(), 16) == block.sha256) | assert int(self.nodes[0].getbestblockhash(), 16) == block.sha256 | ||||
self.nodes[0].generate(100) | self.nodes[0].generate(100) | ||||
total_value = block.vtx[0].vout[0].nValue | total_value = block.vtx[0].vout[0].nValue | ||||
out_value = total_value // 10 | out_value = total_value // 10 | ||||
tx = CTransaction() | tx = CTransaction() | ||||
tx.vin.append(CTxIn(COutPoint(block.vtx[0].sha256, 0), b'')) | tx.vin.append(CTxIn(COutPoint(block.vtx[0].sha256, 0), b'')) | ||||
for i in range(10): | for i in range(10): | ||||
tx.vout.append(CTxOut(out_value, CScript([OP_TRUE]))) | tx.vout.append(CTxOut(out_value, CScript([OP_TRUE]))) | ||||
Show All 31 Lines | def test_sendcmpct(self, node, test_node, preferred_version, old_node=None): | ||||
test_node.last_sendcmpct = [] | test_node.last_sendcmpct = [] | ||||
tip = int(node.getbestblockhash(), 16) | tip = int(node.getbestblockhash(), 16) | ||||
def check_announcement_of_new_block(node, peer, predicate): | def check_announcement_of_new_block(node, peer, predicate): | ||||
peer.clear_block_announcement() | peer.clear_block_announcement() | ||||
block_hash = int(node.generate(1)[0], 16) | block_hash = int(node.generate(1)[0], 16) | ||||
peer.wait_for_block_announcement(block_hash, timeout=30) | peer.wait_for_block_announcement(block_hash, timeout=30) | ||||
assert(peer.block_announced) | assert peer.block_announced | ||||
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_message.get("cmpctblock", None), peer.last_message.get("inv", None))) | 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( | check_announcement_of_new_block( | ||||
▲ Show 20 Lines • Show All 120 Lines • ▼ Show 20 Lines | def test_compactblock_construction(self, node, test_node): | ||||
# Wait until the block was announced (via compact blocks) | # Wait until the block was announced (via compact blocks) | ||||
wait_until(test_node.received_block_announcement, | wait_until(test_node.received_block_announcement, | ||||
timeout=30, lock=mininode_lock) | timeout=30, lock=mininode_lock) | ||||
# 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("cmpctblock" in test_node.last_message) | 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( | header_and_shortids = HeaderAndShortIDs( | ||||
test_node.last_message["cmpctblock"].header_and_shortids) | test_node.last_message["cmpctblock"].header_and_shortids) | ||||
self.check_compactblock_construction_from_block( | self.check_compactblock_construction_from_block( | ||||
header_and_shortids, block_hash, block) | 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 | ||||
with mininode_lock: | with mininode_lock: | ||||
test_node.clear_block_announcement() | test_node.clear_block_announcement() | ||||
inv = CInv(4, block_hash) # 4 == "CompactBlock" | inv = CInv(4, block_hash) # 4 == "CompactBlock" | ||||
test_node.send_message(msg_getdata([inv])) | test_node.send_message(msg_getdata([inv])) | ||||
wait_until(test_node.received_block_announcement, | wait_until(test_node.received_block_announcement, | ||||
timeout=30, lock=mininode_lock) | timeout=30, lock=mininode_lock) | ||||
# 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("cmpctblock" in test_node.last_message) | 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( | header_and_shortids = HeaderAndShortIDs( | ||||
test_node.last_message["cmpctblock"].header_and_shortids) | test_node.last_message["cmpctblock"].header_and_shortids) | ||||
self.check_compactblock_construction_from_block( | self.check_compactblock_construction_from_block( | ||||
header_and_shortids, block_hash, block) | header_and_shortids, block_hash, block) | ||||
def check_compactblock_construction_from_block(self, header_and_shortids, block_hash, block): | def check_compactblock_construction_from_block(self, header_and_shortids, block_hash, block): | ||||
# Check that we got the right block! | # Check that we got the right block! | ||||
header_and_shortids.header.calc_sha256() | header_and_shortids.header.calc_sha256() | ||||
assert_equal(header_and_shortids.header.sha256, block_hash) | assert_equal(header_and_shortids.header.sha256, block_hash) | ||||
# Make sure the prefilled_txn appears to have included the coinbase | # Make sure the prefilled_txn appears to have included the coinbase | ||||
assert(len(header_and_shortids.prefilled_txn) >= 1) | assert len(header_and_shortids.prefilled_txn) >= 1 | ||||
assert_equal(header_and_shortids.prefilled_txn[0].index, 0) | assert_equal(header_and_shortids.prefilled_txn[0].index, 0) | ||||
# Check that all prefilled_txn entries match what's in the block. | # Check that all prefilled_txn entries match what's in the block. | ||||
for entry in header_and_shortids.prefilled_txn: | for entry in header_and_shortids.prefilled_txn: | ||||
entry.tx.calc_sha256() | entry.tx.calc_sha256() | ||||
# This checks the tx agree | # This checks the tx agree | ||||
assert_equal(entry.tx.sha256, block.vtx[entry.index].sha256) | assert_equal(entry.tx.sha256, block.vtx[entry.index].sha256) | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | def test_compactblock_requests(self, node, test_node, version): | ||||
[k0, k1] = comp_block.get_siphash_keys() | [k0, k1] = comp_block.get_siphash_keys() | ||||
coinbase_hash = block.vtx[0].sha256 | coinbase_hash = block.vtx[0].sha256 | ||||
comp_block.shortids = [ | comp_block.shortids = [ | ||||
calculate_shortid(k0, k1, coinbase_hash)] | calculate_shortid(k0, k1, coinbase_hash)] | ||||
test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p())) | test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p())) | ||||
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("getblocktxn" in test_node.last_message) | assert "getblocktxn" in test_node.last_message | ||||
absolute_indexes = test_node.last_message["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. | ||||
msg = msg_blocktxn() | msg = msg_blocktxn() | ||||
msg.block_transactions.blockhash = block.sha256 | msg.block_transactions.blockhash = block.sha256 | ||||
msg.block_transactions.transactions = [block.vtx[0]] | msg.block_transactions.transactions = [block.vtx[0]] | ||||
Show All 25 Lines | class CompactBlocksTest(BitcoinTestFramework): | ||||
# Test that we only receive getblocktxn requests for transactions that the | # Test that we only receive getblocktxn requests for transactions that the | ||||
# node needs, and that responding to them causes the block to be | # node needs, and that responding to them causes the block to be | ||||
# reconstructed. | # reconstructed. | ||||
def test_getblocktxn_requests(self, node, test_node, version): | def test_getblocktxn_requests(self, node, test_node, version): | ||||
def test_getblocktxn_response(compact_block, peer, expected_result): | def test_getblocktxn_response(compact_block, peer, expected_result): | ||||
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("getblocktxn" in peer.last_message) | assert "getblocktxn" in peer.last_message | ||||
absolute_indexes = peer.last_message["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): | ||||
peer.send_and_ping(msg) | peer.send_and_ping(msg) | ||||
assert_equal(int(node.getbestblockhash(), 16), tip) | assert_equal(int(node.getbestblockhash(), 16), tip) | ||||
Show All 28 Lines | def test_getblocktxn_requests(self, node, test_node, version): | ||||
test_tip_after_message(node, test_node, msg_bt, block.sha256) | test_tip_after_message(node, test_node, msg_bt, block.sha256) | ||||
# Now try giving one transaction ahead of time. | # Now try giving one transaction ahead of time. | ||||
utxo = self.utxos.pop(0) | utxo = self.utxos.pop(0) | ||||
block, ordered_txs = self.build_block_with_transactions(node, utxo, 5) | block, ordered_txs = self.build_block_with_transactions(node, utxo, 5) | ||||
self.utxos.append( | self.utxos.append( | ||||
[ordered_txs[-1].sha256, 0, ordered_txs[-1].vout[0].nValue]) | [ordered_txs[-1].sha256, 0, ordered_txs[-1].vout[0].nValue]) | ||||
test_node.send_and_ping(msg_tx(ordered_txs[1])) | test_node.send_and_ping(msg_tx(ordered_txs[1])) | ||||
assert(ordered_txs[1].hash in node.getrawmempool()) | assert ordered_txs[1].hash in node.getrawmempool() | ||||
test_node.send_and_ping(msg_tx(ordered_txs[1])) | test_node.send_and_ping(msg_tx(ordered_txs[1])) | ||||
# Prefill 4 out of the 6 transactions, and verify that only the one | # Prefill 4 out of the 6 transactions, and verify that only the one | ||||
# that was not in the mempool is requested. | # that was not in the mempool is requested. | ||||
prefill_list = [0, 1, 2, 3, 4, 5] | prefill_list = [0, 1, 2, 3, 4, 5] | ||||
prefill_list.remove(block.vtx.index(ordered_txs[1])) | prefill_list.remove(block.vtx.index(ordered_txs[1])) | ||||
expected_index = block.vtx.index(ordered_txs[-1]) | expected_index = block.vtx.index(ordered_txs[-1]) | ||||
prefill_list.remove(expected_index) | prefill_list.remove(expected_index) | ||||
Show All 11 Lines | def test_getblocktxn_requests(self, node, test_node, version): | ||||
self.utxos.append( | self.utxos.append( | ||||
[ordered_txs[-1].sha256, 0, ordered_txs[-1].vout[0].nValue]) | [ordered_txs[-1].sha256, 0, ordered_txs[-1].vout[0].nValue]) | ||||
for tx in block.vtx[1:]: | for tx in block.vtx[1:]: | ||||
test_node.send_message(msg_tx(tx)) | test_node.send_message(msg_tx(tx)) | ||||
test_node.sync_with_ping() | test_node.sync_with_ping() | ||||
# Make sure all transactions were accepted. | # Make sure all transactions were accepted. | ||||
mempool = node.getrawmempool() | mempool = node.getrawmempool() | ||||
for tx in block.vtx[1:]: | for tx in block.vtx[1:]: | ||||
assert(tx.hash in mempool) | assert tx.hash in mempool | ||||
# Clear out last request. | # Clear out last request. | ||||
with mininode_lock: | with mininode_lock: | ||||
test_node.last_message.pop("getblocktxn", None) | test_node.last_message.pop("getblocktxn", None) | ||||
# Send compact block | # Send compact block | ||||
comp_block.initialize_from_block(block, prefill_list=[0]) | comp_block.initialize_from_block(block, prefill_list=[0]) | ||||
test_tip_after_message( | test_tip_after_message( | ||||
node, test_node, msg_cmpctblock(comp_block.to_p2p()), block.sha256) | 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("getblocktxn" not in test_node.last_message) | 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. | ||||
def test_incorrect_blocktxn_response(self, node, test_node, version): | def test_incorrect_blocktxn_response(self, node, test_node, version): | ||||
if (len(self.utxos) == 0): | if (len(self.utxos) == 0): | ||||
self.make_utxos() | self.make_utxos() | ||||
utxo = self.utxos.pop(0) | utxo = self.utxos.pop(0) | ||||
block, ordered_txs = self.build_block_with_transactions(node, utxo, 10) | block, ordered_txs = self.build_block_with_transactions(node, utxo, 10) | ||||
self.utxos.append( | self.utxos.append( | ||||
[ordered_txs[-1].sha256, 0, ordered_txs[-1].vout[0].nValue]) | [ordered_txs[-1].sha256, 0, ordered_txs[-1].vout[0].nValue]) | ||||
# Relay the first 5 transactions from the block in advance | # Relay the first 5 transactions from the block in advance | ||||
for tx in ordered_txs[1:6]: | for tx in ordered_txs[1:6]: | ||||
test_node.send_message(msg_tx(tx)) | test_node.send_message(msg_tx(tx)) | ||||
test_node.sync_with_ping() | test_node.sync_with_ping() | ||||
# Make sure all transactions were accepted. | # Make sure all transactions were accepted. | ||||
mempool = node.getrawmempool() | mempool = node.getrawmempool() | ||||
for tx in ordered_txs[1:6]: | for tx in ordered_txs[1:6]: | ||||
assert(tx.hash in mempool) | assert tx.hash in mempool | ||||
# Send compact block | # Send compact block | ||||
comp_block = HeaderAndShortIDs() | comp_block = HeaderAndShortIDs() | ||||
comp_block.initialize_from_block(block, prefill_list=[0]) | comp_block.initialize_from_block(block, prefill_list=[0]) | ||||
test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p())) | test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p())) | ||||
absolute_indices = [] | absolute_indices = [] | ||||
with mininode_lock: | with mininode_lock: | ||||
assert("getblocktxn" in test_node.last_message) | assert "getblocktxn" in test_node.last_message | ||||
absolute_indices = test_node.last_message["getblocktxn"].block_txn_request.to_absolute( | absolute_indices = test_node.last_message["getblocktxn"].block_txn_request.to_absolute( | ||||
) | ) | ||||
expected_indices = [] | expected_indices = [] | ||||
for i in [6, 7, 8, 9, 10]: | for i in [6, 7, 8, 9, 10]: | ||||
expected_indices.append(block.vtx.index(ordered_txs[i])) | expected_indices.append(block.vtx.index(ordered_txs[i])) | ||||
assert_equal(absolute_indices, sorted(expected_indices)) | assert_equal(absolute_indices, sorted(expected_indices)) | ||||
# Now give an incorrect response. | # Now give an incorrect response. | ||||
Show All 11 Lines | def test_incorrect_blocktxn_response(self, node, test_node, version): | ||||
# Tip should not have updated | # Tip should not have updated | ||||
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 | ||||
wait_until(lambda: "getdata" in test_node.last_message, | wait_until(lambda: "getdata" in test_node.last_message, | ||||
timeout=10, lock=mininode_lock) | timeout=10, lock=mininode_lock) | ||||
assert_equal(len(test_node.last_message["getdata"].inv), 1) | assert_equal(len(test_node.last_message["getdata"].inv), 1) | ||||
assert(test_node.last_message["getdata"].inv[0].type == 2) | assert test_node.last_message["getdata"].inv[0].type == 2 | ||||
assert_equal( | assert_equal( | ||||
test_node.last_message["getdata"].inv[0].hash, block.sha256) | test_node.last_message["getdata"].inv[0].hash, block.sha256) | ||||
# Deliver the block | # Deliver the block | ||||
test_node.send_and_ping(msg_block(block)) | test_node.send_and_ping(msg_block(block)) | ||||
assert_equal(int(node.getbestblockhash(), 16), block.sha256) | assert_equal(int(node.getbestblockhash(), 16), block.sha256) | ||||
def test_getblocktxn_handler(self, node, test_node, version): | def test_getblocktxn_handler(self, node, test_node, version): | ||||
▲ Show 20 Lines • Show All 87 Lines • ▼ Show 20 Lines | def test_compactblocks_not_at_tip(self, node, test_node): | ||||
tips = node.getchaintips() | tips = node.getchaintips() | ||||
found = False | found = False | ||||
for x in tips: | for x in tips: | ||||
if x["hash"] == block.hash: | if x["hash"] == block.hash: | ||||
assert_equal(x["status"], "headers-only") | assert_equal(x["status"], "headers-only") | ||||
found = True | found = True | ||||
break | break | ||||
assert(found) | assert found | ||||
# Requesting this block via getblocktxn should silently fail | # Requesting this block via getblocktxn should silently fail | ||||
# (to avoid fingerprinting attacks). | # (to avoid fingerprinting attacks). | ||||
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_message.pop("blocktxn", None) | test_node.last_message.pop("blocktxn", None) | ||||
test_node.send_and_ping(msg) | test_node.send_and_ping(msg) | ||||
Show All 18 Lines | def test_end_to_end_block_relay(self, node, listeners): | ||||
l.last_message["cmpctblock"].header_and_shortids.header.calc_sha256( | l.last_message["cmpctblock"].header_and_shortids.header.calc_sha256( | ||||
) | ) | ||||
assert_equal( | assert_equal( | ||||
l.last_message["cmpctblock"].header_and_shortids.header.sha256, block.sha256) | 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. | ||||
def test_invalid_tx_in_compactblock(self, node, test_node): | def test_invalid_tx_in_compactblock(self, node, test_node): | ||||
assert(len(self.utxos)) | assert len(self.utxos) | ||||
utxo = self.utxos[0] | utxo = self.utxos[0] | ||||
block, ordered_txs = self.build_block_with_transactions(node, utxo, 5) | block, ordered_txs = self.build_block_with_transactions(node, utxo, 5) | ||||
block.vtx.remove(ordered_txs[3]) | block.vtx.remove(ordered_txs[3]) | ||||
block.hashMerkleRoot = block.calc_merkle_root() | block.hashMerkleRoot = block.calc_merkle_root() | ||||
block.solve() | block.solve() | ||||
# Now send the compact block with all transactions prefilled, and | # Now send the compact block with all transactions prefilled, and | ||||
# verify that we don't get disconnected. | # verify that we don't get disconnected. | ||||
comp_block = HeaderAndShortIDs() | comp_block = HeaderAndShortIDs() | ||||
comp_block.initialize_from_block(block, prefill_list=[0, 1, 2, 3, 4]) | comp_block.initialize_from_block(block, prefill_list=[0, 1, 2, 3, 4]) | ||||
msg = msg_cmpctblock(comp_block.to_p2p()) | msg = msg_cmpctblock(comp_block.to_p2p()) | ||||
test_node.send_and_ping(msg) | test_node.send_and_ping(msg) | ||||
# Check that the tip didn't advance | # Check that the tip didn't advance | ||||
assert(int(node.getbestblockhash(), 16) is not block.sha256) | assert int(node.getbestblockhash(), 16) is not block.sha256 | ||||
test_node.sync_with_ping() | test_node.sync_with_ping() | ||||
# Helper for enabling cb announcements | # Helper for enabling cb announcements | ||||
# Send the sendcmpct request and sync headers | # Send the sendcmpct request and sync headers | ||||
def request_cb_announcements(self, peer, node, version=1): | def request_cb_announcements(self, peer, node, version=1): | ||||
tip = node.getbestblockhash() | tip = node.getbestblockhash() | ||||
peer.get_headers(locator=[int(tip, 16)], hashstop=0) | peer.get_headers(locator=[int(tip, 16)], hashstop=0) | ||||
msg = msg_sendcmpct() | msg = msg_sendcmpct() | ||||
msg.version = version | msg.version = version | ||||
msg.announce = True | msg.announce = True | ||||
peer.send_and_ping(msg) | peer.send_and_ping(msg) | ||||
def test_compactblock_reconstruction_multiple_peers(self, node, stalling_peer, delivery_peer): | def test_compactblock_reconstruction_multiple_peers(self, node, stalling_peer, delivery_peer): | ||||
assert(len(self.utxos)) | assert len(self.utxos) | ||||
def announce_cmpct_block(node, peer): | def announce_cmpct_block(node, peer): | ||||
utxo = self.utxos.pop(0) | utxo = self.utxos.pop(0) | ||||
block, _ = self.build_block_with_transactions(node, utxo, 5) | block, _ = self.build_block_with_transactions(node, utxo, 5) | ||||
cmpct_block = HeaderAndShortIDs() | cmpct_block = HeaderAndShortIDs() | ||||
cmpct_block.initialize_from_block(block) | cmpct_block.initialize_from_block(block) | ||||
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 "getblocktxn" in peer.last_message | 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) | ||||
for tx in block.vtx[1:]: | for tx in block.vtx[1:]: | ||||
delivery_peer.send_message(msg_tx(tx)) | delivery_peer.send_message(msg_tx(tx)) | ||||
delivery_peer.sync_with_ping() | delivery_peer.sync_with_ping() | ||||
mempool = node.getrawmempool() | mempool = node.getrawmempool() | ||||
for tx in block.vtx[1:]: | for tx in block.vtx[1:]: | ||||
assert(tx.hash in mempool) | assert tx.hash in mempool | ||||
delivery_peer.send_and_ping(msg_cmpctblock(cmpct_block.to_p2p())) | delivery_peer.send_and_ping(msg_cmpctblock(cmpct_block.to_p2p())) | ||||
assert_equal(int(node.getbestblockhash(), 16), block.sha256) | assert_equal(int(node.getbestblockhash(), 16), block.sha256) | ||||
self.utxos.append( | self.utxos.append( | ||||
[block.vtx[-1].sha256, 0, block.vtx[-1].vout[0].nValue]) | [block.vtx[-1].sha256, 0, block.vtx[-1].vout[0].nValue]) | ||||
# Now test that delivering an invalid compact block won't break relay | # Now test that delivering an invalid compact block won't break relay | ||||
block, cmpct_block = announce_cmpct_block(node, stalling_peer) | block, cmpct_block = announce_cmpct_block(node, stalling_peer) | ||||
for tx in block.vtx[1:]: | for tx in block.vtx[1:]: | ||||
delivery_peer.send_message(msg_tx(tx)) | delivery_peer.send_message(msg_tx(tx)) | ||||
delivery_peer.sync_with_ping() | delivery_peer.sync_with_ping() | ||||
# TODO: modify txhash in a way that doesn't impact txid. | # TODO: modify txhash in a way that doesn't impact txid. | ||||
delivery_peer.send_and_ping(msg_cmpctblock(cmpct_block.to_p2p())) | delivery_peer.send_and_ping(msg_cmpctblock(cmpct_block.to_p2p())) | ||||
# Because txhash isn't modified, we end up reconstructing the same block | # Because txhash isn't modified, we end up reconstructing the same block | ||||
# assert(int(node.getbestblockhash(), 16) != block.sha256) | # assert int(node.getbestblockhash(), 16) != block.sha256 | ||||
msg = msg_blocktxn() | msg = msg_blocktxn() | ||||
msg.block_transactions.blockhash = block.sha256 | msg.block_transactions.blockhash = block.sha256 | ||||
msg.block_transactions.transactions = block.vtx[1:] | msg.block_transactions.transactions = block.vtx[1:] | ||||
stalling_peer.send_and_ping(msg) | stalling_peer.send_and_ping(msg) | ||||
assert_equal(int(node.getbestblockhash(), 16), block.sha256) | assert_equal(int(node.getbestblockhash(), 16), block.sha256) | ||||
def run_test(self): | def run_test(self): | ||||
▲ Show 20 Lines • Show All 91 Lines • Show Last 20 Lines |