From 0155d5d7b0b6851f63b0f23c3a25be9ddf3a5fad Mon Sep 17 00:00:00 2001 From: Elle Mouton Date: Mon, 12 May 2025 14:36:49 +0200 Subject: [PATCH] graph/db: handle topology updates in a single location In this commit, we ensure that any topology update is forced to go via the `handleTopologySubscriptions` handler so that client subscriptions and updates are handled correctly and in the correct order. This removes a bug that could result from a client missing a notification about a channel being closed if the client is subscribed and shortly after, `PruneGraph` is called which would notify all subscribed clients and possibly do so before the client subscription has actually been persisted. --- docs/release-notes/release-notes-0.19.0.md | 3 +++ graph/db/graph.go | 9 ++++++--- graph/db/notifications.go | 10 +++++++++- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/docs/release-notes/release-notes-0.19.0.md b/docs/release-notes/release-notes-0.19.0.md index dd0def15d..3b6618692 100644 --- a/docs/release-notes/release-notes-0.19.0.md +++ b/docs/release-notes/release-notes-0.19.0.md @@ -128,6 +128,9 @@ when running LND with an aux component injected (custom channels). such that the probability is evaluated quicker and to be more accurate in outdated scenarios. +* [Fix a bug](https://github.com/lightningnetwork/lnd/pull/9798) that could + result in a new topology client missing a channel-close notifications. + # New Features * Add support for [archiving channel backup](https://github.com/lightningnetwork/lnd/pull/9232) diff --git a/graph/db/graph.go b/graph/db/graph.go index 9e35e58dd..5b72b4ef8 100644 --- a/graph/db/graph.go +++ b/graph/db/graph.go @@ -492,9 +492,12 @@ func (c *ChannelGraph) PruneGraph(spentOutputs []*wire.OutPoint, closeSummaries := createCloseSummaries( blockHeight, edges..., ) - c.notifyTopologyChange(&TopologyChange{ - ClosedChannels: closeSummaries, - }) + + select { + case c.topologyUpdate <- closeSummaries: + case <-c.quit: + return nil, ErrChanGraphShuttingDown + } } return edges, nil diff --git a/graph/db/notifications.go b/graph/db/notifications.go index 2ed2be16f..8b69b7d85 100644 --- a/graph/db/notifications.go +++ b/graph/db/notifications.go @@ -149,6 +149,9 @@ type topologyClient struct { // notifyTopologyChange notifies all registered clients of a new change in // graph topology in a non-blocking. +// +// NOTE: this should only ever be called from a call-stack originating from the +// handleTopologySubscriptions handler. func (c *ChannelGraph) notifyTopologyChange(topologyDiff *TopologyChange) { // notifyClient is a helper closure that will send topology updates to // the given client. @@ -194,7 +197,8 @@ func (c *ChannelGraph) notifyTopologyChange(topologyDiff *TopologyChange) { // handleTopologyUpdate is responsible for sending any topology changes // notifications to registered clients. // -// NOTE: must be run inside goroutine. +// NOTE: must be run inside goroutine and must only ever be called from within +// handleTopologySubscriptions. func (c *ChannelGraph) handleTopologyUpdate(update any) { defer c.wg.Done() @@ -445,6 +449,10 @@ func (c *ChannelGraph) addToTopologyChange(update *TopologyChange, edgeUpdate) return nil + case []*ClosedChanSummary: + update.ClosedChannels = append(update.ClosedChannels, m...) + return nil + default: return fmt.Errorf("unable to add to topology change, "+ "unknown message type %T", msg)