From 648af0292b95074bf3ca7eee3e85dfbc546af79d Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Wed, 22 Jul 2020 16:06:39 +0200 Subject: [PATCH] paymod: Randomly select a routehint, or none at random The adaptive MPP test was showing an issue with always using a routehint, even when it wasn't necessary: we would insist on routhing to the entrypoint of the routehint, even through the actual destination. If a channel on that loop would result being over capacity we'd slam below 0, and then increase again by unapplying the route. The solution really is not to insist on routing through a routehint, so we implement random skipping of routehints, and we rotate them if we have multiples. --- plugins/libplugin-pay.c | 15 +++++++++++---- tests/test_pay.py | 8 ++++---- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/plugins/libplugin-pay.c b/plugins/libplugin-pay.c index 4c896d4e1..d2a058f1c 100644 --- a/plugins/libplugin-pay.c +++ b/plugins/libplugin-pay.c @@ -1769,12 +1769,19 @@ static bool routehint_excluded(struct payment *p, static struct route_info *next_routehint(struct routehints_data *d, struct payment *p) { - /* FIXME: Add a pseudorandom offset to rotate between the routehints - * we use, similar to what we'd do by randomizing the routes. */ + /* Implements a random selection of a routehint, or none in 1/numhints + * cases, by starting the iteration of the routehints in a random + * order, and adding a virtual NULL result at the end. */ + size_t numhints = tal_count(d->routehints); + size_t offset = pseudorand(numhints + 1); + for (size_t i=0; iroutehints); i++) { - if (!routehint_excluded(p, d->routehints[i])) { + size_t curr = (offset + i) % (numhints + 1); + if (curr == numhints) + return NULL; + + if (!routehint_excluded(p, d->routehints[curr])) return d->routehints[i]; - } } return NULL; } diff --git a/tests/test_pay.py b/tests/test_pay.py index e41afdfff..e4b7c2df6 100644 --- a/tests/test_pay.py +++ b/tests/test_pay.py @@ -3103,10 +3103,10 @@ def test_mpp_adaptive(node_factory, bitcoind): ```dot digraph { - l1 -> l2; - l2 -> l4; - l1 -> l3; - l3 -> l4; + l1 -> l2 [label="scid=103x1x1, cap=amt-1"]; + l2 -> l4 [label="scid=105x1x1, cap=max"]; + l1 -> l3 [label="scid=107x1x1, cap=max"]; + l3 -> l4 [label="scid=109x1x1, cap=amt-1"]; } """ amt = 10**7 - 1