What changed, and why it matters
This commit is a routine code cleanup: it threads a request-scoped cancellation signal (a 'context') into a database lookup function called HasV1ChannelEdge. Previously the SQL database backend used a placeholder context.TODO(), which meant long-running queries could not be cancelled cleanly. The change lets callers cancel or time out the lookup, improving robustness but not directly fixing an exploitable security bug.
No immediate security action required. Treat as normal maintenance. If deploying this commit, ensure downstream callers of HasV1ChannelEdge are updated to pass a meaningful context so cancellation/timeouts can take effect.
Security signals we found
context propagation improvement
potential denial-of-service hardening (long-running SQL query cancellation)
no change to access control, authorization, or cryptographic logic
no input validation changes
no bug fix or vulnerability patch described by the vendor
Evidence from the diff
The patch changes the signature of HasV1ChannelEdge across the Store interface, ChannelGraph wrapper, KVStore and SQLStore implementations, and two call sites in graph/builder.go so that a context.Context is accepted and propagated. The KVStore implementation ignores the context (uses _ context.Context) because its BoltDB backend does not support context cancellation. The SQLStore now uses the supplied context instead of context.TODO(). Callers in builder.go pass their existing ctx, except IsStaleEdgePolicy which uses context.TODO() because it currently lacks a context. This is a non-functional refactor that enables request cancellation/timeouts for SQL graph queries.
Changed components
graph/builder.gograph/db/graph.gograph/db/interfaces.gograph/db/kv_store.gograph/db/sql_store.goInspect captured patch +15 / −13
diff --git a/graph/builder.go b/graph/builder.go
index 96b79fc..64ce013 100644
--- a/graph/builder.go
+++ b/graph/builder.go
@@ -1151,7 +1151,7 @@ func (b *Builder) updateEdge(ctx context.Context,
defer b.channelEdgeMtx.Unlock(policy.ChannelID)
edge1Timestamp, edge2Timestamp, exists, isZombie, err :=
- b.cfg.Graph.HasV1ChannelEdge(policy.ChannelID)
+ b.cfg.Graph.HasV1ChannelEdge(ctx, policy.ChannelID)
if err != nil && !errors.Is(err, graphdb.ErrGraphNoEdgesFound) {
return fmt.Errorf("unable to check for edge existence: %w", err)
}
@@ -1366,7 +1366,9 @@ func (b *Builder) IsStaleEdgePolicy(chanID lnwire.ShortChannelID,
timestamp time.Time, flags lnwire.ChanUpdateChanFlags) bool {
edge1Timestamp, edge2Timestamp, exists, isZombie, err :=
- b.cfg.Graph.HasV1ChannelEdge(chanID.ToUint64())
+ b.cfg.Graph.HasV1ChannelEdge(
+ context.TODO(), chanID.ToUint64(),
+ )
if err != nil {
log.Debugf("Check stale edge policy got error: %v", err)
return false
diff --git a/graph/db/graph.go b/graph/db/graph.go
index 85e8785..6c76f4d 100644
--- a/graph/db/graph.go
+++ b/graph/db/graph.go
@@ -674,10 +674,10 @@ func (c *ChannelGraph) DisabledChannelIDs(ctx context.Context,
}
// HasV1ChannelEdge returns true if the database knows of a channel edge.
-func (c *ChannelGraph) HasV1ChannelEdge(chanID uint64) (time.Time,
- time.Time, bool, bool, error) {
+func (c *ChannelGraph) HasV1ChannelEdge(ctx context.Context,
+ chanID uint64) (time.Time, time.Time, bool, bool, error) {
- return c.db.HasV1ChannelEdge(chanID)
+ return c.db.HasV1ChannelEdge(ctx, chanID)
}
// HasChannelEdge returns true if the database knows of a channel edge.
diff --git a/graph/db/interfaces.go b/graph/db/interfaces.go
index 8db7e0e..1ca68eb 100644
--- a/graph/db/interfaces.go
+++ b/graph/db/interfaces.go
@@ -211,8 +211,8 @@ type Store interface { //nolint:interfacebloat
// last time the edge was updated for both directed edges are returned
// along with the boolean. If it is not found, then the zombie index is
// checked and its result is returned as the second boolean.
- HasV1ChannelEdge(chanID uint64) (time.Time, time.Time, bool, bool,
- error)
+ HasV1ChannelEdge(ctx context.Context, chanID uint64) (
+ time.Time, time.Time, bool, bool, error)
// HasChannelEdge returns true if the database knows of a channel edge
// with the passed channel ID and gossip version, and false otherwise.
diff --git a/graph/db/kv_store.go b/graph/db/kv_store.go
index 6fbd7df..d258361 100644
--- a/graph/db/kv_store.go
+++ b/graph/db/kv_store.go
@@ -1318,7 +1318,7 @@ func (c *KVStore) addChannelEdge(tx kvdb.RwTx,
// the edge was updated for both directed edges are returned along with the
// boolean. If it is not found, then the zombie index is checked and its
// result is returned as the second boolean.
-func (c *KVStore) HasV1ChannelEdge(
+func (c *KVStore) HasV1ChannelEdge(_ context.Context,
chanID uint64) (time.Time, time.Time, bool, bool, error) {
var (
@@ -1434,7 +1434,9 @@ func (c *KVStore) HasChannelEdge(v lnwire.GossipVersion,
return false, false, ErrVersionNotSupportedForKVDB
}
- _, _, exists, isZombie, err := c.HasV1ChannelEdge(chanID)
+ _, _, exists, isZombie, err := c.HasV1ChannelEdge(
+ context.TODO(), chanID,
+ )
return exists, isZombie, err
}
diff --git a/graph/db/sql_store.go b/graph/db/sql_store.go
index 71f9d08..5e358d3 100644
--- a/graph/db/sql_store.go
+++ b/graph/db/sql_store.go
@@ -2244,10 +2244,8 @@ func (s *SQLStore) FetchChannelEdgesByOutpoint(ctx context.Context,
// result is returned as the second boolean.
//
// NOTE: part of the Store interface.
-func (s *SQLStore) HasV1ChannelEdge(chanID uint64) (time.Time, time.Time, bool,
- bool, error) {
-
- ctx := context.TODO()
+func (s *SQLStore) HasV1ChannelEdge(ctx context.Context,
+ chanID uint64) (time.Time, time.Time, bool, bool, error) {
var (
exists bool
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.