diff --git a/plugins/topology.c b/plugins/topology.c index a16ad7eeb77a..5e916b1d0931 100644 --- a/plugins/topology.c +++ b/plugins/topology.c @@ -192,6 +192,43 @@ static struct command_result *json_getroute(struct command *cmd, return command_finished(cmd, js); } +struct channel_routing_data { + struct amount_msat fee_base; + struct amount_msat fee_ppm; + u16 delay; + struct amount_msat htlc_minimum_msat; + struct amount_msat htlc_maximum_msat; +}; + +struct private_channel { + struct short_channel_id scid; + struct node_id nodes[2]; + struct channel_routing_data half_chan_data[2]; + struct amount_msat amount_msat; + /* FIXME: Add full data to populate listchannels */ +}; +/* FIXME: Add private_channel_populate_from_result */ + +static inline const struct short_channel_id *priv_chan_scid(const struct private_channel *c) +{ + return &c->scid; +} + +static inline size_t hash_scid(const struct short_channel_id *scid) +{ + /* scids cost money to generate, so simple hash works here */ + return (scid->u64 >> 32) ^ (scid->u64 >> 16) ^ scid->u64; +} + +static inline bool chan_eq_scid(const struct private_channel *c, + const struct short_channel_id *scid) +{ + return short_channel_id_eq(scid, &c->scid); +} + +HTABLE_DEFINE_TYPE(struct private_channel, priv_chan_scid, hash_scid, chan_eq_scid, + private_channel_map); + HTABLE_DEFINE_TYPE(struct node_id, node_id_keyof, node_id_hash, node_id_eq, node_map); @@ -287,7 +324,9 @@ struct listchannels_opts { * channels in the store it knows nothing about. */ static struct node_map *local_connected(const tal_t *ctx, const char *buf, - const jsmntok_t *result) + const jsmntok_t *result, + const jsmntok_t *inbound_result, + struct private_channel_map **private) { size_t i; const jsmntok_t *channel, *channels = json_get_member(buf, result, "channels"); @@ -295,10 +334,16 @@ static struct node_map *local_connected(const tal_t *ctx, node_map_init(connected); tal_add_destructor(connected, node_map_clear); + *private = tal(ctx, struct private_channel_map); + private_channel_map_init(*private); + tal_add_destructor(*private, private_channel_map_clear); json_for_each_arr(i, channel, channels) { struct node_id id; bool is_connected; + const jsmntok_t *private_tok, *scid_tok; + bool is_private; + struct short_channel_id scid; const char *err, *state; err = json_scan(tmpctx, buf, channel, @@ -314,30 +359,53 @@ static struct node_map *local_connected(const tal_t *ctx, if (!is_connected) continue; + private_tok = json_get_member(buf, channel, "private"); + json_to_bool(buf, private_tok, &is_private); + scid_tok = json_get_member(buf, channel, "short_channel_id"); + json_to_short_channel_id(buf, scid_tok, &scid); /* Must also have a channel in CHANNELD_NORMAL/splice */ if (streq(state, "CHANNELD_NORMAL") || streq(state, "CHANNELD_AWAITING_SPLICE")) { node_map_add(connected, tal_dup(connected, struct node_id, &id)); + if (is_private) { + struct private_channel *chan; + chan = private_channel_map_get(*private, &scid); + if (!chan) { + chan = tal(*private, struct private_channel); + private_channel_map_add(*private, chan); + } + /* FIXME: populate in correct position */ + chan->nodes[0] = id; + chan->half_chan_data[0].delay = 40; + } } } return connected; } -/* We want to combine local knowledge to we know which are actually inactive! */ +struct opts_and_privinbound { + struct listchannels_opts *opts; + const jsmntok_t *privinboundresult; +}; + +/* We want to combine local knowledge so we know which are actually inactive! */ static struct command_result *listpeerchannels_done(struct command *cmd, const char *buf, const jsmntok_t *result, - struct listchannels_opts *opts) + struct opts_and_privinbound *opts_and_inbound) { struct node_map *connected; + struct private_channel_map *private; struct gossmap_chan *c; struct json_stream *js; struct gossmap *gossmap = get_gossmap(); + struct listchannels_opts *opts = opts_and_inbound->opts; + const jsmntok_t *inbound_result = opts_and_inbound->privinboundresult; - connected = local_connected(opts, buf, result); + connected = local_connected(opts, buf, result, inbound_result, &private); js = jsonrpc_stream_success(cmd); json_array_start(js, "channels"); @@ -382,6 +450,24 @@ static struct command_result *listpeerchannels_done(struct command *cmd, return command_finished(cmd, js); } +/* Private channel gossip data must be retrieved from lightningd. */ +static struct command_result *listchannels_privateinbound_done(struct command *cmd, + const char *buffer, + const jsmntok_t *result, + struct listchannels_opts *opts) +{ + struct opts_and_privinbound *opts_and_inbound; + struct out_req *req; + opts_and_inbound = tal(cmd, struct opts_and_privinbound); + opts_and_inbound->opts = opts; + opts_and_inbound->privinboundresult = result; + + req = jsonrpc_request_start(cmd->plugin, cmd, "listpeerchannels", + listpeerchannels_done, forward_error, + opts_and_inbound); + return send_outreq(cmd->plugin, req); +} + static struct command_result *json_listchannels(struct command *cmd, const char *buffer, const jsmntok_t *params) @@ -402,8 +488,9 @@ static struct command_result *json_listchannels(struct command *cmd, "Can only specify one of " "`short_channel_id`, " "`source` or `destination`"); - req = jsonrpc_request_start(cmd->plugin, cmd, "listpeerchannels", - listpeerchannels_done, forward_error, opts); + req = jsonrpc_request_start(cmd->plugin, cmd, "listprivateinbound", + listchannels_privateinbound_done, + forward_error, opts); return send_outreq(cmd->plugin, req); }