Skip to content

Commit f6df989

Browse files
committed
Merge #14197: [psbt] Convert non-witness UTXOs to witness if witness sig created
862d159 Add test for conversion from non-witness to witness UTXO (Pieter Wuille) f8c1714 Convert non-witness UTXOs to witness if witness sig created (Andrew Chow) Pull request description: If a witness signature was created when a non-witness UTXO is used, convert the non-witness UTXO to a witness one. Port of #14196 to master. Tree-SHA512: 2235eeb008ffa48e821628032d689e4a83bff6c29b93fa050ab2ee492b0e67b3a30f29a680d4a0e574e05c3a2f9edf0005e161fbe25b7aef2acd034a2424e2f2
2 parents 9899e65 + 862d159 commit f6df989

File tree

2 files changed

+51
-1
lines changed

2 files changed

+51
-1
lines changed

src/script/sign.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,11 @@ bool SignPSBTInput(const SigningProvider& provider, const CMutableTransaction& t
280280
if (require_witness_sig && !sigdata.witness) return false;
281281
input.FromSignatureData(sigdata);
282282

283+
if (sigdata.witness) {
284+
assert(!utxo.IsNull());
285+
input.witness_utxo = utxo;
286+
}
287+
283288
// If both UTXO types are present, drop the unnecessary one.
284289
if (input.non_witness_utxo && !input.witness_utxo.IsNull()) {
285290
if (sigdata.witness) {

test/functional/rpc_psbt.py

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"""
77

88
from test_framework.test_framework import BitcoinTestFramework
9-
from test_framework.util import assert_equal, assert_raises_rpc_error, find_output
9+
from test_framework.util import assert_equal, assert_raises_rpc_error, find_output, disconnect_nodes, connect_nodes_bi, sync_blocks
1010

1111
import json
1212
import os
@@ -23,6 +23,45 @@ def set_test_params(self):
2323
def skip_test_if_missing_module(self):
2424
self.skip_if_no_wallet()
2525

26+
def test_utxo_conversion(self):
27+
mining_node = self.nodes[2]
28+
offline_node = self.nodes[0]
29+
online_node = self.nodes[1]
30+
31+
# Disconnect offline node from others
32+
disconnect_nodes(offline_node, 1)
33+
disconnect_nodes(online_node, 0)
34+
disconnect_nodes(offline_node, 2)
35+
disconnect_nodes(mining_node, 0)
36+
37+
# Mine a transaction that credits the offline address
38+
offline_addr = offline_node.getnewaddress(address_type="p2sh-segwit")
39+
online_addr = online_node.getnewaddress(address_type="p2sh-segwit")
40+
online_node.importaddress(offline_addr, "", False)
41+
mining_node.sendtoaddress(address=offline_addr, amount=1.0)
42+
mining_node.generate(nblocks=1)
43+
sync_blocks([mining_node, online_node])
44+
45+
# Construct an unsigned PSBT on the online node (who doesn't know the output is Segwit, so will include a non-witness UTXO)
46+
utxos = online_node.listunspent(addresses=[offline_addr])
47+
raw = online_node.createrawtransaction([{"txid":utxos[0]["txid"], "vout":utxos[0]["vout"]}],[{online_addr:0.9999}])
48+
psbt = online_node.walletprocesspsbt(online_node.converttopsbt(raw))["psbt"]
49+
assert("non_witness_utxo" in mining_node.decodepsbt(psbt)["inputs"][0])
50+
51+
# Have the offline node sign the PSBT (which will update the UTXO to segwit)
52+
signed_psbt = offline_node.walletprocesspsbt(psbt)["psbt"]
53+
assert("witness_utxo" in mining_node.decodepsbt(signed_psbt)["inputs"][0])
54+
55+
# Make sure we can mine the resulting transaction
56+
txid = mining_node.sendrawtransaction(mining_node.finalizepsbt(signed_psbt)["hex"])
57+
mining_node.generate(1)
58+
sync_blocks([mining_node, online_node])
59+
assert_equal(online_node.gettxout(txid,0)["confirmations"], 1)
60+
61+
# Reconnect
62+
connect_nodes_bi(self.nodes, 0, 1)
63+
connect_nodes_bi(self.nodes, 0, 2)
64+
2665
def run_test(self):
2766
# Create and fund a raw tx for sending 10 BTC
2867
psbtx1 = self.nodes[0].walletcreatefundedpsbt([], {self.nodes[2].getnewaddress():10})['psbt']
@@ -224,6 +263,12 @@ def run_test(self):
224263
extracted = self.nodes[2].finalizepsbt(extractor['extract'], True)['hex']
225264
assert_equal(extracted, extractor['result'])
226265

266+
# Unload extra wallets
267+
for i, signer in enumerate(signers):
268+
self.nodes[2].unloadwallet("wallet{}".format(i))
269+
270+
self.test_utxo_conversion()
271+
227272

228273
if __name__ == '__main__':
229274
PSBTTest().main()

0 commit comments

Comments
 (0)