@@ -195,6 +195,7 @@ func newLoopOutSwap(globalCtx context.Context, cfg *swapConfig,
195195 ProtocolVersion : loopdb .CurrentProtocolVersion (),
196196 },
197197 OutgoingChanSet : chanSet ,
198+ PaymentTimeout : request .PaymentTimeout ,
198199 }
199200
200201 swapKit := newSwapKit (
@@ -610,7 +611,8 @@ func (s *loopOutSwap) payInvoices(ctx context.Context) {
610611 // Use the recommended routing plugin.
611612 s .swapPaymentChan = s .payInvoice (
612613 ctx , s .SwapInvoice , s .MaxSwapRoutingFee ,
613- s .LoopOutContract .OutgoingChanSet , pluginType , true ,
614+ s .LoopOutContract .OutgoingChanSet ,
615+ s .LoopOutContract .PaymentTimeout , pluginType , true ,
614616 )
615617
616618 // Pay the prepay invoice. Won't use the routing plugin here as the
@@ -619,7 +621,8 @@ func (s *loopOutSwap) payInvoices(ctx context.Context) {
619621 s .log .Infof ("Sending prepayment %v" , s .PrepayInvoice )
620622 s .prePaymentChan = s .payInvoice (
621623 ctx , s .PrepayInvoice , s .MaxPrepayRoutingFee ,
622- s .LoopOutContract .OutgoingChanSet , RoutingPluginNone , false ,
624+ s .LoopOutContract .OutgoingChanSet ,
625+ s .LoopOutContract .PaymentTimeout , RoutingPluginNone , false ,
623626 )
624627}
625628
@@ -647,7 +650,7 @@ func (p paymentResult) failure() error {
647650// payInvoice pays a single invoice.
648651func (s * loopOutSwap ) payInvoice (ctx context.Context , invoice string ,
649652 maxFee btcutil.Amount , outgoingChanIds loopdb.ChannelSet ,
650- pluginType RoutingPluginType ,
653+ paymentTimeout time. Duration , pluginType RoutingPluginType ,
651654 reportPluginResult bool ) chan paymentResult {
652655
653656 resultChan := make (chan paymentResult )
@@ -662,8 +665,8 @@ func (s *loopOutSwap) payInvoice(ctx context.Context, invoice string,
662665 var result paymentResult
663666
664667 status , err := s .payInvoiceAsync (
665- ctx , invoice , maxFee , outgoingChanIds , pluginType ,
666- reportPluginResult ,
668+ ctx , invoice , maxFee , outgoingChanIds , paymentTimeout ,
669+ pluginType , reportPluginResult ,
667670 )
668671 if err != nil {
669672 result .err = err
@@ -691,8 +694,9 @@ func (s *loopOutSwap) payInvoice(ctx context.Context, invoice string,
691694// payInvoiceAsync is the asynchronously executed part of paying an invoice.
692695func (s * loopOutSwap ) payInvoiceAsync (ctx context.Context ,
693696 invoice string , maxFee btcutil.Amount ,
694- outgoingChanIds loopdb.ChannelSet , pluginType RoutingPluginType ,
695- reportPluginResult bool ) (* lndclient.PaymentStatus , error ) {
697+ outgoingChanIds loopdb.ChannelSet , paymentTimeout time.Duration ,
698+ pluginType RoutingPluginType , reportPluginResult bool ) (
699+ * lndclient.PaymentStatus , error ) {
696700
697701 // Extract hash from payment request. Unfortunately the request
698702 // components aren't available directly.
@@ -705,7 +709,7 @@ func (s *loopOutSwap) payInvoiceAsync(ctx context.Context,
705709 }
706710
707711 maxRetries := 1
708- paymentTimeout := s .executeConfig .totalPaymentTimeout
712+ totalPaymentTimeout := s .executeConfig .totalPaymentTimeout
709713
710714 // Attempt to acquire and initialize the routing plugin.
711715 routingPlugin , err := AcquireRoutingPlugin (
@@ -720,8 +724,30 @@ func (s *loopOutSwap) payInvoiceAsync(ctx context.Context,
720724 pluginType , hash .String ())
721725
722726 maxRetries = s .executeConfig .maxPaymentRetries
723- paymentTimeout /= time .Duration (maxRetries )
727+
728+ // If not set, default to the per payment timeout to the total
729+ // payment timeout divied by the configured maximum retries.
730+ if paymentTimeout == 0 {
731+ paymentTimeout = totalPaymentTimeout /
732+ time .Duration (maxRetries )
733+ }
734+
735+ // If the payment timeout is too long, we need to adjust the
736+ // number of retries to ensure we don't exceed the total
737+ // payment timeout.
738+ if paymentTimeout * time .Duration (maxRetries ) >
739+ totalPaymentTimeout {
740+
741+ maxRetries = int (totalPaymentTimeout / paymentTimeout )
742+ s .log .Infof ("Adjusted max routing plugin retries to " +
743+ "%v to stay within total payment timeout" ,
744+ maxRetries )
745+ }
724746 defer ReleaseRoutingPlugin (ctx )
747+ } else if paymentTimeout == 0 {
748+ // If not set, default the payment timeout to the total payment
749+ // timeout.
750+ paymentTimeout = totalPaymentTimeout
725751 }
726752
727753 req := lndclient.SendPaymentRequest {
0 commit comments