Skip to content

Commit fc642c3

Browse files
committed
Merge bitcoin#30718: test: switch MiniWallet padding unit from weight to vsize
940edd6 test: refactor: introduce and use `TRUC_CHILD_MAX_VSIZE` constant (Sebastian Falbesoner) c16ae71 test: switch MiniWallet padding unit from weight to vsize (Sebastian Falbesoner) Pull request description: This PR is a late follow-up for bitcoin#30162, where I retrospectively consider the padding unit of choice as a mistake. The weight unit is merely a consensus rule detail and is largely irrelevant from a user's perspective w.r.t. fee-rate calculations and mempool policy rules (e.g. for package relay and TRUC limits), so there doesn't seem to be any value of using a granularity that we can't even guarantee to reach exactly anyway. Switch to the more natural unit of vsize instead, which simplifies both the padding implementation (no "round up to the next multiple of 4" anymore) and the current tests that take use of this padding. The rather annoying multiplications by `WITNESS_SCALE_FACTOR` can then be removed and weird-looking magic numbers like `4004` can be replaced by numbers that are more connected to actual policy limit constants from the codebase, e.g. `1001` for exceeding `TRUC_CHILD_MAX_VSIZE` by one. The second commits introduces a constant for that. ACKs for top commit: glozow: reACK 940edd6 via range-diff instagibbs: reACK 940edd6 maflcko: re-ACK 940edd6 🍷 achow101: ACK 940edd6 Tree-SHA512: 35325f22bbe548664273051b705059b8f2f4316215be116c71b8c21dc87d190b3e8fcc4a48f04deaba2f3632a9c809d272b0bae654cf74d7492759554c0f0d14
2 parents d7f956a + 940edd6 commit fc642c3

6 files changed

+69
-78
lines changed

test/functional/feature_blocksxor.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def run_test(self):
3131
node = self.nodes[0]
3232
wallet = MiniWallet(node)
3333
for _ in range(5):
34-
wallet.send_self_transfer(from_node=node, target_weight=80000)
34+
wallet.send_self_transfer(from_node=node, target_vsize=20000)
3535
self.generate(wallet, 1)
3636

3737
block_files = list(node.blocks_path.glob('blk[0-9][0-9][0-9][0-9][0-9].dat'))

test/functional/feature_framework_miniwallet.py

+7-9
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from test_framework.blocktools import COINBASE_MATURITY
1010
from test_framework.test_framework import BitcoinTestFramework
1111
from test_framework.util import (
12-
assert_greater_than_or_equal,
12+
assert_equal,
1313
)
1414
from test_framework.wallet import (
1515
MiniWallet,
@@ -22,17 +22,15 @@ def set_test_params(self):
2222
self.num_nodes = 1
2323

2424
def test_tx_padding(self):
25-
"""Verify that MiniWallet's transaction padding (`target_weight` parameter)
26-
works accurately enough (i.e. at most 3 WUs higher) with all modes."""
25+
"""Verify that MiniWallet's transaction padding (`target_vsize` parameter)
26+
works accurately with all modes."""
2727
for mode_name, wallet in self.wallets:
2828
self.log.info(f"Test tx padding with MiniWallet mode {mode_name}...")
2929
utxo = wallet.get_utxo(mark_as_spent=False)
30-
for target_weight in [1000, 2000, 5000, 10000, 20000, 50000, 100000, 200000, 4000000,
31-
989, 2001, 4337, 13371, 23219, 49153, 102035, 223419, 3999989]:
32-
tx = wallet.create_self_transfer(utxo_to_spend=utxo, target_weight=target_weight)["tx"]
33-
self.log.debug(f"-> target weight: {target_weight}, actual weight: {tx.get_weight()}")
34-
assert_greater_than_or_equal(tx.get_weight(), target_weight)
35-
assert_greater_than_or_equal(target_weight + 3, tx.get_weight())
30+
for target_vsize in [250, 500, 1250, 2500, 5000, 12500, 25000, 50000, 1000000,
31+
248, 501, 1085, 3343, 5805, 12289, 25509, 55855, 999998]:
32+
tx = wallet.create_self_transfer(utxo_to_spend=utxo, target_vsize=target_vsize)["tx"]
33+
assert_equal(tx.get_vsize(), target_vsize)
3634

3735
def test_wallet_tagging(self):
3836
"""Verify that tagged wallet instances are able to send funds."""

test/functional/mempool_limit.py

+17-14
Original file line numberDiff line numberDiff line change
@@ -55,28 +55,28 @@ def test_rbf_carveout_disallowed(self):
5555
self.generate(node, 1)
5656

5757
# tx_A needs to be RBF'd, set minfee at set size
58-
A_weight = 1000
58+
A_vsize = 250
5959
mempoolmin_feerate = node.getmempoolinfo()["mempoolminfee"]
6060
tx_A = self.wallet.send_self_transfer(
6161
from_node=node,
6262
fee_rate=mempoolmin_feerate,
63-
target_weight=A_weight,
63+
target_vsize=A_vsize,
6464
utxo_to_spend=rbf_utxo,
6565
confirmed_only=True
6666
)
6767

6868
# RBF's tx_A, is not yet submitted
6969
tx_B = self.wallet.create_self_transfer(
7070
fee=tx_A["fee"] * 4,
71-
target_weight=A_weight,
71+
target_vsize=A_vsize,
7272
utxo_to_spend=rbf_utxo,
7373
confirmed_only=True
7474
)
7575

7676
# Spends tx_B's output, too big for cpfp carveout (because that would also increase the descendant limit by 1)
77-
non_cpfp_carveout_weight = 40001 # EXTRA_DESCENDANT_TX_SIZE_LIMIT + 1
77+
non_cpfp_carveout_vsize = 10001 # EXTRA_DESCENDANT_TX_SIZE_LIMIT + 1
7878
tx_C = self.wallet.create_self_transfer(
79-
target_weight=non_cpfp_carveout_weight,
79+
target_vsize=non_cpfp_carveout_vsize,
8080
fee_rate=mempoolmin_feerate,
8181
utxo_to_spend=tx_B["new_utxo"],
8282
confirmed_only=True
@@ -103,14 +103,14 @@ def test_mid_package_eviction(self):
103103
# UTXOs to be spent by the ultimate child transaction
104104
parent_utxos = []
105105

106-
evicted_weight = 8000
106+
evicted_vsize = 2000
107107
# Mempool transaction which is evicted due to being at the "bottom" of the mempool when the
108108
# mempool overflows and evicts by descendant score. It's important that the eviction doesn't
109109
# happen in the middle of package evaluation, as it can invalidate the coins cache.
110110
mempool_evicted_tx = self.wallet.send_self_transfer(
111111
from_node=node,
112112
fee_rate=mempoolmin_feerate,
113-
target_weight=evicted_weight,
113+
target_vsize=evicted_vsize,
114114
confirmed_only=True
115115
)
116116
# Already in mempool when package is submitted.
@@ -132,14 +132,16 @@ def test_mid_package_eviction(self):
132132

133133
# Series of parents that don't need CPFP and are submitted individually. Each one is large and
134134
# high feerate, which means they should trigger eviction but not be evicted.
135-
parent_weight = 100000
135+
parent_vsize = 25000
136136
num_big_parents = 3
137-
assert_greater_than(parent_weight * num_big_parents, current_info["maxmempool"] - current_info["bytes"])
137+
# Need to be large enough to trigger eviction
138+
# (note that the mempool usage of a tx is about three times its vsize)
139+
assert_greater_than(parent_vsize * num_big_parents * 3, current_info["maxmempool"] - current_info["bytes"])
138140
parent_feerate = 100 * mempoolmin_feerate
139141

140142
big_parent_txids = []
141143
for i in range(num_big_parents):
142-
parent = self.wallet.create_self_transfer(fee_rate=parent_feerate, target_weight=parent_weight, confirmed_only=True)
144+
parent = self.wallet.create_self_transfer(fee_rate=parent_feerate, target_vsize=parent_vsize, confirmed_only=True)
143145
parent_utxos.append(parent["new_utxo"])
144146
package_hex.append(parent["hex"])
145147
big_parent_txids.append(parent["txid"])
@@ -311,17 +313,18 @@ def run_test(self):
311313
entry = node.getmempoolentry(txid)
312314
worst_feerate_btcvb = min(worst_feerate_btcvb, entry["fees"]["descendant"] / entry["descendantsize"])
313315
# Needs to be large enough to trigger eviction
314-
target_weight_each = 200000
315-
assert_greater_than(target_weight_each * 2, node.getmempoolinfo()["maxmempool"] - node.getmempoolinfo()["bytes"])
316+
# (note that the mempool usage of a tx is about three times its vsize)
317+
target_vsize_each = 50000
318+
assert_greater_than(target_vsize_each * 2 * 3, node.getmempoolinfo()["maxmempool"] - node.getmempoolinfo()["bytes"])
316319
# Should be a true CPFP: parent's feerate is just below mempool min feerate
317320
parent_feerate = mempoolmin_feerate - Decimal("0.000001") # 0.1 sats/vbyte below min feerate
318321
# Parent + child is above mempool minimum feerate
319322
child_feerate = (worst_feerate_btcvb * 1000) - Decimal("0.000001") # 0.1 sats/vbyte below worst feerate
320323
# However, when eviction is triggered, these transactions should be at the bottom.
321324
# This assertion assumes parent and child are the same size.
322325
miniwallet.rescan_utxos()
323-
tx_parent_just_below = miniwallet.create_self_transfer(fee_rate=parent_feerate, target_weight=target_weight_each)
324-
tx_child_just_above = miniwallet.create_self_transfer(utxo_to_spend=tx_parent_just_below["new_utxo"], fee_rate=child_feerate, target_weight=target_weight_each)
326+
tx_parent_just_below = miniwallet.create_self_transfer(fee_rate=parent_feerate, target_vsize=target_vsize_each)
327+
tx_child_just_above = miniwallet.create_self_transfer(utxo_to_spend=tx_parent_just_below["new_utxo"], fee_rate=child_feerate, target_vsize=target_vsize_each)
325328
# This package ranks below the lowest descendant package in the mempool
326329
package_fee = tx_parent_just_below["fee"] + tx_child_just_above["fee"]
327330
package_vsize = tx_parent_just_below["tx"].get_vsize() + tx_child_just_above["tx"].get_vsize()

test/functional/mempool_package_limits.py

+6-11
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@
44
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
55
"""Test logic for limiting mempool and package ancestors/descendants."""
66
from test_framework.blocktools import COINBASE_MATURITY
7-
from test_framework.messages import (
8-
WITNESS_SCALE_FACTOR,
9-
)
107
from test_framework.test_framework import BitcoinTestFramework
118
from test_framework.util import (
129
assert_equal,
@@ -290,19 +287,18 @@ def test_anc_size_limits(self):
290287
parent_utxos = []
291288
target_vsize = 30_000
292289
high_fee = 10 * target_vsize # 10 sats/vB
293-
target_weight = target_vsize * WITNESS_SCALE_FACTOR
294290
self.log.info("Check that in-mempool and in-package ancestor size limits are calculated properly in packages")
295291
# Mempool transactions A and B
296292
for _ in range(2):
297-
bulked_tx = self.wallet.create_self_transfer(target_weight=target_weight)
293+
bulked_tx = self.wallet.create_self_transfer(target_vsize=target_vsize)
298294
self.wallet.sendrawtransaction(from_node=node, tx_hex=bulked_tx["hex"])
299295
parent_utxos.append(bulked_tx["new_utxo"])
300296

301297
# Package transaction C
302-
pc_tx = self.wallet.create_self_transfer_multi(utxos_to_spend=parent_utxos, fee_per_output=high_fee, target_weight=target_weight)
298+
pc_tx = self.wallet.create_self_transfer_multi(utxos_to_spend=parent_utxos, fee_per_output=high_fee, target_vsize=target_vsize)
303299

304300
# Package transaction D
305-
pd_tx = self.wallet.create_self_transfer(utxo_to_spend=pc_tx["new_utxos"][0], target_weight=target_weight)
301+
pd_tx = self.wallet.create_self_transfer(utxo_to_spend=pc_tx["new_utxos"][0], target_vsize=target_vsize)
306302

307303
assert_equal(2, node.getmempoolinfo()["size"])
308304
return [pc_tx["hex"], pd_tx["hex"]]
@@ -321,20 +317,19 @@ def test_desc_size_limits(self):
321317
node = self.nodes[0]
322318
target_vsize = 21_000
323319
high_fee = 10 * target_vsize # 10 sats/vB
324-
target_weight = target_vsize * WITNESS_SCALE_FACTOR
325320
self.log.info("Check that in-mempool and in-package descendant sizes are calculated properly in packages")
326321
# Top parent in mempool, Ma
327-
ma_tx = self.wallet.create_self_transfer_multi(num_outputs=2, fee_per_output=high_fee // 2, target_weight=target_weight)
322+
ma_tx = self.wallet.create_self_transfer_multi(num_outputs=2, fee_per_output=high_fee // 2, target_vsize=target_vsize)
328323
self.wallet.sendrawtransaction(from_node=node, tx_hex=ma_tx["hex"])
329324

330325
package_hex = []
331326
for j in range(2): # Two legs (left and right)
332327
# Mempool transaction (Mb and Mc)
333-
mempool_tx = self.wallet.create_self_transfer(utxo_to_spend=ma_tx["new_utxos"][j], target_weight=target_weight)
328+
mempool_tx = self.wallet.create_self_transfer(utxo_to_spend=ma_tx["new_utxos"][j], target_vsize=target_vsize)
334329
self.wallet.sendrawtransaction(from_node=node, tx_hex=mempool_tx["hex"])
335330

336331
# Package transaction (Pd and Pe)
337-
package_tx = self.wallet.create_self_transfer(utxo_to_spend=mempool_tx["new_utxo"], target_weight=target_weight)
332+
package_tx = self.wallet.create_self_transfer(utxo_to_spend=mempool_tx["new_utxo"], target_vsize=target_vsize)
338333
package_hex.append(package_tx["hex"])
339334

340335
assert_equal(3, node.getmempoolinfo()["size"])

0 commit comments

Comments
 (0)