@@ -838,6 +838,10 @@ const CHECK_CLTV_EXPIRY_SANITY: u32 = MIN_CLTV_EXPIRY_DELTA as u32 - LATENCY_GRA
838838#[ allow( dead_code) ]
839839const CHECK_CLTV_EXPIRY_SANITY_2 : u32 = MIN_CLTV_EXPIRY_DELTA as u32 - LATENCY_GRACE_PERIOD_BLOCKS - 2 * CLTV_CLAIM_BUFFER ;
840840
841+ /// The number of blocks before we consider an outbound payment for expiry if it doesn't have any
842+ /// pending HTLCs in flight.
843+ pub ( crate ) const PAYMENT_EXPIRY_BLOCKS : u32 = 3 ;
844+
841845/// Information needed for constructing an invoice route hint for this channel.
842846#[ derive( Clone , Debug , PartialEq ) ]
843847pub struct CounterpartyForwardingInfo {
@@ -2409,15 +2413,26 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
24092413 /// Signals that no further retries for the given payment will occur.
24102414 ///
24112415 /// After this method returns, any future calls to [`retry_payment`] for the given `payment_id`
2412- /// will fail with an [`PaymentSendFailure::ParameterError`] error.
2416+ /// will fail with an [`PaymentSendFailure::ParameterError`] error. If no such event has been
2417+ /// generated, an [`Event::PaymentFailed`] event will be generated as soon as there are no
2418+ /// remaining pending HTLCs for this payment.
24132419 ///
24142420 /// [`retry_payment`]: Self::retry_payment
2421+ /// [`Event::PaymentFailed`]: events::Event::PaymentFailed
24152422 pub fn no_further_payment_retries ( & self , payment_id : PaymentId ) {
24162423 let _persistence_guard = PersistenceNotifierGuard :: notify_on_drop ( & self . total_consistency_lock , & self . persistence_notifier ) ;
24172424
24182425 let mut outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
24192426 if let hash_map:: Entry :: Occupied ( mut payment) = outbounds. entry ( payment_id) {
2420- let _ = payment. get_mut ( ) . mark_retries_exceeded ( ) ;
2427+ if let Ok ( ( ) ) = payment. get_mut ( ) . mark_retries_exceeded ( ) {
2428+ if payment. get ( ) . remaining_parts ( ) == 0 {
2429+ self . pending_events . lock ( ) . unwrap ( ) . push ( events:: Event :: PaymentFailed {
2430+ payment_id,
2431+ payment_hash : payment. get ( ) . payment_hash ( ) . expect ( "RetriesExceeded PendintOutboundPayments always have a payment hash set" ) ,
2432+ } ) ;
2433+ payment. remove ( ) ;
2434+ }
2435+ }
24212436 }
24222437 }
24232438
@@ -3246,22 +3261,28 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
32463261 final_cltv_expiry_delta : path_last_hop. cltv_expiry_delta ,
32473262 } )
32483263 } else { None } ;
3249- self . pending_events . lock ( ) . unwrap ( ) . push (
3250- events:: Event :: PaymentPathFailed {
3251- payment_id : Some ( payment_id) ,
3252- payment_hash,
3253- rejected_by_dest : false ,
3254- network_update : None ,
3255- all_paths_failed : payment. get ( ) . remaining_parts ( ) == 0 ,
3256- path : path. clone ( ) ,
3257- short_channel_id : None ,
3258- retry,
3259- #[ cfg( test) ]
3260- error_code : None ,
3261- #[ cfg( test) ]
3262- error_data : None ,
3263- }
3264- ) ;
3264+ let mut pending_events = self . pending_events . lock ( ) . unwrap ( ) ;
3265+ pending_events. push ( events:: Event :: PaymentPathFailed {
3266+ payment_id : Some ( payment_id) ,
3267+ payment_hash,
3268+ rejected_by_dest : false ,
3269+ network_update : None ,
3270+ all_paths_failed : payment. get ( ) . remaining_parts ( ) == 0 ,
3271+ path : path. clone ( ) ,
3272+ short_channel_id : None ,
3273+ retry,
3274+ #[ cfg( test) ]
3275+ error_code : None ,
3276+ #[ cfg( test) ]
3277+ error_data : None ,
3278+ } ) ;
3279+ if payment. get ( ) . retries_exceeded ( ) && payment. get ( ) . remaining_parts ( ) == 0 {
3280+ pending_events. push ( events:: Event :: PaymentFailed {
3281+ payment_id,
3282+ payment_hash : payment. get ( ) . payment_hash ( ) . expect ( "RetriesExceeded PendintOutboundPayments always have a payment hash set" ) ,
3283+ } ) ;
3284+ payment. remove ( ) ;
3285+ }
32653286 }
32663287 } else {
32673288 log_trace ! ( self . logger, "Received duplicative fail for HTLC with payment_hash {}" , log_bytes!( payment_hash. 0 ) ) ;
@@ -3292,6 +3313,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
32923313 session_priv_bytes. copy_from_slice ( & session_priv[ ..] ) ;
32933314 let mut outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
32943315 let mut all_paths_failed = false ;
3316+ let mut full_failure_ev = None ;
32953317 if let hash_map:: Entry :: Occupied ( mut payment) = outbounds. entry ( payment_id) {
32963318 if !payment. get_mut ( ) . remove ( & session_priv_bytes, Some ( & path) ) {
32973319 log_trace ! ( self . logger, "Received duplicative fail for HTLC with payment_hash {}" , log_bytes!( payment_hash. 0 ) ) ;
@@ -3303,6 +3325,13 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
33033325 }
33043326 if payment. get ( ) . remaining_parts ( ) == 0 {
33053327 all_paths_failed = true ;
3328+ if payment. get ( ) . retries_exceeded ( ) {
3329+ full_failure_ev = Some ( events:: Event :: PaymentFailed {
3330+ payment_id,
3331+ payment_hash : payment. get ( ) . payment_hash ( ) . expect ( "RetriesExceeded PendintOutboundPayments always have a payment hash set" ) ,
3332+ } ) ;
3333+ payment. remove ( ) ;
3334+ }
33063335 }
33073336 } else {
33083337 log_trace ! ( self . logger, "Received duplicative fail for HTLC with payment_hash {}" , log_bytes!( payment_hash. 0 ) ) ;
@@ -3318,6 +3347,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
33183347 } )
33193348 } else { None } ;
33203349 log_trace ! ( self . logger, "Failing outbound payment HTLC with payment_hash {}" , log_bytes!( payment_hash. 0 ) ) ;
3350+
33213351 match & onion_error {
33223352 & HTLCFailReason :: LightningError { ref err } => {
33233353#[ cfg( test) ]
@@ -3327,22 +3357,22 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
33273357 // TODO: If we decided to blame ourselves (or one of our channels) in
33283358 // process_onion_failure we should close that channel as it implies our
33293359 // next-hop is needlessly blaming us!
3330- self . pending_events . lock ( ) . unwrap ( ) . push (
3331- events:: Event :: PaymentPathFailed {
3332- payment_id : Some ( payment_id) ,
3333- payment_hash : payment_hash. clone ( ) ,
3334- rejected_by_dest : !payment_retryable,
3335- network_update,
3336- all_paths_failed,
3337- path : path. clone ( ) ,
3338- short_channel_id,
3339- retry,
3360+ let mut pending_events = self . pending_events . lock ( ) . unwrap ( ) ;
3361+ pending_events . push ( events:: Event :: PaymentPathFailed {
3362+ payment_id : Some ( payment_id) ,
3363+ payment_hash : payment_hash. clone ( ) ,
3364+ rejected_by_dest : !payment_retryable,
3365+ network_update,
3366+ all_paths_failed,
3367+ path : path. clone ( ) ,
3368+ short_channel_id,
3369+ retry,
33403370#[ cfg( test) ]
3341- error_code : onion_error_code,
3371+ error_code : onion_error_code,
33423372#[ cfg( test) ]
3343- error_data : onion_error_data
3344- }
3345- ) ;
3373+ error_data : onion_error_data
3374+ } ) ;
3375+ if let Some ( ev ) = full_failure_ev { pending_events . push ( ev ) ; }
33463376 } ,
33473377 & HTLCFailReason :: Reason {
33483378#[ cfg( test) ]
@@ -3357,22 +3387,22 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
33573387 // ChannelDetails.
33583388 // TODO: For non-temporary failures, we really should be closing the
33593389 // channel here as we apparently can't relay through them anyway.
3360- self . pending_events . lock ( ) . unwrap ( ) . push (
3361- events:: Event :: PaymentPathFailed {
3362- payment_id : Some ( payment_id) ,
3363- payment_hash : payment_hash. clone ( ) ,
3364- rejected_by_dest : path. len ( ) == 1 ,
3365- network_update : None ,
3366- all_paths_failed,
3367- path : path. clone ( ) ,
3368- short_channel_id : Some ( path. first ( ) . unwrap ( ) . short_channel_id ) ,
3369- retry,
3390+ let mut pending_events = self . pending_events . lock ( ) . unwrap ( ) ;
3391+ pending_events . push ( events:: Event :: PaymentPathFailed {
3392+ payment_id : Some ( payment_id) ,
3393+ payment_hash : payment_hash. clone ( ) ,
3394+ rejected_by_dest : path. len ( ) == 1 ,
3395+ network_update : None ,
3396+ all_paths_failed,
3397+ path : path. clone ( ) ,
3398+ short_channel_id : Some ( path. first ( ) . unwrap ( ) . short_channel_id ) ,
3399+ retry,
33703400#[ cfg( test) ]
3371- error_code : Some ( * failure_code) ,
3401+ error_code : Some ( * failure_code) ,
33723402#[ cfg( test) ]
3373- error_data : Some ( data. clone ( ) ) ,
3374- }
3375- ) ;
3403+ error_data : Some ( data. clone ( ) ) ,
3404+ } ) ;
3405+ if let Some ( ev ) = full_failure_ev { pending_events . push ( ev ) ; }
33763406 }
33773407 }
33783408 } ,
@@ -4901,14 +4931,19 @@ where
49014931 inbound_payment. expiry_time > header. time as u64
49024932 } ) ;
49034933
4934+ let mut pending_events = self . pending_events . lock ( ) . unwrap ( ) ;
49044935 let mut outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
4905- outbounds. retain ( |_, payment| {
4906- const PAYMENT_EXPIRY_BLOCKS : u32 = 3 ;
4936+ outbounds. retain ( |payment_id, payment| {
49074937 if payment. remaining_parts ( ) != 0 { return true }
4908- if let PendingOutboundPayment :: Retryable { starting_block_height, .. } = payment {
4909- return * starting_block_height + PAYMENT_EXPIRY_BLOCKS > height
4910- }
4911- true
4938+ if let PendingOutboundPayment :: Retryable { starting_block_height, payment_hash, .. } = payment {
4939+ if * starting_block_height + PAYMENT_EXPIRY_BLOCKS <= height {
4940+ log_info ! ( self . logger, "Timing out payment with id {} and hash {}" , log_bytes!( payment_id. 0 ) , log_bytes!( payment_hash. 0 ) ) ;
4941+ pending_events. push ( events:: Event :: PaymentFailed {
4942+ payment_id : * payment_id, payment_hash : * payment_hash,
4943+ } ) ;
4944+ false
4945+ } else { true }
4946+ } else { true }
49124947 } ) ;
49134948 }
49144949
0 commit comments