aboutsummaryrefslogtreecommitdiff
path: root/test/functional/rpc_psbt.py
diff options
context:
space:
mode:
Diffstat (limited to 'test/functional/rpc_psbt.py')
-rwxr-xr-xtest/functional/rpc_psbt.py58
1 files changed, 57 insertions, 1 deletions
diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py
index 54dc871448..ba3818bf24 100755
--- a/test/functional/rpc_psbt.py
+++ b/test/functional/rpc_psbt.py
@@ -6,7 +6,7 @@
"""
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import assert_equal, assert_raises_rpc_error, find_output
+from test_framework.util import assert_equal, assert_raises_rpc_error, find_output, disconnect_nodes, connect_nodes_bi, sync_blocks
import json
import os
@@ -23,6 +23,45 @@ class PSBTTest(BitcoinTestFramework):
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
+ def test_utxo_conversion(self):
+ mining_node = self.nodes[2]
+ offline_node = self.nodes[0]
+ online_node = self.nodes[1]
+
+ # Disconnect offline node from others
+ disconnect_nodes(offline_node, 1)
+ disconnect_nodes(online_node, 0)
+ disconnect_nodes(offline_node, 2)
+ disconnect_nodes(mining_node, 0)
+
+ # Mine a transaction that credits the offline address
+ offline_addr = offline_node.getnewaddress(address_type="p2sh-segwit")
+ online_addr = online_node.getnewaddress(address_type="p2sh-segwit")
+ online_node.importaddress(offline_addr, "", False)
+ mining_node.sendtoaddress(address=offline_addr, amount=1.0)
+ mining_node.generate(nblocks=1)
+ sync_blocks([mining_node, online_node])
+
+ # Construct an unsigned PSBT on the online node (who doesn't know the output is Segwit, so will include a non-witness UTXO)
+ utxos = online_node.listunspent(addresses=[offline_addr])
+ raw = online_node.createrawtransaction([{"txid":utxos[0]["txid"], "vout":utxos[0]["vout"]}],[{online_addr:0.9999}])
+ psbt = online_node.walletprocesspsbt(online_node.converttopsbt(raw))["psbt"]
+ assert("non_witness_utxo" in mining_node.decodepsbt(psbt)["inputs"][0])
+
+ # Have the offline node sign the PSBT (which will update the UTXO to segwit)
+ signed_psbt = offline_node.walletprocesspsbt(psbt)["psbt"]
+ assert("witness_utxo" in mining_node.decodepsbt(signed_psbt)["inputs"][0])
+
+ # Make sure we can mine the resulting transaction
+ txid = mining_node.sendrawtransaction(mining_node.finalizepsbt(signed_psbt)["hex"])
+ mining_node.generate(1)
+ sync_blocks([mining_node, online_node])
+ assert_equal(online_node.gettxout(txid,0)["confirmations"], 1)
+
+ # Reconnect
+ connect_nodes_bi(self.nodes, 0, 1)
+ connect_nodes_bi(self.nodes, 0, 2)
+
def run_test(self):
# Create and fund a raw tx for sending 10 BTC
psbtx1 = self.nodes[0].walletcreatefundedpsbt([], {self.nodes[2].getnewaddress():10})['psbt']
@@ -168,6 +207,13 @@ class PSBTTest(BitcoinTestFramework):
assert tx_in["sequence"] > MAX_BIP125_RBF_SEQUENCE
assert_equal(decoded_psbt["tx"]["locktime"], 0)
+ # 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}])
+ complete_psbt = self.nodes[0].walletprocesspsbt(psbtx_info["psbt"])
+ double_processed_psbt = self.nodes[0].walletprocesspsbt(complete_psbt["psbt"])
+ assert_equal(complete_psbt, double_processed_psbt)
+ # We don't care about the decode result, but decoding must succeed.
+ self.nodes[0].decodepsbt(double_processed_psbt["psbt"])
# BIP 174 Test Vectors
@@ -224,6 +270,16 @@ class PSBTTest(BitcoinTestFramework):
extracted = self.nodes[2].finalizepsbt(extractor['extract'], True)['hex']
assert_equal(extracted, extractor['result'])
+ # Unload extra wallets
+ for i, signer in enumerate(signers):
+ self.nodes[2].unloadwallet("wallet{}".format(i))
+
+ self.test_utxo_conversion()
+
+ # Test that psbts with p2pkh outputs are created properly
+ p2pkh = self.nodes[0].getnewaddress(address_type='legacy')
+ psbt = self.nodes[1].walletcreatefundedpsbt([], [{p2pkh : 1}], 0, {"includeWatching" : True}, True)
+ self.nodes[0].decodepsbt(psbt['psbt'])
if __name__ == '__main__':
PSBTTest().main()