Changeset View
Changeset View
Standalone View
Standalone View
test/functional/abc_p2p_compactblocks.py
Show All 33 Lines | |||||
from test_framework.p2p import P2PDataStore, P2PInterface, p2p_lock | from test_framework.p2p import P2PDataStore, P2PInterface, p2p_lock | ||||
from test_framework.script import OP_RETURN, OP_TRUE, CScript | from test_framework.script import OP_RETURN, OP_TRUE, CScript | ||||
from test_framework.test_framework import BitcoinTestFramework | from test_framework.test_framework import BitcoinTestFramework | ||||
from test_framework.txtools import pad_tx | from test_framework.txtools import pad_tx | ||||
from test_framework.util import assert_equal | from test_framework.util import assert_equal | ||||
class PreviousSpendableOutput: | class PreviousSpendableOutput: | ||||
def __init__(self, tx=CTransaction(), n=-1): | def __init__(self, tx=CTransaction(), n=-1): | ||||
self.tx = tx | self.tx = tx | ||||
# the output we're spending | # the output we're spending | ||||
self.n = n | self.n = n | ||||
# TestP2PConn: A peer we use to send messages to bitcoind, and store responses. | # TestP2PConn: A peer we use to send messages to bitcoind, and store responses. | ||||
class TestP2PConn(P2PInterface): | class TestP2PConn(P2PInterface): | ||||
def __init__(self): | def __init__(self): | ||||
self.last_sendcmpct = None | self.last_sendcmpct = None | ||||
self.last_cmpctblock = None | self.last_cmpctblock = None | ||||
self.last_getheaders = None | self.last_getheaders = None | ||||
self.last_headers = None | self.last_headers = None | ||||
super().__init__() | super().__init__() | ||||
def on_sendcmpct(self, message): | def on_sendcmpct(self, message): | ||||
Show All 13 Lines | class TestP2PConn(P2PInterface): | ||||
def clear_block_data(self): | def clear_block_data(self): | ||||
with p2p_lock: | with p2p_lock: | ||||
self.last_sendcmpct = None | self.last_sendcmpct = None | ||||
self.last_cmpctblock = None | self.last_cmpctblock = None | ||||
class FullBlockTest(BitcoinTestFramework): | class FullBlockTest(BitcoinTestFramework): | ||||
def set_test_params(self): | def set_test_params(self): | ||||
self.num_nodes = 1 | self.num_nodes = 1 | ||||
self.setup_clean_chain = True | self.setup_clean_chain = True | ||||
self.block_heights = {} | self.block_heights = {} | ||||
self.tip = None | self.tip = None | ||||
self.blocks = {} | self.blocks = {} | ||||
self.excessive_block_size = 16 * ONE_MEGABYTE | self.excessive_block_size = 16 * ONE_MEGABYTE | ||||
self.extra_args = [['-whitelist=noban@127.0.0.1', | self.extra_args = [ | ||||
'-limitancestorcount=999999', | [ | ||||
'-limitancestorsize=999999', | "-whitelist=noban@127.0.0.1", | ||||
'-limitdescendantcount=999999', | "-limitancestorcount=999999", | ||||
'-limitdescendantsize=999999', | "-limitancestorsize=999999", | ||||
'-maxmempool=99999', | "-limitdescendantcount=999999", | ||||
f'-excessiveblocksize={self.excessive_block_size}', | "-limitdescendantsize=999999", | ||||
'-acceptnonstdtxn=1']] | "-maxmempool=99999", | ||||
f"-excessiveblocksize={self.excessive_block_size}", | |||||
"-acceptnonstdtxn=1", | |||||
] | |||||
] | |||||
# UBSAN will cause this test to timeout without this. | # UBSAN will cause this test to timeout without this. | ||||
self.rpc_timeout = 180 | self.rpc_timeout = 180 | ||||
def add_transactions_to_block(self, block, tx_list): | def add_transactions_to_block(self, block, tx_list): | ||||
[tx.rehash() for tx in tx_list] | [tx.rehash() for tx in tx_list] | ||||
block.vtx.extend(tx_list) | block.vtx.extend(tx_list) | ||||
def next_block(self, number, spend=None, script=CScript( | def next_block( | ||||
[OP_TRUE]), block_size=0, extra_txns=0): | self, number, spend=None, script=CScript([OP_TRUE]), block_size=0, extra_txns=0 | ||||
): | |||||
if self.tip is None: | if self.tip is None: | ||||
base_block_hash = self.genesis_hash | base_block_hash = self.genesis_hash | ||||
block_time = int(time.time()) + 1 | block_time = int(time.time()) + 1 | ||||
else: | else: | ||||
base_block_hash = self.tip.sha256 | base_block_hash = self.tip.sha256 | ||||
block_time = self.tip.nTime + 1 | block_time = self.tip.nTime + 1 | ||||
# First create the coinbase | # First create the coinbase | ||||
height = self.block_heights[base_block_hash] + 1 | height = self.block_heights[base_block_hash] + 1 | ||||
Show All 32 Lines | ): | ||||
tx.rehash() | tx.rehash() | ||||
# If a specific script is required, add it. | # If a specific script is required, add it. | ||||
if script is not None: | if script is not None: | ||||
tx.vout.append(CTxOut(1, script)) | tx.vout.append(CTxOut(1, script)) | ||||
# Put some random data into the first transaction of the chain to | # Put some random data into the first transaction of the chain to | ||||
# randomize ids. | # randomize ids. | ||||
tx.vout.append( | tx.vout.append(CTxOut(0, CScript([random.randint(0, 256), OP_RETURN]))) | ||||
CTxOut(0, CScript([random.randint(0, 256), OP_RETURN]))) | |||||
# Add the transaction to the block | # Add the transaction to the block | ||||
self.add_transactions_to_block(block, [tx]) | self.add_transactions_to_block(block, [tx]) | ||||
# Add transaction until we reach the expected transaction count | # Add transaction until we reach the expected transaction count | ||||
for _ in range(extra_txns): | for _ in range(extra_txns): | ||||
self.add_transactions_to_block(block, [get_base_transaction()]) | self.add_transactions_to_block(block, [get_base_transaction()]) | ||||
▲ Show 20 Lines • Show All 90 Lines • ▼ Show 20 Lines | def run_test(self): | ||||
# collect spendable outputs now to avoid cluttering the code later on | # collect spendable outputs now to avoid cluttering the code later on | ||||
out = [] | out = [] | ||||
for i in range(100): | for i in range(100): | ||||
out.append(get_spendable_output()) | out.append(get_spendable_output()) | ||||
# Check that compact block also work for big blocks | # Check that compact block also work for big blocks | ||||
# Wait for SENDCMPCT | # Wait for SENDCMPCT | ||||
def received_sendcmpct(): | def received_sendcmpct(): | ||||
return (test_p2p.last_sendcmpct is not None) | return test_p2p.last_sendcmpct is not None | ||||
self.wait_until(received_sendcmpct, timeout=30) | self.wait_until(received_sendcmpct, timeout=30) | ||||
test_p2p.send_and_ping(msg_sendcmpct(announce=True, version=1)) | test_p2p.send_and_ping(msg_sendcmpct(announce=True, version=1)) | ||||
# Exchange headers | # Exchange headers | ||||
def received_getheaders(): | def received_getheaders(): | ||||
return (test_p2p.last_getheaders is not None) | return test_p2p.last_getheaders is not None | ||||
self.wait_until(received_getheaders, timeout=30) | self.wait_until(received_getheaders, timeout=30) | ||||
# Return the favor | # Return the favor | ||||
test_p2p.send_message(test_p2p.last_getheaders) | test_p2p.send_message(test_p2p.last_getheaders) | ||||
# Wait for the header list | # Wait for the header list | ||||
def received_headers(): | def received_headers(): | ||||
return (test_p2p.last_headers is not None) | return test_p2p.last_headers is not None | ||||
self.wait_until(received_headers, timeout=30) | self.wait_until(received_headers, timeout=30) | ||||
# It's like we know about the same headers ! | # It's like we know about the same headers ! | ||||
test_p2p.send_message(test_p2p.last_headers) | test_p2p.send_message(test_p2p.last_headers) | ||||
# Send a block | # Send a block | ||||
b1 = block(1, spend=out[0], block_size=ONE_MEGABYTE + 1) | b1 = block(1, spend=out[0], block_size=ONE_MEGABYTE + 1) | ||||
default_p2p.send_blocks_and_test([self.tip], node) | default_p2p.send_blocks_and_test([self.tip], node) | ||||
# Checks the node to forward it via compact block | # Checks the node to forward it via compact block | ||||
def received_block(): | def received_block(): | ||||
return (test_p2p.last_cmpctblock is not None) | return test_p2p.last_cmpctblock is not None | ||||
self.wait_until(received_block, timeout=30) | self.wait_until(received_block, timeout=30) | ||||
# Was it our block ? | # Was it our block ? | ||||
cmpctblk_header = test_p2p.last_cmpctblock.header_and_shortids.header | cmpctblk_header = test_p2p.last_cmpctblock.header_and_shortids.header | ||||
cmpctblk_header.calc_sha256() | cmpctblk_header.calc_sha256() | ||||
assert cmpctblk_header.sha256 == b1.sha256 | assert cmpctblk_header.sha256 == b1.sha256 | ||||
# Send a large block with numerous transactions. | # Send a large block with numerous transactions. | ||||
test_p2p.clear_block_data() | test_p2p.clear_block_data() | ||||
b2 = block(2, spend=out[1], extra_txns=70000, | b2 = block( | ||||
block_size=self.excessive_block_size - 1000) | 2, | ||||
spend=out[1], | |||||
extra_txns=70000, | |||||
block_size=self.excessive_block_size - 1000, | |||||
) | |||||
default_p2p.send_blocks_and_test([self.tip], node) | default_p2p.send_blocks_and_test([self.tip], node) | ||||
# Checks the node forwards it via compact block | # Checks the node forwards it via compact block | ||||
self.wait_until(received_block, timeout=30) | self.wait_until(received_block, timeout=30) | ||||
# Was it our block ? | # Was it our block ? | ||||
cmpctblk_header = test_p2p.last_cmpctblock.header_and_shortids.header | cmpctblk_header = test_p2p.last_cmpctblock.header_and_shortids.header | ||||
cmpctblk_header.calc_sha256() | cmpctblk_header.calc_sha256() | ||||
Show All 18 Lines | def run_test(self): | ||||
comp_block = HeaderAndShortIDs() | comp_block = HeaderAndShortIDs() | ||||
comp_block.initialize_from_block(b2) | comp_block.initialize_from_block(b2) | ||||
test_p2p.send_and_ping(msg_cmpctblock(comp_block.to_p2p())) | test_p2p.send_and_ping(msg_cmpctblock(comp_block.to_p2p())) | ||||
# Check that compact block is received properly | # Check that compact block is received properly | ||||
assert int(node.getbestblockhash(), 16) == b2.sha256 | assert int(node.getbestblockhash(), 16) == b2.sha256 | ||||
if __name__ == '__main__': | if __name__ == "__main__": | ||||
FullBlockTest().main() | FullBlockTest().main() |