Skip to content

Commit

Permalink
peer_control: Have close accept channel IDs also.
Browse files Browse the repository at this point in the history
  • Loading branch information
ZmnSCPxj authored and cdecker committed May 3, 2018
1 parent 7767b68 commit e588737
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 16 deletions.
6 changes: 3 additions & 3 deletions doc/lightning-close.7
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
.\" Title: lightning-close
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
.\" Date: 04/15/2018
.\" Date: 04/30/2018
.\" Manual: \ \&
.\" Source: \ \&
.\" Language: English
.\"
.TH "LIGHTNING\-CLOSE" "7" "04/15/2018" "\ \&" "\ \&"
.TH "LIGHTNING\-CLOSE" "7" "04/30/2018" "\ \&" "\ \&"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
Expand All @@ -34,7 +34,7 @@ lightning-close \- Command for closing channels with direct peers
\fBclose\fR \fIid\fR [\fIforce\fR] [\fItimeout\fR]
.SH "DESCRIPTION"
.sp
The \fBclose\fR RPC command attempts to close the channel cooperatively with the peer\&. It applies to the active channel of the direct peer corresponding to the given peer \fIid\fR\&.
The \fBclose\fR RPC command attempts to close the channel cooperatively with the peer\&. If the given \fIid\fR is a peer ID (66 hex digits as a string), then it applies to the active channel of the direct peer corresponding to the given peer ID\&. If the given \fIid\fR is a channel ID (64 hex digits as a string, or the short channel ID \fIblockheight:txindex:outindex\fR form), then it applies to that channel\&.
.sp
The \fBclose\fR command will time out and return with an error when the number of seconds specified in \fItimeout\fR is reached\&. If unspecified, it times out in 30 seconds\&.
.sp
Expand Down
8 changes: 6 additions & 2 deletions doc/lightning-close.7.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@ DESCRIPTION

The *close* RPC command attempts to close the channel cooperatively
with the peer.
It applies to the active channel of the direct peer corresponding to
the given peer 'id'.
If the given 'id' is a peer ID (66 hex digits as a string), then
it applies to the active channel of the direct peer corresponding to
the given peer ID.
If the given 'id' is a channel ID (64 hex digits as a string, or
the short channel ID 'blockheight:txindex:outindex' form), then it
applies to that channel.

The *close* command will time out and return with an error when the
number of seconds specified in 'timeout' is reached.
Expand Down
9 changes: 9 additions & 0 deletions lightningd/json.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <lightningd/options.h>
#include <sys/socket.h>
#include <wallet/wallet.h>
#include <wire/wire.h>

/* Output a route hop */
static void
Expand Down Expand Up @@ -110,6 +111,14 @@ bool json_tok_short_channel_id(const char *buffer, const jsmntok_t *tok,
scid);
}

bool
json_tok_channel_id(const char *buffer, const jsmntok_t *tok,
struct channel_id *cid)
{
return hex_decode(buffer + tok->start, tok->end - tok->start,
cid, sizeof(*cid));
}

void json_add_address(struct json_result *response, const char *fieldname,
const struct wireaddr *addr)
{
Expand Down
4 changes: 4 additions & 0 deletions lightningd/json.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# include <external/jsmn/jsmn.h>

struct bitcoin_txid;
struct channel_id;
struct json_result;
struct pubkey;
struct route_hop;
Expand Down Expand Up @@ -50,6 +51,9 @@ void json_add_short_channel_id(struct json_result *response,
const char *fieldname,
const struct short_channel_id *id);

bool json_tok_channel_id(const char *buffer, const jsmntok_t *tok,
struct channel_id *cid);

/* JSON serialize a network address for a node */
void json_add_address(struct json_result *response, const char *fieldname,
const struct wireaddr *addr);
Expand Down
80 changes: 69 additions & 11 deletions lightningd/peer_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -985,10 +985,60 @@ static const struct json_command listpeers_command = {
};
AUTODATA(json_command, &listpeers_command);

static struct channel *
command_find_channel(struct command *cmd,
const char *buffer, const jsmntok_t *tok)
{
struct lightningd *ld = cmd->ld;
struct channel_id cid;
struct channel_id channel_cid;
struct short_channel_id scid;
struct peer *peer;
struct channel *channel;

if (json_tok_channel_id(buffer, tok, &cid)) {
list_for_each(&ld->peers, peer, list) {
channel = peer_active_channel(peer);
if (!channel)
continue;
derive_channel_id(&channel_cid,
&channel->funding_txid,
channel->funding_outnum);
if (structeq(&channel_cid, &cid))
return channel;
}
command_fail(cmd,
"Channel ID not found: '%.*s'",
tok->end - tok->start,
buffer + tok->start);
return NULL;
} else if (json_tok_short_channel_id(buffer, tok, &scid)) {
list_for_each(&ld->peers, peer, list) {
channel = peer_active_channel(peer);
if (!channel)
continue;
if (channel->scid && channel->scid->u64 == scid.u64)
return channel;
}
command_fail(cmd,
"Short channel ID not found: '%.*s'",
tok->end - tok->start,
buffer + tok->start);
return NULL;
} else {
command_fail(cmd,
"Given id is not a channel ID or "
"short channel ID: '%.*s'",
tok->end - tok->start,
buffer + tok->start);
return NULL;
}
}

static void json_close(struct command *cmd,
const char *buffer, const jsmntok_t *params)
{
jsmntok_t *peertok;
jsmntok_t *idtok;
jsmntok_t *timeouttok;
jsmntok_t *forcetok;
struct peer *peer;
Expand All @@ -997,18 +1047,13 @@ static void json_close(struct command *cmd,
bool force = false;

if (!json_get_params(cmd, buffer, params,
"id", &peertok,
"id", &idtok,
"?force", &forcetok,
"?timeout", &timeouttok,
NULL)) {
return;
}

peer = peer_from_json(cmd->ld, buffer, peertok);
if (!peer) {
command_fail(cmd, "Could not find peer with that id");
return;
}
if (forcetok && !json_tok_bool(buffer, forcetok, &force)) {
command_fail(cmd, "Force '%.*s' must be true or false",
forcetok->end - forcetok->start,
Expand All @@ -1022,8 +1067,16 @@ static void json_close(struct command *cmd,
return;
}

channel = peer_active_channel(peer);
if (!channel) {
peer = peer_from_json(cmd->ld, buffer, idtok);
if (peer)
channel = peer_active_channel(peer);
else {
channel = command_find_channel(cmd, buffer, idtok);
if (!channel)
return;
}

if (!channel && peer) {
struct uncommitted_channel *uc = peer->uncommitted_channel;
if (uc) {
/* Easy case: peer can simply be forgotten. */
Expand All @@ -1045,7 +1098,7 @@ static void json_close(struct command *cmd,
channel->state != CHANNELD_AWAITING_LOCKIN &&
channel->state != CHANNELD_SHUTTING_DOWN &&
channel->state != CLOSINGD_SIGEXCHANGE)
command_fail(cmd, "Peer is in state %s",
command_fail(cmd, "Channel is in state %s",
channel_state_name(channel));

/* If normal or locking in, transition to shutting down
Expand All @@ -1071,7 +1124,12 @@ static void json_close(struct command *cmd,
static const struct json_command close_command = {
"close",
json_close,
"Close the channel with peer {id}"
"Close the channel with {id} "
"(either peer ID, channel ID, or short channel ID). "
"If {force} (default false) is true, force a unilateral close "
"after {timeout} seconds (default 30), "
"otherwise just schedule a mutual close later and fail after "
"timing out."
};
AUTODATA(json_command, &close_command);

Expand Down
4 changes: 4 additions & 0 deletions wallet/test/run-wallet.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,10 @@ void json_object_start(struct json_result *ptr UNNEEDED, const char *fieldname U
/* Generated stub for json_tok_bool */
bool json_tok_bool(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, bool *b UNNEEDED)
{ fprintf(stderr, "json_tok_bool called!\n"); abort(); }
/* Generated stub for json_tok_channel_id */
bool json_tok_channel_id(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct channel_id *cid UNNEEDED)
{ fprintf(stderr, "json_tok_channel_id called!\n"); abort(); }
/* Generated stub for json_tok_loglevel */
bool json_tok_loglevel(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
enum log_level *level UNNEEDED)
Expand Down

0 comments on commit e588737

Please sign in to comment.