From e215530759f2bede39b1bfdc3db9404c839dc91c Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 14 Feb 2024 16:47:56 +1030 Subject: [PATCH] gossipd: handle case where block closes multiple channels requiring node_announcement moves more than once. If we delete it the first time a channel before it is closed, we will crash when we try to move it again: ``` $ lightning_gossipd: gossip_store: get delete entry offset 47411992/51608943 (version v23.11-378-gac2a386-modded) 0x1002544b send_backtrace common/daemon.c:33 0x1003415f status_failed common/status.c:221 0x10016ef3 gossip_store_get_with_hdr gossipd/gossip_store.c:466 0x10016faf check_msg_type gossipd/gossip_store.c:491 0x1001722b gossip_store_set_flag gossipd/gossip_store.c:509 0x1001752b gossip_store_del gossipd/gossip_store.c:561 0x10017f5b remove_channel gossipd/gossmap_manage.c:299 0x100181cf kill_spent_channel gossipd/gossmap_manage.c:1144 0x1001a7df gossmap_manage_new_block gossipd/gossmap_manage.c:1183 0x10014673 new_blockheight gossipd/gossipd.c:483 0x10014d73 recv_req gossipd/gossipd.c:594 ``` Reported-by: @microsatosi on Discord Signed-off-by: Rusty Russell --- gossipd/gossmap_manage.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/gossipd/gossmap_manage.c b/gossipd/gossmap_manage.c index 20eb9ab47d29..5235e5325b44 100644 --- a/gossipd/gossmap_manage.c +++ b/gossipd/gossmap_manage.c @@ -1150,7 +1150,6 @@ static void kill_spent_channel(struct gossmap_manage *gm, void gossmap_manage_new_block(struct gossmap_manage *gm, u32 new_blockheight) { u64 idx; - struct gossmap *gossmap = gossmap_manage_get_gossmap(gm); for (struct pending_cannounce *pca = uintmap_first(&gm->early_ann_map.map, &idx); pca != NULL; @@ -1180,9 +1179,14 @@ void gossmap_manage_new_block(struct gossmap_manage *gm, u32 new_blockheight) } for (size_t i = 0; i < tal_count(gm->dying_channels); i++) { + struct gossmap *gossmap; + if (gm->dying_channels[i].deadline > new_blockheight) continue; + /* Refresh gossmap each time in case we move things in the loop: + * in particular, we might move a node_announcement twice! */ + gossmap = gossmap_manage_get_gossmap(gm); kill_spent_channel(gm, gossmap, gm->dying_channels[i].scid); gossip_store_del(gm->daemon->gs, gm->dying_channels[i].gossmap_offset,