mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-17 19:03:42 +01:00
routing: remove possibility of overflow.
This check is expensive, so just restrict msatoshi going in, as well as turn off channels charging more than 24x fee. # 1M nodes: $ /gossipd/test/run-bench-find_route 1000000 1 > /tmp/out => 44164 msec Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
589cb673ce
commit
2824ff2b30
@ -6,7 +6,6 @@
|
||||
#include <ccan/endian/endian.h>
|
||||
#include <ccan/structeq/structeq.h>
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <common/overflows.h>
|
||||
#include <common/pseudorand.h>
|
||||
#include <common/status.h>
|
||||
#include <common/type_to_string.h>
|
||||
@ -21,6 +20,12 @@
|
||||
/* 365.25 * 24 * 60 / 10 */
|
||||
#define BLOCKS_PER_YEAR 52596
|
||||
|
||||
/* For overflow avoidance, we never deal with msatoshi > 40 bits. */
|
||||
#define MAX_MSATOSHI (1ULL << 40)
|
||||
|
||||
/* Proportional fee must be less than 24 bits, so never overflows. */
|
||||
#define MAX_PROPORTIONAL_FEE (1 << 24)
|
||||
|
||||
static struct node_map *empty_node_map(const tal_t *ctx)
|
||||
{
|
||||
struct node_map *map = tal(ctx, struct node_map);
|
||||
@ -250,8 +255,9 @@ static u64 connection_fee(const struct node_connection *c, u64 msatoshi)
|
||||
{
|
||||
u64 fee;
|
||||
|
||||
if (mul_overflows_u64(c->proportional_fee, msatoshi))
|
||||
return INFINITE;
|
||||
assert(msatoshi < MAX_MSATOSHI);
|
||||
assert(c->proportional_fee < MAX_PROPORTIONAL_FEE);
|
||||
|
||||
fee = (c->proportional_fee * msatoshi) / 1000000;
|
||||
/* This can't overflow: c->base_fee is a u32 */
|
||||
return c->base_fee + fee;
|
||||
@ -283,6 +289,15 @@ static void bfg_one_edge(struct node *node, size_t edgenum, double riskfactor)
|
||||
fee = connection_fee(c, node->bfg[h].total);
|
||||
risk = node->bfg[h].risk + risk_fee(node->bfg[h].total + fee,
|
||||
c->delay, riskfactor);
|
||||
|
||||
if (node->bfg[h].total + fee + risk >= MAX_MSATOSHI) {
|
||||
SUPERVERBOSE("...extreme %"PRIu64
|
||||
" + fee %"PRIu64
|
||||
" + risk %"PRIu64" ignored",
|
||||
node->bfg[h].total, fee, risk);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (node->bfg[h].total + fee + risk
|
||||
< c->src->bfg[h+1].total + c->src->bfg[h+1].risk) {
|
||||
SUPERVERBOSE("...%s can reach here in hoplen %zu total %"PRIu64,
|
||||
@ -325,6 +340,12 @@ find_route(const tal_t *ctx, struct routing_state *rstate,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (msatoshi >= MAX_MSATOSHI) {
|
||||
status_trace("find_route: can't route huge amount %"PRIu64,
|
||||
msatoshi);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Reset all the information. */
|
||||
clear_bfg(rstate->nodes);
|
||||
|
||||
@ -639,6 +660,16 @@ void handle_channel_update(struct routing_state *rstate, const u8 *update)
|
||||
&short_channel_id),
|
||||
flags);
|
||||
|
||||
if (c->proportional_fee >= MAX_PROPORTIONAL_FEE) {
|
||||
status_trace("Channel %s(%d) massive proportional fee %u:"
|
||||
" disabling.",
|
||||
type_to_string(trc, struct short_channel_id,
|
||||
&short_channel_id),
|
||||
flags,
|
||||
fee_proportional_millionths);
|
||||
c->active = false;
|
||||
}
|
||||
|
||||
u8 *tag = tal_arr(tmpctx, u8, 0);
|
||||
towire_short_channel_id(&tag, &short_channel_id);
|
||||
towire_u16(&tag, flags & 0x1);
|
||||
|
Loading…
Reference in New Issue
Block a user