rpc_psbt.py raw

   1  #!/usr/bin/env python3
   2  # Copyright (c) 2018-present The Bitcoin Core developers
   3  # Distributed under the MIT software license, see the accompanying
   4  # file COPYING or http://www.opensource.org/licenses/mit-license.php.
   5  """Test the Partially Signed Transaction RPCs.
   6  """
   7  from decimal import Decimal
   8  from itertools import product
   9  from random import randbytes
  10  
  11  from test_framework.blocktools import (
  12      MAX_STANDARD_TX_WEIGHT,
  13  )
  14  from test_framework.descriptors import descsum_create
  15  from test_framework.key import H_POINT
  16  from test_framework.messages import (
  17      COutPoint,
  18      CTransaction,
  19      CTxIn,
  20      CTxOut,
  21      MAX_BIP125_RBF_SEQUENCE,
  22      WITNESS_SCALE_FACTOR,
  23      ser_compact_size,
  24  )
  25  from test_framework.psbt import (
  26      PSBT,
  27      PSBTMap,
  28      PSBT_GLOBAL_PROPRIETARY,
  29      PSBT_GLOBAL_UNSIGNED_TX,
  30      PSBT_GLOBAL_VERSION,
  31      PSBT_IN_RIPEMD160,
  32      PSBT_IN_SHA256,
  33      PSBT_IN_SIGHASH_TYPE,
  34      PSBT_IN_HASH160,
  35      PSBT_IN_HASH256,
  36      PSBT_IN_MUSIG2_PARTIAL_SIG,
  37      PSBT_IN_MUSIG2_PARTICIPANT_PUBKEYS,
  38      PSBT_IN_MUSIG2_PUB_NONCE,
  39      PSBT_IN_NON_WITNESS_UTXO,
  40      PSBT_IN_PROPRIETARY,
  41      PSBT_IN_WITNESS_UTXO,
  42      PSBT_OUT_MUSIG2_PARTICIPANT_PUBKEYS,
  43      PSBT_OUT_PROPRIETARY,
  44      PSBT_OUT_TAP_TREE,
  45      PSBT_OUT_SCRIPT,
  46  )
  47  from test_framework.script import CScript, OP_TRUE, SIGHASH_ALL, SIGHASH_ANYONECANPAY
  48  from test_framework.script_util import MIN_STANDARD_TX_NONWITNESS_SIZE
  49  from test_framework.test_framework import BitcoinTestFramework
  50  from test_framework.util import (
  51      assert_not_equal,
  52      assert_approx,
  53      assert_equal,
  54      assert_greater_than,
  55      assert_greater_than_or_equal,
  56      assert_raises_rpc_error,
  57      find_vout_for_address,
  58      wallet_importprivkey,
  59  )
  60  from test_framework.wallet_util import (
  61      calculate_input_weight,
  62      generate_keypair,
  63      get_generate_key,
  64  )
  65  
  66  import json
  67  import os
  68  
  69  
  70  class PSBTTest(BitcoinTestFramework):
  71      def set_test_params(self):
  72          self.num_nodes = 3
  73          self.extra_args = [
  74              [],
  75              ["-changetype=legacy"],
  76              []
  77          ]
  78          # whitelist peers to speed up tx relay / mempool sync
  79          for args in self.extra_args:
  80              args.append("-whitelist=noban@127.0.0.1")
  81  
  82      def skip_test_if_missing_module(self):
  83          self.skip_if_no_wallet()
  84  
  85      @staticmethod
  86      def create_psbt(inputs=None, outputs=None):
  87          if inputs is None:
  88              inputs = {}
  89          if outputs is None:
  90              outputs = {}
  91          tx = CTransaction()
  92          tx.vin = [CTxIn(outpoint=COutPoint(hash=0, n=0))]
  93          tx.vout = [CTxOut(nValue=1, scriptPubKey=CScript([OP_TRUE]))]
  94  
  95          # https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki#specification
  96          psbt = PSBT()
  97          # global map
  98          psbt.g = PSBTMap({PSBT_GLOBAL_UNSIGNED_TX: tx.serialize()})
  99          # input map
 100          psbt.i = [PSBTMap(inputs)]
 101          # output map
 102          psbt.o = [PSBTMap(outputs)]
 103          return psbt
 104  
 105      def test_psbt_incomplete_after_invalid_modification(self):
 106          self.log.info("Check that PSBT is correctly marked as incomplete after invalid modification")
 107          node = self.nodes[2]
 108          wallet = node.get_wallet_rpc(self.default_wallet_name)
 109          address = wallet.getnewaddress()
 110          wallet.sendtoaddress(address=address, amount=1.0)
 111          self.generate(node, nblocks=1)
 112  
 113          utxos = wallet.listunspent(addresses=[address])
 114          psbt = wallet.createpsbt([{"txid": utxos[0]["txid"], "vout": utxos[0]["vout"]}], [{wallet.getnewaddress(): 0.9999}])
 115          signed_psbt = wallet.walletprocesspsbt(psbt)["psbt"]
 116  
 117          # Modify the raw transaction by changing the output address, so the signature is no longer valid
 118          signed_psbt_obj = PSBT.from_base64(signed_psbt)
 119          signed_psbt_obj.o[0].map[PSBT_OUT_SCRIPT] = CScript([OP_TRUE])
 120  
 121          # Check that the walletprocesspsbt call succeeds but also recognizes that the transaction is not complete
 122          signed_psbt_incomplete = wallet.walletprocesspsbt(psbt=signed_psbt_obj.to_base64(), finalize=False)
 123          assert_equal(signed_psbt_incomplete["complete"], False)
 124  
 125      def test_utxo_conversion(self):
 126          self.log.info("Check that non-witness UTXOs are removed for segwit v1+ inputs")
 127          mining_node = self.nodes[2]
 128          offline_node = self.nodes[0]
 129          online_node = self.nodes[1]
 130  
 131          # Disconnect offline node from others
 132          # Topology of test network is linear, so this one call is enough
 133          self.disconnect_nodes(0, 1)
 134  
 135          # Create watchonly on online_node
 136          online_node.createwallet(wallet_name='wonline', disable_private_keys=True)
 137          wonline = online_node.get_wallet_rpc('wonline')
 138          w2 = online_node.get_wallet_rpc(self.default_wallet_name)
 139  
 140          # Mine a transaction that credits the offline address
 141          offline_addr = offline_node.getnewaddress(address_type="bech32m")
 142          online_addr = w2.getnewaddress(address_type="bech32m")
 143          import_res = wonline.importdescriptors([{"desc": offline_node.getaddressinfo(offline_addr)["desc"], "timestamp": "now"}])
 144          assert_equal(import_res[0]["success"], True)
 145          mining_wallet = mining_node.get_wallet_rpc(self.default_wallet_name)
 146          mining_wallet.sendtoaddress(address=offline_addr, amount=1.0)
 147          self.generate(mining_node, nblocks=1, sync_fun=lambda: self.sync_all([online_node, mining_node]))
 148  
 149          # Construct an unsigned PSBT on the online node
 150          utxos = wonline.listunspent(addresses=[offline_addr])
 151          raw = wonline.createrawtransaction([{"txid":utxos[0]["txid"], "vout":utxos[0]["vout"]}],[{online_addr:0.9999}])
 152          psbt = wonline.walletprocesspsbt(online_node.converttopsbt(raw))["psbt"]
 153          assert "not_witness_utxo" not in mining_node.decodepsbt(psbt)["inputs"][0]
 154  
 155          # add non-witness UTXO manually
 156          psbt_new = PSBT.from_base64(psbt)
 157          prev_tx = wonline.gettransaction(utxos[0]["txid"])["hex"]
 158          psbt_new.i[0].map[PSBT_IN_NON_WITNESS_UTXO] = bytes.fromhex(prev_tx)
 159          assert "non_witness_utxo" in mining_node.decodepsbt(psbt_new.to_base64())["inputs"][0]
 160  
 161          # Have the offline node sign the PSBT (which will remove the non-witness UTXO)
 162          signed_psbt = offline_node.walletprocesspsbt(psbt_new.to_base64())
 163          assert "non_witness_utxo" not in mining_node.decodepsbt(signed_psbt["psbt"])["inputs"][0]
 164  
 165          # Make sure we can mine the resulting transaction
 166          txid = mining_node.sendrawtransaction(signed_psbt["hex"])
 167          self.generate(mining_node, nblocks=1, sync_fun=lambda: self.sync_all([online_node, mining_node]))
 168          assert_equal(online_node.gettxout(txid,0)["confirmations"], 1)
 169  
 170          wonline.unloadwallet()
 171  
 172          # Reconnect
 173          self.connect_nodes(1, 0)
 174          self.connect_nodes(0, 2)
 175  
 176      def test_input_confs_control(self):
 177          self.nodes[0].createwallet("minconf")
 178          wallet = self.nodes[0].get_wallet_rpc("minconf")
 179  
 180          # Fund the wallet with different chain heights
 181          for _ in range(2):
 182              self.nodes[1].sendmany("", {wallet.getnewaddress():1, wallet.getnewaddress():1})
 183              self.generate(self.nodes[1], 1)
 184  
 185          unconfirmed_txid = wallet.sendtoaddress(wallet.getnewaddress(), 0.5)
 186  
 187          self.log.info("Crafting PSBT using an unconfirmed input")
 188          target_address = self.nodes[1].getnewaddress()
 189          psbtx1 = wallet.walletcreatefundedpsbt([], {target_address: 0.1}, 0, {'fee_rate': 1, 'maxconf': 0})['psbt']
 190  
 191          # Make sure we only had the one input
 192          tx1_inputs = self.nodes[0].decodepsbt(psbtx1)['inputs']
 193          assert_equal(len(tx1_inputs), 1)
 194  
 195          utxo1 = tx1_inputs[0]
 196          assert_equal(unconfirmed_txid, utxo1['previous_txid'])
 197  
 198          signed_tx1 = wallet.walletprocesspsbt(psbtx1)
 199          txid1 = self.nodes[0].sendrawtransaction(signed_tx1['hex'])
 200  
 201          mempool = self.nodes[0].getrawmempool()
 202          assert txid1 in mempool
 203  
 204          self.log.info("Fail to craft a new PSBT that sends more funds with add_inputs = False")
 205          assert_raises_rpc_error(-4, "The preselected coins total amount does not cover the transaction target. Please allow other inputs to be automatically selected or include more coins manually", wallet.walletcreatefundedpsbt, [{'txid': utxo1['previous_txid'], 'vout': utxo1['previous_vout']}], {target_address: 1}, 0, {'add_inputs': False})
 206  
 207          self.log.info("Fail to craft a new PSBT with minconf above highest one")
 208          assert_raises_rpc_error(-4, "Insufficient funds", wallet.walletcreatefundedpsbt, [{'txid': utxo1['previous_txid'], 'vout': utxo1['previous_vout']}], {target_address: 1}, 0, {'add_inputs': True, 'minconf': 3, 'fee_rate': 10})
 209  
 210          self.log.info("Fail to broadcast a new PSBT with maxconf 0 due to BIP125 rules to verify it actually chose unconfirmed outputs")
 211          psbt_invalid = wallet.walletcreatefundedpsbt([{'txid': utxo1['previous_txid'], 'vout': utxo1['previous_vout']}], {target_address: 1}, 0, {'add_inputs': True, 'maxconf': 0, 'fee_rate': 10})['psbt']
 212          signed_invalid = wallet.walletprocesspsbt(psbt_invalid)
 213          assert_raises_rpc_error(-26, "bad-txns-spends-conflicting-tx", self.nodes[0].sendrawtransaction, signed_invalid['hex'])
 214  
 215          self.log.info("Craft a replacement adding inputs with highest confs possible")
 216          psbtx2 = wallet.walletcreatefundedpsbt([{'txid': utxo1['previous_txid'], 'vout': utxo1['previous_vout']}], {target_address: 1}, 0, {'add_inputs': True, 'minconf': 2, 'fee_rate': 10})['psbt']
 217          tx2_inputs = self.nodes[0].decodepsbt(psbtx2)['inputs']
 218          assert_greater_than_or_equal(len(tx2_inputs), 2)
 219          for vin in tx2_inputs:
 220              if vin['previous_txid'] != unconfirmed_txid:
 221                  assert_greater_than_or_equal(self.nodes[0].gettxout(vin['previous_txid'], vin['previous_vout'])['confirmations'], 2)
 222  
 223          signed_tx2 = wallet.walletprocesspsbt(psbtx2)
 224          txid2 = self.nodes[0].sendrawtransaction(signed_tx2['hex'])
 225  
 226          mempool = self.nodes[0].getrawmempool()
 227          assert txid1 not in mempool
 228          assert txid2 in mempool
 229  
 230          wallet.unloadwallet()
 231  
 232      def test_decodepsbt_musig2_input_output_types(self):
 233          self.log.info("Test decoding PSBT with MuSig2 per-input and per-output types")
 234          # create 2-of-2 musig2 using fake aggregate key, leaf hash, pubnonce, and partial sig
 235          # TODO: actually implement MuSig2 aggregation (for decoding only it doesn't matter though)
 236          _, in_pubkey1 = generate_keypair()
 237          _, in_pubkey2 = generate_keypair()
 238          _, in_fake_agg_pubkey = generate_keypair()
 239          fake_leaf_hash = randbytes(32)
 240          fake_pubnonce = randbytes(66)
 241          fake_partialsig = randbytes(32)
 242          tx = CTransaction()
 243          tx.vin = [CTxIn(outpoint=COutPoint(hash=int('ee' * 32, 16), n=0), scriptSig=b"")]
 244          tx.vout = [CTxOut(nValue=0, scriptPubKey=b"")]
 245          psbt = PSBT()
 246          psbt.g = PSBTMap({PSBT_GLOBAL_UNSIGNED_TX: tx.serialize()})
 247          participant1_keydata = in_pubkey1 + in_fake_agg_pubkey + fake_leaf_hash
 248          psbt.i = [PSBTMap({
 249                      bytes([PSBT_IN_MUSIG2_PARTICIPANT_PUBKEYS]) + in_fake_agg_pubkey: [in_pubkey1, in_pubkey2],
 250                      bytes([PSBT_IN_MUSIG2_PUB_NONCE]) + participant1_keydata: fake_pubnonce,
 251                      bytes([PSBT_IN_MUSIG2_PARTIAL_SIG]) + participant1_keydata: fake_partialsig,
 252                   })]
 253          _, out_pubkey1 = generate_keypair()
 254          _, out_pubkey2 = generate_keypair()
 255          _, out_fake_agg_pubkey = generate_keypair()
 256          psbt.o = [PSBTMap({
 257                      bytes([PSBT_OUT_MUSIG2_PARTICIPANT_PUBKEYS]) + out_fake_agg_pubkey: [out_pubkey1, out_pubkey2],
 258                   })]
 259          res = self.nodes[0].decodepsbt(psbt.to_base64())
 260          assert_equal(len(res["inputs"]), 1)
 261          res_input = res["inputs"][0]
 262          assert_equal(len(res["outputs"]), 1)
 263          res_output = res["outputs"][0]
 264  
 265          assert "musig2_participant_pubkeys" in res_input
 266          in_participant_pks = res_input["musig2_participant_pubkeys"][0]
 267          assert "aggregate_pubkey" in in_participant_pks
 268          assert_equal(in_participant_pks["aggregate_pubkey"], in_fake_agg_pubkey.hex())
 269          assert "participant_pubkeys" in in_participant_pks
 270          assert_equal(in_participant_pks["participant_pubkeys"], [in_pubkey1.hex(), in_pubkey2.hex()])
 271  
 272          assert "musig2_pubnonces" in res_input
 273          in_pubnonce = res_input["musig2_pubnonces"][0]
 274          assert "participant_pubkey" in in_pubnonce
 275          assert_equal(in_pubnonce["participant_pubkey"], in_pubkey1.hex())
 276          assert "aggregate_pubkey" in in_pubnonce
 277          assert_equal(in_pubnonce["aggregate_pubkey"], in_fake_agg_pubkey.hex())
 278          assert "leaf_hash" in in_pubnonce
 279          assert_equal(in_pubnonce["leaf_hash"], fake_leaf_hash.hex())
 280          assert "pubnonce" in in_pubnonce
 281          assert_equal(in_pubnonce["pubnonce"], fake_pubnonce.hex())
 282  
 283          assert "musig2_partial_sigs" in res_input
 284          in_partialsig = res_input["musig2_partial_sigs"][0]
 285          assert "participant_pubkey" in in_partialsig
 286          assert_equal(in_partialsig["participant_pubkey"], in_pubkey1.hex())
 287          assert "aggregate_pubkey" in in_partialsig
 288          assert_equal(in_partialsig["aggregate_pubkey"], in_fake_agg_pubkey.hex())
 289          assert "leaf_hash" in in_partialsig
 290          assert_equal(in_partialsig["leaf_hash"], fake_leaf_hash.hex())
 291          assert "partial_sig" in in_partialsig
 292          assert_equal(in_partialsig["partial_sig"], fake_partialsig.hex())
 293  
 294          assert "musig2_participant_pubkeys" in res_output
 295          out_participant_pks = res_output["musig2_participant_pubkeys"][0]
 296          assert "aggregate_pubkey" in out_participant_pks
 297          assert_equal(out_participant_pks["aggregate_pubkey"], out_fake_agg_pubkey.hex())
 298          assert "participant_pubkeys" in out_participant_pks
 299          assert_equal(out_participant_pks["participant_pubkeys"], [out_pubkey1.hex(), out_pubkey2.hex()])
 300  
 301      def test_combinepsbt_preserves_proprietary_fields(self):
 302          self.log.info("Test that combining PSBTs preserves proprietary fields")
 303  
 304          def proprietary_key(type_byte, identifier, subtype, key_data=b""):
 305              return bytes([type_byte]) + ser_compact_size(len(identifier)) + identifier + ser_compact_size(subtype) + key_data
 306  
 307          def proprietary_entry(key, value, identifier, subtype):
 308              return {"identifier": identifier.hex(), "subtype": subtype, "key": key.hex(), "value": value.hex()}
 309  
 310          tx = CTransaction()
 311          tx.vin = [CTxIn(outpoint=COutPoint(hash=int('aa' * 32, 16), n=0), scriptSig=b"")]
 312          tx.vout = [CTxOut(nValue=0, scriptPubKey=b"")]
 313  
 314          global_key_a = proprietary_key(type_byte=PSBT_GLOBAL_PROPRIETARY, identifier=b"gc", subtype=1, key_data=b"\x01")
 315          global_key_b = proprietary_key(type_byte=PSBT_GLOBAL_PROPRIETARY, identifier=b"gc", subtype=2, key_data=b"\x02")
 316          input_key_a = proprietary_key(type_byte=PSBT_IN_PROPRIETARY, identifier=b"in", subtype=3, key_data=b"\x03")
 317          input_key_b = proprietary_key(type_byte=PSBT_IN_PROPRIETARY, identifier=b"in", subtype=4, key_data=b"\x04")
 318          output_key_a = proprietary_key(type_byte=PSBT_OUT_PROPRIETARY, identifier=b"out", subtype=5, key_data=b"\x05")
 319          output_key_b = proprietary_key(type_byte=PSBT_OUT_PROPRIETARY, identifier=b"out", subtype=6, key_data=b"\x06")
 320  
 321          psbt1 = PSBT(
 322              g=PSBTMap({
 323                  PSBT_GLOBAL_UNSIGNED_TX: tx.serialize(),
 324                  global_key_a: b"\xaa",
 325              }),
 326              i=[PSBTMap({
 327                  input_key_a: b"\xbb",
 328              })],
 329              o=[PSBTMap({
 330                  output_key_a: b"\xcc",
 331              })],
 332          ).to_base64()
 333          psbt2 = PSBT(
 334              g=PSBTMap({
 335                  PSBT_GLOBAL_UNSIGNED_TX: tx.serialize(),
 336                  global_key_b: b"\xdd",
 337              }),
 338              i=[PSBTMap({
 339                  input_key_b: b"\xee",
 340              })],
 341              o=[PSBTMap({
 342                  output_key_b: b"\xff",
 343              })],
 344          ).to_base64()
 345  
 346          decoded = self.nodes[0].decodepsbt(self.nodes[0].combinepsbt([psbt1, psbt2]))
 347          assert_equal(decoded["proprietary"], [
 348              proprietary_entry(key=global_key_a, value=b"\xaa", identifier=b"gc", subtype=1),
 349              proprietary_entry(key=global_key_b, value=b"\xdd", identifier=b"gc", subtype=2),
 350          ])
 351          assert_equal(decoded["inputs"][0]["proprietary"], [
 352              proprietary_entry(key=input_key_a, value=b"\xbb", identifier=b"in", subtype=3),
 353              proprietary_entry(key=input_key_b, value=b"\xee", identifier=b"in", subtype=4),
 354          ])
 355          assert_equal(decoded["outputs"][0]["proprietary"], [
 356              proprietary_entry(key=output_key_a, value=b"\xcc", identifier=b"out", subtype=5),
 357              proprietary_entry(key=output_key_b, value=b"\xff", identifier=b"out", subtype=6),
 358          ])
 359  
 360      def test_sighash_mismatch(self):
 361          self.log.info("Test sighash type mismatches")
 362          self.nodes[0].createwallet("sighash_mismatch")
 363          wallet = self.nodes[0].get_wallet_rpc("sighash_mismatch")
 364          def_wallet = self.nodes[0].get_wallet_rpc(self.default_wallet_name)
 365  
 366          addr = wallet.getnewaddress(address_type="bech32")
 367          def_wallet.sendtoaddress(addr, 5)
 368          self.generate(self.nodes[0], 6)
 369  
 370          # Retrieve the descriptors so we can do all of the tests with descriptorprocesspsbt as well
 371          descs = wallet.listdescriptors(True)["descriptors"]
 372  
 373          # Make a PSBT
 374          psbt = wallet.walletcreatefundedpsbt([], [{def_wallet.getnewaddress(): 1}])["psbt"]
 375  
 376          # Modify the PSBT and insert a sighash field for ALL|ANYONECANPAY on input 0
 377          mod_psbt = PSBT.from_base64(psbt)
 378          mod_psbt.i[0].map[PSBT_IN_SIGHASH_TYPE] = (SIGHASH_ALL | SIGHASH_ANYONECANPAY).to_bytes(4, byteorder="little")
 379          psbt = mod_psbt.to_base64()
 380  
 381          # Mismatching sighash type fails, including when no type is specified
 382          for sighash in ["DEFAULT", "ALL", "NONE", "SINGLE", "NONE|ANYONECANPAY", "SINGLE|ANYONECANPAY", None]:
 383              assert_raises_rpc_error(-22, "Specified sighash value does not match value stored in PSBT", wallet.walletprocesspsbt, psbt, True, sighash)
 384  
 385          # Matching sighash type succeeds
 386          proc = wallet.walletprocesspsbt(psbt, True, "ALL|ANYONECANPAY")
 387          assert_equal(proc["complete"], True)
 388  
 389          # Repeat with descriptorprocesspsbt
 390          # Mismatching sighash type fails, including when no type is specified
 391          for sighash in ["DEFAULT", "ALL", "NONE", "SINGLE", "NONE|ANYONECANPAY", "SINGLE|ANYONECANPAY", None]:
 392              assert_raises_rpc_error(-22, "Specified sighash value does not match value stored in PSBT", self.nodes[0].descriptorprocesspsbt, psbt, descs, sighash)
 393  
 394          # Matching sighash type succeeds
 395          proc = self.nodes[0].descriptorprocesspsbt(psbt, descs, "ALL|ANYONECANPAY")
 396          assert_equal(proc["complete"], True)
 397  
 398          wallet.unloadwallet()
 399  
 400      def test_sighash_adding(self):
 401          self.log.info("Test adding of sighash type field")
 402          self.nodes[0].createwallet("sighash_adding")
 403          wallet = self.nodes[0].get_wallet_rpc("sighash_adding")
 404          def_wallet = self.nodes[0].get_wallet_rpc(self.default_wallet_name)
 405  
 406          outputs = [{wallet.getnewaddress(address_type="bech32"): 1}]
 407          outputs.append({wallet.getnewaddress(address_type="bech32m"): 1})
 408          descs = wallet.listdescriptors(True)["descriptors"]
 409          def_wallet.send(outputs)
 410          self.generate(self.nodes[0], 6)
 411          utxos = wallet.listunspent()
 412  
 413          # Make a PSBT
 414          psbt = wallet.walletcreatefundedpsbt(utxos, [{def_wallet.getnewaddress(): 0.5}])["psbt"]
 415  
 416          # Process the PSBT with the wallet
 417          wallet_psbt = wallet.walletprocesspsbt(psbt=psbt, sighashtype="ALL|ANYONECANPAY", finalize=False)["psbt"]
 418  
 419          # Separately process the PSBT with descriptors
 420          desc_psbt = self.nodes[0].descriptorprocesspsbt(psbt=psbt, descriptors=descs, sighashtype="ALL|ANYONECANPAY", finalize=False)["psbt"]
 421  
 422          for psbt in [wallet_psbt, desc_psbt]:
 423              # Check that the PSBT has a sighash field on all inputs
 424              dec_psbt = self.nodes[0].decodepsbt(psbt)
 425              for input in dec_psbt["inputs"]:
 426                  assert_equal(input["sighash"], "ALL|ANYONECANPAY")
 427  
 428              # Make sure we can still finalize the transaction
 429              fin_res = self.nodes[0].finalizepsbt(psbt)
 430              assert_equal(fin_res["complete"], True)
 431              fin_hex = fin_res["hex"]
 432              assert_equal(self.nodes[0].testmempoolaccept([fin_hex])[0]["allowed"], True)
 433  
 434              # Change the sighash field to a different value and make sure we can no longer finalize
 435              mod_psbt = PSBT.from_base64(psbt)
 436              mod_psbt.i[0].map[PSBT_IN_SIGHASH_TYPE] = (SIGHASH_ALL).to_bytes(4, byteorder="little")
 437              mod_psbt.i[1].map[PSBT_IN_SIGHASH_TYPE] = (SIGHASH_ALL).to_bytes(4, byteorder="little")
 438              psbt = mod_psbt.to_base64()
 439              fin_res = self.nodes[0].finalizepsbt(psbt)
 440              assert_equal(fin_res["complete"], False)
 441  
 442          self.nodes[0].sendrawtransaction(fin_hex)
 443          self.generate(self.nodes[0], 1)
 444  
 445          wallet.unloadwallet()
 446  
 447      def assert_change_type(self, psbtx, expected_type):
 448          """Assert that the given PSBT has a change output with the given type."""
 449  
 450          # The decodepsbt RPC is stateless and independent of any settings, we can always just call it on the first node
 451          decoded_psbt = self.nodes[0].decodepsbt(psbtx["psbt"])
 452          changepos = psbtx["changepos"]
 453          assert_equal(decoded_psbt["outputs"][changepos]["script"]["type"], expected_type)
 454  
 455      def test_psbt_named_parameter_handling(self):
 456          """Test that PSBT Base64 parameters with '=' padding are handled correctly in -named mode"""
 457          self.log.info("Testing PSBT Base64 parameter handling with '=' padding characters")
 458          node = self.nodes[0]
 459          psbt_with_padding = "cHNidP8BAJoCAAAAAqvNEjSrzRI0q80SNKvNEjSrzRI0q80SNKvNEjSrzRI0AAAAAAD9////NBLNqzQSzas0Es2rNBLNqzQSzas0Es2rNBLNqzQSzasBAAAAAP3///8CoIYBAAAAAAAWABQVQBGVs/sqFAmC8HZ8O+g1htqivkANAwAAAAAAFgAUir7MzgyzDnRMjdkVa7d+Dwr07jsAAAAAAAAAAAA="
 460  
 461          # Test decodepsbt with explicit named parameter containing '=' padding
 462          result = node.cli("-named", "decodepsbt", f"psbt={psbt_with_padding}").send_cli()
 463          assert 'tx' in result
 464  
 465          # Test decodepsbt with positional argument containing '=' padding
 466          result = node.cli("-named", "decodepsbt", psbt_with_padding).send_cli()
 467          assert 'tx' in result
 468  
 469          # Test analyzepsbt with positional argument containing '=' padding
 470          result = node.cli("-named", "analyzepsbt", psbt_with_padding).send_cli()
 471          assert 'inputs' in result
 472  
 473          # Test finalizepsbt with positional argument containing '=' padding
 474          result = node.cli("-named", "finalizepsbt", psbt_with_padding, "extract=true").send_cli()
 475          assert 'complete' in result
 476  
 477          # Test walletprocesspsbt with positional argument containing '=' padding
 478          result = node.cli("-named", "walletprocesspsbt", psbt_with_padding).send_cli()
 479          assert 'complete' in result
 480  
 481          # Test utxoupdatepsbt with positional argument containing '=' padding
 482          result = node.cli("-named", "utxoupdatepsbt", psbt_with_padding).send_cli()
 483          assert isinstance(result, str) and len(result) > 0
 484  
 485          # Test that unknown parameter with '=' gets treated as positional and return error
 486          unknown_psbt_param = "unknown_param_data=more_data="
 487          # This should be treated as positional and fail with decode error, not parameter error
 488          assert_raises_rpc_error(-22, "TX decode failed invalid base64", node.cli("-named", "finalizepsbt", unknown_psbt_param).send_cli)
 489  
 490          self.log.info("PSBT parameter handling test completed successfully")
 491  
 492      def test_psbt_roundtrip(self):
 493          self.log.info("Test that PSBTs roundtrip when RPC does nothing")
 494          utxo = self.nodes[0].listunspent()[0]
 495          for ver in [0, 2]:
 496              psbt = self.nodes[0].walletcreatefundedpsbt(inputs=[utxo], outputs=[{self.nodes[0].getnewaddress(): utxo["amount"] / 2}], psbt_version=ver)["psbt"]
 497  
 498              rt_psbts = [
 499                  self.nodes[0].combinepsbt([psbt, psbt]),
 500                  self.nodes[0].finalizepsbt(psbt)["psbt"],
 501                  self.nodes[0].utxoupdatepsbt(psbt),
 502                  self.nodes[0].descriptorprocesspsbt(psbt, [])["psbt"],
 503                  self.nodes[0].walletprocesspsbt(psbt, sign=False)["psbt"],
 504              ]
 505              for p in rt_psbts:
 506                  assert_equal(psbt, p)
 507  
 508      def test_psbt_version(self):
 509          tobump = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1)
 510          utxo = self.nodes[0].listunspent()[0]
 511          outputs = [{self.nodes[0].getnewaddress(): utxo["amount"] / 2}]
 512          rawtx = self.nodes[0].createrawtransaction(inputs=[utxo], outputs=outputs)
 513          for ver in [0, 2]:
 514              psbt = self.nodes[0].createpsbt(inputs=[utxo], outputs=outputs, psbt_version=ver)
 515              dec = self.nodes[0].decodepsbt(psbt)
 516              assert_equal(ver, dec["psbt_version"])
 517  
 518              psbt = self.nodes[0].walletcreatefundedpsbt(inputs=[utxo], outputs=outputs, psbt_version=ver)
 519              dec = self.nodes[0].decodepsbt(psbt["psbt"])
 520              assert_equal(ver, dec["psbt_version"])
 521  
 522              psbt = self.nodes[0].converttopsbt(hexstring=rawtx, psbt_version=ver)
 523              dec = self.nodes[0].decodepsbt(psbt)
 524              assert_equal(ver, dec["psbt_version"])
 525  
 526              psbt = self.nodes[0].psbtbumpfee(txid=tobump, psbt_version=ver)
 527              dec = self.nodes[0].decodepsbt(psbt["psbt"])
 528              assert_equal(ver, dec["psbt_version"])
 529  
 530          assert_raises_rpc_error(-8, "The PSBT version can only be 2 or 0", self.nodes[0].createpsbt, inputs=[utxo], outputs=outputs, psbt_version=1)
 531          assert_raises_rpc_error(-8, "The PSBT version can only be 2 or 0", self.nodes[0].walletcreatefundedpsbt, inputs=[utxo], outputs=outputs, psbt_version=1)
 532          assert_raises_rpc_error(-8, "The PSBT version can only be 2 or 0", self.nodes[0].converttopsbt, hexstring=rawtx, psbt_version=1)
 533          assert_raises_rpc_error(-8, "The PSBT version can only be 2 or 0", self.nodes[0].psbtbumpfee, txid=tobump, psbt_version=1)
 534  
 535      def run_test(self):
 536          # Create and fund a raw tx for sending 10 BTC
 537          psbtx1 = self.nodes[0].walletcreatefundedpsbt([], {self.nodes[2].getnewaddress():10})['psbt']
 538  
 539          self.log.info("Test for invalid maximum transaction weights")
 540          dest_arg = [{self.nodes[0].getnewaddress(): 1}]
 541          min_tx_weight = MIN_STANDARD_TX_NONWITNESS_SIZE * WITNESS_SCALE_FACTOR
 542          assert_raises_rpc_error(-4, f"Maximum transaction weight must be between {min_tx_weight} and {MAX_STANDARD_TX_WEIGHT}", self.nodes[0].walletcreatefundedpsbt, [], dest_arg, 0, {"max_tx_weight": -1})
 543          assert_raises_rpc_error(-4, f"Maximum transaction weight must be between {min_tx_weight} and {MAX_STANDARD_TX_WEIGHT}", self.nodes[0].walletcreatefundedpsbt, [], dest_arg, 0, {"max_tx_weight": 0})
 544          assert_raises_rpc_error(-4, f"Maximum transaction weight must be between {min_tx_weight} and {MAX_STANDARD_TX_WEIGHT}", self.nodes[0].walletcreatefundedpsbt, [], dest_arg, 0, {"max_tx_weight": MAX_STANDARD_TX_WEIGHT + 1})
 545  
 546          # Base transaction vsize: version (4) + locktime (4) + input count (1) + witness overhead (1) = 10 vbytes
 547          base_tx_vsize = 10
 548          # One P2WPKH output vsize: outpoint (31 vbytes)
 549          p2wpkh_output_vsize = 31
 550          # 1 vbyte for output count
 551          output_count = 1
 552          tx_weight_without_inputs = (base_tx_vsize + output_count + p2wpkh_output_vsize) * WITNESS_SCALE_FACTOR
 553          # min_tx_weight is greater than transaction weight without inputs
 554          assert_greater_than(min_tx_weight, tx_weight_without_inputs)
 555  
 556          # In order to test for when the passed max weight is less than the transaction weight without inputs
 557          # Define destination with two outputs.
 558          dest_arg_large = [{self.nodes[0].getnewaddress(): 1}, {self.nodes[0].getnewaddress(): 1}]
 559          large_tx_vsize_without_inputs = base_tx_vsize + output_count + (p2wpkh_output_vsize * 2)
 560          large_tx_weight_without_inputs = large_tx_vsize_without_inputs * WITNESS_SCALE_FACTOR
 561          assert_greater_than(large_tx_weight_without_inputs, min_tx_weight)
 562          # Test for max_tx_weight less than Transaction weight without inputs
 563          assert_raises_rpc_error(-4, "Maximum transaction weight is less than transaction weight without inputs", self.nodes[0].walletcreatefundedpsbt, [], dest_arg_large, 0, {"max_tx_weight": min_tx_weight})
 564          assert_raises_rpc_error(-4, "Maximum transaction weight is less than transaction weight without inputs", self.nodes[0].walletcreatefundedpsbt, [], dest_arg_large, 0, {"max_tx_weight": large_tx_weight_without_inputs})
 565  
 566          # Test for max_tx_weight just enough to include inputs but not change output
 567          assert_raises_rpc_error(-4, "Maximum transaction weight is too low, can not accommodate change output", self.nodes[0].walletcreatefundedpsbt, [], dest_arg_large, 0, {"max_tx_weight": (large_tx_vsize_without_inputs + 1) * WITNESS_SCALE_FACTOR})
 568          self.log.info("Test that a funded PSBT is always faithful to max_tx_weight option")
 569          large_tx_vsize_with_change = large_tx_vsize_without_inputs + p2wpkh_output_vsize
 570          # It's enough but won't accommodate selected input size
 571          assert_raises_rpc_error(-4, "The inputs size exceeds the maximum weight", self.nodes[0].walletcreatefundedpsbt, [], dest_arg_large, 0, {"max_tx_weight": (large_tx_vsize_with_change) * WITNESS_SCALE_FACTOR})
 572  
 573          max_tx_weight_sufficient = 1000 # 1k vbytes is enough
 574          psbt = self.nodes[0].walletcreatefundedpsbt(outputs=dest_arg,locktime=0, options={"max_tx_weight": max_tx_weight_sufficient})["psbt"]
 575          psbt = self.nodes[0].walletprocesspsbt(psbt)["psbt"]
 576          final_tx = self.nodes[0].finalizepsbt(psbt)["hex"]
 577          weight = self.nodes[0].decoderawtransaction(final_tx)["weight"]
 578          # ensure the transaction's weight is below the specified max_tx_weight.
 579          assert_greater_than_or_equal(max_tx_weight_sufficient, weight)
 580  
 581          # If inputs are specified, do not automatically add more:
 582          utxo1 = self.nodes[0].listunspent()[0]
 583          assert_raises_rpc_error(-4, "The preselected coins total amount does not cover the transaction target. "
 584                                      "Please allow other inputs to be automatically selected or include more coins manually",
 585                                  self.nodes[0].walletcreatefundedpsbt, [{"txid": utxo1['txid'], "vout": utxo1['vout']}], {self.nodes[2].getnewaddress():90})
 586  
 587          psbtx1 = self.nodes[0].walletcreatefundedpsbt([{"txid": utxo1['txid'], "vout": utxo1['vout']}], {self.nodes[2].getnewaddress():90}, 0, {"add_inputs": True})['psbt']
 588          assert_equal(len(self.nodes[0].decodepsbt(psbtx1)['inputs']), 2)
 589  
 590          # Inputs argument can be null
 591          self.nodes[0].walletcreatefundedpsbt(None, {self.nodes[2].getnewaddress():10})
 592  
 593          # Node 1 should not be able to add anything to it but still return the psbtx same as before
 594          psbtx = self.nodes[1].walletprocesspsbt(psbtx1)['psbt']
 595          assert_equal(psbtx1, psbtx)
 596  
 597          # Node 0 should not be able to sign the transaction with the wallet is locked
 598          self.nodes[0].encryptwallet("password")
 599          assert_raises_rpc_error(-13, "Please enter the wallet passphrase with walletpassphrase first", self.nodes[0].walletprocesspsbt, psbtx)
 600  
 601          # Node 0 should be able to process without signing though
 602          unsigned_tx = self.nodes[0].walletprocesspsbt(psbtx, False)
 603          assert_equal(unsigned_tx['complete'], False)
 604  
 605          self.nodes[0].walletpassphrase(passphrase="password", timeout=1000000)
 606  
 607          # Sign the transaction but don't finalize
 608          processed_psbt = self.nodes[0].walletprocesspsbt(psbt=psbtx, finalize=False)
 609          assert "hex" not in processed_psbt
 610          signed_psbt = processed_psbt['psbt']
 611  
 612          # Finalize and send
 613          finalized_hex = self.nodes[0].finalizepsbt(signed_psbt)['hex']
 614          self.nodes[0].sendrawtransaction(finalized_hex)
 615  
 616          # Alternative method: sign AND finalize in one command
 617          processed_finalized_psbt = self.nodes[0].walletprocesspsbt(psbt=psbtx, finalize=True)
 618          finalized_psbt = processed_finalized_psbt['psbt']
 619          finalized_psbt_hex = processed_finalized_psbt['hex']
 620          assert_not_equal(signed_psbt, finalized_psbt)
 621          assert_equal(finalized_psbt_hex, finalized_hex)
 622  
 623          # Manually selected inputs can be locked:
 624          assert_equal(len(self.nodes[0].listlockunspent()), 0)
 625          utxo1 = self.nodes[0].listunspent()[0]
 626          psbtx1 = self.nodes[0].walletcreatefundedpsbt([{"txid": utxo1['txid'], "vout": utxo1['vout']}], {self.nodes[2].getnewaddress():1}, 0,{"lockUnspents": True})["psbt"]
 627          assert_equal(len(self.nodes[0].listlockunspent()), 1)
 628  
 629          # Locks are ignored for manually selected inputs
 630          self.nodes[0].walletcreatefundedpsbt([{"txid": utxo1['txid'], "vout": utxo1['vout']}], {self.nodes[2].getnewaddress():1}, 0)
 631  
 632          # Create p2sh, p2wpkh, and p2wsh addresses
 633          pubkey0 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())['pubkey']
 634          pubkey1 = self.nodes[1].getaddressinfo(self.nodes[1].getnewaddress())['pubkey']
 635          pubkey2 = self.nodes[2].getaddressinfo(self.nodes[2].getnewaddress())['pubkey']
 636  
 637          # Setup watchonly wallets
 638          self.nodes[2].createwallet(wallet_name='wmulti', disable_private_keys=True)
 639          wmulti = self.nodes[2].get_wallet_rpc('wmulti')
 640  
 641          # Create all the addresses
 642          p2sh_ms = wmulti.createmultisig(2, [pubkey0, pubkey1, pubkey2], address_type="legacy")
 643          p2sh = p2sh_ms["address"]
 644          p2wsh_ms = wmulti.createmultisig(2, [pubkey0, pubkey1, pubkey2], address_type="bech32")
 645          p2wsh = p2wsh_ms["address"]
 646          p2sh_p2wsh_ms = wmulti.createmultisig(2, [pubkey0, pubkey1, pubkey2], address_type="p2sh-segwit")
 647          p2sh_p2wsh = p2sh_p2wsh_ms["address"]
 648          import_res = wmulti.importdescriptors(
 649              [
 650                  {"desc": p2sh_ms["descriptor"], "timestamp": "now"},
 651                  {"desc": p2wsh_ms["descriptor"], "timestamp": "now"},
 652                  {"desc": p2sh_p2wsh_ms["descriptor"], "timestamp": "now"},
 653              ])
 654          assert_equal(all([r["success"] for r in import_res]), True)
 655          p2wpkh = self.nodes[1].getnewaddress("", "bech32")
 656          p2pkh = self.nodes[1].getnewaddress("", "legacy")
 657          p2sh_p2wpkh = self.nodes[1].getnewaddress("", "p2sh-segwit")
 658  
 659          # fund those addresses
 660          rawtx = self.nodes[0].createrawtransaction([], {p2sh:10, p2wsh:10, p2wpkh:10, p2sh_p2wsh:10, p2sh_p2wpkh:10, p2pkh:10})
 661          rawtx = self.nodes[0].fundrawtransaction(rawtx, {"changePosition":3})
 662          signed_tx = self.nodes[0].signrawtransactionwithwallet(rawtx['hex'])['hex']
 663          txid = self.nodes[0].sendrawtransaction(signed_tx)
 664          self.generate(self.nodes[0], 6)
 665  
 666          # Find the output pos
 667          p2sh_pos = -1
 668          p2wsh_pos = -1
 669          p2wpkh_pos = -1
 670          p2pkh_pos = -1
 671          p2sh_p2wsh_pos = -1
 672          p2sh_p2wpkh_pos = -1
 673          decoded = self.nodes[0].decoderawtransaction(signed_tx)
 674          for out in decoded['vout']:
 675              if out['scriptPubKey']['address'] == p2sh:
 676                  p2sh_pos = out['n']
 677              elif out['scriptPubKey']['address'] == p2wsh:
 678                  p2wsh_pos = out['n']
 679              elif out['scriptPubKey']['address'] == p2wpkh:
 680                  p2wpkh_pos = out['n']
 681              elif out['scriptPubKey']['address'] == p2sh_p2wsh:
 682                  p2sh_p2wsh_pos = out['n']
 683              elif out['scriptPubKey']['address'] == p2sh_p2wpkh:
 684                  p2sh_p2wpkh_pos = out['n']
 685              elif out['scriptPubKey']['address'] == p2pkh:
 686                  p2pkh_pos = out['n']
 687  
 688          inputs = [{"txid": txid, "vout": p2wpkh_pos}, {"txid": txid, "vout": p2sh_p2wpkh_pos}, {"txid": txid, "vout": p2pkh_pos}]
 689          outputs = [{self.nodes[1].getnewaddress(): 29.99}]
 690  
 691          # spend single key from node 1
 692          created_psbt = self.nodes[1].walletcreatefundedpsbt(inputs, outputs)
 693          walletprocesspsbt_out = self.nodes[1].walletprocesspsbt(created_psbt['psbt'])
 694          # Make sure it has both types of UTXOs
 695          decoded = self.nodes[1].decodepsbt(walletprocesspsbt_out['psbt'])
 696          assert 'non_witness_utxo' in decoded['inputs'][0]
 697          assert 'witness_utxo' in decoded['inputs'][0]
 698          # Check decodepsbt fee calculation (input values shall only be counted once per UTXO)
 699          assert_equal(decoded['fee'], created_psbt['fee'])
 700          assert_equal(walletprocesspsbt_out['complete'], True)
 701          self.nodes[1].sendrawtransaction(walletprocesspsbt_out['hex'])
 702  
 703          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)")
 704          res1 = self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"fee_rate": 10000, "add_inputs": True})
 705          assert_approx(res1["fee"], 0.055, 0.005)
 706          res2 = self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"feeRate": "0.1", "add_inputs": True})
 707          assert_approx(res2["fee"], 0.055, 0.005)
 708  
 709          self.log.info("Test min fee rate checks with walletcreatefundedpsbt are bypassed, e.g. a fee_rate under 1 sat/vB is allowed")
 710          res3 = self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"fee_rate": "0.999", "add_inputs": True})
 711          assert_approx(res3["fee"], 0.00000381, 0.0000001)
 712          res4 = self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"feeRate": 0.00000999, "add_inputs": True})
 713          assert_approx(res4["fee"], 0.00000381, 0.0000001)
 714  
 715          self.log.info("Test min fee rate checks with walletcreatefundedpsbt are bypassed and that funding non-standard 'zero-fee' transactions is valid")
 716          for param, zero_value in product(["fee_rate", "feeRate"], [0, 0.000, 0.00000000, "0", "0.000", "0.00000000"]):
 717              assert_equal(0, self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {param: zero_value, "add_inputs": True})["fee"])
 718  
 719          self.log.info("Test invalid fee rate settings")
 720          for param, value in {("fee_rate", 100000), ("feeRate", 1)}:
 721              assert_raises_rpc_error(-4, "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)",
 722                  self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {param: value, "add_inputs": True})
 723              assert_raises_rpc_error(-3, "Amount out of range",
 724                  self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {param: -1, "add_inputs": True})
 725              assert_raises_rpc_error(-3, "Amount is not a number or string",
 726                  self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {param: {"foo": "bar"}, "add_inputs": True})
 727              # Test fee rate values that don't pass fixed-point parsing checks.
 728              for invalid_value in ["", 0.000000001, 1e-09, 1.111111111, 1111111111111111, "31.999999999999999999999"]:
 729                  assert_raises_rpc_error(-3, "Invalid amount",
 730                      self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {param: invalid_value, "add_inputs": True})
 731          # Test fee_rate values that cannot be represented in sat/vB.
 732          for invalid_value in [0.0001, 0.00000001, 0.00099999, 31.99999999]:
 733              assert_raises_rpc_error(-3, "Invalid amount",
 734                  self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"fee_rate": invalid_value, "add_inputs": True})
 735  
 736          self.log.info("- raises RPC error if both feeRate and fee_rate are passed")
 737          assert_raises_rpc_error(-8, "Cannot specify both fee_rate (sat/vB) and feeRate (BTC/kvB)",
 738              self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"fee_rate": 0.1, "feeRate": 0.1, "add_inputs": True})
 739  
 740          self.log.info("- raises RPC error if both feeRate and estimate_mode passed")
 741          assert_raises_rpc_error(-8, "Cannot specify both estimate_mode and feeRate",
 742              self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"estimate_mode": "economical", "feeRate": 0.1, "add_inputs": True})
 743  
 744          for param in ["feeRate", "fee_rate"]:
 745              self.log.info("- raises RPC error if both {} and conf_target are passed".format(param))
 746              assert_raises_rpc_error(-8, "Cannot specify both conf_target and {}. Please provide either a confirmation "
 747                  "target in blocks for automatic fee estimation, or an explicit fee rate.".format(param),
 748                  self.nodes[1].walletcreatefundedpsbt ,inputs, outputs, 0, {param: 1, "conf_target": 1, "add_inputs": True})
 749  
 750          self.log.info("- raises RPC error if both fee_rate and estimate_mode are passed")
 751          assert_raises_rpc_error(-8, "Cannot specify both estimate_mode and fee_rate",
 752              self.nodes[1].walletcreatefundedpsbt ,inputs, outputs, 0, {"fee_rate": 1, "estimate_mode": "economical", "add_inputs": True})
 753  
 754          self.log.info("- raises RPC error with invalid estimate_mode settings")
 755          for k, v in {"number": 42, "object": {"foo": "bar"}}.items():
 756              assert_raises_rpc_error(-3, f"JSON value of type {k} for field estimate_mode is not of expected type string",
 757                  self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"estimate_mode": v, "conf_target": 0.1, "add_inputs": True})
 758          for mode in ["", "foo", Decimal("3.141592")]:
 759              assert_raises_rpc_error(-8, 'Invalid estimate_mode parameter, must be one of: "unset", "economical", "conservative"',
 760                  self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"estimate_mode": mode, "conf_target": 0.1, "add_inputs": True})
 761  
 762          self.log.info("- raises RPC error with invalid conf_target settings")
 763          for mode in ["unset", "economical", "conservative"]:
 764              self.log.debug("{}".format(mode))
 765              for k, v in {"string": "", "object": {"foo": "bar"}}.items():
 766                  assert_raises_rpc_error(-3, f"JSON value of type {k} for field conf_target is not of expected type number",
 767                      self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"estimate_mode": mode, "conf_target": v, "add_inputs": True})
 768              for n in [-1, 0, 1009]:
 769                  assert_raises_rpc_error(-8, "Invalid conf_target, must be between 1 and 1008",  # max value of 1008 per src/policy/fees/block_policy_estimator.h
 770                      self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"estimate_mode": mode, "conf_target": n, "add_inputs": True})
 771  
 772          self.log.info("Test walletcreatefundedpsbt with too-high fee rate produces total fee well above -maxtxfee and raises RPC error")
 773          # previously this was silently capped at -maxtxfee
 774          for bool_add, outputs_array in {True: outputs, False: [{self.nodes[1].getnewaddress(): 1}]}.items():
 775              msg = "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)"
 776              assert_raises_rpc_error(-4, msg, self.nodes[1].walletcreatefundedpsbt, inputs, outputs_array, 0, {"fee_rate": 1000000, "add_inputs": bool_add})
 777              assert_raises_rpc_error(-4, msg, self.nodes[1].walletcreatefundedpsbt, inputs, outputs_array, 0, {"feeRate": 1, "add_inputs": bool_add})
 778  
 779          self.log.info("Test various PSBT operations")
 780          # partially sign multisig things with node 1
 781          psbtx = wmulti.walletcreatefundedpsbt(inputs=[{"txid":txid,"vout":p2wsh_pos},{"txid":txid,"vout":p2sh_pos},{"txid":txid,"vout":p2sh_p2wsh_pos}], outputs={self.nodes[1].getnewaddress():29.99}, changeAddress=self.nodes[1].getrawchangeaddress())['psbt']
 782          walletprocesspsbt_out = self.nodes[1].walletprocesspsbt(psbtx)
 783          psbtx = walletprocesspsbt_out['psbt']
 784          assert_equal(walletprocesspsbt_out['complete'], False)
 785  
 786          # Unload wmulti, we don't need it anymore
 787          wmulti.unloadwallet()
 788  
 789          # partially sign with node 2. This should be complete and sendable
 790          walletprocesspsbt_out = self.nodes[2].walletprocesspsbt(psbtx)
 791          assert_equal(walletprocesspsbt_out['complete'], True)
 792          self.nodes[2].sendrawtransaction(walletprocesspsbt_out['hex'])
 793  
 794          # check that walletprocesspsbt fails to decode a non-psbt
 795          rawtx = self.nodes[1].createrawtransaction([{"txid":txid,"vout":p2wpkh_pos}], {self.nodes[1].getnewaddress():9.99})
 796          assert_raises_rpc_error(-22, "TX decode failed", self.nodes[1].walletprocesspsbt, rawtx)
 797  
 798          # Convert a non-psbt to psbt and make sure we can decode it
 799          rawtx = self.nodes[0].createrawtransaction([], {self.nodes[1].getnewaddress():10})
 800          rawtx = self.nodes[0].fundrawtransaction(rawtx)
 801          new_psbt = self.nodes[0].converttopsbt(rawtx['hex'])
 802          self.nodes[0].decodepsbt(new_psbt)
 803  
 804          # Make sure that a non-psbt with signatures cannot be converted
 805          signedtx = self.nodes[0].signrawtransactionwithwallet(rawtx['hex'])
 806          assert_raises_rpc_error(-22, "Inputs must not have scriptSigs and scriptWitnesses",
 807                                  self.nodes[0].converttopsbt, hexstring=signedtx['hex'])  # permitsigdata=False by default
 808          assert_raises_rpc_error(-22, "Inputs must not have scriptSigs and scriptWitnesses",
 809                                  self.nodes[0].converttopsbt, hexstring=signedtx['hex'], permitsigdata=False)
 810          assert_raises_rpc_error(-22, "Inputs must not have scriptSigs and scriptWitnesses",
 811                                  self.nodes[0].converttopsbt, hexstring=signedtx['hex'], permitsigdata=False, iswitness=True)
 812          # Unless we allow it to convert and strip signatures
 813          self.nodes[0].converttopsbt(hexstring=signedtx['hex'], permitsigdata=True)
 814  
 815          # Create outputs to nodes 1 and 2
 816          # (note that we intentionally create two different txs here, as we want
 817          #  to check that each node is missing prevout data for one of the two
 818          #  utxos, see "should only have data for one input" test below)
 819          node1_addr = self.nodes[1].getnewaddress()
 820          node2_addr = self.nodes[2].getnewaddress()
 821          utxo1 = self.create_outpoints(self.nodes[0], outputs=[{node1_addr: 13}])[0]
 822          utxo2 = self.create_outpoints(self.nodes[0], outputs=[{node2_addr: 13}])[0]
 823          self.generate(self.nodes[0], 6)[0]
 824  
 825          # Create a psbt spending outputs from nodes 1 and 2
 826          psbt_orig = self.nodes[0].createpsbt([utxo1, utxo2], {self.nodes[0].getnewaddress():25.999})
 827  
 828          # Check that the default psbt version is 2
 829          assert_equal(self.nodes[0].decodepsbt(psbt_orig)["psbt_version"], 2)
 830  
 831          # Update psbts, should only have data for one input and not the other
 832          psbt1 = self.nodes[1].walletprocesspsbt(psbt_orig, False, "ALL")['psbt']
 833          psbt1_decoded = self.nodes[0].decodepsbt(psbt1)
 834          assert len(psbt1_decoded['inputs'][0].keys()) > 3
 835          assert len(psbt1_decoded['inputs'][1].keys()) == 3
 836          # Check that BIP32 path was added
 837          assert "bip32_derivs" in psbt1_decoded['inputs'][0]
 838          psbt2 = self.nodes[2].walletprocesspsbt(psbt_orig, False, "ALL", False)['psbt']
 839          psbt2_decoded = self.nodes[0].decodepsbt(psbt2)
 840          assert len(psbt2_decoded['inputs'][0].keys()) == 3
 841          assert len(psbt2_decoded['inputs'][1].keys()) > 3
 842          # Check that BIP32 paths were not added
 843          assert "bip32_derivs" not in psbt2_decoded['inputs'][1]
 844  
 845          # Sign PSBTs (workaround issue #18039)
 846          psbt1 = self.nodes[1].walletprocesspsbt(psbt_orig)['psbt']
 847          psbt2 = self.nodes[2].walletprocesspsbt(psbt_orig)['psbt']
 848  
 849          # Combine, finalize, and send the psbts
 850          combined = self.nodes[0].combinepsbt([psbt1, psbt2])
 851          finalized = self.nodes[0].finalizepsbt(combined)['hex']
 852          self.nodes[0].sendrawtransaction(finalized)
 853          self.generate(self.nodes[0], 6)
 854  
 855          # Test additional args in walletcreatepsbt
 856          # Make sure both pre-included and funded inputs
 857          # have the correct sequence numbers based on
 858          # replaceable arg
 859          block_height = self.nodes[0].getblockcount()
 860          unspent = self.nodes[0].listunspent()[0]
 861          psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid":unspent["txid"], "vout":unspent["vout"]}], [{self.nodes[2].getnewaddress():unspent["amount"]+1}], block_height+2, {"replaceable": False, "add_inputs": True}, False)
 862          decoded_psbt = self.nodes[0].decodepsbt(psbtx_info["psbt"])
 863          for psbt_in in decoded_psbt["inputs"]:
 864              assert_greater_than(psbt_in["sequence"], MAX_BIP125_RBF_SEQUENCE)
 865              assert "bip32_derivs" not in psbt_in
 866          assert_equal(decoded_psbt["fallback_locktime"], block_height+2)
 867  
 868          # Same construction with only locktime set and RBF explicitly enabled
 869          psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid":unspent["txid"], "vout":unspent["vout"]}], [{self.nodes[2].getnewaddress():unspent["amount"]+1}], block_height, {"replaceable": True, "add_inputs": True}, True)
 870          decoded_psbt = self.nodes[0].decodepsbt(psbtx_info["psbt"])
 871          for psbt_in in decoded_psbt["inputs"]:
 872              assert_equal(psbt_in["sequence"], MAX_BIP125_RBF_SEQUENCE)
 873              assert "bip32_derivs" in psbt_in
 874          assert_equal(decoded_psbt["fallback_locktime"], block_height)
 875  
 876          # Same construction without optional arguments
 877          psbtx_info = self.nodes[0].walletcreatefundedpsbt([], [{self.nodes[2].getnewaddress():unspent["amount"]+1}])
 878          decoded_psbt = self.nodes[0].decodepsbt(psbtx_info["psbt"])
 879          for psbt_in in decoded_psbt["inputs"]:
 880              assert_equal(psbt_in["sequence"], MAX_BIP125_RBF_SEQUENCE)
 881              assert "bip32_derivs" in psbt_in
 882          assert_equal(decoded_psbt["fallback_locktime"], 0)
 883  
 884          # Make sure change address wallet does not have P2SH innerscript access to results in success
 885          # when attempting BnB coin selection
 886          self.nodes[0].walletcreatefundedpsbt([], [{self.nodes[2].getnewaddress():unspent["amount"]+1}], block_height+2, {"changeAddress":self.nodes[1].getnewaddress()}, False)
 887  
 888          # Make sure the wallet's change type is respected by default
 889          small_output = {self.nodes[0].getnewaddress():0.1}
 890          psbtx_native = self.nodes[0].walletcreatefundedpsbt([], [small_output])
 891          self.assert_change_type(psbtx_native, "witness_v0_keyhash")
 892          psbtx_legacy = self.nodes[1].walletcreatefundedpsbt([], [small_output])
 893          self.assert_change_type(psbtx_legacy, "pubkeyhash")
 894  
 895          # Make sure the change type of the wallet can also be overwritten
 896          psbtx_np2wkh = self.nodes[1].walletcreatefundedpsbt([], [small_output], 0, {"change_type":"p2sh-segwit"})
 897          self.assert_change_type(psbtx_np2wkh, "scripthash")
 898  
 899          # Make sure the change type cannot be specified if a change address is given
 900          invalid_options = {"change_type":"legacy","changeAddress":self.nodes[0].getnewaddress()}
 901          assert_raises_rpc_error(-8, "both change address and address type options", self.nodes[0].walletcreatefundedpsbt, [], [small_output], 0, invalid_options)
 902  
 903          # Regression test for 14473 (mishandling of already-signed witness transaction):
 904          psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid":unspent["txid"], "vout":unspent["vout"]}], [{self.nodes[2].getnewaddress():unspent["amount"]+1}], 0, {"add_inputs": True})
 905          complete_psbt = self.nodes[0].walletprocesspsbt(psbtx_info["psbt"])
 906          double_processed_psbt = self.nodes[0].walletprocesspsbt(complete_psbt["psbt"])
 907          assert_equal(complete_psbt, double_processed_psbt)
 908          # We don't care about the decode result, but decoding must succeed.
 909          self.nodes[0].decodepsbt(double_processed_psbt["psbt"])
 910  
 911          # Make sure unsafe inputs are included if specified
 912          self.nodes[2].createwallet(wallet_name="unsafe")
 913          wunsafe = self.nodes[2].get_wallet_rpc("unsafe")
 914          self.nodes[0].sendtoaddress(wunsafe.getnewaddress(), 2)
 915          self.sync_mempools()
 916          assert_raises_rpc_error(-4, "Insufficient funds", wunsafe.walletcreatefundedpsbt, [], [{self.nodes[0].getnewaddress(): 1}])
 917          wunsafe.walletcreatefundedpsbt([], [{self.nodes[0].getnewaddress(): 1}], 0, {"include_unsafe": True})
 918  
 919          self.log.info("Test that unknown values are just passed through")
 920          unknown_type = b'\xf0'
 921          unknown_key = unknown_type + bytes(range(1, 10))
 922          unknown_value = bytes(range(1, 16))
 923  
 924          unknown_psbt = self.create_psbt(inputs={unknown_key: unknown_value}).to_base64()
 925          unknown_out = self.nodes[0].walletprocesspsbt(unknown_psbt)['psbt']
 926          assert_equal(unknown_psbt, unknown_out)
 927  
 928          unknown_key2 = unknown_type + bytes(range(1, 9)) + bytes(11)
 929          unknown_psbt2 = self.create_psbt(inputs={unknown_key2: unknown_value}).to_base64()
 930          merged_unknown = self.nodes[0].combinepsbt([unknown_psbt, unknown_psbt2])
 931          merged_unknown_psbt = PSBT.from_base64(merged_unknown)
 932          assert_equal(merged_unknown_psbt.i[0].map[unknown_key], unknown_value)
 933          assert_equal(merged_unknown_psbt.i[0].map[unknown_key2], unknown_value)
 934  
 935          # The explicit PSBT_GLOBAL_VERSION=0 encoding is equivalent to omitting the
 936          # version field, and both accepted v0 encodings can be merged.
 937          explicit_v0_psbt = self.create_psbt(inputs={unknown_key2: unknown_value})
 938          explicit_v0_psbt.g.map[PSBT_GLOBAL_VERSION] = (0).to_bytes(4, "little")
 939          merged_v0_versions = self.nodes[0].combinepsbt([unknown_psbt, explicit_v0_psbt.to_base64()])
 940          merged_v0_versions_psbt = PSBT.from_base64(merged_v0_versions)
 941          assert_equal(merged_v0_versions_psbt.i[0].map[unknown_key], unknown_value)
 942          assert_equal(merged_v0_versions_psbt.i[0].map[unknown_key2], unknown_value)
 943  
 944          # BIP 174 Test Vectors
 945  
 946          # Open the data file
 947          with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data/rpc_psbt.json')) as f:
 948              d = json.load(f)
 949              invalids = d['invalid']
 950              invalid_with_msgs = d["invalid_with_msg"]
 951              valids = d['valid']
 952              creators = d['creator']
 953              signers = d['signer']
 954              combiners = d['combiner']
 955              finalizers = d['finalizer']
 956              extractors = d['extractor']
 957  
 958          # Invalid PSBTs
 959          for invalid in invalids:
 960              assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].decodepsbt, invalid)
 961          for invalid in invalid_with_msgs:
 962              psbt, msg = invalid
 963              assert_raises_rpc_error(-22, f"TX decode failed {msg}", self.nodes[0].decodepsbt, psbt)
 964  
 965          # Valid PSBTs
 966          for valid in valids:
 967              self.nodes[0].decodepsbt(valid)
 968  
 969          # Creator Tests
 970          for creator in creators:
 971              created_tx = self.nodes[0].createpsbt(inputs=creator['inputs'], outputs=creator['outputs'], replaceable=False, psbt_version=creator['version'])
 972              assert_equal(created_tx, creator['result'])
 973  
 974          # Signer tests
 975          for i, signer in enumerate(signers):
 976              self.nodes[2].createwallet(wallet_name="wallet{}".format(i))
 977              wrpc = self.nodes[2].get_wallet_rpc("wallet{}".format(i))
 978              for key in signer['privkeys']:
 979                  wallet_importprivkey(wrpc, key, "now")
 980              signed_tx = wrpc.walletprocesspsbt(signer['psbt'], True, "ALL")['psbt']
 981              assert_equal(signed_tx, signer['result'])
 982  
 983          # Combiner test
 984          for combiner in combiners:
 985              combined = self.nodes[2].combinepsbt(combiner['combine'])
 986              assert_equal(combined, combiner['result'])
 987  
 988          # Empty combiner test
 989          assert_raises_rpc_error(-8, "Parameter 'txs' cannot be empty", self.nodes[0].combinepsbt, [])
 990  
 991          # Finalizer test
 992          for finalizer in finalizers:
 993              finalized = self.nodes[2].finalizepsbt(finalizer['finalize'], False)['psbt']
 994              assert_equal(finalized, finalizer['result'])
 995  
 996          # Extractor test
 997          for extractor in extractors:
 998              extracted = self.nodes[2].finalizepsbt(extractor['extract'], True)['hex']
 999              assert_equal(extracted, extractor['result'])
1000  
1001          # Unload extra wallets
1002          for i, signer in enumerate(signers):
1003              self.nodes[2].unloadwallet("wallet{}".format(i))
1004  
1005          self.test_utxo_conversion()
1006          self.test_psbt_incomplete_after_invalid_modification()
1007  
1008          self.test_input_confs_control()
1009  
1010          # Test that psbts with p2pkh outputs are created properly
1011          p2pkh = self.nodes[0].getnewaddress(address_type='legacy')
1012          psbt = self.nodes[1].walletcreatefundedpsbt(inputs=[], outputs=[{p2pkh : 1}], bip32derivs=True)
1013          self.nodes[0].decodepsbt(psbt['psbt'])
1014  
1015          # Test decoding error: invalid base64
1016          assert_raises_rpc_error(-22, "TX decode failed invalid base64", self.nodes[0].decodepsbt, ";definitely not base64;")
1017  
1018          # Send to all types of addresses
1019          addr1 = self.nodes[1].getnewaddress("", "bech32")
1020          addr2 = self.nodes[1].getnewaddress("", "legacy")
1021          addr3 = self.nodes[1].getnewaddress("", "p2sh-segwit")
1022          utxo1, utxo2, utxo3 = self.create_outpoints(self.nodes[1], outputs=[{addr1: 11}, {addr2: 11}, {addr3: 11}])
1023          self.sync_all()
1024  
1025          psbt_v2_required_keys = ["previous_txid", "previous_vout", "sequence"]
1026  
1027          def test_psbt_input_keys(psbt_input, keys):
1028              """Check that the psbt input has only the expected keys."""
1029              keys.extend(["previous_txid", "previous_vout", "sequence"])
1030              assert_equal(set(keys), set(psbt_input.keys()))
1031  
1032          # Create a PSBT. None of the inputs are filled initially
1033          psbt = self.nodes[1].createpsbt([utxo1, utxo2, utxo3], {self.nodes[0].getnewaddress():32.999})
1034          decoded = self.nodes[1].decodepsbt(psbt)
1035          test_psbt_input_keys(decoded['inputs'][0], psbt_v2_required_keys)
1036          test_psbt_input_keys(decoded['inputs'][1], psbt_v2_required_keys)
1037          test_psbt_input_keys(decoded['inputs'][2], psbt_v2_required_keys)
1038  
1039          # Update a PSBT with UTXOs from the node
1040          # Bech32 inputs should be filled with witness UTXO. Other inputs should not be filled because they are non-witness
1041          updated = self.nodes[1].utxoupdatepsbt(psbt)
1042          decoded = self.nodes[1].decodepsbt(updated)
1043          test_psbt_input_keys(decoded['inputs'][0], psbt_v2_required_keys + ['witness_utxo', 'non_witness_utxo'])
1044          test_psbt_input_keys(decoded['inputs'][1], psbt_v2_required_keys + ['non_witness_utxo'])
1045          test_psbt_input_keys(decoded['inputs'][2], psbt_v2_required_keys + ['non_witness_utxo'])
1046  
1047          # Try again, now while providing descriptors, making P2SH-segwit work, and causing bip32_derivs and redeem_script to be filled in
1048          descs = [self.nodes[1].getaddressinfo(addr)['desc'] for addr in [addr1,addr2,addr3]]
1049          updated = self.nodes[1].utxoupdatepsbt(psbt=psbt, descriptors=descs)
1050          decoded = self.nodes[1].decodepsbt(updated)
1051          test_psbt_input_keys(decoded['inputs'][0], psbt_v2_required_keys + ['witness_utxo', 'non_witness_utxo', 'bip32_derivs'])
1052          test_psbt_input_keys(decoded['inputs'][1], psbt_v2_required_keys + ['non_witness_utxo', 'bip32_derivs'])
1053          test_psbt_input_keys(decoded['inputs'][2], psbt_v2_required_keys + ['non_witness_utxo', 'witness_utxo', 'bip32_derivs', 'redeem_script'])
1054  
1055          # Cannot join PSBTv2s
1056          psbt1 = self.nodes[1].createpsbt(inputs=[utxo1], outputs={self.nodes[0].getnewaddress():Decimal('10.999')}, psbt_version=0)
1057          psbt2 = self.nodes[1].createpsbt(inputs=[utxo1], outputs={self.nodes[0].getnewaddress():Decimal('10.999')}, psbt_version=2)
1058          assert_raises_rpc_error(-8, "joinpsbts only operates on version 0 PSBTs", self.nodes[1].joinpsbts, [psbt1, psbt2])
1059  
1060          # Two PSBTs with a common input should not be joinable
1061          psbt2 = self.nodes[1].createpsbt([utxo1], {self.nodes[0].getnewaddress():Decimal('10.999')}, psbt_version=0)
1062          assert_raises_rpc_error(-8, "exists in multiple PSBTs", self.nodes[1].joinpsbts, [psbt1, psbt2])
1063  
1064          # Join two distinct PSBTs
1065          psbt1 = self.nodes[1].createpsbt(inputs=[utxo1, utxo2, utxo3], outputs={self.nodes[0].getnewaddress():32.999}, psbt_version=0)
1066          addr4 = self.nodes[1].getnewaddress("", "p2sh-segwit")
1067          utxo4 = self.create_outpoints(self.nodes[0], outputs=[{addr4: 5}])[0]
1068          self.generate(self.nodes[0], 6)
1069          psbt2 = self.nodes[1].createpsbt([utxo4], {self.nodes[0].getnewaddress():Decimal('4.999')}, psbt_version=0)
1070          psbt2 = self.nodes[1].walletprocesspsbt(psbt2)['psbt']
1071          psbt2_decoded = self.nodes[0].decodepsbt(psbt2)
1072          assert "final_scriptwitness" in psbt2_decoded['inputs'][0] and "final_scriptSig" in psbt2_decoded['inputs'][0]
1073          joined = self.nodes[0].joinpsbts([psbt1, psbt2])
1074          joined_decoded = self.nodes[0].decodepsbt(joined)
1075          assert_equal(len(joined_decoded['inputs']), 4)
1076          assert_equal(len(joined_decoded['outputs']), 2)
1077          assert "final_scriptwitness" not in joined_decoded['inputs'][3]
1078          assert "final_scriptSig" not in joined_decoded['inputs'][3]
1079  
1080          # Check that joining shuffles the inputs and outputs
1081          # 10 attempts should be enough to get a shuffled join
1082          shuffled = False
1083          for _ in range(10):
1084              shuffled_joined = self.nodes[0].joinpsbts([psbt1, psbt2])
1085              shuffled |= joined != shuffled_joined
1086              if shuffled:
1087                  break
1088          assert shuffled
1089  
1090          # Newly created PSBT needs UTXOs and updating
1091          addr = self.nodes[1].getnewaddress("", "p2sh-segwit")
1092          utxo = self.create_outpoints(self.nodes[0], outputs=[{addr: 7}])[0]
1093          addrinfo = self.nodes[1].getaddressinfo(addr)
1094          self.generate(self.nodes[0], 6)[0]
1095          psbt = self.nodes[1].createpsbt([utxo], {self.nodes[0].getnewaddress("", "p2sh-segwit"):Decimal('6.999')})
1096          analyzed = self.nodes[0].analyzepsbt(psbt)
1097          assert_equal(analyzed['inputs'][0]['has_utxo'], False)
1098          assert_equal(analyzed['inputs'][0]['is_final'], False)
1099          assert_equal(analyzed['inputs'][0]['next'], 'updater')
1100          assert_equal(analyzed['next'], 'updater')
1101  
1102          # After update with wallet, only needs signing
1103          updated = self.nodes[1].walletprocesspsbt(psbt, False, 'ALL', True)['psbt']
1104          analyzed = self.nodes[0].analyzepsbt(updated)
1105          assert_equal(analyzed['inputs'][0]['has_utxo'], True)
1106          assert_equal(analyzed['inputs'][0]['is_final'], False)
1107          assert_equal(analyzed['inputs'][0]['next'], 'signer')
1108          assert_equal(analyzed['next'], 'signer')
1109          assert_equal(analyzed['inputs'][0]['missing']['signatures'][0], addrinfo['embedded']['witness_program'])
1110  
1111          # Check fee and size things
1112          assert_equal(analyzed['fee'], Decimal('0.001'))
1113          assert_equal(analyzed['estimated_vsize'], 134)
1114          assert_equal(analyzed['estimated_feerate'], Decimal('0.00746268'))
1115  
1116          # After signing and finalizing, needs extracting
1117          signed = self.nodes[1].walletprocesspsbt(updated)['psbt']
1118          analyzed = self.nodes[0].analyzepsbt(signed)
1119          assert_equal(analyzed['inputs'][0]['has_utxo'], True)
1120          assert_equal(analyzed['inputs'][0]['is_final'], True)
1121          assert_equal(analyzed['next'], 'extractor')
1122  
1123          self.log.info("PSBT spending unspendable outputs should have error message and Creator as next")
1124          analysis = self.nodes[0].analyzepsbt('cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWAEHYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFv8/wADXYP/7//////8JxOh0LR2HAI8AAAAAAAEBIADC6wsAAAAAF2oUt/X69ELjeX2nTof+fZ10l+OyAokDAQcJAwEHEAABAACAAAEBIADC6wsAAAAAF2oUt/X69ELjeX2nTof+fZ10l+OyAokDAQcJAwEHENkMak8AAAAA')
1125          assert_equal(analysis['next'], 'creator')
1126          assert_equal(analysis['error'], 'PSBT is not valid. Input 0 spends unspendable output')
1127  
1128          self.log.info("PSBT with invalid values should have error message and Creator as next")
1129          analysis = self.nodes[0].analyzepsbt('cHNidP8BAHECAAAAAfA00BFgAm6tp86RowwH6BMImQNL5zXUcTT97XoLGz0BAAAAAAD/////AgD5ApUAAAAAFgAUKNw0x8HRctAgmvoevm4u1SbN7XL87QKVAAAAABYAFPck4gF7iL4NL4wtfRAKgQbghiTUAAAAAAABAR8AgIFq49AHABYAFJUDtxf2PHo641HEOBOAIvFMNTr2AAAA')
1130          assert_equal(analysis['next'], 'creator')
1131          assert_equal(analysis['error'], 'PSBT is not valid. Input 0 has invalid value')
1132  
1133          self.log.info("PSBT with signed, but not finalized, inputs should have Finalizer as next")
1134          analysis = self.nodes[0].analyzepsbt('cHNidP8BAHECAAAAAZYezcxdnbXoQCmrD79t/LzDgtUo9ERqixk8wgioAobrAAAAAAD9////AlDDAAAAAAAAFgAUy/UxxZuzZswcmFnN/E9DGSiHLUsuGPUFAAAAABYAFLsH5o0R38wXx+X2cCosTMCZnQ4baAAAAAABAR8A4fUFAAAAABYAFOBI2h5thf3+Lflb2LGCsVSZwsltIgIC/i4dtVARCRWtROG0HHoGcaVklzJUcwo5homgGkSNAnJHMEQCIGx7zKcMIGr7cEES9BR4Kdt/pzPTK3fKWcGyCJXb7MVnAiALOBgqlMH4GbC1HDh/HmylmO54fyEy4lKde7/BT/PWxwEBAwQBAAAAIgYC/i4dtVARCRWtROG0HHoGcaVklzJUcwo5homgGkSNAnIYDwVpQ1QAAIABAACAAAAAgAAAAAAAAAAAAAAiAgL+CIiB59NSCssOJRGiMYQK1chahgAaaJpIXE41Cyir+xgPBWlDVAAAgAEAAIAAAACAAQAAAAAAAAAA')
1135          assert_equal(analysis['next'], 'finalizer')
1136  
1137          analysis = self.nodes[0].analyzepsbt('cHNidP8BAHECAAAAAfA00BFgAm6tp86RowwH6BMImQNL5zXUcTT97XoLGz0BAAAAAAD/////AgCAgWrj0AcAFgAUKNw0x8HRctAgmvoevm4u1SbN7XL87QKVAAAAABYAFPck4gF7iL4NL4wtfRAKgQbghiTUAAAAAAABAR8A8gUqAQAAABYAFJUDtxf2PHo641HEOBOAIvFMNTr2AAAA')
1138          assert_equal(analysis['next'], 'creator')
1139          assert_equal(analysis['error'], 'PSBT is not valid. Output amount invalid')
1140  
1141          assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].analyzepsbt, "cHNidP8BAJoCAAAAAkvEW8NnDtdNtDpsmze+Ht2LH35IJcKv00jKAlUs21RrAwAAAAD/////S8Rbw2cO1020OmybN74e3Ysffkglwq/TSMoCVSzbVGsBAAAAAP7///8CwLYClQAAAAAWABSNJKzjaUb3uOxixsvh1GGE3fW7zQD5ApUAAAAAFgAUKNw0x8HRctAgmvoevm4u1SbN7XIAAAAAAAEAnQIAAAACczMa321tVHuN4GKWKRncycI22aX3uXgwSFUKM2orjRsBAAAAAP7///9zMxrfbW1Ue43gYpYpGdzJwjbZpfe5eDBIVQozaiuNGwAAAAAA/v///wIA+QKVAAAAABl2qRT9zXUVA8Ls5iVqynLHe5/vSe1XyYisQM0ClQAAAAAWABRmWQUcjSjghQ8/uH4Bn/zkakwLtAAAAAAAAQEfQM0ClQAAAAAWABRmWQUcjSjghQ8/uH4Bn/zkakwLtAAAAA==")
1142  
1143          assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].walletprocesspsbt, "cHNidP8BAJoCAAAAAkvEW8NnDtdNtDpsmze+Ht2LH35IJcKv00jKAlUs21RrAwAAAAD/////S8Rbw2cO1020OmybN74e3Ysffkglwq/TSMoCVSzbVGsBAAAAAP7///8CwLYClQAAAAAWABSNJKzjaUb3uOxixsvh1GGE3fW7zQD5ApUAAAAAFgAUKNw0x8HRctAgmvoevm4u1SbN7XIAAAAAAAEAnQIAAAACczMa321tVHuN4GKWKRncycI22aX3uXgwSFUKM2orjRsBAAAAAP7///9zMxrfbW1Ue43gYpYpGdzJwjbZpfe5eDBIVQozaiuNGwAAAAAA/v///wIA+QKVAAAAABl2qRT9zXUVA8Ls5iVqynLHe5/vSe1XyYisQM0ClQAAAAAWABRmWQUcjSjghQ8/uH4Bn/zkakwLtAAAAAAAAQEfQM0ClQAAAAAWABRmWQUcjSjghQ8/uH4Bn/zkakwLtAAAAA==")
1144  
1145          self.log.info("Test that we can fund psbts with external inputs specified")
1146  
1147          privkey, _ = generate_keypair(wif=True)
1148  
1149          self.nodes[1].createwallet("extfund")
1150          wallet = self.nodes[1].get_wallet_rpc("extfund")
1151  
1152          # Make a weird but signable script. sh(wsh(pkh())) descriptor accomplishes this
1153          desc = descsum_create("sh(wsh(pkh({})))".format(privkey))
1154          res = self.nodes[0].importdescriptors([{"desc": desc, "timestamp": "now"}])
1155          assert_equal(res[0]["success"], True)
1156          addr = self.nodes[0].deriveaddresses(desc)[0]
1157          addr_info = self.nodes[0].getaddressinfo(addr)
1158  
1159          self.nodes[0].sendtoaddress(addr, 10)
1160          self.nodes[0].sendtoaddress(wallet.getnewaddress(), 10)
1161          self.generate(self.nodes[0], 6)
1162          ext_utxo = self.nodes[0].listunspent(addresses=[addr])[0]
1163  
1164          # An external input without solving data should result in an error
1165          assert_raises_rpc_error(-4, "Not solvable pre-selected input COutPoint(%s, %s)" % (ext_utxo["txid"][0:10], ext_utxo["vout"]), wallet.walletcreatefundedpsbt, [ext_utxo], {self.nodes[0].getnewaddress(): 15})
1166  
1167          # But funding should work when the solving data is provided
1168          psbt = wallet.walletcreatefundedpsbt([ext_utxo], {self.nodes[0].getnewaddress(): 15}, 0, {"add_inputs": True, "solving_data": {"pubkeys": [addr_info['pubkey']], "scripts": [addr_info["embedded"]["scriptPubKey"], addr_info["embedded"]["embedded"]["scriptPubKey"]]}})
1169          signed = wallet.walletprocesspsbt(psbt['psbt'])
1170          assert_equal(signed['complete'], False)
1171          signed = self.nodes[0].walletprocesspsbt(signed['psbt'])
1172          assert_equal(signed['complete'], True)
1173  
1174          psbt = wallet.walletcreatefundedpsbt([ext_utxo], {self.nodes[0].getnewaddress(): 15}, 0, {"add_inputs": True, "solving_data":{"descriptors": [desc]}})
1175          signed = wallet.walletprocesspsbt(psbt['psbt'])
1176          assert_equal(signed['complete'], False)
1177          signed = self.nodes[0].walletprocesspsbt(signed['psbt'])
1178          assert_equal(signed['complete'], True)
1179          final = signed['hex']
1180  
1181          dec = self.nodes[0].decodepsbt(signed["psbt"])
1182          for psbt_in in dec["inputs"]:
1183              if psbt_in["previous_txid"] == ext_utxo["txid"] and psbt_in["previous_vout"] == ext_utxo["vout"]:
1184                  break
1185          scriptsig_hex = psbt_in["final_scriptSig"]["hex"] if "final_scriptSig" in psbt_in else ""
1186          witness_stack_hex = psbt_in["final_scriptwitness"] if "final_scriptwitness" in psbt_in else None
1187          input_weight = calculate_input_weight(scriptsig_hex, witness_stack_hex)
1188          low_input_weight = input_weight // 2
1189          high_input_weight = input_weight * 2
1190  
1191          # Input weight error conditions
1192          assert_raises_rpc_error(
1193              -8,
1194              "Input weights should be specified in inputs rather than in options.",
1195              wallet.walletcreatefundedpsbt,
1196              inputs=[ext_utxo],
1197              outputs={self.nodes[0].getnewaddress(): 15},
1198              options={"input_weights": [{"txid": ext_utxo["txid"], "vout": ext_utxo["vout"], "weight": 1000}]}
1199          )
1200  
1201          # Funding should also work if the input weight is provided
1202          psbt = wallet.walletcreatefundedpsbt(
1203              inputs=[{"txid": ext_utxo["txid"], "vout": ext_utxo["vout"], "weight": input_weight}],
1204              outputs={self.nodes[0].getnewaddress(): 15},
1205              add_inputs=True,
1206          )
1207          signed = wallet.walletprocesspsbt(psbt["psbt"])
1208          signed = self.nodes[0].walletprocesspsbt(signed["psbt"])
1209          final = signed["hex"]
1210          assert_equal(self.nodes[0].testmempoolaccept([final])[0]["allowed"], True)
1211          # Reducing the weight should have a lower fee
1212          psbt2 = wallet.walletcreatefundedpsbt(
1213              inputs=[{"txid": ext_utxo["txid"], "vout": ext_utxo["vout"], "weight": low_input_weight}],
1214              outputs={self.nodes[0].getnewaddress(): 15},
1215              add_inputs=True,
1216          )
1217          assert_greater_than(psbt["fee"], psbt2["fee"])
1218          # Increasing the weight should have a higher fee
1219          psbt2 = wallet.walletcreatefundedpsbt(
1220              inputs=[{"txid": ext_utxo["txid"], "vout": ext_utxo["vout"], "weight": high_input_weight}],
1221              outputs={self.nodes[0].getnewaddress(): 15},
1222              add_inputs=True,
1223          )
1224          assert_greater_than(psbt2["fee"], psbt["fee"])
1225          # The provided weight should override the calculated weight when solving data is provided
1226          psbt3 = wallet.walletcreatefundedpsbt(
1227              inputs=[{"txid": ext_utxo["txid"], "vout": ext_utxo["vout"], "weight": high_input_weight}],
1228              outputs={self.nodes[0].getnewaddress(): 15},
1229              add_inputs=True, solving_data={"descriptors": [desc]},
1230          )
1231          assert_equal(psbt2["fee"], psbt3["fee"])
1232  
1233          # Import the external utxo descriptor so that we can sign for it from the test wallet
1234          res = wallet.importdescriptors([{"desc": desc, "timestamp": "now"}])
1235          assert_equal(res[0]["success"], True)
1236          # The provided weight should override the calculated weight for a wallet input
1237          psbt3 = wallet.walletcreatefundedpsbt(
1238              inputs=[{"txid": ext_utxo["txid"], "vout": ext_utxo["vout"], "weight": high_input_weight}],
1239              outputs={self.nodes[0].getnewaddress(): 15},
1240              add_inputs=True,
1241          )
1242          assert_equal(psbt2["fee"], psbt3["fee"])
1243  
1244          self.log.info("Test signing inputs that the wallet has keys for but is not watching the scripts")
1245          self.nodes[1].createwallet(wallet_name="scriptwatchonly", disable_private_keys=True)
1246          watchonly = self.nodes[1].get_wallet_rpc("scriptwatchonly")
1247  
1248          privkey, pubkey = generate_keypair(wif=True)
1249  
1250          desc = descsum_create("wsh(pkh({}))".format(pubkey.hex()))
1251          res = watchonly.importdescriptors([{"desc": desc, "timestamp": "now"}])
1252          assert_equal(res[0]["success"], True)
1253          addr = self.nodes[0].deriveaddresses(desc)[0]
1254          self.nodes[0].sendtoaddress(addr, 10)
1255          self.generate(self.nodes[0], 1)
1256          wallet_importprivkey(self.nodes[0], privkey, "now")
1257  
1258          psbt = watchonly.sendall([wallet.getnewaddress()])["psbt"]
1259          signed_tx = self.nodes[0].walletprocesspsbt(psbt)
1260          self.nodes[0].sendrawtransaction(signed_tx["hex"])
1261  
1262          # Same test but for taproot
1263          privkey, pubkey = generate_keypair(wif=True)
1264  
1265          desc = descsum_create("tr({},pk({}))".format(H_POINT, pubkey.hex()))
1266          res = watchonly.importdescriptors([{"desc": desc, "timestamp": "now"}])
1267          assert_equal(res[0]["success"], True)
1268          addr = self.nodes[0].deriveaddresses(desc)[0]
1269          self.nodes[0].sendtoaddress(addr, 10)
1270          self.generate(self.nodes[0], 1)
1271          self.nodes[0].importdescriptors([{"desc": descsum_create("tr({})".format(privkey)), "timestamp":"now"}])
1272  
1273          psbt = watchonly.sendall([wallet.getnewaddress(), addr])["psbt"]
1274          processed_psbt = self.nodes[0].walletprocesspsbt(psbt)
1275          txid = self.nodes[0].sendrawtransaction(processed_psbt["hex"])
1276          vout = find_vout_for_address(self.nodes[0], txid, addr)
1277  
1278          # Make sure tap tree is in psbt
1279          parsed_psbt = PSBT.from_base64(psbt)
1280          assert_greater_than(len(parsed_psbt.o[vout].map[PSBT_OUT_TAP_TREE]), 0)
1281          assert "taproot_tree" in self.nodes[0].decodepsbt(psbt)["outputs"][vout]
1282          parsed_psbt.make_blank()
1283          comb_psbt = self.nodes[0].combinepsbt([psbt, parsed_psbt.to_base64()])
1284          assert_equal(comb_psbt, psbt)
1285  
1286          self.log.info("Test that walletprocesspsbt both updates and signs a non-updated psbt containing Taproot inputs")
1287          addr = self.nodes[0].getnewaddress("", "bech32m")
1288          utxo = self.create_outpoints(self.nodes[0], outputs=[{addr: 1}])[0]
1289          psbt = self.nodes[0].createpsbt([utxo], [{self.nodes[0].getnewaddress(): 0.9999}])
1290          signed = self.nodes[0].walletprocesspsbt(psbt)
1291          rawtx = signed["hex"]
1292          self.nodes[0].sendrawtransaction(rawtx)
1293          self.generate(self.nodes[0], 1)
1294  
1295          # Make sure tap tree is not in psbt
1296          parsed_psbt = PSBT.from_base64(psbt)
1297          assert PSBT_OUT_TAP_TREE not in parsed_psbt.o[0].map
1298          assert "taproot_tree" not in self.nodes[0].decodepsbt(psbt)["outputs"][0]
1299          parsed_psbt.make_blank()
1300          comb_psbt = self.nodes[0].combinepsbt([psbt, parsed_psbt.to_base64()])
1301          assert_equal(comb_psbt, psbt)
1302  
1303          self.log.info("Test walletprocesspsbt raises if an invalid sighashtype is passed")
1304          assert_raises_rpc_error(-8, "'all' is not a valid sighash parameter.", self.nodes[0].walletprocesspsbt, psbt=psbt, sighashtype="all")
1305  
1306          self.log.info("Test decoding PSBT with per-input preimage types")
1307          # note that the decodepsbt RPC doesn't check whether preimages and hashes match
1308          hash_ripemd160, preimage_ripemd160 = randbytes(20), randbytes(50)
1309          hash_sha256, preimage_sha256 = randbytes(32), randbytes(50)
1310          hash_hash160, preimage_hash160 = randbytes(20), randbytes(50)
1311          hash_hash256, preimage_hash256 = randbytes(32), randbytes(50)
1312  
1313          tx = CTransaction()
1314          tx.vin = [CTxIn(outpoint=COutPoint(hash=int('aa' * 32, 16), n=0), scriptSig=b""),
1315                    CTxIn(outpoint=COutPoint(hash=int('bb' * 32, 16), n=0), scriptSig=b""),
1316                    CTxIn(outpoint=COutPoint(hash=int('cc' * 32, 16), n=0), scriptSig=b""),
1317                    CTxIn(outpoint=COutPoint(hash=int('dd' * 32, 16), n=0), scriptSig=b"")]
1318          tx.vout = [CTxOut(nValue=0, scriptPubKey=b"")]
1319          psbt = PSBT()
1320          psbt.g = PSBTMap({PSBT_GLOBAL_UNSIGNED_TX: tx.serialize()})
1321          psbt.i = [PSBTMap({bytes([PSBT_IN_RIPEMD160]) + hash_ripemd160: preimage_ripemd160}),
1322                    PSBTMap({bytes([PSBT_IN_SHA256]) + hash_sha256: preimage_sha256}),
1323                    PSBTMap({bytes([PSBT_IN_HASH160]) + hash_hash160: preimage_hash160}),
1324                    PSBTMap({bytes([PSBT_IN_HASH256]) + hash_hash256: preimage_hash256})]
1325          psbt.o = [PSBTMap()]
1326          res_inputs = self.nodes[0].decodepsbt(psbt.to_base64())["inputs"]
1327          assert_equal(len(res_inputs), 4)
1328          preimage_keys = ["ripemd160_preimages", "sha256_preimages", "hash160_preimages", "hash256_preimages"]
1329          expected_hashes = [hash_ripemd160, hash_sha256, hash_hash160, hash_hash256]
1330          expected_preimages = [preimage_ripemd160, preimage_sha256, preimage_hash160, preimage_hash256]
1331          for res_input, preimage_key, hash, preimage in zip(res_inputs, preimage_keys, expected_hashes, expected_preimages):
1332              assert preimage_key in res_input
1333              assert_equal(len(res_input[preimage_key]), 1)
1334              assert hash.hex() in res_input[preimage_key]
1335              assert_equal(res_input[preimage_key][hash.hex()], preimage.hex())
1336  
1337          self.test_decodepsbt_musig2_input_output_types()
1338  
1339          self.test_combinepsbt_preserves_proprietary_fields()
1340  
1341          self.log.info("Test that combining PSBTs with different transactions fails")
1342          tx = CTransaction()
1343          tx.vin = [CTxIn(outpoint=COutPoint(hash=int('aa' * 32, 16), n=0), scriptSig=b"")]
1344          tx.vout = [CTxOut(nValue=0, scriptPubKey=b"")]
1345          psbt1 = PSBT(g=PSBTMap({PSBT_GLOBAL_UNSIGNED_TX: tx.serialize()}), i=[PSBTMap()], o=[PSBTMap()]).to_base64()
1346          tx.vout[0].nValue += 1  # slightly modify tx
1347          psbt2 = PSBT(g=PSBTMap({PSBT_GLOBAL_UNSIGNED_TX: tx.serialize()}), i=[PSBTMap()], o=[PSBTMap()]).to_base64()
1348          assert_raises_rpc_error(-8, "PSBTs not compatible (different transactions)", self.nodes[0].combinepsbt, [psbt1, psbt2])
1349          assert_equal(self.nodes[0].combinepsbt([psbt1, psbt1]), psbt1)
1350  
1351          self.log.info("Test that PSBT inputs are being checked via script execution")
1352          acs_prevout = CTxOut(nValue=0, scriptPubKey=CScript([OP_TRUE]))
1353          tx = CTransaction()
1354          tx.vin = [CTxIn(outpoint=COutPoint(hash=int('dd' * 32, 16), n=0), scriptSig=b"")]
1355          tx.vout = [CTxOut(nValue=0, scriptPubKey=b"")]
1356          psbt = PSBT()
1357          psbt.g = PSBTMap({PSBT_GLOBAL_UNSIGNED_TX: tx.serialize()})
1358          psbt.i = [PSBTMap({bytes([PSBT_IN_WITNESS_UTXO]) : acs_prevout.serialize()})]
1359          psbt.o = [PSBTMap()]
1360          assert_equal(self.nodes[0].finalizepsbt(psbt.to_base64()),
1361              {'hex': '0200000001dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd0000000000000000000100000000000000000000000000', 'complete': True})
1362  
1363          self.log.info("Test we don't crash when making a 0-value funded transaction at 0 fee without forcing an input selection")
1364          assert_raises_rpc_error(-4, "Transaction requires one destination of non-zero value, a non-zero feerate, or a pre-selected input", self.nodes[0].walletcreatefundedpsbt, [], [{"data": "deadbeef"}], 0, {"fee_rate": "0"})
1365  
1366          self.log.info("Test descriptorprocesspsbt updates and signs a psbt with descriptors")
1367  
1368          self.generate(self.nodes[2], 1)
1369  
1370          # Disable the wallet for node 2 since `descriptorprocesspsbt` does not use the wallet
1371          self.restart_node(2, extra_args=["-disablewallet"])
1372          self.connect_nodes(0, 2)
1373          self.connect_nodes(1, 2)
1374  
1375          key_info = get_generate_key()
1376          key = key_info.privkey
1377          address = key_info.p2wpkh_addr
1378  
1379          descriptor = descsum_create(f"wpkh({key})")
1380  
1381          utxo = self.create_outpoints(self.nodes[0], outputs=[{address: 1}])[0]
1382          self.sync_all()
1383  
1384          psbt = self.nodes[2].createpsbt([utxo], {self.nodes[0].getnewaddress(): 0.99999})
1385          decoded = self.nodes[2].decodepsbt(psbt)
1386          test_psbt_input_keys(decoded['inputs'][0], [])
1387  
1388          # Test that even if the wrong descriptor is given, `witness_utxo` and `non_witness_utxo`
1389          # are still added to the psbt
1390          alt_descriptor = descsum_create(f"wpkh({get_generate_key().privkey})")
1391          alt_psbt = self.nodes[2].descriptorprocesspsbt(psbt=psbt, descriptors=[alt_descriptor], sighashtype="ALL")["psbt"]
1392          decoded = self.nodes[2].decodepsbt(alt_psbt)
1393          test_psbt_input_keys(decoded['inputs'][0], ['witness_utxo', 'non_witness_utxo'])
1394  
1395          # Test that the psbt is not finalized and does not have bip32_derivs unless specified
1396          processed_psbt = self.nodes[2].descriptorprocesspsbt(psbt=psbt, descriptors=[descriptor], sighashtype="ALL", bip32derivs=True, finalize=False)
1397          decoded = self.nodes[2].decodepsbt(processed_psbt['psbt'])
1398          test_psbt_input_keys(decoded['inputs'][0], ['witness_utxo', 'non_witness_utxo', 'partial_signatures', 'bip32_derivs'])
1399  
1400          # If psbt not finalized, test that result does not have hex
1401          assert "hex" not in processed_psbt
1402  
1403          processed_psbt = self.nodes[2].descriptorprocesspsbt(psbt=psbt, descriptors=[descriptor], sighashtype="ALL", bip32derivs=False, finalize=True)
1404          decoded = self.nodes[2].decodepsbt(processed_psbt['psbt'])
1405          test_psbt_input_keys(decoded['inputs'][0], ['witness_utxo', 'non_witness_utxo', 'final_scriptwitness'])
1406  
1407          # Test psbt is complete
1408          assert_equal(processed_psbt['complete'], True)
1409  
1410          # Broadcast transaction
1411          self.nodes[2].sendrawtransaction(processed_psbt['hex'])
1412  
1413          self.log.info("Test descriptorprocesspsbt raises if an invalid sighashtype is passed")
1414          assert_raises_rpc_error(-8, "'all' is not a valid sighash parameter.", self.nodes[2].descriptorprocesspsbt, psbt=psbt, descriptors=[descriptor], sighashtype="all")
1415  
1416          if not self.options.usecli:
1417              self.test_sighash_mismatch()
1418          self.test_sighash_adding()
1419          self.test_psbt_named_parameter_handling()
1420          self.test_psbt_roundtrip()
1421          self.test_psbt_version()
1422  
1423  if __name__ == '__main__':
1424      PSBTTest(__file__).main()
1425