diff options
Diffstat (limited to 'test/functional/rpc_psbt.py')
-rwxr-xr-x | test/functional/rpc_psbt.py | 51 |
1 files changed, 42 insertions, 9 deletions
diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py index f7f23bc8f4..32dc2f8644 100755 --- a/test/functional/rpc_psbt.py +++ b/test/functional/rpc_psbt.py @@ -12,8 +12,6 @@ from test_framework.util import ( assert_equal, assert_greater_than, assert_raises_rpc_error, - connect_nodes, - disconnect_nodes, find_output, ) @@ -30,7 +28,7 @@ class PSBTTest(BitcoinTestFramework): self.num_nodes = 3 self.extra_args = [ ["-walletrbf=1"], - ["-walletrbf=0"], + ["-walletrbf=0", "-changetype=legacy"], [] ] self.supports_cli = False @@ -46,7 +44,7 @@ class PSBTTest(BitcoinTestFramework): # Disconnect offline node from others # Topology of test network is linear, so this one call is enough - disconnect_nodes(offline_node, 1) + self.disconnect_nodes(0, 1) # Create watchonly on online_node online_node.createwallet(wallet_name='wonline', disable_private_keys=True) @@ -80,8 +78,16 @@ class PSBTTest(BitcoinTestFramework): wonline.unloadwallet() # Reconnect - connect_nodes(self.nodes[0], 1) - connect_nodes(self.nodes[0], 2) + self.connect_nodes(0, 1) + self.connect_nodes(0, 2) + + def assert_change_type(self, psbtx, expected_type): + """Assert that the given PSBT has a change output with the given type.""" + + # The decodepsbt RPC is stateless and independent of any settings, we can always just call it on the first node + decoded_psbt = self.nodes[0].decodepsbt(psbtx["psbt"]) + changepos = psbtx["changepos"] + assert_equal(decoded_psbt["tx"]["vout"][changepos]["scriptPubKey"]["type"], expected_type) def run_test(self): # Create and fund a raw tx for sending 10 BTC @@ -94,6 +100,9 @@ class PSBTTest(BitcoinTestFramework): psbtx1 = self.nodes[0].walletcreatefundedpsbt([{"txid": utxo1['txid'], "vout": utxo1['vout']}], {self.nodes[2].getnewaddress():90}, 0, {"add_inputs": True})['psbt'] assert_equal(len(self.nodes[0].decodepsbt(psbtx1)['tx']['vin']), 2) + # Inputs argument can be null + self.nodes[0].walletcreatefundedpsbt(None, {self.nodes[2].getnewaddress():10}) + # Node 1 should not be able to add anything to it but still return the psbtx same as before psbtx = self.nodes[1].walletprocesspsbt(psbtx1)['psbt'] assert_equal(psbtx1, psbtx) @@ -103,7 +112,16 @@ class PSBTTest(BitcoinTestFramework): final_tx = self.nodes[0].finalizepsbt(signed_tx)['hex'] self.nodes[0].sendrawtransaction(final_tx) - # Get pubkeys + # Manually selected inputs can be locked: + assert_equal(len(self.nodes[0].listlockunspent()), 0) + utxo1 = self.nodes[0].listunspent()[0] + psbtx1 = self.nodes[0].walletcreatefundedpsbt([{"txid": utxo1['txid'], "vout": utxo1['vout']}], {self.nodes[2].getnewaddress():1}, 0,{"lockUnspents": True})["psbt"] + assert_equal(len(self.nodes[0].listlockunspent()), 1) + + # Locks are ignored for manually selected inputs + self.nodes[0].walletcreatefundedpsbt([{"txid": utxo1['txid'], "vout": utxo1['vout']}], {self.nodes[2].getnewaddress():1}, 0) + + # Create p2sh, p2wpkh, and p2wsh addresses pubkey0 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())['pubkey'] pubkey1 = self.nodes[1].getaddressinfo(self.nodes[1].getnewaddress())['pubkey'] pubkey2 = self.nodes[2].getaddressinfo(self.nodes[2].getnewaddress())['pubkey'] @@ -172,8 +190,8 @@ class PSBTTest(BitcoinTestFramework): # feeRate of 10 BTC / KB produces a total fee well above -maxtxfee # previously this was silently capped at -maxtxfee - assert_raises_rpc_error(-4, "Fee exceeds maximum configured by -maxtxfee", self.nodes[1].walletcreatefundedpsbt, [{"txid":txid,"vout":p2wpkh_pos},{"txid":txid,"vout":p2sh_p2wpkh_pos},{"txid":txid,"vout":p2pkh_pos}], {self.nodes[1].getnewaddress():29.99}, 0, {"feeRate": 10, "add_inputs": True}) - assert_raises_rpc_error(-4, "Fee exceeds maximum configured by -maxtxfee", self.nodes[1].walletcreatefundedpsbt, [{"txid":txid,"vout":p2wpkh_pos},{"txid":txid,"vout":p2sh_p2wpkh_pos},{"txid":txid,"vout":p2pkh_pos}], {self.nodes[1].getnewaddress():1}, 0, {"feeRate": 10, "add_inputs": False}) + assert_raises_rpc_error(-4, "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)", self.nodes[1].walletcreatefundedpsbt, [{"txid":txid,"vout":p2wpkh_pos},{"txid":txid,"vout":p2sh_p2wpkh_pos},{"txid":txid,"vout":p2pkh_pos}], {self.nodes[1].getnewaddress():29.99}, 0, {"feeRate": 10, "add_inputs": True}) + assert_raises_rpc_error(-4, "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)", self.nodes[1].walletcreatefundedpsbt, [{"txid":txid,"vout":p2wpkh_pos},{"txid":txid,"vout":p2sh_p2wpkh_pos},{"txid":txid,"vout":p2pkh_pos}], {self.nodes[1].getnewaddress():1}, 0, {"feeRate": 10, "add_inputs": False}) # partially sign multisig things with node 1 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}, options={'changeAddress': self.nodes[1].getrawchangeaddress()})['psbt'] @@ -289,6 +307,21 @@ class PSBTTest(BitcoinTestFramework): # when attempting BnB coin selection self.nodes[0].walletcreatefundedpsbt([], [{self.nodes[2].getnewaddress():unspent["amount"]+1}], block_height+2, {"changeAddress":self.nodes[1].getnewaddress()}, False) + # Make sure the wallet's change type is respected by default + small_output = {self.nodes[0].getnewaddress():0.1} + psbtx_native = self.nodes[0].walletcreatefundedpsbt([], [small_output]) + self.assert_change_type(psbtx_native, "witness_v0_keyhash") + psbtx_legacy = self.nodes[1].walletcreatefundedpsbt([], [small_output]) + self.assert_change_type(psbtx_legacy, "pubkeyhash") + + # Make sure the change type of the wallet can also be overwritten + psbtx_np2wkh = self.nodes[1].walletcreatefundedpsbt([], [small_output], 0, {"change_type":"p2sh-segwit"}) + self.assert_change_type(psbtx_np2wkh, "scripthash") + + # Make sure the change type cannot be specified if a change address is given + invalid_options = {"change_type":"legacy","changeAddress":self.nodes[0].getnewaddress()} + assert_raises_rpc_error(-8, "both change address and address type options", self.nodes[0].walletcreatefundedpsbt, [], [small_output], 0, invalid_options) + # Regression test for 14473 (mishandling of already-signed witness transaction): psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid":unspent["txid"], "vout":unspent["vout"]}], [{self.nodes[2].getnewaddress():unspent["amount"]+1}], 0, {"add_inputs": True}) complete_psbt = self.nodes[0].walletprocesspsbt(psbtx_info["psbt"]) |