From da7ba6c1464aa6e1f1832907df1d09a87ff51187 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 15 Mar 2021 14:57:56 +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. --- doc/lightning-fundchannel_complete.7 | 12 ++-- doc/lightning-fundchannel_complete.7.md | 8 +-- lightningd/opening_control.c | 90 ++++++++++++++++++++----- 3 files changed, 85 insertions(+), 25 deletions(-) diff --git a/doc/lightning-fundchannel_complete.7 b/doc/lightning-fundchannel_complete.7 index 7caaa6740..41a0acda8 100644 --- a/doc/lightning-fundchannel_complete.7 +++ b/doc/lightning-fundchannel_complete.7 @@ -3,7 +3,7 @@ lightning-fundchannel_complete - Command for completing channel establishment .SH SYNOPSIS -\fBfundchannel_complete\fR \fIid\fR \fItxid\fR \fItxout\fR +\fBfundchannel_complete\fR \fIid\fR \fIpsbt\fR .SH DESCRIPTION @@ -14,10 +14,8 @@ complete an initiated channel establishment with a connected peer\. \fIid\fR is the node id of the remote peer\. -\fItxid\fR is the hex string of the funding transaction id\. - - -\fItxout\fR is the integer outpoint of the funding output for this channel\. +\fIpsbt\fR is the transaction to use for funding (does not need to be +signed but must be otherwise complete)\. Note that the funding transaction MUST NOT be broadcast until after @@ -44,6 +42,8 @@ with \fBcode\fR being one of the following: 305: Peer is not connected\. .IP \[bu] 306: Unknown peer id\. +.IP \[bu] +309: PSBT does not have a unique, correct output to fund the channel\. .RE .SH AUTHOR @@ -62,4 +62,4 @@ lightning-openchannel_\fBabort\fR(7) Main web site: \fIhttps://github.com/ElementsProject/lightning\fR -\" SHA256STAMP:53e7f55055cdfb8cf66e89ba76a1cfa6fffaa5d6e72b441c44e7e6065707fc66 +\" SHA256STAMP:13e5fee7b987b38e9b08685f4b49062314ec9e2cf52afbb5a2c5a4965fe2b01f diff --git a/doc/lightning-fundchannel_complete.7.md b/doc/lightning-fundchannel_complete.7.md index 7136d9e6e..06b8b53b7 100644 --- a/doc/lightning-fundchannel_complete.7.md +++ b/doc/lightning-fundchannel_complete.7.md @@ -4,7 +4,7 @@ lightning-fundchannel\_complete -- Command for completing channel establishment SYNOPSIS -------- -**fundchannel\_complete** *id* *txid* *txout* +**fundchannel\_complete** *id* *psbt* DESCRIPTION ----------- @@ -14,9 +14,8 @@ complete an initiated channel establishment with a connected peer. *id* is the node id of the remote peer. -*txid* is the hex string of the funding transaction id. - -*txout* is the integer outpoint of the funding output for this channel. +*psbt* is the transaction to use for funding (does not need to be +signed but must be otherwise complete). Note that the funding transaction MUST NOT be broadcast until after channel establishment has been successfully completed, as the commitment @@ -37,6 +36,7 @@ with `code` being one of the following: - -1: Catchall nonspecific error. - 305: Peer is not connected. - 306: Unknown peer id. +- 309: PSBT does not have a unique, correct output to fund the channel. AUTHOR ------ diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index a3f7c8903..63830336d 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 @@ -958,22 +960,38 @@ static struct command_result *json_fundchannel_complete(struct command *cmd, struct bitcoin_txid *funding_txid; struct peer *peer; struct channel *channel; - u32 *funding_txout_num; - u16 funding_txout; + struct wally_psbt *funding_psbt; + u32 *funding_txout_num = NULL; + struct funding_channel *fc; + bool 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(); + /* 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 (*funding_txout_num > UINT16_MAX) - return command_fail(cmd, LIGHTNINGD, - "Invalid parameter: funding tx vout too large %u", - *funding_txout_num); + 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"); @@ -993,11 +1011,53 @@ 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. */ + 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); } @@ -1193,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);