Skip to content

Commit d24318a

Browse files
author
MacroFake
committed
Merge bitcoin/bitcoin#24941: test: MiniWallet: support skipping mempool checks (feature_fee_estimation.py performance fix)
a498acc test: MiniWallet: skip mempool check if `mempool_valid=False` (Sebastian Falbesoner) 01552e8 test: MiniWallet: always rehash after signing (P2PK mode) (Sebastian Falbesoner) Pull request description: MiniWallet's core method for creating txs (`create_self_transfer`) right now always executes the `testmempoolaccept` RPC to check for mempool validity or invalidity. In some test cases where we use MiniWallet to create a huge number of transactions this can lead to performance issues, in particular feature_fee_estimation.py where the execution time after MiniWallet usage (PR #24817) doubled, see bitcoin/bitcoin#24828 (comment), bitcoin/bitcoin#24828 (comment). This PR mitigates this by skipping the mempool check if the parameter `mempool_valid` is set to `False`. As a preparatory commit, the test feature_csv_activation.py has to be adapted w.r.t. to rehashing of transactions, as we now hash all transactions immediately in `create_self_transfer` in order to get the txid (before we relied on the result of `testmempoolaccept`). On my machine, this decreases the execution time quite noticably: master branch: ``` $ time ./test/functional/feature_fee_estimation.py real 3m20.771s user 2m52.360s sys 0m39.340s ``` PR branch: ``` $ time ./test/functional/feature_fee_estimation.py real 2m1.386s user 1m42.510s sys 0m22.980s ``` Partly fixes #24828 (hopefully). ACKs for top commit: danielabrozzoni: tACK a498acc Tree-SHA512: f20c358ba42b2ded86175f46ff3ff9eaefb84175cbd1c2624f44904c8d8888e67ce64d6dcbb26aabbf07906e6f5bdea40353eba9ae668618cadcfc517ef7201b
2 parents 2c56404 + a498acc commit d24318a

File tree

2 files changed

+9
-10
lines changed

2 files changed

+9
-10
lines changed

test/functional/feature_csv_activation.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,13 +112,15 @@ def create_bip112special(self, input, txversion):
112112
tx.nVersion = txversion
113113
self.miniwallet.sign_tx(tx)
114114
tx.vin[0].scriptSig = CScript([-1, OP_CHECKSEQUENCEVERIFY, OP_DROP] + list(CScript(tx.vin[0].scriptSig)))
115+
tx.rehash()
115116
return tx
116117

117118
def create_bip112emptystack(self, input, txversion):
118119
tx = self.create_self_transfer_from_utxo(input)
119120
tx.nVersion = txversion
120121
self.miniwallet.sign_tx(tx)
121122
tx.vin[0].scriptSig = CScript([OP_CHECKSEQUENCEVERIFY] + list(CScript(tx.vin[0].scriptSig)))
123+
tx.rehash()
122124
return tx
123125

124126
def send_generic_input_tx(self, coinbases):
@@ -136,7 +138,6 @@ def create_bip68txs(self, bip68inputs, txversion, locktime_delta=0):
136138
tx.nVersion = txversion
137139
tx.vin[0].nSequence = locktime + locktime_delta
138140
self.miniwallet.sign_tx(tx)
139-
tx.rehash()
140141
txs.append({'tx': tx, 'sdf': sdf, 'stf': stf})
141142

142143
return txs
@@ -339,20 +340,16 @@ def run_test(self):
339340
# BIP 113 tests should now fail regardless of version number if nLockTime isn't satisfied by new rules
340341
bip113tx_v1.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
341342
self.miniwallet.sign_tx(bip113tx_v1)
342-
bip113tx_v1.rehash()
343343
bip113tx_v2.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
344344
self.miniwallet.sign_tx(bip113tx_v2)
345-
bip113tx_v2.rehash()
346345
for bip113tx in [bip113tx_v1, bip113tx_v2]:
347346
self.send_blocks([self.create_test_block([bip113tx])], success=False, reject_reason='bad-txns-nonfinal')
348347

349348
# BIP 113 tests should now pass if the locktime is < MTP
350349
bip113tx_v1.nLockTime = self.last_block_time - 600 * 5 - 1 # < MTP of prior block
351350
self.miniwallet.sign_tx(bip113tx_v1)
352-
bip113tx_v1.rehash()
353351
bip113tx_v2.nLockTime = self.last_block_time - 600 * 5 - 1 # < MTP of prior block
354352
self.miniwallet.sign_tx(bip113tx_v2)
355-
bip113tx_v2.rehash()
356353
for bip113tx in [bip113tx_v1, bip113tx_v2]:
357354
self.send_blocks([self.create_test_block([bip113tx])])
358355
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
@@ -477,7 +474,6 @@ def run_test(self):
477474
for tx in [tx['tx'] for tx in bip112txs_vary_OP_CSV_v2 if not tx['sdf'] and tx['stf']]:
478475
tx.vin[0].nSequence = BASE_RELATIVE_LOCKTIME | SEQ_TYPE_FLAG
479476
self.miniwallet.sign_tx(tx)
480-
tx.rehash()
481477
time_txs.append(tx)
482478

483479
self.send_blocks([self.create_test_block(time_txs)])

test/functional/test_framework/wallet.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ def sign_tx(self, tx, fixed_length=True):
127127
if not fixed_length:
128128
break
129129
tx.vin[0].scriptSig = CScript([der_sig + bytes(bytearray([SIGHASH_ALL]))])
130+
tx.rehash()
130131

131132
def generate(self, num_blocks, **kwargs):
132133
"""Generate blocks with coinbase outputs to the internal address, and append the outputs to the internal list"""
@@ -233,7 +234,8 @@ def create_self_transfer_multi(self, *, from_node, utxos_to_spend=None, num_outp
233234
return tx
234235

235236
def create_self_transfer(self, *, fee_rate=Decimal("0.003"), from_node=None, utxo_to_spend=None, mempool_valid=True, locktime=0, sequence=0):
236-
"""Create and return a tx with the specified fee_rate. Fee may be exact or at most one satoshi higher than needed."""
237+
"""Create and return a tx with the specified fee_rate. Fee may be exact or at most one satoshi higher than needed.
238+
Checking mempool validity via the testmempoolaccept RPC can be skipped by setting mempool_valid to False."""
237239
from_node = from_node or self._test_node
238240
utxo_to_spend = utxo_to_spend or self.get_utxo()
239241
if self._priv_key is None:
@@ -260,12 +262,13 @@ def create_self_transfer(self, *, fee_rate=Decimal("0.003"), from_node=None, utx
260262
tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([OP_TRUE]), bytes([LEAF_VERSION_TAPSCRIPT]) + self._internal_key]
261263
tx_hex = tx.serialize().hex()
262264

263-
tx_info = from_node.testmempoolaccept([tx_hex])[0]
264-
assert_equal(mempool_valid, tx_info['allowed'])
265265
if mempool_valid:
266+
tx_info = from_node.testmempoolaccept([tx_hex])[0]
267+
assert_equal(tx_info['allowed'], True)
266268
assert_equal(tx_info['vsize'], vsize)
267269
assert_equal(tx_info['fees']['base'], utxo_to_spend['value'] - Decimal(send_value) / COIN)
268-
return {'txid': tx_info['txid'], 'wtxid': tx_info['wtxid'], 'hex': tx_hex, 'tx': tx}
270+
271+
return {'txid': tx.rehash(), 'wtxid': tx.getwtxid(), 'hex': tx_hex, 'tx': tx}
269272

270273
def sendrawtransaction(self, *, from_node, tx_hex, **kwargs):
271274
txid = from_node.sendrawtransaction(hexstring=tx_hex, **kwargs)

0 commit comments

Comments
 (0)