@@ -47,7 +47,40 @@ def setup_network(self):
47
47
self .connect_nodes (0 , 2 )
48
48
self .connect_nodes (0 , 3 )
49
49
50
+ def lock_outputs_type (self , wallet , outputtype ):
51
+ """
52
+ Only allow UTXOs of the given type
53
+ """
54
+ if outputtype in ["legacy" , "p2pkh" , "pkh" ]:
55
+ prefixes = ["pkh(" , "sh(multi(" ]
56
+ elif outputtype in ["p2sh-segwit" , "sh_wpkh" ]:
57
+ prefixes = ["sh(wpkh(" , "sh(wsh(" ]
58
+ elif outputtype in ["bech32" , "wpkh" ]:
59
+ prefixes = ["wpkh(" , "wsh(" ]
60
+ else :
61
+ assert False , f"Unknown output type { outputtype } "
62
+
63
+ to_lock = []
64
+ for utxo in wallet .listunspent ():
65
+ if "desc" in utxo :
66
+ for prefix in prefixes :
67
+ if utxo ["desc" ].startswith (prefix ):
68
+ to_lock .append ({"txid" : utxo ["txid" ], "vout" : utxo ["vout" ]})
69
+ wallet .lockunspent (False , to_lock )
70
+
71
+ def unlock_utxos (self , wallet ):
72
+ """
73
+ Unlock all UTXOs except the watchonly one
74
+ """
75
+ to_keep = []
76
+ if self .watchonly_txid is not None and self .watchonly_vout is not None :
77
+ to_keep .append ({"txid" : self .watchonly_txid , "vout" : self .watchonly_vout })
78
+ wallet .lockunspent (True )
79
+ wallet .lockunspent (False , to_keep )
80
+
50
81
def run_test (self ):
82
+ self .watchonly_txid = None
83
+ self .watchonly_vout = None
51
84
self .log .info ("Connect nodes, set fees, generate blocks, and sync" )
52
85
self .min_relay_tx_fee = self .nodes [0 ].getnetworkinfo ()['relayfee' ]
53
86
# This test is not meant to test fee estimation and we'd like
@@ -373,6 +406,7 @@ def test_invalid_input(self):
373
406
def test_fee_p2pkh (self ):
374
407
"""Compare fee of a standard pubkeyhash transaction."""
375
408
self .log .info ("Test fundrawtxn p2pkh fee" )
409
+ self .lock_outputs_type (self .nodes [0 ], "p2pkh" )
376
410
inputs = []
377
411
outputs = {self .nodes [1 ].getnewaddress ():1.1 }
378
412
rawtx = self .nodes [0 ].createrawtransaction (inputs , outputs )
@@ -386,9 +420,12 @@ def test_fee_p2pkh(self):
386
420
feeDelta = Decimal (fundedTx ['fee' ]) - Decimal (signedFee )
387
421
assert feeDelta >= 0 and feeDelta <= self .fee_tolerance
388
422
423
+ self .unlock_utxos (self .nodes [0 ])
424
+
389
425
def test_fee_p2pkh_multi_out (self ):
390
426
"""Compare fee of a standard pubkeyhash transaction with multiple outputs."""
391
427
self .log .info ("Test fundrawtxn p2pkh fee with multiple outputs" )
428
+ self .lock_outputs_type (self .nodes [0 ], "p2pkh" )
392
429
inputs = []
393
430
outputs = {
394
431
self .nodes [1 ].getnewaddress ():1.1 ,
@@ -409,8 +446,11 @@ def test_fee_p2pkh_multi_out(self):
409
446
feeDelta = Decimal (fundedTx ['fee' ]) - Decimal (signedFee )
410
447
assert feeDelta >= 0 and feeDelta <= self .fee_tolerance
411
448
449
+ self .unlock_utxos (self .nodes [0 ])
450
+
412
451
def test_fee_p2sh (self ):
413
452
"""Compare fee of a 2-of-2 multisig p2sh transaction."""
453
+ self .lock_outputs_type (self .nodes [0 ], "p2pkh" )
414
454
# Create 2-of-2 addr.
415
455
addr1 = self .nodes [1 ].getnewaddress ()
416
456
addr2 = self .nodes [1 ].getnewaddress ()
@@ -433,9 +473,12 @@ def test_fee_p2sh(self):
433
473
feeDelta = Decimal (fundedTx ['fee' ]) - Decimal (signedFee )
434
474
assert feeDelta >= 0 and feeDelta <= self .fee_tolerance
435
475
476
+ self .unlock_utxos (self .nodes [0 ])
477
+
436
478
def test_fee_4of5 (self ):
437
479
"""Compare fee of a standard pubkeyhash transaction."""
438
480
self .log .info ("Test fundrawtxn fee with 4-of-5 addresses" )
481
+ self .lock_outputs_type (self .nodes [0 ], "p2pkh" )
439
482
440
483
# Create 4-of-5 addr.
441
484
addr1 = self .nodes [1 ].getnewaddress ()
@@ -474,6 +517,8 @@ def test_fee_4of5(self):
474
517
feeDelta = Decimal (fundedTx ['fee' ]) - Decimal (signedFee )
475
518
assert feeDelta >= 0 and feeDelta <= self .fee_tolerance
476
519
520
+ self .unlock_utxos (self .nodes [0 ])
521
+
477
522
def test_spend_2of2 (self ):
478
523
"""Spend a 2-of-2 multisig transaction over fundraw."""
479
524
self .log .info ("Test fundpsbt spending 2-of-2 multisig" )
@@ -542,15 +587,18 @@ def test_locked_wallet(self):
542
587
# Drain the keypool.
543
588
self .nodes [1 ].getnewaddress ()
544
589
self .nodes [1 ].getrawchangeaddress ()
545
- inputs = []
546
- outputs = {self .nodes [0 ].getnewaddress ():1.19999500 }
590
+
591
+ # Choose 2 inputs
592
+ inputs = self .nodes [1 ].listunspent ()[0 :2 ]
593
+ value = sum (inp ["amount" ] for inp in inputs ) - Decimal ("0.00000500" ) # Pay a 500 sat fee
594
+ outputs = {self .nodes [0 ].getnewaddress ():value }
547
595
rawtx = self .nodes [1 ].createrawtransaction (inputs , outputs )
548
596
# fund a transaction that does not require a new key for the change output
549
597
self .nodes [1 ].fundrawtransaction (rawtx )
550
598
551
599
# fund a transaction that requires a new key for the change output
552
600
# creating the key must be impossible because the wallet is locked
553
- outputs = {self .nodes [0 ].getnewaddress ():1.1 }
601
+ outputs = {self .nodes [0 ].getnewaddress ():value - Decimal ( "0.1" ) }
554
602
rawtx = self .nodes [1 ].createrawtransaction (inputs , outputs )
555
603
assert_raises_rpc_error (- 4 , "Transaction needs a change address, but we can't generate it." , self .nodes [1 ].fundrawtransaction , rawtx )
556
604
@@ -944,31 +992,31 @@ def test_include_unsafe(self):
944
992
945
993
# We receive unconfirmed funds from external keys (unsafe outputs).
946
994
addr = wallet .getnewaddress ()
947
- txid1 = self .nodes [2 ].sendtoaddress (addr , 6 )
948
- txid2 = self .nodes [2 ].sendtoaddress (addr , 4 )
949
- self .sync_all ()
950
- vout1 = find_vout_for_address (wallet , txid1 , addr )
951
- vout2 = find_vout_for_address (wallet , txid2 , addr )
995
+ inputs = []
996
+ for i in range (0 , 2 ):
997
+ txid = self .nodes [2 ].sendtoaddress (addr , 5 )
998
+ self .sync_mempools ()
999
+ vout = find_vout_for_address (wallet , txid , addr )
1000
+ inputs .append ((txid , vout ))
952
1001
953
1002
# Unsafe inputs are ignored by default.
954
- rawtx = wallet .createrawtransaction ([], [{self .nodes [2 ].getnewaddress (): 5 }])
1003
+ rawtx = wallet .createrawtransaction ([], [{self .nodes [2 ].getnewaddress (): 7. 5 }])
955
1004
assert_raises_rpc_error (- 4 , "Insufficient funds" , wallet .fundrawtransaction , rawtx )
956
1005
957
1006
# But we can opt-in to use them for funding.
958
1007
fundedtx = wallet .fundrawtransaction (rawtx , {"include_unsafe" : True })
959
1008
tx_dec = wallet .decoderawtransaction (fundedtx ['hex' ])
960
- assert any ([ txin [' txid' ] == txid1 and txin [' vout' ] == vout1 for txin in tx_dec [' vin' ] ])
1009
+ assert all (( txin [" txid" ], txin [" vout" ]) in inputs for txin in tx_dec [" vin" ])
961
1010
signedtx = wallet .signrawtransactionwithwallet (fundedtx ['hex' ])
962
- wallet .sendrawtransaction ( signedtx ['hex' ])
1011
+ assert wallet .testmempoolaccept ([ signedtx ['hex' ]])[ 0 ][ "allowed" ]
963
1012
964
1013
# And we can also use them once they're confirmed.
965
1014
self .generate (self .nodes [0 ], 1 )
966
- rawtx = wallet .createrawtransaction ([], [{self .nodes [2 ].getnewaddress (): 3 }])
967
- fundedtx = wallet .fundrawtransaction (rawtx , {"include_unsafe" : True })
1015
+ fundedtx = wallet .fundrawtransaction (rawtx , {"include_unsafe" : False })
968
1016
tx_dec = wallet .decoderawtransaction (fundedtx ['hex' ])
969
- assert any ([ txin [' txid' ] == txid2 and txin [' vout' ] == vout2 for txin in tx_dec [' vin' ] ])
1017
+ assert all (( txin [" txid" ], txin [" vout" ]) in inputs for txin in tx_dec [" vin" ])
970
1018
signedtx = wallet .signrawtransactionwithwallet (fundedtx ['hex' ])
971
- wallet .sendrawtransaction ( signedtx ['hex' ])
1019
+ assert wallet .testmempoolaccept ([ signedtx ['hex' ]])[ 0 ][ "allowed" ]
972
1020
973
1021
def test_22670 (self ):
974
1022
# In issue #22670, it was observed that ApproximateBestSubset may
0 commit comments