Skip to content

Commit 494455f

Browse files
committed
test: use MiniWallet for feature_fee_estimation.py
This test can now be run even with the Bitcoin Core wallet disabled.
1 parent 747cdf1 commit 494455f

File tree

1 file changed

+35
-70
lines changed

1 file changed

+35
-70
lines changed

test/functional/feature_fee_estimation.py

Lines changed: 35 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,13 @@
33
# Distributed under the MIT software license, see the accompanying
44
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
55
"""Test fee estimation code."""
6+
from copy import deepcopy
67
from decimal import Decimal
78
import os
89
import random
910

1011
from test_framework.messages import (
1112
COIN,
12-
COutPoint,
13-
CTransaction,
14-
CTxIn,
15-
CTxOut,
16-
)
17-
from test_framework.script import (
18-
CScript,
19-
OP_1,
20-
OP_DROP,
21-
OP_TRUE,
22-
)
23-
from test_framework.script_util import (
24-
script_to_p2sh_script,
2513
)
2614
from test_framework.test_framework import BitcoinTestFramework
2715
from test_framework.util import (
@@ -31,22 +19,14 @@
3119
assert_raises_rpc_error,
3220
satoshi_round,
3321
)
34-
35-
# Construct 2 trivial P2SH's and the ScriptSigs that spend them
36-
# So we can create many transactions without needing to spend
37-
# time signing.
38-
SCRIPT = CScript([OP_1, OP_DROP])
39-
P2SH = script_to_p2sh_script(SCRIPT)
40-
REDEEM_SCRIPT = CScript([OP_TRUE, SCRIPT])
22+
from test_framework.wallet import MiniWallet
4123

4224

4325
def small_txpuzzle_randfee(
44-
from_node, conflist, unconflist, amount, min_fee, fee_increment
26+
wallet, from_node, conflist, unconflist, amount, min_fee, fee_increment
4527
):
46-
"""Create and send a transaction with a random fee.
28+
"""Create and send a transaction with a random fee using MiniWallet.
4729
48-
The transaction pays to a trivial P2SH script, and assumes that its inputs
49-
are of the same form.
5030
The function takes a list of confirmed outputs and unconfirmed outputs
5131
and attempts to use the confirmed list first for its inputs.
5232
It adds the newly created outputs to the unconfirmed list.
@@ -58,23 +38,29 @@ def small_txpuzzle_randfee(
5838
rand_fee = float(fee_increment) * (1.1892 ** random.randint(0, 28))
5939
# Total fee ranges from min_fee to min_fee + 127*fee_increment
6040
fee = min_fee - fee_increment + satoshi_round(rand_fee)
61-
tx = CTransaction()
41+
utxos_to_spend = []
6242
total_in = Decimal("0.00000000")
6343
while total_in <= (amount + fee) and len(conflist) > 0:
6444
t = conflist.pop(0)
65-
total_in += t["amount"]
66-
tx.vin.append(CTxIn(COutPoint(int(t["txid"], 16), t["vout"]), REDEEM_SCRIPT))
45+
total_in += t["value"]
46+
utxos_to_spend.append(t)
6747
while total_in <= (amount + fee) and len(unconflist) > 0:
6848
t = unconflist.pop(0)
69-
total_in += t["amount"]
70-
tx.vin.append(CTxIn(COutPoint(int(t["txid"], 16), t["vout"]), REDEEM_SCRIPT))
49+
total_in += t["value"]
50+
utxos_to_spend.append(t)
7151
if total_in <= amount + fee:
7252
raise RuntimeError(f"Insufficient funds: need {amount + fee}, have {total_in}")
73-
tx.vout.append(CTxOut(int((total_in - amount - fee) * COIN), P2SH))
74-
tx.vout.append(CTxOut(int(amount * COIN), P2SH))
53+
tx = wallet.create_self_transfer_multi(
54+
from_node=from_node,
55+
utxos_to_spend=utxos_to_spend,
56+
fee_per_output=0)
57+
tx.vout[0].nValue = int((total_in - amount - fee) * COIN)
58+
tx.vout.append(deepcopy(tx.vout[0]))
59+
tx.vout[1].nValue = int(amount * COIN)
60+
7561
txid = from_node.sendrawtransaction(hexstring=tx.serialize().hex(), maxfeerate=0)
76-
unconflist.append({"txid": txid, "vout": 0, "amount": total_in - amount - fee})
77-
unconflist.append({"txid": txid, "vout": 1, "amount": amount})
62+
unconflist.append({"txid": txid, "vout": 0, "value": total_in - amount - fee})
63+
unconflist.append({"txid": txid, "vout": 1, "value": amount})
7864

7965
return (tx.serialize().hex(), fee)
8066

@@ -129,17 +115,13 @@ def check_estimates(node, fees_seen):
129115
check_smart_estimates(node, fees_seen)
130116

131117

132-
def send_tx(node, utxo, feerate):
118+
def send_tx(wallet, node, utxo, feerate):
133119
"""Broadcast a 1in-1out transaction with a specific input and feerate (sat/vb)."""
134-
tx = CTransaction()
135-
tx.vin = [CTxIn(COutPoint(int(utxo["txid"], 16), utxo["vout"]), REDEEM_SCRIPT)]
136-
tx.vout = [CTxOut(int(utxo["amount"] * COIN), P2SH)]
137-
138-
# vbytes == bytes as we are using legacy transactions
139-
fee = tx.get_vsize() * feerate
140-
tx.vout[0].nValue -= fee
141-
142-
return node.sendrawtransaction(tx.serialize().hex())
120+
return wallet.send_self_transfer(
121+
from_node=node,
122+
utxo_to_spend=utxo,
123+
fee_rate=Decimal(feerate * 1000) / COIN,
124+
)['txid']
143125

144126

145127
class EstimateFeeTest(BitcoinTestFramework):
@@ -152,9 +134,6 @@ def set_test_params(self):
152134
["[email protected]", "-blockmaxweight=32000"],
153135
]
154136

155-
def skip_test_if_missing_module(self):
156-
self.skip_if_no_wallet()
157-
158137
def setup_network(self):
159138
"""
160139
We'll setup the network to have 3 nodes that all mine with different parameters.
@@ -168,9 +147,6 @@ def setup_network(self):
168147
# (68k weight is room enough for 120 or so transactions)
169148
# Node2 is a stingy miner, that
170149
# produces too small blocks (room for only 55 or so transactions)
171-
self.start_nodes()
172-
self.import_deterministic_coinbase_privkeys()
173-
self.stop_nodes()
174150

175151
def transact_and_mine(self, numblocks, mining_node):
176152
min_fee = Decimal("0.00001")
@@ -183,6 +159,7 @@ def transact_and_mine(self, numblocks, mining_node):
183159
for _ in range(random.randrange(100 - 50, 100 + 50)):
184160
from_index = random.randint(1, 2)
185161
(txhex, fee) = small_txpuzzle_randfee(
162+
self.wallet,
186163
self.nodes[from_index],
187164
self.confutxo,
188165
self.memutxo,
@@ -205,24 +182,10 @@ def transact_and_mine(self, numblocks, mining_node):
205182

206183
def initial_split(self, node):
207184
"""Split two coinbase UTxOs into many small coins"""
208-
utxo_count = 2048
209-
self.confutxo = []
210-
splitted_amount = Decimal("0.04")
211-
fee = Decimal("0.1")
212-
change = Decimal("100") - splitted_amount * utxo_count - fee
213-
tx = CTransaction()
214-
tx.vin = [
215-
CTxIn(COutPoint(int(cb["txid"], 16), cb["vout"]))
216-
for cb in node.listunspent()[:2]
217-
]
218-
tx.vout = [CTxOut(int(splitted_amount * COIN), P2SH) for _ in range(utxo_count)]
219-
tx.vout.append(CTxOut(int(change * COIN), P2SH))
220-
txhex = node.signrawtransactionwithwallet(tx.serialize().hex())["hex"]
221-
txid = node.sendrawtransaction(txhex)
222-
self.confutxo = [
223-
{"txid": txid, "vout": i, "amount": splitted_amount}
224-
for i in range(utxo_count)
225-
]
185+
self.confutxo = self.wallet.send_self_transfer_multi(
186+
from_node=node,
187+
utxos_to_spend=[self.wallet.get_utxo() for _ in range(2)],
188+
num_outputs=2048)['new_utxos']
226189
while len(node.getrawmempool()) > 0:
227190
self.generate(node, 1, sync_fun=self.no_op)
228191

@@ -284,12 +247,12 @@ def sanity_check_rbf_estimates(self, utxos):
284247
# Broadcast 45 low fee transactions that will need to be RBF'd
285248
for _ in range(45):
286249
u = utxos.pop(0)
287-
txid = send_tx(node, u, low_feerate)
250+
txid = send_tx(self.wallet, node, u, low_feerate)
288251
utxos_to_respend.append(u)
289252
txids_to_replace.append(txid)
290253
# Broadcast 5 low fee transaction which don't need to
291254
for _ in range(5):
292-
send_tx(node, utxos.pop(0), low_feerate)
255+
send_tx(self.wallet, node, utxos.pop(0), low_feerate)
293256
# Mine the transactions on another node
294257
self.sync_mempools(wait=0.1, nodes=[node, miner])
295258
for txid in txids_to_replace:
@@ -298,7 +261,7 @@ def sanity_check_rbf_estimates(self, utxos):
298261
# RBF the low-fee transactions
299262
while len(utxos_to_respend) > 0:
300263
u = utxos_to_respend.pop(0)
301-
send_tx(node, u, high_feerate)
264+
send_tx(self.wallet, node, u, high_feerate)
302265

303266
# Mine the last replacement txs
304267
self.sync_mempools(wait=0.1, nodes=[node, miner])
@@ -316,6 +279,8 @@ def run_test(self):
316279

317280
# Split two coinbases into many small utxos
318281
self.start_node(0)
282+
self.wallet = MiniWallet(self.nodes[0])
283+
self.wallet.rescan_utxos()
319284
self.initial_split(self.nodes[0])
320285
self.log.info("Finished splitting")
321286

0 commit comments

Comments
 (0)