mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 07:04:22 +01:00
plugins/libplugin-pay.c: Round-robin routehints when splitting.
This improves the success rate of `test_mpp_interference_2`, though still not quite up to the level that we can remove `@flaky` from it.
This commit is contained in:
committed by
Rusty Russell
parent
ba3f38077e
commit
128adf0938
@@ -2021,8 +2021,8 @@ static struct route_info *next_routehint(struct routehints_data *d,
|
|||||||
* - MUST specify the most-preferred field first, followed
|
* - MUST specify the most-preferred field first, followed
|
||||||
* by less-preferred fields, in order.
|
* by less-preferred fields, in order.
|
||||||
*/
|
*/
|
||||||
for (; d->offset <numhints; d->offset++) {
|
for (; d->offset < numhints; d->offset++) {
|
||||||
curr = d->routehints[d->offset];
|
curr = d->routehints[(d->base + d->offset) % numhints];
|
||||||
if (curr == NULL || !routehint_excluded(p, curr))
|
if (curr == NULL || !routehint_excluded(p, curr))
|
||||||
return curr;
|
return curr;
|
||||||
}
|
}
|
||||||
@@ -2269,18 +2269,50 @@ static struct routehints_data *routehint_data_init(struct payment *p)
|
|||||||
d->routehints = pd->routehints;
|
d->routehints = pd->routehints;
|
||||||
pd = payment_mod_routehints_get_data(p->parent);
|
pd = payment_mod_routehints_get_data(p->parent);
|
||||||
if (p->parent->step == PAYMENT_STEP_RETRY) {
|
if (p->parent->step == PAYMENT_STEP_RETRY) {
|
||||||
|
d->base = pd->base;
|
||||||
d->offset = pd->offset;
|
d->offset = pd->offset;
|
||||||
/* If the previous try failed to route, advance
|
/* If the previous try failed to route, advance
|
||||||
* to the next routehint. */
|
* to the next routehint. */
|
||||||
if (!p->parent->route)
|
if (!p->parent->route)
|
||||||
++d->offset;
|
++d->offset;
|
||||||
} else
|
} else {
|
||||||
|
size_t num_routehints = tal_count(d->routehints);
|
||||||
d->offset = 0;
|
d->offset = 0;
|
||||||
|
/* This used to be pseudorand.
|
||||||
|
*
|
||||||
|
* However, it turns out that using the partid for
|
||||||
|
* this payment has some nice properties.
|
||||||
|
* The partid is in general quite random, due to
|
||||||
|
* getting entropy from the network on the timing
|
||||||
|
* of when payments complete/fail, and the routehint
|
||||||
|
* randomization is not a privacy or security feature,
|
||||||
|
* only a reliability one, thus does not need a lot
|
||||||
|
* of entropy.
|
||||||
|
*
|
||||||
|
* But the most important bit is that *splits get
|
||||||
|
* contiguous partids*, e.g. a presplit into 4 will
|
||||||
|
* usually be numbered 2,3,4,5, and an adaptive split
|
||||||
|
* will get two consecutive partid.
|
||||||
|
* Because of the contiguity, using the partid for
|
||||||
|
* the base will cause the split-up payments to
|
||||||
|
* have fairly diverse initial routehints.
|
||||||
|
*
|
||||||
|
* The special-casing for <= 2 and the - 2 is due
|
||||||
|
* to the presplitter skipping over partid 1, we want
|
||||||
|
* the starting splits to have partid 2 start at
|
||||||
|
* base 0.
|
||||||
|
*/
|
||||||
|
if (p->partid <= 2 || num_routehints <= 1)
|
||||||
|
d->base = 0;
|
||||||
|
else
|
||||||
|
d->base = (p->partid - 2) % num_routehints;
|
||||||
|
}
|
||||||
return d;
|
return d;
|
||||||
} else {
|
} else {
|
||||||
/* We defer the actual initialization of the routehints array to
|
/* We defer the actual initialization of the routehints array to
|
||||||
* the step callback when we have the invoice attached. */
|
* the step callback when we have the invoice attached. */
|
||||||
d->routehints = NULL;
|
d->routehints = NULL;
|
||||||
|
d->base = 0;
|
||||||
d->offset = 0;
|
d->offset = 0;
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -306,16 +306,26 @@ struct routehints_data {
|
|||||||
/* What we did about routehints (if anything) */
|
/* What we did about routehints (if anything) */
|
||||||
const char *routehint_modifications;
|
const char *routehint_modifications;
|
||||||
|
|
||||||
/* Any remaining routehints to try. */
|
/* Array of routehints to try. */
|
||||||
struct route_info **routehints;
|
struct route_info **routehints;
|
||||||
|
|
||||||
/* Current routehint, if any. */
|
/* Current routehint, if any. */
|
||||||
struct route_info *current_routehint;
|
struct route_info *current_routehint;
|
||||||
|
|
||||||
/* Position of the current routehint in the routehints
|
/* Position of the current routehint in the routehints
|
||||||
* array. Inherited and incremented on child payments and reset on
|
* array. Inherited on retry (and possibly incremented),
|
||||||
* split. */
|
* reset to 0 on split. */
|
||||||
int offset;
|
int offset;
|
||||||
|
/* Base of the current routehint.
|
||||||
|
* This is randomized to start routehints at a random point
|
||||||
|
* on each split, to reduce the chances of multiple splits
|
||||||
|
* going to the same routehint.
|
||||||
|
* The sum of base + offset is used as the index into the
|
||||||
|
* routehints array (wraps around).
|
||||||
|
* offset is used to determine if we have run out of
|
||||||
|
* routehints, base is used for randomization.
|
||||||
|
*/
|
||||||
|
int base;
|
||||||
|
|
||||||
/* We modify the CLTV in the getroute call, so we need to remember
|
/* We modify the CLTV in the getroute call, so we need to remember
|
||||||
* what the final cltv delta was so we re-apply it correctly. */
|
* what the final cltv delta was so we re-apply it correctly. */
|
||||||
|
|||||||
Reference in New Issue
Block a user