mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 15:14:23 +01:00
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.
This commit is contained in:
committed by
Christian Decker
parent
56dd18e01e
commit
2556df5f7c
@@ -26,6 +26,7 @@ struct payment *payment_new(tal_t *ctx, struct command *cmd,
|
|||||||
p->getroute->riskfactorppm = 10000000;
|
p->getroute->riskfactorppm = 10000000;
|
||||||
p->abort = false;
|
p->abort = false;
|
||||||
p->route = NULL;
|
p->route = NULL;
|
||||||
|
p->temp_exclusion = NULL;
|
||||||
|
|
||||||
/* Copy over the relevant pieces of information. */
|
/* Copy over the relevant pieces of information. */
|
||||||
if (parent != NULL) {
|
if (parent != NULL) {
|
||||||
@@ -482,6 +483,16 @@ static void payment_getroute_add_excludes(struct payment *p,
|
|||||||
for (size_t i=0; i<tal_count(nodes); i++)
|
for (size_t i=0; i<tal_count(nodes); i++)
|
||||||
json_add_node_id(js, NULL, &nodes[i]);
|
json_add_node_id(js, NULL, &nodes[i]);
|
||||||
|
|
||||||
|
/* And make sure we don't route in a circle via the routehint! */
|
||||||
|
if (p->temp_exclusion) {
|
||||||
|
struct short_channel_id_dir scidd;
|
||||||
|
scidd.scid = *p->temp_exclusion;
|
||||||
|
for (size_t dir = 0; dir < 2; dir++) {
|
||||||
|
scidd.dir = dir;
|
||||||
|
json_add_short_channel_id_dir(js, NULL, &scidd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
json_array_end(js);
|
json_array_end(js);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1776,6 +1787,12 @@ static struct route_info *next_routehint(struct routehints_data *d,
|
|||||||
if (d->routehints == NULL || numhints == 0)
|
if (d->routehints == NULL || numhints == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
/* BOLT #11:
|
||||||
|
*
|
||||||
|
* - if a writer offers more than one of any field type, it:
|
||||||
|
* - MUST specify the most-preferred field first, followed
|
||||||
|
* 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->offset];
|
||||||
if (curr == NULL || !routehint_excluded(p, curr))
|
if (curr == NULL || !routehint_excluded(p, curr))
|
||||||
@@ -1840,8 +1857,13 @@ static void routehint_pre_getroute(struct routehints_data *d, struct payment *p)
|
|||||||
type_to_string(tmpctx, struct short_channel_id,
|
type_to_string(tmpctx, struct short_channel_id,
|
||||||
&d->current_routehint->short_channel_id),
|
&d->current_routehint->short_channel_id),
|
||||||
d->current_routehint->cltv_expiry_delta);
|
d->current_routehint->cltv_expiry_delta);
|
||||||
|
|
||||||
|
/* Exclude the entrypoint to the routehint, so we don't end up
|
||||||
|
* going through the destination to the entrypoint. */
|
||||||
|
p->temp_exclusion = &d->current_routehint[0].short_channel_id;
|
||||||
} else {
|
} else {
|
||||||
plugin_log(p->plugin, LOG_DBG, "Not using a routehint");
|
plugin_log(p->plugin, LOG_DBG, "Not using a routehint");
|
||||||
|
p->temp_exclusion = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -232,6 +232,9 @@ struct payment {
|
|||||||
struct channel_hint *channel_hints;
|
struct channel_hint *channel_hints;
|
||||||
struct node_id *excluded_nodes;
|
struct node_id *excluded_nodes;
|
||||||
|
|
||||||
|
/* Optional temporarily excluded channel (i.e. this routehint) */
|
||||||
|
struct short_channel_id *temp_exclusion;
|
||||||
|
|
||||||
struct payment_result *result;
|
struct payment_result *result;
|
||||||
|
|
||||||
/* Did something happen that will cause all future attempts to fail?
|
/* Did something happen that will cause all future attempts to fail?
|
||||||
|
|||||||
Reference in New Issue
Block a user