@@ -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 {
@@ -2411,15 +2415,31 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
24112415 /// Signals that no further retries for the given payment will occur.
24122416 ///
24132417 /// After this method returns, any future calls to [`retry_payment`] for the given `payment_id`
2414- /// will fail with [`PaymentSendFailure::ParameterError`].
2418+ /// will fail with [`PaymentSendFailure::ParameterError`]. If no such event has been generated,
2419+ /// an [`Event::PaymentFailed`] event will be generated as soon as there are no remaining
2420+ /// pending HTLCs for this payment.
2421+ ///
2422+ /// Note that calling this method does *not* prevent a payment from succeeding. You must still
2423+ /// wait until you receive either a [`Event::PaymentFailed`] or [`Event::PaymentSent`] event to
2424+ /// determine the ultimate status of a payment.
24152425 ///
24162426 /// [`retry_payment`]: Self::retry_payment
2427+ /// [`Event::PaymentFailed`]: events::Event::PaymentFailed
2428+ /// [`Event::PaymentSent`]: events::Event::PaymentSent
24172429 pub fn abandon_payment ( & self , payment_id : PaymentId ) {
24182430 let _persistence_guard = PersistenceNotifierGuard :: notify_on_drop ( & self . total_consistency_lock , & self . persistence_notifier ) ;
24192431
24202432 let mut outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
24212433 if let hash_map:: Entry :: Occupied ( mut payment) = outbounds. entry ( payment_id) {
2422- let _ = payment. get_mut ( ) . mark_abandoned ( ) ;
2434+ if let Ok ( ( ) ) = payment. get_mut ( ) . mark_abandoned ( ) {
2435+ if payment. get ( ) . remaining_parts ( ) == 0 {
2436+ self . pending_events . lock ( ) . unwrap ( ) . push ( events:: Event :: PaymentFailed {
2437+ payment_id,
2438+ payment_hash : payment. get ( ) . payment_hash ( ) . expect ( "PendingOutboundPayments::RetriesExceeded always has a payment hash set" ) ,
2439+ } ) ;
2440+ payment. remove ( ) ;
2441+ }
2442+ }
24232443 }
24242444 }
24252445
@@ -3250,22 +3270,28 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
32503270 final_cltv_expiry_delta : path_last_hop. cltv_expiry_delta ,
32513271 } )
32523272 } else { None } ;
3253- self . pending_events . lock ( ) . unwrap ( ) . push (
3254- events:: Event :: PaymentPathFailed {
3255- payment_id : Some ( payment_id) ,
3256- payment_hash,
3257- rejected_by_dest : false ,
3258- network_update : None ,
3259- all_paths_failed : payment. get ( ) . remaining_parts ( ) == 0 ,
3260- path : path. clone ( ) ,
3261- short_channel_id : None ,
3262- retry,
3263- #[ cfg( test) ]
3264- error_code : None ,
3265- #[ cfg( test) ]
3266- error_data : None ,
3267- }
3268- ) ;
3273+ let mut pending_events = self . pending_events . lock ( ) . unwrap ( ) ;
3274+ pending_events. push ( events:: Event :: PaymentPathFailed {
3275+ payment_id : Some ( payment_id) ,
3276+ payment_hash,
3277+ rejected_by_dest : false ,
3278+ network_update : None ,
3279+ all_paths_failed : payment. get ( ) . remaining_parts ( ) == 0 ,
3280+ path : path. clone ( ) ,
3281+ short_channel_id : None ,
3282+ retry,
3283+ #[ cfg( test) ]
3284+ error_code : None ,
3285+ #[ cfg( test) ]
3286+ error_data : None ,
3287+ } ) ;
3288+ if payment. get ( ) . abandoned ( ) && payment. get ( ) . remaining_parts ( ) == 0 {
3289+ pending_events. push ( events:: Event :: PaymentFailed {
3290+ payment_id,
3291+ payment_hash : payment. get ( ) . payment_hash ( ) . expect ( "PendingOutboundPayments::RetriesExceeded always has a payment hash set" ) ,
3292+ } ) ;
3293+ payment. remove ( ) ;
3294+ }
32693295 }
32703296 } else {
32713297 log_trace ! ( self . logger, "Received duplicative fail for HTLC with payment_hash {}" , log_bytes!( payment_hash. 0 ) ) ;
@@ -3296,6 +3322,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
32963322 session_priv_bytes. copy_from_slice ( & session_priv[ ..] ) ;
32973323 let mut outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
32983324 let mut all_paths_failed = false ;
3325+ let mut full_failure_ev = None ;
32993326 if let hash_map:: Entry :: Occupied ( mut payment) = outbounds. entry ( payment_id) {
33003327 if !payment. get_mut ( ) . remove ( & session_priv_bytes, Some ( & path) ) {
33013328 log_trace ! ( self . logger, "Received duplicative fail for HTLC with payment_hash {}" , log_bytes!( payment_hash. 0 ) ) ;
@@ -3307,6 +3334,13 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
33073334 }
33083335 if payment. get ( ) . remaining_parts ( ) == 0 {
33093336 all_paths_failed = true ;
3337+ if payment. get ( ) . abandoned ( ) {
3338+ full_failure_ev = Some ( events:: Event :: PaymentFailed {
3339+ payment_id,
3340+ payment_hash : payment. get ( ) . payment_hash ( ) . expect ( "PendingOutboundPayments::RetriesExceeded always has a payment hash set" ) ,
3341+ } ) ;
3342+ payment. remove ( ) ;
3343+ }
33103344 }
33113345 } else {
33123346 log_trace ! ( self . logger, "Received duplicative fail for HTLC with payment_hash {}" , log_bytes!( payment_hash. 0 ) ) ;
@@ -3322,7 +3356,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
33223356 } )
33233357 } else { None } ;
33243358 log_trace ! ( self . logger, "Failing outbound payment HTLC with payment_hash {}" , log_bytes!( payment_hash. 0 ) ) ;
3325- match & onion_error {
3359+
3360+ let path_failure = match & onion_error {
33263361 & HTLCFailReason :: LightningError { ref err } => {
33273362#[ cfg( test) ]
33283363 let ( network_update, short_channel_id, payment_retryable, onion_error_code, onion_error_data) = onion_utils:: process_onion_failure ( & self . secp_ctx , & self . logger , & source, err. data . clone ( ) ) ;
@@ -3331,22 +3366,20 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
33313366 // TODO: If we decided to blame ourselves (or one of our channels) in
33323367 // process_onion_failure we should close that channel as it implies our
33333368 // next-hop is needlessly blaming us!
3334- self . pending_events . lock ( ) . unwrap ( ) . push (
3335- events:: Event :: PaymentPathFailed {
3336- payment_id : Some ( payment_id) ,
3337- payment_hash : payment_hash. clone ( ) ,
3338- rejected_by_dest : !payment_retryable,
3339- network_update,
3340- all_paths_failed,
3341- path : path. clone ( ) ,
3342- short_channel_id,
3343- retry,
3369+ events:: Event :: PaymentPathFailed {
3370+ payment_id : Some ( payment_id) ,
3371+ payment_hash : payment_hash. clone ( ) ,
3372+ rejected_by_dest : !payment_retryable,
3373+ network_update,
3374+ all_paths_failed,
3375+ path : path. clone ( ) ,
3376+ short_channel_id,
3377+ retry,
33443378#[ cfg( test) ]
3345- error_code : onion_error_code,
3379+ error_code : onion_error_code,
33463380#[ cfg( test) ]
3347- error_data : onion_error_data
3348- }
3349- ) ;
3381+ error_data : onion_error_data
3382+ }
33503383 } ,
33513384 & HTLCFailReason :: Reason {
33523385#[ cfg( test) ]
@@ -3361,24 +3394,25 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
33613394 // ChannelDetails.
33623395 // TODO: For non-temporary failures, we really should be closing the
33633396 // channel here as we apparently can't relay through them anyway.
3364- self . pending_events . lock ( ) . unwrap ( ) . push (
3365- events:: Event :: PaymentPathFailed {
3366- payment_id : Some ( payment_id) ,
3367- payment_hash : payment_hash. clone ( ) ,
3368- rejected_by_dest : path. len ( ) == 1 ,
3369- network_update : None ,
3370- all_paths_failed,
3371- path : path. clone ( ) ,
3372- short_channel_id : Some ( path. first ( ) . unwrap ( ) . short_channel_id ) ,
3373- retry,
3397+ events:: Event :: PaymentPathFailed {
3398+ payment_id : Some ( payment_id) ,
3399+ payment_hash : payment_hash. clone ( ) ,
3400+ rejected_by_dest : path. len ( ) == 1 ,
3401+ network_update : None ,
3402+ all_paths_failed,
3403+ path : path. clone ( ) ,
3404+ short_channel_id : Some ( path. first ( ) . unwrap ( ) . short_channel_id ) ,
3405+ retry,
33743406#[ cfg( test) ]
3375- error_code : Some ( * failure_code) ,
3407+ error_code : Some ( * failure_code) ,
33763408#[ cfg( test) ]
3377- error_data : Some ( data. clone ( ) ) ,
3378- }
3379- ) ;
3409+ error_data : Some ( data. clone ( ) ) ,
3410+ }
33803411 }
3381- }
3412+ } ;
3413+ let mut pending_events = self . pending_events . lock ( ) . unwrap ( ) ;
3414+ pending_events. push ( path_failure) ;
3415+ if let Some ( ev) = full_failure_ev { pending_events. push ( ev) ; }
33823416 } ,
33833417 HTLCSource :: PreviousHopData ( HTLCPreviousHopData { short_channel_id, htlc_id, incoming_packet_shared_secret, .. } ) => {
33843418 let err_packet = match onion_error {
@@ -4907,14 +4941,19 @@ where
49074941 inbound_payment. expiry_time > header. time as u64
49084942 } ) ;
49094943
4944+ let mut pending_events = self . pending_events . lock ( ) . unwrap ( ) ;
49104945 let mut outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
4911- outbounds. retain ( |_, payment| {
4912- const PAYMENT_EXPIRY_BLOCKS : u32 = 3 ;
4946+ outbounds. retain ( |payment_id, payment| {
49134947 if payment. remaining_parts ( ) != 0 { return true }
4914- if let PendingOutboundPayment :: Retryable { starting_block_height, .. } = payment {
4915- return * starting_block_height + PAYMENT_EXPIRY_BLOCKS > height
4916- }
4917- true
4948+ if let PendingOutboundPayment :: Retryable { starting_block_height, payment_hash, .. } = payment {
4949+ if * starting_block_height + PAYMENT_EXPIRY_BLOCKS <= height {
4950+ log_info ! ( self . logger, "Timing out payment with id {} and hash {}" , log_bytes!( payment_id. 0 ) , log_bytes!( payment_hash. 0 ) ) ;
4951+ pending_events. push ( events:: Event :: PaymentFailed {
4952+ payment_id : * payment_id, payment_hash : * payment_hash,
4953+ } ) ;
4954+ false
4955+ } else { true }
4956+ } else { true }
49184957 } ) ;
49194958 }
49204959
0 commit comments