From 3c66d5fa03bc02068fe0efdf32a113520917764a Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 27 Jul 2018 06:51:37 +0930 Subject: [PATCH] gossipd: add flag for locally disabling channel. We used to just manually set ROUTING_FLAGS_DISABLED, but that means we then suppressed the real channel_update because we thought it was a duplicate! So use a local flag: set it for the channel when the peer disconnects, and clear it when channeld sends a local update. Signed-off-by: Rusty Russell --- gossipd/gossip.c | 12 +++++++----- gossipd/routing.c | 9 ++++++--- gossipd/routing.h | 3 +++ lightningd/gossip_control.c | 3 ++- lightningd/gossip_msg.c | 2 ++ lightningd/gossip_msg.h | 1 + 6 files changed, 21 insertions(+), 9 deletions(-) diff --git a/gossipd/gossip.c b/gossipd/gossip.c index 6fbdae949..79927fc57 100644 --- a/gossipd/gossip.c +++ b/gossipd/gossip.c @@ -1188,6 +1188,8 @@ static void handle_local_channel_update(struct peer *peer, const u8 *msg) return; } + /* channeld has reconnected, remove local disable. */ + chan->local_disabled = false; queue_local_update(peer->daemon, local_update); } @@ -1398,6 +1400,7 @@ static void append_half_channel(struct gossip_getchannels_entry **entries, e->destination = chan->nodes[!idx]->id; e->satoshis = chan->satoshis; e->flags = c->flags; + e->local_disabled = chan->local_disabled; e->public = is_chan_public(chan); e->short_channel_id = chan->scid; e->last_update_timestamp = c->last_timestamp; @@ -1823,9 +1826,9 @@ static void gossip_disable_outgoing_halfchan(struct daemon *daemon, * * Disables both directions of a local channel as a result of a close or lost * connection. A disabling `channel_update` will be queued for the outgoing - * direction as well. We can't do that for the incoming direction, so we just - * locally flip the flag, and the other endpoint should take care of publicly - * disabling it with a `channel_update`. + * direction as well, but that will be a little delayed. We can't do that for + * the incoming direction, so we set local_disabled and the other endpoint + * should take care of publicly disabling it with a `channel_update`. * * It is important to disable the incoming edge as well since we might otherwise * return that edge as a `contact_point` as part of an invoice. @@ -1838,8 +1841,7 @@ static void gossip_disable_local_channel(struct daemon *daemon, assert(pubkey_eq(&rstate->local_id, &chan->nodes[0]->id) || pubkey_eq(&rstate->local_id, &chan->nodes[1]->id)); - chan->half[0].flags |= ROUTING_FLAGS_DISABLED; - chan->half[1].flags |= ROUTING_FLAGS_DISABLED; + chan->local_disabled = true; gossip_disable_outgoing_halfchan(daemon, chan); } diff --git a/gossipd/routing.c b/gossipd/routing.c index b7ee92ca7..cc0b61a04 100644 --- a/gossipd/routing.c +++ b/gossipd/routing.c @@ -307,6 +307,7 @@ struct chan *new_chan(struct routing_state *rstate, chan->channel_announce = NULL; chan->channel_announcement_index = 0; chan->satoshis = 0; + chan->local_disabled = false; n = tal_count(n2->chans); tal_resize(&n2->chans, n+1); @@ -420,9 +421,11 @@ static void bfg_one_edge(struct node *node, } /* Determine if the given half_chan is routable */ -static bool hc_is_routable(const struct half_chan *hc, time_t now) +static bool hc_is_routable(const struct chan *chan, int idx, time_t now) { - return is_halfchan_enabled(hc) && hc->unroutable_until < now; + return !chan->local_disabled + && is_halfchan_enabled(&chan->half[idx]) + && chan->half[idx].unroutable_until < now; } /* riskfactor is already scaled to per-block amount */ @@ -491,7 +494,7 @@ find_route(const tal_t *ctx, struct routing_state *rstate, &n->id), i, num_edges); - if (!hc_is_routable(&chan->half[idx], now)) { + if (!hc_is_routable(chan, idx, now)) { SUPERVERBOSE("...unroutable"); continue; } diff --git a/gossipd/routing.h b/gossipd/routing.h index 4f10d2732..10df1a023 100644 --- a/gossipd/routing.h +++ b/gossipd/routing.h @@ -55,6 +55,9 @@ struct chan { /* Index in broadcast map, if public (otherwise 0) */ u64 channel_announcement_index; + /* Disabled locally (due to peer disconnect) */ + bool local_disabled; + u64 satoshis; }; diff --git a/lightningd/gossip_control.c b/lightningd/gossip_control.c index e63bf09a7..62919465a 100644 --- a/lightningd/gossip_control.c +++ b/lightningd/gossip_control.c @@ -359,7 +359,8 @@ static void json_listchannels_reply(struct subd *gossip UNUSED, const u8 *reply, json_add_u64(response, "satoshis", entries[i].satoshis); json_add_num(response, "flags", entries[i].flags); json_add_bool(response, "active", - !(entries[i].flags & ROUTING_FLAGS_DISABLED)); + !(entries[i].flags & ROUTING_FLAGS_DISABLED) + && !entries[i].local_disabled); json_add_num(response, "last_update", entries[i].last_update_timestamp); json_add_num(response, "base_fee_millisatoshi", diff --git a/lightningd/gossip_msg.c b/lightningd/gossip_msg.c index f29625b3e..3fc3f4e02 100644 --- a/lightningd/gossip_msg.c +++ b/lightningd/gossip_msg.c @@ -85,6 +85,7 @@ void fromwire_gossip_getchannels_entry(const u8 **pptr, size_t *max, entry->satoshis = fromwire_u64(pptr, max); entry->flags = fromwire_u16(pptr, max); entry->public = fromwire_bool(pptr, max); + entry->local_disabled = fromwire_bool(pptr, max); entry->last_update_timestamp = fromwire_u32(pptr, max); entry->base_fee_msat = fromwire_u32(pptr, max); entry->fee_per_millionth = fromwire_u32(pptr, max); @@ -100,6 +101,7 @@ void towire_gossip_getchannels_entry(u8 **pptr, towire_u64(pptr, entry->satoshis); towire_u16(pptr, entry->flags); towire_bool(pptr, entry->public); + towire_bool(pptr, entry->local_disabled); towire_u32(pptr, entry->last_update_timestamp); towire_u32(pptr, entry->base_fee_msat); towire_u32(pptr, entry->fee_per_millionth); diff --git a/lightningd/gossip_msg.h b/lightningd/gossip_msg.h index c255faaaa..b6c61ca04 100644 --- a/lightningd/gossip_msg.h +++ b/lightningd/gossip_msg.h @@ -24,6 +24,7 @@ struct gossip_getchannels_entry { struct short_channel_id short_channel_id; u16 flags; bool public; + bool local_disabled; u32 last_update_timestamp; u32 delay; u32 base_fee_msat;