Browse Source

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>
sanitizers
Rusty Russell 6 years ago
committed by Christian Decker
parent
commit
4eddf57fd9
  1. 5
      gossipd/gossip_wire.csv
  2. 21
      gossipd/gossipd.c
  3. 43
      gossipd/routing.c
  4. 7
      gossipd/routing.h
  5. 1
      lightningd/gossip_control.c
  6. 29
      lightningd/pay.c

5
gossipd/gossip_wire.csv

@ -126,11 +126,6 @@ gossip_routing_failure,,failcode,u16
gossip_routing_failure,,len,u16
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
gossip_outpoint_spent,3024
gossip_outpoint_spent,,short_channel_id,struct short_channel_id

Can't render this file because it has a wrong number of fields in line 6.

21
gossipd/gossipd.c

@ -2540,24 +2540,6 @@ static struct io_plan *handle_routing_failure(struct io_conn *conn,
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
* been spent. */
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:
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:
return handle_outpoint_spent(conn, daemon, msg);

43
gossipd/routing.c

@ -265,7 +265,6 @@ static void init_half_chan(struct routing_state *rstate,
struct half_chan *c = &chan->half[channel_idx];
c->channel_update = NULL;
c->unroutable_until = 0;
/* Set the channel direction */
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 */
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
&& is_halfchan_enabled(&chan->half[idx])
&& chan->half[idx].unroutable_until < now;
&& is_halfchan_enabled(&chan->half[idx]);
}
/* 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_map_iter it;
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
* 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),
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",
chan->local_disabled,
is_halfchan_enabled(&chan->half[idx]),
@ -1040,9 +1034,6 @@ static void set_connection_values(struct chan *chan,
c->last_timestamp = timestamp;
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.",
type_to_string(tmpctx, struct short_channel_id, &chan->scid),
idx);
@ -1583,17 +1574,12 @@ static void routing_failure_channel_out(const tal_t *disposal_context,
struct chan *chan,
time_t now)
{
struct half_chan *hc = half_chan_from(node, chan);
/* BOLT #4:
*
* - if the PERM bit is NOT set:
* - SHOULD restore the channels as it receives new `channel_update`s.
*/
if (!(failcode & PERM))
/* Prevent it for 20 seconds. */
hc->unroutable_until = now + 20;
else
if (failcode & PERM)
/* Set it up to be pruned. */
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)
{

7
gossipd/routing.h

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

1
lightningd/gossip_control.c

@ -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_OUTPOINT_SPENT:
case WIRE_GOSSIP_ROUTING_FAILURE:
case WIRE_GOSSIP_MARK_CHANNEL_UNROUTABLE:
case WIRE_GOSSIP_QUERY_SCIDS:
case WIRE_GOSSIP_QUERY_CHANNEL_RANGE:
case WIRE_GOSSIP_SEND_TIMESTAMP_FILTER:

29
lightningd/pay.c

@ -394,31 +394,6 @@ remote_routing_failure(const tal_t *ctx,
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,
struct subd *gossip,
struct routing_failure *fail)
@ -535,10 +510,6 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout,
tal_hex(tmpctx, hout->failuremsg));
/* Cannot report failure. */
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
* unroutable by random */
retry_plausible = true;

Loading…
Cancel
Save