From d4200a52257cbe689cb01cf05a29eeff62864f48 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 12 Mar 2021 12:09:40 +1030 Subject: [PATCH] lightningd/opening_control: allow single-arg fundchannel_complete with PSBT Requiring the user to calculate the txid of the PSBT is a horrible, bad, no-good idea. Doesn't deprecate yet, so I can test that this path works while multifundchannel still uses it. Fixes: #4416 (at least for future users!) Signed-off-by: Rusty Russell Changelog-Added: JSON-RPC: `fundchannel_complete` takes a psbt parameter. --- lightningd/opening_control.c | 93 +++++++++++++++++++++++++++++------- 1 file changed, 77 insertions(+), 16 deletions(-) diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 33b49f207c94..d9a7e66ecf00 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -1,6 +1,8 @@ #include "bitcoin/feerate.h" #include +#include #include +#include #include #include #include @@ -957,22 +959,38 @@ static struct command_result *json_fundchannel_complete(struct command *cmd, struct bitcoin_txid *funding_txid; struct peer *peer; struct channel *channel; + struct wally_psbt *funding_psbt; u32 *funding_txout_num; - u16 funding_txout; - - if (!param(cmd, buffer, params, - p_req("id", param_node_id, &id), - p_req("txid", param_txid, &funding_txid), - p_req("txout", param_number, &funding_txout_num), - NULL)) - return command_param_failed(); - - if (*funding_txout_num > UINT16_MAX) - return command_fail(cmd, LIGHTNINGD, - "Invalid parameter: funding tx vout too large %u", - *funding_txout_num); + struct funding_channel *fc; + bool old_api; + + /* params is NULL for initial parameter desc generation! */ + if (params /* FIXME: && deprecated_apis */) { + /* We used to have a three-arg version. */ + if (params->type == JSMN_ARRAY) + old_api = (params->size == 3); + else + old_api = (json_get_member(buffer, params, "txid") + != NULL); + if (old_api) { + if (!param(cmd, buffer, params, + p_req("id", param_node_id, &id), + p_req("txid", param_txid, &funding_txid), + p_req("txout", param_number, &funding_txout_num), + NULL)) + return command_param_failed(); + } + } else + old_api = false; + + if (!old_api) { + if (!param(cmd, buffer, params, + p_req("id", param_node_id, &id), + p_req("psbt", param_psbt, &funding_psbt), + NULL)) + return command_param_failed(); + } - funding_txout = *funding_txout_num; peer = peer_by_id(cmd->ld, id); if (!peer) { return command_fail(cmd, FUNDING_UNKNOWN_PEER, "Unknown peer"); @@ -992,11 +1010,54 @@ static struct command_result *json_fundchannel_complete(struct command *cmd, if (peer->uncommitted_channel->fc->cmd) return command_fail(cmd, LIGHTNINGD, "Channel funding in progress."); + fc = peer->uncommitted_channel->fc; + + if (!old_api) { + /* Figure out the correct output, and perform sanity checks. */ + funding_txout_num = NULL; + for (size_t i = 0; i < funding_psbt->tx->num_outputs; i++) { + if (memeq(funding_psbt->tx->outputs[i].script, + funding_psbt->tx->outputs[i].script_len, + fc->funding_scriptpubkey, + tal_bytelen(fc->funding_scriptpubkey))) { + if (funding_txout_num) + return command_fail(cmd, FUNDING_PSBT_INVALID, + "Two outputs to open channel"); + funding_txout_num = tal(cmd, u32); + *funding_txout_num = i; + } + } + if (!funding_txout_num) + return command_fail(cmd, FUNDING_PSBT_INVALID, + "No output to open channel"); + + if (!amount_sat_eq(amount_sat(funding_psbt->tx->outputs + [*funding_txout_num].satoshi), + fc->funding)) + return command_fail(cmd, FUNDING_PSBT_INVALID, + "Output to open channel is %"PRIu64"sat," + " should be %s", + funding_psbt->tx->outputs + [*funding_txout_num].satoshi, + type_to_string(tmpctx, struct amount_sat, + &fc->funding)); + + funding_txid = tal(cmd, struct bitcoin_txid); + psbt_txid(NULL, funding_psbt, funding_txid, NULL); + } + + /* Fun fact: our wire protocol only allows 16 bits for outnum. + * That is reflected in our encoding scheme for short_channel_id. */ + if (*funding_txout_num > UINT16_MAX) + return command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "Invalid parameter: funding tx vout too large %u", + *funding_txout_num); + /* Set the cmd to this new cmd */ peer->uncommitted_channel->fc->cmd = cmd; msg = towire_openingd_funder_complete(NULL, funding_txid, - funding_txout); + *funding_txout_num); subd_send_msg(peer->uncommitted_channel->open_daemon, take(msg)); return command_still_pending(cmd); } @@ -1192,7 +1253,7 @@ static const struct json_command fundchannel_complete_command = { "channels", json_fundchannel_complete, "Complete channel establishment with peer {id} for funding transaction" - "with {txid}. Returns true on success, false otherwise." + "with {psbt}. Returns true on success, false otherwise." }; AUTODATA(json_command, &fundchannel_complete_command);