From 6815a1d9a285e7f6299dec6b7bb07af5396703ff Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 26 Aug 2020 10:10:48 +0930 Subject: [PATCH] common/route: routing helpers built on gossmap and dijksra. Signed-off-by: Rusty Russell --- common/Makefile | 1 + common/route.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++ common/route.h | 49 +++++++++++++++++++++++ 3 files changed, 152 insertions(+) create mode 100644 common/route.c create mode 100644 common/route.h diff --git a/common/Makefile b/common/Makefile index 6096266cb..b75e89a75 100644 --- a/common/Makefile +++ b/common/Makefile @@ -61,6 +61,7 @@ COMMON_SRC_NOGEN := \ common/pseudorand.c \ common/random_select.c \ common/read_peer_msg.c \ + common/route.c \ common/setup.c \ common/socket_close.c \ common/sphinx.c \ diff --git a/common/route.c b/common/route.c new file mode 100644 index 000000000..a3ae3ac01 --- /dev/null +++ b/common/route.c @@ -0,0 +1,102 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +bool route_can_carry_even_disabled(const struct gossmap *map, + const struct gossmap_chan *c, + int dir, + struct amount_msat amount, + void *unused) +{ + if (!gossmap_chan_set(c, dir)) + return false; + if (!gossmap_chan_capacity(c, dir, amount)) + return false; + return true; +} + +/* Generally only one side gets marked disabled, but it's disabled. */ +bool route_can_carry(const struct gossmap *map, + const struct gossmap_chan *c, + int dir, + struct amount_msat amount, + void *arg) +{ + if (!c->half[dir].enabled || !c->half[!dir].enabled) + return false; + return route_can_carry_even_disabled(map, c, dir, amount, arg); +} + +bool route_path_shorter(u32 old_distance, u32 new_distance, + struct amount_msat old_cost, + struct amount_msat new_cost, + struct amount_msat old_risk, + struct amount_msat new_risk, + void *unused) +{ + if (new_distance > old_distance) + return false; + if (new_distance < old_distance) + return true; + + /* Tiebreak by cost */ + if (!amount_msat_add(&old_cost, old_cost, old_risk) + || !amount_msat_add(&new_cost, new_cost, new_risk)) + return false; + return amount_msat_less(new_cost, old_cost); +} + +bool route_path_cheaper(u32 old_distance, u32 new_distance, + struct amount_msat old_cost, + struct amount_msat new_cost, + struct amount_msat old_risk, + struct amount_msat new_risk, + void *unused) +{ + if (!amount_msat_add(&old_cost, old_cost, old_risk) + || !amount_msat_add(&new_cost, new_cost, new_risk)) + return false; + + if (amount_msat_greater(new_cost, old_cost)) + return false; + if (amount_msat_less(new_cost, old_cost)) + return true; + + /* Tiebreak by distance */ + return new_distance < old_distance; +} + +struct route **route_from_dijkstra(const struct gossmap *map, + const struct dijkstra *dij, + const struct gossmap_node *cur) +{ + struct route **path = tal_arr(map, struct route *, 0); + u32 curidx = gossmap_node_idx(map, cur); + + while (dijkstra_distance(dij, curidx) != 0) { + struct route *r; + + r = tal(path, struct route); + r->c = dijkstra_best_chan(dij, curidx); + if (r->c->half[0].nodeidx == curidx) { + r->dir = 0; + } else { + assert(r->c->half[1].nodeidx == curidx); + r->dir = 1; + } + tal_arr_expand(&path, r); + cur = gossmap_nth_node(map, r->c, !r->dir); + curidx = gossmap_node_idx(map, cur); + } + return path; +} diff --git a/common/route.h b/common/route.h new file mode 100644 index 000000000..fdb7c02d1 --- /dev/null +++ b/common/route.h @@ -0,0 +1,49 @@ +/* Routing helpers for use with dijkstra */ +#ifndef LIGHTNING_COMMON_ROUTE_H +#define LIGHTNING_COMMON_ROUTE_H +#include "config.h" +#include + +struct dijkstra; +struct gossmap; + +struct route { + int dir; + struct gossmap_chan *c; +}; + +/* Can c carrt amount in dir? */ +bool route_can_carry(const struct gossmap *map, + const struct gossmap_chan *c, + int dir, + struct amount_msat amount, + void *arg); + +/* Same, but ignore disabled flags on channel */ +bool route_can_carry_even_disabled(const struct gossmap *map, + const struct gossmap_chan *c, + int dir, + struct amount_msat amount, + void *unused); + +/* Shortest path, with lower amount tiebreak */ +bool route_path_shorter(u32 old_distance, u32 new_distance, + struct amount_msat old_cost, + struct amount_msat new_cost, + struct amount_msat old_risk, + struct amount_msat new_risk, + void *unused); + +/* Cheapest path, with shorter path tiebreak */ +bool route_path_cheaper(u32 old_distance, u32 new_distance, + struct amount_msat old_cost, + struct amount_msat new_cost, + struct amount_msat old_risk, + struct amount_msat new_risk, + void *unused); + +/* Extract route tal_arr from completed dijkstra */ +struct route **route_from_dijkstra(const struct gossmap *map, + const struct dijkstra *dij, + const struct gossmap_node *cur); +#endif /* LIGHTNING_COMMON_ROUTE_H */