diff --git a/docs/release-notes/release-notes-0.20.0.md b/docs/release-notes/release-notes-0.20.0.md index dab221f2e..040290f33 100644 --- a/docs/release-notes/release-notes-0.20.0.md +++ b/docs/release-notes/release-notes-0.20.0.md @@ -87,6 +87,7 @@ circuit. The indices are only available for forwarding events saved after v0.20. * [5](https://github.com/lightningnetwork/lnd/pull/9935) * [6](https://github.com/lightningnetwork/lnd/pull/9936) * [7](https://github.com/lightningnetwork/lnd/pull/9937) + * [8](https://github.com/lightningnetwork/lnd/pull/9938) ## RPC Updates diff --git a/graph/db/graph_test.go b/graph/db/graph_test.go index a340acb1d..eb04ef20b 100644 --- a/graph/db/graph_test.go +++ b/graph/db/graph_test.go @@ -3592,7 +3592,7 @@ func TestDisabledChannelIDs(t *testing.T) { t.Parallel() ctx := context.Background() - graph := MakeTestGraph(t) + graph := MakeTestGraphNew(t) // Create first node and add it to the graph. node1 := createTestVertex(t) @@ -3608,6 +3608,7 @@ func TestDisabledChannelIDs(t *testing.T) { // Adding a new channel edge to the graph. edgeInfo, edge1, edge2 := createChannelEdge(node1, node2) + node2.LastUpdate = time.Unix(nextUpdateTime(), 0) if err := graph.AddLightningNode(ctx, node2); err != nil { t.Fatalf("unable to add node: %v", err) } diff --git a/graph/db/sql_store.go b/graph/db/sql_store.go index cfaaf3b3d..6d2dd85ae 100644 --- a/graph/db/sql_store.go +++ b/graph/db/sql_store.go @@ -109,6 +109,7 @@ type SQLQueries interface { */ UpsertEdgePolicy(ctx context.Context, arg sqlc.UpsertEdgePolicyParams) (int64, error) GetChannelPolicyByChannelAndNode(ctx context.Context, arg sqlc.GetChannelPolicyByChannelAndNodeParams) (sqlc.ChannelPolicy, error) + GetV1DisabledSCIDs(ctx context.Context) ([][]byte, error) InsertChanPolicyExtraType(ctx context.Context, arg sqlc.InsertChanPolicyExtraTypeParams) error GetChannelPolicyExtraTypes(ctx context.Context, arg sqlc.GetChannelPolicyExtraTypesParams) ([]sqlc.GetChannelPolicyExtraTypesRow, error) @@ -372,6 +373,35 @@ func (s *SQLStore) FetchNodeFeatures(nodePub route.Vertex) ( return fetchNodeFeatures(ctx, s.db, nodePub) } +// DisabledChannelIDs returns the channel ids of disabled channels. +// A channel is disabled when two of the associated ChanelEdgePolicies +// have their disabled bit on. +// +// NOTE: part of the V1Store interface. +func (s *SQLStore) DisabledChannelIDs() ([]uint64, error) { + var ( + ctx = context.TODO() + chanIDs []uint64 + ) + err := s.db.ExecTx(ctx, sqldb.ReadTxOpt(), func(db SQLQueries) error { + dbChanIDs, err := db.GetV1DisabledSCIDs(ctx) + if err != nil { + return fmt.Errorf("unable to fetch disabled "+ + "channels: %w", err) + } + + chanIDs = fn.Map(dbChanIDs, byteOrder.Uint64) + + return nil + }, sqldb.NoOpReset) + if err != nil { + return nil, fmt.Errorf("unable to fetch disabled channels: %w", + err) + } + + return chanIDs, nil +} + // LookupAlias attempts to return the alias as advertised by the target node. // // NOTE: part of the V1Store interface. diff --git a/sqldb/sqlc/graph.sql.go b/sqldb/sqlc/graph.sql.go index 58b02425d..6463885cd 100644 --- a/sqldb/sqlc/graph.sql.go +++ b/sqldb/sqlc/graph.sql.go @@ -1219,6 +1219,43 @@ func (q *Queries) GetSourceNodesByVersion(ctx context.Context, version int16) ([ return items, nil } +const getV1DisabledSCIDs = `-- name: GetV1DisabledSCIDs :many +SELECT c.scid +FROM channels c + JOIN channel_policies cp ON cp.channel_id = c.id +WHERE cp.disabled = true +AND c.version = 1 +GROUP BY c.scid +HAVING COUNT(*) > 1 +` + +// NOTE: this is V1 specific since for V1, disabled is a +// simple, single boolean. The proposed V2 policy +// structure will have a more complex disabled bit vector +// and so the query for V2 may differ. +func (q *Queries) GetV1DisabledSCIDs(ctx context.Context) ([][]byte, error) { + rows, err := q.db.QueryContext(ctx, getV1DisabledSCIDs) + if err != nil { + return nil, err + } + defer rows.Close() + var items [][]byte + for rows.Next() { + var scid []byte + if err := rows.Scan(&scid); err != nil { + return nil, err + } + items = append(items, scid) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + const getZombieChannel = `-- name: GetZombieChannel :one SELECT scid, version, node_key_1, node_key_2 FROM zombie_channels diff --git a/sqldb/sqlc/querier.go b/sqldb/sqlc/querier.go index 8c0064bf9..83ee30a8a 100644 --- a/sqldb/sqlc/querier.go +++ b/sqldb/sqlc/querier.go @@ -60,6 +60,11 @@ type Querier interface { GetPublicV1ChannelsBySCID(ctx context.Context, arg GetPublicV1ChannelsBySCIDParams) ([]Channel, error) GetSCIDByOutpoint(ctx context.Context, arg GetSCIDByOutpointParams) ([]byte, error) GetSourceNodesByVersion(ctx context.Context, version int16) ([]GetSourceNodesByVersionRow, error) + // NOTE: this is V1 specific since for V1, disabled is a + // simple, single boolean. The proposed V2 policy + // structure will have a more complex disabled bit vector + // and so the query for V2 may differ. + GetV1DisabledSCIDs(ctx context.Context) ([][]byte, error) GetZombieChannel(ctx context.Context, arg GetZombieChannelParams) (ZombieChannel, error) HighestSCID(ctx context.Context, version int16) ([]byte, error) InsertAMPSubInvoice(ctx context.Context, arg InsertAMPSubInvoiceParams) error diff --git a/sqldb/sqlc/queries/graph.sql b/sqldb/sqlc/queries/graph.sql index 332d5f958..ca40db176 100644 --- a/sqldb/sqlc/queries/graph.sql +++ b/sqldb/sqlc/queries/graph.sql @@ -573,6 +573,19 @@ JOIN channel_policy_extra_types cpet ON cp.id = cpet.channel_policy_id WHERE cp.id = $1 OR cp.id = $2; +-- name: GetV1DisabledSCIDs :many +SELECT c.scid +FROM channels c + JOIN channel_policies cp ON cp.channel_id = c.id +-- NOTE: this is V1 specific since for V1, disabled is a +-- simple, single boolean. The proposed V2 policy +-- structure will have a more complex disabled bit vector +-- and so the query for V2 may differ. +WHERE cp.disabled = true +AND c.version = 1 +GROUP BY c.scid +HAVING COUNT(*) > 1; + -- name: DeleteChannelPolicyExtraTypes :exec DELETE FROM channel_policy_extra_types WHERE channel_policy_id = $1;