Skip to content

sqldb: move native SQL payments migrations into mainline#10627

Open
ziggie1984 wants to merge 12 commits intolightningnetwork:masterfrom
ziggie1984:promote-payments-migrations
Open

sqldb: move native SQL payments migrations into mainline#10627
ziggie1984 wants to merge 12 commits intolightningnetwork:masterfrom
ziggie1984:promote-payments-migrations

Conversation

@ziggie1984
Copy link
Collaborator

@ziggie1984 ziggie1984 commented Mar 4, 2026

This PR is based on #10535.

Moves the native SQL payments schema migrations from the dev/test-only
migrations_dev.go into the mainline migrationConfig, making them
available in production builds.

When this PR is merged this can be closed: #9861

The invoice tombstone acts as a system wide kv db tombstone so
there is no need for a specific payment tombstone. Moreover a
TODO is added to redesign the current setting of the invoice
tombstone because it is also fragile to crashes after
the tombstone is set and the sql transaction of the migration
fails to commit.

Additionally the missing cleanup calls are added in case we return
early because of an error.
During route retrieval don't query for the channel capacity. We
default to the static incomingAmt of the route. That was already
done previously when the channel was closed or private. The
channel capacity has been deprecated for quite a while so it is
acceptable to avoid the performance hit querying the graph db.

In the next release this field will be removed.
The previous commit stopped setting the channel capacity when
retrieving the route. This commit makes sure that in the next
release we remove the entries from the rpc interface.
Since migration 10 is already merged into master it cannot be edited.
Add a new migration (000013_payments_index_improvements) that carries
forward two index improvements:

 - Drop idx_htlc_attempt_index on payment_htlc_attempts(attempt_index)
   and idx_route_hops_htlc_attempt_index on
   payment_route_hops(htlc_attempt_index). Both are redundant with
   existing UNIQUE constraints and only add write/maintenance overhead.

 - Add idx_htlc_payment_id_attempt_time on
   payment_htlc_attempts(payment_id, attempt_time) to optimise batched
   attempt reads that filter by payment_id and order by attempt_time
   (FetchHtlcAttemptsForPayments).

 - Add idx_htlc_resolutions_type_attempt_index on
   payment_htlc_attempt_resolutions(resolution_type, attempt_index) to
   optimise the failed-attempt cleanup path that filters by
   resolution_type before joining on attempt_index
   (DeleteFailedAttempts).
Add a new omit_hops field to ListPaymentsRequest that allows clients
to skip loading hop-level route data for HTLC attempts, reducing both
query cost and response size. When set, the route is returned with
only route-level fields (TotalTimeLock, TotalAmount, SourcePubKey)
and no individual hop data or hop-level custom records.
The previous query used an IN subquery that scanned all failed
resolutions across all payments (O(N) where N = total failed attempts
globally). Replace with a correlated EXISTS subquery that only checks
resolutions for the specific payment's attempts, making it O(k) where
k = attempts for this payment (typically 1-5).
fixes it for the orignal file and the code migration package where
the code was just copied over.
Before this change the migration progress log only showed absolute counts
and a cumulative average rate. This adds two improvements:

- A cheap pre-count pass over the payments index bucket before migration
  starts, giving an upper-bound estimate of the total entries to migrate
  (noted as approximate since duplicates are also indexed). This allows
  showing a percentage complete on each progress line.

- A rolling 30s window rate for the ETA calculation instead of the
  cumulative average rate. The cumulative rate is slow to react when
  throughput changes mid-migration; the rolling window makes the ETA
  responsive to recent conditions. On window reset the previous window's
  rate is used as a fallback for one tick to avoid a gap in the ETA.

Example progress line after this change:

  Progress: 500000 payments (~48.5%), 499860 attempts | Rate: 399.2
  pmt/s | Elapsed: 20m50s | ETA: ~22m8s
Replace direct `err != sql.ErrNoRows` comparison with `errors.Is` and
extract the repeated fetch-and-check logic into a helper to reduce
duplication across the sequential and concurrent benchmarks.
The native SQL payments migrations were previously gated behind test
build tags in migrations_dev.go. This commit promotes them into the
main migration sequence in migrations.go, making them available in
production builds.

The following migrations are moved to mainline:
- 000010_payments (v12): initial payments SQL schema
- 000011_payment_duplicates (v13): duplicate payment support
- kv_payments_migration (v14): optional KV to SQL payment migration
- 000012_drop_redundant_invoice_indexes (v15): index cleanup
- 000013_payments_index_improvements (v16): payment index optimizations
@gemini-code-assist
Copy link

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request integrates the native SQL payments schema migrations into the core application, enabling their use in production builds. It also introduces a new omit_hops option for the ListPayments RPC, allowing users to reduce response size and query overhead by excluding detailed hop information. Complementing these changes are various performance enhancements to the SQL payment store, including improved indexing and query efficiency, and a refined migration progress reporting mechanism. The removal of the dedicated payments bucket tombstone streamlines the database management logic.

Highlights

  • Mainline SQL Payments Migrations: The native SQL payments schema migrations, previously restricted to dev/test builds, have been moved into the mainline migrationConfig, making them available for production environments.
  • omit_hops Flag for ListPayments: A new omit_hops boolean flag has been added to the ListPayments RPC. When set, this flag reduces query cost and response size by omitting hop-level route data for HTLC attempts.
  • SQL Payment Store Optimizations: Several improvements have been made to the SQL payment store, including optimized schema indexes, enhanced query performance for payment filtering and failed attempt cleanup, and fixes for cross-database timestamp handling.
  • Migration Progress Reporting: The KV to SQL payment migration now includes a more robust progress reporter with rolling-window ETA calculation.
  • Removal of Payments Bucket Tombstone: The logic and file (payments/db/kv_tombstone.go) related to the payments bucket tombstone have been removed, as the invoice bucket tombstone now serves as the system-wide guard against switching back to KV mode.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • cmd/commands/cmd_payments.go
    • Added omit_hops boolean flag to the listPaymentsCommand CLI.
    • Passed the omit_hops flag value to the ListPayments client request.
  • config_builder.go
    • Added a TODO comment regarding the fragility of the invoice bucket tombstone setting within SQL transaction callbacks.
    • Removed the logic for setting and checking the payments bucket tombstone.
    • Added cleanUp() calls to error paths when getting graph and payments stores, and when checking the invoice bucket tombstone.
  • docs/release-notes/release-notes-0.21.0.md
    • Added a deprecation warning for lnrpc.Hop fields (chan_capacity, amt_to_forward, fee).
    • Included a summary of SQL payment store improvements from PR improve speed of retrieval of payments #10535, such as index optimization, query performance, timestamp handling, omit_hops option, and SQLite cache size increase.
  • lnrpc/lightning.proto
    • Added omit_hops boolean field to the ListPaymentsRequest message.
  • lnrpc/lightning.swagger.json
    • Added omit_hops boolean parameter to the ListPayments endpoint definition.
  • lnrpc/routerrpc/router_backend.go
    • Simplified chanCapacity calculation to avoid per-hop graph lookups, using incomingAmt as an approximation.
    • Removed an unused incomingAmt assignment.
  • payments/db/kv_duplicate_payments.go
    • Corrected a string literal in an error message.
  • payments/db/kv_tombstone.go
    • Removed the entire file, which contained functions for setting and getting the payments bucket tombstone.
  • payments/db/migration1/kv_duplicate_payments.go
    • Corrected a string literal in an error message.
  • payments/db/migration1/sql_migration.go
    • Introduced migrationProgressReporter struct and report() method for rolling-window ETA progress reporting during migration.
    • Refactored MigratePaymentsKVToSQL to use the new progress reporter and moved the core migration logic for a single index entry into a new migrateIndexEntry function.
    • Removed redundant validation progress logging.
  • payments/db/migration1/sql_store.go
    • Updated a comment for NewSQLStore to reflect a more general BatchedSQLQueries backend.
  • payments/db/query.go
    • Added OmitHops boolean field to the Query struct.
  • payments/db/sql_converters.go
    • Modified dbAttemptToHTLCAttempt to accept an includeHops boolean parameter, conditionally processing route-level custom records.
    • Modified dbDataToRoute to accept an allowEmpty boolean parameter, allowing a minimal route to be returned if no hops are provided and allowEmpty is true.
  • payments/db/sql_converters_test.go
    • Added a new test file containing TestOmitHopsRouteBuilding, TestOmitHopsAttemptConversion, and TestOmitHopsBuildPayment to verify the omit_hops functionality.
  • payments/db/sql_store.go
    • Updated NewSQLStore comment.
    • Modified fetchPaymentWithCompleteData, batchLoadPayments, batchLoadPaymentDetailsData, buildPaymentFromBatchData, QueryPayments, and FetchInFlightPayments to pass and utilize the includeHops parameter, conditionally loading and building hop-related data.
    • batchLoadPaymentDetailsData now conditionally loads hops, hop custom records, and route custom records based on includeHops.
  • rpcserver.go
    • Mapped the new OmitHops field from ListPaymentsRequest to the internal payments.Query struct.
  • sqldb/migrations.go
    • Moved payment-related migrations (000010_payments, 000011_payment_duplicates, kv_payments_migration, 000012_drop_redundant_invoice_indexes, 000013_payments_index_improvements) from migrations_dev.go into the main migrationConfig slice.
  • sqldb/migrations_dev.go
    • Emptied the migrationAdditions slice, indicating that all migrations are now in mainline.
  • sqldb/sqlc/migrations/000013_payments_index_improvements.down.sql
    • Added SQL to restore dropped indexes and remove new composite indexes.
  • sqldb/sqlc/migrations/000013_payments_index_improvements.up.sql
    • Added SQL to drop redundant indexes (idx_htlc_attempt_index, idx_route_hops_htlc_attempt_index) and create new composite indexes (idx_htlc_payment_id_attempt_time, idx_htlc_resolutions_type_attempt_index) for payment query optimization.
  • sqldb/sqlc/payments.sql.go
    • Updated the DeleteFailedAttempts SQL query to use an EXISTS clause instead of IN for better performance, along with an updated comment.
  • sqldb/sqlc/querier.go
    • Updated the comment for DeleteFailedAttempts to reflect the improved query performance.
  • sqldb/sqlc/queries/payments.sql
    • Modified the DeleteFailedAttempts SQL query to use EXISTS for improved performance and updated its comment.
  • sqldb/sqlite_bench_test.go
    • Extracted invoice fetching logic into a helper function getInvoiceByHashForBench to reduce code duplication in benchmarks.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@ziggie1984 ziggie1984 added the sql label Mar 4, 2026
@ziggie1984 ziggie1984 added this to v0.21 Mar 4, 2026
@ziggie1984 ziggie1984 added this to the v0.21.0 milestone Mar 4, 2026
@ziggie1984 ziggie1984 self-assigned this Mar 4, 2026
@ziggie1984 ziggie1984 added the payments Related to invoices/payments label Mar 4, 2026
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request moves the native SQL payments schema migrations into the mainline, making them available in production builds. It also includes several related improvements, such as adding an omit_hops flag to the listpayments command for better performance, optimizing SQL queries, and improving migration progress reporting. The changes are well-structured and consistent across the codebase. I have one suggestion to improve a comment for clarity.

Note: Security Review did not run due to the size of the PR.

Comment on lines +658 to +661
// Avoid per-hop graph lookups by using the incoming amount as a
// lower bound for the capacity. This is not the actual channel
// capacity, but it is a reasonable approximation that avoids
// slow graph lookups and works for closed/private channels too.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The comment states that the incoming amount is used as a lower bound for the capacity. However, the incomingAmt variable is initialized to route.TotalAmount before the loop and is no longer updated within it. This means the total route amount is used for every hop, not the specific incoming amount for that hop. To avoid confusion, I suggest clarifying in the comment that the total route amount is being used.

Suggested change
// Avoid per-hop graph lookups by using the incoming amount as a
// lower bound for the capacity. This is not the actual channel
// capacity, but it is a reasonable approximation that avoids
// slow graph lookups and works for closed/private channels too.
// Avoid per-hop graph lookups by using the total route amount as a
// lower bound for the capacity. This is not the actual channel
// capacity, but it is a reasonable approximation that avoids
// slow graph lookups and works for closed/private channels too.

@saubyk saubyk moved this to In progress in v0.21 Mar 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

payments Related to invoices/payments sql

Projects

Status: In progress

Development

Successfully merging this pull request may close these issues.

[epic]: payment db: SQL implementation & migration

1 participant