Browse Source

getroute: allow caller to specify maximum hops.

This is required for routeboost.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
plugin-timeout-inc
Rusty Russell 6 years ago
committed by Christian Decker
parent
commit
358b7fda91
  1. 1
      gossipd/gossip_wire.csv
  2. 6
      gossipd/gossipd.c
  3. 23
      gossipd/routing.c
  4. 3
      gossipd/routing.h
  5. 1
      gossipd/test/run-bench-find_route.c
  6. 18
      gossipd/test/run-find_route-specific.c
  7. 15
      gossipd/test/run-find_route.c
  8. 6
      lightningd/gossip_control.c
  9. 3
      lightningd/payalgo.c

1
gossipd/gossip_wire.csv

@ -35,6 +35,7 @@ gossip_getroute_request,,fuzz,double
gossip_getroute_request,,num_excluded,u16
gossip_getroute_request,,excluded,num_excluded*struct short_channel_id
gossip_getroute_request,,excluded_dir,num_excluded*bool
gossip_getroute_request,,max_hops,u32
gossip_getroute_reply,3106
gossip_getroute_reply,,num_hops,u16

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

6
gossipd/gossipd.c

@ -1867,6 +1867,7 @@ static struct io_plan *getroute_req(struct io_conn *conn, struct daemon *daemon,
u64 msatoshi;
u32 final_cltv;
u16 riskfactor;
u32 max_hops;
u8 *out;
struct route_hop *hops;
double fuzz;
@ -1883,7 +1884,8 @@ static struct io_plan *getroute_req(struct io_conn *conn, struct daemon *daemon,
&source, &destination,
&msatoshi, &riskfactor,
&final_cltv, &fuzz,
&excluded, &excluded_dir))
&excluded, &excluded_dir,
&max_hops))
master_badmsg(WIRE_GOSSIP_GETROUTE_REQUEST, msg);
status_trace("Trying to find a route from %s to %s for %"PRIu64" msatoshi",
@ -1893,7 +1895,7 @@ static struct io_plan *getroute_req(struct io_conn *conn, struct daemon *daemon,
/* routing.c does all the hard work; can return NULL. */
hops = get_route(tmpctx, daemon->rstate, &source, &destination,
msatoshi, riskfactor, final_cltv,
fuzz, siphash_seed(), excluded, excluded_dir);
fuzz, siphash_seed(), excluded, excluded_dir, max_hops);
out = towire_gossip_getroute_reply(NULL, hops);
daemon_conn_send(daemon->master, take(out));

23
gossipd/routing.c

@ -377,7 +377,8 @@ static bool hc_can_carry(const struct half_chan *hc, u64 requiredcap)
static void bfg_one_edge(struct node *node,
struct chan *chan, int idx,
double riskfactor,
double fuzz, const struct siphash_seed *base_seed)
double fuzz, const struct siphash_seed *base_seed,
size_t max_hops)
{
size_t h;
double fee_scale = 1.0;
@ -394,7 +395,7 @@ static void bfg_one_edge(struct node *node,
fee_scale = 1.0 + (2.0 * fuzz * h / UINT64_MAX) - fuzz;
}
for (h = 0; h < ROUTING_MAX_HOPS; h++) {
for (h = 0; h < max_hops; h++) {
struct node *src;
/* FIXME: Bias against smaller channels. */
u64 fee;
@ -450,6 +451,7 @@ find_route(const tal_t *ctx, struct routing_state *rstate,
const struct pubkey *from, const struct pubkey *to, u64 msatoshi,
double riskfactor,
double fuzz, const struct siphash_seed *base_seed,
size_t max_hops,
u64 *fee)
{
struct chan **route;
@ -486,6 +488,11 @@ find_route(const tal_t *ctx, struct routing_state *rstate,
return NULL;
}
if (max_hops > ROUTING_MAX_HOPS) {
status_info("find_route: max_hops huge amount %zu", max_hops);
return NULL;
}
/* Reset all the information. */
clear_bfg(rstate->nodes);
@ -494,7 +501,7 @@ find_route(const tal_t *ctx, struct routing_state *rstate,
src->bfg[0].total = msatoshi;
src->bfg[0].risk = 0;
for (runs = 0; runs < ROUTING_MAX_HOPS; runs++) {
for (runs = 0; runs < max_hops; runs++) {
SUPERVERBOSE("Run %i", runs);
/* Run through every edge. */
for (n = node_map_first(rstate->nodes, &it);
@ -518,14 +525,15 @@ find_route(const tal_t *ctx, struct routing_state *rstate,
continue;
}
bfg_one_edge(n, chan, idx,
riskfactor, fuzz, base_seed);
riskfactor, fuzz, base_seed,
max_hops);
SUPERVERBOSE("...done");
}
}
}
best = 0;
for (i = 1; i <= ROUTING_MAX_HOPS; i++) {
for (i = 1; i <= max_hops; i++) {
if (dst->bfg[i].total < dst->bfg[best].total)
best = i;
}
@ -1498,7 +1506,8 @@ struct route_hop *get_route(const tal_t *ctx, struct routing_state *rstate,
u32 final_cltv,
double fuzz, const struct siphash_seed *base_seed,
const struct short_channel_id *excluded,
const bool *excluded_dir)
const bool *excluded_dir,
size_t max_hops)
{
struct chan **route;
u64 total_amount;
@ -1523,7 +1532,7 @@ struct route_hop *get_route(const tal_t *ctx, struct routing_state *rstate,
route = find_route(ctx, rstate, source, destination, msatoshi,
riskfactor / BLOCKS_PER_YEAR / 10000,
fuzz, base_seed, &fee);
fuzz, base_seed, max_hops, &fee);
/* Now restore the capacity. */
for (size_t i = 0; i < tal_count(excluded); i++) {

3
gossipd/routing.h

@ -269,7 +269,8 @@ struct route_hop *get_route(const tal_t *ctx, struct routing_state *rstate,
double fuzz,
const struct siphash_seed *base_seed,
const struct short_channel_id *excluded,
const bool *excluded_dir);
const bool *excluded_dir,
size_t max_hops);
/* Disable channel(s) based on the given routing failure. */
void routing_failure(struct routing_state *rstate,
const struct pubkey *erring_node,

1
gossipd/test/run-bench-find_route.c

@ -261,6 +261,7 @@ int main(int argc, char *argv[])
pseudorand(100000),
riskfactor,
0.75, &base_seed,
ROUTING_MAX_HOPS,
&fee);
num_success += (route != NULL);
tal_free(route);

18
gossipd/test/run-find_route-specific.c

@ -222,7 +222,8 @@ int main(void)
nc->message_flags = 0;
nc->last_timestamp = 1504064344;
route = find_route(tmpctx, rstate, &a, &c, 100000, riskfactor, 0.0, NULL, &fee);
route = find_route(tmpctx, rstate, &a, &c, 100000, riskfactor, 0.0, NULL,
ROUTING_MAX_HOPS, &fee);
assert(route);
assert(tal_count(route) == 2);
assert(channel_is_between(route[0], &a, &b));
@ -230,17 +231,20 @@ int main(void)
/* We should not be able to find a route that exceeds our own capacity */
route = find_route(tmpctx, rstate, &a, &c, 1000001, riskfactor, 0.0, NULL, &fee);
route = find_route(tmpctx, rstate, &a, &c, 1000001, riskfactor, 0.0, NULL,
ROUTING_MAX_HOPS, &fee);
assert(!route);
/* Now test with a query that exceeds the channel capacity after adding
* some fees */
route = find_route(tmpctx, rstate, &a, &c, 999999, riskfactor, 0.0, NULL, &fee);
route = find_route(tmpctx, rstate, &a, &c, 999999, riskfactor, 0.0, NULL,
ROUTING_MAX_HOPS, &fee);
assert(!route);
/* This should fail to return a route because it is smaller than these
* htlc_minimum_msat on the last channel. */
route = find_route(tmpctx, rstate, &a, &c, 1, riskfactor, 0.0, NULL, &fee);
route = find_route(tmpctx, rstate, &a, &c, 1, riskfactor, 0.0, NULL,
ROUTING_MAX_HOPS, &fee);
assert(!route);
/* {'active': True, 'short_id': '6990:2:1/0', 'fee_per_kw': 10, 'delay': 5, 'message_flags': 1, 'htlc_maximum_msat': 500000, 'htlc_minimum_msat': 100, 'channel_flags': 0, 'destination': '02cca6c5c966fcf61d121e3a70e03a1cd9eeeea024b26ea666ce974d43b242e636', 'source': '03c173897878996287a8100469f954dd820fcd8941daed91c327f168f3329be0bf', 'last_update': 1504064344}, */
@ -255,12 +259,14 @@ int main(void)
nc->htlc_maximum_msat = 500000; /* half capacity */
/* This should route correctly at the max_msat level */
route = find_route(tmpctx, rstate, &a, &d, 500000, riskfactor, 0.0, NULL, &fee);
route = find_route(tmpctx, rstate, &a, &d, 500000, riskfactor, 0.0, NULL,
ROUTING_MAX_HOPS, &fee);
assert(route);
/* This should fail to return a route because it's larger than the
* htlc_maximum_msat on the last channel. */
route = find_route(tmpctx, rstate, &a, &d, 500001, riskfactor, 0.0, NULL, &fee);
route = find_route(tmpctx, rstate, &a, &d, 500001, riskfactor, 0.0, NULL,
ROUTING_MAX_HOPS, &fee);
assert(!route);
tal_free(tmpctx);

15
gossipd/test/run-find_route.c

@ -222,7 +222,8 @@ int main(void)
/* A<->B */
add_connection(rstate, &a, &b, 1, 1, 1);
route = find_route(tmpctx, rstate, &a, &b, 1000, riskfactor, 0.0, NULL, &fee);
route = find_route(tmpctx, rstate, &a, &b, 1000, riskfactor, 0.0, NULL,
ROUTING_MAX_HOPS, &fee);
assert(route);
assert(tal_count(route) == 1);
assert(fee == 0);
@ -237,7 +238,8 @@ int main(void)
status_trace("C = %s", type_to_string(tmpctx, struct pubkey, &c));
add_connection(rstate, &b, &c, 1, 1, 1);
route = find_route(tmpctx, rstate, &a, &c, 1000, riskfactor, 0.0, NULL, &fee);
route = find_route(tmpctx, rstate, &a, &c, 1000, riskfactor, 0.0, NULL,
ROUTING_MAX_HOPS, &fee);
assert(route);
assert(tal_count(route) == 2);
assert(fee == 1);
@ -252,7 +254,8 @@ int main(void)
add_connection(rstate, &d, &c, 0, 2, 1);
/* Will go via D for small amounts. */
route = find_route(tmpctx, rstate, &a, &c, 1000, riskfactor, 0.0, NULL, &fee);
route = find_route(tmpctx, rstate, &a, &c, 1000, riskfactor, 0.0, NULL,
ROUTING_MAX_HOPS, &fee);
assert(route);
assert(tal_count(route) == 2);
assert(channel_is_between(route[0], &a, &d));
@ -260,7 +263,8 @@ int main(void)
assert(fee == 0);
/* Will go via B for large amounts. */
route = find_route(tmpctx, rstate, &a, &c, 3000000, riskfactor, 0.0, NULL, &fee);
route = find_route(tmpctx, rstate, &a, &c, 3000000, riskfactor, 0.0, NULL,
ROUTING_MAX_HOPS, &fee);
assert(route);
assert(tal_count(route) == 2);
assert(channel_is_between(route[0], &a, &b));
@ -269,7 +273,8 @@ int main(void)
/* Make B->C inactive, force it back via D */
get_connection(rstate, &b, &c)->channel_flags |= ROUTING_FLAGS_DISABLED;
route = find_route(tmpctx, rstate, &a, &c, 3000000, riskfactor, 0.0, NULL, &fee);
route = find_route(tmpctx, rstate, &a, &c, 3000000, riskfactor, 0.0, NULL,
ROUTING_MAX_HOPS, &fee);
assert(route);
assert(tal_count(route) == 2);
assert(channel_is_between(route[0], &a, &d));

6
lightningd/gossip_control.c

@ -327,6 +327,7 @@ static struct command_result *json_getroute(struct command *cmd,
double *riskfactor;
struct short_channel_id *excluded;
bool *excluded_dir;
u32 *max_hops;
/* Higher fuzz means that some high-fee paths can be discounted
* for an even larger value, increasing the scope for route
@ -343,6 +344,8 @@ static struct command_result *json_getroute(struct command *cmd,
p_opt_def("fromid", param_pubkey, &source, ld->id),
p_opt_def("fuzzpercent", param_percent, &fuzz, 5.0),
p_opt("exclude", param_array, &excludetok),
p_opt_def("maxhops", param_number, &max_hops,
ROUTING_MAX_HOPS),
NULL))
return command_param_failed();
@ -378,7 +381,8 @@ static struct command_result *json_getroute(struct command *cmd,
u8 *req = towire_gossip_getroute_request(cmd, source, destination,
*msatoshi, *riskfactor * 1000,
*cltv, fuzz,
excluded, excluded_dir);
excluded, excluded_dir,
*max_hops);
subd_req(ld->gossip, ld->gossip, req, -1, 0, json_getroute_reply, cmd);
return command_still_pending(cmd);
}

3
lightningd/payalgo.c

@ -557,7 +557,8 @@ static struct command_result *json_pay_try(struct pay *pay)
pay->msatoshi + overpayment,
pay->riskfactor,
pay->min_final_cltv_expiry,
&pay->fuzz, NULL, NULL);
&pay->fuzz, NULL, NULL,
ROUTING_MAX_HOPS);
subd_req(pay->try_parent, cmd->ld->gossip, req, -1, 0, json_pay_getroute_reply, pay);
return NULL;

Loading…
Cancel
Save