pay: Remove routehints with unreachable entrypoints

Changelog-Added: pay: `pay` will now remove routehints that are unusable due to the entrypoint being unknown or unreachable.
This commit is contained in:
Christian Decker
2021-02-25 16:48:04 +01:00
committed by Rusty Russell
parent 1e1d7b387c
commit cb21a5384b
2 changed files with 35 additions and 2 deletions

View File

@@ -2322,7 +2322,9 @@ static struct route_info **filter_routehints(struct gossmap *map,
const size_t max_hops = ROUTING_MAX_HOPS / 2; const size_t max_hops = ROUTING_MAX_HOPS / 2;
char *mods = tal_strdup(tmpctx, ""); char *mods = tal_strdup(tmpctx, "");
for (size_t i = 0; i < tal_count(hints); i++) { for (size_t i = 0; i < tal_count(hints); i++) {
struct gossmap_node *entrynode; struct gossmap_node *entrynode, *src;
u32 distance;
/* Trim any routehint > 10 hops */ /* Trim any routehint > 10 hops */
if (tal_count(hints[i]) > max_hops) { if (tal_count(hints[i]) > max_hops) {
tal_append_fmt(&mods, tal_append_fmt(&mods,
@@ -2351,6 +2353,8 @@ static struct route_info **filter_routehints(struct gossmap *map,
/* If routehint entrypoint is unreachable there's no /* If routehint entrypoint is unreachable there's no
* point in keeping it. */ * point in keeping it. */
entrynode = gossmap_find_node(map, &hints[i][0].pubkey); entrynode = gossmap_find_node(map, &hints[i][0].pubkey);
src = gossmap_find_node(map, p->local_id);
if (entrynode == NULL) { if (entrynode == NULL) {
tal_append_fmt(&mods, tal_append_fmt(&mods,
"Removed routehint %zu because " "Removed routehint %zu because "
@@ -2368,6 +2372,29 @@ static struct route_info **filter_routehints(struct gossmap *map,
i--; i--;
continue; continue;
} }
distance = dijkstra_distance(
dijkstra(tmpctx, map, entrynode, AMOUNT_MSAT(1), 1,
payment_route_can_carry_even_disabled,
route_score_cheaper, p),
gossmap_node_idx(map, src));
if (distance == UINT_MAX) {
tal_append_fmt(&mods,
"Removed routehint %zu because "
"entrypoint %s is unreachable. ",
i,
type_to_string(tmpctx, struct node_id,
&hints[i][0].pubkey));
plugin_log(p->plugin, LOG_DBG,
"Removed routehint %zu because "
"entrypoint %s is unreachable. ",
i,
type_to_string(tmpctx, struct node_id,
&hints[i][0].pubkey));
tal_arr_remove(&hints, i);
i--;
}
} }
if (!streq(mods, "")) if (!streq(mods, ""))

View File

@@ -4219,4 +4219,10 @@ def test_unreachable_routehint(node_factory, bitcoind):
l2.connect(l3) l2.connect(l3)
wait_for(lambda: len(l1.rpc.listnodes(entrypoint)['nodes']) == 1) wait_for(lambda: len(l1.rpc.listnodes(entrypoint)['nodes']) == 1)
# TODO(cdecker) investigate why dijkstra_distance tells us the entrypoint is reachable... with pytest.raises(RpcError):
l1.rpc.pay(invoice)
assert(l1.daemon.is_in_log(
r"Removed routehint 0 because entrypoint {entrypoint} is unreachable.".format(
entrypoint=entrypoint
)
))