From 6bbb9a32fc9cb7df2b33baa7b4fccc2e48de70fe Mon Sep 17 00:00:00 2001 From: Elle Mouton Date: Wed, 25 Feb 2026 11:06:12 +0200 Subject: [PATCH] graph/db: thread context through FetchChannelEdgesByID --- discovery/chan_series.go | 2 +- graph/builder.go | 4 +++- graph/db/graph.go | 10 ++++++---- graph/db/graph_test.go | 28 ++++++++++++++++++++-------- graph/db/interfaces.go | 3 ++- graph/db/kv_store.go | 5 +++-- graph/db/notifications.go | 5 ++++- graph/db/sql_store.go | 6 +++--- lnrpc/invoicesrpc/addinvoice.go | 25 ++++++++++++++++++++----- lnrpc/invoicesrpc/interfaces.go | 7 +++++-- routing/pathfind_test.go | 16 ++++++++++++---- routing/router_test.go | 12 +++++++----- rpcserver.go | 10 ++++++---- server.go | 2 +- 14 files changed, 93 insertions(+), 42 deletions(-) diff --git a/discovery/chan_series.go b/discovery/chan_series.go index a1f0778e2..5fff3ca6e 100644 --- a/discovery/chan_series.go +++ b/discovery/chan_series.go @@ -354,7 +354,7 @@ func (c *ChanSeries) FetchChanUpdates(chain chainhash.Hash, shortChanID lnwire.ShortChannelID) ([]*lnwire.ChannelUpdate1, error) { chanInfo, e1, e2, err := c.graph.FetchChannelEdgesByID( - shortChanID.ToUint64(), + context.TODO(), shortChanID.ToUint64(), ) if err != nil { return nil, err diff --git a/graph/builder.go b/graph/builder.go index 497b26329..96b79fcc7 100644 --- a/graph/builder.go +++ b/graph/builder.go @@ -1259,7 +1259,9 @@ func (b *Builder) GetChannelByID(chanID lnwire.ShortChannelID) ( *models.ChannelEdgePolicy, *models.ChannelEdgePolicy, error) { - return b.cfg.Graph.FetchChannelEdgesByID(chanID.ToUint64()) + return b.cfg.Graph.FetchChannelEdgesByID( + context.TODO(), chanID.ToUint64(), + ) } // FetchNode attempts to look up a target node by its identity public diff --git a/graph/db/graph.go b/graph/db/graph.go index e199ce0b1..a192ae3f1 100644 --- a/graph/db/graph.go +++ b/graph/db/graph.go @@ -739,12 +739,13 @@ func (c *ChannelGraph) FetchChannelEdgesByOutpoint(op *wire.OutPoint) ( } // FetchChannelEdgesByID attempts to lookup directed edges by channel ID. -func (c *ChannelGraph) FetchChannelEdgesByID(chanID uint64) ( +func (c *ChannelGraph) FetchChannelEdgesByID(ctx context.Context, + chanID uint64) ( *models.ChannelEdgeInfo, *models.ChannelEdgePolicy, *models.ChannelEdgePolicy, error) { return c.db.FetchChannelEdgesByID( - lnwire.GossipVersion1, chanID, + ctx, lnwire.GossipVersion1, chanID, ) } @@ -812,11 +813,12 @@ func (c *VersionedGraph) FetchNode(ctx context.Context, } // FetchChannelEdgesByID attempts to lookup directed edges by channel ID. -func (c *VersionedGraph) FetchChannelEdgesByID(chanID uint64) ( +func (c *VersionedGraph) FetchChannelEdgesByID(ctx context.Context, + chanID uint64) ( *models.ChannelEdgeInfo, *models.ChannelEdgePolicy, *models.ChannelEdgePolicy, error) { - return c.db.FetchChannelEdgesByID(c.v, chanID) + return c.db.FetchChannelEdgesByID(ctx, c.v, chanID) } // FetchChannelEdgesByOutpoint attempts to lookup directed edges by funding diff --git a/graph/db/graph_test.go b/graph/db/graph_test.go index 8572808c4..b201e969a 100644 --- a/graph/db/graph_test.go +++ b/graph/db/graph_test.go @@ -643,7 +643,7 @@ func testEdgeInsertionDeletion(t *testing.T, v lnwire.GossipVersion) { // Ensure that both policies are returned as unknown (nil) and that // the edge info round-trips correctly. - dbEdge, e1, e2, err := graph.FetchChannelEdgesByID(chanID) + dbEdge, e1, e2, err := graph.FetchChannelEdgesByID(ctx, chanID) require.NoError(t, err) require.Nil(t, e1) require.Nil(t, e2) @@ -712,7 +712,7 @@ func testEdgeInsertionDeletion(t *testing.T, v lnwire.GossipVersion) { // Assert that if the edge is a zombie, then FetchChannelEdgesByID // still returns a populated models.ChannelEdgeInfo as its comment // description promises. - edge, _, _, err := graph.FetchChannelEdgesByID(chanID) + edge, _, _, err := graph.FetchChannelEdgesByID(ctx, chanID) require.ErrorIs(t, err, ErrZombieEdge) require.NotNil(t, edge) @@ -1195,7 +1195,9 @@ func testEdgeInfoUpdates(t *testing.T, v lnwire.GossipVersion) { // With the edges inserted, perform some queries to ensure that they've // been inserted properly. - dbEdgeInfo, dbEdge1, dbEdge2, err := graph.FetchChannelEdgesByID(chanID) + dbEdgeInfo, dbEdge1, dbEdge2, err := graph.FetchChannelEdgesByID( + ctx, chanID, + ) require.NoError(t, err, "unable to fetch channel by ID") compareEdgePolicies(t, dbEdge1, edge1) compareEdgePolicies(t, dbEdge2, edge2) @@ -1578,7 +1580,9 @@ func testAddEdgeProof(t *testing.T, v lnwire.GossipVersion) { require.NoError(t, graph.AddChannelEdge(ctx, edge1)) // Fetch the edge and assert that the proof is nil. - dbEdge, _, _, err := graph.FetchChannelEdgesByID(edge1.ChannelID) + dbEdge, _, _, err := graph.FetchChannelEdgesByID( + ctx, edge1.ChannelID, + ) require.NoError(t, err) require.Nil(t, dbEdge.AuthProof) @@ -1608,7 +1612,9 @@ func testAddEdgeProof(t *testing.T, v lnwire.GossipVersion) { require.NoError(t, graph.AddEdgeProof(scid1, proof)) // Fetch the edge again and assert that the proof is now set. - dbEdge, _, _, err = graph.FetchChannelEdgesByID(edge1.ChannelID) + dbEdge, _, _, err = graph.FetchChannelEdgesByID( + ctx, edge1.ChannelID, + ) require.NoError(t, err) require.NotNil(t, dbEdge.AuthProof) @@ -1618,7 +1624,9 @@ func testAddEdgeProof(t *testing.T, v lnwire.GossipVersion) { require.NoError(t, graph.AddChannelEdge(ctx, edge2)) // Fetch the edge and assert that the proof is set. - dbEdge2, _, _, err := graph.FetchChannelEdgesByID(edge2.ChannelID) + dbEdge2, _, _, err := graph.FetchChannelEdgesByID( + ctx, edge2.ChannelID, + ) require.NoError(t, err) require.NotNil(t, dbEdge2.AuthProof) } @@ -4486,7 +4494,9 @@ func TestEdgePolicyMissingMaxHTLC(t *testing.T) { // we added is invalid according to the new format, it should be as we // are not aware of the policy (indicated by the policy returned being // nil) - dbEdgeInfo, dbEdge1, dbEdge2, err := graph.FetchChannelEdgesByID(chanID) + dbEdgeInfo, dbEdge1, dbEdge2, err := graph.FetchChannelEdgesByID( + ctx, chanID, + ) require.NoError(t, err, "unable to fetch channel by ID") // The first edge should have a nil-policy returned @@ -4498,7 +4508,9 @@ func TestEdgePolicyMissingMaxHTLC(t *testing.T) { // policies then become fully populated. require.NoError(t, graph.UpdateEdgePolicy(ctx, edge1)) - dbEdgeInfo, dbEdge1, dbEdge2, err = graph.FetchChannelEdgesByID(chanID) + dbEdgeInfo, dbEdge1, dbEdge2, err = graph.FetchChannelEdgesByID( + ctx, chanID, + ) require.NoError(t, err, "unable to fetch channel by ID") compareEdgePolicies(t, dbEdge1, edge1) compareEdgePolicies(t, dbEdge2, edge2) diff --git a/graph/db/interfaces.go b/graph/db/interfaces.go index a69818366..550c78ae9 100644 --- a/graph/db/interfaces.go +++ b/graph/db/interfaces.go @@ -311,7 +311,8 @@ type Store interface { //nolint:interfacebloat // zombie within the database. In this case, the ChannelEdgePolicy's // will be nil, and the ChannelEdgeInfo will only include the public // keys of each node. - FetchChannelEdgesByID(v lnwire.GossipVersion, chanID uint64) ( + FetchChannelEdgesByID(ctx context.Context, v lnwire.GossipVersion, + chanID uint64) ( *models.ChannelEdgeInfo, *models.ChannelEdgePolicy, *models.ChannelEdgePolicy, error) diff --git a/graph/db/kv_store.go b/graph/db/kv_store.go index 09b180b1f..f77484a7c 100644 --- a/graph/db/kv_store.go +++ b/graph/db/kv_store.go @@ -3989,8 +3989,9 @@ func (c *KVStore) FetchChannelEdgesByOutpoint(v lnwire.GossipVersion, // ErrZombieEdge an be returned if the edge is currently marked as a zombie // within the database. In this case, the ChannelEdgePolicy's will be nil, and // the ChannelEdgeInfo will only include the public keys of each node. -func (c *KVStore) FetchChannelEdgesByID(v lnwire.GossipVersion, - chanID uint64) (*models.ChannelEdgeInfo, *models.ChannelEdgePolicy, +func (c *KVStore) FetchChannelEdgesByID(_ context.Context, + v lnwire.GossipVersion, chanID uint64) ( + *models.ChannelEdgeInfo, *models.ChannelEdgePolicy, *models.ChannelEdgePolicy, error) { if v != lnwire.GossipVersion1 { diff --git a/graph/db/notifications.go b/graph/db/notifications.go index 54a748c66..6676cbebe 100644 --- a/graph/db/notifications.go +++ b/graph/db/notifications.go @@ -1,6 +1,7 @@ package graphdb import ( + "context" "errors" "fmt" "image/color" @@ -412,7 +413,9 @@ func (c *ChannelGraph) addToTopologyChange(update *TopologyChange, // We'll need to fetch the edge's information from the database // in order to get the information concerning which nodes are // being connected. - edgeInfo, _, _, err := c.FetchChannelEdgesByID(m.ChannelID) + edgeInfo, _, _, err := c.FetchChannelEdgesByID( + context.TODO(), m.ChannelID, + ) if err != nil { return fmt.Errorf("unable fetch channel edge: %w", err) } diff --git a/graph/db/sql_store.go b/graph/db/sql_store.go index a534eccf7..9085e06e5 100644 --- a/graph/db/sql_store.go +++ b/graph/db/sql_store.go @@ -2050,12 +2050,12 @@ func (s *SQLStore) DeleteChannelEdges(ctx context.Context, // the ChannelEdgeInfo will only include the public keys of each node. // // NOTE: part of the Store interface. -func (s *SQLStore) FetchChannelEdgesByID(v lnwire.GossipVersion, - chanID uint64) (*models.ChannelEdgeInfo, *models.ChannelEdgePolicy, +func (s *SQLStore) FetchChannelEdgesByID(ctx context.Context, + v lnwire.GossipVersion, chanID uint64) ( + *models.ChannelEdgeInfo, *models.ChannelEdgePolicy, *models.ChannelEdgePolicy, error) { var ( - ctx = context.TODO() edge *models.ChannelEdgeInfo policy1, policy2 *models.ChannelEdgePolicy chanIDB = channelIDToBytes(chanID) diff --git a/lnrpc/invoicesrpc/addinvoice.go b/lnrpc/invoicesrpc/addinvoice.go index aba5da4df..7d8ece0a8 100644 --- a/lnrpc/invoicesrpc/addinvoice.go +++ b/lnrpc/invoicesrpc/addinvoice.go @@ -522,8 +522,16 @@ func AddInvoice(ctx context.Context, cfg *AddInvoiceConfig, //nolint:ll paths, err := blindedpath.BuildBlindedPaymentPaths( &blindedpath.BuildBlindedPathCfg{ - FindRoutes: cfg.QueryBlindedRoutes, - FetchChannelEdgesByID: cfg.Graph.FetchChannelEdgesByID, + FindRoutes: cfg.QueryBlindedRoutes, + FetchChannelEdgesByID: func(chanID uint64) ( + *models.ChannelEdgeInfo, + *models.ChannelEdgePolicy, + *models.ChannelEdgePolicy, error) { + + return cfg.Graph.FetchChannelEdgesByID( + context.TODO(), chanID, + ) + }, FetchOurOpenChannels: cfg.ChanDB.FetchAllOpenChannels, PathID: paymentAddr[:], ValueMsat: invoice.Value, @@ -790,9 +798,16 @@ func newSelectHopHintsCfg(invoicesCfg *AddInvoiceConfig, FetchAllChannels: invoicesCfg.ChanDB.FetchAllChannels, IsChannelActive: invoicesCfg.IsChannelActive, IsPublicNode: invoicesCfg.Graph.IsPublicNode, - FetchChannelEdgesByID: invoicesCfg.Graph.FetchChannelEdgesByID, - GetAlias: invoicesCfg.GetAlias, - MaxHopHints: maxHopHints, + FetchChannelEdgesByID: func(chanID uint64) ( + *models.ChannelEdgeInfo, *models.ChannelEdgePolicy, + *models.ChannelEdgePolicy, error) { + + return invoicesCfg.Graph.FetchChannelEdgesByID( + context.TODO(), chanID, + ) + }, + GetAlias: invoicesCfg.GetAlias, + MaxHopHints: maxHopHints, } } diff --git a/lnrpc/invoicesrpc/interfaces.go b/lnrpc/invoicesrpc/interfaces.go index df47d2f24..d350af6a2 100644 --- a/lnrpc/invoicesrpc/interfaces.go +++ b/lnrpc/invoicesrpc/interfaces.go @@ -1,6 +1,8 @@ package invoicesrpc import ( + "context" + "github.com/lightningnetwork/lnd/graph/db/models" ) @@ -9,8 +11,9 @@ type GraphSource interface { // FetchChannelEdgesByID attempts to look up the two directed edges for // the channel identified by the channel ID. If the channel can't be // found, then graphdb.ErrEdgeNotFound is returned. - FetchChannelEdgesByID(chanID uint64) (*models.ChannelEdgeInfo, - *models.ChannelEdgePolicy, *models.ChannelEdgePolicy, error) + FetchChannelEdgesByID(ctx context.Context, chanID uint64) ( + *models.ChannelEdgeInfo, *models.ChannelEdgePolicy, + *models.ChannelEdgePolicy, error) // IsPublicNode is a helper method that determines whether the node with // the given public key is seen as a public node in the graph from the diff --git a/routing/pathfind_test.go b/routing/pathfind_test.go index 01f5d9849..3dc1ddfe1 100644 --- a/routing/pathfind_test.go +++ b/routing/pathfind_test.go @@ -2199,7 +2199,9 @@ func runRouteFailMaxHTLC(t *testing.T, useCache bool) { // Next, update the middle edge policy to only allow payments up to 100k // msat. graph := ctx.testGraphInstance.graph - _, midEdge, _, err := graph.FetchChannelEdgesByID(firstToSecondID) + _, midEdge, _, err := graph.FetchChannelEdgesByID( + t.Context(), firstToSecondID, + ) require.NoError(t, err, "unable to fetch channel edges by ID") midEdge.MessageFlags = 1 midEdge.MaxHTLC = payAmt - 1 @@ -2243,7 +2245,9 @@ func runRouteFailDisabledEdge(t *testing.T, useCache bool) { // path finding, as we don't consider the disable flag for local // channels (and roasbeef is the source). roasToPham := uint64(999991) - _, e1, e2, err := graph.graph.FetchChannelEdgesByID(roasToPham) + _, e1, e2, err := graph.graph.FetchChannelEdgesByID( + t.Context(), roasToPham, + ) require.NoError(t, err, "unable to fetch edge") e1.ChannelFlags |= lnwire.ChanUpdateDisabled e1.LastUpdate = e1.LastUpdate.Add(time.Second) @@ -2266,7 +2270,9 @@ func runRouteFailDisabledEdge(t *testing.T, useCache bool) { // Now, we'll modify the edge from phamnuwen -> sophon, to read that // it's disabled. phamToSophon := uint64(99999) - _, e, _, err := graph.graph.FetchChannelEdgesByID(phamToSophon) + _, e, _, err := graph.graph.FetchChannelEdgesByID( + t.Context(), phamToSophon, + ) require.NoError(t, err, "unable to fetch edge") e.ChannelFlags |= lnwire.ChanUpdateDisabled e.LastUpdate = e.LastUpdate.Add(time.Second) @@ -2349,7 +2355,9 @@ func runPathSourceEdgesBandwidth(t *testing.T, useCache bool) { // Finally, set the roasbeef->songoku bandwidth, but also set its // disable flag. bandwidths.hints[roasToSongoku] = 2 * payAmt - _, e1, e2, err := graph.graph.FetchChannelEdgesByID(roasToSongoku) + _, e1, e2, err := graph.graph.FetchChannelEdgesByID( + t.Context(), roasToSongoku, + ) require.NoError(t, err, "unable to fetch edge") e1.ChannelFlags |= lnwire.ChanUpdateDisabled e1.LastUpdate = e1.LastUpdate.Add(time.Second) diff --git a/routing/router_test.go b/routing/router_test.go index 115c02c2c..d3dea61ce 100644 --- a/routing/router_test.go +++ b/routing/router_test.go @@ -454,7 +454,7 @@ func TestChannelUpdateValidation(t *testing.T) { // Assert that the initially configured fee is retrieved correctly. _, e1, e2, err := ctx.graph.FetchChannelEdgesByID( - lnwire.NewShortChanIDFromInt(1).ToUint64(), + t.Context(), lnwire.NewShortChanIDFromInt(1).ToUint64(), ) require.NoError(t, err, "cannot retrieve channel") @@ -526,7 +526,7 @@ func TestChannelUpdateValidation(t *testing.T) { require.Error(t, err, "expected route to fail with channel update") _, e1, e2, err = ctx.graph.FetchChannelEdgesByID( - lnwire.NewShortChanIDFromInt(1).ToUint64(), + t.Context(), lnwire.NewShortChanIDFromInt(1).ToUint64(), ) require.NoError(t, err, "cannot retrieve channel") @@ -548,7 +548,7 @@ func TestChannelUpdateValidation(t *testing.T) { // This time a valid signature was supplied and the policy change should // have been applied to the graph. _, e1, e2, err = ctx.graph.FetchChannelEdgesByID( - lnwire.NewShortChanIDFromInt(1).ToUint64(), + t.Context(), lnwire.NewShortChanIDFromInt(1).ToUint64(), ) require.NoError(t, err, "cannot retrieve channel") @@ -589,7 +589,7 @@ func TestSendPaymentErrorRepeatedFeeInsufficient(t *testing.T) { // to sophon. We'll obtain this as we'll need to to generate the // FeeInsufficient error that we'll send back. _, _, edgeUpdateToFail, err := ctx.graph.FetchChannelEdgesByID( - songokuSophonChanID, + t.Context(), songokuSophonChanID, ) require.NoError(t, err, "unable to fetch chan id") @@ -936,7 +936,9 @@ func TestSendPaymentErrorNonFinalTimeLockErrors(t *testing.T) { chanID := ctx.getChannelIDFromAlias(t, "roasbeef", "songoku") roasbeefSongoku := lnwire.NewShortChanIDFromInt(chanID) - _, _, edgeUpdateToFail, err := ctx.graph.FetchChannelEdgesByID(chanID) + _, _, edgeUpdateToFail, err := ctx.graph.FetchChannelEdgesByID( + t.Context(), chanID, + ) require.NoError(t, err, "unable to fetch chan id") errChanUpdate := lnwire.ChannelUpdate1{ diff --git a/rpcserver.go b/rpcserver.go index bfe537a14..4a9c8e76a 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -716,7 +716,9 @@ func (r *rpcServer) addDeps(ctx context.Context, s *server, FetchChannelCapacity: func(chanID uint64) (btcutil.Amount, error) { - info, _, _, err := graph.FetchChannelEdgesByID(chanID) + info, _, _, err := graph.FetchChannelEdgesByID( + ctx, chanID, + ) if err != nil { return 0, err } @@ -734,7 +736,7 @@ func (r *rpcServer) addDeps(ctx context.Context, s *server, route.Vertex, error) { info, _, _, err := graph.FetchChannelEdgesByID( - chanID, + ctx, chanID, ) if err != nil { return route.Vertex{}, route.Vertex{}, @@ -7106,7 +7108,7 @@ func (r *rpcServer) GetNodeMetrics(ctx context.Context, // uniquely identify the location of transaction's funding output within the // blockchain. The former is an 8-byte integer, while the latter is a string // formatted as funding_txid:output_index. -func (r *rpcServer) GetChanInfo(_ context.Context, +func (r *rpcServer) GetChanInfo(ctx context.Context, in *lnrpc.ChanInfoRequest) (*lnrpc.ChannelEdge, error) { graph := r.server.graphDB @@ -7120,7 +7122,7 @@ func (r *rpcServer) GetChanInfo(_ context.Context, switch { case in.ChanId != 0: edgeInfo, edge1, edge2, err = graph.FetchChannelEdgesByID( - in.ChanId, + ctx, in.ChanId, ) case in.ChanPoint != "": diff --git a/server.go b/server.go index 248a69c6c..6c689719c 100644 --- a/server.go +++ b/server.go @@ -1397,7 +1397,7 @@ func newServer(ctx context.Context, cfg *Config, listenAddrs []net.Addr, *models.ChannelEdgePolicy, error) { info, e1, e2, err := s.graphDB.FetchChannelEdgesByID( - scid.ToUint64(), + context.TODO(), scid.ToUint64(), ) if errors.Is(err, graphdb.ErrEdgeNotFound) { // This is unlikely but there is a slim chance of this