Skip to content

Commit 2556df5

Browse files
rustyrussellcdecker
authored andcommitted
plugins/pay: Exclude the entrypoint to a routehint to avoid cycles
This uses @cdecker's idea of excluding the routehinted channel from the route, and also consumes the route hints as it goes so that it makes progress. I don't know if this is correct, but it reliably passes tests/test_pay.py::test_tlv_or_legacy now.
1 parent 56dd18e commit 2556df5

File tree

2 files changed

+25
-0
lines changed

2 files changed

+25
-0
lines changed

plugins/libplugin-pay.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ struct payment *payment_new(tal_t *ctx, struct command *cmd,
2626
p->getroute->riskfactorppm = 10000000;
2727
p->abort = false;
2828
p->route = NULL;
29+
p->temp_exclusion = NULL;
2930

3031
/* Copy over the relevant pieces of information. */
3132
if (parent != NULL) {
@@ -482,6 +483,16 @@ static void payment_getroute_add_excludes(struct payment *p,
482483
for (size_t i=0; i<tal_count(nodes); i++)
483484
json_add_node_id(js, NULL, &nodes[i]);
484485

486+
/* And make sure we don't route in a circle via the routehint! */
487+
if (p->temp_exclusion) {
488+
struct short_channel_id_dir scidd;
489+
scidd.scid = *p->temp_exclusion;
490+
for (size_t dir = 0; dir < 2; dir++) {
491+
scidd.dir = dir;
492+
json_add_short_channel_id_dir(js, NULL, &scidd);
493+
}
494+
}
495+
485496
json_array_end(js);
486497
}
487498

@@ -1776,6 +1787,12 @@ static struct route_info *next_routehint(struct routehints_data *d,
17761787
if (d->routehints == NULL || numhints == 0)
17771788
return NULL;
17781789

1790+
/* BOLT #11:
1791+
*
1792+
* - if a writer offers more than one of any field type, it:
1793+
* - MUST specify the most-preferred field first, followed
1794+
* by less-preferred fields, in order.
1795+
*/
17791796
for (; d->offset <numhints; d->offset++) {
17801797
curr = d->routehints[d->offset];
17811798
if (curr == NULL || !routehint_excluded(p, curr))
@@ -1840,8 +1857,13 @@ static void routehint_pre_getroute(struct routehints_data *d, struct payment *p)
18401857
type_to_string(tmpctx, struct short_channel_id,
18411858
&d->current_routehint->short_channel_id),
18421859
d->current_routehint->cltv_expiry_delta);
1860+
1861+
/* Exclude the entrypoint to the routehint, so we don't end up
1862+
* going through the destination to the entrypoint. */
1863+
p->temp_exclusion = &d->current_routehint[0].short_channel_id;
18431864
} else {
18441865
plugin_log(p->plugin, LOG_DBG, "Not using a routehint");
1866+
p->temp_exclusion = NULL;
18451867
}
18461868
}
18471869

plugins/libplugin-pay.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,9 @@ struct payment {
232232
struct channel_hint *channel_hints;
233233
struct node_id *excluded_nodes;
234234

235+
/* Optional temporarily excluded channel (i.e. this routehint) */
236+
struct short_channel_id *temp_exclusion;
237+
235238
struct payment_result *result;
236239

237240
/* Did something happen that will cause all future attempts to fail?

0 commit comments

Comments
 (0)