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;
char *mods = tal_strdup(tmpctx, "");
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 */
if (tal_count(hints[i]) > max_hops) {
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
* point in keeping it. */
entrynode = gossmap_find_node(map, &hints[i][0].pubkey);
src = gossmap_find_node(map, p->local_id);
if (entrynode == NULL) {
tal_append_fmt(&mods,
"Removed routehint %zu because "
@ -2368,6 +2372,29 @@ static struct route_info **filter_routehints(struct gossmap *map,
i--;
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, ""))

View File

@ -4219,4 +4219,10 @@ def test_unreachable_routehint(node_factory, bitcoind):
l2.connect(l3)
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
)
))