Merge pull request #9844 from ziggie1984/refactor-payments-code-03

Refactor Payment PR 3
This commit is contained in:
Yong authored and GitHub committed 2025-08-13 06:05:01 -04:00
commit c6a9116e3a
20 files changed
+538 -350

No files matched your search

-2
View File
@@ -352,7 +352,6 @@ type DB struct {
dbPath string
clock clock.Clock
dryRun bool
keepFailedPaymentAttempts bool
storeFinalHtlcResolutions bool
// noRevLogAmtData if true, means that commitment transaction amount
@@ -413,7 +412,6 @@ func CreateWithBackend(backend kvdb.Backend, modifiers ...OptionModifier) (*DB,
},
clock: opts.clock,
dryRun: opts.dryRun,
keepFailedPaymentAttempts: opts.keepFailedPaymentAttempts,
storeFinalHtlcResolutions: opts.storeFinalHtlcResolutions,
noRevLogAmtData: opts.NoRevLogAmtData,
}
+2 -1
View File
@@ -11,6 +11,7 @@ import (
"github.com/lightningnetwork/lnd/kvdb"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwire"
paymentsdb "github.com/lightningnetwork/lnd/payments/db"
"github.com/lightningnetwork/lnd/routing/route"
)
@@ -74,7 +75,7 @@ func fetchDuplicatePaymentStatus(bucket kvdb.RBucket) (PaymentStatus, error) {
return StatusInFlight, nil
}
return 0, ErrPaymentNotInitiated
return 0, paymentsdb.ErrPaymentNotInitiated
}
func deserializeDuplicateHTLCAttemptInfo(r io.Reader) (
+17 -13
View File
@@ -15,6 +15,7 @@ import (
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnutils"
"github.com/lightningnetwork/lnd/lnwire"
paymentsdb "github.com/lightningnetwork/lnd/payments/db"
"github.com/lightningnetwork/lnd/routing/route"
)
@@ -349,12 +350,12 @@ func (m *MPPayment) Registrable() error {
// are settled HTLCs or the payment is failed. If we already have
// settled HTLCs, we won't allow adding more HTLCs.
if m.State.HasSettledHTLC {
return ErrPaymentPendingSettled
return paymentsdb.ErrPaymentPendingSettled
}
// If the payment is already failed, we won't allow adding more HTLCs.
if m.State.PaymentFailed {
return ErrPaymentPendingFailed
return paymentsdb.ErrPaymentPendingFailed
}
// Otherwise we can add more HTLCs.
@@ -371,8 +372,8 @@ func (m *MPPayment) setState() error {
// Sanity check we haven't sent a value larger than the payment amount.
totalAmt := m.Info.Value
if sentAmt > totalAmt {
return fmt.Errorf("%w: sent=%v, total=%v", ErrSentExceedsTotal,
sentAmt, totalAmt)
return fmt.Errorf("%w: sent=%v, total=%v",
paymentsdb.ErrSentExceedsTotal, sentAmt, totalAmt)
}
// Get any terminal info for this payment.
@@ -451,7 +452,7 @@ func (m *MPPayment) NeedWaitAttempts() (bool, error) {
case StatusSucceeded:
return false, fmt.Errorf("%w: parts of the payment "+
"already succeeded but still have remaining "+
"amount %v", ErrPaymentInternal,
"amount %v", paymentsdb.ErrPaymentInternal,
m.State.RemainingAmt)
// The payment is failed and we have no inflight HTLCs, no need
@@ -462,7 +463,7 @@ func (m *MPPayment) NeedWaitAttempts() (bool, error) {
// Unknown payment status.
default:
return false, fmt.Errorf("%w: %s",
ErrUnknownPaymentStatus, m.Status)
paymentsdb.ErrUnknownPaymentStatus, m.Status)
}
}
@@ -472,7 +473,8 @@ func (m *MPPayment) NeedWaitAttempts() (bool, error) {
// When the payment is newly created, yet the payment has no remaining
// amount, return an error.
case StatusInitiated:
return false, fmt.Errorf("%w: %v", ErrPaymentInternal, m.Status)
return false, fmt.Errorf("%w: %v",
paymentsdb.ErrPaymentInternal, m.Status)
// If the payment is inflight, we must wait.
//
@@ -493,12 +495,13 @@ func (m *MPPayment) NeedWaitAttempts() (bool, error) {
// marked as failed with a reason, which means the remainingAmt must
// not be zero because our sentAmt is zero.
case StatusFailed:
return false, fmt.Errorf("%w: %v", ErrPaymentInternal, m.Status)
return false, fmt.Errorf("%w: %v",
paymentsdb.ErrPaymentInternal, m.Status)
// Unknown payment status.
default:
return false, fmt.Errorf("%w: %s", ErrUnknownPaymentStatus,
m.Status)
return false, fmt.Errorf("%w: %s",
paymentsdb.ErrUnknownPaymentStatus, m.Status)
}
}
@@ -528,7 +531,8 @@ func (m *MPPayment) AllowMoreAttempts() (bool, error) {
// remainingAmt, return an error.
if m.Status == StatusInitiated {
return false, fmt.Errorf("%w: initiated payment has "+
"zero remainingAmt", ErrPaymentInternal)
"zero remainingAmt",
paymentsdb.ErrPaymentInternal)
}
// Otherwise, exit early since all other statuses with zero
@@ -544,8 +548,8 @@ func (m *MPPayment) AllowMoreAttempts() (bool, error) {
// as the preimage is received. In this case, return an error state.
if m.Status == StatusSucceeded {
return false, fmt.Errorf("%w: payment already succeeded but "+
"still have remaining amount %v", ErrPaymentInternal,
m.State.RemainingAmt)
"still have remaining amount %v",
paymentsdb.ErrPaymentInternal, m.State.RemainingAmt)
}
// Now check if we can register a new HTLC.
+15 -14
View File
@@ -8,6 +8,7 @@ import (
"github.com/btcsuite/btcd/btcec/v2"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwire"
paymentsdb "github.com/lightningnetwork/lnd/payments/db"
"github.com/lightningnetwork/lnd/routing/route"
"github.com/stretchr/testify/require"
)
@@ -65,35 +66,35 @@ func TestRegistrable(t *testing.T) {
// Test inflight status with settled HTLC but no failed
// payment.
status: StatusInFlight,
registryErr: ErrPaymentPendingSettled,
registryErr: paymentsdb.ErrPaymentPendingSettled,
hasSettledHTLC: true,
},
{
// Test inflight status with no settled HTLC but failed
// payment.
status: StatusInFlight,
registryErr: ErrPaymentPendingFailed,
registryErr: paymentsdb.ErrPaymentPendingFailed,
paymentFailed: true,
},
{
// Test error state with settled HTLC and failed
// payment.
status: 0,
registryErr: ErrUnknownPaymentStatus,
registryErr: paymentsdb.ErrUnknownPaymentStatus,
hasSettledHTLC: true,
paymentFailed: true,
},
{
status: StatusSucceeded,
registryErr: ErrPaymentAlreadySucceeded,
registryErr: paymentsdb.ErrPaymentAlreadySucceeded,
},
{
status: StatusFailed,
registryErr: ErrPaymentAlreadyFailed,
registryErr: paymentsdb.ErrPaymentAlreadyFailed,
},
{
status: 0,
registryErr: ErrUnknownPaymentStatus,
registryErr: paymentsdb.ErrUnknownPaymentStatus,
},
}
@@ -149,7 +150,7 @@ func TestPaymentSetState(t *testing.T) {
},
},
totalAmt: 1,
errExpected: ErrSentExceedsTotal,
errExpected: paymentsdb.ErrSentExceedsTotal,
},
{
// Test that when the htlc is failed, the fee is not
@@ -294,7 +295,7 @@ func TestNeedWaitAttempts(t *testing.T) {
status: StatusSucceeded,
remainingAmt: 1000,
needWait: false,
expectedErr: ErrPaymentInternal,
expectedErr: paymentsdb.ErrPaymentInternal,
},
{
// Payment is in terminal state, no need to wait.
@@ -309,7 +310,7 @@ func TestNeedWaitAttempts(t *testing.T) {
status: StatusInitiated,
remainingAmt: 0,
needWait: false,
expectedErr: ErrPaymentInternal,
expectedErr: paymentsdb.ErrPaymentInternal,
},
{
// With zero remainingAmt we must wait for the results.
@@ -330,21 +331,21 @@ func TestNeedWaitAttempts(t *testing.T) {
status: StatusFailed,
remainingAmt: 0,
needWait: false,
expectedErr: ErrPaymentInternal,
expectedErr: paymentsdb.ErrPaymentInternal,
},
{
// Payment is in an unknown status, return an error.
status: 0,
remainingAmt: 0,
needWait: false,
expectedErr: ErrUnknownPaymentStatus,
expectedErr: paymentsdb.ErrUnknownPaymentStatus,
},
{
// Payment is in an unknown status, return an error.
status: 0,
remainingAmt: 1000,
needWait: false,
expectedErr: ErrUnknownPaymentStatus,
expectedErr: paymentsdb.ErrUnknownPaymentStatus,
},
}
@@ -397,7 +398,7 @@ func TestAllowMoreAttempts(t *testing.T) {
status: StatusInitiated,
remainingAmt: 0,
allowMore: false,
expectedErr: ErrPaymentInternal,
expectedErr: paymentsdb.ErrPaymentInternal,
},
{
// With zero remainingAmt we don't allow more HTLC
@@ -505,7 +506,7 @@ func TestAllowMoreAttempts(t *testing.T) {
remainingAmt: 1000,
hasSettledHTLC: true,
allowMore: false,
expectedErr: ErrPaymentInternal,
expectedErr: paymentsdb.ErrPaymentInternal,
},
{
// With the payment failed with no inflight HTLCs, we
-12
View File
@@ -68,10 +68,6 @@ type Options struct {
// database if set to true.
dryRun bool
// keepFailedPaymentAttempts determines whether failed htlc attempts
// are kept on disk or removed to save space.
keepFailedPaymentAttempts bool
// storeFinalHtlcResolutions determines whether to persistently store
// the final resolution of incoming htlcs.
storeFinalHtlcResolutions bool
@@ -120,14 +116,6 @@ func OptionDryRunMigration(dryRun bool) OptionModifier {
}
}
// OptionKeepFailedPaymentAttempts controls whether failed payment attempts are
// kept on disk after a payment settles.
func OptionKeepFailedPaymentAttempts(keepFailedPaymentAttempts bool) OptionModifier {
return func(o *Options) {
o.keepFailedPaymentAttempts = keepFailedPaymentAttempts
}
}
// OptionStoreFinalHtlcResolutions controls whether to persistently store the
// final resolution of incoming htlcs.
func OptionStoreFinalHtlcResolutions(
+17 -10
View File
@@ -1,6 +1,10 @@
package channeldb
import "fmt"
import (
"fmt"
paymentsdb "github.com/lightningnetwork/lnd/payments/db"
)
// PaymentStatus represent current status of payment.
type PaymentStatus byte
@@ -58,24 +62,25 @@ func (ps PaymentStatus) initializable() error {
// again in case other goroutines have already been creating HTLCs for
// it.
case StatusInitiated:
return ErrPaymentExists
return paymentsdb.ErrPaymentExists
// We already have an InFlight payment on the network. We will disallow
// any new payments.
case StatusInFlight:
return ErrPaymentInFlight
return paymentsdb.ErrPaymentInFlight
// The payment has been attempted and is succeeded so we won't allow
// creating it again.
case StatusSucceeded:
return ErrAlreadyPaid
return paymentsdb.ErrAlreadyPaid
// We allow retrying failed payments.
case StatusFailed:
return nil
default:
return fmt.Errorf("%w: %v", ErrUnknownPaymentStatus, ps)
return fmt.Errorf("%w: %v", paymentsdb.ErrUnknownPaymentStatus,
ps)
}
}
@@ -91,7 +96,7 @@ func (ps PaymentStatus) removable() error {
// There are still inflight HTLCs and the payment needs to wait for the
// final outcomes.
case StatusInFlight:
return ErrPaymentInFlight
return paymentsdb.ErrPaymentInFlight
// The payment has been attempted and is succeeded and is allowed to be
// removed.
@@ -103,7 +108,8 @@ func (ps PaymentStatus) removable() error {
return nil
default:
return fmt.Errorf("%w: %v", ErrUnknownPaymentStatus, ps)
return fmt.Errorf("%w: %v", paymentsdb.ErrUnknownPaymentStatus,
ps)
}
}
@@ -121,13 +127,14 @@ func (ps PaymentStatus) updatable() error {
// If the payment has a terminal condition, we won't allow any updates.
case StatusSucceeded:
return ErrPaymentAlreadySucceeded
return paymentsdb.ErrPaymentAlreadySucceeded
case StatusFailed:
return ErrPaymentAlreadyFailed
return paymentsdb.ErrPaymentAlreadyFailed
default:
return fmt.Errorf("%w: %v", ErrUnknownPaymentStatus, ps)
return fmt.Errorf("%w: %v", paymentsdb.ErrUnknownPaymentStatus,
ps)
}
}
+10 -9
View File
@@ -5,6 +5,7 @@ import (
"testing"
"github.com/lightningnetwork/lnd/lntypes"
paymentsdb "github.com/lightningnetwork/lnd/payments/db"
"github.com/stretchr/testify/require"
)
@@ -197,33 +198,33 @@ func TestPaymentStatusActions(t *testing.T) {
}{
{
status: StatusInitiated,
initErr: ErrPaymentExists,
initErr: paymentsdb.ErrPaymentExists,
updateErr: nil,
removeErr: nil,
},
{
status: StatusInFlight,
initErr: ErrPaymentInFlight,
initErr: paymentsdb.ErrPaymentInFlight,
updateErr: nil,
removeErr: ErrPaymentInFlight,
removeErr: paymentsdb.ErrPaymentInFlight,
},
{
status: StatusSucceeded,
initErr: ErrAlreadyPaid,
updateErr: ErrPaymentAlreadySucceeded,
initErr: paymentsdb.ErrAlreadyPaid,
updateErr: paymentsdb.ErrPaymentAlreadySucceeded,
removeErr: nil,
},
{
status: StatusFailed,
initErr: nil,
updateErr: ErrPaymentAlreadyFailed,
updateErr: paymentsdb.ErrPaymentAlreadyFailed,
removeErr: nil,
},
{
status: 0,
initErr: ErrUnknownPaymentStatus,
updateErr: ErrUnknownPaymentStatus,
removeErr: ErrUnknownPaymentStatus,
initErr: paymentsdb.ErrUnknownPaymentStatus,
updateErr: paymentsdb.ErrUnknownPaymentStatus,
removeErr: paymentsdb.ErrUnknownPaymentStatus,
},
}
+102 -178
View File
@@ -2,6 +2,7 @@ package channeldb
import (
"bytes"
"context"
"encoding/binary"
"errors"
"fmt"
@@ -15,6 +16,7 @@ import (
"github.com/lightningnetwork/lnd/kvdb"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwire"
paymentsdb "github.com/lightningnetwork/lnd/payments/db"
"github.com/lightningnetwork/lnd/record"
"github.com/lightningnetwork/lnd/routing/route"
"github.com/lightningnetwork/lnd/tlv"
@@ -30,113 +32,6 @@ const (
paymentProgressLogInterval = 30 * time.Second
)
var (
// ErrAlreadyPaid signals we have already paid this payment hash.
ErrAlreadyPaid = errors.New("invoice is already paid")
// ErrPaymentInFlight signals that payment for this payment hash is
// already "in flight" on the network.
ErrPaymentInFlight = errors.New("payment is in transition")
// ErrPaymentExists is returned when we try to initialize an already
// existing payment that is not failed.
ErrPaymentExists = errors.New("payment already exists")
// ErrPaymentInternal is returned when performing the payment has a
// conflicting state, such as,
// - payment has StatusSucceeded but remaining amount is not zero.
// - payment has StatusInitiated but remaining amount is zero.
// - payment has StatusFailed but remaining amount is zero.
ErrPaymentInternal = errors.New("internal error")
// ErrPaymentNotInitiated is returned if the payment wasn't initiated.
ErrPaymentNotInitiated = errors.New("payment isn't initiated")
// ErrPaymentAlreadySucceeded is returned in the event we attempt to
// change the status of a payment already succeeded.
ErrPaymentAlreadySucceeded = errors.New("payment is already succeeded")
// ErrPaymentAlreadyFailed is returned in the event we attempt to alter
// a failed payment.
ErrPaymentAlreadyFailed = errors.New("payment has already failed")
// ErrUnknownPaymentStatus is returned when we do not recognize the
// existing state of a payment.
ErrUnknownPaymentStatus = errors.New("unknown payment status")
// ErrPaymentTerminal is returned if we attempt to alter a payment that
// already has reached a terminal condition.
ErrPaymentTerminal = errors.New("payment has reached terminal " +
"condition")
// ErrAttemptAlreadySettled is returned if we try to alter an already
// settled HTLC attempt.
ErrAttemptAlreadySettled = errors.New("attempt already settled")
// ErrAttemptAlreadyFailed is returned if we try to alter an already
// failed HTLC attempt.
ErrAttemptAlreadyFailed = errors.New("attempt already failed")
// ErrValueMismatch is returned if we try to register a non-MPP attempt
// with an amount that doesn't match the payment amount.
ErrValueMismatch = errors.New("attempted value doesn't match payment " +
"amount")
// ErrValueExceedsAmt is returned if we try to register an attempt that
// would take the total sent amount above the payment amount.
ErrValueExceedsAmt = errors.New("attempted value exceeds payment " +
"amount")
// ErrNonMPPayment is returned if we try to register an MPP attempt for
// a payment that already has a non-MPP attempt registered.
ErrNonMPPayment = errors.New("payment has non-MPP attempts")
// ErrMPPayment is returned if we try to register a non-MPP attempt for
// a payment that already has an MPP attempt registered.
ErrMPPayment = errors.New("payment has MPP attempts")
// ErrMPPRecordInBlindedPayment is returned if we try to register an
// attempt with an MPP record for a payment to a blinded path.
ErrMPPRecordInBlindedPayment = errors.New("blinded payment cannot " +
"contain MPP records")
// ErrBlindedPaymentTotalAmountMismatch is returned if we try to
// register an HTLC shard to a blinded route where the total amount
// doesn't match existing shards.
ErrBlindedPaymentTotalAmountMismatch = errors.New("blinded path " +
"total amount mismatch")
// ErrMPPPaymentAddrMismatch is returned if we try to register an MPP
// shard where the payment address doesn't match existing shards.
ErrMPPPaymentAddrMismatch = errors.New("payment address mismatch")
// ErrMPPTotalAmountMismatch is returned if we try to register an MPP
// shard where the total amount doesn't match existing shards.
ErrMPPTotalAmountMismatch = errors.New("mp payment total amount " +
"mismatch")
// ErrPaymentPendingSettled is returned when we try to add a new
// attempt to a payment that has at least one of its HTLCs settled.
ErrPaymentPendingSettled = errors.New("payment has settled htlcs")
// ErrPaymentPendingFailed is returned when we try to add a new attempt
// to a payment that already has a failure reason.
ErrPaymentPendingFailed = errors.New("payment has failure reason")
// ErrSentExceedsTotal is returned if the payment's current total sent
// amount exceed the total amount.
ErrSentExceedsTotal = errors.New("total sent exceeds total amount")
// errNoAttemptInfo is returned when no attempt info is stored yet.
errNoAttemptInfo = errors.New("unable to find attempt info for " +
"inflight payment")
// errNoSequenceNrIndex is returned when an attempt to lookup a payment
// index is made for a sequence number that is not indexed.
errNoSequenceNrIndex = errors.New("payment sequence number index " +
"does not exist")
)
//nolint:ll
var (
// paymentsRootBucket is the name of the top-level bucket within the
@@ -222,41 +117,70 @@ var (
paymentsIndexBucket = []byte("payments-index-bucket")
)
var (
// ErrNoSequenceNumber is returned if we look up a payment which does
// not have a sequence number.
ErrNoSequenceNumber = errors.New("sequence number not found")
// ErrDuplicateNotFound is returned when we lookup a payment by its
// index and cannot find a payment with a matching sequence number.
ErrDuplicateNotFound = errors.New("duplicate payment not found")
// ErrNoDuplicateBucket is returned when we expect to find duplicates
// when looking up a payment from its index, but the payment does not
// have any.
ErrNoDuplicateBucket = errors.New("expected duplicate bucket")
// ErrNoDuplicateNestedBucket is returned if we do not find duplicate
// payments in their own sub-bucket.
ErrNoDuplicateNestedBucket = errors.New("nested duplicate bucket not " +
"found")
)
// KVPaymentsDB implements persistence for payments and payment attempts.
type KVPaymentsDB struct {
paymentSeqMx sync.Mutex
currPaymentSeq uint64
storedPaymentSeq uint64
db *DB
// Sequence management for the kv store.
seqMu sync.Mutex
currSeq uint64
storedSeq uint64
// db is the underlying database implementation.
db kvdb.Backend
keepFailedPaymentAttempts bool
}
// NewKVPaymentsDB creates a new instance of the KVPaymentsDB.
func NewKVPaymentsDB(db *DB) *KVPaymentsDB {
return &KVPaymentsDB{
db: db,
// defaultKVStoreOptions returns the default options for the KV store.
func defaultKVStoreOptions() *paymentsdb.StoreOptions {
return &paymentsdb.StoreOptions{
KeepFailedPaymentAttempts: false,
}
}
// NewKVPaymentsDB creates a new KVStore for payments.
func NewKVPaymentsDB(db kvdb.Backend,
options ...paymentsdb.OptionModifier) (*KVPaymentsDB, error) {
opts := defaultKVStoreOptions()
for _, applyOption := range options {
applyOption(opts)
}
if !opts.NoMigration {
if err := initKVStore(db); err != nil {
return nil, err
}
}
return &KVPaymentsDB{
db: db,
keepFailedPaymentAttempts: opts.KeepFailedPaymentAttempts,
}, nil
}
var paymentsTopLevelBuckets = [][]byte{
paymentsRootBucket,
paymentsIndexBucket,
}
// initKVStore creates and initializes the top-level buckets for the payment db.
func initKVStore(db kvdb.Backend) error {
err := kvdb.Update(db, func(tx kvdb.RwTx) error {
for _, tlb := range paymentsTopLevelBuckets {
if _, err := tx.CreateTopLevelBucket(tlb); err != nil {
return err
}
}
return nil
}, func() {})
if err != nil {
return fmt.Errorf("unable to create new payments db: %w", err)
}
return nil
}
// InitPayment checks or records the given PaymentCreationInfo with the DB,
// 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
@@ -279,7 +203,7 @@ func (p *KVPaymentsDB) InitPayment(paymentHash lntypes.Hash,
infoBytes := b.Bytes()
var updateErr error
err = kvdb.Batch(p.db.Backend, func(tx kvdb.RwTx) error {
err = kvdb.Batch(p.db, func(tx kvdb.RwTx) error {
// Reset the update error, to avoid carrying over an error
// from a previous execution of the batched db transaction.
updateErr = nil
@@ -305,7 +229,7 @@ func (p *KVPaymentsDB) InitPayment(paymentHash lntypes.Hash,
// Otherwise, if the error is not `ErrPaymentNotInitiated`,
// we'll return the error.
case !errors.Is(err, ErrPaymentNotInitiated):
case !errors.Is(err, paymentsdb.ErrPaymentNotInitiated):
return err
}
@@ -366,7 +290,7 @@ func (p *KVPaymentsDB) InitPayment(paymentHash lntypes.Hash,
// DeleteFailedAttempts deletes all failed htlcs for a payment if configured
// by the KVPaymentsDB db.
func (p *KVPaymentsDB) DeleteFailedAttempts(hash lntypes.Hash) error {
if !p.db.keepFailedPaymentAttempts {
if !p.keepFailedPaymentAttempts {
const failedHtlcsOnly = true
err := p.DeletePayment(hash, failedHtlcsOnly)
if err != nil {
@@ -447,7 +371,7 @@ func (p *KVPaymentsDB) RegisterAttempt(paymentHash lntypes.Hash,
binary.BigEndian.PutUint64(htlcIDBytes, attempt.AttemptID)
var payment *MPPayment
err = kvdb.Batch(p.db.Backend, func(tx kvdb.RwTx) error {
err = kvdb.Batch(p.db, func(tx kvdb.RwTx) error {
prefetchPayment(tx, paymentHash)
bucket, err := fetchPaymentBucketUpdate(tx, paymentHash)
if err != nil {
@@ -479,7 +403,7 @@ func (p *KVPaymentsDB) RegisterAttempt(paymentHash lntypes.Hash,
// MPP records should not be set for attempts to blinded paths.
if isBlinded && mpp != nil {
return ErrMPPRecordInBlindedPayment
return paymentsdb.ErrMPPRecordInBlindedPayment
}
for _, h := range payment.InFlightHTLCs() {
@@ -488,7 +412,7 @@ func (p *KVPaymentsDB) RegisterAttempt(paymentHash lntypes.Hash,
// If this is a blinded payment, then no existing HTLCs
// should have MPP records.
if isBlinded && hMpp != nil {
return ErrMPPRecordInBlindedPayment
return paymentsdb.ErrMPPRecordInBlindedPayment
}
// If this is a blinded payment, then we just need to
@@ -500,7 +424,7 @@ func (p *KVPaymentsDB) RegisterAttempt(paymentHash lntypes.Hash,
h.Route.FinalHop().TotalAmtMsat {
//nolint:ll
return ErrBlindedPaymentTotalAmountMismatch
return paymentsdb.ErrBlindedPaymentTotalAmountMismatch
}
continue
@@ -510,12 +434,12 @@ func (p *KVPaymentsDB) RegisterAttempt(paymentHash lntypes.Hash,
// We tried to register a non-MPP attempt for a MPP
// payment.
case mpp == nil && hMpp != nil:
return ErrMPPayment
return paymentsdb.ErrMPPayment
// We tried to register a MPP shard for a non-MPP
// payment.
case mpp != nil && hMpp == nil:
return ErrNonMPPayment
return paymentsdb.ErrNonMPPayment
// Non-MPP payment, nothing more to validate.
case mpp == nil:
@@ -524,11 +448,11 @@ func (p *KVPaymentsDB) RegisterAttempt(paymentHash lntypes.Hash,
// Check that MPP options match.
if mpp.PaymentAddr() != hMpp.PaymentAddr() {
return ErrMPPPaymentAddrMismatch
return paymentsdb.ErrMPPPaymentAddrMismatch
}
if mpp.TotalMsat() != hMpp.TotalMsat() {
return ErrMPPTotalAmountMismatch
return paymentsdb.ErrMPPTotalAmountMismatch
}
}
@@ -537,15 +461,15 @@ func (p *KVPaymentsDB) RegisterAttempt(paymentHash lntypes.Hash,
// attempt.
amt := attempt.Route.ReceiverAmt()
if !isBlinded && mpp == nil && amt != payment.Info.Value {
return ErrValueMismatch
return paymentsdb.ErrValueMismatch
}
// Ensure we aren't sending more than the total payment amount.
sentAmt, _ := payment.SentAmt()
if sentAmt+amt > payment.Info.Value {
return fmt.Errorf("%w: attempted=%v, payment amount="+
"%v", ErrValueExceedsAmt, sentAmt+amt,
payment.Info.Value)
"%v", paymentsdb.ErrValueExceedsAmt,
sentAmt+amt, payment.Info.Value)
}
htlcsBucket, err := bucket.CreateBucketIfNotExists(
@@ -615,7 +539,7 @@ func (p *KVPaymentsDB) updateHtlcKey(paymentHash lntypes.Hash,
binary.BigEndian.PutUint64(aid, attemptID)
var payment *MPPayment
err := kvdb.Batch(p.db.Backend, func(tx kvdb.RwTx) error {
err := kvdb.Batch(p.db, func(tx kvdb.RwTx) error {
payment = nil
prefetchPayment(tx, paymentHash)
@@ -650,12 +574,12 @@ func (p *KVPaymentsDB) updateHtlcKey(paymentHash lntypes.Hash,
// Make sure the shard is not already failed or settled.
failKey := htlcBucketKey(htlcFailInfoKey, aid)
if htlcsBucket.Get(failKey) != nil {
return ErrAttemptAlreadyFailed
return paymentsdb.ErrAttemptAlreadyFailed
}
settleKey := htlcBucketKey(htlcSettleInfoKey, aid)
if htlcsBucket.Get(settleKey) != nil {
return ErrAttemptAlreadySettled
return paymentsdb.ErrAttemptAlreadySettled
}
// Add or update the key for this htlc.
@@ -687,7 +611,7 @@ func (p *KVPaymentsDB) Fail(paymentHash lntypes.Hash,
updateErr error
payment *MPPayment
)
err := kvdb.Batch(p.db.Backend, func(tx kvdb.RwTx) error {
err := kvdb.Batch(p.db, func(tx kvdb.RwTx) error {
// Reset the update error, to avoid carrying over an error
// from a previous execution of the batched db transaction.
updateErr = nil
@@ -695,8 +619,8 @@ func (p *KVPaymentsDB) Fail(paymentHash lntypes.Hash,
prefetchPayment(tx, paymentHash)
bucket, err := fetchPaymentBucketUpdate(tx, paymentHash)
if errors.Is(err, ErrPaymentNotInitiated) {
updateErr = ErrPaymentNotInitiated
if errors.Is(err, paymentsdb.ErrPaymentNotInitiated) {
updateErr = paymentsdb.ErrPaymentNotInitiated
return nil
} else if err != nil {
return err
@@ -707,8 +631,8 @@ func (p *KVPaymentsDB) Fail(paymentHash lntypes.Hash,
// failure to the KVPaymentsDB without synchronizing with
// other attempts.
_, err = fetchPaymentStatus(bucket)
if errors.Is(err, ErrPaymentNotInitiated) {
updateErr = ErrPaymentNotInitiated
if errors.Is(err, paymentsdb.ErrPaymentNotInitiated) {
updateErr = paymentsdb.ErrPaymentNotInitiated
return nil
} else if err != nil {
return err
@@ -801,12 +725,12 @@ func fetchPaymentBucket(tx kvdb.RTx, paymentHash lntypes.Hash) (
payments := tx.ReadBucket(paymentsRootBucket)
if payments == nil {
return nil, ErrPaymentNotInitiated
return nil, paymentsdb.ErrPaymentNotInitiated
}
bucket := payments.NestedReadBucket(paymentHash[:])
if bucket == nil {
return nil, ErrPaymentNotInitiated
return nil, paymentsdb.ErrPaymentNotInitiated
}
return bucket, nil
@@ -819,12 +743,12 @@ func fetchPaymentBucketUpdate(tx kvdb.RwTx, paymentHash lntypes.Hash) (
payments := tx.ReadWriteBucket(paymentsRootBucket)
if payments == nil {
return nil, ErrPaymentNotInitiated
return nil, paymentsdb.ErrPaymentNotInitiated
}
bucket := payments.NestedReadWriteBucket(paymentHash[:])
if bucket == nil {
return nil, ErrPaymentNotInitiated
return nil, paymentsdb.ErrPaymentNotInitiated
}
return bucket, nil
@@ -833,14 +757,14 @@ func fetchPaymentBucketUpdate(tx kvdb.RwTx, paymentHash lntypes.Hash) (
// nextPaymentSequence returns the next sequence number to store for a new
// payment.
func (p *KVPaymentsDB) nextPaymentSequence() ([]byte, error) {
p.paymentSeqMx.Lock()
defer p.paymentSeqMx.Unlock()
p.seqMu.Lock()
defer p.seqMu.Unlock()
// Set a new upper bound in the DB every 1000 payments to avoid
// conflicts on the sequence when using etcd.
if p.currPaymentSeq == p.storedPaymentSeq {
if p.currSeq == p.storedSeq {
var currPaymentSeq, newUpperBound uint64
if err := kvdb.Update(p.db.Backend, func(tx kvdb.RwTx) error {
if err := kvdb.Update(p.db, func(tx kvdb.RwTx) error {
paymentsBucket, err := tx.CreateTopLevelBucket(
paymentsRootBucket,
)
@@ -861,16 +785,16 @@ func (p *KVPaymentsDB) nextPaymentSequence() ([]byte, error) {
// initialize our stored currPaymentSeq, since by default both
// this variable and storedPaymentSeq are zero which in turn
// will have us fetch the current values from the DB.
if p.currPaymentSeq == 0 {
p.currPaymentSeq = currPaymentSeq
if p.currSeq == 0 {
p.currSeq = currPaymentSeq
}
p.storedPaymentSeq = newUpperBound
p.storedSeq = newUpperBound
}
p.currPaymentSeq++
p.currSeq++
b := make([]byte, 8)
binary.BigEndian.PutUint64(b, p.currPaymentSeq)
binary.BigEndian.PutUint64(b, p.currSeq)
return b, nil
}
@@ -881,7 +805,7 @@ func fetchPaymentStatus(bucket kvdb.RBucket) (PaymentStatus, error) {
// Creation info should be set for all payments, regardless of state.
// If not, it is unknown.
if bucket.Get(paymentCreationInfoKey) == nil {
return 0, ErrPaymentNotInitiated
return 0, paymentsdb.ErrPaymentNotInitiated
}
payment, err := fetchPayment(bucket)
@@ -1127,7 +1051,7 @@ func fetchHtlcAttempts(bucket kvdb.RBucket) ([]HTLCAttempt, error) {
// Sanity check that all htlcs have an attempt info.
if attemptInfoCount != len(htlcsMap) {
return nil, errNoAttemptInfo
return nil, paymentsdb.ErrNoAttemptInfo
}
keys := make([]uint64, len(htlcsMap))
@@ -1206,8 +1130,8 @@ func fetchFailedHtlcKeys(bucket kvdb.RBucket) ([][]byte, error) {
// QueryPayments is a query to the payments database which is restricted
// to a subset of payments by the payments query, containing an offset
// index and a maximum number of returned payments.
func (p *KVPaymentsDB) QueryPayments(query PaymentsQuery) (PaymentsResponse,
error) {
func (p *KVPaymentsDB) QueryPayments(_ context.Context,
query PaymentsQuery) (PaymentsResponse, error) {
var resp PaymentsResponse
@@ -1366,7 +1290,7 @@ func fetchPaymentWithSequenceNumber(tx kvdb.RTx, paymentHash lntypes.Hash,
// the payment we are actually looking for.
seqBytes := bucket.Get(paymentSequenceKey)
if seqBytes == nil {
return nil, ErrNoSequenceNumber
return nil, paymentsdb.ErrNoSequenceNumber
}
// If this top level payment has the sequence number we are looking for,
@@ -1381,7 +1305,7 @@ func fetchPaymentWithSequenceNumber(tx kvdb.RTx, paymentHash lntypes.Hash,
// find a duplicate payments bucket here, something is wrong.
dup := bucket.NestedReadBucket(duplicatePaymentsBucket)
if dup == nil {
return nil, ErrNoDuplicateBucket
return nil, paymentsdb.ErrNoDuplicateBucket
}
var duplicatePayment *MPPayment
@@ -1389,7 +1313,7 @@ func fetchPaymentWithSequenceNumber(tx kvdb.RTx, paymentHash lntypes.Hash,
subBucket := dup.NestedReadBucket(k)
if subBucket == nil {
// We one bucket for each duplicate to be found.
return ErrNoDuplicateNestedBucket
return paymentsdb.ErrNoDuplicateNestedBucket
}
seqBytes := subBucket.Get(duplicatePaymentSequenceKey)
@@ -1418,7 +1342,7 @@ func fetchPaymentWithSequenceNumber(tx kvdb.RTx, paymentHash lntypes.Hash,
// failed to find the payment with this sequence number; something is
// wrong.
if duplicatePayment == nil {
return nil, ErrDuplicateNotFound
return nil, paymentsdb.ErrDuplicateNotFound
}
return duplicatePayment, nil
+56 -49
View File
@@ -16,6 +16,7 @@ import (
"github.com/lightningnetwork/lnd/kvdb"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwire"
paymentsdb "github.com/lightningnetwork/lnd/payments/db"
"github.com/lightningnetwork/lnd/record"
"github.com/lightningnetwork/lnd/routing/route"
"github.com/lightningnetwork/lnd/tlv"
@@ -66,7 +67,8 @@ func TestKVPaymentsDBSwitchFail(t *testing.T) {
db, err := MakeTestDB(t)
require.NoError(t, err, "unable to init db")
paymentDB := NewKVPaymentsDB(db)
paymentDB, err := NewKVPaymentsDB(db)
require.NoError(t, err)
info, attempt, preimg, err := genInfo(t)
require.NoError(t, err, "unable to generate htlc message")
@@ -193,7 +195,7 @@ func TestKVPaymentsDBSwitchFail(t *testing.T) {
// Attempt a final payment, which should now fail since the prior
// payment succeed.
err = paymentDB.InitPayment(info.PaymentIdentifier, info)
if !errors.Is(err, ErrAlreadyPaid) {
if !errors.Is(err, paymentsdb.ErrAlreadyPaid) {
t.Fatalf("unable to send htlc message: %v", err)
}
}
@@ -206,7 +208,8 @@ func TestKVPaymentsDBSwitchDoubleSend(t *testing.T) {
db, err := MakeTestDB(t)
require.NoError(t, err, "unable to init db")
paymentDB := NewKVPaymentsDB(db)
paymentDB, err := NewKVPaymentsDB(db)
require.NoError(t, err)
info, attempt, preimg, err := genInfo(t)
require.NoError(t, err, "unable to generate htlc message")
@@ -228,7 +231,7 @@ func TestKVPaymentsDBSwitchDoubleSend(t *testing.T) {
// payment hash, should result in error indicating that payment has
// already been sent.
err = paymentDB.InitPayment(info.PaymentIdentifier, info)
require.ErrorIs(t, err, ErrPaymentExists)
require.ErrorIs(t, err, paymentsdb.ErrPaymentExists)
// Record an attempt.
_, err = paymentDB.RegisterAttempt(info.PaymentIdentifier, attempt)
@@ -246,7 +249,7 @@ func TestKVPaymentsDBSwitchDoubleSend(t *testing.T) {
// Sends base htlc message which initiate StatusInFlight.
err = paymentDB.InitPayment(info.PaymentIdentifier, info)
if !errors.Is(err, ErrPaymentInFlight) {
if !errors.Is(err, paymentsdb.ErrPaymentInFlight) {
t.Fatalf("payment control wrong behaviour: " +
"double sending must trigger ErrPaymentInFlight error")
}
@@ -269,7 +272,7 @@ func TestKVPaymentsDBSwitchDoubleSend(t *testing.T) {
)
err = paymentDB.InitPayment(info.PaymentIdentifier, info)
if !errors.Is(err, ErrAlreadyPaid) {
if !errors.Is(err, paymentsdb.ErrAlreadyPaid) {
t.Fatalf("unable to send htlc message: %v", err)
}
}
@@ -282,7 +285,8 @@ func TestKVPaymentsDBSuccessesWithoutInFlight(t *testing.T) {
db, err := MakeTestDB(t)
require.NoError(t, err, "unable to init db")
paymentDB := NewKVPaymentsDB(db)
paymentDB, err := NewKVPaymentsDB(db)
require.NoError(t, err)
info, _, preimg, err := genInfo(t)
require.NoError(t, err, "unable to generate htlc message")
@@ -294,9 +298,7 @@ func TestKVPaymentsDBSuccessesWithoutInFlight(t *testing.T) {
Preimage: preimg,
},
)
if err != ErrPaymentNotInitiated {
t.Fatalf("expected ErrPaymentNotInitiated, got %v", err)
}
require.ErrorIs(t, err, paymentsdb.ErrPaymentNotInitiated)
}
// TestKVPaymentsDBFailsWithoutInFlight checks that a strict payment
@@ -307,16 +309,15 @@ func TestKVPaymentsDBFailsWithoutInFlight(t *testing.T) {
db, err := MakeTestDB(t)
require.NoError(t, err, "unable to init db")
paymentDB := NewKVPaymentsDB(db)
paymentDB, err := NewKVPaymentsDB(db)
require.NoError(t, err)
info, _, _, err := genInfo(t)
require.NoError(t, err, "unable to generate htlc message")
// Calling Fail should return an error.
_, err = paymentDB.Fail(info.PaymentIdentifier, FailureReasonNoRoute)
if err != ErrPaymentNotInitiated {
t.Fatalf("expected ErrPaymentNotInitiated, got %v", err)
}
require.ErrorIs(t, err, paymentsdb.ErrPaymentNotInitiated)
}
// TestKVPaymentsDBDeleteNonInFlight checks that calling DeletePayments only
@@ -332,7 +333,8 @@ func TestKVPaymentsDBDeleteNonInFlight(t *testing.T) {
// start at 1, so 9999 is a safe bet for this test.
var duplicateSeqNr = 9999
paymentDB := NewKVPaymentsDB(db)
paymentDB, err := NewKVPaymentsDB(db)
require.NoError(t, err)
payments := []struct {
failed bool
@@ -550,7 +552,8 @@ func TestKVPaymentsDBDeletePayments(t *testing.T) {
db, err := MakeTestDB(t)
require.NoError(t, err, "unable to init db")
paymentDB := NewKVPaymentsDB(db)
paymentDB, err := NewKVPaymentsDB(db)
require.NoError(t, err)
// Register three payments:
// 1. A payment with two failed attempts.
@@ -611,7 +614,8 @@ func TestKVPaymentsDBDeleteSinglePayment(t *testing.T) {
db, err := MakeTestDB(t)
require.NoError(t, err, "unable to init db")
paymentDB := NewKVPaymentsDB(db)
paymentDB, err := NewKVPaymentsDB(db)
require.NoError(t, err)
// Register four payments:
// All payments will have one failed HTLC attempt and one HTLC attempt
@@ -717,7 +721,8 @@ func TestKVPaymentsDBMultiShard(t *testing.T) {
t.Fatalf("unable to init db: %v", err)
}
paymentDB := NewKVPaymentsDB(db)
paymentDB, err := NewKVPaymentsDB(db)
require.NoError(t, err)
info, attempt, preimg, err := genInfo(t)
if err != nil {
@@ -780,7 +785,7 @@ func TestKVPaymentsDBMultiShard(t *testing.T) {
b := *attempt
b.AttemptID = 3
_, err = paymentDB.RegisterAttempt(info.PaymentIdentifier, &b)
require.ErrorIs(t, err, ErrValueExceedsAmt)
require.ErrorIs(t, err, paymentsdb.ErrValueExceedsAmt)
// Fail the second attempt.
a := attempts[1]
@@ -880,9 +885,13 @@ func TestKVPaymentsDBMultiShard(t *testing.T) {
b.AttemptID = 3
_, err = paymentDB.RegisterAttempt(info.PaymentIdentifier, &b)
if test.settleFirst {
require.ErrorIs(t, err, ErrPaymentPendingSettled)
require.ErrorIs(
t, err, paymentsdb.ErrPaymentPendingSettled,
)
} else {
require.ErrorIs(t, err, ErrPaymentPendingFailed)
require.ErrorIs(
t, err, paymentsdb.ErrPaymentPendingFailed,
)
}
assertPaymentStatus(
@@ -951,21 +960,21 @@ func TestKVPaymentsDBMultiShard(t *testing.T) {
// settled.
case test.settleFirst && !test.settleLast:
finalStatus = StatusSucceeded
registerErr = ErrPaymentAlreadySucceeded
registerErr = paymentsdb.ErrPaymentAlreadySucceeded
case !test.settleFirst && test.settleLast:
finalStatus = StatusSucceeded
registerErr = ErrPaymentAlreadySucceeded
registerErr = paymentsdb.ErrPaymentAlreadySucceeded
// If both failed, we end up in a failed status.
case !test.settleFirst && !test.settleLast:
finalStatus = StatusFailed
registerErr = ErrPaymentAlreadyFailed
registerErr = paymentsdb.ErrPaymentAlreadyFailed
// Otherwise, the payment has a succeed status.
case test.settleFirst && test.settleLast:
finalStatus = StatusSucceeded
registerErr = ErrPaymentAlreadySucceeded
registerErr = paymentsdb.ErrPaymentAlreadySucceeded
}
assertPaymentStatus(
@@ -994,7 +1003,8 @@ func TestKVPaymentsDBMPPRecordValidation(t *testing.T) {
db, err := MakeTestDB(t)
require.NoError(t, err, "unable to init db")
paymentDB := NewKVPaymentsDB(db)
paymentDB, err := NewKVPaymentsDB(db)
require.NoError(t, err)
info, attempt, _, err := genInfo(t)
require.NoError(t, err, "unable to generate htlc message")
@@ -1021,27 +1031,21 @@ func TestKVPaymentsDBMPPRecordValidation(t *testing.T) {
b.AttemptID = 1
b.Route.FinalHop().MPP = nil
_, err = paymentDB.RegisterAttempt(info.PaymentIdentifier, &b)
if err != ErrMPPayment {
t.Fatalf("expected ErrMPPayment, got: %v", err)
}
require.ErrorIs(t, err, paymentsdb.ErrMPPayment)
// Try to register attempt one with a different payment address.
b.Route.FinalHop().MPP = record.NewMPP(
info.Value, [32]byte{2},
)
_, err = paymentDB.RegisterAttempt(info.PaymentIdentifier, &b)
if err != ErrMPPPaymentAddrMismatch {
t.Fatalf("expected ErrMPPPaymentAddrMismatch, got: %v", err)
}
require.ErrorIs(t, err, paymentsdb.ErrMPPPaymentAddrMismatch)
// Try registering one with a different total amount.
b.Route.FinalHop().MPP = record.NewMPP(
info.Value/2, [32]byte{1},
)
_, err = paymentDB.RegisterAttempt(info.PaymentIdentifier, &b)
if err != ErrMPPTotalAmountMismatch {
t.Fatalf("expected ErrMPPTotalAmountMismatch, got: %v", err)
}
require.ErrorIs(t, err, paymentsdb.ErrMPPTotalAmountMismatch)
// Create and init a new payment. This time we'll check that we cannot
// register an MPP attempt if we already registered a non-MPP one.
@@ -1063,9 +1067,7 @@ func TestKVPaymentsDBMPPRecordValidation(t *testing.T) {
)
_, err = paymentDB.RegisterAttempt(info.PaymentIdentifier, &b)
if err != ErrNonMPPayment {
t.Fatalf("expected ErrNonMPPayment, got: %v", err)
}
require.ErrorIs(t, err, paymentsdb.ErrNonMPPayment)
}
// TestDeleteFailedAttempts checks that DeleteFailedAttempts properly removes
@@ -1083,11 +1085,15 @@ func TestDeleteFailedAttempts(t *testing.T) {
func testDeleteFailedAttempts(t *testing.T, keepFailedPaymentAttempts bool) {
db, err := MakeTestDB(t)
require.NoError(t, err, "unable to init db")
db.keepFailedPaymentAttempts = keepFailedPaymentAttempts
paymentDB := NewKVPaymentsDB(db)
paymentDB, err := NewKVPaymentsDB(
db,
paymentsdb.WithKeepFailedPaymentAttempts(
keepFailedPaymentAttempts,
),
)
require.NoError(t, err)
// Register three payments:
// All payments will have one failed HTLC attempt and one HTLC attempt
@@ -1171,7 +1177,7 @@ func assertPaymentStatus(t *testing.T, p *KVPaymentsDB,
t.Helper()
payment, err := p.FetchPayment(hash)
if errors.Is(err, ErrPaymentNotInitiated) {
if errors.Is(err, paymentsdb.ErrPaymentNotInitiated) {
return
}
if err != nil {
@@ -1271,7 +1277,7 @@ func fetchPaymentIndexEntry(_ *testing.T, p *KVPaymentsDB,
indexValue := indexBucket.Get(key)
if indexValue == nil {
return errNoSequenceNrIndex
return paymentsdb.ErrNoSequenceNrIndex
}
r := bytes.NewReader(indexValue)
@@ -1307,7 +1313,7 @@ func assertPaymentIndex(t *testing.T, p *KVPaymentsDB,
// exist.
func assertNoIndex(t *testing.T, p *KVPaymentsDB, seqNr uint64) {
_, err := fetchPaymentIndexEntry(t, p, seqNr)
require.Equal(t, errNoSequenceNrIndex, err)
require.Equal(t, paymentsdb.ErrNoSequenceNrIndex, err)
}
// payment is a helper structure that holds basic information on a test payment,
@@ -1584,7 +1590,8 @@ func TestFetchPaymentWithSequenceNumber(t *testing.T) {
db, err := MakeTestDB(t)
require.NoError(t, err)
paymentDB := NewKVPaymentsDB(db)
paymentDB, err := NewKVPaymentsDB(db)
require.NoError(t, err)
// Generate a test payment which does not have duplicates.
noDuplicates, _, _, err := genInfo(t)
@@ -1669,14 +1676,14 @@ func TestFetchPaymentWithSequenceNumber(t *testing.T) {
name: "lookup non-existent duplicate",
paymentHash: hasDuplicates.PaymentIdentifier,
sequenceNumber: 999999,
expectedErr: ErrDuplicateNotFound,
expectedErr: paymentsdb.ErrDuplicateNotFound,
},
{
name: "lookup duplicate, no duplicates " +
"bucket",
paymentHash: noDuplicates.PaymentIdentifier,
sequenceNumber: duplicateTwoSeqNr,
expectedErr: ErrNoDuplicateBucket,
expectedErr: paymentsdb.ErrNoDuplicateBucket,
},
}
@@ -1710,8 +1717,8 @@ func TestFetchPaymentWithSequenceNumber(t *testing.T) {
//
// This code is *only* intended to replicate legacy duplicate payments in lnd,
// our current schema does not allow duplicates.
func appendDuplicatePayment(t *testing.T, db *DB, paymentHash lntypes.Hash,
seqNr uint64, preImg lntypes.Preimage) {
func appendDuplicatePayment(t *testing.T, db kvdb.Backend,
paymentHash lntypes.Hash, seqNr uint64, preImg lntypes.Preimage) {
err := kvdb.Update(db, func(tx walletdb.ReadWriteTx) error {
bucket, err := fetchPaymentBucketUpdate(
+17 -14
View File
@@ -1,6 +1,7 @@
package channeldb
import (
"context"
"fmt"
"math"
"reflect"
@@ -348,20 +349,21 @@ func TestQueryPayments(t *testing.T) {
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
db, err := MakeTestDB(t)
if err != nil {
t.Fatalf("unable to init db: %v", err)
}
ctx := context.Background()
paymentDB := NewKVPaymentsDB(db)
db, err := MakeTestDB(t)
require.NoError(t, err)
// Initialize the payment database.
paymentDB, err := NewKVPaymentsDB(db)
require.NoError(t, err)
// Make a preliminary query to make sure it's ok to
// query when we have no payments.
resp, err := paymentDB.QueryPayments(tt.query)
resp, err := paymentDB.QueryPayments(ctx, tt.query)
require.NoError(t, err)
require.Len(t, resp.Payments, 0)
@@ -389,10 +391,7 @@ func TestQueryPayments(t *testing.T) {
err = paymentDB.InitPayment(
info.PaymentIdentifier, info,
)
if err != nil {
t.Fatalf("unable to initialize "+
"payment in database: %v", err)
}
require.NoError(t, err)
// Immediately delete the payment with index 2.
if i == 1 {
@@ -401,8 +400,10 @@ func TestQueryPayments(t *testing.T) {
)
require.NoError(t, err)
deletePayment(t, db, info.PaymentIdentifier,
pmt.SequenceNum)
deletePayment(
t, db, info.PaymentIdentifier,
pmt.SequenceNum,
)
}
// If we are on the last payment entry, add a
@@ -437,7 +438,9 @@ func TestQueryPayments(t *testing.T) {
"want %v.", len(allPayments), 6)
}
querySlice, err := paymentDB.QueryPayments(tt.query)
querySlice, err := paymentDB.QueryPayments(
ctx, tt.query,
)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
+17 -4
View File
@@ -48,6 +48,7 @@ import (
"github.com/lightningnetwork/lnd/lnwallet/rpcwallet"
"github.com/lightningnetwork/lnd/macaroons"
"github.com/lightningnetwork/lnd/msgmux"
paymentsdb "github.com/lightningnetwork/lnd/payments/db"
"github.com/lightningnetwork/lnd/rpcperms"
"github.com/lightningnetwork/lnd/signal"
"github.com/lightningnetwork/lnd/sqldb"
@@ -1052,9 +1053,6 @@ func (d *DefaultDatabaseBuilder) BuildDatabase(
dbOptions := []channeldb.OptionModifier{
channeldb.OptionDryRunMigration(cfg.DryRunMigration),
channeldb.OptionKeepFailedPaymentAttempts(
cfg.KeepFailedPaymentAttempts,
),
channeldb.OptionStoreFinalHtlcResolutions(
cfg.StoreFinalHtlcResolutions,
),
@@ -1222,9 +1220,24 @@ func (d *DefaultDatabaseBuilder) BuildDatabase(
// Mount the payments DB which is only KV for now.
//
// TODO(ziggie): Add support for SQL payments DB.
kvPaymentsDB := channeldb.NewKVPaymentsDB(
// Mount the payments DB for the KV store.
paymentsDBOptions := []paymentsdb.OptionModifier{
paymentsdb.WithKeepFailedPaymentAttempts(
cfg.KeepFailedPaymentAttempts,
),
}
kvPaymentsDB, err := channeldb.NewKVPaymentsDB(
dbs.ChanStateDB,
paymentsDBOptions...,
)
if err != nil {
cleanUp()
err = fmt.Errorf("unable to open payments DB: %w", err)
d.logger.Error(err)
return nil, nil, err
}
dbs.KVPaymentsDB = kvPaymentsDB
// Wrap the watchtower client DB and make sure we clean up.
+8 -7
View File
@@ -22,6 +22,7 @@ import (
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/macaroons"
paymentsdb "github.com/lightningnetwork/lnd/payments/db"
"github.com/lightningnetwork/lnd/routing"
"github.com/lightningnetwork/lnd/routing/route"
"github.com/lightningnetwork/lnd/zpay32"
@@ -373,9 +374,9 @@ func (s *Server) SendPaymentV2(req *SendPaymentRequest,
payment.Identifier(), err)
// Transform user errors to grpc code.
if errors.Is(err, channeldb.ErrPaymentExists) ||
errors.Is(err, channeldb.ErrPaymentInFlight) ||
errors.Is(err, channeldb.ErrAlreadyPaid) {
if errors.Is(err, paymentsdb.ErrPaymentExists) ||
errors.Is(err, paymentsdb.ErrPaymentInFlight) ||
errors.Is(err, paymentsdb.ErrAlreadyPaid) {
return status.Error(
codes.AlreadyExists, err.Error(),
@@ -955,13 +956,13 @@ func (s *Server) SendToRouteV2(ctx context.Context,
// Transform user errors to grpc code.
switch {
case errors.Is(err, channeldb.ErrPaymentExists):
case errors.Is(err, paymentsdb.ErrPaymentExists):
fallthrough
case errors.Is(err, channeldb.ErrPaymentInFlight):
case errors.Is(err, paymentsdb.ErrPaymentInFlight):
fallthrough
case errors.Is(err, channeldb.ErrAlreadyPaid):
case errors.Is(err, paymentsdb.ErrAlreadyPaid):
return nil, status.Error(
codes.AlreadyExists, err.Error(),
)
@@ -1368,7 +1369,7 @@ func (s *Server) subscribePayment(identifier lntypes.Hash) (
sub, err := router.Tower.SubscribePayment(identifier)
switch {
case errors.Is(err, channeldb.ErrPaymentNotInitiated):
case errors.Is(err, paymentsdb.ErrPaymentNotInitiated):
return nil, status.Error(codes.NotFound, err.Error())
case err != nil:
+5
View File
@@ -46,6 +46,7 @@ import (
"github.com/lightningnetwork/lnd/monitoring"
"github.com/lightningnetwork/lnd/msgmux"
"github.com/lightningnetwork/lnd/netann"
paymentsdb "github.com/lightningnetwork/lnd/payments/db"
"github.com/lightningnetwork/lnd/peer"
"github.com/lightningnetwork/lnd/peernotifier"
"github.com/lightningnetwork/lnd/protofsm"
@@ -207,6 +208,10 @@ func SetupLoggers(root *build.SubLoggerManager, interceptor signal.Interceptor)
AddSubLogger(root, chainio.Subsystem, interceptor, chainio.UseLogger)
AddSubLogger(root, msgmux.Subsystem, interceptor, msgmux.UseLogger)
AddSubLogger(root, sqldb.Subsystem, interceptor, sqldb.UseLogger)
AddSubLogger(
root, paymentsdb.Subsystem, interceptor, paymentsdb.UseLogger,
)
}
// AddSubLogger is a helper method to conveniently create and register the
+133
View File
@@ -0,0 +1,133 @@
package paymentsdb
import "errors"
var (
// ErrAlreadyPaid signals we have already paid this payment hash.
ErrAlreadyPaid = errors.New("invoice is already paid")
// ErrPaymentInFlight signals that payment for this payment hash is
// already "in flight" on the network.
ErrPaymentInFlight = errors.New("payment is in transition")
// ErrPaymentExists is returned when we try to initialize an already
// existing payment that is not failed.
ErrPaymentExists = errors.New("payment already exists")
// ErrPaymentInternal is returned when performing the payment has a
// conflicting state, such as,
// - payment has StatusSucceeded but remaining amount is not zero.
// - payment has StatusInitiated but remaining amount is zero.
// - payment has StatusFailed but remaining amount is zero.
ErrPaymentInternal = errors.New("internal error")
// ErrPaymentNotInitiated is returned if the payment wasn't initiated.
ErrPaymentNotInitiated = errors.New("payment isn't initiated")
// ErrPaymentAlreadySucceeded is returned in the event we attempt to
// change the status of a payment already succeeded.
ErrPaymentAlreadySucceeded = errors.New("payment is already succeeded")
// ErrPaymentAlreadyFailed is returned in the event we attempt to alter
// a failed payment.
ErrPaymentAlreadyFailed = errors.New("payment has already failed")
// ErrUnknownPaymentStatus is returned when we do not recognize the
// existing state of a payment.
ErrUnknownPaymentStatus = errors.New("unknown payment status")
// ErrPaymentTerminal is returned if we attempt to alter a payment that
// already has reached a terminal condition.
ErrPaymentTerminal = errors.New("payment has reached terminal " +
"condition")
// ErrAttemptAlreadySettled is returned if we try to alter an already
// settled HTLC attempt.
ErrAttemptAlreadySettled = errors.New("attempt already settled")
// ErrAttemptAlreadyFailed is returned if we try to alter an already
// failed HTLC attempt.
ErrAttemptAlreadyFailed = errors.New("attempt already failed")
// ErrValueMismatch is returned if we try to register a non-MPP attempt
// with an amount that doesn't match the payment amount.
ErrValueMismatch = errors.New("attempted value doesn't match payment " +
"amount")
// ErrValueExceedsAmt is returned if we try to register an attempt that
// would take the total sent amount above the payment amount.
ErrValueExceedsAmt = errors.New("attempted value exceeds payment " +
"amount")
// ErrNonMPPayment is returned if we try to register an MPP attempt for
// a payment that already has a non-MPP attempt registered.
ErrNonMPPayment = errors.New("payment has non-MPP attempts")
// ErrMPPayment is returned if we try to register a non-MPP attempt for
// a payment that already has an MPP attempt registered.
ErrMPPayment = errors.New("payment has MPP attempts")
// ErrMPPRecordInBlindedPayment is returned if we try to register an
// attempt with an MPP record for a payment to a blinded path.
ErrMPPRecordInBlindedPayment = errors.New("blinded payment cannot " +
"contain MPP records")
// ErrBlindedPaymentTotalAmountMismatch is returned if we try to
// register an HTLC shard to a blinded route where the total amount
// doesn't match existing shards.
ErrBlindedPaymentTotalAmountMismatch = errors.New("blinded path " +
"total amount mismatch")
// ErrMPPPaymentAddrMismatch is returned if we try to register an MPP
// shard where the payment address doesn't match existing shards.
ErrMPPPaymentAddrMismatch = errors.New("payment address mismatch")
// ErrMPPTotalAmountMismatch is returned if we try to register an MPP
// shard where the total amount doesn't match existing shards.
ErrMPPTotalAmountMismatch = errors.New("mp payment total amount " +
"mismatch")
// ErrPaymentPendingSettled is returned when we try to add a new
// attempt to a payment that has at least one of its HTLCs settled.
ErrPaymentPendingSettled = errors.New("payment has settled htlcs")
// ErrPaymentPendingFailed is returned when we try to add a new attempt
// to a payment that already has a failure reason.
ErrPaymentPendingFailed = errors.New("payment has failure reason")
// ErrSentExceedsTotal is returned if the payment's current total sent
// amount exceed the total amount.
ErrSentExceedsTotal = errors.New("total sent exceeds total amount")
// ErrNoAttemptInfo is returned when no attempt info is stored yet.
ErrNoAttemptInfo = errors.New("unable to find attempt info for " +
"inflight payment")
)
// KV backend specific errors.
var (
// ErrNoSequenceNumber is returned if we look up a payment which does
// not have a sequence number.
ErrNoSequenceNumber = errors.New("sequence number not found")
// ErrDuplicateNotFound is returned when we lookup a payment by its
// index and cannot find a payment with a matching sequence number.
ErrDuplicateNotFound = errors.New("duplicate payment not found")
// ErrNoDuplicateBucket is returned when we expect to find duplicates
// when looking up a payment from its index, but the payment does not
// have any.
ErrNoDuplicateBucket = errors.New("expected duplicate bucket")
// ErrNoDuplicateNestedBucket is returned if we do not find duplicate
// payments in their own sub-bucket.
ErrNoDuplicateNestedBucket = errors.New("nested duplicate bucket not " +
"found")
// ErrNoSequenceNrIndex is returned when an attempt to lookup a payment
// index is made for a sequence number that is not indexed.
//
// NOTE: Only used for the kv backend.
ErrNoSequenceNrIndex = errors.New("payment sequence number index " +
"does not exist")
)
+34
View File
@@ -0,0 +1,34 @@
package paymentsdb
import (
"github.com/btcsuite/btclog/v2"
"github.com/lightningnetwork/lnd/build"
)
// log is a logger that is initialized with no output filters. This
// means the package will not perform any logging by default until the caller
// requests it.
//
//nolint:unused
var log btclog.Logger
// Subsystem defines the logging identifier for this subsystem.
const Subsystem = "PYDB"
// The default amount of logging is none.
func init() {
UseLogger(build.NewSubLogger(Subsystem, nil))
}
// DisableLog disables all library log output. Logging output is disabled
// by default until UseLogger is called.
func DisableLog() {
UseLogger(btclog.Disabled)
}
// UseLogger uses a specified Logger to output package logging info.
// This should be used in preference to SetLogWriter if the caller is also
// using btclog.
func UseLogger(logger btclog.Logger) {
log = logger
}
+30
View File
@@ -0,0 +1,30 @@
package paymentsdb
// StoreOptions holds parameters for the KVStore.
type StoreOptions struct {
// NoMigration allows to open the database in readonly mode
NoMigration bool
// KeepFailedPaymentAttempts is a flag that determines whether to keep
// failed payment attempts for a settled payment in the db.
KeepFailedPaymentAttempts bool
}
// OptionModifier is a function signature for modifying the default
// StoreOptions.
type OptionModifier func(*StoreOptions)
// WithKeepFailedPaymentAttempts sets the KeepFailedPaymentAttempts to n.
func WithKeepFailedPaymentAttempts(n bool) OptionModifier {
return func(o *StoreOptions) {
o.KeepFailedPaymentAttempts = n
}
}
// WithNoMigration allows the database to be opened in read only mode by
// disabling migrations.
func WithNoMigration(b bool) OptionModifier {
return func(o *StoreOptions) {
o.NoMigration = b
}
}
+52 -18
View File
@@ -13,6 +13,7 @@ import (
"github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/lntypes"
paymentsdb "github.com/lightningnetwork/lnd/payments/db"
"github.com/lightningnetwork/lnd/routing/route"
"github.com/stretchr/testify/require"
)
@@ -47,13 +48,19 @@ var (
func TestControlTowerSubscribeUnknown(t *testing.T) {
t.Parallel()
db := initDB(t, false)
db := initDB(t)
pControl := NewControlTower(channeldb.NewKVPaymentsDB(db))
paymentDB, err := channeldb.NewKVPaymentsDB(
db,
paymentsdb.WithKeepFailedPaymentAttempts(true),
)
require.NoError(t, err)
pControl := NewControlTower(paymentDB)
// Subscription should fail when the payment is not known.
_, err := pControl.SubscribePayment(lntypes.Hash{1})
require.ErrorIs(t, err, channeldb.ErrPaymentNotInitiated)
_, err = pControl.SubscribePayment(lntypes.Hash{1})
require.ErrorIs(t, err, paymentsdb.ErrPaymentNotInitiated)
}
// TestControlTowerSubscribeSuccess tests that payment updates for a
@@ -61,9 +68,12 @@ func TestControlTowerSubscribeUnknown(t *testing.T) {
func TestControlTowerSubscribeSuccess(t *testing.T) {
t.Parallel()
db := initDB(t, false)
db := initDB(t)
pControl := NewControlTower(channeldb.NewKVPaymentsDB(db))
paymentDB, err := channeldb.NewKVPaymentsDB(db)
require.NoError(t, err)
pControl := NewControlTower(paymentDB)
// Initiate a payment.
info, attempt, preimg, err := genInfo()
@@ -180,9 +190,15 @@ func TestKVPaymentsDBSubscribeFail(t *testing.T) {
func TestKVPaymentsDBSubscribeAllSuccess(t *testing.T) {
t.Parallel()
db := initDB(t, true)
db := initDB(t)
pControl := NewControlTower(channeldb.NewKVPaymentsDB(db))
paymentDB, err := channeldb.NewKVPaymentsDB(
db,
paymentsdb.WithKeepFailedPaymentAttempts(true),
)
require.NoError(t, err)
pControl := NewControlTower(paymentDB)
// Initiate a payment.
info1, attempt1, preimg1, err := genInfo()
@@ -293,9 +309,15 @@ func TestKVPaymentsDBSubscribeAllSuccess(t *testing.T) {
func TestKVPaymentsDBSubscribeAllImmediate(t *testing.T) {
t.Parallel()
db := initDB(t, true)
db := initDB(t)
pControl := NewControlTower(channeldb.NewKVPaymentsDB(db))
paymentDB, err := channeldb.NewKVPaymentsDB(
db,
paymentsdb.WithKeepFailedPaymentAttempts(true),
)
require.NoError(t, err)
pControl := NewControlTower(paymentDB)
// Initiate a payment.
info, attempt, _, err := genInfo()
@@ -330,9 +352,15 @@ func TestKVPaymentsDBSubscribeAllImmediate(t *testing.T) {
func TestKVPaymentsDBUnsubscribeSuccess(t *testing.T) {
t.Parallel()
db := initDB(t, true)
db := initDB(t)
pControl := NewControlTower(channeldb.NewKVPaymentsDB(db))
paymentDB, err := channeldb.NewKVPaymentsDB(
db,
paymentsdb.WithKeepFailedPaymentAttempts(true),
)
require.NoError(t, err)
pControl := NewControlTower(paymentDB)
subscription1, err := pControl.SubscribeAllPayments()
require.NoError(t, err, "expected subscribe to succeed, but got: %v")
@@ -399,9 +427,17 @@ func TestKVPaymentsDBUnsubscribeSuccess(t *testing.T) {
func testKVPaymentsDBSubscribeFail(t *testing.T, registerAttempt,
keepFailedPaymentAttempts bool) {
db := initDB(t, keepFailedPaymentAttempts)
db := initDB(t)
pControl := NewControlTower(channeldb.NewKVPaymentsDB(db))
paymentDB, err := channeldb.NewKVPaymentsDB(
db,
paymentsdb.WithKeepFailedPaymentAttempts(
keepFailedPaymentAttempts,
),
)
require.NoError(t, err)
pControl := NewControlTower(paymentDB)
// Initiate a payment.
info, attempt, _, err := genInfo()
@@ -517,11 +553,9 @@ func testKVPaymentsDBSubscribeFail(t *testing.T, registerAttempt,
}
}
func initDB(t *testing.T, keepFailedPaymentAttempts bool) *channeldb.DB {
func initDB(t *testing.T) *channeldb.DB {
return channeldb.OpenForTesting(
t, t.TempDir(), channeldb.OptionKeepFailedPaymentAttempts(
keepFailedPaymentAttempts,
),
t, t.TempDir(),
)
}
+17 -16
View File
@@ -13,6 +13,7 @@ import (
"github.com/lightningnetwork/lnd/htlcswitch"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwire"
paymentsdb "github.com/lightningnetwork/lnd/payments/db"
"github.com/lightningnetwork/lnd/record"
"github.com/lightningnetwork/lnd/routing/route"
"github.com/lightningnetwork/lnd/routing/shards"
@@ -308,7 +309,7 @@ func (m *mockControlTowerOld) InitPayment(phash lntypes.Hash,
// Don't allow re-init a successful payment.
if _, ok := m.successful[phash]; ok {
return channeldb.ErrAlreadyPaid
return paymentsdb.ErrAlreadyPaid
}
_, failed := m.failed[phash]
@@ -316,7 +317,7 @@ func (m *mockControlTowerOld) InitPayment(phash lntypes.Hash,
// If the payment is known, only allow re-init if failed.
if ok && !failed {
return channeldb.ErrPaymentInFlight
return paymentsdb.ErrPaymentInFlight
}
delete(m.failed, phash)
@@ -330,7 +331,7 @@ func (m *mockControlTowerOld) InitPayment(phash lntypes.Hash,
func (m *mockControlTowerOld) DeleteFailedAttempts(phash lntypes.Hash) error {
p, ok := m.payments[phash]
if !ok {
return channeldb.ErrPaymentNotInitiated
return paymentsdb.ErrPaymentNotInitiated
}
var inFlight bool
@@ -347,7 +348,7 @@ func (m *mockControlTowerOld) DeleteFailedAttempts(phash lntypes.Hash) error {
}
if inFlight {
return channeldb.ErrPaymentInFlight
return paymentsdb.ErrPaymentInFlight
}
return nil
@@ -366,7 +367,7 @@ func (m *mockControlTowerOld) RegisterAttempt(phash lntypes.Hash,
// Lookup payment.
p, ok := m.payments[phash]
if !ok {
return channeldb.ErrPaymentNotInitiated
return paymentsdb.ErrPaymentNotInitiated
}
var inFlight bool
@@ -387,15 +388,15 @@ func (m *mockControlTowerOld) RegisterAttempt(phash lntypes.Hash,
_, failed := m.failed[phash]
if settled || failed {
return channeldb.ErrPaymentTerminal
return paymentsdb.ErrPaymentTerminal
}
if settled && !inFlight {
return channeldb.ErrPaymentAlreadySucceeded
return paymentsdb.ErrPaymentAlreadySucceeded
}
if failed && !inFlight {
return channeldb.ErrPaymentAlreadyFailed
return paymentsdb.ErrPaymentAlreadyFailed
}
// Add attempt to payment.
@@ -421,7 +422,7 @@ func (m *mockControlTowerOld) SettleAttempt(phash lntypes.Hash,
// Only allow setting attempts if the payment is known.
p, ok := m.payments[phash]
if !ok {
return nil, channeldb.ErrPaymentNotInitiated
return nil, paymentsdb.ErrPaymentNotInitiated
}
// Find the attempt with this pid, and set the settle info.
@@ -431,10 +432,10 @@ func (m *mockControlTowerOld) SettleAttempt(phash lntypes.Hash,
}
if a.Settle != nil {
return nil, channeldb.ErrAttemptAlreadySettled
return nil, paymentsdb.ErrAttemptAlreadySettled
}
if a.Failure != nil {
return nil, channeldb.ErrAttemptAlreadyFailed
return nil, paymentsdb.ErrAttemptAlreadyFailed
}
p.attempts[i].Settle = settleInfo
@@ -462,7 +463,7 @@ func (m *mockControlTowerOld) FailAttempt(phash lntypes.Hash, pid uint64,
// Only allow failing attempts if the payment is known.
p, ok := m.payments[phash]
if !ok {
return nil, channeldb.ErrPaymentNotInitiated
return nil, paymentsdb.ErrPaymentNotInitiated
}
// Find the attempt with this pid, and set the failure info.
@@ -472,10 +473,10 @@ func (m *mockControlTowerOld) FailAttempt(phash lntypes.Hash, pid uint64,
}
if a.Settle != nil {
return nil, channeldb.ErrAttemptAlreadySettled
return nil, paymentsdb.ErrAttemptAlreadySettled
}
if a.Failure != nil {
return nil, channeldb.ErrAttemptAlreadyFailed
return nil, paymentsdb.ErrAttemptAlreadyFailed
}
p.attempts[i].Failure = failInfo
@@ -499,7 +500,7 @@ func (m *mockControlTowerOld) FailPayment(phash lntypes.Hash,
// Payment must be known.
if _, ok := m.payments[phash]; !ok {
return channeldb.ErrPaymentNotInitiated
return paymentsdb.ErrPaymentNotInitiated
}
m.failed[phash] = reason
@@ -521,7 +522,7 @@ func (m *mockControlTowerOld) fetchPayment(phash lntypes.Hash) (
p, ok := m.payments[phash]
if !ok {
return nil, channeldb.ErrPaymentNotInitiated
return nil, paymentsdb.ErrPaymentNotInitiated
}
mp := &channeldb.MPPayment{
+3 -2
View File
@@ -24,6 +24,7 @@ import (
"github.com/lightningnetwork/lnd/lnutils"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwire"
paymentsdb "github.com/lightningnetwork/lnd/payments/db"
"github.com/lightningnetwork/lnd/record"
"github.com/lightningnetwork/lnd/routing/route"
"github.com/lightningnetwork/lnd/routing/shards"
@@ -1133,8 +1134,8 @@ func (r *ChannelRouter) sendToRoute(htlcHash lntypes.Hash, rt *route.Route,
switch {
// If this is an MPP attempt and the hash is already registered with
// the database, we can go on to launch the shard.
case mpp != nil && errors.Is(err, channeldb.ErrPaymentInFlight):
case mpp != nil && errors.Is(err, channeldb.ErrPaymentExists):
case mpp != nil && errors.Is(err, paymentsdb.ErrPaymentInFlight):
case mpp != nil && errors.Is(err, paymentsdb.ErrPaymentExists):
// Any other error is not tolerated.
case err != nil:
+3 -1
View File
@@ -7528,7 +7528,9 @@ func (r *rpcServer) ListPayments(ctx context.Context,
query.MaxPayments = math.MaxUint64
}
paymentsQuerySlice, err := r.server.kvPaymentsDB.QueryPayments(query)
paymentsQuerySlice, err := r.server.kvPaymentsDB.QueryPayments(
ctx, query,
)
if err != nil {
return nil, err
}