diff --git a/test/functional/abc-p2p-compactblocks.py b/test/functional/abc-p2p-compactblocks.py --- a/test/functional/abc-p2p-compactblocks.py +++ b/test/functional/abc-p2p-compactblocks.py @@ -96,10 +96,6 @@ self.nodes[0].setexcessiveblock(self.excessive_block_size) self.test.run() - def add_transactions_to_block(self, block, tx_list): - [tx.rehash() for tx in tx_list] - block.vtx.extend(tx_list) - # 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])): tx = create_transaction(spend_tx, n, b"", value, script) @@ -127,7 +123,7 @@ coinbase.rehash() block = create_block(base_block_hash, coinbase, block_time) - # Make sure we have plenty engough to spend going forward. + # Make sure we have plenty enough to spend going forward. spendable_outputs = deque([spend]) def get_base_transaction(): @@ -135,11 +131,13 @@ tx = CTransaction() # Spend from one of the spendable outputs spend = spendable_outputs.popleft() + spend.tx.rehash() tx.vin.append(CTxIn(COutPoint(spend.tx.sha256, spend.n))) # Add spendable outputs for i in range(4): tx.vout.append(CTxOut(0, CScript([OP_TRUE]))) spendable_outputs.append(PreviousSpendableOutput(tx, i)) + pad_tx(tx) return tx tx = get_base_transaction() @@ -158,51 +156,56 @@ CTxOut(0, CScript([random.randint(0, 256), OP_RETURN]))) # Add the transaction to the block - self.add_transactions_to_block(block, [tx]) + block.vtx.append(tx) # Add transaction until we reach the expected transaction count - for _ in range(extra_txns): - self.add_transactions_to_block(block, [get_base_transaction()]) + block.vtx.extend([get_base_transaction() + for _ in range(extra_txns)]) # If we have a block size requirement, just fill # the block until we get there current_block_size = len(block.serialize()) + overage_bytes = 0 while current_block_size < block_size: + # Add padding to fill the block. + left_to_fill = block_size - current_block_size + # We will add a new transaction. That means the size of # the field enumerating how many transaction go in the block # may change. current_block_size -= len(ser_compact_size(len(block.vtx))) current_block_size += len(ser_compact_size(len(block.vtx) + 1)) + left_to_fill = block_size - current_block_size + + # Don't go over the 1 mb limit for a txn + if left_to_fill > 500000: + # Make sure we eat up non-divisible by 100 amounts quickly + # Also keep transaction less than 1 MB + left_to_fill = 500000 + left_to_fill % 100 # Create the new transaction tx = get_base_transaction() - - # Add padding to fill the block. - script_length = block_size - current_block_size - base_tx_size - if script_length > 510000: - if script_length < 1000000: - # Make sure we don't find ourselves in a position where we - # need to generate a transaction smaller than what we expected. - script_length = script_length // 2 - else: - script_length = 500000 - script_output = CScript([b'\x00' * script_length]) - tx.vout.append(CTxOut(0, script_output)) + pad_tx(tx, left_to_fill - overage_bytes) + if len(tx.serialize()) + current_block_size > block_size: + # Our padding was too big try again + overage_bytes += 1 + continue # Add the tx to the list of transactions to be included # in the block. - self.add_transactions_to_block(block, [tx]) + block.vtx.append(tx) current_block_size += len(tx.serialize()) # Now that we added a bunch of transaction, we need to recompute # the merkle root. make_conform_to_ctor(block) - block.hashMerkleRoot = block.calc_merkle_root() - # Check that the block size is what's expected - if block_size > 0: - assert_equal(len(block.serialize()), block_size) + # Check that the block size is what's expected + if block_size > 0: + assert len(block.serialize()) == block_size, "Block size wrong {} != {}".format( + len(block.serialize()), block_size) + block.hashMerkleRoot = block.calc_merkle_root() # Do PoW, which is cheap on regnet block.solve() self.tip = block @@ -238,23 +241,6 @@ def tip(number): self.tip = self.blocks[number] - # adds transactions to the block and updates state - def update_block(block_number, new_transactions): - block = self.blocks[block_number] - self.add_transactions_to_block(block, new_transactions) - old_sha256 = block.sha256 - make_conform_to_ctor(block) - block.hashMerkleRoot = block.calc_merkle_root() - block.solve() - # Update the internal state just like in next_block - self.tip = block - if block.sha256 != old_sha256: - self.block_heights[ - block.sha256] = self.block_heights[old_sha256] - del self.block_heights[old_sha256] - self.blocks[block_number] = block - return block - # shorthand for functions block = self.next_block