gossipd: don't mark channels unroutable.

For transient failures, the pay plugin should simply exclude those
from route considerations.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2019-01-18 01:53:32 +10:30 committed by Christian Decker
parent 018a3f1d58
commit 4eddf57fd9
6 changed files with 4 additions and 102 deletions

View File

@ -126,11 +126,6 @@ gossip_routing_failure,,failcode,u16
gossip_routing_failure,,len,u16 gossip_routing_failure,,len,u16
gossip_routing_failure,,channel_update,len*u8 gossip_routing_failure,,channel_update,len*u8
# master->gossipd temporarily mark a channel unroutable
# (used in case of unparseable onion reply)
gossip_mark_channel_unroutable,3022
gossip_mark_channel_unroutable,,channel,struct short_channel_id
# master -> gossipd: a potential funding outpoint was spent, please forget the eventual channel # master -> gossipd: a potential funding outpoint was spent, please forget the eventual channel
gossip_outpoint_spent,3024 gossip_outpoint_spent,3024
gossip_outpoint_spent,,short_channel_id,struct short_channel_id gossip_outpoint_spent,,short_channel_id,struct short_channel_id

1 #include <common/cryptomsg.h>
126
127
128
129
130
131

View File

@ -2540,24 +2540,6 @@ static struct io_plan *handle_routing_failure(struct io_conn *conn,
return daemon_conn_read_next(conn, daemon->master); return daemon_conn_read_next(conn, daemon->master);
} }
/*~ This allows lightningd to explicitly mark a channel temporarily unroutable.
* This is used when we get an unparsable error, and we don't know who to blame;
* lightningd uses this to marking routes unroutable at random... */
static struct io_plan *
handle_mark_channel_unroutable(struct io_conn *conn,
struct daemon *daemon,
const u8 *msg)
{
struct short_channel_id channel;
if (!fromwire_gossip_mark_channel_unroutable(msg, &channel))
master_badmsg(WIRE_GOSSIP_MARK_CHANNEL_UNROUTABLE, msg);
mark_channel_unroutable(daemon->rstate, &channel);
return daemon_conn_read_next(conn, daemon->master);
}
/*~ This is where lightningd tells us that a channel's funding transaction has /*~ This is where lightningd tells us that a channel's funding transaction has
* been spent. */ * been spent. */
static struct io_plan *handle_outpoint_spent(struct io_conn *conn, static struct io_plan *handle_outpoint_spent(struct io_conn *conn,
@ -2642,9 +2624,6 @@ static struct io_plan *recv_req(struct io_conn *conn,
case WIRE_GOSSIP_ROUTING_FAILURE: case WIRE_GOSSIP_ROUTING_FAILURE:
return handle_routing_failure(conn, daemon, msg); return handle_routing_failure(conn, daemon, msg);
case WIRE_GOSSIP_MARK_CHANNEL_UNROUTABLE:
return handle_mark_channel_unroutable(conn, daemon, msg);
case WIRE_GOSSIP_OUTPOINT_SPENT: case WIRE_GOSSIP_OUTPOINT_SPENT:
return handle_outpoint_spent(conn, daemon, msg); return handle_outpoint_spent(conn, daemon, msg);

View File

@ -265,7 +265,6 @@ static void init_half_chan(struct routing_state *rstate,
struct half_chan *c = &chan->half[channel_idx]; struct half_chan *c = &chan->half[channel_idx];
c->channel_update = NULL; c->channel_update = NULL;
c->unroutable_until = 0;
/* Set the channel direction */ /* Set the channel direction */
c->channel_flags = channel_idx; c->channel_flags = channel_idx;
@ -438,11 +437,10 @@ static void bfg_one_edge(struct node *node,
} }
/* Determine if the given half_chan is routable */ /* Determine if the given half_chan is routable */
static bool hc_is_routable(const struct chan *chan, int idx, time_t now) static bool hc_is_routable(const struct chan *chan, int idx)
{ {
return !chan->local_disabled return !chan->local_disabled
&& is_halfchan_enabled(&chan->half[idx]) && is_halfchan_enabled(&chan->half[idx]);
&& chan->half[idx].unroutable_until < now;
} }
/* riskfactor is already scaled to per-block amount */ /* riskfactor is already scaled to per-block amount */
@ -458,10 +456,6 @@ find_route(const tal_t *ctx, struct routing_state *rstate,
struct node *n, *src, *dst; struct node *n, *src, *dst;
struct node_map_iter it; struct node_map_iter it;
int runs, i, best; int runs, i, best;
/* Call time_now() once at the start, so that our tight loop
* does not keep calling into operating system for the
* current time */
time_t now = time_now().ts.tv_sec;
/* Note: we map backwards, since we know the amount of satoshi we want /* Note: we map backwards, since we know the amount of satoshi we want
* at the end, and need to derive how much we need to send. */ * at the end, and need to derive how much we need to send. */
@ -518,7 +512,7 @@ find_route(const tal_t *ctx, struct routing_state *rstate,
&n->id), &n->id),
i, num_edges); i, num_edges);
if (!hc_is_routable(chan, idx, now)) { if (!hc_is_routable(chan, idx)) {
SUPERVERBOSE("...unroutable (local_disabled = %i, is_halfchan_enabled = %i, unroutable_until = %i", SUPERVERBOSE("...unroutable (local_disabled = %i, is_halfchan_enabled = %i, unroutable_until = %i",
chan->local_disabled, chan->local_disabled,
is_halfchan_enabled(&chan->half[idx]), is_halfchan_enabled(&chan->half[idx]),
@ -1040,9 +1034,6 @@ static void set_connection_values(struct chan *chan,
c->last_timestamp = timestamp; c->last_timestamp = timestamp;
assert((c->channel_flags & ROUTING_FLAGS_DIRECTION) == idx); assert((c->channel_flags & ROUTING_FLAGS_DIRECTION) == idx);
/* If it was temporarily unroutable, re-enable */
c->unroutable_until = 0;
SUPERVERBOSE("Channel %s/%d was updated.", SUPERVERBOSE("Channel %s/%d was updated.",
type_to_string(tmpctx, struct short_channel_id, &chan->scid), type_to_string(tmpctx, struct short_channel_id, &chan->scid),
idx); idx);
@ -1583,17 +1574,12 @@ static void routing_failure_channel_out(const tal_t *disposal_context,
struct chan *chan, struct chan *chan,
time_t now) time_t now)
{ {
struct half_chan *hc = half_chan_from(node, chan);
/* BOLT #4: /* BOLT #4:
* *
* - if the PERM bit is NOT set: * - if the PERM bit is NOT set:
* - SHOULD restore the channels as it receives new `channel_update`s. * - SHOULD restore the channels as it receives new `channel_update`s.
*/ */
if (!(failcode & PERM)) if (failcode & PERM)
/* Prevent it for 20 seconds. */
hc->unroutable_until = now + 20;
else
/* Set it up to be pruned. */ /* Set it up to be pruned. */
tal_steal(disposal_context, chan); tal_steal(disposal_context, chan);
} }
@ -1692,27 +1678,6 @@ void routing_failure(struct routing_state *rstate,
} }
} }
void mark_channel_unroutable(struct routing_state *rstate,
const struct short_channel_id *channel)
{
struct chan *chan;
time_t now = time_now().ts.tv_sec;
const char *scid = type_to_string(tmpctx, struct short_channel_id,
channel);
status_trace("Received mark_channel_unroutable channel %s",
scid);
chan = get_channel(rstate, channel);
if (!chan) {
status_unusual("mark_channel_unroutable: "
"channel %s not in routemap",
scid);
return;
}
chan->half[0].unroutable_until = now + 20;
chan->half[1].unroutable_until = now + 20;
}
void route_prune(struct routing_state *rstate) void route_prune(struct routing_state *rstate)
{ {

View File

@ -39,10 +39,6 @@ struct half_chan {
/* Flags as specified by the `channel_update`s, indicates /* Flags as specified by the `channel_update`s, indicates
* optional fields. */ * optional fields. */
u8 message_flags; u8 message_flags;
/* If greater than current time, this connection should not
* be used for routing. */
time_t unroutable_until;
}; };
struct chan { struct chan {
@ -277,9 +273,6 @@ void routing_failure(struct routing_state *rstate,
const struct short_channel_id *erring_channel, const struct short_channel_id *erring_channel,
enum onion_type failcode, enum onion_type failcode,
const u8 *channel_update); const u8 *channel_update);
/* Disable specific channel from routing. */
void mark_channel_unroutable(struct routing_state *rstate,
const struct short_channel_id *channel);
void route_prune(struct routing_state *rstate); void route_prune(struct routing_state *rstate);

View File

@ -112,7 +112,6 @@ static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds)
case WIRE_GOSSIP_GET_TXOUT_REPLY: case WIRE_GOSSIP_GET_TXOUT_REPLY:
case WIRE_GOSSIP_OUTPOINT_SPENT: case WIRE_GOSSIP_OUTPOINT_SPENT:
case WIRE_GOSSIP_ROUTING_FAILURE: case WIRE_GOSSIP_ROUTING_FAILURE:
case WIRE_GOSSIP_MARK_CHANNEL_UNROUTABLE:
case WIRE_GOSSIP_QUERY_SCIDS: case WIRE_GOSSIP_QUERY_SCIDS:
case WIRE_GOSSIP_QUERY_CHANNEL_RANGE: case WIRE_GOSSIP_QUERY_CHANNEL_RANGE:
case WIRE_GOSSIP_SEND_TIMESTAMP_FILTER: case WIRE_GOSSIP_SEND_TIMESTAMP_FILTER:

View File

@ -394,31 +394,6 @@ 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)
{
size_t num_channels = tal_count(route_channels);
size_t i;
const struct short_channel_id *channel;
u8 *msg;
assert(num_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);
}
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)
@ -535,10 +510,6 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout,
tal_hex(tmpctx, hout->failuremsg)); tal_hex(tmpctx, hout->failuremsg));
/* Cannot report failure. */ /* Cannot report failure. */
fail = NULL; fail = NULL;
/* Select a channel to mark unroutable by random */
random_mark_channel_unroutable(hout->key.channel->log,
ld->gossip,
payment->route_channels);
/* Can now retry; we selected a channel to mark /* Can now retry; we selected a channel to mark
* unroutable by random */ * unroutable by random */
retry_plausible = true; retry_plausible = true;