What changed, and why it matters
This commit refactors how LND removes old, closed channels from its network graph database. Instead of building and deleting each channel one at a time inside a loop, it first collects all matching channels, then builds their details in a batch, and finally deletes them together. There is no visible security fix here; it appears to be a performance and code-cleanup change.
No security action required. Treat as a normal performance/refactoring commit. If reviewing for release notes, confirm with the author whether any behavioral change (e.g., prune-log update timing) was intended.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change modifies PruneGraph in graph/db/sql_store.go. Previously the channel callback built edge info and appended a delete ID per row. Now the callback only collects rows, an early-exit path updates the prune log if no rows are found, and a new batchBuildChannelInfo helper builds all closed channel info and delete IDs at once. The supporting change in sqldb/sqlc/db_custom.go adds ChannelAndNodeIDs interface methods to GetChannelsByOutpointsRow so it can be passed to the batch builder. No input validation, authorization, or resource-limit changes are evident.
Changed components
graph/db/sql_store.gosqldb/sqlc/db_custom.goInspect captured patch +50 / −22
diff --git a/graph/db/sql_store.go b/graph/db/sql_store.go
index cd960b1..f1b34b6 100644
--- a/graph/db/sql_store.go
+++ b/graph/db/sql_store.go
@@ -2325,31 +2325,12 @@ func (s *SQLStore) PruneGraph(spentOutputs []*wire.OutPoint,
prunedNodes []route.Vertex
)
err := s.db.ExecTx(ctx, sqldb.WriteTxOpt(), func(db SQLQueries) error {
- var chansToDelete []int64
-
- // Define the callback function for processing each channel.
+ // First, collect all channel rows that need to be pruned.
+ var channelRows []sqlc.GetChannelsByOutpointsRow
channelCallback := func(ctx context.Context,
row sqlc.GetChannelsByOutpointsRow) error {
- node1, node2, err := buildNodeVertices(
- row.Node1Pubkey, row.Node2Pubkey,
- )
- if err != nil {
- return err
- }
-
- info, err := getAndBuildEdgeInfo(
- ctx, db, s.cfg.ChainHash, row.GraphChannel,
- node1, node2,
- )
- if err != nil {
- return err
- }
-
- closedChans = append(closedChans, info)
- chansToDelete = append(
- chansToDelete, row.GraphChannel.ID,
- )
+ channelRows = append(channelRows, row)
return nil
}
@@ -2362,6 +2343,32 @@ func (s *SQLStore) PruneGraph(spentOutputs []*wire.OutPoint,
"outpoints: %w", err)
}
+ if len(channelRows) == 0 {
+ // There are no channels to prune. So we can exit early
+ // after updating the prune log.
+ err = db.UpsertPruneLogEntry(
+ ctx, sqlc.UpsertPruneLogEntryParams{
+ BlockHash: blockHash[:],
+ BlockHeight: int64(blockHeight),
+ },
+ )
+ if err != nil {
+ return fmt.Errorf("unable to insert prune log "+
+ "entry: %w", err)
+ }
+
+ return nil
+ }
+
+ // Batch build all channel edges for pruning.
+ var chansToDelete []int64
+ closedChans, chansToDelete, err = batchBuildChannelInfo(
+ ctx, s.cfg, db, channelRows,
+ )
+ if err != nil {
+ return err
+ }
+
err = s.deleteChannels(ctx, db, chansToDelete)
if err != nil {
return fmt.Errorf("unable to delete channels: %w", err)
diff --git a/sqldb/sqlc/db_custom.go b/sqldb/sqlc/db_custom.go
index 8230028..2b378d4 100644
--- a/sqldb/sqlc/db_custom.go
+++ b/sqldb/sqlc/db_custom.go
@@ -105,3 +105,24 @@ func (r GetChannelsBySCIDWithPoliciesRow) Node1Pub() []byte {
func (r GetChannelsBySCIDWithPoliciesRow) Node2Pub() []byte {
return r.GraphNode_2.PubKey
}
+
+// Channel returns the GraphChannel associated with this interface.
+//
+// NOTE: This method is part of the ChannelAndNodeIDs interface.
+func (r GetChannelsByOutpointsRow) Channel() GraphChannel {
+ return r.GraphChannel
+}
+
+// Node1Pub returns the public key of the first node as a byte slice.
+//
+// NOTE: This method is part of the ChannelAndNodeIDs interface.
+func (r GetChannelsByOutpointsRow) Node1Pub() []byte {
+ return r.Node1Pubkey
+}
+
+// Node2Pub returns the public key of the second node as a byte slice.
+//
+// NOTE: This method is part of the ChannelAndNodeIDs interface.
+func (r GetChannelsByOutpointsRow) Node2Pub() []byte {
+ return r.Node2Pubkey
+}
Why this scored 11/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.