pay: Recover from unparseable routing failures by random disabling of channels.

Fixes: #868

Not pretty, but workable.
This commit is contained in:
ZmnSCPxj 2018-02-07 12:35:52 +00:00 committed by Rusty Russell
parent 0d0ef2c733
commit d666857aed

View File

@ -307,6 +307,34 @@ remote_routing_failure(const tal_t *ctx,
return routing_failure; return routing_failure;
} }
static void random_mark_channel_unroutable(struct log *log,
struct subd *gossip,
struct short_channel_id *route_channels)
{
const tal_t *tmpctx = tal_tmpctx(gossip);
size_t num_channels = tal_count(route_channels);
size_t i;
const struct short_channel_id *channel;
u8 *msg;
assert(tal_len(route_channels) != 0);
/* Select one channel by random. */
randombytes_buf(&i, sizeof(i));
i = i % num_channels;
channel = &route_channels[i];
log_debug(log,
"Disable randomly %dth channel (%s) along route "
"(guessing due to bad reply)",
(int) i,
type_to_string(tmpctx, struct short_channel_id,
channel));
msg = towire_gossip_mark_channel_unroutable(tmpctx, channel);
subd_send_msg(gossip, msg);
tal_free(tmpctx);
}
static void report_routing_failure(struct log *log, static void report_routing_failure(struct log *log,
struct subd *gossip, struct subd *gossip,
struct routing_failure *fail) struct routing_failure *fail)
@ -374,9 +402,15 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout,
/* Cannot report failure. */ /* Cannot report failure. */
fail = NULL; fail = NULL;
failcode = WIRE_PERMANENT_NODE_FAILURE; failcode = WIRE_PERMANENT_NODE_FAILURE;
/* Not safe to retry, not know what failed. */ /* Select a channel to mark unroutable by random */
/* FIXME: some mitigation for this branch. */ random_mark_channel_unroutable(hout->key.peer->log,
retry_plausible = false; ld->gossip,
payment->route_channels);
/* Can now retry; we selected a channel to mark
* unroutable by random */
retry_plausible = true;
/* Already reported something to gossipd, do not
* report anything else */
report_to_gossipd = false; report_to_gossipd = false;
} else { } else {
failcode = fromwire_peektype(reply->msg); failcode = fromwire_peektype(reply->msg);