From 14000a22bc9d0fcc87207b54b028f3056499a0f6 Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Mon, 30 Jul 2018 15:31:45 +0200 Subject: [PATCH] routing: Skip channels that don't have sufficient capacity We know the total channel capacity after checking for its existence on-chain, so we can actually make use of that information to discard channels that don't have a sufficient capacity anyway, reducing the number of failed attempts. --- gossipd/routing.c | 18 ++++++++++++------ gossipd/test/run-find_route-specific.c | 23 ++++++++++++++++++----- gossipd/test/run-find_route.c | 2 ++ 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/gossipd/routing.c b/gossipd/routing.c index 935795892..bcbae8ffd 100644 --- a/gossipd/routing.c +++ b/gossipd/routing.c @@ -389,15 +389,21 @@ static void bfg_one_edge(struct node *node, /* FIXME: Bias against smaller channels. */ u64 fee; u64 risk; + u64 requiredcap; if (node->bfg[h].total == INFINITE) continue; fee = connection_fee(c, node->bfg[h].total) * fee_scale; - risk = node->bfg[h].risk + risk_fee(node->bfg[h].total + fee, - c->delay, riskfactor); + requiredcap = node->bfg[h].total + fee; + risk = node->bfg[h].risk + + risk_fee(requiredcap, c->delay, riskfactor); - if (node->bfg[h].total + fee + risk >= MAX_MSATOSHI) { + if (requiredcap > chan->satoshis * 1000) { + /* Skip this edge if the channel has insufficient + * capacity to route the required amount */ + continue; + } else if (requiredcap + risk >= MAX_MSATOSHI) { SUPERVERBOSE("...extreme %"PRIu64 " + fee %"PRIu64 " + risk %"PRIu64" ignored", @@ -407,13 +413,13 @@ static void bfg_one_edge(struct node *node, /* nodes[0] is src for connections[0] */ src = chan->nodes[idx]; - if (node->bfg[h].total + fee + risk - < src->bfg[h+1].total + src->bfg[h+1].risk) { + if (requiredcap + risk < + src->bfg[h + 1].total + src->bfg[h + 1].risk) { SUPERVERBOSE("...%s can reach here in hoplen %zu total %"PRIu64, type_to_string(trc, struct pubkey, &src->id), h, node->bfg[h].total + fee); - src->bfg[h+1].total = node->bfg[h].total + fee; + src->bfg[h+1].total = requiredcap; src->bfg[h+1].risk = risk; src->bfg[h+1].prev = chan; } diff --git a/gossipd/test/run-find_route-specific.c b/gossipd/test/run-find_route-specific.c index 3995c32e5..dea3e4d24 100644 --- a/gossipd/test/run-find_route-specific.c +++ b/gossipd/test/run-find_route-specific.c @@ -110,7 +110,8 @@ static struct half_chan * get_or_make_connection(struct routing_state *rstate, const struct pubkey *from_id, const struct pubkey *to_id, - const char *shortid) + const char *shortid, + const u64 satoshis) { struct short_channel_id scid; struct chan *chan; @@ -123,6 +124,7 @@ get_or_make_connection(struct routing_state *rstate, /* Make sure it's seen as initialized (update non-NULL). */ chan->half[pubkey_idx(from_id, to_id)].channel_update = (void *)chan; + chan->satoshis = satoshis; return &chan->half[pubkey_idx(from_id, to_id)]; } @@ -169,7 +171,8 @@ int main(void) rstate = new_routing_state(tmpctx, &zerohash, &a, 0); /* [{'active': True, 'short_id': '6990:2:1/1', 'fee_per_kw': 10, 'delay': 5, 'flags': 1, 'destination': '0230ad0e74ea03976b28fda587bb75bdd357a1938af4424156a18265167f5e40ae', 'source': '02ea622d5c8d6143f15ed3ce1d501dd0d3d09d3b1c83a44d0034949f8a9ab60f06', 'last_update': 1504064344}, */ - nc = get_or_make_connection(rstate, &c, &b, "6990:2:1"); + + nc = get_or_make_connection(rstate, &c, &b, "6990:2:1", 1000); nc->base_fee = 0; nc->proportional_fee = 10; nc->delay = 5; @@ -177,7 +180,7 @@ int main(void) nc->last_timestamp = 1504064344; /* {'active': True, 'short_id': '6989:2:1/0', 'fee_per_kw': 10, 'delay': 5, 'flags': 0, 'destination': '03c173897878996287a8100469f954dd820fcd8941daed91c327f168f3329be0bf', 'source': '0230ad0e74ea03976b28fda587bb75bdd357a1938af4424156a18265167f5e40ae', 'last_update': 1504064344}, */ - nc = get_or_make_connection(rstate, &b, &a, "6989:2:1"); + nc = get_or_make_connection(rstate, &b, &a, "6989:2:1", 1000); nc->base_fee = 0; nc->proportional_fee = 10; nc->delay = 5; @@ -185,7 +188,7 @@ int main(void) nc->last_timestamp = 1504064344; /* {'active': True, 'short_id': '6990:2:1/0', 'fee_per_kw': 10, 'delay': 5, 'flags': 0, 'destination': '02ea622d5c8d6143f15ed3ce1d501dd0d3d09d3b1c83a44d0034949f8a9ab60f06', 'source': '0230ad0e74ea03976b28fda587bb75bdd357a1938af4424156a18265167f5e40ae', 'last_update': 1504064344}, */ - nc = get_or_make_connection(rstate, &b, &c, "6990:2:1"); + nc = get_or_make_connection(rstate, &b, &c, "6990:2:1", 1000); nc->base_fee = 0; nc->proportional_fee = 10; nc->delay = 5; @@ -193,7 +196,7 @@ int main(void) nc->last_timestamp = 1504064344; /* {'active': True, 'short_id': '6989:2:1/1', 'fee_per_kw': 10, 'delay': 5, 'flags': 1, 'destination': '0230ad0e74ea03976b28fda587bb75bdd357a1938af4424156a18265167f5e40ae', 'source': '03c173897878996287a8100469f954dd820fcd8941daed91c327f168f3329be0bf', 'last_update': 1504064344}]} */ - nc = get_or_make_connection(rstate, &a, &b, "6989:2:1"); + nc = get_or_make_connection(rstate, &a, &b, "6989:2:1", 1000); nc->base_fee = 0; nc->proportional_fee = 10; nc->delay = 5; @@ -206,6 +209,16 @@ int main(void) assert(channel_is_between(route[0], &a, &b)); assert(channel_is_between(route[1], &b, &c)); + + /* 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); + 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); + assert(!route); + tal_free(tmpctx); secp256k1_context_destroy(secp256k1_ctx); return 0; diff --git a/gossipd/test/run-find_route.c b/gossipd/test/run-find_route.c index 8bd1d8070..612b46aaa 100644 --- a/gossipd/test/run-find_route.c +++ b/gossipd/test/run-find_route.c @@ -121,6 +121,8 @@ static void add_connection(struct routing_state *rstate, if (!chan) chan = new_chan(rstate, &scid, from, to); + chan->satoshis = 100000; + c = &chan->half[pubkey_idx(from, to)]; /* Make sure it's seen as initialized (update non-NULL). */ c->channel_update = (void *)c;