@@ -52,6 +52,8 @@ use crate::ln::onion_utils;
5252use crate :: ln:: onion_utils:: HTLCFailReason ;
5353use crate :: ln:: msgs:: { ChannelMessageHandler , DecodeError , LightningError , MAX_VALUE_MSAT } ;
5454use crate :: ln:: payment_retry:: { PaymentAttempts , Retry } ;
55+ #[ cfg( feature = "std" ) ]
56+ use crate :: ln:: payment_retry:: has_expired;
5557use crate :: ln:: wire:: Encode ;
5658use crate :: chain:: keysinterface:: { Sign , KeysInterface , KeysManager , Recipient } ;
5759use crate :: util:: config:: { UserConfig , ChannelConfig } ;
@@ -2607,6 +2609,47 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, R: Deref, L: Deref> ChannelManager<
26072609 self . send_payment_internal ( route, payment_hash, payment_secret, None , payment_id, None , onion_session_privs)
26082610 }
26092611
2612+ /// Similar to [`ChannelManager::send_payment`], but will automatically find a route based on
2613+ /// `route_params` and retry failed payment paths based on `retry_strategy`.
2614+ pub fn send_payment_with_retry ( & self , payment_hash : PaymentHash , payment_secret : & Option < PaymentSecret > , payment_id : PaymentId , route_params : RouteParameters , retry_strategy : Retry ) -> Result < ( ) , PaymentSendFailure > {
2615+ #[ cfg( feature = "std" ) ] {
2616+ if has_expired ( & route_params) {
2617+ log_trace ! ( self . logger, "Invoice expired prior to send for payment {}" , log_bytes!( payment_hash. 0 ) ) ;
2618+ return Err ( PaymentSendFailure :: ParameterError ( APIError :: APIMisuseError { err : format ! ( "Invoice expired prior to send for payment {}" , log_bytes!( payment_hash. 0 ) ) } ) ) ;
2619+ }
2620+ }
2621+
2622+ let route = self . router . find_route (
2623+ & self . get_our_node_id ( ) , & route_params, Some ( & self . list_usable_channels ( ) . iter ( ) . collect :: < Vec < _ > > ( ) ) ,
2624+ self . compute_inflight_htlcs ( )
2625+ ) . map_err ( |e| PaymentSendFailure :: ParameterError ( APIError :: APIMisuseError {
2626+ err : format ! ( "Failed to find a route for payment {}: {:?}" , log_bytes!( payment_id. 0 ) , e) , // TODO: add APIError::RouteNotFound
2627+ } ) ) ?;
2628+
2629+ log_trace ! ( self . logger, "Attempting to send payment with id {} and hash {} over route {}" , log_bytes!( payment_id. 0 ) , log_bytes!( payment_hash. 0 ) , log_route!( route) ) ;
2630+ let onion_session_privs = self . add_new_pending_payment ( payment_hash, * payment_secret, payment_id, & route, retry_strategy) ?;
2631+ match self . send_payment_internal ( & route, payment_hash, payment_secret, None , payment_id, None , onion_session_privs) {
2632+ Err ( PaymentSendFailure :: AllFailedResendSafe ( _) ) => {
2633+ self . retry_payment_auto_route ( payment_id, route_params)
2634+ } ,
2635+ Err ( PaymentSendFailure :: PartialFailure { failed_paths_retry, .. } ) => {
2636+ if let Some ( retry_data) = failed_paths_retry {
2637+ // Some paths were sent, even if we failed to send the full MPP value our recipient may
2638+ // misbehave and claim the funds, at which point we have to consider the payment sent, so
2639+ // return `Ok()` here, ignoring any retry errors.
2640+ let _ = self . retry_payment_auto_route ( payment_id, retry_data) ;
2641+ Ok ( ( ) )
2642+ } else {
2643+ // This may happen if we send a payment and some paths fail, but only due to a temporary
2644+ // monitor failure or the like, implying they're really in-flight, but we haven't sent the
2645+ // initial HTLC-Add messages yet.
2646+ Ok ( ( ) )
2647+ }
2648+ } ,
2649+ res => res,
2650+ }
2651+ }
2652+
26102653 #[ cfg( test) ]
26112654 pub ( crate ) fn test_add_new_pending_payment ( & self , payment_hash : PaymentHash , payment_secret : Option < PaymentSecret > , payment_id : PaymentId , route : & Route ) -> Result < Vec < [ u8 ; 32 ] > , PaymentSendFailure > {
26122655 self . add_new_pending_payment ( payment_hash, payment_secret, payment_id, route, Retry :: Attempts ( 0 ) )
@@ -2732,16 +2775,58 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, R: Deref, L: Deref> ChannelManager<
27322775 } else { None } ,
27332776 } )
27342777 } else if has_err {
2735- // If we failed to send any paths, we should remove the new PaymentId from the
2736- // `pending_outbound_payments` map, as the user isn't expected to `abandon_payment`.
2737- let removed = self . pending_outbound_payments . lock ( ) . unwrap ( ) . remove ( & payment_id) . is_some ( ) ;
2738- debug_assert ! ( removed, "We should always have a pending payment to remove here" ) ;
2778+ if !self . pending_outbound_payments . lock ( ) . unwrap ( ) . get ( & payment_id)
2779+ . map_or ( false , |payment| payment. is_retryable ( ) )
2780+ {
2781+ // If we failed to send any paths, we should remove the new PaymentId from the
2782+ // `pending_outbound_payments` map, as the user isn't expected to `abandon_payment`.
2783+ let removed = self . pending_outbound_payments . lock ( ) . unwrap ( ) . remove ( & payment_id) . is_some ( ) ;
2784+ debug_assert ! ( removed, "We should always have a pending payment to remove here" ) ;
2785+ }
27392786 Err ( PaymentSendFailure :: AllFailedResendSafe ( results. drain ( ..) . map ( |r| r. unwrap_err ( ) ) . collect ( ) ) )
27402787 } else {
27412788 Ok ( ( ) )
27422789 }
27432790 }
27442791
2792+ fn retry_payment_auto_route ( & self , payment_id : PaymentId , route_params : RouteParameters ) -> Result < ( ) , PaymentSendFailure > {
2793+ #[ cfg( feature = "std" ) ] {
2794+ if has_expired ( & route_params) {
2795+ return Err ( PaymentSendFailure :: ParameterError ( APIError :: APIMisuseError {
2796+ err : format ! ( "Invoice expired for payment id {}; not retrying" , log_bytes!( payment_id. 0 ) ) ,
2797+ } ) )
2798+ }
2799+ }
2800+
2801+ self . pending_outbound_payments . lock ( ) . unwrap ( ) . get_mut ( & payment_id) . map ( |pmt| pmt. increment_attempts ( ) ) ;
2802+ if !self . pending_outbound_payments . lock ( ) . unwrap ( ) . get ( & payment_id)
2803+ . map_or ( false , |payment| payment. is_retryable ( ) )
2804+ {
2805+ return Err ( PaymentSendFailure :: ParameterError ( APIError :: APIMisuseError {
2806+ err : format ! ( "Payment {} is not retryable" , log_bytes!( payment_id. 0 ) ) ,
2807+ } ) )
2808+ }
2809+
2810+ let route = self . router . find_route (
2811+ & self . get_our_node_id ( ) , & route_params, Some ( & self . list_usable_channels ( ) . iter ( ) . collect :: < Vec < _ > > ( ) ) ,
2812+ self . compute_inflight_htlcs ( )
2813+ ) . map_err ( |e| PaymentSendFailure :: ParameterError ( APIError :: APIMisuseError {
2814+ err : format ! ( "Failed to find a route for payment {}: {:?}" , log_bytes!( payment_id. 0 ) , e) , // TODO: add APIError::RouteNotFound
2815+ } ) ) ?;
2816+
2817+ match self . retry_payment ( & route, payment_id) {
2818+ Err ( PaymentSendFailure :: AllFailedResendSafe ( _) ) => {
2819+ self . retry_payment_auto_route ( payment_id, route_params)
2820+ } ,
2821+ Err ( PaymentSendFailure :: PartialFailure { failed_paths_retry : Some ( retry) , .. } ) => {
2822+ // Always return Ok for the same reason as noted in send_payment_with_retry.
2823+ let _ = self . retry_payment_auto_route ( payment_id, retry) ;
2824+ Ok ( ( ) )
2825+ } ,
2826+ res => res,
2827+ }
2828+ }
2829+
27452830 /// Retries a payment along the given [`Route`].
27462831 ///
27472832 /// Errors returned are a superset of those returned from [`send_payment`], so see
@@ -3600,6 +3685,17 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, R: Deref, L: Deref> ChannelManager<
36003685 }
36013686 }
36023687 }
3688+ {
3689+ let mut retryable_htlcs = Vec :: new ( ) ;
3690+ mem:: swap ( & mut retryable_htlcs, & mut self . retryable_htlcs . lock ( ) . unwrap ( ) ) ;
3691+ for ( payment_id, params) in retryable_htlcs {
3692+ // TODO: do we need to generate a PendingHTLCsForwardable event?
3693+ if let Err ( e) = self . retry_payment_auto_route ( payment_id, params) {
3694+ log_trace ! ( self . logger, "Errored retrying payment, marking as abandoned: {:?}" , e) ;
3695+ self . abandon_payment ( payment_id) ;
3696+ }
3697+ }
3698+ }
36033699
36043700 for ( htlc_source, payment_hash, failure_reason, destination) in failed_forwards. drain ( ..) {
36053701 self . fail_htlc_backwards_internal ( & htlc_source, & payment_hash, & failure_reason, destination) ;
@@ -3966,7 +4062,8 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, R: Deref, L: Deref> ChannelManager<
39664062 let mut outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
39674063 let mut all_paths_failed = false ;
39684064 let mut full_failure_ev = None ;
3969- if let hash_map:: Entry :: Occupied ( mut payment) = outbounds. entry ( * payment_id) {
4065+ let mut pending_retry_ev = None ;
4066+ let attempts_remaining = if let hash_map:: Entry :: Occupied ( mut payment) = outbounds. entry ( * payment_id) {
39704067 if !payment. get_mut ( ) . remove ( & session_priv_bytes, Some ( & path) ) {
39714068 log_trace ! ( self . logger, "Received duplicative fail for HTLC with payment_hash {}" , log_bytes!( payment_hash. 0 ) ) ;
39724069 return ;
@@ -3975,6 +4072,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, R: Deref, L: Deref> ChannelManager<
39754072 log_trace ! ( self . logger, "Received failure of HTLC with payment_hash {} after payment completion" , log_bytes!( payment_hash. 0 ) ) ;
39764073 return ;
39774074 }
4075+ let is_retryable = payment. get ( ) . is_retryable ( ) ;
39784076 if payment. get ( ) . remaining_parts ( ) == 0 {
39794077 all_paths_failed = true ;
39804078 if payment. get ( ) . abandoned ( ) {
@@ -3985,10 +4083,11 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, R: Deref, L: Deref> ChannelManager<
39854083 payment. remove ( ) ;
39864084 }
39874085 }
4086+ is_retryable
39884087 } else {
39894088 log_trace ! ( self . logger, "Received duplicative fail for HTLC with payment_hash {}" , log_bytes!( payment_hash. 0 ) ) ;
39904089 return ;
3991- }
4090+ } ;
39924091 let mut retry = if let Some ( payment_params_data) = payment_params {
39934092 let path_last_hop = path. last ( ) . expect ( "Outbound payments must have had a valid path" ) ;
39944093 Some ( RouteParameters {
@@ -4027,6 +4126,15 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, R: Deref, L: Deref> ChannelManager<
40274126 if let Some ( scid) = short_channel_id {
40284127 retry. as_mut ( ) . map ( |r| r. payment_params . previously_failed_channels . push ( scid) ) ;
40294128 }
4129+ if payment_retryable && attempts_remaining {
4130+ if let Some ( retry_params) = & retry {
4131+ debug_assert ! ( full_failure_ev. is_none( ) ) ;
4132+ pending_retry_ev = Some ( events:: Event :: PendingHTLCsForwardable {
4133+ time_forwardable : Duration :: from_millis ( MIN_HTLC_RELAY_HOLDING_CELL_MILLIS ) ,
4134+ } ) ;
4135+ self . retryable_htlcs . lock ( ) . unwrap ( ) . push ( ( * payment_id, retry_params. clone ( ) ) ) ;
4136+ }
4137+ }
40304138 events:: Event :: PaymentPathFailed {
40314139 payment_id : Some ( * payment_id) ,
40324140 payment_hash : payment_hash. clone ( ) ,
@@ -4046,6 +4154,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, R: Deref, L: Deref> ChannelManager<
40464154 let mut pending_events = self . pending_events . lock ( ) . unwrap ( ) ;
40474155 pending_events. push ( path_failure) ;
40484156 if let Some ( ev) = full_failure_ev { pending_events. push ( ev) ; }
4157+ if let Some ( ev) = pending_retry_ev { pending_events. push ( ev) ; }
40494158 } ,
40504159 HTLCSource :: PreviousHopData ( HTLCPreviousHopData { ref short_channel_id, ref htlc_id, ref incoming_packet_shared_secret, ref phantom_shared_secret, ref outpoint } ) => {
40514160 log_trace ! ( self . logger, "Failing HTLC with payment_hash {} backwards from us with {:?}" , log_bytes!( payment_hash. 0 ) , onion_error) ;
0 commit comments