mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-23 17:14:22 +01:00
devtool/route: simple routing tool and benchmark.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
DEVTOOLS_SRC := devtools/gen_print_wire.c devtools/gen_print_onion_wire.c devtools/print_wire.c
|
DEVTOOLS_SRC := devtools/gen_print_wire.c devtools/gen_print_onion_wire.c devtools/print_wire.c
|
||||||
DEVTOOLS_OBJS := $(DEVTOOLS_SRC:.c=.o)
|
DEVTOOLS_OBJS := $(DEVTOOLS_SRC:.c=.o)
|
||||||
DEVTOOLS := devtools/bolt11-cli devtools/decodemsg devtools/onion devtools/dump-gossipstore devtools/gossipwith devtools/create-gossipstore devtools/mkcommit devtools/mkfunding devtools/mkclose devtools/mkgossip devtools/mkencoded devtools/checkchannels devtools/mkquery devtools/lightning-checkmessage devtools/topology
|
DEVTOOLS := devtools/bolt11-cli devtools/decodemsg devtools/onion devtools/dump-gossipstore devtools/gossipwith devtools/create-gossipstore devtools/mkcommit devtools/mkfunding devtools/mkclose devtools/mkgossip devtools/mkencoded devtools/checkchannels devtools/mkquery devtools/lightning-checkmessage devtools/topology devtools/route
|
||||||
ifeq ($(EXPERIMENTAL_FEATURES),1)
|
ifeq ($(EXPERIMENTAL_FEATURES),1)
|
||||||
DEVTOOLS += devtools/blindedpath
|
DEVTOOLS += devtools/blindedpath
|
||||||
endif
|
endif
|
||||||
@@ -93,6 +93,8 @@ devtools/mkquery: $(DEVTOOLS_COMMON_OBJS) $(CCAN_OBJS) $(BITCOIN_OBJS) wire/from
|
|||||||
|
|
||||||
devtools/lightning-checkmessage: $(DEVTOOLS_COMMON_OBJS) $(CCAN_OBJS) $(BITCOIN_OBJS) wire/fromwire.o wire/towire.o devtools/lightning-checkmessage.o
|
devtools/lightning-checkmessage: $(DEVTOOLS_COMMON_OBJS) $(CCAN_OBJS) $(BITCOIN_OBJS) wire/fromwire.o wire/towire.o devtools/lightning-checkmessage.o
|
||||||
|
|
||||||
|
devtools/route: $(DEVTOOLS_COMMON_OBJS) $(CCAN_OBJS) $(BITCOIN_OBJS) wire/fromwire.o wire/towire.o wire/tlvstream.o common/gossmap.o common/random_select.o common/route.o common/dijkstra.o devtools/clean_topo.o devtools/route.o
|
||||||
|
|
||||||
devtools/topology: $(DEVTOOLS_COMMON_OBJS) $(CCAN_OBJS) $(BITCOIN_OBJS) wire/fromwire.o wire/towire.o wire/tlvstream.o common/gossmap.o common/random_select.o common/dijkstra.o common/route.o devtools/clean_topo.o devtools/topology.o
|
devtools/topology: $(DEVTOOLS_COMMON_OBJS) $(CCAN_OBJS) $(BITCOIN_OBJS) wire/fromwire.o wire/towire.o wire/tlvstream.o common/gossmap.o common/random_select.o common/dijkstra.o common/route.o devtools/clean_topo.o devtools/topology.o
|
||||||
|
|
||||||
# Make sure these depend on everything.
|
# Make sure these depend on everything.
|
||||||
|
|||||||
165
devtools/route.c
Normal file
165
devtools/route.c
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
#include <ccan/err/err.h>
|
||||||
|
#include <ccan/opt/opt.h>
|
||||||
|
#include <ccan/time/time.h>
|
||||||
|
#include <common/amount.h>
|
||||||
|
#include <common/dijkstra.h>
|
||||||
|
#include <common/gossmap.h>
|
||||||
|
#include <common/node_id.h>
|
||||||
|
#include <common/pseudorand.h>
|
||||||
|
#include <common/random_select.h>
|
||||||
|
#include <common/route.h>
|
||||||
|
#include <common/type_to_string.h>
|
||||||
|
#include <devtools/clean_topo.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* ->B->C->D. D needs 100msat, each charges 10msat. */
|
||||||
|
static struct amount_msat route_amount(struct route **path,
|
||||||
|
size_t npath,
|
||||||
|
struct amount_msat amount)
|
||||||
|
{
|
||||||
|
if (npath == 0)
|
||||||
|
return amount;
|
||||||
|
|
||||||
|
amount = route_amount(path+1, npath-1, amount);
|
||||||
|
if (!amount_msat_add_fee(&amount,
|
||||||
|
path[0]->c->half[path[0]->dir].base_fee,
|
||||||
|
path[0]->c->half[path[0]->dir].proportional_fee))
|
||||||
|
abort();
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct route **least_cost(struct gossmap *map,
|
||||||
|
struct gossmap_node *src,
|
||||||
|
struct gossmap_node *dst)
|
||||||
|
{
|
||||||
|
const struct dijkstra *dij;
|
||||||
|
u32 srcidx = gossmap_node_idx(map, src);
|
||||||
|
/* 10ksat, budget is 0.5% */
|
||||||
|
const struct amount_msat sent = AMOUNT_MSAT(10000000);
|
||||||
|
const struct amount_msat budget = amount_msat_div(sent, 200);
|
||||||
|
struct amount_msat fee;
|
||||||
|
const u32 riskfactor = 10;
|
||||||
|
/* Max distance is 20 */
|
||||||
|
const u32 distance_budget = ROUTING_MAX_HOPS;
|
||||||
|
struct amount_msat maxcost;
|
||||||
|
struct route **path;
|
||||||
|
struct timemono tstart, tstop;
|
||||||
|
|
||||||
|
setup_locale();
|
||||||
|
setup_tmpctx();
|
||||||
|
|
||||||
|
tstart = time_mono();
|
||||||
|
dij = dijkstra(tmpctx, map, dst,
|
||||||
|
sent, riskfactor, route_can_carry,
|
||||||
|
route_path_cheaper, NULL);
|
||||||
|
tstop = time_mono();
|
||||||
|
|
||||||
|
printf("# Time to find route: %"PRIu64" usec\n",
|
||||||
|
time_to_usec(timemono_between(tstop, tstart)));
|
||||||
|
|
||||||
|
if (dijkstra_distance(dij, srcidx) > distance_budget) {
|
||||||
|
printf("failed (too far)\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!amount_msat_add(&maxcost, sent, budget))
|
||||||
|
abort();
|
||||||
|
if (amount_msat_greater(dijkstra_amount(dij, srcidx), maxcost)) {
|
||||||
|
printf("failed (too expensive)\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
path = route_from_dijkstra(map, dij, src);
|
||||||
|
printf("# path length %zu\n", tal_count(path));
|
||||||
|
/* We don't pay fee on first hop! */
|
||||||
|
if (!amount_msat_sub(&fee,
|
||||||
|
route_amount(path+1, tal_count(path)-1, sent),
|
||||||
|
sent))
|
||||||
|
abort();
|
||||||
|
printf("# path fee %s\n",
|
||||||
|
type_to_string(tmpctx, struct amount_msat, &fee));
|
||||||
|
tal_free(dij);
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct timemono tstart, tstop;
|
||||||
|
struct gossmap_node *n, *dst;
|
||||||
|
struct gossmap *map;
|
||||||
|
struct node_id dstid;
|
||||||
|
bool clean_topology = false;
|
||||||
|
|
||||||
|
opt_register_noarg("--clean-topology", opt_set_bool, &clean_topology,
|
||||||
|
"Clean up topology before run");
|
||||||
|
opt_register_noarg("-h|--help", opt_usage_and_exit,
|
||||||
|
"<gossipstore> <srcid>|all <dstid>\n"
|
||||||
|
"A routing test and benchmark program.",
|
||||||
|
"Get usage information");
|
||||||
|
opt_parse(&argc, argv, opt_log_stderr_exit);
|
||||||
|
if (argc != 4)
|
||||||
|
opt_usage_exit_fail("Expect 3 arguments");
|
||||||
|
|
||||||
|
tstart = time_mono();
|
||||||
|
map = gossmap_load(NULL, argv[1]);
|
||||||
|
if (!map)
|
||||||
|
err(1, "Loading gossip store %s", argv[1]);
|
||||||
|
tstop = time_mono();
|
||||||
|
|
||||||
|
printf("# Time to load: %"PRIu64" msec\n",
|
||||||
|
time_to_msec(timemono_between(tstop, tstart)));
|
||||||
|
|
||||||
|
if (clean_topology)
|
||||||
|
clean_topo(map, false);
|
||||||
|
|
||||||
|
if (!node_id_from_hexstr(argv[3], strlen(argv[3]), &dstid))
|
||||||
|
errx(1, "Bad dstid");
|
||||||
|
dst = gossmap_find_node(map, &dstid);
|
||||||
|
if (!dst)
|
||||||
|
errx(1, "Unknown destination node '%s'", argv[3]);
|
||||||
|
|
||||||
|
if (streq(argv[2], "all")) {
|
||||||
|
for (n = gossmap_first_node(map);
|
||||||
|
n;
|
||||||
|
n = gossmap_next_node(map, n)) {
|
||||||
|
struct node_id srcid, dstid;
|
||||||
|
|
||||||
|
gossmap_node_get_id(map, n, &srcid);
|
||||||
|
gossmap_node_get_id(map, dst, &dstid);
|
||||||
|
printf("# %s->%s\n",
|
||||||
|
type_to_string(tmpctx, struct node_id, &srcid),
|
||||||
|
type_to_string(tmpctx, struct node_id, &dstid));
|
||||||
|
tal_free(least_cost(map, n, dst));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
struct route **path;
|
||||||
|
struct node_id srcid;
|
||||||
|
|
||||||
|
if (!node_id_from_hexstr(argv[2], strlen(argv[2]), &srcid))
|
||||||
|
errx(1, "Bad srcid");
|
||||||
|
n = gossmap_find_node(map, &srcid);
|
||||||
|
if (!n)
|
||||||
|
errx(1, "Unknown source node '%s'", argv[2]);
|
||||||
|
path = least_cost(map, n, dst);
|
||||||
|
if (!path)
|
||||||
|
exit(1);
|
||||||
|
for (size_t i = 0; i < tal_count(path); i++) {
|
||||||
|
struct gossmap_node *from, *to;
|
||||||
|
struct node_id fromid, toid;
|
||||||
|
struct short_channel_id scid;
|
||||||
|
|
||||||
|
from = gossmap_nth_node(map, path[i]->c, path[i]->dir);
|
||||||
|
to = gossmap_nth_node(map, path[i]->c, !path[i]->dir);
|
||||||
|
gossmap_node_get_id(map, from, &fromid);
|
||||||
|
gossmap_node_get_id(map, to, &toid);
|
||||||
|
scid = gossmap_chan_scid(map, path[i]->c);
|
||||||
|
printf("%s->%s via %s\n",
|
||||||
|
type_to_string(tmpctx, struct node_id, &fromid),
|
||||||
|
type_to_string(tmpctx, struct node_id, &toid),
|
||||||
|
type_to_string(tmpctx, struct short_channel_id,
|
||||||
|
&scid));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tal_free(map);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user