getroute: allow caller to specify maximum hops.

This is required for routeboost.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell
2019-01-15 14:36:27 +10:30
committed by Christian Decker
parent 3d016e7249
commit 358b7fda91
9 changed files with 57 additions and 27 deletions

View File

@@ -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
1 #include <common/cryptomsg.h>
35 gossip_getroute_reply,,num_hops,u16 gossip_getroute_reply,3106
36 gossip_getroute_reply,,hops,num_hops*struct route_hop gossip_getroute_reply,,num_hops,u16
37 gossip_getchannels_request,3007 gossip_getroute_reply,,hops,num_hops*struct route_hop
38 gossip_getchannels_request,3007
39 gossip_getchannels_request,,short_channel_id,?struct short_channel_id
40 gossip_getchannels_reply,3107
41 gossip_getchannels_reply,,num_channels,u16

View File

@@ -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));

View File

@@ -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++) {

View File

@@ -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,

View File

@@ -258,10 +258,11 @@ int main(int argc, char *argv[])
struct chan **route;
route = find_route(tmpctx, rstate, from, to,
pseudorand(100000),
riskfactor,
0.75, &base_seed,
&fee);
pseudorand(100000),
riskfactor,
0.75, &base_seed,
ROUTING_MAX_HOPS,
&fee);
num_success += (route != NULL);
tal_free(route);
}

View File

@@ -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);

View File

@@ -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));

View File

@@ -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);
}

View File

@@ -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;