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); }