Skip to content

Commit 599e941

Browse files
author
MarcoFalke
committed
Merge bitcoin/bitcoin#26657: test: Run feature_bip68_sequence.py with MiniWallet
4159ccd test: Run feature_bip68_sequence.py with MiniWallet (Miles Liu) fc0caaf test: Add "include mempool" flag to MiniWallet rescan_utxos (Miles Liu) d0a909a test: Add "include immature coinbase" flag to MiniWallet get_utxos (Miles Liu) e5b9127 test: Add signs P2TR and RAWSCRIPT to MiniWallet sign_tx (Miles Liu) Pull request description: This PR enables one more of the non-wallet functional tests (feature_bip68_sequence.py) to be run even when no wallet is compiled in by using the MiniWallet instead, as proposed in #20078. ACKs for top commit: achow101: ACK 4159ccd MarcoFalke: review ACK 4159ccd 🤸 Tree-SHA512: e891b189381e961c840b45fc30d058363707fd54c1c4bdc3d29623b03309981f1d3ebfac27e6aecf621bdbcd7e31754a3ef7c53f86346f7dd241c137e64c92bd
2 parents 6b7ccb9 + 4159ccd commit 599e941

File tree

2 files changed

+93
-92
lines changed

2 files changed

+93
-92
lines changed

test/functional/feature_bip68_sequence.py

+44-60
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
assert_raises_rpc_error,
3333
softfork_active,
3434
)
35+
from test_framework.wallet import MiniWallet
3536

3637
SCRIPT_W0_SH_OP_TRUE = script_to_p2wsh_script(CScript([OP_TRUE]))
3738

@@ -58,14 +59,12 @@ def set_test_params(self):
5859
],
5960
]
6061

61-
def skip_test_if_missing_module(self):
62-
self.skip_if_no_wallet()
63-
6462
def run_test(self):
6563
self.relayfee = self.nodes[0].getnetworkinfo()["relayfee"]
64+
self.wallet = MiniWallet(self.nodes[0])
6665

6766
# Generate some coins
68-
self.generate(self.nodes[0], 110)
67+
self.generate(self.wallet, 110)
6968

7069
self.log.info("Running test disable flag")
7170
self.test_disable_flag()
@@ -92,16 +91,10 @@ def run_test(self):
9291
# the first sequence bit is set.
9392
def test_disable_flag(self):
9493
# Create some unconfirmed inputs
95-
new_addr = self.nodes[0].getnewaddress()
96-
self.nodes[0].sendtoaddress(new_addr, 2) # send 2 BTC
97-
98-
utxos = self.nodes[0].listunspent(0, 0)
99-
assert len(utxos) > 0
100-
101-
utxo = utxos[0]
94+
utxo = self.wallet.send_self_transfer(from_node=self.nodes[0])["new_utxo"]
10295

10396
tx1 = CTransaction()
104-
value = int((utxo["amount"] - self.relayfee) * COIN)
97+
value = int((utxo["value"] - self.relayfee) * COIN)
10598

10699
# Check that the disable flag disables relative locktime.
107100
# If sequence locks were used, this would require 1 block for the
@@ -110,8 +103,8 @@ def test_disable_flag(self):
110103
tx1.vin = [CTxIn(COutPoint(int(utxo["txid"], 16), utxo["vout"]), nSequence=sequence_value)]
111104
tx1.vout = [CTxOut(value, SCRIPT_W0_SH_OP_TRUE)]
112105

113-
tx1_signed = self.nodes[0].signrawtransactionwithwallet(tx1.serialize().hex())["hex"]
114-
tx1_id = self.nodes[0].sendrawtransaction(tx1_signed)
106+
self.wallet.sign_tx(tx=tx1)
107+
tx1_id = self.wallet.sendrawtransaction(from_node=self.nodes[0], tx_hex=tx1.serialize().hex())
115108
tx1_id = int(tx1_id, 16)
116109

117110
# This transaction will enable sequence-locks, so this transaction should
@@ -125,13 +118,13 @@ def test_disable_flag(self):
125118
tx2.vout = [CTxOut(int(value - self.relayfee * COIN), SCRIPT_W0_SH_OP_TRUE)]
126119
tx2.rehash()
127120

128-
assert_raises_rpc_error(-26, NOT_FINAL_ERROR, self.nodes[0].sendrawtransaction, tx2.serialize().hex())
121+
assert_raises_rpc_error(-26, NOT_FINAL_ERROR, self.wallet.sendrawtransaction, from_node=self.nodes[0], tx_hex=tx2.serialize().hex())
129122

130123
# Setting the version back down to 1 should disable the sequence lock,
131124
# so this should be accepted.
132125
tx2.nVersion = 1
133126

134-
self.nodes[0].sendrawtransaction(tx2.serialize().hex())
127+
self.wallet.sendrawtransaction(from_node=self.nodes[0], tx_hex=tx2.serialize().hex())
135128

136129
# Calculate the median time past of a prior block ("confirmations" before
137130
# the current tip).
@@ -144,20 +137,13 @@ def test_sequence_lock_confirmed_inputs(self):
144137
# Create lots of confirmed utxos, and use them to generate lots of random
145138
# transactions.
146139
max_outputs = 50
147-
addresses = []
148-
while len(addresses) < max_outputs:
149-
addresses.append(self.nodes[0].getnewaddress())
150-
while len(self.nodes[0].listunspent()) < 200:
140+
while len(self.wallet.get_utxos(include_immature_coinbase=False, mark_as_spent=False)) < 200:
151141
import random
152-
random.shuffle(addresses)
153142
num_outputs = random.randint(1, max_outputs)
154-
outputs = {}
155-
for i in range(num_outputs):
156-
outputs[addresses[i]] = random.randint(1, 20)*0.01
157-
self.nodes[0].sendmany("", outputs)
158-
self.generate(self.nodes[0], 1)
143+
self.wallet.send_self_transfer_multi(from_node=self.nodes[0], num_outputs=num_outputs)
144+
self.generate(self.wallet, 1)
159145

160-
utxos = self.nodes[0].listunspent()
146+
utxos = self.wallet.get_utxos(include_immature_coinbase=False)
161147

162148
# Try creating a lot of random transactions.
163149
# Each time, choose a random number of inputs, and randomly set
@@ -214,19 +200,20 @@ def test_sequence_lock_confirmed_inputs(self):
214200
sequence_value = ((cur_time - orig_time) >> SEQUENCE_LOCKTIME_GRANULARITY)+1
215201
sequence_value |= SEQUENCE_LOCKTIME_TYPE_FLAG
216202
tx.vin.append(CTxIn(COutPoint(int(utxos[j]["txid"], 16), utxos[j]["vout"]), nSequence=sequence_value))
217-
value += utxos[j]["amount"]*COIN
203+
value += utxos[j]["value"]*COIN
218204
# Overestimate the size of the tx - signatures should be less than 120 bytes, and leave 50 for the output
219205
tx_size = len(tx.serialize().hex())//2 + 120*num_inputs + 50
220206
tx.vout.append(CTxOut(int(value - self.relayfee * tx_size * COIN / 1000), SCRIPT_W0_SH_OP_TRUE))
221-
rawtx = self.nodes[0].signrawtransactionwithwallet(tx.serialize().hex())["hex"]
207+
self.wallet.sign_tx(tx=tx)
222208

223209
if (using_sequence_locks and not should_pass):
224210
# This transaction should be rejected
225-
assert_raises_rpc_error(-26, NOT_FINAL_ERROR, self.nodes[0].sendrawtransaction, rawtx)
211+
assert_raises_rpc_error(-26, NOT_FINAL_ERROR, self.wallet.sendrawtransaction, from_node=self.nodes[0], tx_hex=tx.serialize().hex())
226212
else:
227213
# This raw transaction should be accepted
228-
self.nodes[0].sendrawtransaction(rawtx)
229-
utxos = self.nodes[0].listunspent()
214+
self.wallet.sendrawtransaction(from_node=self.nodes[0], tx_hex=tx.serialize().hex())
215+
self.wallet.rescan_utxos()
216+
utxos = self.wallet.get_utxos(include_immature_coinbase=False)
230217

231218
# Test that sequence locks on unconfirmed inputs must have nSequence
232219
# height or time of 0 to be accepted.
@@ -237,8 +224,8 @@ def test_sequence_lock_unconfirmed_inputs(self):
237224
cur_height = self.nodes[0].getblockcount()
238225

239226
# Create a mempool tx.
240-
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 2)
241-
tx1 = tx_from_hex(self.nodes[0].getrawtransaction(txid))
227+
self.wallet.rescan_utxos()
228+
tx1 = self.wallet.send_self_transfer(from_node=self.nodes[0])["tx"]
242229
tx1.rehash()
243230

244231
# Anyone-can-spend mempool tx.
@@ -247,11 +234,11 @@ def test_sequence_lock_unconfirmed_inputs(self):
247234
tx2.nVersion = 2
248235
tx2.vin = [CTxIn(COutPoint(tx1.sha256, 0), nSequence=0)]
249236
tx2.vout = [CTxOut(int(tx1.vout[0].nValue - self.relayfee * COIN), SCRIPT_W0_SH_OP_TRUE)]
250-
tx2_raw = self.nodes[0].signrawtransactionwithwallet(tx2.serialize().hex())["hex"]
251-
tx2 = tx_from_hex(tx2_raw)
237+
self.wallet.sign_tx(tx=tx2)
238+
tx2_raw = tx2.serialize().hex()
252239
tx2.rehash()
253240

254-
self.nodes[0].sendrawtransaction(tx2_raw)
241+
self.wallet.sendrawtransaction(from_node=self.nodes[0], tx_hex=tx2_raw)
255242

256243
# Create a spend of the 0th output of orig_tx with a sequence lock
257244
# of 1, and test what happens when submitting.
@@ -271,10 +258,10 @@ def test_nonzero_locks(orig_tx, node, relayfee, use_height_lock):
271258

272259
if (orig_tx.hash in node.getrawmempool()):
273260
# sendrawtransaction should fail if the tx is in the mempool
274-
assert_raises_rpc_error(-26, NOT_FINAL_ERROR, node.sendrawtransaction, tx.serialize().hex())
261+
assert_raises_rpc_error(-26, NOT_FINAL_ERROR, self.wallet.sendrawtransaction, from_node=node, tx_hex=tx.serialize().hex())
275262
else:
276263
# sendrawtransaction should succeed if the tx is not in the mempool
277-
node.sendrawtransaction(tx.serialize().hex())
264+
self.wallet.sendrawtransaction(from_node=node, tx_hex=tx.serialize().hex())
278265

279266
return tx
280267

@@ -287,7 +274,7 @@ def test_nonzero_locks(orig_tx, node, relayfee, use_height_lock):
287274
cur_time = int(time.time())
288275
for _ in range(10):
289276
self.nodes[0].setmocktime(cur_time + 600)
290-
self.generate(self.nodes[0], 1, sync_fun=self.no_op)
277+
self.generate(self.wallet, 1, sync_fun=self.no_op)
291278
cur_time += 600
292279

293280
assert tx2.hash in self.nodes[0].getrawmempool()
@@ -321,12 +308,12 @@ def test_nonzero_locks(orig_tx, node, relayfee, use_height_lock):
321308
tx5 = test_nonzero_locks(tx4, self.nodes[0], self.relayfee, use_height_lock=True)
322309
assert tx5.hash not in self.nodes[0].getrawmempool()
323310

324-
utxos = self.nodes[0].listunspent()
325-
tx5.vin.append(CTxIn(COutPoint(int(utxos[0]["txid"], 16), utxos[0]["vout"]), nSequence=1))
326-
tx5.vout[0].nValue += int(utxos[0]["amount"]*COIN)
327-
raw_tx5 = self.nodes[0].signrawtransactionwithwallet(tx5.serialize().hex())["hex"]
311+
utxo = self.wallet.get_utxo()
312+
tx5.vin.append(CTxIn(COutPoint(int(utxo["txid"], 16), utxo["vout"]), nSequence=1))
313+
tx5.vout[0].nValue += int(utxo["value"]*COIN)
314+
self.wallet.sign_tx(tx=tx5)
328315

329-
assert_raises_rpc_error(-26, NOT_FINAL_ERROR, self.nodes[0].sendrawtransaction, raw_tx5)
316+
assert_raises_rpc_error(-26, NOT_FINAL_ERROR, self.wallet.sendrawtransaction, from_node=self.nodes[0], tx_hex=tx5.serialize().hex())
330317

331318
# Test mempool-BIP68 consistency after reorg
332319
#
@@ -362,17 +349,16 @@ def test_nonzero_locks(orig_tx, node, relayfee, use_height_lock):
362349
# Reset the chain and get rid of the mocktimed-blocks
363350
self.nodes[0].setmocktime(0)
364351
self.nodes[0].invalidateblock(self.nodes[0].getblockhash(cur_height+1))
365-
self.generate(self.nodes[0], 10, sync_fun=self.no_op)
352+
self.generate(self.wallet, 10, sync_fun=self.no_op)
366353

367354
# Make sure that BIP68 isn't being used to validate blocks prior to
368355
# activation height. If more blocks are mined prior to this test
369356
# being run, then it's possible the test has activated the soft fork, and
370357
# this test should be moved to run earlier, or deleted.
371358
def test_bip68_not_consensus(self):
372359
assert not softfork_active(self.nodes[0], 'csv')
373-
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 2)
374360

375-
tx1 = tx_from_hex(self.nodes[0].getrawtransaction(txid))
361+
tx1 = self.wallet.send_self_transfer(from_node=self.nodes[0])["tx"]
376362
tx1.rehash()
377363

378364
# Make an anyone-can-spend transaction
@@ -382,11 +368,12 @@ def test_bip68_not_consensus(self):
382368
tx2.vout = [CTxOut(int(tx1.vout[0].nValue - self.relayfee * COIN), SCRIPT_W0_SH_OP_TRUE)]
383369

384370
# sign tx2
385-
tx2_raw = self.nodes[0].signrawtransactionwithwallet(tx2.serialize().hex())["hex"]
371+
self.wallet.sign_tx(tx=tx2)
372+
tx2_raw = tx2.serialize().hex()
386373
tx2 = tx_from_hex(tx2_raw)
387374
tx2.rehash()
388375

389-
self.nodes[0].sendrawtransaction(tx2.serialize().hex())
376+
self.wallet.sendrawtransaction(from_node=self.nodes[0], tx_hex=tx2_raw)
390377

391378
# Now make an invalid spend of tx2 according to BIP68
392379
sequence_value = 100 # 100 block relative locktime
@@ -399,7 +386,7 @@ def test_bip68_not_consensus(self):
399386
tx3.vout = [CTxOut(int(tx2.vout[0].nValue - self.relayfee * COIN), SCRIPT_W0_SH_OP_TRUE)]
400387
tx3.rehash()
401388

402-
assert_raises_rpc_error(-26, NOT_FINAL_ERROR, self.nodes[0].sendrawtransaction, tx3.serialize().hex())
389+
assert_raises_rpc_error(-26, NOT_FINAL_ERROR, self.wallet.sendrawtransaction, from_node=self.nodes[0], tx_hex=tx3.serialize().hex())
403390

404391
# make a block that violates bip68; ensure that the tip updates
405392
block = create_block(tmpl=self.nodes[0].getblocktemplate(NORMAL_GBT_REQUEST_PARAMS), txlist=[tx1, tx2, tx3])
@@ -415,22 +402,19 @@ def activateCSV(self):
415402
min_activation_height = 432
416403
height = self.nodes[0].getblockcount()
417404
assert_greater_than(min_activation_height - height, 2)
418-
self.generate(self.nodes[0], min_activation_height - height - 2, sync_fun=self.no_op)
405+
self.generate(self.wallet, min_activation_height - height - 2, sync_fun=self.no_op)
419406
assert not softfork_active(self.nodes[0], 'csv')
420-
self.generate(self.nodes[0], 1, sync_fun=self.no_op)
407+
self.generate(self.wallet, 1, sync_fun=self.no_op)
421408
assert softfork_active(self.nodes[0], 'csv')
422409
self.sync_blocks()
423410

424411
# Use self.nodes[1] to test that version 2 transactions are standard.
425412
def test_version2_relay(self):
426-
inputs = [ ]
427-
outputs = { self.nodes[1].getnewaddress() : 1.0 }
428-
rawtx = self.nodes[1].createrawtransaction(inputs, outputs)
429-
rawtxfund = self.nodes[1].fundrawtransaction(rawtx)['hex']
430-
tx = tx_from_hex(rawtxfund)
413+
mini_wallet = MiniWallet(self.nodes[1])
414+
mini_wallet.rescan_utxos()
415+
tx = mini_wallet.create_self_transfer()["tx"]
431416
tx.nVersion = 2
432-
tx_signed = self.nodes[1].signrawtransactionwithwallet(tx.serialize().hex())["hex"]
433-
self.nodes[1].sendrawtransaction(tx_signed)
417+
mini_wallet.sendrawtransaction(from_node=self.nodes[1], tx_hex=tx.serialize().hex())
434418

435419
if __name__ == '__main__':
436420
BIP68Test().main()

0 commit comments

Comments
 (0)