Skip to content

Commit 160799d

Browse files
committed
test: refactor: introduce create_ephemeral_dust_package helper
1 parent 61e18de commit 160799d

File tree

1 file changed

+30
-63
lines changed

1 file changed

+30
-63
lines changed

test/functional/mempool_ephemeral_dust.py

+30-63
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,22 @@ def add_output_to_create_multi_result(self, result, output_value=0):
4747

4848
result["new_utxos"].append({"txid": new_txid, "vout": len(result["tx"].vout) - 1, "value": Decimal(output_value) / COIN, "height": 0, "coinbase": False, "confirmations": 0})
4949

50+
def create_ephemeral_dust_package(self, *, tx_version, dust_tx_fee=0, dust_value=0, num_dust_outputs=1, extra_sponsors=None):
51+
"""Creates a 1P1C package containing ephemeral dust. By default, the parent transaction
52+
is zero-fee and creates a single zero-value dust output, and all of its outputs are
53+
spent by the child."""
54+
dusty_tx = self.wallet.create_self_transfer_multi(fee_per_output=dust_tx_fee, version=tx_version)
55+
for _ in range(num_dust_outputs):
56+
self.add_output_to_create_multi_result(dusty_tx, dust_value)
57+
58+
extra_sponsors = extra_sponsors or []
59+
sweep_tx = self.wallet.create_self_transfer_multi(
60+
utxos_to_spend=dusty_tx["new_utxos"] + extra_sponsors,
61+
version=tx_version,
62+
)
63+
64+
return dusty_tx, sweep_tx
65+
5066
def run_test(self):
5167

5268
node = self.nodes[0]
@@ -67,11 +83,7 @@ def test_normal_dust(self):
6783
self.log.info("Create 0-value dusty output, show that it works inside truc when spent in package")
6884

6985
assert_equal(self.nodes[0].getrawmempool(), [])
70-
71-
dusty_tx = self.wallet.create_self_transfer_multi(fee_per_output=0, version=3)
72-
self.add_output_to_create_multi_result(dusty_tx)
73-
74-
sweep_tx = self.wallet.create_self_transfer_multi(utxos_to_spend=dusty_tx["new_utxos"], version=3)
86+
dusty_tx, sweep_tx = self.create_ephemeral_dust_package(tx_version=3)
7587

7688
# Test doesn't work because lack of package feerates
7789
test_res = self.nodes[0].testmempoolaccept([dusty_tx["hex"], sweep_tx["hex"]])
@@ -107,11 +119,7 @@ def test_node_restart(self):
107119
self.log.info("Test that an ephemeral package is rejected on restart due to individual evaluation")
108120

109121
assert_equal(self.nodes[0].getrawmempool(), [])
110-
111-
dusty_tx = self.wallet.create_self_transfer_multi(fee_per_output=0, version=3)
112-
self.add_output_to_create_multi_result(dusty_tx)
113-
114-
sweep_tx = self.wallet.create_self_transfer_multi(utxos_to_spend=dusty_tx["new_utxos"], version=3)
122+
dusty_tx, sweep_tx = self.create_ephemeral_dust_package(tx_version=3)
115123

116124
res = self.nodes[0].submitpackage([dusty_tx["hex"], sweep_tx["hex"]])
117125
assert_equal(res["package_msg"], "success")
@@ -132,14 +140,11 @@ def test_fee_having_parent(self):
132140
assert_equal(self.nodes[0].getrawmempool(), [])
133141

134142
sats_fee = 1
135-
dusty_tx = self.wallet.create_self_transfer_multi(fee_per_output=sats_fee, version=3)
136-
self.add_output_to_create_multi_result(dusty_tx)
143+
dusty_tx, sweep_tx = self.create_ephemeral_dust_package(tx_version=3, dust_tx_fee=sats_fee)
137144
assert_equal(int(COIN * dusty_tx["fee"]), sats_fee) # has fees
138145
assert_greater_than(dusty_tx["tx"].vout[0].nValue, 330) # main output is not dust
139146
assert_equal(dusty_tx["tx"].vout[1].nValue, 0) # added one is dust
140147

141-
sweep_tx = self.wallet.create_self_transfer_multi(utxos_to_spend=dusty_tx["new_utxos"], version=3)
142-
143148
# When base fee is non-0, we report dust like usual
144149
res = self.nodes[0].submitpackage([dusty_tx["hex"], sweep_tx["hex"]])
145150
assert_equal(res["package_msg"], "transaction failed")
@@ -153,10 +158,7 @@ def test_fee_having_parent(self):
153158
assert_equal(res["tx-results"][dusty_tx["wtxid"]]["error"], "dust, tx with dust output must be 0-fee")
154159

155160
# Will not be accepted if base fee is 0 with modified fee of non-0
156-
dusty_tx = self.wallet.create_self_transfer_multi(fee_per_output=0, version=3)
157-
self.add_output_to_create_multi_result(dusty_tx)
158-
159-
sweep_tx = self.wallet.create_self_transfer_multi(utxos_to_spend=dusty_tx["new_utxos"], version=3)
161+
dusty_tx, sweep_tx = self.create_ephemeral_dust_package(tx_version=3)
160162

161163
self.nodes[0].prioritisetransaction(txid=dusty_tx["txid"], dummy=0, fee_delta=1000)
162164
self.nodes[1].prioritisetransaction(txid=dusty_tx["txid"], dummy=0, fee_delta=1000)
@@ -177,12 +179,7 @@ def test_multidust(self):
177179
self.log.info("Test that a transaction with multiple ephemeral dusts is not allowed")
178180

179181
assert_mempool_contents(self, self.nodes[0], expected=[])
180-
181-
dusty_tx = self.wallet.create_self_transfer_multi(fee_per_output=0, version=3)
182-
self.add_output_to_create_multi_result(dusty_tx)
183-
self.add_output_to_create_multi_result(dusty_tx)
184-
185-
sweep_tx = self.wallet.create_self_transfer_multi(utxos_to_spend=dusty_tx["new_utxos"], version=3)
182+
dusty_tx, sweep_tx = self.create_ephemeral_dust_package(tx_version=3, num_dust_outputs=2)
186183

187184
res = self.nodes[0].submitpackage([dusty_tx["hex"], sweep_tx["hex"]])
188185
assert_equal(res["package_msg"], "transaction failed")
@@ -200,10 +197,7 @@ def test_nonzero_dust(self):
200197
# 330 is dust threshold for taproot outputs
201198
for value in [1, 329, 330]:
202199
assert_equal(self.nodes[0].getrawmempool(), [])
203-
204-
dusty_tx = self.wallet.create_self_transfer_multi(fee_per_output=0, version=3)
205-
self.add_output_to_create_multi_result(dusty_tx, value)
206-
200+
dusty_tx, _ = self.create_ephemeral_dust_package(tx_version=3, dust_value=value)
207201
test_res = self.nodes[0].testmempoolaccept([dusty_tx["hex"]])
208202
assert test_res[0]["allowed"]
209203

@@ -217,11 +211,7 @@ def test_non_truc(self):
217211
self.log.info("Test that v2 dust-having transaction is rejected even if spent, because of min relay requirement")
218212

219213
assert_equal(self.nodes[0].getrawmempool(), [])
220-
221-
dusty_tx = self.wallet.create_self_transfer_multi(fee_per_output=0, version=2)
222-
self.add_output_to_create_multi_result(dusty_tx)
223-
224-
sweep_tx = self.wallet.create_self_transfer_multi(utxos_to_spend=dusty_tx["new_utxos"], version=2)
214+
dusty_tx, sweep_tx = self.create_ephemeral_dust_package(tx_version=2)
225215

226216
res = self.nodes[0].submitpackage([dusty_tx["hex"], sweep_tx["hex"]])
227217
assert_equal(res["package_msg"], "transaction failed")
@@ -233,12 +223,9 @@ def test_unspent_ephemeral(self):
233223
self.log.info("Test that spending from a tx with ephemeral outputs is only allowed if dust is spent as well")
234224

235225
assert_equal(self.nodes[0].getrawmempool(), [])
236-
237-
dusty_tx = self.wallet.create_self_transfer_multi(fee_per_output=0, version=3)
238-
self.add_output_to_create_multi_result(dusty_tx, 329)
226+
dusty_tx, sweep_tx = self.create_ephemeral_dust_package(tx_version=3, dust_value=329)
239227

240228
# Valid sweep we will RBF incorrectly by not spending dust as well
241-
sweep_tx = self.wallet.create_self_transfer_multi(utxos_to_spend=dusty_tx["new_utxos"], version=3)
242229
self.nodes[0].submitpackage([dusty_tx["hex"], sweep_tx["hex"]])
243230
assert_mempool_contents(self, self.nodes[0], expected=[dusty_tx["tx"], sweep_tx["tx"]])
244231

@@ -260,8 +247,7 @@ def test_unspent_ephemeral(self):
260247
self.generate(self.nodes[0], 1)
261248
assert_equal(self.nodes[0].getrawmempool(), [])
262249

263-
dusty_tx = self.wallet.create_self_transfer_multi(fee_per_output=0, version=3)
264-
self.add_output_to_create_multi_result(dusty_tx, 329)
250+
dusty_tx, _ = self.create_ephemeral_dust_package(tx_version=3, dust_value=329)
265251

266252
# Spend non-dust only
267253
unspent_sweep_tx = self.wallet.create_self_transfer_multi(utxos_to_spend=[dusty_tx["new_utxos"][0]], version=3)
@@ -286,18 +272,9 @@ def test_sponsor_cycle(self):
286272
self.log.info("Test that dust txn is not evicted when it becomes childless, but won't be mined")
287273

288274
assert_equal(self.nodes[0].getrawmempool(), [])
289-
290-
dusty_tx = self.wallet.create_self_transfer_multi(
291-
fee_per_output=0,
292-
version=3
293-
)
294-
295-
self.add_output_to_create_multi_result(dusty_tx)
296-
297275
sponsor_coin = self.wallet.get_utxo()
298-
299276
# Bring "fee" input that can be double-spend separately
300-
sweep_tx = self.wallet.create_self_transfer_multi(utxos_to_spend=dusty_tx["new_utxos"] + [sponsor_coin], version=3)
277+
dusty_tx, sweep_tx = self.create_ephemeral_dust_package(tx_version=3, extra_sponsors=[sponsor_coin])
301278

302279
res = self.nodes[0].submitpackage([dusty_tx["hex"], sweep_tx["hex"]])
303280
assert_equal(res["package_msg"], "success")
@@ -345,8 +322,7 @@ def test_reorgs(self):
345322

346323
# Get dusty tx mined, then check that it makes it back into mempool on reorg
347324
# due to bypass_limits allowing 0-fee individually
348-
dusty_tx = self.wallet.create_self_transfer_multi(fee_per_output=0, version=3)
349-
self.add_output_to_create_multi_result(dusty_tx)
325+
dusty_tx, _ = self.create_ephemeral_dust_package(tx_version=3)
350326
assert_raises_rpc_error(-26, "min relay fee not met", self.nodes[0].sendrawtransaction, dusty_tx["hex"])
351327

352328
block_res = self.nodes[0].rpc.generateblock(self.wallet.get_address(), [dusty_tx["hex"]])
@@ -380,18 +356,13 @@ def test_reorgs(self):
380356
assert_equal(self.nodes[0].getrawmempool(), [])
381357

382358
self.log.info("Test that ephemeral dust tx with fees or multi dust don't enter mempool via reorg")
383-
multi_dusty_tx = self.wallet.create_self_transfer_multi(fee_per_output=0, version=3)
384-
self.add_output_to_create_multi_result(multi_dusty_tx)
385-
self.add_output_to_create_multi_result(multi_dusty_tx)
386-
359+
multi_dusty_tx, _ = self.create_ephemeral_dust_package(tx_version=3, num_dust_outputs=2)
387360
block_res = self.nodes[0].rpc.generateblock(self.wallet.get_address(), [multi_dusty_tx["hex"]])
388361
self.nodes[0].invalidateblock(block_res["hash"])
389362
assert_equal(self.nodes[0].getrawmempool(), [])
390363

391364
# With fee and one dust
392-
dusty_fee_tx = self.wallet.create_self_transfer_multi(fee_per_output=1, version=3)
393-
self.add_output_to_create_multi_result(dusty_fee_tx)
394-
365+
dusty_fee_tx, _ = self.create_ephemeral_dust_package(tx_version=3, dust_tx_fee=1)
395366
block_res = self.nodes[0].rpc.generateblock(self.wallet.get_address(), [dusty_fee_tx["hex"]])
396367
self.nodes[0].invalidateblock(block_res["hash"])
397368
assert_equal(self.nodes[0].getrawmempool(), [])
@@ -410,11 +381,7 @@ def test_no_minrelay_fee(self):
410381
self.connect_nodes(0, 1)
411382

412383
assert_equal(self.nodes[0].getrawmempool(), [])
413-
414-
dusty_tx = self.wallet.create_self_transfer_multi(fee_per_output=0, version=2)
415-
self.add_output_to_create_multi_result(dusty_tx)
416-
417-
sweep_tx = self.wallet.create_self_transfer_multi(utxos_to_spend=dusty_tx["new_utxos"], version=2)
384+
dusty_tx, sweep_tx = self.create_ephemeral_dust_package(tx_version=2)
418385

419386
self.nodes[0].submitpackage([dusty_tx["hex"], sweep_tx["hex"]])
420387

0 commit comments

Comments
 (0)