From d5246e43bbe4b1059ad9b618837bb32bf9ba3f63 Mon Sep 17 00:00:00 2001 From: Alex Myers Date: Tue, 28 Feb 2023 13:04:00 -0600 Subject: [PATCH] gossipd: flag zombie channels when loading from gossip_store Without inheriting zombie status, gossipd would allow regular channel updates into the store until the pruning cycle hits (and the channel is properly flagged) which is 3.5 days. Applying zombie status when reading channel updates from the store prevents this. Changelog-None --- gossipd/gossip_store.c | 5 ++++- gossipd/routing.c | 33 ++++++++++++++++++++------------- gossipd/routing.h | 3 ++- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/gossipd/gossip_store.c b/gossipd/gossip_store.c index bceb0b7c3..968c138f6 100644 --- a/gossipd/gossip_store.c +++ b/gossipd/gossip_store.c @@ -778,6 +778,7 @@ u32 gossip_store_load(struct routing_state *rstate, struct gossip_store *gs) gs->writable = false; while (pread(gs->fd, &hdr, sizeof(hdr), gs->len) == sizeof(hdr)) { bool spam; + bool zombie; msglen = be16_to_cpu(hdr.len); checksum = be32_to_cpu(hdr.crc); @@ -802,6 +803,7 @@ u32 gossip_store_load(struct routing_state *rstate, struct gossip_store *gs) goto next; } spam = (be16_to_cpu(hdr.flags) & GOSSIP_STORE_RATELIMIT_BIT); + zombie = (be16_to_cpu(hdr.flags) & GOSSIP_STORE_ZOMBIE_BIT); switch (fromwire_peektype(msg)) { case WIRE_GOSSIP_STORE_PRIVATE_CHANNEL: { @@ -872,7 +874,8 @@ u32 gossip_store_load(struct routing_state *rstate, struct gossip_store *gs) case WIRE_CHANNEL_UPDATE: if (!routing_add_channel_update(rstate, take(msg), gs->len, - NULL, false, spam)) { + NULL, false, + spam, zombie)) { bad = "Bad channel_update"; goto badmsg; } diff --git a/gossipd/routing.c b/gossipd/routing.c index b61360b7a..11e0c5cd7 100644 --- a/gossipd/routing.c +++ b/gossipd/routing.c @@ -980,10 +980,10 @@ bool routing_add_channel_announcement(struct routing_state *rstate, /* If we had private updates, they'll immediately create the channel. */ if (private_updates[0]) routing_add_channel_update(rstate, take(private_updates[0]), 0, - peer, false, false); + peer, false, false, false); if (private_updates[1]) routing_add_channel_update(rstate, take(private_updates[1]), 0, - peer, false, false); + peer, false, false, false); /* Now we can finish cleanup of gossip store, so there's no window where * channel (or nodes) vanish. */ @@ -1327,7 +1327,8 @@ bool routing_add_channel_update(struct routing_state *rstate, u32 index, struct peer *peer, bool ignore_timestamp, - bool force_spam_flag) + bool force_spam_flag, + bool force_zombie_flag) { secp256k1_ecdsa_signature signature; struct short_channel_id short_channel_id; @@ -1373,7 +1374,8 @@ bool routing_add_channel_update(struct routing_state *rstate, return false; } sat = uc->sat; - zombie = false; + /* When loading zombies from the store. */ + zombie = force_zombie_flag; } /* Reject update if the `htlc_maximum_msat` is greater @@ -1396,6 +1398,9 @@ bool routing_add_channel_update(struct routing_state *rstate, assert(!chan); chan = new_chan(rstate, &short_channel_id, &uc->id[0], &uc->id[1], sat); + /* Assign zombie flag if loading zombie from store */ + if (force_zombie_flag) + chan->half[direction].zombie = true; } /* Discard older updates */ @@ -1735,7 +1740,8 @@ u8 *handle_channel_update(struct routing_state *rstate, const u8 *update TAKES, return warn; } - routing_add_channel_update(rstate, take(serialized), 0, peer, force, false); + routing_add_channel_update(rstate, take(serialized), 0, peer, force, + false, false); return NULL; } @@ -2009,20 +2015,21 @@ u8 *handle_node_announcement(struct routing_state *rstate, const u8 *node_ann, /* Set zombie flags in gossip_store and tombstone the channel for any * gossip_store consumers. Remove any orphaned node_announcements. */ -static void zombify_channel(struct gossip_store *gs, struct chan *channel) +static void zombify_channel(struct routing_state *rstate, struct chan *channel) { struct half_chan *half; assert(!is_chan_zombie(channel)); - gossip_store_mark_channel_zombie(gs, &channel->bcast); - gossip_store_mark_channel_deleted(gs, &channel->scid); + gossip_store_mark_channel_zombie(rstate->gs, &channel->bcast); + gossip_store_mark_channel_deleted(rstate->gs, &channel->scid); for (int i = 0; i < 2; i++) { half = &channel->half[i]; half->zombie = true; if (half->bcast.index) { - gossip_store_mark_cupdate_zombie(gs, &half->bcast); + gossip_store_mark_cupdate_zombie(rstate->gs, &half->bcast); /* Channel may also have a spam entry */ if (half->bcast.index != half->rgraph.index) - gossip_store_mark_cupdate_zombie(gs, &half->rgraph); + gossip_store_mark_cupdate_zombie(rstate->gs, + &half->rgraph); } } status_debug("Channel %s zombified", @@ -2044,9 +2051,9 @@ static void zombify_channel(struct gossip_store *gs, struct chan *channel) continue; } if (node->rgraph.index != node->bcast.index) - gossip_store_delete(gs, &node->rgraph, + gossip_store_delete(rstate->gs, &node->rgraph, WIRE_NODE_ANNOUNCEMENT); - gossip_store_delete(gs, &node->bcast, + gossip_store_delete(rstate->gs, &node->bcast, WIRE_NODE_ANNOUNCEMENT); node->rgraph.index = node->bcast.index = 0; } @@ -2110,7 +2117,7 @@ void route_prune(struct routing_state *rstate) * stashed away for later use. If all remaining channels for a node are * zombies, the node is zombified too. */ for (size_t i = 0; i < tal_count(pruned); i++) { - zombify_channel(rstate->gs, pruned[i]); + zombify_channel(rstate, pruned[i]); } } diff --git a/gossipd/routing.h b/gossipd/routing.h index f1666c167..d64e763c2 100644 --- a/gossipd/routing.h +++ b/gossipd/routing.h @@ -370,7 +370,8 @@ bool routing_add_channel_update(struct routing_state *rstate, u32 index, struct peer *peer, bool ignore_timestamp, - bool force_spam_flag); + bool force_spam_flag, + bool force_zombie_flag); /** * Add a node_announcement to the network view without checking it *