signpsbt: add utxo info to inputs

If you build a PSBT externally from CLN and attempt to sign for the
output, we would crash. Now we don't crash.

Changelog-Changed: JSON-RPC: `signpsbt` will now add redeemscript + witness-utxo to the PSBT for an input that we can sign for, before signing it.

Fixes #5499 ?
This commit is contained in:
niftynei 2022-08-11 16:29:58 -05:00 committed by neil saitug
parent 63f8c74da9
commit 4984014578
2 changed files with 56 additions and 0 deletions

View file

@ -695,6 +695,35 @@ def test_utxopsbt(node_factory, bitcoind, chainparams):
reservedok=True)
def test_sign_external_psbt(node_factory, bitcoind, chainparams):
"""
A PSBT w/ one of our inputs should be signable (we can fill
in the required UTXO data).
"""
l1 = node_factory.get_node(feerates=(7500, 7500, 7500, 7500))
amount = 1000000
total_outs = 4
# Add a medley of funds to withdraw later, bech32 + p2sh-p2wpkh
for i in range(total_outs // 2):
bitcoind.rpc.sendtoaddress(l1.rpc.newaddr()['bech32'],
amount / 10**8)
bitcoind.rpc.sendtoaddress(l1.rpc.newaddr('p2sh-segwit')['p2sh-segwit'], amount / 10**8)
bitcoind.generate_block(1)
wait_for(lambda: len(l1.rpc.listfunds()['outputs']) == total_outs)
# Build a PSBT using all our inputs, externally
inputs = []
for inp in l1.rpc.listfunds()['outputs']:
inputs.append({'txid': inp['txid'], 'vout': inp['output']})
addr = l1.rpc.newaddr()['bech32']
psbt = bitcoind.rpc.createpsbt(inputs, [{addr: (amount * 3) / 10**8}])
l1.rpc.reserveinputs(psbt)
l1.rpc.signpsbt(psbt)
def test_sign_and_send_psbt(node_factory, bitcoind, chainparams):
"""
Tests for the sign + send psbt RPCs

View file

@ -648,6 +648,33 @@ static struct command_result *match_psbt_inputs_to_utxos(struct command *cmd,
"Aborting PSBT signing. UTXO %s is not reserved",
type_to_string(tmpctx, struct bitcoin_outpoint,
&utxo->outpoint));
/* If the psbt doesn't have the UTXO info yet, add it.
* We only add the witness_utxo for this */
if (!psbt->inputs[i].utxo && !psbt->inputs[i].witness_utxo) {
u8 *scriptPubKey;
if (utxo->is_p2sh) {
struct pubkey key;
u8 *redeemscript;
int wally_err;
bip32_pubkey(cmd->ld->wallet->bip32_base, &key,
utxo->keyindex);
redeemscript = bitcoin_redeem_p2sh_p2wpkh(tmpctx, &key);
scriptPubKey = scriptpubkey_p2sh(tmpctx, redeemscript);
tal_wally_start();
wally_err = wally_psbt_input_set_redeem_script(&psbt->inputs[i],
redeemscript,
tal_bytelen(redeemscript));
assert(wally_err == WALLY_OK);
tal_wally_end(psbt);
} else
scriptPubKey = utxo->scriptPubkey;
psbt_input_set_wit_utxo(psbt, i, scriptPubKey, utxo->amount);
}
tal_arr_expand(utxos, utxo);
}