Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fundchannel complete psbt not txid #4428

12 changes: 6 additions & 6 deletions doc/lightning-fundchannel_complete.7

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions doc/lightning-fundchannel_complete.7.md
Expand Up @@ -4,7 +4,7 @@ lightning-fundchannel\_complete -- Command for completing channel establishment
SYNOPSIS
--------

**fundchannel\_complete** *id* *txid* *txout*
**fundchannel\_complete** *id* *psbt*

DESCRIPTION
-----------
Expand All @@ -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
Expand All @@ -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
------
Expand Down
94 changes: 77 additions & 17 deletions lightningd/opening_control.c
@@ -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>
Expand Down Expand Up @@ -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;
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 wally_psbt *funding_psbt;
u32 *funding_txout_num = NULL;
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");
Expand All @@ -992,11 +1010,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);
}
Expand Down Expand Up @@ -1192,7 +1252,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."
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this will actually make us incompatible with LN Pool? surely not... as the pool probably produces PSBTs for peers to sign for the collectively built opening tx?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can always re-add a txid arg, but I really think that it's a great sanity-check!

};
AUTODATA(json_command, &fundchannel_complete_command);

Expand Down