mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-05 14:06:27 -05:00
Merge bitcoin/bitcoin#27035: test: simplify and speedup mempool_updatefromblock.py by using MiniWallet
dee8549be3
test: simplify and speedup mempool_updatefromblock.py by using MiniWallet (Sebastian Falbesoner) Pull request description: This PR simplifies the functional test mempool_updatefromblock.py by using MiniWallet in order to avoid manual low-level tx creation (signing, outputs selection, fee calculation). Most of the tedious work is done by the method `MiniWallet.send_self_transfer_multi` (calling `create_self_transfer_multi` internally) which supports spending a given set of UTXOs and creating a certain number of outputs. As a nice side-effect, the test's performance increases significantly (~3.5x on my system): ``` master 1m56.80s real 1m50.10s user 0m06.36s system PR 0m32.34s real 0m30.26s user 0m01.41s system ``` The arguments `start_input_txid` and `end_address` have been removed from the `transaction_graph_test` method, as they are currently unused and I don't see them being needed for future tests. ACKs for top commit: brunoerg: crACKdee8549be3
MarcoFalke: lgtm ACKdee8549be3
🚏 Tree-SHA512: 9f6da634bdc8c272f9a2af1cddaa364ee371d4e95554463a066249eecebb668d8c6cb123ec8a5404c41b3291010c0c8806a8a01dd227733cec03e73aa93b0103
This commit is contained in:
commit
a65d2259f1
1 changed files with 15 additions and 42 deletions
|
@ -7,14 +7,12 @@
|
||||||
Test mempool update of transaction descendants/ancestors information (count, size)
|
Test mempool update of transaction descendants/ancestors information (count, size)
|
||||||
when transactions have been re-added from a disconnected block to the mempool.
|
when transactions have been re-added from a disconnected block to the mempool.
|
||||||
"""
|
"""
|
||||||
|
from math import ceil
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from decimal import Decimal
|
|
||||||
from test_framework.test_framework import BitcoinTestFramework
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
from test_framework.util import assert_equal
|
from test_framework.util import assert_equal
|
||||||
from test_framework.address import key_to_p2pkh
|
from test_framework.wallet import MiniWallet
|
||||||
from test_framework.wallet_util import bytes_to_wif
|
|
||||||
from test_framework.key import ECKey
|
|
||||||
|
|
||||||
|
|
||||||
class MempoolUpdateFromBlockTest(BitcoinTestFramework):
|
class MempoolUpdateFromBlockTest(BitcoinTestFramework):
|
||||||
|
@ -22,15 +20,7 @@ class MempoolUpdateFromBlockTest(BitcoinTestFramework):
|
||||||
self.num_nodes = 1
|
self.num_nodes = 1
|
||||||
self.extra_args = [['-limitdescendantsize=1000', '-limitancestorsize=1000', '-limitancestorcount=100']]
|
self.extra_args = [['-limitdescendantsize=1000', '-limitancestorsize=1000', '-limitancestorcount=100']]
|
||||||
|
|
||||||
def get_new_address(self):
|
def transaction_graph_test(self, size, n_tx_to_mine=None, fee=100_000):
|
||||||
key = ECKey()
|
|
||||||
key.generate()
|
|
||||||
pubkey = key.get_pubkey().get_bytes()
|
|
||||||
address = key_to_p2pkh(pubkey)
|
|
||||||
self.priv_keys.append(bytes_to_wif(key.get_bytes()))
|
|
||||||
return address
|
|
||||||
|
|
||||||
def transaction_graph_test(self, size, n_tx_to_mine=None, start_input_txid='', end_address='', fee=Decimal(0.00100000)):
|
|
||||||
"""Create an acyclic tournament (a type of directed graph) of transactions and use it for testing.
|
"""Create an acyclic tournament (a type of directed graph) of transactions and use it for testing.
|
||||||
|
|
||||||
Keyword arguments:
|
Keyword arguments:
|
||||||
|
@ -45,14 +35,7 @@ class MempoolUpdateFromBlockTest(BitcoinTestFramework):
|
||||||
|
|
||||||
More details: https://en.wikipedia.org/wiki/Tournament_(graph_theory)
|
More details: https://en.wikipedia.org/wiki/Tournament_(graph_theory)
|
||||||
"""
|
"""
|
||||||
|
wallet = MiniWallet(self.nodes[0])
|
||||||
self.priv_keys = [self.nodes[0].get_deterministic_priv_key().key]
|
|
||||||
if not start_input_txid:
|
|
||||||
start_input_txid = self.nodes[0].getblock(self.nodes[0].getblockhash(1))['tx'][0]
|
|
||||||
|
|
||||||
if not end_address:
|
|
||||||
end_address = self.get_new_address()
|
|
||||||
|
|
||||||
first_block_hash = ''
|
first_block_hash = ''
|
||||||
tx_id = []
|
tx_id = []
|
||||||
tx_size = []
|
tx_size = []
|
||||||
|
@ -61,41 +44,31 @@ class MempoolUpdateFromBlockTest(BitcoinTestFramework):
|
||||||
self.log.debug('Preparing transaction #{}...'.format(i))
|
self.log.debug('Preparing transaction #{}...'.format(i))
|
||||||
# Prepare inputs.
|
# Prepare inputs.
|
||||||
if i == 0:
|
if i == 0:
|
||||||
inputs = [{'txid': start_input_txid, 'vout': 0}]
|
inputs = [wallet.get_utxo()] # let MiniWallet provide a start UTXO
|
||||||
inputs_value = self.nodes[0].gettxout(start_input_txid, 0)['value']
|
|
||||||
else:
|
else:
|
||||||
inputs = []
|
inputs = []
|
||||||
inputs_value = 0
|
|
||||||
for j, tx in enumerate(tx_id[0:i]):
|
for j, tx in enumerate(tx_id[0:i]):
|
||||||
# Transaction tx[K] is a child of each of previous transactions tx[0]..tx[K-1] at their output K-1.
|
# Transaction tx[K] is a child of each of previous transactions tx[0]..tx[K-1] at their output K-1.
|
||||||
vout = i - j - 1
|
vout = i - j - 1
|
||||||
inputs.append({'txid': tx_id[j], 'vout': vout})
|
inputs.append(wallet.get_utxo(txid=tx_id[j], vout=vout))
|
||||||
inputs_value += self.nodes[0].gettxout(tx, vout)['value']
|
|
||||||
|
|
||||||
self.log.debug('inputs={}'.format(inputs))
|
|
||||||
self.log.debug('inputs_value={}'.format(inputs_value))
|
|
||||||
|
|
||||||
# Prepare outputs.
|
# Prepare outputs.
|
||||||
tx_count = i + 1
|
tx_count = i + 1
|
||||||
if tx_count < size:
|
if tx_count < size:
|
||||||
# Transaction tx[K] is an ancestor of each of subsequent transactions tx[K+1]..tx[N-1].
|
# Transaction tx[K] is an ancestor of each of subsequent transactions tx[K+1]..tx[N-1].
|
||||||
n_outputs = size - tx_count
|
n_outputs = size - tx_count
|
||||||
output_value = ((inputs_value - fee) / Decimal(n_outputs)).quantize(Decimal('0.00000001'))
|
|
||||||
outputs = {}
|
|
||||||
for _ in range(n_outputs):
|
|
||||||
outputs[self.get_new_address()] = output_value
|
|
||||||
else:
|
else:
|
||||||
output_value = (inputs_value - fee).quantize(Decimal('0.00000001'))
|
n_outputs = 1
|
||||||
outputs = {end_address: output_value}
|
|
||||||
|
|
||||||
self.log.debug('output_value={}'.format(output_value))
|
|
||||||
self.log.debug('outputs={}'.format(outputs))
|
|
||||||
|
|
||||||
# Create a new transaction.
|
# Create a new transaction.
|
||||||
unsigned_raw_tx = self.nodes[0].createrawtransaction(inputs, outputs)
|
new_tx = wallet.send_self_transfer_multi(
|
||||||
signed_raw_tx = self.nodes[0].signrawtransactionwithkey(unsigned_raw_tx, self.priv_keys)
|
from_node=self.nodes[0],
|
||||||
tx_id.append(self.nodes[0].sendrawtransaction(signed_raw_tx['hex']))
|
utxos_to_spend=inputs,
|
||||||
tx_size.append(self.nodes[0].getmempoolentry(tx_id[-1])['vsize'])
|
num_outputs=n_outputs,
|
||||||
|
fee_per_output=ceil(fee / n_outputs)
|
||||||
|
)
|
||||||
|
tx_id.append(new_tx['txid'])
|
||||||
|
tx_size.append(new_tx['tx'].get_vsize())
|
||||||
|
|
||||||
if tx_count in n_tx_to_mine:
|
if tx_count in n_tx_to_mine:
|
||||||
# The created transactions are mined into blocks by batches.
|
# The created transactions are mined into blocks by batches.
|
||||||
|
|
Loading…
Add table
Reference in a new issue