From 2e3c96f9866fefaa232f4187e0fc5f5567d76f0b Mon Sep 17 00:00:00 2001 From: Slyghtning Date: Thu, 13 Jun 2024 09:43:35 +0200 Subject: [PATCH] routing: new failure reason for cancelled payments --- channeldb/payments.go | 12 ++++++++---- lnrpc/routerrpc/router_backend.go | 3 +++ routing/payment_lifecycle.go | 4 +++- routing/payment_lifecycle_test.go | 8 ++++---- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/channeldb/payments.go b/channeldb/payments.go index a1baa07f7..079fedf23 100644 --- a/channeldb/payments.go +++ b/channeldb/payments.go @@ -104,7 +104,7 @@ var ( ) var ( - // ErrNoSequenceNumber is returned if we lookup a payment which does + // ErrNoSequenceNumber is returned if we look up a payment which does // not have a sequence number. ErrNoSequenceNumber = errors.New("sequence number not found") @@ -147,18 +147,20 @@ const ( // balance to complete the payment. FailureReasonInsufficientBalance FailureReason = 4 - // TODO(halseth): cancel state. + // FailureReasonCanceled indicates that the payment was canceled by the + // user. + FailureReasonCanceled FailureReason = 5 // TODO(joostjager): Add failure reasons for: // LocalLiquidityInsufficient, RemoteCapacityInsufficient. ) -// Error returns a human readable error string for the FailureReason. +// Error returns a human-readable error string for the FailureReason. func (r FailureReason) Error() string { return r.String() } -// String returns a human readable FailureReason. +// String returns a human-readable FailureReason. func (r FailureReason) String() string { switch r { case FailureReasonTimeout: @@ -171,6 +173,8 @@ func (r FailureReason) String() string { return "incorrect_payment_details" case FailureReasonInsufficientBalance: return "insufficient_balance" + case FailureReasonCanceled: + return "canceled" } return "unknown" diff --git a/lnrpc/routerrpc/router_backend.go b/lnrpc/routerrpc/router_backend.go index faf53c4b6..ac493ba33 100644 --- a/lnrpc/routerrpc/router_backend.go +++ b/lnrpc/routerrpc/router_backend.go @@ -1747,6 +1747,9 @@ func marshallPaymentFailureReason(reason *channeldb.FailureReason) ( case channeldb.FailureReasonInsufficientBalance: return lnrpc.PaymentFailureReason_FAILURE_REASON_INSUFFICIENT_BALANCE, nil + + case channeldb.FailureReasonCanceled: + return lnrpc.PaymentFailureReason_FAILURE_REASON_CANCELED, nil } return 0, errors.New("unknown failure reason") diff --git a/routing/payment_lifecycle.go b/routing/payment_lifecycle.go index 5e7f8b491..1d103c5ac 100644 --- a/routing/payment_lifecycle.go +++ b/routing/payment_lifecycle.go @@ -322,10 +322,13 @@ func (p *paymentLifecycle) checkContext(ctx context.Context) error { // user-provided timeout was reached, or the context was // canceled, either to a manual cancellation or due to an // unknown error. + var reason channeldb.FailureReason if errors.Is(ctx.Err(), context.DeadlineExceeded) { + reason = channeldb.FailureReasonTimeout log.Warnf("Payment attempt not completed before "+ "timeout, id=%s", p.identifier.String()) } else { + reason = channeldb.FailureReasonCanceled log.Warnf("Payment attempt context canceled, id=%s", p.identifier.String()) } @@ -334,7 +337,6 @@ func (p *paymentLifecycle) checkContext(ctx context.Context) error { // inflight HTLCs or not, its status will now either be // `StatusInflight` or `StatusFailed`. In either case, no more // HTLCs will be attempted. - reason := channeldb.FailureReasonTimeout err := p.router.cfg.Control.FailPayment(p.identifier, reason) if err != nil { return fmt.Errorf("FailPayment got %w", err) diff --git a/routing/payment_lifecycle_test.go b/routing/payment_lifecycle_test.go index 3b19812c6..34c8d6c17 100644 --- a/routing/payment_lifecycle_test.go +++ b/routing/payment_lifecycle_test.go @@ -772,17 +772,17 @@ func TestResumePaymentFailContextCancel(t *testing.T) { cancel() m.control.On( - "FailPayment", p.identifier, channeldb.FailureReasonTimeout, + "FailPayment", p.identifier, channeldb.FailureReasonCanceled, ).Return(nil).Once() - // 5. decideNextStep now returns stepExit. + // 4. decideNextStep now returns stepExit. m.payment.On("AllowMoreAttempts").Return(false, nil).Once(). On("NeedWaitAttempts").Return(false, nil).Once() - // 6. Control tower deletes failed attempts. + // 5. Control tower deletes failed attempts. m.control.On("DeleteFailedAttempts", p.identifier).Return(nil).Once() - // 7. We will observe FailureReasonError if the context was cancelled. + // 6. We will observe FailureReasonError if the context was cancelled. reason := channeldb.FailureReasonError m.payment.On("TerminalInfo").Return(nil, &reason)