JSON-API: `getroute` now also support `exclude` nodes

This commit is contained in:
trueptolemy 2019-08-31 21:57:08 +08:00 committed by ZmnSCPxj, ZmnSCPxj jxPCSmnZ
parent 090a43fd3d
commit 5361a5d059
8 changed files with 69 additions and 30 deletions

View File

@ -596,8 +596,8 @@ class LightningRpc(UnixDomainSocketRpc):
{cltv} (default 9). If specified search from {fromid} otherwise use
this node as source. Randomize the route with up to {fuzzpercent}
(0.0 -> 100.0, default 5.0). {exclude} is an optional array of
scid/direction to exclude. Limit the number of hops in the route to
{maxhops}.
scid/direction or node-id to exclude. Limit the number of hops in the
route to {maxhops}.
"""
payload = {
"id": node_id,

View File

@ -39,7 +39,7 @@ msgdata,gossip_getroute_request,riskfactor_by_million,u64,
msgdata,gossip_getroute_request,final_cltv,u32,
msgdata,gossip_getroute_request,fuzz,double,
msgdata,gossip_getroute_request,num_excluded,u16,
msgdata,gossip_getroute_request,excluded,short_channel_id_dir,num_excluded
msgdata,gossip_getroute_request,excluded,exclude_entry,num_excluded
msgdata,gossip_getroute_request,max_hops,u32,
msgtype,gossip_getroute_reply,3106

Can't render this file because it has a wrong number of fields in line 6.

View File

@ -2488,7 +2488,7 @@ static struct io_plan *getroute_req(struct io_conn *conn, struct daemon *daemon,
u8 *out;
struct route_hop *hops;
double fuzz;
struct short_channel_id_dir *excluded;
struct exclude_entry **excluded;
/* To choose between variations, we need to know how much we're
* sending (eliminates too-small channels, and also effects the fees

View File

@ -2336,7 +2336,7 @@ struct route_hop *get_route(const tal_t *ctx, struct routing_state *rstate,
struct amount_msat msat, double riskfactor,
u32 final_cltv,
double fuzz, u64 seed,
const struct short_channel_id_dir *excluded,
struct exclude_entry **excluded,
size_t max_hops)
{
struct chan **route;
@ -2346,22 +2346,49 @@ struct route_hop *get_route(const tal_t *ctx, struct routing_state *rstate,
struct route_hop *hops;
struct node *n;
struct amount_msat *saved_capacity;
struct short_channel_id_dir *excluded_chan;
struct siphash_seed base_seed;
saved_capacity = tal_arr(tmpctx, struct amount_msat, tal_count(excluded));
saved_capacity = tal_arr(tmpctx, struct amount_msat, 0);
excluded_chan = tal_arr(tmpctx, struct short_channel_id_dir, 0);
base_seed.u.u64[0] = base_seed.u.u64[1] = seed;
if (amount_msat_eq(msat, AMOUNT_MSAT(0)))
return NULL;
/* Temporarily set excluded channels' capacity to zero. */
/* Temporarily set the capacity of the excluded channels and the incoming channels
* of excluded nodes to zero. */
for (size_t i = 0; i < tal_count(excluded); i++) {
struct chan *chan = get_channel(rstate, &excluded[i].scid);
if (!chan)
continue;
saved_capacity[i] = chan->half[excluded[i].dir].htlc_maximum;
chan->half[excluded[i].dir].htlc_maximum = AMOUNT_MSAT(0);
if (excluded[i]->type == EXCLUDE_CHANNEL) {
struct short_channel_id_dir *chan_id = &excluded[i]->u.chan_id;
struct chan *chan = get_channel(rstate, &chan_id->scid);
if (!chan)
continue;
tal_arr_expand(&saved_capacity, chan->half[chan_id->dir].htlc_maximum);
tal_arr_expand(&excluded_chan, *chan_id);
chan->half[chan_id->dir].htlc_maximum = AMOUNT_MSAT(0);
} else {
assert(excluded[i]->type == EXCLUDE_NODE);
struct node *node = get_node(rstate, &excluded[i]->u.node_id);
if (!node)
continue;
struct chan_map_iter i;
struct chan *chan;
for (chan = first_chan(node, &i); chan; chan = next_chan(node, &i)) {
int dir = half_chan_to(node, chan);
tal_arr_expand(&saved_capacity, chan->half[dir].htlc_maximum);
struct short_channel_id_dir id;
id.scid = chan->scid;
id.dir = dir;
tal_arr_expand(&excluded_chan, id);
chan->half[dir].htlc_maximum = AMOUNT_MSAT(0);
}
}
}
route = find_route(ctx, rstate, source, destination, msat,
@ -2378,11 +2405,11 @@ struct route_hop *get_route(const tal_t *ctx, struct routing_state *rstate,
* By restoring in reverse order we ensure we can restore
* the correct capacity.
*/
for (ssize_t i = tal_count(excluded) - 1; i >= 0; i--) {
struct chan *chan = get_channel(rstate, &excluded[i].scid);
for (ssize_t i = tal_count(excluded_chan) - 1; i >= 0; i--) {
struct chan *chan = get_channel(rstate, &excluded_chan[i].scid);
if (!chan)
continue;
chan->half[excluded[i].dir].htlc_maximum = saved_capacity[i];
chan->half[excluded_chan[i].dir].htlc_maximum = saved_capacity[i];
}
if (!route) {

View File

@ -348,7 +348,7 @@ struct route_hop *get_route(const tal_t *ctx, struct routing_state *rstate,
u32 final_cltv,
double fuzz,
u64 seed,
const struct short_channel_id_dir *excluded,
struct exclude_entry **excluded,
size_t max_hops);
/* Disable channel(s) based on the given routing failure. */
void routing_failure(struct routing_state *rstate,

View File

@ -87,7 +87,7 @@ bool fromwire_gossip_get_incoming_channels(const tal_t *ctx UNNEEDED, const void
bool fromwire_gossip_getnodes_request(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct node_id **id UNNEEDED)
{ fprintf(stderr, "fromwire_gossip_getnodes_request called!\n"); abort(); }
/* Generated stub for fromwire_gossip_getroute_request */
bool fromwire_gossip_getroute_request(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct node_id **source UNNEEDED, struct node_id *destination UNNEEDED, struct amount_msat *msatoshi UNNEEDED, u64 *riskfactor_by_million UNNEEDED, u32 *final_cltv UNNEEDED, double *fuzz UNNEEDED, struct short_channel_id_dir **excluded UNNEEDED, u32 *max_hops UNNEEDED)
bool fromwire_gossip_getroute_request(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct node_id **source UNNEEDED, struct node_id *destination UNNEEDED, struct amount_msat *msatoshi UNNEEDED, u64 *riskfactor_by_million UNNEEDED, u32 *final_cltv UNNEEDED, double *fuzz UNNEEDED, struct exclude_entry ***excluded UNNEEDED, u32 *max_hops UNNEEDED)
{ fprintf(stderr, "fromwire_gossip_getroute_request called!\n"); abort(); }
/* Generated stub for fromwire_gossip_get_txout_reply */
bool fromwire_gossip_get_txout_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED, struct amount_sat *satoshis UNNEEDED, u8 **outscript UNNEEDED)
@ -140,7 +140,7 @@ struct route_hop *get_route(const tal_t *ctx UNNEEDED, struct routing_state *rst
u32 final_cltv UNNEEDED,
double fuzz UNNEEDED,
u64 seed UNNEEDED,
const struct short_channel_id_dir *excluded UNNEEDED,
struct exclude_entry **excluded UNNEEDED,
size_t max_hops UNNEEDED)
{ fprintf(stderr, "get_route called!\n"); abort(); }
/* Generated stub for gossip_peerd_wire_type_name */

View File

@ -110,7 +110,7 @@ bool fromwire_gossip_get_incoming_channels(const tal_t *ctx UNNEEDED, const void
bool fromwire_gossip_getnodes_request(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct node_id **id UNNEEDED)
{ fprintf(stderr, "fromwire_gossip_getnodes_request called!\n"); abort(); }
/* Generated stub for fromwire_gossip_getroute_request */
bool fromwire_gossip_getroute_request(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct node_id **source UNNEEDED, struct node_id *destination UNNEEDED, struct amount_msat *msatoshi UNNEEDED, u64 *riskfactor_by_million UNNEEDED, u32 *final_cltv UNNEEDED, double *fuzz UNNEEDED, struct short_channel_id_dir **excluded UNNEEDED, u32 *max_hops UNNEEDED)
bool fromwire_gossip_getroute_request(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct node_id **source UNNEEDED, struct node_id *destination UNNEEDED, struct amount_msat *msatoshi UNNEEDED, u64 *riskfactor_by_million UNNEEDED, u32 *final_cltv UNNEEDED, double *fuzz UNNEEDED, struct exclude_entry ***excluded UNNEEDED, u32 *max_hops UNNEEDED)
{ fprintf(stderr, "fromwire_gossip_getroute_request called!\n"); abort(); }
/* Generated stub for fromwire_gossip_get_txout_reply */
bool fromwire_gossip_get_txout_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED, struct amount_sat *satoshis UNNEEDED, u8 **outscript UNNEEDED)
@ -163,7 +163,7 @@ struct route_hop *get_route(const tal_t *ctx UNNEEDED, struct routing_state *rst
u32 final_cltv UNNEEDED,
double fuzz UNNEEDED,
u64 seed UNNEEDED,
const struct short_channel_id_dir *excluded UNNEEDED,
struct exclude_entry **excluded UNNEEDED,
size_t max_hops UNNEEDED)
{ fprintf(stderr, "get_route called!\n"); abort(); }
/* Generated stub for gossip_peerd_wire_type_name */

View File

@ -313,7 +313,7 @@ static struct command_result *json_getroute(struct command *cmd,
struct amount_msat *msat;
unsigned *cltv;
double *riskfactor;
struct short_channel_id_dir *excluded;
const struct exclude_entry **excluded;
u32 *max_hops;
/* Higher fuzz means that some high-fee paths can be discounted
@ -343,19 +343,31 @@ static struct command_result *json_getroute(struct command *cmd,
const jsmntok_t *t;
size_t i;
excluded = tal_arr(cmd, struct short_channel_id_dir,
excludetok->size);
excluded = tal_arr(cmd, const struct exclude_entry *, 0);
json_for_each_arr(i, t, excludetok) {
struct exclude_entry *entry = tal(excluded, struct exclude_entry);
struct short_channel_id_dir *chan_id = tal(tmpctx, struct short_channel_id_dir);
if (!short_channel_id_dir_from_str(buffer + t->start,
t->end - t->start,
&excluded[i])) {
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"%.*s is not a valid"
" short_channel_id/direction",
t->end - t->start,
buffer + t->start);
chan_id)) {
struct node_id *node_id = tal(tmpctx, struct node_id);
if (!json_to_node_id(buffer, t, node_id))
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"%.*s is not a valid"
" short_channel_id/node_id",
t->end - t->start,
buffer + t->start);
entry->type = EXCLUDE_NODE;
entry->u.node_id = *node_id;
} else {
entry->type = EXCLUDE_CHANNEL;
entry->u.chan_id = *chan_id;
}
tal_arr_expand(&excluded, entry);
}
} else {
excluded = NULL;
@ -379,7 +391,7 @@ static const struct json_command getroute_command = {
"If specified search from {fromid} otherwise use this node as source. "
"Randomize the route with up to {fuzzpercent} (default 5.0). "
"{exclude} an array of short-channel-id/direction (e.g. [ '564334x877x1/0', '564195x1292x0/1' ]) "
"from consideration. "
"or node-id from consideration. "
"Set the {maxhops} the route can take (default 20)."
};
AUTODATA(json_command, &getroute_command);