graph/db: thread context through FetchNodeFeatures
What changed, and why it matters
This commit is a routine code cleanup that threads a request-scoped context.Context parameter through the FetchNodeFeatures function and its callers. It does not change any security logic, fix a bug, or alter behavior. The change simply lets callers pass cancellation/timeout context into database reads instead of the function internally creating a blank context.TODO().
No security action required. Treat as normal refactoring/review as part of standard code review.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff propagates context.Context through the FetchNodeFeatures method across ChannelGraph, KVStore, SQLStore, NodeTraverser/Store interfaces, routing.Graph, mockGraph, and pathfinding code. Previously SQLStore and sqlNodeTraverser created context.TODO() inside the method; now the caller-provided context is used. KVStore and mockGraph accept but ignore the context. Call sites in routing/pathfind.go pass context.TODO() explicitly. No logic changes, no bug fixes, no security boundary changes.
Changed components
graph/db/graph.gograph/db/interfaces.gograph/db/kv_store.gograph/db/sql_store.gorouting/graph.gorouting/pathfind.gorouting/mock_graph_test.gograph/db/graph_test.goInspect captured patch +30 / −22
diff --git a/graph/db/graph.go b/graph/db/graph.go
index 283f7d5..ba63941 100644
--- a/graph/db/graph.go
+++ b/graph/db/graph.go
@@ -236,14 +236,14 @@ func (c *ChannelGraph) ForEachNodeDirectedChannel(node route.Vertex,
// features instead of the database.
//
// NOTE: this is part of the graphdb.NodeTraverser interface.
-func (c *ChannelGraph) FetchNodeFeatures(node route.Vertex) (
- *lnwire.FeatureVector, error) {
+func (c *ChannelGraph) FetchNodeFeatures(ctx context.Context,
+ node route.Vertex) (*lnwire.FeatureVector, error) {
if c.graphCache != nil {
return c.graphCache.GetFeatures(node), nil
}
- return c.db.FetchNodeFeatures(lnwire.GossipVersion1, node)
+ return c.db.FetchNodeFeatures(ctx, lnwire.GossipVersion1, node)
}
// GraphSession will provide the call-back with access to a NodeTraverser
diff --git a/graph/db/graph_test.go b/graph/db/graph_test.go
index aa0e02b..051f59a 100644
--- a/graph/db/graph_test.go
+++ b/graph/db/graph_test.go
@@ -298,13 +298,13 @@ func testNodeInsertionAndDeletion(t *testing.T, v lnwire.GossipVersion) {
// Check that the node's features are fetched correctly. This check
// will use the graph cache to fetch the features.
- features, err := graph.FetchNodeFeatures(node.PubKeyBytes)
+ features, err := graph.FetchNodeFeatures(ctx, node.PubKeyBytes)
require.NoError(t, err)
require.Equal(t, testFeatures, features)
// Check that the node's features are fetched correctly. This check
// will check the database directly.
- features, err = graph.FetchNodeFeatures(node.PubKeyBytes)
+ features, err = graph.FetchNodeFeatures(ctx, node.PubKeyBytes)
require.NoError(t, err)
require.Equal(t, testFeatures, features)
diff --git a/graph/db/interfaces.go b/graph/db/interfaces.go
index 4466440..9daabb0 100644
--- a/graph/db/interfaces.go
+++ b/graph/db/interfaces.go
@@ -25,7 +25,8 @@ type NodeTraverser interface {
cb func(channel *DirectedChannel) error, reset func()) error
// FetchNodeFeatures returns the features of the given node.
- FetchNodeFeatures(nodePub route.Vertex) (*lnwire.FeatureVector, error)
+ FetchNodeFeatures(ctx context.Context,
+ nodePub route.Vertex) (*lnwire.FeatureVector, error)
}
// Store represents the main interface for the channel graph database for all
@@ -37,7 +38,7 @@ type Store interface { //nolint:interfacebloat
cb func(channel *DirectedChannel) error, reset func()) error
// FetchNodeFeatures returns the features of the given node.
- FetchNodeFeatures(v lnwire.GossipVersion,
+ FetchNodeFeatures(ctx context.Context, v lnwire.GossipVersion,
nodePub route.Vertex) (*lnwire.FeatureVector, error)
// AddNode adds a vertex/node to the graph database. If the
diff --git a/graph/db/kv_store.go b/graph/db/kv_store.go
index de9ff40..67cebc2 100644
--- a/graph/db/kv_store.go
+++ b/graph/db/kv_store.go
@@ -684,7 +684,7 @@ func (c *KVStore) ForEachNodeDirectedChannel(v lnwire.GossipVersion,
// known for the node, an empty feature vector is returned.
//
// NOTE: this is part of the graphdb.NodeTraverser interface.
-func (c *KVStore) FetchNodeFeatures(v lnwire.GossipVersion,
+func (c *KVStore) FetchNodeFeatures(_ context.Context, v lnwire.GossipVersion,
nodePub route.Vertex) (*lnwire.FeatureVector, error) {
if v != lnwire.GossipVersion1 {
@@ -4511,7 +4511,8 @@ func (c *nodeTraverserSession) ForEachNodeDirectedChannel(
// unknown, assume no additional features are supported.
//
// NOTE: Part of the NodeTraverser interface.
-func (c *nodeTraverserSession) FetchNodeFeatures(nodePub route.Vertex) (
+func (c *nodeTraverserSession) FetchNodeFeatures(_ context.Context,
+ nodePub route.Vertex) (
*lnwire.FeatureVector, error) {
return c.db.fetchNodeFeatures(c.tx, nodePub)
diff --git a/graph/db/sql_store.go b/graph/db/sql_store.go
index a04a70a..cc058c8 100644
--- a/graph/db/sql_store.go
+++ b/graph/db/sql_store.go
@@ -447,10 +447,9 @@ func (s *SQLStore) DeleteNode(ctx context.Context, v lnwire.GossipVersion,
// known for the node, an empty feature vector is returned.
//
// NOTE: this is part of the graphdb.NodeTraverser interface.
-func (s *SQLStore) FetchNodeFeatures(v lnwire.GossipVersion,
- nodePub route.Vertex) (*lnwire.FeatureVector, error) {
-
- ctx := context.TODO()
+func (s *SQLStore) FetchNodeFeatures(ctx context.Context,
+ v lnwire.GossipVersion, nodePub route.Vertex) (*lnwire.FeatureVector,
+ error) {
return fetchNodeFeatures(ctx, s.db, v, nodePub)
}
@@ -3391,11 +3390,10 @@ func (s *sqlNodeTraverser) ForEachNodeDirectedChannel(
// unknown, assume no additional features are supported.
//
// NOTE: Part of the NodeTraverser interface.
-func (s *sqlNodeTraverser) FetchNodeFeatures(nodePub route.Vertex) (
+func (s *sqlNodeTraverser) FetchNodeFeatures(ctx context.Context,
+ nodePub route.Vertex) (
*lnwire.FeatureVector, error) {
- ctx := context.TODO()
-
return fetchNodeFeatures(ctx, s.db, lnwire.GossipVersion1, nodePub)
}
diff --git a/routing/graph.go b/routing/graph.go
index 4be34de..2cfaec0 100644
--- a/routing/graph.go
+++ b/routing/graph.go
@@ -1,6 +1,7 @@
package routing
import (
+ "context"
"fmt"
"github.com/btcsuite/btcd/btcutil"
@@ -19,7 +20,8 @@ type Graph interface {
reset func()) error
// FetchNodeFeatures returns the features of the given node.
- FetchNodeFeatures(nodePub route.Vertex) (*lnwire.FeatureVector, error)
+ FetchNodeFeatures(ctx context.Context,
+ nodePub route.Vertex) (*lnwire.FeatureVector, error)
}
// GraphSessionFactory can be used to gain access to a graphdb.NodeTraverser
diff --git a/routing/mock_graph_test.go b/routing/mock_graph_test.go
index d9b16f6..b11bdf8 100644
--- a/routing/mock_graph_test.go
+++ b/routing/mock_graph_test.go
@@ -2,6 +2,7 @@ package routing
import (
"bytes"
+ "context"
"fmt"
"testing"
@@ -221,8 +222,8 @@ func (m *mockGraph) sourceNode() route.Vertex {
// fetchNodeFeatures returns the features of the given node.
//
// NOTE: Part of the Graph interface.
-func (m *mockGraph) FetchNodeFeatures(nodePub route.Vertex) (
- *lnwire.FeatureVector, error) {
+func (m *mockGraph) FetchNodeFeatures(_ context.Context,
+ _ route.Vertex) (*lnwire.FeatureVector, error) {
return lnwire.EmptyFeatureVector(), nil
}
diff --git a/routing/pathfind.go b/routing/pathfind.go
index ddaade6..0f177c3 100644
--- a/routing/pathfind.go
+++ b/routing/pathfind.go
@@ -3,6 +3,7 @@ package routing
import (
"bytes"
"container/heap"
+ "context"
"errors"
"fmt"
"math"
@@ -621,7 +622,9 @@ func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig,
features := r.DestFeatures
if features == nil {
var err error
- features, err = g.graph.FetchNodeFeatures(target)
+ features, err = g.graph.FetchNodeFeatures(
+ context.TODO(), target,
+ )
if err != nil {
return nil, 0, err
}
@@ -1019,7 +1022,9 @@ func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig,
}
// Fetch node features fresh from the graph.
- fromFeatures, err := g.graph.FetchNodeFeatures(node)
+ fromFeatures, err := g.graph.FetchNodeFeatures(
+ context.TODO(), node,
+ )
if err != nil {
return nil, err
}
@@ -1349,7 +1354,7 @@ func findBlindedPaths(g Graph, target route.Vertex,
return true, nil
}
- features, err := g.FetchNodeFeatures(node)
+ features, err := g.FetchNodeFeatures(context.TODO(), node)
if err != nil {
return false, err
}
Why this scored 15/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.