paymentsdb: implement FetchPayment for sql backend
What changed, and why it matters
This commit adds a new database helper function that retrieves a single Lightning payment record from the new SQL-based storage backend. It is a routine feature implementation with no visible security bug.
No security action required; review as normal code-quality change.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch implements FetchPayment in payments/db/sql_store.go for the SQL backend. It opens a read transaction, calls db.FetchPayment by payment hash, maps sql.ErrNoRows to ErrPaymentNotInitiated, and otherwise delegates to s.fetchPaymentWithCompleteData to assemble the full MPPayment. No input validation, authorization, cryptographic, or concurrency flaws are evident in the diff.
Changed components
payments/db/sql_store.goInspect captured patch +43 / −0
diff --git a/payments/db/sql_store.go b/payments/db/sql_store.go
index b0ce408..1b7bfba 100644
--- a/payments/db/sql_store.go
+++ b/payments/db/sql_store.go
@@ -2,11 +2,13 @@ package paymentsdb
import (
"context"
+ "database/sql"
"errors"
"fmt"
"math"
"time"
+ "github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/sqldb"
"github.com/lightningnetwork/lnd/sqldb/sqlc"
@@ -652,3 +654,44 @@ func (s *SQLStore) QueryPayments(ctx context.Context, query Query) (Response,
TotalCount: uint64(totalCount),
}, nil
}
+
+// FetchPayment retrieves a complete payment record from the database by its
+// payment hash. The returned MPPayment includes all payment metadata such as
+// creation info, payment status, current state, all HTLC attempts (both
+// successful and failed), and the failure reason if the payment has been
+// marked as failed.
+//
+// Returns ErrPaymentNotInitiated if no payment with the given hash exists.
+//
+// This is part of the DB interface.
+func (s *SQLStore) FetchPayment(paymentHash lntypes.Hash) (*MPPayment, error) {
+ ctx := context.TODO()
+
+ var mpPayment *MPPayment
+
+ err := s.db.ExecTx(ctx, sqldb.ReadTxOpt(), func(db SQLQueries) error {
+ dbPayment, err := db.FetchPayment(ctx, paymentHash[:])
+ if err != nil && !errors.Is(err, sql.ErrNoRows) {
+ return fmt.Errorf("failed to fetch payment: %w", err)
+ }
+
+ if errors.Is(err, sql.ErrNoRows) {
+ return ErrPaymentNotInitiated
+ }
+
+ mpPayment, err = s.fetchPaymentWithCompleteData(
+ ctx, db, dbPayment,
+ )
+ if err != nil {
+ return fmt.Errorf("failed to fetch payment with "+
+ "complete data: %w", err)
+ }
+
+ return nil
+ }, sqldb.NoOpReset)
+ if err != nil {
+ return nil, err
+ }
+
+ return mpPayment, nil
+}
Why this scored 15/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.