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