Skip to content

Commit

Permalink
wallet: Precompute Txdata after setting PSBT inputs' UTXOs
Browse files Browse the repository at this point in the history
If we are given a PSBT that is missing one or more input UTXOs, our
PrecomputedTransactionData will be incorrect and missing information
that it should otherwise have, and therefore we may not produce a
signature when we should. To avoid this problem, we can do the
precomputation after we have set the UTXOs the wallet is able to set for
the PSBT.

Also adds a test for this behavior.
  • Loading branch information
achow101 committed Jul 11, 2022
1 parent 0817cc3 commit d2ed976
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 1 deletion.
3 changes: 2 additions & 1 deletion src/wallet/wallet.cpp
Expand Up @@ -1969,7 +1969,6 @@ TransactionError CWallet::FillPSBT(PartiallySignedTransaction& psbtx, bool& comp
if (n_signed) {
*n_signed = 0;
}
const PrecomputedTransactionData txdata = PrecomputePSBTData(psbtx);
LOCK(cs_wallet);
// Get all of the previous transactions
for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
Expand All @@ -1993,6 +1992,8 @@ TransactionError CWallet::FillPSBT(PartiallySignedTransaction& psbtx, bool& comp
}
}

const PrecomputedTransactionData txdata = PrecomputePSBTData(psbtx);

// Fill in information from ScriptPubKeyMans
for (ScriptPubKeyMan* spk_man : GetAllScriptPubKeyMans()) {
int n_signed_this_spkm = 0;
Expand Down
11 changes: 11 additions & 0 deletions test/functional/rpc_psbt.py
Expand Up @@ -21,6 +21,7 @@
assert_greater_than,
assert_raises_rpc_error,
find_output,
find_vout_for_address,
)
from test_framework.wallet_util import bytes_to_wif

Expand Down Expand Up @@ -764,5 +765,15 @@ def test_psbt_input_keys(psbt_input, keys):
psbt = self.nodes[0].walletprocesspsbt(psbt)["psbt"]
self.nodes[0].sendrawtransaction(self.nodes[0].finalizepsbt(psbt)["hex"])

self.log.info("Test that walletprocesspsbt both updates and signs a non-updated psbt containing Taproot inputs")
addr = self.nodes[0].getnewaddress("", "bech32m")
txid = self.nodes[0].sendtoaddress(addr, 1)
vout = find_vout_for_address(self.nodes[0], txid, addr)
psbt = self.nodes[0].createpsbt([{"txid": txid, "vout": vout}], [{self.nodes[0].getnewaddress(): 0.9999}])
signed = self.nodes[0].walletprocesspsbt(psbt)
rawtx = self.nodes[0].finalizepsbt(signed["psbt"])["hex"]
self.nodes[0].sendrawtransaction(rawtx)
self.generate(self.nodes[0], 1)

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

0 comments on commit d2ed976

Please sign in to comment.