@@ -313,9 +313,44 @@ impl<T: Time> Display for PaymentAttemptsUsingTime<T> {
313313 }
314314}
315315
316- /// If a payment fails to send, it can be in one of several states. This enum is returned as the
317- /// Err() type describing which state the payment is in, see the description of individual enum
318- /// states for more.
316+ /// If a payment fails to send with [`ChannelManager::send_payment_with_retry`], it can be in one of
317+ /// several states. This enum is returned as the Err() type describing which state the payment is
318+ /// in, see the description of individual enum states for more.
319+ ///
320+ /// [`ChannelManager::send_payment_with_retry`]: crate::ln::channelmanager::ChannelManager::send_payment_with_retry
321+ #[ derive( Clone , Debug ) ]
322+ pub enum RetryableSendFailure {
323+ /// A parameter which was passed to send_payment was invalid, preventing us from attempting to
324+ /// send the payment at all.
325+ ///
326+ /// You can freely resend the payment in full (with the parameter error fixed).
327+ ParameterError ( APIError ) ,
328+ /// A parameter in a single path which was passed to send_payment was invalid, preventing us
329+ /// from attempting to send the payment at all.
330+ ///
331+ /// You can freely resend the payment in full (with the parameter error fixed).
332+ ///
333+ /// The results here are ordered the same as the paths in the route object which was passed to
334+ /// send_payment.
335+ PathParameterError ( Vec < Result < ( ) , APIError > > ) ,
336+ /// All paths which were attempted failed to send, with no channel state change taking place.
337+ /// You can freely resend the payment in full (though you probably want to do so over different
338+ /// paths than the ones selected).
339+ AllFailedResendSafe ( Vec < APIError > ) ,
340+ /// Indicates that a payment for the provided [`PaymentId`] is already in-flight and has not
341+ /// yet completed (i.e. generated an [`Event::PaymentSent`] or [`Event::PaymentFailed`]).
342+ ///
343+ /// [`PaymentId`]: crate::ln::channelmanager::PaymentId
344+ /// [`Event::PaymentSent`]: crate::util::events::Event::PaymentSent
345+ /// [`Event::PaymentFailed`]: crate::util::events::Event::PaymentFailed
346+ DuplicatePayment ,
347+ }
348+
349+ /// If a payment fails to send with [`ChannelManager::send_payment`], it can be in one of several
350+ /// states. This enum is returned as the Err() type describing which state the payment is in, see
351+ /// the description of individual enum states for more.
352+ ///
353+ /// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment
319354#[ derive( Clone , Debug ) ]
320355pub enum PaymentSendFailure {
321356 /// A parameter which was passed to send_payment was invalid, preventing us from attempting to
@@ -379,7 +414,7 @@ impl OutboundPayments {
379414 retry_strategy : Retry , route_params : RouteParameters , router : & R ,
380415 first_hops : Vec < ChannelDetails > , inflight_htlcs : InFlightHtlcs , entropy_source : & ES ,
381416 node_signer : & NS , best_block_height : u32 , logger : & L , send_payment_along_path : F ,
382- ) -> Result < ( ) , PaymentSendFailure >
417+ ) -> Result < ( ) , RetryableSendFailure >
383418 where
384419 R :: Target : Router ,
385420 ES :: Target : EntropySource ,
@@ -388,10 +423,18 @@ impl OutboundPayments {
388423 F : Fn ( & Vec < RouteHop > , & Option < PaymentParameters > , & PaymentHash , & Option < PaymentSecret > , u64 ,
389424 u32 , PaymentId , & Option < PaymentPreimage > , [ u8 ; 32 ] ) -> Result < ( ) , APIError > ,
390425 {
391- self . pay_internal ( payment_id, Some ( ( payment_hash, payment_secret, None , retry_strategy) ) ,
426+ let res = self . pay_internal ( payment_id, Some ( ( payment_hash, payment_secret, None , retry_strategy) ) ,
392427 route_params, router, first_hops, inflight_htlcs, entropy_source, node_signer,
393428 best_block_height, logger, & send_payment_along_path)
394- . map_err ( |e| { self . remove_outbound_if_all_failed ( payment_id, & e) ; e } )
429+ . map_err ( |e| { self . remove_outbound_if_all_failed ( payment_id, & e) ; e } ) ;
430+ match res {
431+ Err ( PaymentSendFailure :: ParameterError ( e) ) => Err ( RetryableSendFailure :: ParameterError ( e) ) ,
432+ Err ( PaymentSendFailure :: PathParameterError ( e) ) => Err ( RetryableSendFailure :: PathParameterError ( e) ) ,
433+ Err ( PaymentSendFailure :: AllFailedResendSafe ( e) ) => Err ( RetryableSendFailure :: AllFailedResendSafe ( e) ) ,
434+ Err ( PaymentSendFailure :: DuplicatePayment ) => Err ( RetryableSendFailure :: DuplicatePayment ) ,
435+ Err ( PaymentSendFailure :: PartialFailure { .. } ) => Ok ( ( ) ) ,
436+ Ok ( ( ) ) => Ok ( ( ) )
437+ }
395438 }
396439
397440 pub ( super ) fn send_payment_with_route < ES : Deref , NS : Deref , F > (
@@ -416,7 +459,7 @@ impl OutboundPayments {
416459 retry_strategy : Retry , route_params : RouteParameters , router : & R ,
417460 first_hops : Vec < ChannelDetails > , inflight_htlcs : InFlightHtlcs , entropy_source : & ES ,
418461 node_signer : & NS , best_block_height : u32 , logger : & L , send_payment_along_path : F
419- ) -> Result < PaymentHash , PaymentSendFailure >
462+ ) -> Result < PaymentHash , RetryableSendFailure >
420463 where
421464 R :: Target : Router ,
422465 ES :: Target : EntropySource ,
@@ -428,11 +471,18 @@ impl OutboundPayments {
428471 let preimage = payment_preimage
429472 . unwrap_or_else ( || PaymentPreimage ( entropy_source. get_secure_random_bytes ( ) ) ) ;
430473 let payment_hash = PaymentHash ( Sha256 :: hash ( & preimage. 0 ) . into_inner ( ) ) ;
431- self . pay_internal ( payment_id, Some ( ( payment_hash, & None , Some ( preimage) , retry_strategy) ) ,
474+ let res = self . pay_internal ( payment_id, Some ( ( payment_hash, & None , Some ( preimage) , retry_strategy) ) ,
432475 route_params, router, first_hops, inflight_htlcs, entropy_source, node_signer,
433476 best_block_height, logger, & send_payment_along_path)
434- . map ( |( ) | payment_hash)
435- . map_err ( |e| { self . remove_outbound_if_all_failed ( payment_id, & e) ; e } )
477+ . map_err ( |e| { self . remove_outbound_if_all_failed ( payment_id, & e) ; e } ) ;
478+ match res {
479+ Err ( PaymentSendFailure :: ParameterError ( e) ) => Err ( RetryableSendFailure :: ParameterError ( e) ) ,
480+ Err ( PaymentSendFailure :: PathParameterError ( e) ) => Err ( RetryableSendFailure :: PathParameterError ( e) ) ,
481+ Err ( PaymentSendFailure :: AllFailedResendSafe ( e) ) => Err ( RetryableSendFailure :: AllFailedResendSafe ( e) ) ,
482+ Err ( PaymentSendFailure :: DuplicatePayment ) => Err ( RetryableSendFailure :: DuplicatePayment ) ,
483+ Err ( PaymentSendFailure :: PartialFailure { .. } ) => Ok ( payment_hash) ,
484+ Ok ( ( ) ) => Ok ( payment_hash) ,
485+ }
436486 }
437487
438488 pub ( super ) fn send_spontaneous_payment_with_route < ES : Deref , NS : Deref , F > (
@@ -1222,19 +1272,22 @@ mod tests {
12221272 final_value_msat : 0 ,
12231273 final_cltv_expiry_delta : 0 ,
12241274 } ;
1225- let err = if on_retry {
1226- outbound_payments. pay_internal (
1275+ if on_retry {
1276+ let err = outbound_payments. pay_internal (
12271277 PaymentId ( [ 0 ; 32 ] ) , None , expired_route_params, & & router, vec ! [ ] , InFlightHtlcs :: new ( ) ,
1228- & & keys_manager, & & keys_manager, 0 , & & logger, & |_, _, _, _, _, _, _, _, _| Ok ( ( ) ) ) . unwrap_err ( )
1278+ & & keys_manager, & & keys_manager, 0 , & & logger, & |_, _, _, _, _, _, _, _, _| Ok ( ( ) ) ) . unwrap_err ( ) ;
1279+ if let PaymentSendFailure :: ParameterError ( APIError :: APIMisuseError { err } ) = err {
1280+ assert ! ( err. contains( "Invoice expired" ) ) ;
1281+ } else { panic ! ( "Unexpected error" ) ; }
12291282 } else {
1230- outbound_payments. send_payment (
1283+ let err = outbound_payments. send_payment (
12311284 PaymentHash ( [ 0 ; 32 ] ) , & None , PaymentId ( [ 0 ; 32 ] ) , Retry :: Attempts ( 0 ) , expired_route_params,
12321285 & & router, vec ! [ ] , InFlightHtlcs :: new ( ) , & & keys_manager, & & keys_manager, 0 , & & logger,
1233- |_, _, _, _, _, _, _, _, _| Ok ( ( ) ) ) . unwrap_err ( )
1234- } ;
1235- if let PaymentSendFailure :: ParameterError ( APIError :: APIMisuseError { err } ) = err {
1236- assert ! ( err . contains ( "Invoice expired" ) ) ;
1237- } else { panic ! ( "Unexpected error" ) ; }
1286+ |_, _, _, _, _, _, _, _, _| Ok ( ( ) ) ) . unwrap_err ( ) ;
1287+ if let RetryableSendFailure :: ParameterError ( APIError :: APIMisuseError { err } ) = err {
1288+ assert ! ( err. contains ( "Invoice expired" ) ) ;
1289+ } else { panic ! ( "Unexpected error" ) ; }
1290+ }
12381291 }
12391292
12401293 #[ test]
@@ -1261,22 +1314,25 @@ mod tests {
12611314 router. expect_find_route ( route_params. clone ( ) ,
12621315 Err ( LightningError { err : String :: new ( ) , action : ErrorAction :: IgnoreError } ) ) ;
12631316
1264- let err = if on_retry {
1317+ if on_retry {
12651318 outbound_payments. add_new_pending_payment ( PaymentHash ( [ 0 ; 32 ] ) , None , PaymentId ( [ 0 ; 32 ] ) , None ,
12661319 & Route { paths : vec ! [ ] , payment_params : None } , Some ( Retry :: Attempts ( 1 ) ) ,
12671320 Some ( route_params. payment_params . clone ( ) ) , & & keys_manager, 0 ) . unwrap ( ) ;
1268- outbound_payments. pay_internal (
1321+ let err = outbound_payments. pay_internal (
12691322 PaymentId ( [ 0 ; 32 ] ) , None , route_params, & & router, vec ! [ ] , InFlightHtlcs :: new ( ) ,
1270- & & keys_manager, & & keys_manager, 0 , & & logger, & |_, _, _, _, _, _, _, _, _| Ok ( ( ) ) ) . unwrap_err ( )
1323+ & & keys_manager, & & keys_manager, 0 , & & logger, & |_, _, _, _, _, _, _, _, _| Ok ( ( ) ) ) . unwrap_err ( ) ;
1324+ if let PaymentSendFailure :: ParameterError ( APIError :: APIMisuseError { err } ) = err {
1325+ assert ! ( err. contains( "Failed to find a route" ) ) ;
1326+ } else { panic ! ( "Unexpected error" ) ; }
12711327 } else {
1272- outbound_payments. send_payment (
1328+ let err = outbound_payments. send_payment (
12731329 PaymentHash ( [ 0 ; 32 ] ) , & None , PaymentId ( [ 0 ; 32 ] ) , Retry :: Attempts ( 0 ) , route_params,
12741330 & & router, vec ! [ ] , InFlightHtlcs :: new ( ) , & & keys_manager, & & keys_manager, 0 , & & logger,
1275- |_, _, _, _, _, _, _, _, _| Ok ( ( ) ) ) . unwrap_err ( )
1276- } ;
1277- if let PaymentSendFailure :: ParameterError ( APIError :: APIMisuseError { err } ) = err {
1278- assert ! ( err . contains ( "Failed to find a route" ) ) ;
1279- } else { panic ! ( "Unexpected error" ) ; }
1331+ |_, _, _, _, _, _, _, _, _| Ok ( ( ) ) ) . unwrap_err ( ) ;
1332+ if let RetryableSendFailure :: ParameterError ( APIError :: APIMisuseError { err } ) = err {
1333+ assert ! ( err. contains ( "Failed to find a route" ) ) ;
1334+ } else { panic ! ( "Unexpected error" ) ; }
1335+ }
12801336 }
12811337
12821338 #[ test]
0 commit comments