From b696ec89a5728fa5d9e8fdd2da5814d5f6b31c9c Mon Sep 17 00:00:00 2001 From: niftynei Date: Thu, 17 Sep 2020 15:28:46 -0500 Subject: [PATCH] df-open: use channel_id for openchannel_update and openchannel_signed Be as specific as possible is a good rule for things, I think --- common/jsonrpc_errors.h | 1 + doc/lightning-openchannel_signed.7 | 10 ++--- doc/lightning-openchannel_signed.7.md | 6 +-- doc/lightning-openchannel_update.7 | 12 +++--- doc/lightning-openchannel_update.7.md | 8 ++-- lightningd/channel.c | 30 ++++++++++++++ lightningd/channel.h | 5 +++ lightningd/dual_open_control.c | 58 ++++++++++++--------------- lightningd/opening_common.c | 2 + lightningd/opening_common.h | 4 ++ tests/plugins/df_opener.py | 5 ++- 11 files changed, 89 insertions(+), 52 deletions(-) diff --git a/common/jsonrpc_errors.h b/common/jsonrpc_errors.h index 389aea521..a9c9eefd9 100644 --- a/common/jsonrpc_errors.h +++ b/common/jsonrpc_errors.h @@ -54,6 +54,7 @@ static const errcode_t FUNDING_NOTHING_TO_CANCEL = 307; static const errcode_t FUNDING_CANCEL_NOT_SAFE = 308; static const errcode_t FUNDING_PSBT_INVALID = 309; static const errcode_t FUNDING_V2_NOT_SUPPORTED = 310; +static const errcode_t FUNDING_UNKNOWN_CHANNEL = 311; /* `connect` errors */ static const errcode_t CONNECT_NO_KNOWN_ADDRESS = 400; diff --git a/doc/lightning-openchannel_signed.7 b/doc/lightning-openchannel_signed.7 index 7e5d4c7b7..30e6f4f63 100644 --- a/doc/lightning-openchannel_signed.7 +++ b/doc/lightning-openchannel_signed.7 @@ -3,7 +3,7 @@ lightning-openchannel_signed - Command to conclude a channel open .SH SYNOPSIS -\fBopenchannel_signed\fR \fIid\fR \fIsigned_psbt\fR +\fBopenchannel_signed\fR \fIchannel_id\fR \fIsigned_psbt\fR .SH DESCRIPTION @@ -20,7 +20,7 @@ This command will broadcast the finalized funding transaction, if we receive valid signatures from the peer\. -\fIid\fR is the node id of the remote peer\. +\fIchannel_id\fR is the id of the channel\. \fIsigned_psbt\fR is the PSBT returned from \fBopenchannel_update\fR (where @@ -45,9 +45,9 @@ with \fBcode\fR being one of the following: .IP \[bu] 303: Funding transaction broadcast failed\. .IP \[bu] -306: Unknown peer id\. -.IP \[bu] 309: PSBT missing required fields\. +.IP \[bu] +311: Unknown channel id\. .RE .SH SEE ALSO @@ -65,4 +65,4 @@ lightning-fundchannel_\fBstart\fR(7), lightning-fundchannel_\fBcomplete\fR(7), Main web site: \fIhttps://github.com/ElementsProject/lightning\fR -\" SHA256STAMP:68fb78430a5ee3707fdb1324ba46373dd3dfaf325fe4e1bd3dcdc1589d80435c +\" SHA256STAMP:93ad9dfed532d0de1481a2f5d3b2030dbaf2f67df69dfcc3724e934d86d332b5 diff --git a/doc/lightning-openchannel_signed.7.md b/doc/lightning-openchannel_signed.7.md index e975a3b2e..3144006a5 100644 --- a/doc/lightning-openchannel_signed.7.md +++ b/doc/lightning-openchannel_signed.7.md @@ -4,7 +4,7 @@ lightning-openchannel\_signed -- Command to conclude a channel open SYNOPSIS -------- -**openchannel_signed** *id* *signed_psbt* +**openchannel_signed** *channel_id* *signed_psbt* DESCRIPTION ----------- @@ -19,7 +19,7 @@ This command should be called after `openchannel_update` returns This command will broadcast the finalized funding transaction, if we receive valid signatures from the peer. -*id* is the node id of the remote peer. +*channel_id* is the id of the channel. *signed_psbt* is the PSBT returned from `openchannel_update` (where *commitments_secured* was true) with partial signatures or finalized @@ -38,8 +38,8 @@ with `code` being one of the following: - -32602: If the given parameters are wrong. - -1: Catchall nonspecific error. - 303: Funding transaction broadcast failed. -- 306: Unknown peer id. - 309: PSBT missing required fields. +- 311: Unknown channel id. SEE ALSO -------- diff --git a/doc/lightning-openchannel_update.7 b/doc/lightning-openchannel_update.7 index 456033fbe..42677e026 100644 --- a/doc/lightning-openchannel_update.7 +++ b/doc/lightning-openchannel_update.7 @@ -3,12 +3,12 @@ lightning-openchannel_update - Command to update a collab channel open .SH SYNOPSIS -\fBopenchannel_update\fR \fIid\fR \fIpsbt\fR +\fBopenchannel_update\fR \fIchannel_id\fR \fIpsbt\fR .SH DESCRIPTION \fBopenchannel_update\fR is a low level RPC command which continues an open -channel with peer, as specified by \fIid\fR\. An updated \fIpsbt\fR is passed in; any +channel, as specified by \fIchannel_id\fR\. An updated \fIpsbt\fR is passed in; any changes from the PSBT last returned (either from \fBopenchannel_init\fR or a previous call to \fBopenchannel_update\fR) will be communicated to the peer\. @@ -21,7 +21,7 @@ Must be called until \fIcommitments_secured\fR is returned as true, at which poi returned by the last call to \fBopenchannel_update\fR\. -\fIid\fR is the node id of the remote peer\. +\fIchannel_id\fR is the id of the channel\. \fIpsbt\fR is the updated PSBT to be sent to the peer\. May be identical to @@ -43,9 +43,9 @@ returned PSBT and calling \fBopenchannel_signed\fR to complete the channel open\ .IP \[bu] 305: Peer is not connected\. .IP \[bu] -306: Unknown peer id\. -.IP \[bu] 309: PSBT missing required fields +.IP \[bu] +311: Unknown channel id\. .RE .SH SEE ALSO @@ -63,4 +63,4 @@ lightning-fundchannel_\fBstart\fR(7), lightning-fundchannel_\fBcomplete\fR(7), Main web site: \fIhttps://github.com/ElementsProject/lightning\fR -\" SHA256STAMP:dcf253e7b1658e71a9721fccee76a6bb07af7579ca4b0413428d2a1e8c9613bc +\" SHA256STAMP:ab3d19be91c8b2e651a6f4a23552f21323c4f0096ceda8026bb2450c2f9c616c diff --git a/doc/lightning-openchannel_update.7.md b/doc/lightning-openchannel_update.7.md index 0b0546a56..9a8e8475e 100644 --- a/doc/lightning-openchannel_update.7.md +++ b/doc/lightning-openchannel_update.7.md @@ -4,13 +4,13 @@ lightning-openchannel\_update -- Command to update a collab channel open SYNOPSIS -------- -**openchannel_update** *id* *psbt* +**openchannel_update** *channel_id* *psbt* DESCRIPTION ----------- `openchannel_update` is a low level RPC command which continues an open -channel with peer, as specified by *id*. An updated *psbt* is passed in; any +channel, as specified by *channel_id*. An updated *psbt* is passed in; any changes from the PSBT last returned (either from `openchannel_init` or a previous call to `openchannel_update`) will be communicated to the peer. @@ -20,7 +20,7 @@ Must be called until *commitments_secured* is returned as true, at which point `openchannel_signed` should be called with a signed version of the PSBT returned by the last call to `openchannel_update`. -*id* is the node id of the remote peer. +*channel_id* is the id of the channel. *psbt* is the updated PSBT to be sent to the peer. May be identical to the PSBT last returned by either `openchannel_init` or `openchannel_update`. @@ -37,8 +37,8 @@ returned PSBT and calling `openchannel_signed` to complete the channel open. - -32602: If the given parameters are wrong. - -1: Catchall nonspecific error. - 305: Peer is not connected. -- 306: Unknown peer id. - 309: PSBT missing required fields +- 311: Unknown channel id. SEE ALSO -------- diff --git a/lightningd/channel.c b/lightningd/channel.c index 333605a40..908082503 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -376,6 +377,35 @@ struct channel *channel_by_dbid(struct lightningd *ld, const u64 dbid) return NULL; } +struct channel *channel_by_cid(struct lightningd *ld, + const struct channel_id *cid, + struct uncommitted_channel **uc) +{ + struct peer *p; + struct channel *channel; + + list_for_each(&ld->peers, p, list) { + if (p->uncommitted_channel) { + if (channel_id_eq(&p->uncommitted_channel->cid, cid)) { + if (uc) + *uc = p->uncommitted_channel; + return NULL; + } + } + list_for_each(&p->channels, channel, list) { + if (channel_id_eq(&channel->cid, cid)) { + if (uc) + *uc = p->uncommitted_channel; + return channel; + } + } + } + if (uc) + *uc = NULL; + return NULL; +} + + void channel_set_last_tx(struct channel *channel, struct bitcoin_tx *tx, const struct bitcoin_signature *sig, diff --git a/lightningd/channel.h b/lightningd/channel.h index 0a9382836..2a277e595 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -253,6 +253,11 @@ struct channel *channel_by_dbid(struct lightningd *ld, const u64 dbid); struct channel *active_channel_by_scid(struct lightningd *ld, const struct short_channel_id *scid); +/* Get channel by channel_id, optionally returning uncommitted_channel. */ +struct channel *channel_by_cid(struct lightningd *ld, + const struct channel_id *cid, + struct uncommitted_channel **uc); + void channel_set_last_tx(struct channel *channel, struct bitcoin_tx *tx, const struct bitcoin_signature *sig, diff --git a/lightningd/dual_open_control.c b/lightningd/dual_open_control.c index 1f2e58c29..c1875311f 100644 --- a/lightningd/dual_open_control.c +++ b/lightningd/dual_open_control.c @@ -699,6 +699,7 @@ static void opener_psbt_changed(struct subd *dualopend, json_add_psbt(response, "psbt", psbt); json_add_bool(response, "commitments_secured", false); + uc->cid = cid; uc->fc->inflight = true; uc->fc->cmd = NULL; was_pending(command_success(cmd, response)); @@ -1009,32 +1010,25 @@ static struct command_result *json_open_channel_signed(struct command *cmd, const jsmntok_t *params) { struct wally_psbt *psbt; - struct node_id *id; - struct peer *peer; + struct channel_id *cid; struct channel *channel; struct bitcoin_txid txid; if (!param(cmd, buffer, params, - p_req("id", param_node_id, &id), + p_req("channel_id", param_channel_id, &cid), p_req("signed_psbt", param_psbt, &psbt), NULL)) return command_param_failed(); - peer = peer_by_id(cmd->ld, id); - if (!peer) - return command_fail(cmd, FUNDING_UNKNOWN_PEER, "Unknown peer"); - - channel = peer_active_channel(peer); + channel = channel_by_cid(cmd->ld, cid, NULL); if (!channel) - return command_fail(cmd, LIGHTNINGD, - "Peer has no active channel"); - + return command_fail(cmd, FUNDING_UNKNOWN_CHANNEL, + "Unknown channel"); if (!channel->pps) return command_fail(cmd, LIGHTNINGD, "Missing per-peer-state for channel, " "are you in the right state to call " "this method?"); - if (channel->psbt) return command_fail(cmd, LIGHTNINGD, "Already have a finalized PSBT for " @@ -1053,7 +1047,6 @@ static struct command_result *json_open_channel_signed(struct command *cmd, type_to_string(tmpctx, struct bitcoin_txid, &txid)); - /* Go ahead and try to finalize things, or what we can */ psbt_finalize(psbt); @@ -1082,47 +1075,48 @@ static struct command_result *json_open_channel_update(struct command *cmd, const jsmntok_t *params) { struct wally_psbt *psbt; - struct node_id *id; - struct peer *peer; + struct channel_id *cid; struct channel *channel; + struct uncommitted_channel *uc; u8 *msg; if (!param(cmd, buffer, params, - p_req("id", param_node_id, &id), + p_req("channel_id", param_channel_id, &cid), p_req("psbt", param_psbt, &psbt), NULL)) return command_param_failed(); - peer = peer_by_id(cmd->ld, id); - if (!peer) - return command_fail(cmd, FUNDING_UNKNOWN_PEER, "Unknown peer"); - - channel = peer_active_channel(peer); + /* We expect this to return NULL, as the channel hasn't been + * created yet. Instead, the uncommitted channel is populated */ + channel = channel_by_cid(cmd->ld, cid, &uc); if (channel) - return command_fail(cmd, LIGHTNINGD, "Peer already %s", + return command_fail(cmd, LIGHTNINGD, "Channel already %s", channel_state_name(channel)); - if (!peer->uncommitted_channel) - return command_fail(cmd, FUNDING_PEER_NOT_CONNECTED, - "Peer not connected"); + if (!uc) + return command_fail(cmd, FUNDING_UNKNOWN_CHANNEL, + "Unknown channel"); - if (!peer->uncommitted_channel->fc || !peer->uncommitted_channel->fc->inflight) - return command_fail(cmd, LIGHTNINGD, "No channel funding in progress"); + if (!uc->fc || !uc->fc->inflight) + return command_fail(cmd, LIGHTNINGD, + "No channel funding in progress"); - if (peer->uncommitted_channel->fc->cmd) - return command_fail(cmd, LIGHTNINGD, "Channel funding in progress"); + if (uc->fc->cmd) + return command_fail(cmd, LIGHTNINGD, + "Channel funding in progress"); /* Add serials to PSBT */ psbt_add_serials(psbt, TX_INITIATOR); if (!psbt_has_required_fields(psbt)) return command_fail(cmd, FUNDING_PSBT_INVALID, "PSBT is missing required fields %s", - type_to_string(tmpctx, struct wally_psbt, psbt)); + type_to_string(tmpctx, struct wally_psbt, + psbt)); - peer->uncommitted_channel->fc->cmd = cmd; + uc->fc->cmd = cmd; msg = towire_dual_open_psbt_updated(NULL, psbt); - subd_send_msg(peer->uncommitted_channel->open_daemon, take(msg)); + subd_send_msg(uc->open_daemon, take(msg)); return command_still_pending(cmd); } diff --git a/lightningd/opening_common.c b/lightningd/opening_common.c index 8a4f4e4c9..12086ab37 100644 --- a/lightningd/opening_common.c +++ b/lightningd/opening_common.c @@ -47,6 +47,8 @@ new_uncommitted_channel(struct peer *peer) uc->fc = NULL; uc->our_config.id = 0; + memset(&uc->cid, 0xFF, sizeof(uc->cid)); + get_channel_basepoints(ld, &uc->peer->id, uc->dbid, &uc->local_basepoints, &uc->local_funding_pubkey); diff --git a/lightningd/opening_common.h b/lightningd/opening_common.h index 0f804d71d..6d789f51b 100644 --- a/lightningd/opening_common.h +++ b/lightningd/opening_common.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -27,6 +28,9 @@ struct uncommitted_channel { /* Reserved dbid for if we become a real struct channel */ u64 dbid; + /* Channel id, v2 opens only */ + struct channel_id cid; + /* For logging */ struct log *log; diff --git a/tests/plugins/df_opener.py b/tests/plugins/df_opener.py index 8b532c97f..cfbec8354 100755 --- a/tests/plugins/df_opener.py +++ b/tests/plugins/df_opener.py @@ -69,14 +69,15 @@ def openchannel_v2(plugin, node_id, amount): commitment_feerate=feerate, funding_feerate=feerate) + cid = resp['channel_id'] # We don't have an updates, so we send update until our peer is also # finished while not resp['commitments_secured']: - resp = plugin.rpc.openchannel_update(node_id, resp['psbt']) + resp = plugin.rpc.openchannel_update(cid, resp['psbt']) # fixme: pass in array of our input indexes to signonly signed = plugin.rpc.signpsbt(resp['psbt']) - return plugin.rpc.openchannel_signed(node_id, signed['signed_psbt']) + return plugin.rpc.openchannel_signed(cid, signed['signed_psbt']) @plugin.init()