Changeset View
Changeset View
Standalone View
Standalone View
test/functional/abc-p2p-compactblocks.py
Show First 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | class FullBlockTest(ComparisonTestFramework): | ||||
# the comparison. | # the comparison. | ||||
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 = 100 * ONE_MEGABYTE | self.excessive_block_size = 16 * ONE_MEGABYTE | ||||
self.extra_args = [['-norelaypriority', | self.extra_args = [['-norelaypriority', | ||||
'-whitelist=127.0.0.1', | '-whitelist=127.0.0.1', | ||||
'-limitancestorcount=9999', | '-limitancestorcount=999999', | ||||
'-limitancestorsize=9999', | '-limitancestorsize=999999', | ||||
'-limitdescendantcount=9999', | '-limitdescendantcount=999999', | ||||
'-limitdescendantsize=9999', | '-limitdescendantsize=999999', | ||||
'-maxmempool=999', | '-maxmempool=99999', | ||||
"-excessiveblocksize=%d" | "-excessiveblocksize=%d" | ||||
% self.excessive_block_size]] | % self.excessive_block_size]] | ||||
def add_options(self, parser): | def add_options(self, parser): | ||||
super().add_options(parser) | super().add_options(parser) | ||||
parser.add_option( | parser.add_option( | ||||
"--runbarelyexpensive", dest="runbarelyexpensive", default=True) | "--runbarelyexpensive", dest="runbarelyexpensive", default=True) | ||||
Show All 10 Lines | 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) | ||||
# this is a little handier to use than the version in blocktools.py | # this is a little handier to use than the version in blocktools.py | ||||
def create_tx(self, spend_tx, n, value, script=CScript([OP_TRUE])): | def create_tx(self, spend_tx, n, value, script=CScript([OP_TRUE])): | ||||
tx = create_transaction(spend_tx, n, b"", value, script) | tx = create_transaction(spend_tx, n, b"", value, script) | ||||
return tx | return tx | ||||
def next_block(self, number, spend=None, script=CScript([OP_TRUE]), block_size=0): | def next_block(self, number, spend=None, script=CScript([OP_TRUE]), block_size=0, extra_txns=0): | ||||
if self.tip == None: | if self.tip == 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 37 Lines | def next_block(self, number, spend=None, script=CScript([OP_TRUE]), block_size=0, extra_txns=0): | ||||
# Put some random data into the first transaction of the chain to randomize ids. | # Put some random data into the first transaction of the chain to 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 | |||||
for _ in range(extra_txns): | |||||
self.add_transactions_to_block(block, [get_base_transaction()]) | |||||
# If we have a block size requirement, just fill | # If we have a block size requirement, just fill | ||||
# the block until we get there | # the block until we get there | ||||
current_block_size = len(block.serialize()) | current_block_size = len(block.serialize()) | ||||
while current_block_size < block_size: | while current_block_size < block_size: | ||||
# We will add a new transaction. That means the size of | # We will add a new transaction. That means the size of | ||||
# the field enumerating how many transaction go in the block | # the field enumerating how many transaction go in the block | ||||
# may change. | # may change. | ||||
current_block_size -= len(ser_compact_size(len(block.vtx))) | current_block_size -= len(ser_compact_size(len(block.vtx))) | ||||
▲ Show 20 Lines • Show All 145 Lines • ▼ Show 20 Lines | def get_tests(self): | ||||
return (peer.last_cmpctblock != None) | return (peer.last_cmpctblock != None) | ||||
wait_until(received_block, timeout=30) | wait_until(received_block, timeout=30) | ||||
# Was it our block ? | # Was it our block ? | ||||
cmpctblk_header = peer.last_cmpctblock.header_and_shortids.header | cmpctblk_header = peer.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 bigger block | # Send a large block with numerous transactions. | ||||
peer.clear_block_data() | peer.clear_block_data() | ||||
b2 = block(2, spend=out[1], block_size=self.excessive_block_size) | b2 = block(2, spend=out[1], extra_txns=70000, | ||||
block_size=self.excessive_block_size - 1000) | |||||
yield accepted() | yield accepted() | ||||
# Checks the node forwards it via compact block | # Checks the node forwards it via compact block | ||||
wait_until(received_block, timeout=30) | wait_until(received_block, timeout=30) | ||||
# Was it our block ? | # Was it our block ? | ||||
cmpctblk_header = peer.last_cmpctblock.header_and_shortids.header | cmpctblk_header = peer.last_cmpctblock.header_and_shortids.header | ||||
cmpctblk_header.calc_sha256() | cmpctblk_header.calc_sha256() | ||||
assert(cmpctblk_header.sha256 == b2.sha256) | assert(cmpctblk_header.sha256 == b2.sha256) | ||||
# In order to avoid having to resend a ton of transactions, we invalidate | |||||
# b2, which will send all its transactions in the mempool. | |||||
node.invalidateblock(node.getbestblockhash()) | |||||
# Let's send a compact block and see if the node accepts it. | # Let's send a compact block and see if the node accepts it. | ||||
# First, we generate the block and send all transaction to the mempool | # Let's modify b2 and use it so that we can reuse the mempool. | ||||
b3 = block(3, spend=out[2], block_size=8 * ONE_MEGABYTE) | tx = b2.vtx[0] | ||||
for i in range(1, len(b3.vtx)): | tx.vout.append(CTxOut(0, CScript([random.randint(0, 256), OP_RETURN]))) | ||||
node.sendrawtransaction(ToHex(b3.vtx[i]), True) | tx.rehash() | ||||
b2.vtx[0] = tx | |||||
b2.hashMerkleRoot = b2.calc_merkle_root() | |||||
b2.solve() | |||||
# Now we create the compact block and send it | # Now we create the compact block and send it | ||||
comp_block = HeaderAndShortIDs() | comp_block = HeaderAndShortIDs() | ||||
comp_block.initialize_from_block(b3) | comp_block.initialize_from_block(b2) | ||||
peer.send_and_ping(msg_cmpctblock(comp_block.to_p2p())) | peer.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) == b3.sha256) | assert(int(node.getbestblockhash(), 16) == b2.sha256) | ||||
if __name__ == '__main__': | if __name__ == '__main__': | ||||
FullBlockTest().main() | FullBlockTest().main() |