79 Commits
Author SHA1 Message Date
ziggie e751d96c13 sqldb: remove unused GetInvoice query 2026-03-04 13:04:26 +01:00
ziggie e2dfd8f034 invoices: add TODO to change the return type of the query 2026-03-04 13:04:26 +01:00
ziggie 0ca69e6f57 invoices/sql: replace catch-all GetInvoice with indexed lookups
The GetInvoice query used an OR IS NULL pattern for each filter
parameter:

  WHERE (i.hash = $1 OR $1 IS NULL)
    AND (i.payment_addr = $2 OR $2 IS NULL)

SQLite's query planner decides on an execution plan at prepare time,
before seeing any parameter values. Because either condition can be
trivially true when its parameter is NULL, the planner conservatively
falls back to a full table scan rather than using the unique indexes on
hash and payment_addr. This caused every invoice lookup and update on
the hot path (HTLC settlement) to scan the entire invoices table.

Replace the single catch-all query with three dedicated queries, each
using a direct equality on a uniquely constrained column:

- GetInvoiceByHash:  WHERE hash = $1
- GetInvoiceByAddr:  WHERE payment_addr = $1  (new, covers AMP path)
- GetInvoiceBySetID: existing, unchanged

Update getInvoiceByRef to route to the appropriate query based on which
fields are present in the InvoiceRef. When both hash and payment address
are provided, we look up by hash and then verify the returned invoice's
payment address matches.

GetInvoice is now unused and removed from the SQLInvoiceQueries
interface.
2026-03-04 13:04:26 +01:00
ziggie 74f8f2d9e6 sqldb+payments: add payment_duplicates for legacy duplicate payments
Older LND versions could create multiple payments for the same hash.
We need to preserve those historical records during KV→SQL migration,
but they don’t fit the normal payment schema because we enforce a
unique payment hash constraint. Introduce a lean payment_duplicates
table to store only the essential fields (identifier, amount,
timestamps, settle/fail data).

This keeps the primary payment records stable and makes the migration
deterministic even when duplicate records lack attempt info. The table
is intentionally minimal and can be dropped after migration if no
duplicate payments exist.

For now there is no logic in place which allows the noderunner to
fetch duplicate payments after the migration.
2026-02-25 18:52:32 +01:00
ziggie 2596d34619 paymentsdb+sqldb: add migration related query
Add a migration specific query which allows to set the failure
reason when inserting a payment into the db.
2026-02-25 18:52:31 +01:00
ziggie 969b00e4a5 paymentsdb: implement FetchInFlightPayments for sql backend 2026-02-25 08:02:16 +01:00
ziggie ff12082452 paymentsdb: implement DeletePayments for sql backend 2026-02-25 08:02:16 +01:00
ziggie fd6796e561 multi: implement Fail method for sql backend 2026-02-25 08:02:15 +01:00
ziggie 510f6fb532 paymentsdb: implement InitPayment for sql backend 2026-02-25 08:02:09 +01:00
ziggie 0c96a2d722 sqldb+paymentsdb: add queries to insert all relavant data
In this commit we add all queries which we will need to insert
payment related data into the db.
2026-02-25 08:02:09 +01:00
ziggie 3012eb2ca0 paymentsdb: implement DeleteFailedAttempts for sql backend 2026-02-25 08:02:09 +01:00
ziggie 6faf68c5fa paymentsdb: add query to only fetch resolution type for HTLCs 2026-02-25 08:02:08 +01:00
ziggie bdea68bebf sqldb: add queries for deleting a payment and attempts 2026-02-25 08:02:08 +01:00
ziggie 18e7768837 multi: add relevant queries for QueryPayments implemenation 2026-02-25 08:02:04 +01:00
Olaoluwa Osuntokun 0b00c66231 Merge pull request #10601 from ziggie1984/invoice-filter-index-optimization
invoices/sql_store: replace catch-all FilterInvoices with targeted index-friendly queries
2026-02-24 16:34:27 -08:00
ziggie 9becdfa8a3 sqldb/sqlc: remove deprecated FilterInvoices query
All call sites have been migrated to the targeted replacement queries
in the previous commit. Remove FilterInvoices and its associated
params struct from the SQL source and regenerate.
2026-02-21 16:58:31 +01:00
ziggie 866efbd7fb sqldb/sqlc: add targeted invoice queries
The existing FilterInvoices query uses optional parameters via the
pattern `(col >= param OR param IS NULL)` for every filter. SQLite
cannot use indexes with this pattern because the OR prevents the query
planner from determining at plan time which rows satisfy the condition,
resulting in a full table scan regardless of the available indexes
(invoices_state_idx, invoices_settle_index_idx, and the primary-key
clustered index on id).

Additionally, the conditional ORDER BY:

  ORDER BY CASE WHEN reverse = FALSE ... THEN id ELSE NULL END ASC,
           CASE WHEN reverse = TRUE  ... THEN id ELSE NULL END DESC

prevents the planner from using the index ordering and forces an
explicit sort.

Add five focused replacements, each with a plain sargable predicate and
a direct ORDER BY so the planner can always choose an index scan:

  - FetchPendingInvoices:        WHERE state IN (0, 3)
  - FilterInvoicesBySettleIndex: WHERE settle_index >= $1
  - FilterInvoicesByAddIndex:    WHERE id >= $1
  - FilterInvoicesForward:       WHERE id >= $1 ... ORDER BY id ASC
  - FilterInvoicesReverse:       WHERE id <= $1 ... ORDER BY id DESC

FilterInvoicesForward and FilterInvoicesReverse accept non-nullable
timestamp parameters (created_after, created_before) so the planner
always sees plain range predicates on created_at. Callers supply
Go-side defaults when no date filter is needed, following the same
convention already used by the payments query.

FilterInvoices is kept in this commit so all existing call sites
continue to compile. It will be removed once all callers have been
migrated.
2026-02-21 16:09:03 +01:00
Elle Mouton fc19a24d07 graph/db: version disabled channel IDs
Add a gossip version parameter to DisabledChannelIDs in the Store
interface and both implementations. Add a new version-filtered SQL
query and update the builder caller.
2026-02-20 09:19:23 +02:00
Elle Mouton a99604c7d7 sqldb/sqlc: add IsPublicV2Node query
Add SQL query to determine if a node has public v2 channels. Unlike
v1 which requires all four individual signatures, v2 channels are
considered public when the single aggregated signature is present.
2026-02-13 07:21:23 +02:00
Elle Mouton 315f5ed741 sqldb/sqlc: add AddV2ChannelProof query
Add SQL query to update the signature column for v2 channel auth proofs.
Unlike v1 which requires four separate signatures, v2 channels use a
single aggregated signature.
2026-02-13 07:21:23 +02:00
Elle Mouton 5a3c013e91 sqldb/sqlc: add NodeExists query 2026-02-13 07:21:20 +02:00
Elle Mouton 8349a6f84d sqldb: add UpsertSelfNode query
This query is less strict in terms of the latest update timestamp field.
We want to be less strict with our own node data since we always want
our own updates recorded.
2025-12-03 13:08:31 +02:00
Elle Mouton f2ed5564ef graph/db+sqldb: improve performance of chan update sql migration
This commit simplifies insertChanEdgePolicyMig. Much of the logic can be
removed given that this method is only used in the context of the graph
SQL migration.

This should improve the performance of the migration quite a lot since
it removes the extra GetChannelAndNodesBySCID call.
2025-09-01 08:07:57 +02:00
Elle Mouton 22bf88e900 graph/db+sqldb: make policy migration idempotent
Finally, we make the channel-policy part of the SQL migration idempotent
by adding a migration-only policy insert query which will not error out
if the policy already exists and does not have a timestamp that is newer
than the existing records timestamp. To keep the commit simple, a
insertChanEdgePolicyMig function is added which is basically identical
to the updateChanEdgePolicy function except for the fact that it uses
the newly added query. In the next commit, it will be simplified even
more.
2025-09-01 08:06:12 +02:00
Elle Mouton 8736fcafa8 graph/db+sqldb: make channel SQL mig retry-safe
In this commit, we make the channel part of the graph SQL migration
idempotent (retry-safe!). We do this by adding a migration-only channel
insert query that will not error out if a the query is called and a
chanenl with the given scid&version already exists. We also ensure that
errors are not thrown if existing channel features & extra types are
re-added.
2025-09-01 08:05:21 +02:00
Elle Mouton a291d6f1a6 graph/db+sqldb: improve efficiency of node migration
There is no need to use the "collect-then-update" pattern for node
insertion during the SQL migration since if we do have any previously
persisted data for the node and happen to re-run the insertion for that
node, the data will be exactly the same. So we can make use of "On
conflict, no nothing" here too.
2025-09-01 08:02:38 +02:00
Elle Mouton ddea6d59ce graph/db+sqldb: make node migration idempotent
In this commit, the graph SQL migration is updated so that the node
migration step is retry-safe. This is done by using migration specific
logic & queries that do not use the same node-update-constraint as the
normal node upsert logic. For normal "run-time" logic, we always expect
a node update to have a newer timestamp than any previously stored one.
But for the migration, we will only ever be dealing with a single
announcement for a given node & to make things retry-safe, we dont want
the query to error if we re-insert the exact same node.
2025-09-01 07:56:34 +02:00
Elle Mouton 5b06474744 graph/db+sqldb: batch validation for zombie index migration
Finally, we update the migrateZombieIndex function to use batch
validation just like was done in the previous commits. Here, we
additionally make sure to validate the entire zombie index entry and not
just the SCID.
2025-08-14 08:00:07 +02:00
Elle Mouton a490e03479 graph/db+sqldb: use batch validation for closed SCID migration
As was done in the previous commits for nodes & channels, we update the
migrateClosedSCIDIndex function here so that it validates migrated
entries in batches rather than one-by-one.
2025-08-14 08:00:06 +02:00
Elle Mouton 8554f17b3f graph/db+sqldb: validate prune log migration using batching
As was done in the previous commits for nodes & channels, we update the
migratePruneLog function here so that it validates migrated entries in
batches rather than one-by-one.
2025-08-14 08:00:06 +02:00
Elle Mouton 81c54611c1 graph/db+sqldb: use batch fetching during channel&policy migration
Restructue the `migrateChannelsAndPolicies` function so that it does the
validation of migrated channels and policies in batches. So instead of
fetching channel and its policies individually after migrating it, we
wait for a minimum batch size to be reached and then validate a batch of
them together. This lets us make way fewer DB round trips.
2025-08-14 08:00:06 +02:00
Elle Mouton 03ef2740a6 graph/db+sqldb: use batch validation for node migration
Restructue the `migrateNodes` function so that it does the validation of
migrated nodes in batches. So instead of fetching each node individually
after migrating it, we wait for a minimum batch size to be reached and
then validate a batch of nodes together. This lets us make way fewer DB
round trips.
2025-08-14 08:00:06 +02:00
Elle Mouton 3b60d33ac8 sqlc: add ListChannelsForNodeIDs batch query
Add a ListChannelsForNodeIDs query which will let us fetch all channels
belonging to a set of nodes.
2025-08-05 08:00:19 +02:00
Elle Mouton f39edae6e3 graph/db: use new batch helpers for edge loading
Use the new batch helpers to replace the existing logic for loading an
edge.
2025-07-31 07:19:14 +02:00
Elle Mouton 8ad5f633bc sqldb: add channel data batch queries
Also add the calling logic for these queries. This logic is not yet
used.
2025-07-31 07:19:14 +02:00
Elle Mouton 0dc0d320f8 graph/db+sqldb: queries and logic for batch fetching node data
In this commit, we add the queries that will be needed to batch-fetch
the data of a set of nodes. The logic for using these new queries is
also added but not used yet.
2025-07-30 19:29:21 +02:00
Elle Mouton 5a1184c664 graph/db+sqldb: remove LEFT JOIN for fetching node addresses
In this commit, we remove the LEFT JOIN query that was used for fetching
a nodes addresses. The reason it was used before was to ensure that we'd
get an empty address list if the node did exist but had no addresses.
This was for the purposes of the `AddrsForNode` method since it needs to
return false/true to indicate if the given node exists.
2025-07-30 18:11:01 +02:00
Elle Mouton 43db6683d2 graph/db+sqldb: only fetch what is needed for graph cache
Add a ListChannelsWithPoliciesForCachePaginated query that only fetches
the channel/policy fields that the cache requires.
2025-07-30 18:11:01 +02:00
Elle Mouton ddc0e95eda graph/db+sqldb: delete channels in batches
Use the new `SLICES` directive to add a DeleteChannels query which takes
a set of DB channel IDs. Then replace all our calls to DeleteChannel
with a paginated call to DeleteChannels.
2025-07-22 17:17:23 +02:00
Elle Mouton e269d57ffa sqldb+graph/db: use pagination for FetchChanInfos 2025-07-22 17:17:11 +02:00
Elle Mouton 88e9a21d63 sqldb+graph/db: update FilterKnownChanIDs to use pagination
Remove a TODO by making use of the new sqldb.ExecutePagedQuery to fetch
channels in batches rather than one by one.
2025-07-22 17:16:59 +02:00
Elle Mouton f72c48b283 graph/db+sqldb: pass set of outpoints to SQL
This commit adds a new GetChannelsByOutpoints query which takes a slice
of outpoint strings. This lets us then update PruneGraph to use
paginated calls to GetChannelsByOutpoints instead of making one DB call
per outpoint.
2025-07-22 17:16:49 +02:00
Elle Mouton f0d2d1fd0a sqldb: demonstrate the use of ExecutePagedQuery
Here, a new query (GetChannelsByOutpoints) is added which makes use of
the /*SLICE:outpoints*/ directive & added workaround. This is then used
in a test to demonstrate how the ExecutePagedQuery helper can be used to
wrap a query like this such that calls are done in pages.

The query that has been added will also be used by live code paths in an
upcoming commit.
2025-07-22 17:16:38 +02:00
Elle Mouton 74b70a5108 sqldb+graph/db: prefix graph SQL objects with "graph_"
This makes it more clear what each table is for especially when viewed
with other invoice/payments tables.
2025-07-15 18:40:16 +02:00
Elle Mouton 03ede9ccef graph/db: migrate prune log
This commit expands the `MigrateGraphToSQL` to include migration of the
prune log.
2025-07-11 09:15:47 +02:00
Elle Mouton f1b7ccc6b2 sqldb+graph/db: prune graph nodes in a single query
Update the pruneGraphNodes routine to prune the graph nodes in a single
query instead of two.
2025-06-30 18:41:28 +02:00
Elle Mouton 933ab3c6b7 graph/db+sqldb: impl PutClosedScid and IsClosedScid 2025-06-25 13:26:52 +02:00
Elle Mouton d46552f5ad graph/db+sqldb: implement AddEdgeProof
And run `TestAddEdgeProof` against the SQL backends.
2025-06-25 13:26:51 +02:00
Elle Mouton e875183c4f sqldb+graph/db: impl DisconnectBlockAtHeight
Which lets us run `TestDisconnectBlockAtHeight` and
`TestStressTestChannelGraphAPI` against our SQL backends.
2025-06-25 11:22:03 +02:00
Elle Mouton 9dd0361ed0 graph/db+sqldb: impl PruneGraph, PruneTip, ChannelView
Which lets us run `TestGraphPruning` and `TestBatchedAddChannelEdge`
against our SQL backends.
2025-06-25 11:22:00 +02:00