diff options
author | Wladimir J. van der Laan <laanwj@gmail.com> | 2018-11-01 16:08:17 +0100 |
---|---|---|
committer | Wladimir J. van der Laan <laanwj@gmail.com> | 2018-11-01 16:09:38 +0100 |
commit | f6df989842a1dee7e8ad779531c328456c7148a0 (patch) | |
tree | 41e95597fbf6f17e115df7ab5a155e1233b6010d | |
parent | 9899e65d84e72e638be856d5ee7b62daa4488c6d (diff) | |
parent | 862d159d635c1de219d94e030b186a745fe28eb9 (diff) |
Merge #14197: [psbt] Convert non-witness UTXOs to witness if witness sig created
862d159d635c1de219d94e030b186a745fe28eb9 Add test for conversion from non-witness to witness UTXO (Pieter Wuille)
f8c1714634445542a16ac01d128d8ad2b2810e19 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
-rw-r--r-- | src/script/sign.cpp | 5 | ||||
-rwxr-xr-x | test/functional/rpc_psbt.py | 47 |
2 files changed, 51 insertions, 1 deletions
diff --git a/src/script/sign.cpp b/src/script/sign.cpp index c721b20ced..89cc7c808c 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -280,6 +280,11 @@ bool SignPSBTInput(const SigningProvider& provider, const CMutableTransaction& t if (require_witness_sig && !sigdata.witness) return false; input.FromSignatureData(sigdata); + if (sigdata.witness) { + assert(!utxo.IsNull()); + input.witness_utxo = utxo; + } + // If both UTXO types are present, drop the unnecessary one. if (input.non_witness_utxo && !input.witness_utxo.IsNull()) { if (sigdata.witness) { diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py index 54dc871448..fca910bf64 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'] @@ -224,6 +263,12 @@ 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() + if __name__ == '__main__': PSBTTest().main() |