graph/db: fix race in DisconnectBlockAtHeight cache access
What changed, and why it matters
This commit fixes a concurrency bug in LND's channel graph database. When disconnecting a block, the code was removing entries from internal caches without holding the proper lock, while other code paths correctly lock the same caches. This can cause data races, potentially leading to corrupted cache state, inconsistent channel graph views, or crashes under concurrent load.
Apply the patch. Consider running the race detector (go test -race) on graph/db package tests covering block disconnect and channel edge addition paths. Review other cache-modifying methods for consistent cacheMu usage.
Security signals we found
Concurrency race condition on shared cache
Missing mutex lock around cache mutation
Potential cache corruption or inconsistent graph state
Crash or undefined behavior under concurrent block reorganization and channel updates
Evidence from the diff
The patch adds s.cacheMu.Lock()/Unlock() around cache removal in SQLStore.DisconnectBlockAtHeight. Previously, removedChans were iterated to call rejectCache.remove and chanCache.remove without holding cacheMu, while AddChannelEdge’s OnCommit callback modifies the same caches under cacheMu held by the batch scheduler. This is a classic read-modify-write race on shared in-memory cache state.
Changed components
graph/db/sql_store.goSQLStore.DisconnectBlockAtHeightrejectCachechanCacheInspect captured patch +2 / −0
diff --git a/graph/db/sql_store.go b/graph/db/sql_store.go
index 6507707..2bfcce5 100644
--- a/graph/db/sql_store.go
+++ b/graph/db/sql_store.go
@@ -2911,10 +2911,12 @@ func (s *SQLStore) DisconnectBlockAtHeight(height uint32) (
"height: %w", err)
}
+ s.cacheMu.Lock()
for _, channel := range removedChans {
s.rejectCache.remove(channel.ChannelID)
s.chanCache.remove(channel.ChannelID)
}
+ s.cacheMu.Unlock()
return removedChans, nil
}
Why this scored 49/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.