From 744116e5017fbde3bfc99d968c508a6122fcbfa7 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 23 May 2024 10:55:59 +0930 Subject: [PATCH] gossipd: make extra-sure we don't put in redundant channel_announcement messages. We only write these in two places: one where we get a message from lightningd about our own channel, and one where we get a reply from lightningd about a txout check. The former case we explicitly check that we don't already have it in gossmap, so add checks to the latter case, and give verbose detail if it's found. Signed-off-by: Rusty Russell --- common/gossmap.c | 6 ++++++ common/gossmap.h | 3 +++ gossipd/gossip_store.c | 5 +++++ gossipd/gossip_store.h | 4 ++++ gossipd/gossmap_manage.c | 31 ++++++++++++++++++++++++++++++- 5 files changed, 48 insertions(+), 1 deletion(-) diff --git a/common/gossmap.c b/common/gossmap.c index 4eef0426d..dd834b639 100644 --- a/common/gossmap.c +++ b/common/gossmap.c @@ -1444,3 +1444,9 @@ u8 *gossmap_node_get_features(const tal_t *ctx, map_copy(map, n->nann_off + feature_len_off + 2, ret, feature_len); return ret; } + +size_t gossmap_lengths(const struct gossmap *map, size_t *total) +{ + *total = map->map_size; + return map->map_end; +} diff --git a/common/gossmap.h b/common/gossmap.h index c2a86b321..b42045337 100644 --- a/common/gossmap.h +++ b/common/gossmap.h @@ -257,4 +257,7 @@ size_t gossmap_num_chans(const struct gossmap *map); struct gossmap_chan *gossmap_first_chan(const struct gossmap *map); struct gossmap_chan *gossmap_next_chan(const struct gossmap *map, struct gossmap_chan *prev); + +/* For debugging: returns length read, and total known length of file */ +size_t gossmap_lengths(const struct gossmap *map, size_t *total); #endif /* LIGHTNING_COMMON_GOSSMAP_H */ diff --git a/gossipd/gossip_store.c b/gossipd/gossip_store.c index b7362cbef..14c41af7d 100644 --- a/gossipd/gossip_store.c +++ b/gossipd/gossip_store.c @@ -600,3 +600,8 @@ void gossip_store_set_timestamp(struct gossip_store *gs, u64 offset, u32 timesta "Failed writing header to re-timestamp @%"PRIu64": %s", offset, strerror(errno)); } + +u64 gossip_store_len_written(const struct gossip_store *gs) +{ + return gs->len; +} diff --git a/gossipd/gossip_store.h b/gossipd/gossip_store.h index 8e38dc6ab..ba85e78a8 100644 --- a/gossipd/gossip_store.h +++ b/gossipd/gossip_store.h @@ -113,4 +113,8 @@ u32 gossip_store_get_timestamp(struct gossip_store *gs, u64 offset); */ void gossip_store_set_timestamp(struct gossip_store *gs, u64 offset, u32 timestamp); +/** + * For debugging. + */ +u64 gossip_store_len_written(const struct gossip_store *gs); #endif /* LIGHTNING_GOSSIPD_GOSSIP_STORE_H */ diff --git a/gossipd/gossmap_manage.c b/gossipd/gossmap_manage.c index 884acfb10..4ded33768 100644 --- a/gossipd/gossmap_manage.c +++ b/gossipd/gossmap_manage.c @@ -652,6 +652,34 @@ void gossmap_manage_handle_get_txout_reply(struct gossmap_manage *gm, const u8 * goto bad; } + /* We have reports of doubled-up channel_announcements, hence this check! */ + struct gossmap_chan *chan; + size_t before_length_processed, before_total_length; + + before_length_processed = gossmap_lengths(gm->raw_gossmap, &before_total_length); + chan = gossmap_find_chan(gm->raw_gossmap, &scid); + if (chan) { + status_broken("Redundant channel_announce for scid %s at off %u (gossmap %zu/%zu, store %"PRIu64")", + fmt_short_channel_id(tmpctx, scid), chan->cann_off, + before_length_processed, before_total_length, + gossip_store_len_written(gm->daemon->gs)); + goto out; + } else { + size_t after_length_processed, after_total_length; + /* Good, now try refreshing in case it somehow slipped in! */ + gossmap = gossmap_manage_get_gossmap(gm); + after_length_processed = gossmap_lengths(gm->raw_gossmap, &after_total_length); + chan = gossmap_find_chan(gm->raw_gossmap, &scid); + if (chan) { + status_broken("Redundant channel_announce *AFTER REFRESH* for scid %s at off %u (gossmap was %zu/%zu, now %zu/%zu, store %"PRIu64")", + fmt_short_channel_id(tmpctx, scid), chan->cann_off, + before_length_processed, before_total_length, + after_length_processed, after_total_length, + gossip_store_len_written(gm->daemon->gs)); + goto out; + } + } + /* Set with timestamp 0 (we will update once we have a channel_update) */ gossip_store_add(gm->daemon->gs, pca->channel_announcement, 0); gossip_store_add(gm->daemon->gs, @@ -672,8 +700,9 @@ void gossmap_manage_handle_get_txout_reply(struct gossmap_manage *gm, const u8 * return; bad: - tal_free(pca); txout_failures_add(gm->txf, scid); +out: + tal_free(pca); /* If we looking specifically for this, we no longer are. */ remove_unknown_scid(gm->daemon->seeker, &scid, false); }