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 <rusty@rustcorp.com.au>
Changelog-Added: JSON-RPC: `fundchannel_complete` takes a psbt parameter.
This commit is contained in:
Rusty Russell 2021-03-15 14:57:56 +10:30
parent bf928ef47a
commit da7ba6c146
3 changed files with 85 additions and 25 deletions

View File

@ -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

View File

@ -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
------

View File

@ -1,6 +1,8 @@
#include "bitcoin/feerate.h"
#include <bitcoin/privkey.h>
#include <bitcoin/psbt.h>
#include <bitcoin/script.h>
#include <ccan/mem/mem.h>
#include <ccan/tal/str/str.h>
#include <common/addr.h>
#include <common/channel_config.h>
@ -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);