diff --git a/common/gossmap.c b/common/gossmap.c index d0bb948fa..45ea204b2 100644 --- a/common/gossmap.c +++ b/common/gossmap.c @@ -641,8 +641,47 @@ static void node_announcement(struct gossmap *map, u64 nann_off) n->nann_off = nann_off; } +static bool report_dying_cb(struct gossmap *map, + u64 dying_off, + u16 msglen, + void (*dyingcb)(struct short_channel_id scid, + u32 blockheight, + u64 offset, + void *cb_arg), + void *cb_arg) +{ + struct short_channel_id scid; + u32 blockheight; + u8 *msg; + + msg = tal_arr(NULL, u8, msglen); + map_copy(map, dying_off, msg, msglen); + + if (!fromwire_gossip_store_chan_dying(msg, &scid, &blockheight)) { + map->logcb(map->cbarg, + LOG_BROKEN, + "Invalid chan_dying message @%"PRIu64 + "/%"PRIu64": %s", + dying_off, map->map_size, msglen, + tal_hex(tmpctx, msg)); + tal_free(msg); + return false; + } + tal_free(msg); + + dyingcb(scid, blockheight, dying_off, cb_arg); + return true; +} + /* Mutual recursion */ -static bool map_catchup(struct gossmap *map, bool must_be_clean, bool *changed); +static bool map_catchup(struct gossmap *map, + void (*dyingcb)(struct short_channel_id scid, + u32 blockheight, + u64 offset, + void *cb_arg), + void *cb_arg, + bool must_be_clean, + bool *changed); static void init_map_structs(struct gossmap *map) { @@ -724,7 +763,7 @@ static bool reopen_store(struct gossmap *map, u64 ended_off) map->generation++; /* Now do reload. */ - map_catchup(map, false, &changed); + map_catchup(map, NULL, NULL, false, &changed); return changed; } @@ -744,7 +783,14 @@ static bool csum_matches(const struct gossmap *map, } /* Returns false only if must_be_clean is true. */ -static bool map_catchup(struct gossmap *map, bool must_be_clean, bool *changed) +static bool map_catchup(struct gossmap *map, + void (*dyingcb)(struct short_channel_id scid, + u32 blockheight, + u64 offset, + void *cb_arg), + void *cb_arg, + bool must_be_clean, + bool *changed) { size_t reclen, num_bad_cupdates = 0; @@ -830,6 +876,8 @@ static bool map_catchup(struct gossmap *map, bool must_be_clean, bool *changed) /* We absorbed this in add_channel; ignore */ continue; } else if (type == WIRE_GOSSIP_STORE_CHAN_DYING) { + if (dyingcb && !report_dying_cb(map, off, msglen, dyingcb, cb_arg)) + return false; /* We don't really care until it's deleted */ continue; } else if (type == WIRE_GOSSIP_STORE_UUID) { @@ -856,7 +904,13 @@ static bool map_catchup(struct gossmap *map, bool must_be_clean, bool *changed) return true; } -static bool load_gossip_store(struct gossmap *map, bool must_be_clean) +static bool load_gossip_store(struct gossmap *map, + void (*dyingcb)(struct short_channel_id scid, + u32 blockheight, + u64 offset, + void *cb_arg), + void *cb_arg, + bool must_be_clean) { bool updated; @@ -880,7 +934,7 @@ static bool load_gossip_store(struct gossmap *map, bool must_be_clean) init_map_structs(map); map->map_end = 1; - return map_catchup(map, must_be_clean, &updated); + return map_catchup(map, dyingcb, cb_arg, must_be_clean, &updated); } static void destroy_map(struct gossmap *map) @@ -1292,7 +1346,7 @@ bool gossmap_refresh(struct gossmap *map) } } - map_catchup(map, false, &changed); + map_catchup(map, NULL, NULL, false, &changed); return changed; } @@ -1319,7 +1373,11 @@ struct gossmap *gossmap_load_(const tal_t *ctx, enum log_level level, const char *fmt, ...), - void *cbarg) + void (*dyingcb)(struct short_channel_id scid, + u32 blockheight, + u64 offset, + void *cb_arg), + void *cb_arg) { map = tal(ctx, struct gossmap); map->generation = 0; @@ -1331,15 +1389,15 @@ struct gossmap *gossmap_load_(const tal_t *ctx, map->logcb = logcb; else map->logcb = log_stderr; - map->cbarg = cbarg; + map->cbarg = cb_arg; tal_add_destructor(map, destroy_map); - if (!load_gossip_store(map, expected_len != 0)) + if (!load_gossip_store(map, dyingcb, cb_arg, expected_len != 0)) return tal_free(map); if (expected_len != 0 && (map->map_size != map->map_end || map->map_size != expected_len)) { - logcb(cbarg, LOG_BROKEN, + logcb(cb_arg, LOG_BROKEN, "gossip_store only processed %"PRIu64 " bytes of %"PRIu64" (expected %"PRIu64")", map->map_end, map->map_size, expected_len); diff --git a/common/gossmap.h b/common/gossmap.h index 1b60a1fdc..0c1a04257 100644 --- a/common/gossmap.h +++ b/common/gossmap.h @@ -46,17 +46,21 @@ struct gossmap_chan { enum log_level, \ const char *fmt, \ ...), \ - (cbarg)) + NULL, (cbarg)) /* If we're the author of the gossmap, it should have no redundant records, corruption, etc. * So this fails if that's not the case. */ -#define gossmap_load_initial(ctx, filename, expected_len, logcb, cbarg) \ +#define gossmap_load_initial(ctx, filename, expected_len, logcb, dyingcb, cb_arg) \ gossmap_load_((ctx), (filename), (expected_len), \ - typesafe_cb_postargs(void, void *, (logcb), (cbarg), \ + typesafe_cb_postargs(void, void *, (logcb), (cb_arg), \ enum log_level, \ const char *fmt, \ ...), \ - (cbarg)) + typesafe_cb_preargs(void, void *, (dyingcb), (cb_arg), \ + struct short_channel_id, \ + u32, \ + u64), \ + (cb_arg)) struct gossmap *gossmap_load_(const tal_t *ctx, const char *filename, @@ -65,6 +69,10 @@ struct gossmap *gossmap_load_(const tal_t *ctx, enum log_level level, const char *fmt, ...), + void (*dyingcb)(struct short_channel_id scid, + u32 blockheight, + u64 offset, + void *cb_arg), void *cb_arg); /* Disable mmap. Noop if already disabled. */ @@ -305,4 +313,5 @@ u64 gossmap_lengths(const struct gossmap *map, u64 *total); /* Debugging: connectd wants to enumerate fds */ int gossmap_fd(const struct gossmap *map); + #endif /* LIGHTNING_COMMON_GOSSMAP_H */ diff --git a/common/test/run-gossmap_canned.c b/common/test/run-gossmap_canned.c index fd5af5e00..8ae7210dc 100644 --- a/common/test/run-gossmap_canned.c +++ b/common/test/run-gossmap_canned.c @@ -19,6 +19,9 @@ bigsize_t fromwire_bigsize(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct channel_id *channel_id UNNEEDED) { fprintf(stderr, "fromwire_channel_id called!\n"); abort(); } +/* Generated stub for fromwire_gossip_store_chan_dying */ +bool fromwire_gossip_store_chan_dying(const void *p UNNEEDED, struct short_channel_id *scid UNNEEDED, u32 *blockheight UNNEEDED) +{ fprintf(stderr, "fromwire_gossip_store_chan_dying called!\n"); abort(); } /* Generated stub for sciddir_or_pubkey_from_node_id */ bool sciddir_or_pubkey_from_node_id(struct sciddir_or_pubkey *sciddpk UNNEEDED, const struct node_id *node_id UNNEEDED) diff --git a/common/test/run-gossmap_local.c b/common/test/run-gossmap_local.c index b425710ac..0575bcae1 100644 --- a/common/test/run-gossmap_local.c +++ b/common/test/run-gossmap_local.c @@ -19,6 +19,9 @@ bigsize_t fromwire_bigsize(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct channel_id *channel_id UNNEEDED) { fprintf(stderr, "fromwire_channel_id called!\n"); abort(); } +/* Generated stub for fromwire_gossip_store_chan_dying */ +bool fromwire_gossip_store_chan_dying(const void *p UNNEEDED, struct short_channel_id *scid UNNEEDED, u32 *blockheight UNNEEDED) +{ fprintf(stderr, "fromwire_gossip_store_chan_dying called!\n"); abort(); } /* Generated stub for sciddir_or_pubkey_from_node_id */ bool sciddir_or_pubkey_from_node_id(struct sciddir_or_pubkey *sciddpk UNNEEDED, const struct node_id *node_id UNNEEDED) diff --git a/connectd/test/run-crc32_of_update.c b/connectd/test/run-crc32_of_update.c index 85521395f..62c3c5fef 100644 --- a/connectd/test/run-crc32_of_update.c +++ b/connectd/test/run-crc32_of_update.c @@ -10,12 +10,16 @@ int unused_main(int argc, char *argv[]); #include #include #include +#include #include /* AUTOGENERATED MOCKS START */ /* Generated stub for fromwire_connectd_dev_set_max_scids_encode_size */ bool fromwire_connectd_dev_set_max_scids_encode_size(const void *p UNNEEDED, u32 *max UNNEEDED) { fprintf(stderr, "fromwire_connectd_dev_set_max_scids_encode_size called!\n"); abort(); } +/* Generated stub for fromwire_gossip_store_chan_dying */ +bool fromwire_gossip_store_chan_dying(const void *p UNNEEDED, struct short_channel_id *scid UNNEEDED, u32 *blockheight UNNEEDED) +{ fprintf(stderr, "fromwire_gossip_store_chan_dying called!\n"); abort(); } /* Generated stub for get_gossmap */ struct gossmap *get_gossmap(struct daemon *daemon UNNEEDED) { fprintf(stderr, "get_gossmap called!\n"); abort(); } diff --git a/gossipd/gossmap_manage.c b/gossipd/gossmap_manage.c index 4ae675d8d..cc4c6264d 100644 --- a/gossipd/gossmap_manage.c +++ b/gossipd/gossmap_manage.c @@ -464,7 +464,9 @@ static bool setup_gossmap(struct gossmap_manage *gm, /* This actually loads it into memory, with strict checks. */ gm->raw_gossmap = gossmap_load_initial(gm, GOSSIP_STORE_FILENAME, expected_len, - gossmap_logcb, daemon); + gossmap_logcb, + NULL, + daemon); if (!gm->raw_gossmap) { gm->gs = tal_free(gm->gs); return false; diff --git a/gossipd/test/run-next_block_range.c b/gossipd/test/run-next_block_range.c index 60b9530a7..f4dae400a 100644 --- a/gossipd/test/run-next_block_range.c +++ b/gossipd/test/run-next_block_range.c @@ -9,6 +9,7 @@ #include #include #include +#include #include /* AUTOGENERATED MOCKS START */ @@ -19,6 +20,9 @@ struct peer *find_peer(struct daemon *daemon UNNEEDED, const struct node_id *id struct peer *first_random_peer(struct daemon *daemon UNNEEDED, struct peer_node_id_map_iter *it UNNEEDED) { fprintf(stderr, "first_random_peer called!\n"); abort(); } +/* Generated stub for fromwire_gossip_store_chan_dying */ +bool fromwire_gossip_store_chan_dying(const void *p UNNEEDED, struct short_channel_id *scid UNNEEDED, u32 *blockheight UNNEEDED) +{ fprintf(stderr, "fromwire_gossip_store_chan_dying called!\n"); abort(); } /* Generated stub for gossmap_manage_get_gossmap */ struct gossmap *gossmap_manage_get_gossmap(struct gossmap_manage *gm UNNEEDED) { fprintf(stderr, "gossmap_manage_get_gossmap called!\n"); abort(); }