2018-06-27 17:05:54 -07:00
#!/usr/bin/env python3
2020-04-16 13:14:08 -04:00
# Copyright (c) 2018-2020 The Bitcoin Core developers
2018-06-27 17:05:54 -07:00
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
""" Test the Partially Signed Transaction RPCs.
"""
from test_framework . test_framework import BitcoinTestFramework
2019-04-06 18:38:51 -04:00
from test_framework . util import (
2020-12-04 15:20:42 +00:00
# assert_approx,
2019-04-06 18:38:51 -04:00
assert_equal ,
2019-06-28 22:44:38 -04:00
assert_greater_than ,
2019-04-06 18:38:51 -04:00
assert_raises_rpc_error ,
find_output ,
)
2020-11-09 21:20:10 +00:00
from decimal import Decimal
2018-07-07 00:10:35 +02:00
2019-05-01 18:28:10 -07:00
# These imports are used by commented-out tests.
"""
2018-07-07 00:10:35 +02:00
import json
import os
2019-05-01 18:28:10 -07:00
"""
2018-06-27 17:05:54 -07:00
2018-08-14 21:52:16 -04:00
MAX_BIP125_RBF_SEQUENCE = 0xfffffffd
2018-06-27 17:05:54 -07:00
# Create one-input, one-output, no-fee transaction:
class PSBTTest ( BitcoinTestFramework ) :
def set_test_params ( self ) :
self . setup_clean_chain = False
self . num_nodes = 3
2019-04-27 19:44:38 +02:00
self . extra_args = [
[ " -walletrbf=1 " ] ,
2020-09-12 17:07:59 +02:00
[ " -walletrbf=0 " , " -changetype=legacy " ] ,
2019-04-27 19:44:38 +02:00
[ ]
]
2019-12-06 14:37:49 +00:00
self . supports_cli = False
2018-06-27 17:05:54 -07:00
2018-09-09 13:32:37 -04:00
def skip_test_if_missing_module ( self ) :
self . skip_if_no_wallet ( )
2020-06-04 23:43:43 -04:00
# TODO: Re-enable this test with segwit v1
2018-09-20 11:43:06 -07:00
def test_utxo_conversion ( self ) :
mining_node = self . nodes [ 2 ]
offline_node = self . nodes [ 0 ]
online_node = self . nodes [ 1 ]
# Disconnect offline node from others
2020-05-05 13:02:01 -07:00
# Topology of test network is linear, so this one call is enough
2020-09-17 00:32:01 -07:00
self . disconnect_nodes ( 0 , 1 )
2018-09-20 11:43:06 -07:00
2019-07-16 15:33:35 -04:00
# Create watchonly on online_node
online_node . createwallet ( wallet_name = ' wonline ' , disable_private_keys = True )
wonline = online_node . get_wallet_rpc ( ' wonline ' )
w2 = online_node . get_wallet_rpc ( ' ' )
2018-09-20 11:43:06 -07:00
# Mine a transaction that credits the offline address
offline_addr = offline_node . getnewaddress ( address_type = " p2sh-segwit " )
2019-07-16 15:33:35 -04:00
online_addr = w2 . getnewaddress ( address_type = " p2sh-segwit " )
wonline . importaddress ( offline_addr , " " , False )
2018-09-20 11:43:06 -07:00
mining_node . sendtoaddress ( address = offline_addr , amount = 1.0 )
mining_node . generate ( nblocks = 1 )
2019-04-06 18:19:45 -04:00
self . sync_blocks ( [ mining_node , online_node ] )
2018-09-20 11:43:06 -07:00
# Construct an unsigned PSBT on the online node (who doesn't know the output is Segwit, so will include a non-witness UTXO)
2019-07-16 15:33:35 -04:00
utxos = wonline . listunspent ( addresses = [ offline_addr ] )
2020-11-26 01:08:31 +00:00
raw = wonline . createrawtransaction ( [ { " txid " : utxos [ 0 ] [ " txid " ] , " vout " : utxos [ 0 ] [ " vout " ] } ] , [ { online_addr : 0.9999 } , { " fee " : 0.0001 } ] )
2019-07-16 15:33:35 -04:00
psbt = wonline . walletprocesspsbt ( online_node . converttopsbt ( raw ) ) [ " psbt " ]
2019-02-19 17:43:44 -05:00
assert " non_witness_utxo " in mining_node . decodepsbt ( psbt ) [ " inputs " ] [ 0 ]
2018-09-20 11:43:06 -07:00
# Have the offline node sign the PSBT (which will update the UTXO to segwit)
signed_psbt = offline_node . walletprocesspsbt ( psbt ) [ " psbt " ]
2019-02-19 17:43:44 -05:00
assert " witness_utxo " in mining_node . decodepsbt ( signed_psbt ) [ " inputs " ] [ 0 ]
2018-09-20 11:43:06 -07:00
# Make sure we can mine the resulting transaction
txid = mining_node . sendrawtransaction ( mining_node . finalizepsbt ( signed_psbt ) [ " hex " ] )
mining_node . generate ( 1 )
2019-04-06 18:19:45 -04:00
self . sync_blocks ( [ mining_node , online_node ] )
2018-09-20 11:43:06 -07:00
assert_equal ( online_node . gettxout ( txid , 0 ) [ " confirmations " ] , 1 )
2019-07-16 15:33:35 -04:00
wonline . unloadwallet ( )
2018-09-20 11:43:06 -07:00
# Reconnect
2020-09-17 00:46:07 -07:00
self . connect_nodes ( 0 , 1 )
self . connect_nodes ( 0 , 2 )
2018-09-20 11:43:06 -07:00
2019-05-01 18:28:10 -07:00
def get_address ( self , confidential , node_num , addr_mode = None ) :
if ( addr_mode ) :
addr = self . nodes [ node_num ] . getnewaddress ( )
else :
addr = self . nodes [ node_num ] . getnewaddress ( " " , addr_mode )
if confidential :
addr = self . nodes [ node_num ] . getaddressinfo ( addr ) [ ' confidential ' ]
else :
addr = self . nodes [ node_num ] . getaddressinfo ( addr ) [ ' unconfidential ' ]
return addr
def to_unconf_addr ( self , node_num , addr ) :
return self . nodes [ node_num ] . getaddressinfo ( addr ) [ ' unconfidential ' ]
def num_blinded_outputs ( self , tx ) :
result = 0
decoded = self . nodes [ 0 ] . decoderawtransaction ( tx )
for out in decoded [ " vout " ] :
if out [ " scriptPubKey " ] [ " type " ] == " fee " :
pass
if " valuecommitment " in out :
result + = 1
return result
2020-09-12 17:07:59 +02:00
def assert_change_type ( self , psbtx , expected_type ) :
""" Assert that the given PSBT has a change output with the given type. """
# The decodepsbt RPC is stateless and independent of any settings, we can always just call it on the first node
decoded_psbt = self . nodes [ 0 ] . decodepsbt ( psbtx [ " psbt " ] )
changepos = psbtx [ " changepos " ]
2021-03-16 18:34:46 -04:00
assert_equal ( decoded_psbt [ " outputs " ] [ changepos ] [ " script " ] [ " type " ] , expected_type )
2020-09-12 17:07:59 +02:00
2019-05-01 18:28:10 -07:00
def run_basic_tests ( self , confidential ) :
2020-11-28 18:55:44 +00:00
starting_n_unspent = len ( self . nodes [ 0 ] . listlockunspent ( ) ) # ELEMENTS
2018-06-27 17:05:54 -07:00
# Create and fund a raw tx for sending 10 BTC
2021-04-21 14:55:38 -04:00
psbtx1 = self . nodes [ 0 ] . walletcreatefundedpsbt ( [ ] , [ { self . get_address ( confidential , 2 ) : 10 } ] ) [ ' psbt ' ]
2018-06-27 17:05:54 -07:00
2019-07-12 13:30:10 +01:00
# If inputs are specified, do not automatically add more:
utxo1 = self . nodes [ 0 ] . listunspent ( ) [ 0 ]
2021-04-21 14:55:38 -04:00
assert_raises_rpc_error ( - 4 , " Insufficient funds " , self . nodes [ 0 ] . walletcreatefundedpsbt , [ { " txid " : utxo1 [ ' txid ' ] , " vout " : utxo1 [ ' vout ' ] } ] , [ { self . get_address ( confidential , 2 ) : 90 } ] )
2019-07-12 13:30:10 +01:00
2021-04-21 14:55:38 -04:00
psbtx1 = self . nodes [ 0 ] . walletcreatefundedpsbt ( [ { " txid " : utxo1 [ ' txid ' ] , " vout " : utxo1 [ ' vout ' ] } ] , [ { self . get_address ( confidential , 2 ) : 90 } ] , 0 , { " add_inputs " : True } ) [ ' psbt ' ]
2020-11-26 21:31:17 +00:00
# ELEMENTS: we are on the edge between 2 and 3 inputs; don't check exact value,
# just make sure that we added at least one input
2021-01-18 17:13:27 -05:00
assert len ( self . nodes [ 0 ] . decodepsbt ( psbtx1 ) [ " inputs " ] ) > 1
2019-07-12 13:30:10 +01:00
2019-07-11 18:50:45 +01:00
# Inputs argument can be null
2021-04-21 14:55:38 -04:00
self . nodes [ 0 ] . walletcreatefundedpsbt ( None , [ { self . nodes [ 2 ] . getnewaddress ( ) : 10 } ] )
2019-07-11 18:50:45 +01:00
2018-06-27 17:05:54 -07:00
# Node 1 should not be able to add anything to it but still return the psbtx same as before
2021-04-21 15:13:51 -04:00
psbtx = self . nodes [ 1 ] . walletprocesspsbt ( psbtx1 ) [ ' psbt ' ]
2018-06-27 17:05:54 -07:00
assert_equal ( psbtx1 , psbtx )
# Sign the transaction and send
2021-04-21 15:13:51 -04:00
signed_psbt = self . nodes [ 0 ] . walletprocesspsbt ( psbtx ) [ ' psbt ' ]
final_tx = self . nodes [ 0 ] . finalizepsbt ( signed_psbt ) [ ' hex ' ]
2019-05-01 18:28:10 -07:00
if confidential :
# Can't use assert_equal because there may or may not be change
assert ( self . num_blinded_outputs ( final_tx ) > 0 )
2018-06-27 17:05:54 -07:00
self . nodes [ 0 ] . sendrawtransaction ( final_tx )
2020-08-07 13:53:51 +02:00
# Manually selected inputs can be locked:
2020-11-28 18:55:44 +00:00
assert_equal ( len ( self . nodes [ 0 ] . listlockunspent ( ) ) , starting_n_unspent )
2020-08-07 13:53:51 +02:00
utxo1 = self . nodes [ 0 ] . listunspent ( ) [ 0 ]
2021-04-21 14:55:38 -04:00
psbtx1 = self . nodes [ 0 ] . walletcreatefundedpsbt ( [ { " txid " : utxo1 [ ' txid ' ] , " vout " : utxo1 [ ' vout ' ] } ] , [ { self . get_address ( confidential , 2 ) : 1 } ] , 0 , { " lockUnspents " : True } ) [ " psbt " ]
2020-11-28 18:55:44 +00:00
assert_equal ( len ( self . nodes [ 0 ] . listlockunspent ( ) ) , starting_n_unspent + 1 )
2020-08-07 13:53:51 +02:00
# Locks are ignored for manually selected inputs
2021-04-21 14:55:38 -04:00
self . nodes [ 0 ] . walletcreatefundedpsbt ( [ { " txid " : utxo1 [ ' txid ' ] , " vout " : utxo1 [ ' vout ' ] } ] , [ { self . get_address ( confidential , 2 ) : 1 } ] , 0 )
2020-08-07 13:53:51 +02:00
# Create p2sh, p2wpkh, and p2wsh addresses
2019-05-01 18:28:10 -07:00
pubkey0 = self . nodes [ 0 ] . getaddressinfo ( self . get_address ( confidential , 0 ) ) [ ' pubkey ' ]
pubkey1 = self . nodes [ 1 ] . getaddressinfo ( self . get_address ( confidential , 1 ) ) [ ' pubkey ' ]
pubkey2 = self . nodes [ 2 ] . getaddressinfo ( self . get_address ( confidential , 2 ) ) [ ' pubkey ' ]
2019-07-16 15:33:35 -04:00
# Setup watchonly wallets
2020-11-26 01:08:31 +00:00
if confidential :
self . nodes [ 2 ] . createwallet ( wallet_name = ' wmulti_conf ' , disable_private_keys = True )
wmulti = self . nodes [ 2 ] . get_wallet_rpc ( ' wmulti_conf ' )
else :
self . nodes [ 2 ] . createwallet ( wallet_name = ' wmulti ' , disable_private_keys = True )
wmulti = self . nodes [ 2 ] . get_wallet_rpc ( ' wmulti ' )
2019-07-16 15:33:35 -04:00
# Create all the addresses
p2sh = wmulti . addmultisigaddress ( 2 , [ pubkey0 , pubkey1 , pubkey2 ] , " " , " legacy " ) [ ' address ' ]
2019-05-01 18:28:10 -07:00
p2sh_unconf = self . to_unconf_addr ( 1 , p2sh )
2019-07-16 15:33:35 -04:00
p2wsh = wmulti . addmultisigaddress ( 2 , [ pubkey0 , pubkey1 , pubkey2 ] , " " , " bech32 " ) [ ' address ' ]
2019-05-01 18:28:10 -07:00
p2wsh_unconf = self . to_unconf_addr ( 1 , p2wsh )
2019-07-16 15:33:35 -04:00
p2sh_p2wsh = wmulti . addmultisigaddress ( 2 , [ pubkey0 , pubkey1 , pubkey2 ] , " " , " p2sh-segwit " ) [ ' address ' ]
2019-05-01 18:28:10 -07:00
p2sh_p2wsh_unconf = self . to_unconf_addr ( 1 , p2sh_p2wsh )
2019-07-16 15:33:35 -04:00
if not self . options . descriptors :
wmulti . importaddress ( p2sh )
wmulti . importaddress ( p2wsh )
wmulti . importaddress ( p2sh_p2wsh )
2019-05-01 18:28:10 -07:00
p2wpkh = self . get_address ( confidential , 1 , " bech32 " )
p2wpkh_unconf = self . to_unconf_addr ( 1 , p2wpkh )
p2pkh = self . get_address ( confidential , 1 , " legacy " )
p2pkh_unconf = self . to_unconf_addr ( 1 , p2pkh )
p2sh_p2wpkh = self . get_address ( confidential , 1 , " p2sh-segwit " )
p2sh_p2wpkh_unconf = self . to_unconf_addr ( 1 , p2sh_p2wpkh )
2018-06-27 17:05:54 -07:00
# fund those addresses
2021-04-21 14:55:38 -04:00
rawtx = self . nodes [ 0 ] . createrawtransaction ( [ ] , [ { p2sh : 10 } , { p2wsh : 10 } , { p2wpkh : 10 } , { p2sh_p2wsh : 10 } , { p2sh_p2wpkh : 10 } , { p2pkh : 10 } ] )
2018-06-27 17:05:54 -07:00
rawtx = self . nodes [ 0 ] . fundrawtransaction ( rawtx , { " changePosition " : 3 } )
2019-05-01 18:28:10 -07:00
rawtx = self . nodes [ 0 ] . blindrawtransaction ( rawtx [ ' hex ' ] )
signed_tx = self . nodes [ 0 ] . signrawtransactionwithwallet ( rawtx ) [ ' hex ' ]
2018-06-27 17:05:54 -07:00
txid = self . nodes [ 0 ] . sendrawtransaction ( signed_tx )
2019-05-01 18:28:10 -07:00
2018-06-27 17:05:54 -07:00
self . nodes [ 0 ] . generate ( 6 )
self . sync_all ( )
# Find the output pos
p2sh_pos = - 1
p2wsh_pos = - 1
p2wpkh_pos = - 1
p2pkh_pos = - 1
p2sh_p2wsh_pos = - 1
p2sh_p2wpkh_pos = - 1
decoded = self . nodes [ 0 ] . decoderawtransaction ( signed_tx )
for out in decoded [ ' vout ' ] :
2019-05-01 18:28:10 -07:00
if out [ ' scriptPubKey ' ] [ ' type ' ] == ' fee ' :
next
elif out [ ' scriptPubKey ' ] [ ' addresses ' ] [ 0 ] == p2sh_unconf :
2018-06-27 17:05:54 -07:00
p2sh_pos = out [ ' n ' ]
2019-05-01 18:28:10 -07:00
elif out [ ' scriptPubKey ' ] [ ' addresses ' ] [ 0 ] == p2wsh_unconf :
2018-06-27 17:05:54 -07:00
p2wsh_pos = out [ ' n ' ]
2019-05-01 18:28:10 -07:00
elif out [ ' scriptPubKey ' ] [ ' addresses ' ] [ 0 ] == p2wpkh_unconf :
2018-06-27 17:05:54 -07:00
p2wpkh_pos = out [ ' n ' ]
2019-05-01 18:28:10 -07:00
elif out [ ' scriptPubKey ' ] [ ' addresses ' ] [ 0 ] == p2sh_p2wsh_unconf :
2018-06-27 17:05:54 -07:00
p2sh_p2wsh_pos = out [ ' n ' ]
2019-05-01 18:28:10 -07:00
elif out [ ' scriptPubKey ' ] [ ' addresses ' ] [ 0 ] == p2sh_p2wpkh_unconf :
2018-06-27 17:05:54 -07:00
p2sh_p2wpkh_pos = out [ ' n ' ]
2019-05-01 18:28:10 -07:00
elif out [ ' scriptPubKey ' ] [ ' addresses ' ] [ 0 ] == p2pkh_unconf :
2018-06-27 17:05:54 -07:00
p2pkh_pos = out [ ' n ' ]
2020-06-26 16:05:03 +02:00
inputs = [ { " txid " : txid , " vout " : p2wpkh_pos } , { " txid " : txid , " vout " : p2sh_p2wpkh_pos } , { " txid " : txid , " vout " : p2pkh_pos } ]
2020-12-02 03:05:14 +00:00
outputs = [ { self . get_address ( confidential , 1 ) : 29.99 } ]
2020-06-26 16:05:03 +02:00
2018-06-27 17:05:54 -07:00
# spend single key from node 1
2020-06-26 16:05:03 +02:00
created_psbt = self . nodes [ 1 ] . walletcreatefundedpsbt ( inputs , outputs )
2021-04-21 15:13:51 -04:00
walletsignpsbt_out = self . nodes [ 1 ] . walletprocesspsbt ( created_psbt [ " psbt " ] )
2020-06-08 19:27:16 -04:00
# Make sure it has both types of UTXOs
2020-11-26 01:09:18 +00:00
decoded = self . nodes [ 1 ] . decodepsbt ( walletsignpsbt_out [ ' psbt ' ] )
2020-06-08 19:27:16 -04:00
assert ' non_witness_utxo ' in decoded [ ' inputs ' ] [ 0 ]
assert ' witness_utxo ' in decoded [ ' inputs ' ] [ 0 ]
2020-07-26 13:07:45 +02:00
# Check decodepsbt fee calculation (input values shall only be counted once per UTXO)
2020-11-26 21:31:17 +00:00
#assert_equal(decoded['fee'], created_psbt['fee']) # ELEMENTS: we do not have this field. Should be fixed by #900
2019-05-01 18:28:10 -07:00
assert_equal ( walletsignpsbt_out [ ' complete ' ] , True )
2020-12-02 03:05:14 +00:00
self . nodes [ 1 ] . sendrawtransaction ( self . nodes [ 1 ] . finalizepsbt ( walletsignpsbt_out [ ' psbt ' ] ) [ ' hex ' ] )
2018-06-27 17:05:54 -07:00
2020-11-09 21:20:10 +00:00
if confidential :
2020-12-02 03:05:14 +00:00
fee_rate_sb = 2000
2020-11-09 21:20:10 +00:00
else :
2020-12-02 03:05:14 +00:00
fee_rate_sb = 10000
2018-06-27 17:05:54 -07:00
2020-11-04 13:13:17 +01:00
self . log . info ( " Test walletcreatefundedpsbt fee rate of 10000 sat/vB and 0.1 BTC/kvB produces a total fee at or slightly below -maxtxfee (~0.05290000) " )
2020-12-04 15:20:42 +00:00
#res1 =
self . nodes [ 1 ] . walletcreatefundedpsbt ( inputs , outputs , 0 , { " fee_rate " : fee_rate_sb , " add_inputs " : True } )
2020-12-02 17:53:59 +00:00
#assert_approx(res1["fee"], 0.055, 0.005) # ELEMENTS: no "fee" field
2020-12-04 15:20:42 +00:00
#res2 =
self . nodes [ 1 ] . walletcreatefundedpsbt ( inputs , outputs , 0 , { " feeRate " : fee_rate_sb / 100000.0 , " add_inputs " : True } )
2020-12-02 17:53:59 +00:00
#assert_approx(res2["fee"], 0.055, 0.005) # ELEMENTS: no "fee" field
2020-11-12 11:16:48 +01:00
self . log . info ( " Test min fee rate checks with walletcreatefundedpsbt are bypassed, e.g. a fee_rate under 1 sat/vB is allowed " )
2020-12-04 15:20:42 +00:00
#res3 =
self . nodes [ 1 ] . walletcreatefundedpsbt ( inputs , outputs , 0 , { " fee_rate " : 0.99999999 , " add_inputs " : True } )
2020-12-02 17:53:59 +00:00
#assert_approx(res3["fee"], 0.00000381, 0.0000001) # ELEMENTS: no "fee" field
2020-12-04 15:20:42 +00:00
#res4 =
self . nodes [ 1 ] . walletcreatefundedpsbt ( inputs , outputs , 0 , { " feeRate " : 0.00000999 , " add_inputs " : True } )
2020-12-02 17:53:59 +00:00
#assert_approx(res4["fee"], 0.00000381, 0.0000001) # ELEMENTS: no "fee" field
2020-11-04 13:13:17 +01:00
self . log . info ( " Test invalid fee rate settings " )
2020-11-12 11:16:48 +01:00
assert_raises_rpc_error ( - 8 , " Invalid fee_rate 0.000 sat/vB (must be greater than 0) " ,
2020-11-04 13:13:17 +01:00
self . nodes [ 1 ] . walletcreatefundedpsbt , inputs , outputs , 0 , { " fee_rate " : 0 , " add_inputs " : True } )
2020-11-08 19:57:35 +01:00
assert_raises_rpc_error ( - 8 , " Invalid feeRate 0.00000000 BTC/kvB (must be greater than 0) " ,
2020-11-04 13:13:17 +01:00
self . nodes [ 1 ] . walletcreatefundedpsbt , inputs , outputs , 0 , { " feeRate " : 0 , " add_inputs " : True } )
for param , value in { ( " fee_rate " , 100000 ) , ( " feeRate " , 1 ) } :
assert_raises_rpc_error ( - 4 , " Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate) " ,
self . nodes [ 1 ] . walletcreatefundedpsbt , inputs , outputs , 0 , { param : value , " add_inputs " : True } )
assert_raises_rpc_error ( - 3 , " Amount out of range " ,
self . nodes [ 1 ] . walletcreatefundedpsbt , inputs , outputs , 0 , { " fee_rate " : - 1 , " add_inputs " : True } )
assert_raises_rpc_error ( - 3 , " Amount is not a number or string " ,
self . nodes [ 1 ] . walletcreatefundedpsbt , inputs , outputs , 0 , { " fee_rate " : { " foo " : " bar " } , " add_inputs " : True } )
assert_raises_rpc_error ( - 3 , " Invalid amount " ,
self . nodes [ 1 ] . walletcreatefundedpsbt , inputs , outputs , 0 , { " fee_rate " : " " , " add_inputs " : True } )
self . log . info ( " - raises RPC error if both feeRate and fee_rate are passed " )
assert_raises_rpc_error ( - 8 , " Cannot specify both fee_rate (sat/vB) and feeRate (BTC/kvB) " ,
self . nodes [ 1 ] . walletcreatefundedpsbt , inputs , outputs , 0 , { " fee_rate " : 0.1 , " feeRate " : 0.1 , " add_inputs " : True } )
self . log . info ( " - raises RPC error if both feeRate and estimate_mode passed " )
assert_raises_rpc_error ( - 8 , " Cannot specify both estimate_mode and feeRate " ,
self . nodes [ 1 ] . walletcreatefundedpsbt , inputs , outputs , 0 , { " estimate_mode " : " economical " , " feeRate " : 0.1 , " add_inputs " : True } )
for param in [ " feeRate " , " fee_rate " ] :
self . log . info ( " - raises RPC error if both {} and conf_target are passed " . format ( param ) )
assert_raises_rpc_error ( - 8 , " Cannot specify both conf_target and {} . Please provide either a confirmation "
" target in blocks for automatic fee estimation, or an explicit fee rate. " . format ( param ) ,
self . nodes [ 1 ] . walletcreatefundedpsbt , inputs , outputs , 0 , { param : 1 , " conf_target " : 1 , " add_inputs " : True } )
self . log . info ( " - raises RPC error if both fee_rate and estimate_mode are passed " )
assert_raises_rpc_error ( - 8 , " Cannot specify both estimate_mode and fee_rate " ,
self . nodes [ 1 ] . walletcreatefundedpsbt , inputs , outputs , 0 , { " fee_rate " : 1 , " estimate_mode " : " economical " , " add_inputs " : True } )
2020-06-26 16:06:43 +02:00
self . log . info ( " - raises RPC error with invalid estimate_mode settings " )
for k , v in { " number " : 42 , " object " : { " foo " : " bar " } } . items ( ) :
assert_raises_rpc_error ( - 3 , " Expected type string for estimate_mode, got {} " . format ( k ) ,
2020-11-04 13:13:17 +01:00
self . nodes [ 1 ] . walletcreatefundedpsbt , inputs , outputs , 0 , { " estimate_mode " : v , " conf_target " : 0.1 , " add_inputs " : True } )
for mode in [ " " , " foo " , Decimal ( " 3.141592 " ) ] :
2020-11-10 12:29:01 +01:00
assert_raises_rpc_error ( - 8 , ' Invalid estimate_mode parameter, must be one of: " unset " , " economical " , " conservative " ' ,
2020-11-04 13:13:17 +01:00
self . nodes [ 1 ] . walletcreatefundedpsbt , inputs , outputs , 0 , { " estimate_mode " : mode , " conf_target " : 0.1 , " add_inputs " : True } )
2020-06-26 16:06:43 +02:00
self . log . info ( " - raises RPC error with invalid conf_target settings " )
2020-11-04 13:13:17 +01:00
for mode in [ " unset " , " economical " , " conservative " ] :
2020-06-26 16:06:43 +02:00
self . log . debug ( " {} " . format ( mode ) )
for k , v in { " string " : " " , " object " : { " foo " : " bar " } } . items ( ) :
assert_raises_rpc_error ( - 3 , " Expected type number for conf_target, got {} " . format ( k ) ,
2020-11-04 13:13:17 +01:00
self . nodes [ 1 ] . walletcreatefundedpsbt , inputs , outputs , 0 , { " estimate_mode " : mode , " conf_target " : v , " add_inputs " : True } )
for n in [ - 1 , 0 , 1009 ] :
assert_raises_rpc_error ( - 8 , " Invalid conf_target, must be between 1 and 1008 " , # max value of 1008 per src/policy/fees.h
self . nodes [ 1 ] . walletcreatefundedpsbt , inputs , outputs , 0 , { " estimate_mode " : mode , " conf_target " : n , " add_inputs " : True } )
self . log . info ( " Test walletcreatefundedpsbt with too-high fee rate produces total fee well above -maxtxfee and raises RPC error " )
2019-07-02 15:16:36 +01:00
# previously this was silently capped at -maxtxfee
2020-06-26 16:05:03 +02:00
for bool_add , outputs_array in { True : outputs , False : [ { self . nodes [ 1 ] . getnewaddress ( ) : 1 } ] } . items ( ) :
2020-11-04 13:13:17 +01:00
msg = " Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate) "
assert_raises_rpc_error ( - 4 , msg , self . nodes [ 1 ] . walletcreatefundedpsbt , inputs , outputs_array , 0 , { " fee_rate " : 1000000 , " add_inputs " : bool_add } )
assert_raises_rpc_error ( - 4 , msg , self . nodes [ 1 ] . walletcreatefundedpsbt , inputs , outputs_array , 0 , { " feeRate " : 1 , " add_inputs " : bool_add } )
2019-06-28 22:44:38 -04:00
2020-06-26 16:05:03 +02:00
self . log . info ( " Test various PSBT operations " )
2018-06-27 17:05:54 -07:00
# partially sign multisig things with node 1
2021-04-21 15:13:51 -04:00
psbtx = wmulti . walletcreatefundedpsbt ( inputs = [ { " txid " : txid , " vout " : p2wsh_pos } , { " txid " : txid , " vout " : p2sh_pos } , { " txid " : txid , " vout " : p2sh_p2wsh_pos } ] , outputs = [ { self . get_address ( confidential , 1 ) : 29.99 } ] , options = { ' changeAddress ' : self . nodes [ 1 ] . getrawchangeaddress ( ) } ) [ ' psbt ' ]
filled = wmulti . walletprocesspsbt ( psbtx )
2019-05-01 18:28:10 -07:00
# have both nodes fill before we try to blind and sign
2021-04-21 15:13:51 -04:00
walletprocesspsbt_out = self . nodes [ 1 ] . walletprocesspsbt ( filled [ " psbt " ] )
2018-06-27 17:05:54 -07:00
psbtx = walletprocesspsbt_out [ ' psbt ' ]
assert_equal ( walletprocesspsbt_out [ ' complete ' ] , False )
2019-07-16 15:33:35 -04:00
# Unload wmulti, we don't need it anymore
wmulti . unloadwallet ( )
2018-06-27 17:05:54 -07:00
# partially sign with node 2. This should be complete and sendable
2021-04-21 15:13:51 -04:00
walletsignpsbt_out = self . nodes [ 2 ] . walletprocesspsbt ( psbtx )
2019-05-01 18:28:10 -07:00
assert_equal ( walletsignpsbt_out [ ' complete ' ] , True )
hex_tx = self . nodes [ 2 ] . finalizepsbt ( walletsignpsbt_out [ ' psbt ' ] ) [ ' hex ' ]
if confidential :
# Can't use assert_equal because there may or may not be change
assert ( self . num_blinded_outputs ( hex_tx ) > 0 )
self . nodes [ 2 ] . sendrawtransaction ( hex_tx )
2018-06-27 17:05:54 -07:00
# check that walletprocesspsbt fails to decode a non-psbt
2021-04-21 14:55:38 -04:00
rawtx = self . nodes [ 1 ] . createrawtransaction ( [ { " txid " : txid , " vout " : p2wpkh_pos } ] , [ { self . get_address ( confidential , 1 ) : 9.99 } ] )
2018-06-27 17:05:54 -07:00
assert_raises_rpc_error ( - 22 , " TX decode failed " , self . nodes [ 1 ] . walletprocesspsbt , rawtx )
# Convert a non-psbt to psbt and make sure we can decode it
2021-04-21 14:55:38 -04:00
rawtx = self . nodes [ 0 ] . createrawtransaction ( [ ] , [ { self . get_address ( confidential , 1 ) : 10 } ] )
2018-06-27 17:05:54 -07:00
rawtx = self . nodes [ 0 ] . fundrawtransaction ( rawtx )
new_psbt = self . nodes [ 0 ] . converttopsbt ( rawtx [ ' hex ' ] )
self . nodes [ 0 ] . decodepsbt ( new_psbt )
2018-11-27 17:46:20 +00:00
# Make sure that a non-psbt with signatures cannot be converted
2018-11-27 17:43:48 +00:00
# Error could be either "TX decode failed" (segwit inputs causes parsing to fail) or "Inputs must not have scriptSigs and scriptWitnesses"
2019-04-26 09:04:08 -04:00
# We must set iswitness=True because the serialized transaction has inputs and is therefore a witness transaction
2018-06-27 17:05:54 -07:00
signedtx = self . nodes [ 0 ] . signrawtransactionwithwallet ( rawtx [ ' hex ' ] )
2019-05-01 18:28:10 -07:00
# Can be either a scriptSig or a scriptWitness that it yells about, depending on which UTXOs are selected for the TX
assert_raises_rpc_error ( - 22 , " Inputs must not have " , self . nodes [ 0 ] . converttopsbt , signedtx [ ' hex ' ] , False )
assert_raises_rpc_error ( - 22 , " Inputs must not have " , self . nodes [ 0 ] . converttopsbt , signedtx [ ' hex ' ] )
2019-04-26 09:04:08 -04:00
assert_raises_rpc_error ( - 22 , " " , self . nodes [ 0 ] . converttopsbt , hexstring = signedtx [ ' hex ' ] , iswitness = True )
assert_raises_rpc_error ( - 22 , " " , self . nodes [ 0 ] . converttopsbt , hexstring = signedtx [ ' hex ' ] , permitsigdata = False , iswitness = True )
2018-09-29 22:09:15 -04:00
# Unless we allow it to convert and strip signatures
self . nodes [ 0 ] . converttopsbt ( signedtx [ ' hex ' ] , True )
2018-06-27 17:05:54 -07:00
2018-08-14 09:27:30 +02:00
# Explicitly allow converting non-empty txs
2018-06-27 17:05:54 -07:00
new_psbt = self . nodes [ 0 ] . converttopsbt ( rawtx [ ' hex ' ] )
self . nodes [ 0 ] . decodepsbt ( new_psbt )
# Create outputs to nodes 1 and 2
2019-05-01 18:28:10 -07:00
# We do a whole song-and-dance here (instead of calling sendtoaddress) to get access to the unblinded transaction data to find our outputs
node1_addr = self . get_address ( confidential , 1 )
node1_unconf_addr = self . to_unconf_addr ( 1 , node1_addr )
node2_addr = self . get_address ( confidential , 2 )
node2_unconf_addr = self . to_unconf_addr ( 2 , node2_addr )
2021-04-21 14:55:38 -04:00
rt1 = self . nodes [ 0 ] . createrawtransaction ( [ ] , [ { node1_addr : 13 } ] )
2019-05-01 18:28:10 -07:00
rt1 = self . nodes [ 0 ] . fundrawtransaction ( rt1 )
rt1 = self . nodes [ 0 ] . blindrawtransaction ( rt1 [ ' hex ' ] )
rt1 = self . nodes [ 0 ] . signrawtransactionwithwallet ( rt1 )
txid1 = self . nodes [ 0 ] . sendrawtransaction ( rt1 [ ' hex ' ] )
rt1 = self . nodes [ 0 ] . decoderawtransaction ( rt1 [ ' hex ' ] )
2021-04-21 14:55:38 -04:00
rt2 = self . nodes [ 0 ] . createrawtransaction ( [ ] , [ { node2_addr : 13 } ] )
2019-05-01 18:28:10 -07:00
rt2 = self . nodes [ 0 ] . fundrawtransaction ( rt2 )
rt2 = self . nodes [ 0 ] . blindrawtransaction ( rt2 [ ' hex ' ] )
rt2 = self . nodes [ 0 ] . signrawtransactionwithwallet ( rt2 )
txid2 = self . nodes [ 0 ] . sendrawtransaction ( rt2 [ ' hex ' ] )
rt2 = self . nodes [ 0 ] . decoderawtransaction ( rt2 [ ' hex ' ] )
2018-06-27 17:05:54 -07:00
self . nodes [ 0 ] . generate ( 6 )
self . sync_all ( )
2019-05-01 18:28:10 -07:00
for out in rt1 [ ' vout ' ] :
if out [ ' scriptPubKey ' ] [ ' type ' ] == " fee " :
pass
elif out [ ' scriptPubKey ' ] [ ' addresses ' ] [ 0 ] == node1_unconf_addr :
vout1 = out [ ' n ' ]
for out in rt2 [ ' vout ' ] :
if out [ ' scriptPubKey ' ] [ ' type ' ] == " fee " :
pass
elif out [ ' scriptPubKey ' ] [ ' addresses ' ] [ 0 ] == node2_unconf_addr :
vout2 = out [ ' n ' ]
# This test doesn't work with Confidential Assets yet.
if not confidential :
# Create a psbt spending outputs from nodes 1 and 2
psbt_orig = self . nodes [ 0 ] . createpsbt ( [ { " txid " : txid1 , " vout " : vout1 } , { " txid " : txid2 , " vout " : vout2 } ] , [ { self . get_address ( confidential , 0 ) : 25.999 } , { " fee " : 0.001 } ] )
# Update psbts, should only have data for one input and not the other
2020-11-26 01:07:45 +00:00
psbt1 = self . nodes [ 1 ] . walletprocesspsbt ( psbt_orig , False , " ALL " ) [ ' psbt ' ]
2019-05-01 18:28:10 -07:00
psbt1_decoded = self . nodes [ 0 ] . decodepsbt ( psbt1 )
2021-01-18 17:13:27 -05:00
assert len ( psbt1_decoded [ " inputs " ] [ 0 ] . keys ( ) ) > 3
2021-05-05 18:05:54 -04:00
assert len ( psbt1_decoded [ " inputs " ] [ 1 ] . keys ( ) ) == 3
2020-11-26 01:07:45 +00:00
# Check that BIP32 path was added
assert " bip32_derivs " in psbt1_decoded [ ' inputs ' ] [ 0 ]
psbt2 = self . nodes [ 2 ] . walletprocesspsbt ( psbt_orig , False , " ALL " , False ) [ ' psbt ' ]
2019-05-01 18:28:10 -07:00
psbt2_decoded = self . nodes [ 0 ] . decodepsbt ( psbt2 )
2021-01-18 17:13:27 -05:00
assert len ( psbt2_decoded [ " inputs " ] [ 0 ] . keys ( ) ) == 3
assert len ( psbt2_decoded [ " inputs " ] [ 1 ] . keys ( ) ) > 3
2020-11-26 01:07:45 +00:00
# Check that BIP32 paths were not added
assert " bip32_derivs " not in psbt2_decoded [ ' inputs ' ] [ 1 ]
2021-05-05 18:05:54 -04:00
# Fill PSBTs (workaround issue #18039)
psbt1 = self . nodes [ 1 ] . walletprocesspsbt ( psbt_orig , False ) [ ' psbt ' ]
psbt2 = self . nodes [ 2 ] . walletprocesspsbt ( psbt_orig , False ) [ ' psbt ' ]
2019-05-01 18:28:10 -07:00
2021-05-05 18:05:54 -04:00
# Combine and sign
combined = self . nodes [ 0 ] . combinepsbt ( [ psbt1 , psbt2 ] )
psbt1 = self . nodes [ 1 ] . walletprocesspsbt ( combined , True ) [ ' psbt ' ]
psbt2 = self . nodes [ 2 ] . walletprocesspsbt ( combined , True ) [ ' psbt ' ]
# Combine again, finalize, sign, and send the psbts
2019-05-01 18:28:10 -07:00
combined = self . nodes [ 0 ] . combinepsbt ( [ psbt1 , psbt2 ] )
finalized = self . nodes [ 0 ] . finalizepsbt ( combined ) [ ' hex ' ]
self . nodes [ 0 ] . sendrawtransaction ( finalized )
2020-11-26 01:07:45 +00:00
2019-05-01 18:28:10 -07:00
self . nodes [ 0 ] . generate ( 6 )
self . sync_all ( )
2018-08-14 21:52:16 -04:00
# Test additional args in walletcreatepsbt
# Make sure both pre-included and funded inputs
# have the correct sequence numbers based on
# replaceable arg
block_height = self . nodes [ 0 ] . getblockcount ( )
unspent = self . nodes [ 0 ] . listunspent ( ) [ 0 ]
2020-11-26 01:09:10 +00:00
psbtx_info = self . nodes [ 0 ] . walletcreatefundedpsbt ( [ { " txid " : unspent [ " txid " ] , " vout " : unspent [ " vout " ] } ] , [ { self . get_address ( confidential , 2 ) : unspent [ " amount " ] + 1 } ] , block_height + 2 , { " replaceable " : False , " add_inputs " : True } , False )
2018-08-14 21:52:16 -04:00
decoded_psbt = self . nodes [ 0 ] . decodepsbt ( psbtx_info [ " psbt " ] )
2021-01-18 17:13:27 -05:00
for psbt_in in decoded_psbt [ " inputs " ] :
assert_greater_than ( psbt_in [ " sequence " ] , MAX_BIP125_RBF_SEQUENCE )
2019-04-06 18:38:51 -04:00
assert " bip32_derivs " not in psbt_in
2021-01-18 17:13:27 -05:00
assert_equal ( decoded_psbt [ " fallback_locktime " ] , block_height + 2 )
2018-08-14 21:52:16 -04:00
2019-04-27 19:44:38 +02:00
# Same construction with only locktime set and RBF explicitly enabled
2020-11-26 01:09:10 +00:00
psbtx_info = self . nodes [ 0 ] . walletcreatefundedpsbt ( [ { " txid " : unspent [ " txid " ] , " vout " : unspent [ " vout " ] } ] , [ { self . get_address ( confidential , 2 ) : unspent [ " amount " ] + 1 } ] , block_height , { " replaceable " : True , " add_inputs " : True } , True )
2018-08-14 21:52:16 -04:00
decoded_psbt = self . nodes [ 0 ] . decodepsbt ( psbtx_info [ " psbt " ] )
2021-01-18 17:13:27 -05:00
for psbt_in in decoded_psbt [ " inputs " ] :
assert_equal ( psbt_in [ " sequence " ] , MAX_BIP125_RBF_SEQUENCE )
2018-08-24 17:03:55 -04:00
assert " bip32_derivs " in psbt_in
2021-01-18 17:13:27 -05:00
assert_equal ( decoded_psbt [ " fallback_locktime " ] , block_height )
2018-08-14 21:52:16 -04:00
# Same construction without optional arguments
2020-11-26 01:09:10 +00:00
psbtx_info = self . nodes [ 0 ] . walletcreatefundedpsbt ( [ ] , [ { self . get_address ( confidential , 2 ) : unspent [ " amount " ] + 1 } ] )
2018-08-14 21:52:16 -04:00
decoded_psbt = self . nodes [ 0 ] . decodepsbt ( psbtx_info [ " psbt " ] )
2021-01-18 17:13:27 -05:00
for psbt_in in decoded_psbt [ " inputs " ] :
assert_equal ( psbt_in [ " sequence " ] , MAX_BIP125_RBF_SEQUENCE )
2020-01-31 10:37:41 +01:00
assert " bip32_derivs " in psbt_in
2021-01-18 17:13:27 -05:00
assert_equal ( decoded_psbt [ " fallback_locktime " ] , 0 )
2018-08-14 21:52:16 -04:00
2019-07-27 19:35:07 +02:00
# Same construction without optional arguments, for a node with -walletrbf=0
unspent1 = self . nodes [ 1 ] . listunspent ( ) [ 0 ]
2019-07-12 13:30:10 +01:00
psbtx_info = self . nodes [ 1 ] . walletcreatefundedpsbt ( [ { " txid " : unspent1 [ " txid " ] , " vout " : unspent1 [ " vout " ] } ] , [ { self . nodes [ 2 ] . getnewaddress ( ) : unspent1 [ " amount " ] + 1 } ] , block_height , { " add_inputs " : True } )
2019-07-27 19:35:07 +02:00
decoded_psbt = self . nodes [ 1 ] . decodepsbt ( psbtx_info [ " psbt " ] )
2021-01-18 17:13:27 -05:00
for psbt_in in decoded_psbt [ " inputs " ] :
assert_greater_than ( psbt_in [ " sequence " ] , MAX_BIP125_RBF_SEQUENCE )
2020-01-31 10:37:41 +01:00
assert " bip32_derivs " in psbt_in
2019-07-27 19:35:07 +02:00
2018-10-03 14:41:03 +09:00
# Make sure change address wallet does not have P2SH innerscript access to results in success
# when attempting BnB coin selection
self . nodes [ 0 ] . walletcreatefundedpsbt ( [ ] , [ { self . nodes [ 2 ] . getnewaddress ( ) : unspent [ " amount " ] + 1 } ] , block_height + 2 , { " changeAddress " : self . nodes [ 1 ] . getnewaddress ( ) } , False )
2020-09-12 17:07:59 +02:00
# Make sure the wallet's change type is respected by default
small_output = { self . nodes [ 0 ] . getnewaddress ( ) : 0.1 }
psbtx_native = self . nodes [ 0 ] . walletcreatefundedpsbt ( [ ] , [ small_output ] )
self . assert_change_type ( psbtx_native , " witness_v0_keyhash " )
psbtx_legacy = self . nodes [ 1 ] . walletcreatefundedpsbt ( [ ] , [ small_output ] )
self . assert_change_type ( psbtx_legacy , " pubkeyhash " )
# Make sure the change type of the wallet can also be overwritten
psbtx_np2wkh = self . nodes [ 1 ] . walletcreatefundedpsbt ( [ ] , [ small_output ] , 0 , { " change_type " : " p2sh-segwit " } )
self . assert_change_type ( psbtx_np2wkh , " scripthash " )
2020-09-12 17:16:23 +02:00
# Make sure the change type cannot be specified if a change address is given
invalid_options = { " change_type " : " legacy " , " changeAddress " : self . nodes [ 0 ] . getnewaddress ( ) }
assert_raises_rpc_error ( - 8 , " both change address and address type options " , self . nodes [ 0 ] . walletcreatefundedpsbt , [ ] , [ small_output ] , 0 , invalid_options )
2018-10-30 00:41:19 -07:00
# Regression test for 14473 (mishandling of already-signed witness transaction):
2021-04-21 15:13:51 -04:00
psbtx_info = self . nodes [ 0 ] . walletcreatefundedpsbt ( [ { " txid " : unspent [ " txid " ] , " vout " : unspent [ " vout " ] } ] , [ { self . get_address ( confidential , 2 ) : unspent [ " amount " ] + 1 } ] , 0 , { " add_inputs " : True } )
signed = self . nodes [ 0 ] . walletprocesspsbt ( psbtx_info [ " psbt " ] )
signed_again = self . nodes [ 0 ] . walletprocesspsbt ( signed [ " psbt " ] )
2019-05-01 18:28:10 -07:00
assert_equal ( signed , signed_again )
2018-10-30 00:41:19 -07:00
# We don't care about the decode result, but decoding must succeed.
2019-05-01 18:28:10 -07:00
self . nodes [ 0 ] . decodepsbt ( signed [ " psbt " ] )
# BIP 174 tests are disabled because they don't work with CA yet. Comment the function so it doesn't flag lint as unused.
"""
def run_bip174_tests ( self ) :
2018-06-27 17:05:54 -07:00
# BIP 174 Test Vectors
# Check that unknown values are just passed through
2021-01-04 16:56:36 -05:00
unknown_psbt = " cHNidP8BAD8CAAAAAf//////////////////////////////////////////AAAAAAD/////AQAAAAAAAAAAA2oBAAAAAAAACvABAgMEBQYHCAkPAQIDBAUGBwgJCgsMDQ4PAAA= "
2018-06-27 17:05:54 -07:00
unknown_out = self . nodes [ 0 ] . walletprocesspsbt ( unknown_psbt ) [ ' psbt ' ]
assert_equal ( unknown_psbt , unknown_out )
# Open the data file
with open ( os . path . join ( os . path . dirname ( os . path . realpath ( __file__ ) ) , ' data/rpc_psbt.json ' ) , encoding = ' utf-8 ' ) as f :
d = json . load ( f )
invalids = d [ ' invalid ' ]
valids = d [ ' valid ' ]
creators = d [ ' creator ' ]
signers = d [ ' signer ' ]
combiners = d [ ' combiner ' ]
finalizers = d [ ' finalizer ' ]
extractors = d [ ' extractor ' ]
# Invalid PSBTs
for invalid in invalids :
assert_raises_rpc_error ( - 22 , " TX decode failed " , self . nodes [ 0 ] . decodepsbt , invalid )
# Valid PSBTs
for valid in valids :
self . nodes [ 0 ] . decodepsbt ( valid )
# Creator Tests
for creator in creators :
2021-01-25 16:12:11 -05:00
created_tx = self . nodes [ 0 ] . createpsbt ( inputs = creator [ ' inputs ' ] , outputs = creator [ ' outputs ' ] , psbt_version = creator [ ' version ' ] )
2018-06-27 17:05:54 -07:00
assert_equal ( created_tx , creator [ ' result ' ] )
# Signer tests
for i , signer in enumerate ( signers ) :
2019-07-16 15:33:35 -04:00
self . nodes [ 2 ] . createwallet ( wallet_name = " wallet {} " . format ( i ) )
2018-08-08 16:14:01 -07:00
wrpc = self . nodes [ 2 ] . get_wallet_rpc ( " wallet {} " . format ( i ) )
2018-06-27 17:05:54 -07:00
for key in signer [ ' privkeys ' ] :
2018-08-08 16:14:01 -07:00
wrpc . importprivkey ( key )
signed_tx = wrpc . walletprocesspsbt ( signer [ ' psbt ' ] ) [ ' psbt ' ]
2018-06-27 17:05:54 -07:00
assert_equal ( signed_tx , signer [ ' result ' ] )
# Combiner test
for combiner in combiners :
combined = self . nodes [ 2 ] . combinepsbt ( combiner [ ' combine ' ] )
assert_equal ( combined , combiner [ ' result ' ] )
2019-02-04 21:26:43 -06:00
# Empty combiner test
assert_raises_rpc_error ( - 8 , " Parameter ' txs ' cannot be empty " , self . nodes [ 0 ] . combinepsbt , [ ] )
2018-06-27 17:05:54 -07:00
# Finalizer test
for finalizer in finalizers :
finalized = self . nodes [ 2 ] . finalizepsbt ( finalizer [ ' finalize ' ] , False ) [ ' psbt ' ]
assert_equal ( finalized , finalizer [ ' result ' ] )
# Extractor test
for extractor in extractors :
extracted = self . nodes [ 2 ] . finalizepsbt ( extractor [ ' extract ' ] , True ) [ ' hex ' ]
assert_equal ( extracted , extractor [ ' result ' ] )
2018-09-20 11:43:06 -07:00
# Unload extra wallets
for i , signer in enumerate ( signers ) :
self . nodes [ 2 ] . unloadwallet ( " wallet {} " . format ( i ) )
2019-05-01 18:28:10 -07:00
"""
def run_ca_tests ( self ) :
# Confidential Assets tests
# Start by sending some coins to a nonconf address
unconf_addr_0 = self . get_address ( False , 0 )
unconf_addr_1 = self . get_address ( False , 0 )
unconf_addr_4 = self . get_address ( False , 0 )
2021-04-21 14:55:38 -04:00
rawtx = self . nodes [ 0 ] . createrawtransaction ( [ ] , [ { unconf_addr_0 : 50 } , { unconf_addr_1 : 50 } , { unconf_addr_4 : 50 } ] )
2019-05-01 18:28:10 -07:00
rawtx = self . nodes [ 0 ] . fundrawtransaction ( rawtx , { " changePosition " : 3 } ) # our outputs will be 0, 1, 2
rawtx = self . nodes [ 0 ] . blindrawtransaction ( rawtx [ ' hex ' ] )
signed_tx = self . nodes [ 0 ] . signrawtransactionwithwallet ( rawtx ) [ ' hex ' ]
txid_nonconf = self . nodes [ 0 ] . sendrawtransaction ( signed_tx )
self . nodes [ 0 ] . generate ( 1 )
self . sync_all ( )
# Now use PSBT to send some coins nonconf->nonconf
unconf_addr_2 = self . get_address ( False , 1 )
psbt = self . nodes [ 0 ] . createpsbt ( [ { " txid " : txid_nonconf , " vout " : 0 } ] , [ { unconf_addr_2 : 49.999 } , { " fee " : 0.001 } ] )
2021-04-21 15:13:51 -04:00
psbt = self . nodes [ 0 ] . walletprocesspsbt ( psbt ) [ " psbt " ]
2019-05-01 18:28:10 -07:00
tx_hex = self . nodes [ 0 ] . finalizepsbt ( psbt ) [ ' hex ' ]
txid_nonconf_2 = self . nodes [ 0 ] . sendrawtransaction ( tx_hex )
self . nodes [ 0 ] . generate ( 1 )
self . sync_all ( )
# Now send nonconf->conf (with two outputs, blinding succeeds)
conf_addr_1 = self . get_address ( True , 2 )
conf_addr_2 = self . get_address ( True , 2 )
2021-04-21 15:13:51 -04:00
psbt = self . nodes [ 0 ] . createpsbt ( [ { " txid " : txid_nonconf , " vout " : 1 } ] , [ { conf_addr_1 : 24.999 , " blinder_index " : 0 } , { conf_addr_2 : 24.999 , " blinder_index " : 0 } , { " fee " : 0.002 } ] )
psbt = self . nodes [ 0 ] . walletprocesspsbt ( psbt ) [ ' psbt ' ]
2019-05-01 18:28:10 -07:00
hex_tx = self . nodes [ 0 ] . finalizepsbt ( psbt ) [ ' hex ' ]
assert_equal ( self . num_blinded_outputs ( hex_tx ) , 2 )
txid_conf_2 = self . nodes [ 0 ] . sendrawtransaction ( hex_tx )
self . nodes [ 0 ] . generate ( 1 )
self . sync_all ( )
# Try to send conf->nonconf: This will fail because we can't balance the blinders
unconf_addr_3 = self . get_address ( False , 0 )
psbt = self . nodes [ 2 ] . createpsbt ( [ { " txid " : txid_conf_2 , " vout " : 0 } ] , [ { unconf_addr_3 : 24.998 } , { " fee " : 0.001 } ] )
2021-04-21 15:13:51 -04:00
assert_raises_rpc_error ( - 25 , " Transaction values or blinders are not balanced " , self . nodes [ 2 ] . walletprocesspsbt , psbt )
2019-05-01 18:28:10 -07:00
# Try to send conf->(nonconf + conf), so we have a conf output to balance blinders
conf_addr_3 = self . get_address ( True , 0 )
2021-04-21 15:13:51 -04:00
psbt = self . nodes [ 2 ] . createpsbt ( [ { " txid " : txid_conf_2 , " vout " : 0 } ] , [ { unconf_addr_3 : 10 } , { conf_addr_3 : 14.998 , " blinder_index " : 0 } , { " fee " : 0.001 } ] )
psbt = self . nodes [ 2 ] . walletprocesspsbt ( psbt ) [ ' psbt ' ]
2019-05-01 18:28:10 -07:00
hex_tx = self . nodes [ 2 ] . finalizepsbt ( psbt ) [ ' hex ' ]
assert_equal ( self . num_blinded_outputs ( hex_tx ) , 1 )
self . nodes [ 2 ] . sendrawtransaction ( hex_tx )
self . nodes [ 0 ] . generate ( 1 )
self . sync_all ( )
# Try to send conf->conf
conf_addr_4 = self . get_address ( True , 0 )
2021-04-21 15:13:51 -04:00
psbt = self . nodes [ 2 ] . createpsbt ( [ { " txid " : txid_conf_2 , " vout " : 1 } ] , [ { conf_addr_4 : 24.998 , " blinder_index " : 0 } , { " fee " : 0.001 } ] )
psbt = self . nodes [ 2 ] . walletprocesspsbt ( psbt ) [ ' psbt ' ]
2019-05-01 18:28:10 -07:00
hex_tx = self . nodes [ 2 ] . finalizepsbt ( psbt ) [ ' hex ' ]
assert_equal ( self . num_blinded_outputs ( hex_tx ) , 1 )
self . nodes [ 2 ] . sendrawtransaction ( hex_tx )
self . nodes [ 0 ] . generate ( 1 )
self . sync_all ( )
# Try to send nonconf->(nonconf + conf + conf) -- two conf to make blinders balance
nonconf_addr_5 = self . get_address ( False , 1 )
conf_addr_5 = self . get_address ( True , 1 )
conf_addr_6 = self . get_address ( True , 2 )
2021-04-21 15:13:51 -04:00
psbt = self . nodes [ 0 ] . createpsbt ( [ { " txid " : txid_nonconf , " vout " : 2 } ] , [ { nonconf_addr_5 : 24.999 } , { conf_addr_5 : 14.999 , " blinder_index " : 0 } , { conf_addr_6 : 10 , " blinder_index " : 0 } , { " fee " : 0.002 } ] )
psbt = self . nodes [ 0 ] . walletprocesspsbt ( psbt ) [ ' psbt ' ]
2019-05-01 18:28:10 -07:00
hex_tx = self . nodes [ 0 ] . finalizepsbt ( psbt ) [ ' hex ' ]
assert_equal ( self . num_blinded_outputs ( hex_tx ) , 2 )
self . nodes [ 0 ] . sendrawtransaction ( hex_tx )
self . nodes [ 0 ] . generate ( 1 )
self . sync_all ( )
def run_test ( self ) :
self . nodes [ 0 ] . generate ( 200 )
self . sync_all ( )
# Run all the pre-Elements, tests first with non-confidential addresses, then again with confidential addresses
self . run_basic_tests ( False )
self . run_basic_tests ( True )
# BIP 174 test vectors are disabled, because they have embedded serialized CTransactions, and
# the transaction serialization format changed in Elements so none of them work
#self.run_bip174_tests()
# Some Confidential-Assets-specific tests
self . run_ca_tests ( )
2018-09-20 11:43:06 -07:00
2020-06-04 23:43:43 -04:00
# TODO: Re-enable this for segwit v1
# self.test_utxo_conversion()
2018-09-20 11:43:06 -07:00
2018-11-08 10:08:46 -05:00
# Test that psbts with p2pkh outputs are created properly
p2pkh = self . nodes [ 0 ] . getnewaddress ( address_type = ' legacy ' )
psbt = self . nodes [ 1 ] . walletcreatefundedpsbt ( [ ] , [ { p2pkh : 1 } ] , 0 , { " includeWatching " : True } , True )
self . nodes [ 0 ] . decodepsbt ( psbt [ ' psbt ' ] )
2018-06-27 17:05:54 -07:00
2019-01-29 21:32:38 -08:00
# Test decoding error: invalid base64
assert_raises_rpc_error ( - 22 , " TX decode failed invalid base64 " , self . nodes [ 0 ] . decodepsbt , " ;definitely not base64; " )
2018-07-20 17:08:25 -07:00
# Send to all types of addresses
addr1 = self . nodes [ 1 ] . getnewaddress ( " " , " bech32 " )
txid1 = self . nodes [ 0 ] . sendtoaddress ( addr1 , 11 )
vout1 = find_output ( self . nodes [ 0 ] , txid1 , 11 )
addr2 = self . nodes [ 1 ] . getnewaddress ( " " , " legacy " )
txid2 = self . nodes [ 0 ] . sendtoaddress ( addr2 , 11 )
vout2 = find_output ( self . nodes [ 0 ] , txid2 , 11 )
addr3 = self . nodes [ 1 ] . getnewaddress ( " " , " p2sh-segwit " )
txid3 = self . nodes [ 0 ] . sendtoaddress ( addr3 , 11 )
vout3 = find_output ( self . nodes [ 0 ] , txid3 , 11 )
self . sync_all ( )
2021-01-25 16:12:11 -05:00
psbt_v2_required_keys = [ " previous_vout " , " sequence " , " previous_txid " ]
2019-02-16 14:59:16 -08:00
def test_psbt_input_keys ( psbt_input , keys ) :
""" Check that the psbt input has only the expected keys. """
assert_equal ( set ( keys ) , set ( psbt_input . keys ( ) ) )
# Create a PSBT. None of the inputs are filled initially
2021-04-21 14:55:38 -04:00
psbt = self . nodes [ 1 ] . createpsbt ( [ { " txid " : txid1 , " vout " : vout1 } , { " txid " : txid2 , " vout " : vout2 } , { " txid " : txid3 , " vout " : vout3 } ] , [ { self . nodes [ 0 ] . getnewaddress ( ) : 32.999 } ] )
2018-07-20 17:08:25 -07:00
decoded = self . nodes [ 1 ] . decodepsbt ( psbt )
2021-01-25 16:12:11 -05:00
test_psbt_input_keys ( decoded [ ' inputs ' ] [ 0 ] , psbt_v2_required_keys )
test_psbt_input_keys ( decoded [ ' inputs ' ] [ 1 ] , psbt_v2_required_keys )
test_psbt_input_keys ( decoded [ ' inputs ' ] [ 2 ] , psbt_v2_required_keys )
2019-02-16 14:59:16 -08:00
# Update a PSBT with UTXOs from the node
# Bech32 inputs should be filled with witness UTXO. Other inputs should not be filled because they are non-witness
2018-07-20 17:08:25 -07:00
updated = self . nodes [ 1 ] . utxoupdatepsbt ( psbt )
decoded = self . nodes [ 1 ] . decodepsbt ( updated )
2021-01-25 16:12:11 -05:00
test_psbt_input_keys ( decoded [ ' inputs ' ] [ 0 ] , psbt_v2_required_keys + [ ' witness_utxo ' ] )
test_psbt_input_keys ( decoded [ ' inputs ' ] [ 1 ] , psbt_v2_required_keys )
test_psbt_input_keys ( decoded [ ' inputs ' ] [ 2 ] , psbt_v2_required_keys )
2019-02-16 14:59:16 -08:00
# Try again, now while providing descriptors, making P2SH-segwit work, and causing bip32_derivs and redeem_script to be filled in
descs = [ self . nodes [ 1 ] . getaddressinfo ( addr ) [ ' desc ' ] for addr in [ addr1 , addr2 , addr3 ] ]
2019-07-02 18:34:18 +01:00
updated = self . nodes [ 1 ] . utxoupdatepsbt ( psbt = psbt , descriptors = descs )
2019-02-16 14:59:16 -08:00
decoded = self . nodes [ 1 ] . decodepsbt ( updated )
2021-01-25 16:12:11 -05:00
test_psbt_input_keys ( decoded [ ' inputs ' ] [ 0 ] , psbt_v2_required_keys + [ ' witness_utxo ' , ' bip32_derivs ' ] )
test_psbt_input_keys ( decoded [ ' inputs ' ] [ 1 ] , psbt_v2_required_keys )
test_psbt_input_keys ( decoded [ ' inputs ' ] [ 2 ] , psbt_v2_required_keys + [ ' witness_utxo ' , ' bip32_derivs ' , ' redeem_script ' ] )
2021-05-05 18:05:54 -04:00
# Cannot create PSBTv0
assert_raises_rpc_error ( - 8 , " The PSBT version can only be 2 " , self . nodes [ 0 ] . createpsbt , [ { " txid " : txid1 , " vout " : vout1 } ] , [ { self . nodes [ 0 ] . getnewaddress ( ) : Decimal ( ' 10.999 ' ) } ] , 0 , True , 0 )
"""
# TODO: joinpsbts is disabled for PSBTv2s
2021-01-25 16:12:11 -05:00
# Cannot join PSBTv2s
2021-05-05 18:05:54 -04:00
psbt1 = self . nodes [ 1 ] . createpsbt ( inputs = [ { " txid " : txid1 , " vout " : vout1 } ] , outputs = [ { self . nodes [ 0 ] . getnewaddress ( ) : Decimal ( ' 10.999 ' ) } ] , psbt_version = 0 )
psbt2 = self . nodes [ 1 ] . createpsbt ( inputs = [ { " txid " : txid1 , " vout " : vout1 } ] , outputs = [ { self . nodes [ 0 ] . getnewaddress ( ) : Decimal ( ' 10.999 ' ) } ] , psbt_version = 2 )
2021-01-25 16:12:11 -05:00
assert_raises_rpc_error ( - 8 , " joinpsbts only operates on version 0 PSBTs " , self . nodes [ 1 ] . joinpsbts , [ psbt1 , psbt2 ] )
2018-07-20 17:08:25 -07:00
2018-07-20 18:24:16 -07:00
# Two PSBTs with a common input should not be joinable
2021-05-05 18:05:54 -04:00
psbt2 = self . nodes [ 1 ] . createpsbt ( inputs = [ { " txid " : txid1 , " vout " : vout1 } ] , outputs = [ { self . nodes [ 0 ] . getnewaddress ( ) : Decimal ( ' 10.999 ' ) } ] , psbt_version = 0 )
2021-01-25 16:12:11 -05:00
assert_raises_rpc_error ( - 8 , " exists in multiple PSBTs " , self . nodes [ 1 ] . joinpsbts , [ psbt1 , psbt2 ] )
2018-07-20 18:24:16 -07:00
# Join two distinct PSBTs
2021-05-05 18:05:54 -04:00
psbt1 = self . nodes [ 1 ] . createpsbt ( inputs = [ { " txid " : txid1 , " vout " : vout1 } , { " txid " : txid2 , " vout " : vout2 } , { " txid " : txid3 , " vout " : vout3 } ] , outputs = [ { self . nodes [ 0 ] . getnewaddress ( ) : 32.999 } ] , psbt_version = 0 )
2018-07-20 18:24:16 -07:00
addr4 = self . nodes [ 1 ] . getnewaddress ( " " , " p2sh-segwit " )
txid4 = self . nodes [ 0 ] . sendtoaddress ( addr4 , 5 )
vout4 = find_output ( self . nodes [ 0 ] , txid4 , 5 )
self . nodes [ 0 ] . generate ( 6 )
self . sync_all ( )
2021-05-05 18:05:54 -04:00
psbt2 = self . nodes [ 1 ] . createpsbt ( inputs = [ { " txid " : txid4 , " vout " : vout4 } ] , outputs = [ { self . nodes [ 0 ] . getnewaddress ( ) : Decimal ( ' 4.999 ' ) } ] , psbt_version = 0 )
2018-07-20 18:24:16 -07:00
psbt2 = self . nodes [ 1 ] . walletprocesspsbt ( psbt2 ) [ ' psbt ' ]
psbt2_decoded = self . nodes [ 0 ] . decodepsbt ( psbt2 )
assert " final_scriptwitness " in psbt2_decoded [ ' inputs ' ] [ 0 ] and " final_scriptSig " in psbt2_decoded [ ' inputs ' ] [ 0 ]
2021-01-25 16:12:11 -05:00
joined = self . nodes [ 0 ] . joinpsbts ( [ psbt1 , psbt2 ] )
2018-07-20 18:24:16 -07:00
joined_decoded = self . nodes [ 0 ] . decodepsbt ( joined )
2021-01-25 16:12:11 -05:00
assert_equal ( len ( joined_decoded [ ' inputs ' ] ) , 4 )
assert_equal ( len ( joined_decoded [ ' outputs ' ] ) , 2 )
assert " final_scriptwitness " not in joined_decoded [ ' inputs ' ] [ 3 ]
assert " final_scriptSig " not in joined_decoded [ ' inputs ' ] [ 3 ]
2018-07-20 17:08:25 -07:00
2019-08-14 14:29:55 -04:00
# Check that joining shuffles the inputs and outputs
# 10 attempts should be enough to get a shuffled join
shuffled = False
2020-08-03 01:10:56 +02:00
for _ in range ( 10 ) :
2021-01-25 16:12:11 -05:00
shuffled_joined = self . nodes [ 0 ] . joinpsbts ( [ psbt1 , psbt2 ] )
2019-08-14 14:29:55 -04:00
shuffled | = joined != shuffled_joined
if shuffled :
break
assert shuffled
2021-05-05 18:05:54 -04:00
"""
2019-08-14 14:29:55 -04:00
2018-07-31 17:58:01 -07:00
# Newly created PSBT needs UTXOs and updating
addr = self . nodes [ 1 ] . getnewaddress ( " " , " p2sh-segwit " )
txid = self . nodes [ 0 ] . sendtoaddress ( addr , 7 )
addrinfo = self . nodes [ 1 ] . getaddressinfo ( addr )
2019-02-13 19:22:40 -08:00
blockhash = self . nodes [ 0 ] . generate ( 6 ) [ 0 ]
2018-07-31 17:58:01 -07:00
self . sync_all ( )
2019-02-13 19:22:40 -08:00
vout = find_output ( self . nodes [ 0 ] , txid , 7 , blockhash = blockhash )
2021-05-12 18:53:00 -04:00
psbt = self . nodes [ 1 ] . createpsbt ( [ { " txid " : txid , " vout " : vout } ] , [ { self . nodes [ 0 ] . getnewaddress ( " " , " p2sh-segwit " ) : Decimal ( ' 6.999 ' ) } , { " fee " : 0.001 } ] )
2018-07-31 17:58:01 -07:00
analyzed = self . nodes [ 0 ] . analyzepsbt ( psbt )
assert not analyzed [ ' inputs ' ] [ 0 ] [ ' has_utxo ' ] and not analyzed [ ' inputs ' ] [ 0 ] [ ' is_final ' ] and analyzed [ ' inputs ' ] [ 0 ] [ ' next ' ] == ' updater ' and analyzed [ ' next ' ] == ' updater '
# After update with wallet, only needs signing
updated = self . nodes [ 1 ] . walletprocesspsbt ( psbt , False , ' ALL ' , True ) [ ' psbt ' ]
analyzed = self . nodes [ 0 ] . analyzepsbt ( updated )
assert analyzed [ ' inputs ' ] [ 0 ] [ ' has_utxo ' ] and not analyzed [ ' inputs ' ] [ 0 ] [ ' is_final ' ] and analyzed [ ' inputs ' ] [ 0 ] [ ' next ' ] == ' signer ' and analyzed [ ' next ' ] == ' signer ' and analyzed [ ' inputs ' ] [ 0 ] [ ' missing ' ] [ ' signatures ' ] [ 0 ] == addrinfo [ ' embedded ' ] [ ' witness_program ' ]
# Check fee and size things
2021-05-12 18:53:00 -04:00
assert_equal ( analyzed [ ' fee ' ] , Decimal ( ' 0.001 ' ) )
assert_equal ( analyzed [ ' estimated_vsize ' ] , 215 )
assert_equal ( analyzed [ ' estimated_feerate ' ] , Decimal ( ' 0.00465116 ' ) )
2018-07-31 17:58:01 -07:00
# After signing and finalizing, needs extracting
signed = self . nodes [ 1 ] . walletprocesspsbt ( updated ) [ ' psbt ' ]
analyzed = self . nodes [ 0 ] . analyzepsbt ( signed )
assert analyzed [ ' inputs ' ] [ 0 ] [ ' has_utxo ' ] and analyzed [ ' inputs ' ] [ 0 ] [ ' is_final ' ] and analyzed [ ' next ' ] == ' extractor '
2018-07-20 17:08:25 -07:00
2019-11-19 14:54:13 -05:00
self . log . info ( " PSBT spending unspendable outputs should have error message and Creator as next " )
2021-05-12 18:53:00 -04:00
analysis = self . nodes [ 0 ] . analyzepsbt ( " cHNldP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEDAfsEAgAAAAABAUMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAvrwgAAF2oUt/X69ELjeX2nTof+fZ10l+OyAokDAQ4gWOh6IbVtrwwjvo5wcEVsM298uqXIdXkk9UWIe7Kr3XUBDwQAAAAAARAE/////wABAUMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAvrwgAAF2oUt/X69ELjeX2nTof+fZ10l+OyAokDAQ4gg40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BDwQBAAAAARAE/////wABBAMAAAABAwgA4fUFAAAAAAf8BHBzZXQCICMPT11LfG+oRYBu5PZ3E0WeG2no5g/O4uSUDHoNXeGyAAEEA/9RAAEDCADh9QUAAAAAB/wEcHNldAIgIw9PXUt8b6hFgG7k9ncTRZ4baejmD87i5JQMeg1d4bIAAQQAAQMIAOH1BQAAAAAH/ARwc2V0AiAjD09dS3xvqEWAbuT2dxNFnhtp6OYPzuLklAx6DV3hsgA= " )
2019-11-19 14:54:13 -05:00
assert_equal ( analysis [ ' next ' ] , ' creator ' )
assert_equal ( analysis [ ' error ' ] , ' PSBT is not valid. Input 0 spends unspendable output ' )
2019-10-15 17:15:22 -04:00
self . log . info ( " PSBT with invalid values should have error message and Creator as next " )
2021-05-12 18:53:00 -04:00
analysis = self . nodes [ 0 ] . analyzepsbt ( " cHNldP8BAgQCAAAAAQMEAAAAAAEEAQEBBQEDAfsEAgAAAAABAUIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAfQ42qBgAAAFgAUlQO3F/Y8ejrjUcQ4E4Ai8Uw1OvYBDiDwNNARYAJurafOkaMMB+gTCJkDS+c11HE0/e16Cxs9AQEPBAAAAAABEAT/////AAEEFgAUKNw0x8HRctAgmvoevm4u1SbN7XIBAwgA+QKVAAAAAAf8BHBzZXQCICMPT11LfG+oRYBu5PZ3E0WeG2no5g/O4uSUDHoNXeGyAAEEFgAU9yTiAXuIvg0vjC19EAqBBuCGJNQBAwj87QKVAAAAAAf8BHBzZXQCICMPT11LfG+oRYBu5PZ3E0WeG2no5g/O4uSUDHoNXeGyAAEEAAEDCBAnAAAAAAAAB/wEcHNldAIgIw9PXUt8b6hFgG7k9ncTRZ4baejmD87i5JQMeg1d4bIA " )
2019-10-15 17:15:22 -04:00
assert_equal ( analysis [ ' next ' ] , ' creator ' )
assert_equal ( analysis [ ' error ' ] , ' PSBT is not valid. Input 0 has invalid value ' )
2020-02-28 11:27:13 -05:00
self . log . info ( " PSBT with signed, but not finalized, inputs should have Finalizer as next " )
2021-05-12 18:53:00 -04:00
analysis = self . nodes [ 0 ] . analyzepsbt ( " cHNldP8BAgQCAAAAAQMEAAAAAAEEAQEBBQECAfsEAgAAAAABAP1GAQIAAAAAAtpPG2HNaQ7g1RhD88FfUIfJC09s/JOG0O51k1yf+BOGAAAAAAD9////B3dy8WfLRW/bNMpUigt/fepavcJqGEcCLA5HiRruhoABAAAAAP3///8DASMPT11LfG+oRYBu5PZ3E0WeG2no5g/O4uSUDHoNXeGyAQAAAAApuScAABepFI3c8Pl2L3+zDBFaVnU/fbC7u8YXhwrU7XTaIgX0Ui+O3yyCMz3qIu5eWWqhkpvPSTFUT4FBmQmTF2BnoPq5+0AfEsZypoPR7bm/U3+hxwcRJf4goV/3qwNo5VLiic5ce1dZCSUfff5XpRUYgb+WVEDRuomG9fTTbhYAFMThhARjTBZ+SqXAUJy8DC2ynay7ASMPT11LfG+oRYBu5PZ3E0WeG2no5g/O4uSUDHoNXeGyAQAAAAAAAHFwAAC0AQAAAQFDASMPT11LfG+oRYBu5PZ3E0WeG2no5g/O4uSUDHoNXeGyAQAAAAApuScAABepFI3c8Pl2L3+zDBFaVnU/fbC7u8YXhwEEFgAUNZYRdEGQwHLFV2omDyyxxA2RJjgiAgLAsYuL3ObwGidkudS4ZlEL0ZW84Xn7ht6BPnQ1aGrPGEcwRAIgDtAPQnVgJWk2NQfCjnZ4K1gJH82zWfJaPnMYxpBhU1wCIAMuStVULIORnPuLseJPLhBLNzczD72wqBzi7GjGMnqfAQEOINut3V3yAGie+x4icl/6hWw9TuDiUk5fuXQWHKy14+ARAQ8EAAAAAAEQBP////8AAQQXqRSEp5LBkVEYljQOEsxhElkADN7J+ocBAwhgoLcpAAAAAAf8BHBzZXQCICMPT11LfG+oRYBu5PZ3E0WeG2no5g/O4uSUDHoNXeGyAAEEAAEDCKCGAQAAAAAAB/wEcHNldAIgIw9PXUt8b6hFgG7k9ncTRZ4baejmD87i5JQMeg1d4bIA " )
2020-02-28 11:27:13 -05:00
assert_equal ( analysis [ ' next ' ] , ' finalizer ' )
2021-05-12 18:53:00 -04:00
analysis = self . nodes [ 0 ] . analyzepsbt ( " cHNldP8BAgQCAAAAAQMEAAAAAAEEAQEBBQEDAfsEAgAAAAABDiDwNNARYAJurafOkaMMB+gTCJkDS+c11HE0/e16Cxs9AQEPBAAAAAABEAT/////AAEEFgAUKNw0x8HRctAgmvoevm4u1SbN7XIBAwgAgIFq49AHAAf8BHBzZXQCICMPT11LfG+oRYBu5PZ3E0WeG2no5g/O4uSUDHoNXeGyAAEEFgAU9yTiAXuIvg0vjC19EAqBBuCGJNQBAwj87QKVAAAAAAf8BHBzZXQCICMPT11LfG+oRYBu5PZ3E0WeG2no5g/O4uSUDHoNXeGyAAEEAAEDCBAnAAAAAAAAB/wEcHNldAIgIw9PXUt8b6hFgG7k9ncTRZ4baejmD87i5JQMeg1d4bIA " )
2019-10-15 17:15:22 -04:00
assert_equal ( analysis [ ' next ' ] , ' creator ' )
assert_equal ( analysis [ ' error ' ] , ' PSBT is not valid. Output amount invalid ' )
2021-05-12 18:53:00 -04:00
analysis = self . nodes [ 0 ] . analyzepsbt ( " cHNldP8BAgQCAAAAAQMEAAAAAAEEAQEBBQEDAfsEAgAAAAABAKICAAAAAAHH6k+xEgicvmA3NdivY741Mkb1NOcXWr0NNl6hrR/WbgAAAEAA/////wIBIw9PXUt8b6hFgG7k9ncTRZ4baejmD87i5JQMeg1d4bIBAAAAAlQLx/QAFgAUTwXL7rzz4++YOM52QVixAcDETlwBIw9PXUt8b6hFgG7k9ncTRZ4baejmD87i5JQMeg1d4bIBAAAAAAAAHAwAAAAAAAABAUIBIw9PXUt8b6hFgG7k9ncTRZ4baejmD87i5JQMeg1d4bIBAAAAAlQLx/QAFgAUTwXL7rzz4++YOM52QVixAcDETlwBDiBzQYOL5jKoCOgksiRTvw0zfNZ+6QwsBsCZRoqc3PHoygEPBAIAAAABEAT9////ACICAt/pWo4sGJOHmHcQ8znTQCNWAZbCdkdGx3JaRfNNtbr6EAm9XegAAACAAQAAgEgAAIABBBYAFCuDv44MRC5Qj+VetbjoeiSUS5p3AQMIzLoIvwEAAAAH/ARwc2V0AiAjD09dS3xvqEWAbuT2dxNFnhtp6OYPzuLklAx6DV3hsgf8BHBzZXQIBAAAAAAAAQQWABSNJKzjaUb3uOxixsvh1GGE3fW7zQEDCAD5ApUAAAAAB/wEcHNldAIgIw9PXUt8b6hFgG7k9ncTRZ4baejmD87i5JQMeg1d4bIH/ARwc2V0CAQAAAAAAAEEAAEDCCgUAAAAAAAAB/wEcHNldAIgIw9PXUt8b6hFgG7k9ncTRZ4baejmD87i5JQMeg1d4bIH/ARwc2V0CAQAAAAAAA== " )
2019-10-15 17:26:46 -04:00
assert_equal ( analysis [ ' next ' ] , ' creator ' )
assert_equal ( analysis [ ' error ' ] , ' PSBT is not valid. Input 0 specifies invalid prevout ' )
2021-05-12 18:53:00 -04:00
assert_raises_rpc_error ( - 25 , ' Inputs missing or spent ' , self . nodes [ 0 ] . walletprocesspsbt , " cHNldP8BAgQCAAAAAQMEAAAAAAEEAQEBBQEDAfsEAgAAAAABAKICAAAAAAHH6k+xEgicvmA3NdivY741Mkb1NOcXWr0NNl6hrR/WbgAAAEAA/////wIBIw9PXUt8b6hFgG7k9ncTRZ4baejmD87i5JQMeg1d4bIBAAAAAlQLx/QAFgAUTwXL7rzz4++YOM52QVixAcDETlwBIw9PXUt8b6hFgG7k9ncTRZ4baejmD87i5JQMeg1d4bIBAAAAAAAAHAwAAAAAAAABDiBzQYOL5jKoCOgksiRTvw0zfNZ+6QwsBsCZRoqc3PHoygEPBAIAAAABEAT9////ACICAt/pWo4sGJOHmHcQ8znTQCNWAZbCdkdGx3JaRfNNtbr6EAm9XegAAACAAQAAgEgAAIABBBYAFCuDv44MRC5Qj+VetbjoeiSUS5p3AQMIzLoIvwEAAAAH/ARwc2V0AiAjD09dS3xvqEWAbuT2dxNFnhtp6OYPzuLklAx6DV3hsgf8BHBzZXQIBAAAAAAAAQQWABSNJKzjaUb3uOxixsvh1GGE3fW7zQEDCAD5ApUAAAAAB/wEcHNldAIgIw9PXUt8b6hFgG7k9ncTRZ4baejmD87i5JQMeg1d4bIH/ARwc2V0CAQAAAAAAAEEAAEDCCgUAAAAAAAAB/wEcHNldAIgIw9PXUt8b6hFgG7k9ncTRZ4baejmD87i5JQMeg1d4bIH/ARwc2V0CAQAAAAAAA== " )
2019-10-15 17:26:46 -04:00
2018-06-27 17:05:54 -07:00
if __name__ == ' __main__ ' :
PSBTTest ( ) . main ( )