mirror of
https://github.com/aljazceru/lightning.git
synced 2026-01-07 08:04:23 +01:00
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:
committed by
Christian Decker
parent
3d016e7249
commit
358b7fda91
@@ -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
|
||||
|
||||
|
@@ -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));
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user