Skip to content

Commit

Permalink
signpsbt: add utxo info to inputs
Browse files Browse the repository at this point in the history
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 ElementsProject#5499 ?
  • Loading branch information
niftynei authored and whitslack committed Oct 7, 2022
1 parent 96bffac commit f0cf2c9
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 0 deletions.
29 changes: 29 additions & 0 deletions tests/test_wallet.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
27 changes: 27 additions & 0 deletions wallet/walletrpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down

0 comments on commit f0cf2c9

Please sign in to comment.