What changed, and why it matters
This change simply threads a cancellation signal (a 'context') through a database lookup function called FetchChanInfos. It does not fix a crash, stop a theft, or close a privacy hole on its own. It is a routine plumbing improvement that lets callers cancel long-running queries cleanly, which can help avoid resource exhaustion in edge cases.
No immediate action required. Treat as normal maintenance. If deploying, verify that callers eventually pass a real, cancellable context rather than context.TODO() so the new capability actually protects against stuck queries.
Security signals we found
Context propagation added to database read path
SQL read transaction now respects caller-supplied cancellation context
No input validation, bounds-checking, or cryptographic changes
No change to access control, authentication, or authorization
No change to network-facing protocol behavior
Evidence from the diff
The commit updates the FetchChanInfos method signature across the graph database interfaces and both backend implementations (KVStore and SQLStore) to accept a context.Context. The SQL backend previously created a context.TODO() internally; now it uses the caller-supplied context for its read transaction. The KV backend accepts but ignores the context (uses _). Callers in discovery/chan_series.go, graph/builder.go, and graph/db/graph.go pass context.TODO() or an existing context. This is a refactor enabling future cancellation and timeout propagation, not a targeted security fix.
Changed components
graph/db/interfaces.gograph/db/graph.gograph/db/kv_store.gograph/db/sql_store.godiscovery/chan_series.gograph/builder.gograph/db/graph_test.goInspect captured patch +14 / −15
diff --git a/discovery/chan_series.go b/discovery/chan_series.go
index 5fff3ca..eaebc0b 100644
--- a/discovery/chan_series.go
+++ b/discovery/chan_series.go
@@ -261,7 +261,7 @@ func (c *ChanSeries) FetchChanAnns(chain chainhash.Hash,
chanIDs = append(chanIDs, chanID.ToUint64())
}
- channels, err := c.graph.FetchChanInfos(chanIDs)
+ channels, err := c.graph.FetchChanInfos(context.TODO(), chanIDs)
if err != nil {
return nil, err
}
diff --git a/graph/builder.go b/graph/builder.go
index c2121d8..154a00e 100644
--- a/graph/builder.go
+++ b/graph/builder.go
@@ -582,7 +582,7 @@ func (b *Builder) pruneZombieChans() error {
}
disabledEdges, err := b.v1Graph.FetchChanInfos(
- disabledChanIDs,
+ context.TODO(), disabledChanIDs,
)
if err != nil {
return fmt.Errorf("unable to fetch disabled channels "+
diff --git a/graph/db/graph.go b/graph/db/graph.go
index 0a1f517..c5213ac 100644
--- a/graph/db/graph.go
+++ b/graph/db/graph.go
@@ -353,7 +353,7 @@ func (c *ChannelGraph) MarkEdgeLive(ctx context.Context, chanID uint64) error {
// We need to add the channel back into our graph cache,
// otherwise we won't use it for path finding.
infos, err := c.db.FetchChanInfos(
- lnwire.GossipVersion1, []uint64{chanID},
+ ctx, lnwire.GossipVersion1, []uint64{chanID},
)
if err != nil {
return err
@@ -723,10 +723,10 @@ func (c *ChannelGraph) FilterChannelRange(ctx context.Context,
}
// FetchChanInfos returns the set of channel edges for the passed channel IDs.
-func (c *ChannelGraph) FetchChanInfos(v lnwire.GossipVersion,
- chanIDs []uint64) ([]ChannelEdge, error) {
+func (c *ChannelGraph) FetchChanInfos(ctx context.Context,
+ v lnwire.GossipVersion, chanIDs []uint64) ([]ChannelEdge, error) {
- return c.db.FetchChanInfos(v, chanIDs)
+ return c.db.FetchChanInfos(ctx, v, chanIDs)
}
// FetchChannelEdgesByOutpoint attempts to lookup directed edges by funding
@@ -976,10 +976,10 @@ func (c *VersionedGraph) DisabledChannelIDs(
}
// FetchChanInfos returns the set of channel edges for the passed channel IDs.
-func (c *VersionedGraph) FetchChanInfos(chanIDs []uint64) ([]ChannelEdge,
- error) {
+func (c *VersionedGraph) FetchChanInfos(ctx context.Context,
+ chanIDs []uint64) ([]ChannelEdge, error) {
- return c.db.FetchChanInfos(c.v, chanIDs)
+ return c.db.FetchChanInfos(ctx, c.v, chanIDs)
}
// HighestChanID returns the "highest" known channel ID in the channel graph.
diff --git a/graph/db/graph_test.go b/graph/db/graph_test.go
index 7ff5cde..0f2e635 100644
--- a/graph/db/graph_test.go
+++ b/graph/db/graph_test.go
@@ -3785,7 +3785,7 @@ func testFetchChanInfos(t *testing.T, v lnwire.GossipVersion) {
// We'll now attempt to query for the range of channel ID's we just
// inserted into the database. We should get the exact same set of
// edges back.
- resp, err := graph.FetchChanInfos(edgeQuery)
+ resp, err := graph.FetchChanInfos(ctx, edgeQuery)
require.NoError(t, err, "unable to fetch chan edges")
require.Len(t, resp, len(edges))
diff --git a/graph/db/interfaces.go b/graph/db/interfaces.go
index 3b4175b..cdc6df1 100644
--- a/graph/db/interfaces.go
+++ b/graph/db/interfaces.go
@@ -288,7 +288,7 @@ type Store interface { //nolint:interfacebloat
// edges that exist at the time of the query. This can be used to
// respond to peer queries that are seeking to fill in gaps in their
// view of the channel graph.
- FetchChanInfos(v lnwire.GossipVersion,
+ FetchChanInfos(ctx context.Context, v lnwire.GossipVersion,
chanIDs []uint64) ([]ChannelEdge, error)
// FetchChannelEdgesByOutpoint attempts to lookup the two directed edges
diff --git a/graph/db/kv_store.go b/graph/db/kv_store.go
index 84c293e..2db9f39 100644
--- a/graph/db/kv_store.go
+++ b/graph/db/kv_store.go
@@ -2963,7 +2963,7 @@ func (c *KVStore) FilterChannelRange(_ context.Context, startHeight,
// skipped and the result will contain only those edges that exist at the time
// of the query. This can be used to respond to peer queries that are seeking to
// fill in gaps in their view of the channel graph.
-func (c *KVStore) FetchChanInfos(v lnwire.GossipVersion,
+func (c *KVStore) FetchChanInfos(_ context.Context, v lnwire.GossipVersion,
chanIDs []uint64) ([]ChannelEdge, error) {
if v != lnwire.GossipVersion1 {
diff --git a/graph/db/sql_store.go b/graph/db/sql_store.go
index cd4626b..2b72c46 100644
--- a/graph/db/sql_store.go
+++ b/graph/db/sql_store.go
@@ -2580,11 +2580,10 @@ func (s *SQLStore) IsPublicNode(ctx context.Context, v lnwire.GossipVersion,
// fill in gaps in their view of the channel graph.
//
// NOTE: part of the Store interface.
-func (s *SQLStore) FetchChanInfos(v lnwire.GossipVersion,
- chanIDs []uint64) ([]ChannelEdge, error) {
+func (s *SQLStore) FetchChanInfos(ctx context.Context,
+ v lnwire.GossipVersion, chanIDs []uint64) ([]ChannelEdge, error) {
var (
- ctx = context.TODO()
edges = make(map[uint64]ChannelEdge)
)
err := s.db.ExecTx(ctx, sqldb.ReadTxOpt(), func(db SQLQueries) error {
Why this scored 18/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.