From 638594f3c65f4403a0b5664c19559f648a14102b Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Wed, 22 Mar 2017 13:30:09 +0100 Subject: [PATCH] jsonrpc: Implemented `getchannels` JSON-RPC call --- lightningd/gossip/gossip.c | 38 +++++++++++++++++++++ lightningd/gossip/gossip_wire.csv | 6 ++++ lightningd/gossip_control.c | 56 +++++++++++++++++++++++++++++++ lightningd/gossip_msg.c | 25 ++++++++++++++ lightningd/gossip_msg.h | 22 ++++++++++-- 5 files changed, 145 insertions(+), 2 deletions(-) diff --git a/lightningd/gossip/gossip.c b/lightningd/gossip/gossip.c index 79edba8ff..8b8433621 100644 --- a/lightningd/gossip/gossip.c +++ b/lightningd/gossip/gossip.c @@ -476,6 +476,40 @@ static struct io_plan *getroute_req(struct io_conn *conn, struct daemon *daemon, return daemon_conn_read_next(conn, &daemon->master); } +static struct io_plan *getchannels_req(struct io_conn *conn, struct daemon *daemon, + u8 *msg) +{ + tal_t *tmpctx = tal_tmpctx(daemon); + u8 *out; + size_t j, num_chans = 0; + struct gossip_getchannels_entry *entries; + struct node *n; + struct node_map_iter i; + + entries = tal_arr(tmpctx, struct gossip_getchannels_entry, num_chans); + n = node_map_first(daemon->rstate->nodes, &i); + while (n != NULL) { + for (j=0; jout); j++){ + tal_resize(&entries, num_chans + 1); + entries[num_chans].source = n->out[j]->src->id; + entries[num_chans].destination = n->out[j]->dst->id; + entries[num_chans].active = n->out[j]->active; + entries[num_chans].delay = n->out[j]->delay; + entries[num_chans].fee_per_kw = n->out[j]->proportional_fee; + entries[num_chans].last_update_timestamp = n->out[j]->last_timestamp; + entries[num_chans].flags = n->out[j]->flags; + entries[num_chans].short_channel_id = n->out[j]->short_channel_id; + num_chans++; + } + n = node_map_next(daemon->rstate->nodes, &i); + } + + out = towire_gossip_getchannels_reply(daemon, entries); + daemon_conn_send(&daemon->master, take(out)); + tal_free(tmpctx); + return daemon_conn_read_next(conn, &daemon->master); +} + static struct io_plan *getnodes(struct io_conn *conn, struct daemon *daemon) { tal_t *tmpctx = tal_tmpctx(daemon); @@ -521,9 +555,13 @@ static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master case WIRE_GOSSIP_GETROUTE_REQUEST: return getroute_req(conn, daemon, daemon->master.msg_in); + case WIRE_GOSSIP_GETCHANNELS_REQUEST: + return getchannels_req(conn, daemon, daemon->master.msg_in); + case WIRE_GOSSIPCTL_RELEASE_PEER_REPLY: case WIRE_GOSSIP_GETNODES_REPLY: case WIRE_GOSSIP_GETROUTE_REPLY: + case WIRE_GOSSIP_GETCHANNELS_REPLY: case WIRE_GOSSIPSTATUS_INIT_FAILED: case WIRE_GOSSIPSTATUS_BAD_NEW_PEER_REQUEST: case WIRE_GOSSIPSTATUS_BAD_RELEASE_REQUEST: diff --git a/lightningd/gossip/gossip_wire.csv b/lightningd/gossip/gossip_wire.csv index 9f9fc7d56..b6028b50d 100644 --- a/lightningd/gossip/gossip_wire.csv +++ b/lightningd/gossip/gossip_wire.csv @@ -71,3 +71,9 @@ gossip_getroute_request,70,riskfactor,u16 gossip_getroute_reply,106 gossip_getroute_reply,0,num_hops,u16 gossip_getroute_reply,2,hops,num_hops*struct route_hop + +gossip_getchannels_request,7 + +gossip_getchannels_reply,107 +gossip_getchannels_reply,0,num_channels,u16 +gossip_getchannels_reply,2,nodes,num_channels*struct gossip_getchannels_entry diff --git a/lightningd/gossip_control.c b/lightningd/gossip_control.c index b9c02b5ff..6d26d1bb8 100644 --- a/lightningd/gossip_control.c +++ b/lightningd/gossip_control.c @@ -4,6 +4,7 @@ #include "subd.h" #include #include +#include #include #include #include @@ -143,10 +144,12 @@ static size_t gossip_msg(struct subd *gossip, const u8 *msg, const int *fds) case WIRE_GOSSIPCTL_RELEASE_PEER: case WIRE_GOSSIP_GETNODES_REQUEST: case WIRE_GOSSIP_GETROUTE_REQUEST: + case WIRE_GOSSIP_GETCHANNELS_REQUEST: /* This is a reply, so never gets through to here. */ case WIRE_GOSSIPCTL_RELEASE_PEER_REPLY: case WIRE_GOSSIP_GETNODES_REPLY: case WIRE_GOSSIP_GETROUTE_REPLY: + case WIRE_GOSSIP_GETCHANNELS_REPLY: break; case WIRE_GOSSIPSTATUS_PEER_BAD_MSG: peer_bad_message(gossip, msg); @@ -296,3 +299,56 @@ static const struct json_command getroute_command = { "Returns a {route} array of {id} {msatoshi} {delay}: msatoshi and delay (in blocks) is cumulative." }; AUTODATA(json_command, &getroute_command); + +/* Called upon receiving a getchannels_reply from `gossipd` */ +static bool json_getchannels_reply(struct subd *gossip, const u8 *reply, + const int *fds, struct command *cmd) +{ + size_t i; + struct gossip_getchannels_entry *entries; + struct json_result *response = new_json_result(cmd); + struct short_channel_id *scid; + + if (!fromwire_gossip_getchannels_reply(reply, reply, NULL, &entries)) { + command_fail(cmd, "Invalid reply from gossipd"); + return true; + } + + json_object_start(response, NULL); + json_array_start(response, "channels"); + for (i = 0; i < tal_count(entries); i++) { + scid = &entries[i].short_channel_id; + json_object_start(response, NULL); + json_add_pubkey(response, "source", &entries[i].source); + json_add_pubkey(response, "destination", + &entries[i].destination); + json_add_bool(response, "active", entries[i].active); + json_add_num(response, "fee_per_kw", entries[i].fee_per_kw); + json_add_num(response, "last_update", + entries[i].last_update_timestamp); + json_add_num(response, "flags", entries[i].flags); + json_add_num(response, "delay", entries[i].delay); + json_add_string(response, "short_id", + tal_fmt(reply, "%d:%d:%d/%d", scid->blocknum, + scid->txnum, scid->outnum, + entries[i].flags & 0x1)); + json_object_end(response); + } + json_array_end(response); + json_object_end(response); + command_success(cmd, response); + return true; +} + +static void json_getchannels(struct command *cmd, const char *buffer, + const jsmntok_t *params) +{ + struct lightningd *ld = ld_from_dstate(cmd->dstate); + u8 *req = towire_gossip_getchannels_request(cmd); + subd_req(ld->gossip, req, -1, 0, json_getchannels_reply, cmd); +} + +static const struct json_command getchannels_command = { + "getchannels", json_getchannels, "List all known channels.", + "Returns a 'channels' array with all known channels including their fees."}; +AUTODATA(json_command, &getchannels_command); diff --git a/lightningd/gossip_msg.c b/lightningd/gossip_msg.c index 8b16cd30d..e8964734b 100644 --- a/lightningd/gossip_msg.c +++ b/lightningd/gossip_msg.c @@ -39,3 +39,28 @@ void towire_route_hop(u8 **pptr, const struct route_hop *entry) towire_u32(pptr, entry->delay); } +void fromwire_gossip_getchannels_entry(const u8 **pptr, size_t *max, + struct gossip_getchannels_entry *entry) +{ + fromwire_short_channel_id(pptr, max, &entry->short_channel_id); + fromwire_pubkey(pptr, max, &entry->source); + fromwire_pubkey(pptr, max, &entry->destination); + entry->active = fromwire_bool(pptr, max); + entry->fee_per_kw = fromwire_u32(pptr, max); + entry->delay = fromwire_u32(pptr, max); + entry->last_update_timestamp = fromwire_u32(pptr, max); + entry->flags = fromwire_u16(pptr, max); +} + +void towire_gossip_getchannels_entry( + u8 **pptr, const struct gossip_getchannels_entry *entry) +{ + towire_short_channel_id(pptr, &entry->short_channel_id); + towire_pubkey(pptr, &entry->source); + towire_pubkey(pptr, &entry->destination); + towire_bool(pptr, entry->active); + towire_u32(pptr, entry->fee_per_kw); + towire_u32(pptr, entry->delay); + towire_u32(pptr, entry->last_update_timestamp); + towire_u16(pptr, entry->flags); +} diff --git a/lightningd/gossip_msg.h b/lightningd/gossip_msg.h index cb3908bb6..a4133dbcb 100644 --- a/lightningd/gossip_msg.h +++ b/lightningd/gossip_msg.h @@ -10,10 +10,28 @@ struct gossip_getnodes_entry { u16 port; }; -void fromwire_gossip_getnodes_entry(const tal_t *ctx, const u8 **pptr, size_t *max, struct gossip_getnodes_entry *entry); -void towire_gossip_getnodes_entry(u8 **pptr, const struct gossip_getnodes_entry *entry); +struct gossip_getchannels_entry { + struct pubkey source, destination; + u32 fee_per_kw; + bool active; + struct short_channel_id short_channel_id; + u32 last_update_timestamp; + u32 delay; + u16 flags; +}; + +void fromwire_gossip_getnodes_entry(const tal_t *ctx, const u8 **pptr, + size_t *max, + struct gossip_getnodes_entry *entry); +void towire_gossip_getnodes_entry(u8 **pptr, + const struct gossip_getnodes_entry *entry); void fromwire_route_hop(const u8 **pprt, size_t *max, struct route_hop *entry); void towire_route_hop(u8 **pprt, const struct route_hop *entry); +void fromwire_gossip_getchannels_entry(const u8 **pptr, size_t *max, + struct gossip_getchannels_entry *entry); +void towire_gossip_getchannels_entry( + u8 **pptr, const struct gossip_getchannels_entry *entry); + #endif /* LIGHTNING_LIGHTGNINGD_GOSSIP_MSG_H */