Skip to content

Commit e3206c9

Browse files
author
MarcoFalke
committed
Merge bitcoin/bitcoin#24605: test: Use MiniWallet in feature_coinstatsindex
fa48ea3 Use MiniWallet in feature_coinstatsindex (MarcoFalke) fab6143 test: Refactor MiniWallet get_utxo helper (MarcoFalke) Pull request description: Allows the test to be run even without a wallet compiled ACKs for top commit: josibake: ACK bitcoin/bitcoin@fa48ea3 ayush933: tACK fa48ea3 . The test runs successfully with the wallet disabled. willcl-ark: tACK bitcoin/bitcoin@fa48ea3 both with and without wallet compiled in. Tree-SHA512: e04e04ea0f236c062d6be68909ece2770130ce1d5343823893073d95aebc6eedb1ad1dc5bc41e5b0cb0bf2cd9018bb1d668f0e7f5f1101ed4e0b007ed6b00f69
2 parents e66630c + fa48ea3 commit e3206c9

File tree

2 files changed

+40
-39
lines changed

2 files changed

+40
-39
lines changed

test/functional/feature_coinstatsindex.py

Lines changed: 26 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,6 @@
1818
)
1919
from test_framework.messages import (
2020
COIN,
21-
COutPoint,
22-
CTransaction,
23-
CTxIn,
2421
CTxOut,
2522
)
2623
from test_framework.script import (
@@ -33,23 +30,24 @@
3330
assert_equal,
3431
assert_raises_rpc_error,
3532
)
33+
from test_framework.wallet import (
34+
MiniWallet,
35+
getnewdestination,
36+
)
37+
3638

3739
class CoinStatsIndexTest(BitcoinTestFramework):
3840
def set_test_params(self):
3941
self.setup_clean_chain = True
4042
self.num_nodes = 2
4143
self.supports_cli = False
4244
self.extra_args = [
43-
# Explicitly set the output type in order to have consistent tx vsize / fees
44-
# for both legacy and descriptor wallets (disables the change address type detection algorithm)
45-
["-addresstype=bech32", "-changetype=bech32"],
45+
[],
4646
["-coinstatsindex"]
4747
]
4848

49-
def skip_test_if_missing_module(self):
50-
self.skip_if_no_wallet()
51-
5249
def run_test(self):
50+
self.wallet = MiniWallet(self.nodes[0])
5351
self._test_coin_stats_index()
5452
self._test_use_index_option()
5553
self._test_reorg_index()
@@ -69,9 +67,8 @@ def _test_coin_stats_index(self):
6967
index_hash_options = ['none', 'muhash']
7068

7169
# Generate a normal transaction and mine it
72-
self.generate(node, COINBASE_MATURITY + 1)
73-
address = self.nodes[0].get_deterministic_priv_key().address
74-
node.sendtoaddress(address=address, amount=10, subtractfeefromamount=True)
70+
self.generate(self.wallet, COINBASE_MATURITY + 1)
71+
self.wallet.send_self_transfer(from_node=node)
7572
self.generate(node, 1)
7673

7774
self.log.info("Test that gettxoutsetinfo() output is consistent with or without coinstatsindex option")
@@ -136,36 +133,31 @@ def _test_coin_stats_index(self):
136133
assert_equal(res5['block_info'], {
137134
'unspendable': 0,
138135
'prevout_spent': 50,
139-
'new_outputs_ex_coinbase': Decimal('49.99995560'),
140-
'coinbase': Decimal('50.00004440'),
136+
'new_outputs_ex_coinbase': Decimal('49.99968800'),
137+
'coinbase': Decimal('50.00031200'),
141138
'unspendables': {
142139
'genesis_block': 0,
143140
'bip30': 0,
144141
'scripts': 0,
145-
'unclaimed_rewards': 0
142+
'unclaimed_rewards': 0,
146143
}
147144
})
148145
self.block_sanity_check(res5['block_info'])
149146

150147
# Generate and send a normal tx with two outputs
151-
tx1_inputs = []
152-
tx1_outputs = {self.nodes[0].getnewaddress(): 21, self.nodes[0].getnewaddress(): 42}
153-
raw_tx1 = self.nodes[0].createrawtransaction(tx1_inputs, tx1_outputs)
154-
funded_tx1 = self.nodes[0].fundrawtransaction(raw_tx1)
155-
signed_tx1 = self.nodes[0].signrawtransactionwithwallet(funded_tx1['hex'])
156-
tx1_txid = self.nodes[0].sendrawtransaction(signed_tx1['hex'])
148+
tx1_txid, tx1_vout = self.wallet.send_to(
149+
from_node=node,
150+
scriptPubKey=self.wallet.get_scriptPubKey(),
151+
amount=21 * COIN,
152+
)
157153

158154
# Find the right position of the 21 BTC output
159-
tx1_final = self.nodes[0].gettransaction(tx1_txid)
160-
for output in tx1_final['details']:
161-
if output['amount'] == Decimal('21.00000000') and output['category'] == 'receive':
162-
n = output['vout']
155+
tx1_out_21 = self.wallet.get_utxo(txid=tx1_txid, vout=tx1_vout)
163156

164157
# Generate and send another tx with an OP_RETURN output (which is unspendable)
165-
tx2 = CTransaction()
166-
tx2.vin.append(CTxIn(COutPoint(int(tx1_txid, 16), n), b''))
167-
tx2.vout.append(CTxOut(int(Decimal('20.99') * COIN), CScript([OP_RETURN] + [OP_FALSE]*30)))
168-
tx2_hex = self.nodes[0].signrawtransactionwithwallet(tx2.serialize().hex())['hex']
158+
tx2 = self.wallet.create_self_transfer(utxo_to_spend=tx1_out_21)['tx']
159+
tx2.vout = [CTxOut(int(Decimal('20.99') * COIN), CScript([OP_RETURN] + [OP_FALSE] * 30))]
160+
tx2_hex = tx2.serialize().hex()
169161
self.nodes[0].sendrawtransaction(tx2_hex)
170162

171163
# Include both txs in a block
@@ -177,14 +169,14 @@ def _test_coin_stats_index(self):
177169
assert_equal(res6['total_unspendable_amount'], Decimal('70.99000000'))
178170
assert_equal(res6['block_info'], {
179171
'unspendable': Decimal('20.99000000'),
180-
'prevout_spent': 111,
181-
'new_outputs_ex_coinbase': Decimal('89.99993620'),
182-
'coinbase': Decimal('50.01006380'),
172+
'prevout_spent': 71,
173+
'new_outputs_ex_coinbase': Decimal('49.99999000'),
174+
'coinbase': Decimal('50.01001000'),
183175
'unspendables': {
184176
'genesis_block': 0,
185177
'bip30': 0,
186178
'scripts': Decimal('20.99000000'),
187-
'unclaimed_rewards': 0
179+
'unclaimed_rewards': 0,
188180
}
189181
})
190182
self.block_sanity_check(res6['block_info'])
@@ -246,7 +238,7 @@ def _test_reorg_index(self):
246238

247239
# Generate two block, let the index catch up, then invalidate the blocks
248240
index_node = self.nodes[1]
249-
reorg_blocks = self.generatetoaddress(index_node, 2, index_node.getnewaddress())
241+
reorg_blocks = self.generatetoaddress(index_node, 2, getnewdestination()[2])
250242
reorg_block = reorg_blocks[1]
251243
res_invalid = index_node.gettxoutsetinfo('muhash')
252244
index_node.invalidateblock(reorg_blocks[0])

test/functional/test_framework/wallet.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88
from decimal import Decimal
99
from enum import Enum
1010
from random import choice
11-
from typing import Optional
11+
from typing import (
12+
Any,
13+
Optional,
14+
)
1215
from test_framework.address import (
1316
base58_to_byte,
1417
create_deterministic_address_bcrt1_p2tr_op_true,
@@ -131,24 +134,30 @@ def generate(self, num_blocks, **kwargs):
131134
self._utxos.append({'txid': cb_tx['txid'], 'vout': 0, 'value': cb_tx['vout'][0]['value'], 'height': block_info['height']})
132135
return blocks
133136

137+
def get_scriptPubKey(self):
138+
return self._scriptPubKey
139+
134140
def get_descriptor(self):
135141
return descsum_create(f'raw({self._scriptPubKey.hex()})')
136142

137143
def get_address(self):
138144
return self._address
139145

140-
def get_utxo(self, *, txid: Optional[str]='', mark_as_spent=True):
146+
def get_utxo(self, *, txid: str = '', vout: Optional[int] = None, mark_as_spent=True):
141147
"""
142148
Returns a utxo and marks it as spent (pops it from the internal list)
143149
144150
Args:
145151
txid: get the first utxo we find from a specific transaction
146152
"""
147-
index = -1 # by default the last utxo
148153
self._utxos = sorted(self._utxos, key=lambda k: (k['value'], -k['height'])) # Put the largest utxo last
149154
if txid:
150-
utxo = next(filter(lambda utxo: txid == utxo['txid'], self._utxos))
151-
index = self._utxos.index(utxo)
155+
utxo_filter: Any = filter(lambda utxo: txid == utxo['txid'], self._utxos)
156+
else:
157+
utxo_filter = reversed(self._utxos) # By default the largest utxo
158+
if vout is not None:
159+
utxo_filter = filter(lambda utxo: vout == utxo['vout'], utxo_filter)
160+
index = self._utxos.index(next(utxo_filter))
152161
if mark_as_spent:
153162
return self._utxos.pop(index)
154163
else:

0 commit comments

Comments
 (0)