multi: introduce new paymentsDB package

We introduce a new package paymentsDB and start by moving the
payment specifc errors from the channeldb package to the
paymentsDB package. We also fix linter issues which showed up
due to changing this code part.
This commit is contained in:
ziggie committed 2025-08-11 16:44:14 +02:00
1 parent db2c50a599
commit 18afd4442d
12 files changed
+279 -261

No files matched your search

+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
+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,
},
}
+28 -154
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"
@@ -31,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
@@ -223,26 +117,6 @@ 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
@@ -306,7 +180,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
}
@@ -480,7 +354,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() {
@@ -489,7 +363,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
@@ -501,7 +375,7 @@ func (p *KVPaymentsDB) RegisterAttempt(paymentHash lntypes.Hash,
h.Route.FinalHop().TotalAmtMsat {
//nolint:ll
return ErrBlindedPaymentTotalAmountMismatch
return paymentsdb.ErrBlindedPaymentTotalAmountMismatch
}
continue
@@ -511,12 +385,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:
@@ -525,11 +399,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
}
}
@@ -538,15 +412,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(
@@ -651,12 +525,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.
@@ -696,8 +570,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
@@ -708,8 +582,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
@@ -802,12 +676,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
@@ -820,12 +694,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
@@ -882,7 +756,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)
@@ -1128,7 +1002,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))
@@ -1367,7 +1241,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,
@@ -1382,7 +1256,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
@@ -1390,7 +1264,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)
@@ -1419,7 +1293,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
+27 -34
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"
@@ -193,7 +194,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)
}
}
@@ -228,7 +229,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 +247,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 +270,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)
}
}
@@ -294,9 +295,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
@@ -314,9 +313,7 @@ func TestKVPaymentsDBFailsWithoutInFlight(t *testing.T) {
// 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
@@ -780,7 +777,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 +877,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 +952,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(
@@ -1021,27 +1022,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 +1058,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
@@ -1171,7 +1164,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 +1264,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 +1300,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,
@@ -1669,14 +1662,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,
},
}
+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:
+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")
)
+2 -1
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"
)
@@ -53,7 +54,7 @@ func TestControlTowerSubscribeUnknown(t *testing.T) {
// Subscription should fail when the payment is not known.
_, err := pControl.SubscribePayment(lntypes.Hash{1})
require.ErrorIs(t, err, channeldb.ErrPaymentNotInitiated)
require.ErrorIs(t, err, paymentsdb.ErrPaymentNotInitiated)
}
// TestControlTowerSubscribeSuccess tests that payment updates for a
+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: