Skip to content
Merged
3 changes: 3 additions & 0 deletions docs/release-notes/release-notes-0.21.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@
functions](https://github.com/lightningnetwork/lnd/pull/10368)
* Finalize SQL payments implementation [enabling unit and itests
for SQL backend](https://github.com/lightningnetwork/lnd/pull/10292)
* [Thread context through payment
db functions Part 1](https://github.com/lightningnetwork/lnd/pull/10307)


## Code Health

Expand Down
26 changes: 16 additions & 10 deletions payments/db/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,24 @@ type PaymentReader interface {

// FetchPayment fetches the payment corresponding to the given payment
// hash.
FetchPayment(paymentHash lntypes.Hash) (*MPPayment, error)
FetchPayment(ctx context.Context,
paymentHash lntypes.Hash) (*MPPayment, error)

// FetchInFlightPayments returns all payments with status InFlight.
FetchInFlightPayments() ([]*MPPayment, error)
FetchInFlightPayments(ctx context.Context) ([]*MPPayment, error)
}

// PaymentWriter represents the interface to write operations to the payments
// database.
type PaymentWriter interface {
// DeletePayment deletes a payment from the DB given its payment hash.
DeletePayment(paymentHash lntypes.Hash, failedAttemptsOnly bool) error
DeletePayment(ctx context.Context, paymentHash lntypes.Hash,
failedAttemptsOnly bool) error

// DeletePayments deletes all payments from the DB given the specified
// flags.
DeletePayments(failedOnly, failedAttemptsOnly bool) (int, error)
DeletePayments(ctx context.Context, failedOnly,
failedAttemptsOnly bool) (int, error)

PaymentControl
}
Expand All @@ -58,7 +61,7 @@ type PaymentControl interface {
// exists in the database before creating a new payment. However, it
// should allow the user making a subsequent payment if the payment is
// in a Failed state.
InitPayment(lntypes.Hash, *PaymentCreationInfo) error
InitPayment(context.Context, lntypes.Hash, *PaymentCreationInfo) error

// RegisterAttempt atomically records the provided HTLCAttemptInfo.
//
Expand All @@ -72,7 +75,8 @@ type PaymentControl interface {
// - Result: 1700 sats sent, exceeding the payment amount
// The payment router/controller layer is responsible for ensuring
// serialized access per payment hash.
RegisterAttempt(lntypes.Hash, *HTLCAttemptInfo) (*MPPayment, error)
RegisterAttempt(context.Context, lntypes.Hash,
*HTLCAttemptInfo) (*MPPayment, error)

// SettleAttempt marks the given attempt settled with the preimage. If
// this is a multi shard payment, this might implicitly mean the
Expand All @@ -82,23 +86,25 @@ type PaymentControl interface {
// error to prevent us from making duplicate payments to the same
// payment hash. The provided preimage is atomically saved to the DB
// for record keeping.
SettleAttempt(lntypes.Hash, uint64, *HTLCSettleInfo) (*MPPayment, error)
SettleAttempt(context.Context, lntypes.Hash, uint64,
*HTLCSettleInfo) (*MPPayment, error)

// FailAttempt marks the given payment attempt failed.
FailAttempt(lntypes.Hash, uint64, *HTLCFailInfo) (*MPPayment, error)
FailAttempt(context.Context, lntypes.Hash, uint64,
*HTLCFailInfo) (*MPPayment, error)

// Fail transitions a payment into the Failed state, and records
// the ultimate reason the payment failed. Note that this should only
// be called when all active attempts are already failed. After
// invoking this method, InitPayment should return nil on its next call
// for this payment hash, allowing the user to make a subsequent
// payment.
Fail(lntypes.Hash, FailureReason) (*MPPayment, error)
Fail(context.Context, lntypes.Hash, FailureReason) (*MPPayment, error)

// DeleteFailedAttempts removes all failed HTLCs from the db. It should
// be called for a given payment whenever all inflight htlcs are
// completed, and the payment has reached a final terminal state.
DeleteFailedAttempts(lntypes.Hash) error
DeleteFailedAttempts(context.Context, lntypes.Hash) error
}

// DBMPPayment is an interface that represents the payment state during a
Expand Down
28 changes: 16 additions & 12 deletions payments/db/kv_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ func initKVStore(db kvdb.Backend) error {
// making sure it does not already exist as an in-flight payment. When this
// method returns successfully, the payment is guaranteed to be in the InFlight
// state.
func (p *KVStore) InitPayment(paymentHash lntypes.Hash,
func (p *KVStore) InitPayment(_ context.Context, paymentHash lntypes.Hash,
info *PaymentCreationInfo) error {

// Obtain a new sequence number for this payment. This is used
Expand Down Expand Up @@ -290,12 +290,14 @@ func (p *KVStore) InitPayment(paymentHash lntypes.Hash,

// DeleteFailedAttempts deletes all failed htlcs for a payment if configured
// by the KVStore db.
func (p *KVStore) DeleteFailedAttempts(hash lntypes.Hash) error {
func (p *KVStore) DeleteFailedAttempts(ctx context.Context,
hash lntypes.Hash) error {

// TODO(ziggie): Refactor to not mix application logic with database
// logic. This decision should be made in the application layer.
if !p.keepFailedPaymentAttempts {
const failedHtlcsOnly = true
err := p.DeletePayment(hash, failedHtlcsOnly)
err := p.DeletePayment(ctx, hash, failedHtlcsOnly)
if err != nil {
return err
}
Expand Down Expand Up @@ -359,7 +361,7 @@ func deserializePaymentIndex(r io.Reader) (lntypes.Hash, error) {

// RegisterAttempt atomically records the provided HTLCAttemptInfo to the
// DB.
func (p *KVStore) RegisterAttempt(paymentHash lntypes.Hash,
func (p *KVStore) RegisterAttempt(_ context.Context, paymentHash lntypes.Hash,
attempt *HTLCAttemptInfo) (*MPPayment, error) {

// Serialize the information before opening the db transaction.
Expand Down Expand Up @@ -430,7 +432,7 @@ func (p *KVStore) RegisterAttempt(paymentHash lntypes.Hash,
// After invoking this method, InitPayment should always return an error to
// prevent us from making duplicate payments to the same payment hash. The
// provided preimage is atomically saved to the DB for record keeping.
func (p *KVStore) SettleAttempt(hash lntypes.Hash,
func (p *KVStore) SettleAttempt(_ context.Context, hash lntypes.Hash,
attemptID uint64, settleInfo *HTLCSettleInfo) (*MPPayment, error) {

var b bytes.Buffer
Expand All @@ -443,7 +445,7 @@ func (p *KVStore) SettleAttempt(hash lntypes.Hash,
}

// FailAttempt marks the given payment attempt failed.
func (p *KVStore) FailAttempt(hash lntypes.Hash,
func (p *KVStore) FailAttempt(_ context.Context, hash lntypes.Hash,
attemptID uint64, failInfo *HTLCFailInfo) (*MPPayment, error) {

var b bytes.Buffer
Expand Down Expand Up @@ -528,7 +530,7 @@ func (p *KVStore) updateHtlcKey(paymentHash lntypes.Hash,
// payment failed. After invoking this method, InitPayment should return nil on
// its next call for this payment hash, allowing the switch to make a
// subsequent payment.
func (p *KVStore) Fail(paymentHash lntypes.Hash,
func (p *KVStore) Fail(_ context.Context, paymentHash lntypes.Hash,
reason FailureReason) (*MPPayment, error) {

var (
Expand Down Expand Up @@ -585,8 +587,8 @@ func (p *KVStore) Fail(paymentHash lntypes.Hash,
}

// FetchPayment returns information about a payment from the database.
func (p *KVStore) FetchPayment(paymentHash lntypes.Hash) (
*MPPayment, error) {
func (p *KVStore) FetchPayment(_ context.Context,
paymentHash lntypes.Hash) (*MPPayment, error) {

var payment *MPPayment
err := kvdb.View(p.db, func(tx kvdb.RTx) error {
Expand Down Expand Up @@ -741,7 +743,9 @@ func fetchPaymentStatus(bucket kvdb.RBucket) (PaymentStatus, error) {
}

// FetchInFlightPayments returns all payments with status InFlight.
func (p *KVStore) FetchInFlightPayments() ([]*MPPayment, error) {
func (p *KVStore) FetchInFlightPayments(_ context.Context) ([]*MPPayment,
error) {

var (
inFlights []*MPPayment
start = time.Now()
Expand Down Expand Up @@ -1275,7 +1279,7 @@ func fetchPaymentWithSequenceNumber(tx kvdb.RTx, paymentHash lntypes.Hash,
// DeletePayment deletes a payment from the DB given its payment hash. If
// failedHtlcsOnly is set, only failed HTLC attempts of the payment will be
// deleted.
func (p *KVStore) DeletePayment(paymentHash lntypes.Hash,
func (p *KVStore) DeletePayment(_ context.Context, paymentHash lntypes.Hash,
failedHtlcsOnly bool) error {

return kvdb.Update(p.db, func(tx kvdb.RwTx) error {
Expand Down Expand Up @@ -1372,7 +1376,7 @@ func (p *KVStore) DeletePayment(paymentHash lntypes.Hash,
// failedHtlcsOnly is set, the payment itself won't be deleted, only failed HTLC
// attempts. The method returns the number of deleted payments, which is always
// 0 if failedHtlcsOnly is set.
func (p *KVStore) DeletePayments(failedOnly,
func (p *KVStore) DeletePayments(_ context.Context, failedOnly,
failedHtlcsOnly bool) (int, error) {

var numPayments int
Expand Down
32 changes: 18 additions & 14 deletions payments/db/kv_store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import (
func TestKVStoreDeleteNonInFlight(t *testing.T) {
t.Parallel()

ctx := t.Context()

paymentDB := NewKVTestDB(t)

// Create a sequence number for duplicate payments that will not collide
Expand Down Expand Up @@ -78,12 +80,12 @@ func TestKVStoreDeleteNonInFlight(t *testing.T) {
require.NoError(t, err)

// Sends base htlc message which initiate StatusInFlight.
err = paymentDB.InitPayment(info.PaymentIdentifier, info)
err = paymentDB.InitPayment(ctx, info.PaymentIdentifier, info)
if err != nil {
t.Fatalf("unable to send htlc message: %v", err)
}
_, err = paymentDB.RegisterAttempt(
info.PaymentIdentifier, attempt,
ctx, info.PaymentIdentifier, attempt,
)
if err != nil {
t.Fatalf("unable to send htlc message: %v", err)
Expand All @@ -98,7 +100,7 @@ func TestKVStoreDeleteNonInFlight(t *testing.T) {
// Fail the payment attempt.
htlcFailure := HTLCFailUnreadable
_, err := paymentDB.FailAttempt(
info.PaymentIdentifier, attempt.AttemptID,
ctx, info.PaymentIdentifier, attempt.AttemptID,
&HTLCFailInfo{
Reason: htlcFailure,
},
Expand All @@ -110,7 +112,7 @@ func TestKVStoreDeleteNonInFlight(t *testing.T) {
// Fail the payment, which should moved it to Failed.
failReason := FailureReasonNoRoute
_, err = paymentDB.Fail(
info.PaymentIdentifier, failReason,
ctx, info.PaymentIdentifier, failReason,
)
if err != nil {
t.Fatalf("unable to fail payment hash: %v", err)
Expand All @@ -131,7 +133,7 @@ func TestKVStoreDeleteNonInFlight(t *testing.T) {
case p.success:
// Verifies that status was changed to StatusSucceeded.
_, err := paymentDB.SettleAttempt(
info.PaymentIdentifier, attempt.AttemptID,
ctx, info.PaymentIdentifier, attempt.AttemptID,
&HTLCSettleInfo{
Preimage: preimg,
},
Expand Down Expand Up @@ -180,7 +182,7 @@ func TestKVStoreDeleteNonInFlight(t *testing.T) {
}

// Delete all failed payments.
numPayments, err := paymentDB.DeletePayments(true, false)
numPayments, err := paymentDB.DeletePayments(ctx, true, false)
require.NoError(t, err)
require.EqualValues(t, 1, numPayments)

Expand Down Expand Up @@ -216,7 +218,7 @@ func TestKVStoreDeleteNonInFlight(t *testing.T) {
}

// Now delete all payments except in-flight.
numPayments, err = paymentDB.DeletePayments(false, false)
numPayments, err = paymentDB.DeletePayments(ctx, false, false)
require.NoError(t, err)
require.EqualValues(t, 2, numPayments)

Expand Down Expand Up @@ -407,19 +409,21 @@ func deletePayment(t *testing.T, db kvdb.Backend, paymentHash lntypes.Hash,
func TestFetchPaymentWithSequenceNumber(t *testing.T) {
paymentDB := NewKVTestDB(t)

ctx := t.Context()

// Generate a test payment which does not have duplicates.
noDuplicates, _, err := genInfo(t)
require.NoError(t, err)

// Create a new payment entry in the database.
err = paymentDB.InitPayment(
noDuplicates.PaymentIdentifier, noDuplicates,
ctx, noDuplicates.PaymentIdentifier, noDuplicates,
)
require.NoError(t, err)

// Fetch the payment so we can get its sequence nr.
noDuplicatesPayment, err := paymentDB.FetchPayment(
noDuplicates.PaymentIdentifier,
ctx, noDuplicates.PaymentIdentifier,
)
require.NoError(t, err)

Expand All @@ -429,13 +433,13 @@ func TestFetchPaymentWithSequenceNumber(t *testing.T) {

// Create a new payment entry in the database.
err = paymentDB.InitPayment(
hasDuplicates.PaymentIdentifier, hasDuplicates,
ctx, hasDuplicates.PaymentIdentifier, hasDuplicates,
)
require.NoError(t, err)

// Fetch the payment so we can get its sequence nr.
hasDuplicatesPayment, err := paymentDB.FetchPayment(
hasDuplicates.PaymentIdentifier,
ctx, hasDuplicates.PaymentIdentifier,
)
require.NoError(t, err)

Expand Down Expand Up @@ -740,14 +744,14 @@ func TestKVStoreQueryPaymentsDuplicates(t *testing.T) {

// Create a new payment entry in the database.
err = paymentDB.InitPayment(
info.PaymentIdentifier, info,
ctx, info.PaymentIdentifier, info,
)
require.NoError(t, err)

// Immediately delete the payment with index 2.
if i == 1 {
pmt, err := paymentDB.FetchPayment(
info.PaymentIdentifier,
ctx, info.PaymentIdentifier,
)
require.NoError(t, err)

Expand All @@ -764,7 +768,7 @@ func TestKVStoreQueryPaymentsDuplicates(t *testing.T) {
// duplicate payments will always be succeeded.
if i == (nonDuplicatePayments - 1) {
pmt, err := paymentDB.FetchPayment(
info.PaymentIdentifier,
ctx, info.PaymentIdentifier,
)
require.NoError(t, err)

Expand Down
Loading
Loading