channeldb: add new payment status StatusInitiated

This commit adds a new payment status, `StatusInitiated`, to properly
represent the state where a payment is newly created without attempting
any HTLCs. Since the `PaymentStatus` is a memory representation of a
given payment's status, the enum used for the statuses are directly
updated.
This commit is contained in:
yyforyongyu
2022-11-24 12:05:48 +08:00
committed by Olaoluwa Osuntokun
parent 6be3817eed
commit 30fd29371c
4 changed files with 35 additions and 8 deletions

View File

@@ -26,6 +26,10 @@ var (
// already "in flight" on the network. // already "in flight" on the network.
ErrPaymentInFlight = errors.New("payment is in transition") 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")
// ErrPaymentNotInitiated is returned if the payment wasn't initiated. // ErrPaymentNotInitiated is returned if the payment wasn't initiated.
ErrPaymentNotInitiated = errors.New("payment isn't initiated") ErrPaymentNotInitiated = errors.New("payment isn't initiated")
@@ -148,10 +152,15 @@ func (p *PaymentControl) InitPayment(paymentHash lntypes.Hash,
// retrying the payment or return a specific error. // retrying the payment or return a specific error.
case err == nil: case err == nil:
switch paymentStatus { switch paymentStatus {
// We allow retrying failed payments. // We allow retrying failed payments.
case StatusFailed: case StatusFailed:
// We already have payment creation info for this
// payment so we won't allow creating a duplicate one.
case StatusInitiated:
updateErr = ErrPaymentExists
return nil
// We already have an InFlight payment on the network. // We already have an InFlight payment on the network.
// We will disallow any new payments. // We will disallow any new payments.
case StatusInFlight: case StatusInFlight:
@@ -727,6 +736,9 @@ func ensureInFlight(payment *MPPayment) error {
paymentStatus := payment.Status paymentStatus := payment.Status
switch { switch {
// Newly created payment is also inflight.
case paymentStatus == StatusInitiated:
return nil
// The payment was indeed InFlight. // The payment was indeed InFlight.
case paymentStatus == StatusInFlight: case paymentStatus == StatusInFlight:

View File

@@ -7,22 +7,29 @@ const (
// NOTE: PaymentStatus = 0 was previously used for status unknown and // NOTE: PaymentStatus = 0 was previously used for status unknown and
// is now deprecated. // is now deprecated.
// StatusInitiated is the status where a payment has just been
// initiated.
StatusInitiated PaymentStatus = 1
// StatusInFlight is the status where a payment has been initiated, but // StatusInFlight is the status where a payment has been initiated, but
// a response has not been received. // a response has not been received.
StatusInFlight PaymentStatus = 1 StatusInFlight PaymentStatus = 2
// StatusSucceeded is the status where a payment has been initiated and // StatusSucceeded is the status where a payment has been initiated and
// the payment was completed successfully. // the payment was completed successfully.
StatusSucceeded PaymentStatus = 2 StatusSucceeded PaymentStatus = 3
// StatusFailed is the status where a payment has been initiated and a // StatusFailed is the status where a payment has been initiated and a
// failure result has come back. // failure result has come back.
StatusFailed PaymentStatus = 3 StatusFailed PaymentStatus = 4
) )
// String returns readable representation of payment status. // String returns readable representation of payment status.
func (ps PaymentStatus) String() string { func (ps PaymentStatus) String() string {
switch ps { switch ps {
case StatusInitiated:
return "Initiated"
case StatusInFlight: case StatusInFlight:
return "In Flight" return "In Flight"

View File

@@ -446,10 +446,17 @@ func (s *Server) SendToRouteV2(ctx context.Context,
} }
// Transform user errors to grpc code. // Transform user errors to grpc code.
if err == channeldb.ErrPaymentInFlight || switch {
err == channeldb.ErrAlreadyPaid { case errors.Is(err, channeldb.ErrPaymentExists):
fallthrough
return nil, status.Error(codes.AlreadyExists, err.Error()) case errors.Is(err, channeldb.ErrPaymentInFlight):
fallthrough
case errors.Is(err, channeldb.ErrAlreadyPaid):
return nil, status.Error(
codes.AlreadyExists, err.Error(),
)
} }
return nil, err return nil, err

View File

@@ -2276,7 +2276,8 @@ func (r *ChannelRouter) sendToRoute(htlcHash lntypes.Hash, rt *route.Route,
switch { switch {
// If this is an MPP attempt and the hash is already registered with // If this is an MPP attempt and the hash is already registered with
// the database, we can go on to launch the shard. // the database, we can go on to launch the shard.
case err == channeldb.ErrPaymentInFlight && mpp != nil: case mpp != nil && errors.Is(err, channeldb.ErrPaymentInFlight):
case mpp != nil && errors.Is(err, channeldb.ErrPaymentExists):
// Any other error is not tolerated. // Any other error is not tolerated.
case err != nil: case err != nil: