From d16797ce587c3407aec6221e5bdeba8e50ea7713 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 19 Jul 2023 16:05:31 +0930 Subject: [PATCH] gossipd: add dying marker to channel_announcement/channel_update. We don't actually delete them for 12 blocks, but we can't avoid propagating them. We don't mark node_announcements, which is a bit weird, but avoids us tracking logic to un-dying them if a channel is opened. Signed-off-by: Rusty Russell --- gossipd/gossip_store.c | 34 +++++++++++++++++++ gossipd/gossip_store.h | 11 ++++++ gossipd/routing.c | 11 ++++++ gossipd/test/run-check_channel_announcement.c | 5 +++ gossipd/test/run-txout_failure.c | 5 +++ 5 files changed, 66 insertions(+) diff --git a/gossipd/gossip_store.c b/gossipd/gossip_store.c index 2c7c8ab52..abc001e42 100644 --- a/gossipd/gossip_store.c +++ b/gossipd/gossip_store.c @@ -579,6 +579,40 @@ u64 gossip_store_add_private_update(struct gossip_store *gs, const u8 *update) return gossip_store_add(gs, pupdate, 0, false, false, NULL); } +void gossip_store_mark_dying(struct gossip_store *gs, + const struct broadcastable *bcast, + int type) +{ + const u8 *msg; + be16 flags; + + /* Should never get here during loading! */ + assert(gs->writable); + + /* Should never try to overwrite version */ + assert(bcast->index); + + /* Sanity check, that this is a channel announcement */ + msg = gossip_store_get(tmpctx, gs, bcast->index); + if (fromwire_peektype(msg) != type) { + status_broken("gossip_store incorrect dying msg not %u @%u of %"PRIu64": %s", + type, bcast->index, gs->len, tal_hex(tmpctx, msg)); + return; + } + + if (pread(gs->fd, &flags, sizeof(flags), bcast->index) != sizeof(flags)) { + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Could not read to mark dying at %u/%"PRIu64": %s", + bcast->index, gs->len, strerror(errno)); + } + + flags |= cpu_to_be16(GOSSIP_STORE_DYING_BIT); + if (pwrite(gs->fd, &flags, sizeof(flags), bcast->index) != sizeof(flags)) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Failed writing flags to dying @%u: %s", + bcast->index, strerror(errno)); +} + /* Returns index of following entry. */ static u32 delete_by_index(struct gossip_store *gs, u32 index, int type) { diff --git a/gossipd/gossip_store.h b/gossipd/gossip_store.h index 3d27df5ba..698eb6471 100644 --- a/gossipd/gossip_store.h +++ b/gossipd/gossip_store.h @@ -76,6 +76,17 @@ void gossip_store_mark_channel_zombie(struct gossip_store *gs, void gossip_store_mark_cupdate_zombie(struct gossip_store *gs, struct broadcastable *bcast); +/** + * Mark this channel_announcement/channel_update as dying. + * + * We'll clean it up in 12 blocks, but this tells connectd not to gossip + * about it. + */ +void gossip_store_mark_dying(struct gossip_store *gs, + const struct broadcastable *bcast, + int type); + + /** * Direct store accessor: loads gossip msg back from store. * diff --git a/gossipd/routing.c b/gossipd/routing.c index e983db659..ffc7daddd 100644 --- a/gossipd/routing.c +++ b/gossipd/routing.c @@ -2279,6 +2279,17 @@ void routing_channel_spent(struct routing_state *rstate, msg = towire_gossip_store_chan_dying(tmpctx, &chan->scid, deadline); index = gossip_store_add(rstate->gs, msg, 0, false, false, NULL); + /* Mark it dying, so we don't gossip it */ + gossip_store_mark_dying(rstate->gs, &chan->bcast, + WIRE_CHANNEL_ANNOUNCEMENT); + for (int dir = 0; dir < ARRAY_SIZE(chan->half); dir++) { + if (is_halfchan_defined(&chan->half[dir])) { + gossip_store_mark_dying(rstate->gs, + &chan->half[dir].bcast, + WIRE_CHANNEL_UPDATE); + } + } + /* Remember locally so we can kill it in 12 blocks */ status_debug("channel %s closing soon due" " to the funding outpoint being spent", diff --git a/gossipd/test/run-check_channel_announcement.c b/gossipd/test/run-check_channel_announcement.c index f2ded1cf6..bd2d70071 100644 --- a/gossipd/test/run-check_channel_announcement.c +++ b/gossipd/test/run-check_channel_announcement.c @@ -86,6 +86,11 @@ const u8 *gossip_store_get_private_update(const tal_t *ctx UNNEEDED, void gossip_store_mark_channel_deleted(struct gossip_store *gs UNNEEDED, const struct short_channel_id *scid UNNEEDED) { fprintf(stderr, "gossip_store_mark_channel_deleted called!\n"); abort(); } +/* Generated stub for gossip_store_mark_dying */ +void gossip_store_mark_dying(struct gossip_store *gs UNNEEDED, + const struct broadcastable *bcast UNNEEDED, + int type UNNEEDED) +{ fprintf(stderr, "gossip_store_mark_dying called!\n"); abort(); } /* Generated stub for gossip_store_new */ struct gossip_store *gossip_store_new(struct routing_state *rstate UNNEEDED) { fprintf(stderr, "gossip_store_new called!\n"); abort(); } diff --git a/gossipd/test/run-txout_failure.c b/gossipd/test/run-txout_failure.c index 1e924581e..2eb26db8a 100644 --- a/gossipd/test/run-txout_failure.c +++ b/gossipd/test/run-txout_failure.c @@ -57,6 +57,11 @@ const u8 *gossip_store_get_private_update(const tal_t *ctx UNNEEDED, void gossip_store_mark_channel_deleted(struct gossip_store *gs UNNEEDED, const struct short_channel_id *scid UNNEEDED) { fprintf(stderr, "gossip_store_mark_channel_deleted called!\n"); abort(); } +/* Generated stub for gossip_store_mark_dying */ +void gossip_store_mark_dying(struct gossip_store *gs UNNEEDED, + const struct broadcastable *bcast UNNEEDED, + int type UNNEEDED) +{ fprintf(stderr, "gossip_store_mark_dying called!\n"); abort(); } /* Generated stub for memleak_add_helper_ */ void memleak_add_helper_(const tal_t *p UNNEEDED, void (*cb)(struct htable *memtable UNNEEDED, const tal_t *)){ }