mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 21:35:11 +01:00
gossipd: re-add fuzz logic to routing.
Do it inside the can_reach() function, which is less optimal for BFG which does 20 ops on the same channel, but fine for Dijkstra. This does have a measurable cost, so we might want to use non-cryptographic fuzz in future: $ gossipd/test/run-bench-find_route 100000 100: Before: 100 (100 succeeded) routes in 100000 nodes in 97346 msec (973461784 nanoseconds per route) After: 100 (100 succeeded) routes in 100000 nodes in 113381 msec (1133813412 nanoseconds per route) Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
e197956032
commit
cfdb012b30
@ -488,9 +488,25 @@ static bool hc_can_carry(const struct half_chan *hc,
|
||||
}
|
||||
|
||||
/* Theoretically, this could overflow. */
|
||||
static bool fuzz_fee(u64 *fee, double fee_scale)
|
||||
static bool fuzz_fee(u64 *fee,
|
||||
const struct short_channel_id *scid,
|
||||
double fuzz, const struct siphash_seed *base_seed)
|
||||
{
|
||||
u64 fuzzed_fee = *fee * fee_scale;
|
||||
u64 fuzzed_fee, h;
|
||||
double fee_scale;
|
||||
|
||||
if (fuzz == 0.0)
|
||||
return true;
|
||||
|
||||
h = siphash24(base_seed, scid, sizeof(*scid));
|
||||
|
||||
/* Scale fees for this channel */
|
||||
/* rand = (h / UINT64_MAX) random number between 0.0 -> 1.0
|
||||
* 2*fuzz*rand random number between 0.0 -> 2*fuzz
|
||||
* 2*fuzz*rand - fuzz random number between -fuzz -> +fuzz
|
||||
*/
|
||||
fee_scale = 1.0 + (2.0 * fuzz * h / UINT64_MAX) - fuzz;
|
||||
fuzzed_fee = *fee * fee_scale;
|
||||
if (fee_scale > 1.0 && fuzzed_fee < *fee)
|
||||
return false;
|
||||
*fee = fuzzed_fee;
|
||||
@ -500,10 +516,12 @@ static bool fuzz_fee(u64 *fee, double fee_scale)
|
||||
/* Can we carry this amount across the channel? If so, returns true and
|
||||
* sets newtotal and newrisk */
|
||||
static bool can_reach(const struct half_chan *c,
|
||||
const struct short_channel_id *scid,
|
||||
struct amount_msat total,
|
||||
struct amount_msat risk,
|
||||
double riskfactor, double fee_scale,
|
||||
double riskfactor,
|
||||
u64 riskbias,
|
||||
double fuzz, const struct siphash_seed *base_seed,
|
||||
struct amount_msat *newtotal, struct amount_msat *newrisk)
|
||||
{
|
||||
/* FIXME: Bias against smaller channels. */
|
||||
@ -512,7 +530,7 @@ static bool can_reach(const struct half_chan *c,
|
||||
if (!amount_msat_fee(&fee, total, c->base_fee, c->proportional_fee))
|
||||
return false;
|
||||
|
||||
if (!fuzz_fee(&fee.millisatoshis, fee_scale)) /* Raw: double manipulation */
|
||||
if (!fuzz_fee(&fee.millisatoshis, scid, fuzz, base_seed)) /* Raw: double manipulation */
|
||||
return false;
|
||||
|
||||
if (!amount_msat_add(newtotal, total, fee))
|
||||
@ -595,15 +613,14 @@ static void bfg_one_edge(struct node *node,
|
||||
size_t max_hops)
|
||||
{
|
||||
size_t h;
|
||||
double fee_scale = 1.0;
|
||||
const struct half_chan *c = &chan->half[idx];
|
||||
|
||||
for (h = 0; h < max_hops; h++) {
|
||||
struct node *src;
|
||||
struct amount_msat total, risk;
|
||||
|
||||
if (!can_reach(c, node->bfg[h].total, node->bfg[h].risk,
|
||||
riskfactor, fee_scale, 1, &total, &risk))
|
||||
if (!can_reach(c, &chan->scid, node->bfg[h].total, node->bfg[h].risk,
|
||||
riskfactor, 1, fuzz, base_seed, &total, &risk))
|
||||
continue;
|
||||
|
||||
/* nodes[0] is src for connections[0] */
|
||||
@ -764,6 +781,8 @@ static void update_unvisited_neighbors(struct routing_state *rstate,
|
||||
struct node *cur,
|
||||
double riskfactor,
|
||||
u64 riskbias,
|
||||
double fuzz,
|
||||
const struct siphash_seed *base_seed,
|
||||
struct unvisited *unvisited,
|
||||
costfn_t *costfn)
|
||||
{
|
||||
@ -796,9 +815,9 @@ static void update_unvisited_neighbors(struct routing_state *rstate,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!can_reach(&chan->half[idx],
|
||||
if (!can_reach(&chan->half[idx], &chan->scid,
|
||||
cur->dijkstra.total, cur->dijkstra.risk,
|
||||
riskfactor, 1.0 /*FIXME*/, riskbias,
|
||||
riskfactor, riskbias, fuzz, base_seed,
|
||||
&total, &risk)) {
|
||||
SUPERVERBOSE("... can't reach");
|
||||
continue;
|
||||
@ -845,6 +864,7 @@ static void dijkstra(struct routing_state *rstate,
|
||||
const struct node *dst,
|
||||
double riskfactor,
|
||||
u64 riskbias,
|
||||
double fuzz, const struct siphash_seed *base_seed,
|
||||
struct unvisited *unvisited,
|
||||
costfn_t *costfn)
|
||||
{
|
||||
@ -852,7 +872,7 @@ static void dijkstra(struct routing_state *rstate,
|
||||
|
||||
while ((cur = first_unvisited(unvisited)) != NULL) {
|
||||
update_unvisited_neighbors(rstate, cur, riskfactor, riskbias,
|
||||
unvisited, costfn);
|
||||
fuzz, base_seed, unvisited, costfn);
|
||||
remove_unvisited(cur, unvisited, costfn);
|
||||
if (cur == dst)
|
||||
return;
|
||||
@ -867,6 +887,8 @@ static struct chan **build_route(const tal_t *ctx,
|
||||
const struct node *to,
|
||||
double riskfactor,
|
||||
u64 riskbias,
|
||||
double fuzz,
|
||||
const struct siphash_seed *base_seed,
|
||||
struct amount_msat *fee)
|
||||
{
|
||||
const struct node *i;
|
||||
@ -909,10 +931,11 @@ static struct chan **build_route(const tal_t *ctx,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!can_reach(hc,
|
||||
if (!can_reach(hc, &chan->scid,
|
||||
peer->dijkstra.total, peer->dijkstra.risk,
|
||||
riskfactor, 1.0 /*FIXME*/,
|
||||
riskfactor,
|
||||
riskbias,
|
||||
fuzz, base_seed,
|
||||
&total, &risk))
|
||||
continue;
|
||||
|
||||
@ -1006,6 +1029,7 @@ find_shorter_route(const tal_t *ctx, struct routing_state *rstate,
|
||||
struct node *src, struct node *dst,
|
||||
struct amount_msat msat,
|
||||
size_t max_hops,
|
||||
double fuzz, const struct siphash_seed *base_seed,
|
||||
struct chan **long_route,
|
||||
struct amount_msat *fee)
|
||||
{
|
||||
@ -1036,11 +1060,13 @@ find_shorter_route(const tal_t *ctx, struct routing_state *rstate,
|
||||
SUPERVERBOSE("Running shortest path from %s -> %s",
|
||||
type_to_string(tmpctx, struct node_id, &dst->id),
|
||||
type_to_string(tmpctx, struct node_id, &src->id));
|
||||
dijkstra(rstate, dst, riskfactor, 1, unvisited, shortest_cost_function);
|
||||
dijkstra(rstate, dst, riskfactor, 1, fuzz, base_seed,
|
||||
unvisited, shortest_cost_function);
|
||||
dijkstra_cleanup(unvisited);
|
||||
|
||||
/* This must succeed, since we found a route before */
|
||||
short_route = build_route(ctx, rstate, dst, src, riskfactor, 1, fee);
|
||||
short_route = build_route(ctx, rstate, dst, src, riskfactor, 1,
|
||||
fuzz, base_seed, fee);
|
||||
assert(short_route);
|
||||
if (!amount_msat_sub(&short_cost,
|
||||
dst->dijkstra.total, src->dijkstra.total))
|
||||
@ -1081,12 +1107,12 @@ find_shorter_route(const tal_t *ctx, struct routing_state *rstate,
|
||||
|
||||
unvisited = dijkstra_prepare(tmpctx, rstate, src, msat,
|
||||
normal_cost_function);
|
||||
dijkstra(rstate, dst, riskfactor, riskbias, unvisited,
|
||||
normal_cost_function);
|
||||
dijkstra(rstate, dst, riskfactor, riskbias, fuzz, base_seed,
|
||||
unvisited, normal_cost_function);
|
||||
dijkstra_cleanup(unvisited);
|
||||
|
||||
route = build_route(ctx, rstate, dst, src, riskfactor, riskbias,
|
||||
&this_fee);
|
||||
fuzz, base_seed, &this_fee);
|
||||
|
||||
SUPERVERBOSE("riskbias %"PRIu64" rlen %zu",
|
||||
riskbias, tal_count(route));
|
||||
@ -1152,16 +1178,18 @@ find_route_dijkstra(const tal_t *ctx, struct routing_state *rstate,
|
||||
|
||||
unvisited = dijkstra_prepare(tmpctx, rstate, src, msat,
|
||||
normal_cost_function);
|
||||
dijkstra(rstate, dst, riskfactor, 1, unvisited, normal_cost_function);
|
||||
dijkstra(rstate, dst, riskfactor, 1, fuzz, base_seed,
|
||||
unvisited, normal_cost_function);
|
||||
dijkstra_cleanup(unvisited);
|
||||
|
||||
route = build_route(ctx, rstate, dst, src, riskfactor, 1, fee);
|
||||
route = build_route(ctx, rstate, dst, src, riskfactor, 1,
|
||||
fuzz, base_seed, fee);
|
||||
if (tal_count(route) <= max_hops)
|
||||
return route;
|
||||
|
||||
/* This is the far more unlikely case */
|
||||
return find_shorter_route(ctx, rstate, src, dst, msat,
|
||||
max_hops, route, fee);
|
||||
max_hops, fuzz, base_seed, route, fee);
|
||||
}
|
||||
|
||||
/* riskfactor is already scaled to per-block amount */
|
||||
|
Loading…
Reference in New Issue
Block a user