gossipd: set dying flag on node_announcement when all channels are dying.

This avoids us gossiping about nodes which don't have live channels.

Interstingly, we previously tested that we *did* gossip such node
announcements, and now we fix that test.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2024-02-11 21:02:41 +10:30 committed by Christian Decker
parent ca5b7b00b6
commit 450d78ad67
2 changed files with 33 additions and 2 deletions

View File

@ -220,6 +220,17 @@ static bool any_cannounce_preceeds_offset(struct gossmap *gossmap,
return false;
}
/* Are all channels associated with this node dying? */
static bool all_node_channels_dying(struct gossmap *gossmap, const struct gossmap_node *n)
{
for (size_t i = 0; i < n->num_chans; i++) {
const struct gossmap_chan *c = gossmap_nth_chan(gossmap, n, i, NULL);
if (!gossmap_chan_is_dying(gossmap, c))
return false;
}
return true;
}
/* To actually remove a channel:
* - Suppress future lookups in case we receive another channel_update.
* - Put deleted tombstone in gossip_store.
@ -1161,6 +1172,26 @@ void gossmap_manage_channel_spent(struct gossmap_manage *gm,
GOSSIP_STORE_DYING_BIT,
WIRE_CHANNEL_UPDATE);
}
/* If all channels associated with either node are dying, node_announcement is dying
too (so we don't broadcast) */
for (int dir = 0; dir < 2; dir++) {
struct gossmap_node *n = gossmap_nth_node(gossmap, chan, dir);
if (!gossmap_node_announced(n))
continue;
/* Don't get confused if a node has a channel with self! */
if (dir == 1 && n == gossmap_nth_node(gossmap, chan, 0))
continue;
if (all_node_channels_dying(gossmap, n)) {
gossip_store_set_flag(gm->daemon->gs,
n->nann_off,
GOSSIP_STORE_DYING_BIT,
WIRE_NODE_ANNOUNCEMENT);
}
}
}
struct gossmap *gossmap_manage_get_gossmap(struct gossmap_manage *gm)

View File

@ -1960,9 +1960,9 @@ def test_gossip_not_dying(node_factory, bitcoind):
l1.daemon.wait_for_log("closing soon due to the funding outpoint being spent")
# We won't gossip the dead channel any more (but we still propagate node_announcement). But connectd is not explicitly synced, so wait for "a bit".
# We won't gossip the dead channel any more, nor the node_announcements. But connectd is not explicitly synced, so wait for "a bit".
time.sleep(1)
assert len(get_gossip(l1)) == 2
assert get_gossip(l1) == []
def test_dump_own_gossip(node_factory):