I feel there is scope for generalising this function further. Similar to how the previous class implementation used only the CTransaction class and the like. IMO, the earlier class implementation was fine as well but if the consensus is to prefer the function implementation then we should not lose the genericness.
Currently, this function is tied to the MiniWallet that I don’t think is necessary. A more generic form of this function should be able to be used by the usual RPC wallets as well.
Consider the following diff that puts the responsibility of building the base parent transaction and submitting the final parent transaction to the caller, thereby allowing this function to not use any wallet or node at all.
0diff --git a/test/functional/mempool_accept_wtxid.py b/test/functional/mempool_accept_wtxid.py
1index a49a886d3a..f895772b08 100755
2--- a/test/functional/mempool_accept_wtxid.py
3+++ b/test/functional/mempool_accept_wtxid.py
4@@ -11,7 +11,7 @@ from test_framework.messages import (
5 COIN,
6 )
7 from test_framework.p2p import P2PTxInvStore
8-from test_framework.script_util import valid_witness_malleate_tx
9+from test_framework.script_util import build_malleated_tx_package
10 from test_framework.test_framework import BitcoinTestFramework
11 from test_framework.util import (
12 assert_not_equal,
13@@ -36,7 +36,9 @@ class MempoolWtxidTest(BitcoinTestFramework):
14 self.log.info("Submit parent with multiple script branches to mempool")
15 parent_amount = int(9.99998 * COIN)
16 child_amount = int(9.99996 * COIN)
17- _, child_one, child_two = valid_witness_malleate_tx(mini_wallet, node, parent_amount, child_amount)
18+ parent = mini_wallet.create_self_transfer(fee_rate=0)["tx"]
19+ parent, child_one, child_two = build_malleated_tx_package(parent, parent_amount, child_amount)
20+ mini_wallet.sendrawtransaction(from_node=node, tx_hex=parent.serialize().hex())
21
22 self.generate(node, 1)
23
24diff --git a/test/functional/test_framework/script_util.py b/test/functional/test_framework/script_util.py
25index f3b3c803ed..862e30c088 100755
26--- a/test/functional/test_framework/script_util.py
27+++ b/test/functional/test_framework/script_util.py
28@@ -6,6 +6,10 @@
29 import unittest
30
31 from copy import deepcopy
32+from test_framework.util import (
33+ assert_greater_than_or_equal,
34+ assert_equal,
35+)
36
37 from test_framework.messages import (
38 COutPoint,
39@@ -150,19 +154,22 @@ def check_script(script):
40 assert False
41
42
43-def valid_witness_malleate_tx(mini_wallet, node, parent_amount, child_amount):
44+def build_malleated_tx_package(parent: CTransaction, parent_amount, child_amount, fee=1000):
45 """
46- Creates a valid witness malleation transaction:
47+ Creates a malleated transaction package with valid witness:
48 - Parent transaction with a script supporting 2 branches
49- - 2 child transactions with the same txid but different wtxids
50+ - 2 child transactions with the same txid but different wtxids because of different witnesses
51 """
52 hashlock = hash160(b'Preimage')
53 witness_script = CScript([OP_IF, OP_HASH160, hashlock, OP_EQUAL, OP_ELSE, OP_TRUE, OP_ENDIF])
54 witness_program = sha256(witness_script)
55 script_pubkey = CScript([OP_0, witness_program])
56
57- # Create parent transaction with a script supporting 2 branches
58- parent = mini_wallet.send_to(from_node=node, scriptPubKey=script_pubkey, amount=parent_amount, fee=1000)
59+ # Append to the transaction the vout containing the script supporting 2 spending conditions
60+ assert_equal(len(parent.vout), 1)
61+ assert_greater_than_or_equal(parent.vout[0].nValue, parent_amount + fee)
62+ parent.vout[0].nValue -= (parent_amount + fee)
63+ parent.vout.append(CTxOut(parent_amount, script_pubkey))
64
65 # Create 2 valid children that differ only in witness data.
66 # 1. Create a new transaction with witness solving first branch
67@@ -171,13 +178,15 @@ def valid_witness_malleate_tx(mini_wallet, node, parent_amount, child_amount):
68 child_script_pubkey = CScript([OP_0, child_witness_program])
69 child_one = CTransaction()
70
71- child_one.vin.append(CTxIn(COutPoint(int(parent['txid'], 16), parent['sent_vout']), b""))
72+ child_one.vin.append(CTxIn(COutPoint(int(parent.txid_hex, 16), len(parent.vout) - 1), b""))
73 child_one.vout.append(CTxOut(child_amount, child_script_pubkey))
74 child_one.wit.vtxinwit.append(CTxInWitness())
75 child_one.wit.vtxinwit[0].scriptWitness.stack = [b'Preimage', b'\x01', witness_script]
76+
77 # 2. Create another identical transaction with witness solving second branch
78 child_two = deepcopy(child_one)
79 child_two.wit.vtxinwit[0].scriptWitness.stack = [b'', witness_script]
80+
81 return parent, child_one, child_two