@@ -838,6 +838,10 @@ const CHECK_CLTV_EXPIRY_SANITY: u32 = MIN_CLTV_EXPIRY_DELTA as u32 - LATENCY_GRA
838
838
#[ allow( dead_code) ]
839
839
const CHECK_CLTV_EXPIRY_SANITY_2 : u32 = MIN_CLTV_EXPIRY_DELTA as u32 - LATENCY_GRACE_PERIOD_BLOCKS - 2 * CLTV_CLAIM_BUFFER ;
840
840
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
+
841
845
/// Information needed for constructing an invoice route hint for this channel.
842
846
#[ derive( Clone , Debug , PartialEq ) ]
843
847
pub struct CounterpartyForwardingInfo {
@@ -2409,15 +2413,26 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
2409
2413
/// Signals that no further retries for the given payment will occur.
2410
2414
///
2411
2415
/// After this method returns, any future calls to [`retry_payment`] for the given `payment_id`
2412
- /// will fail with [`PaymentSendFailure::ParameterError`].
2416
+ /// will fail with [`PaymentSendFailure::ParameterError`]. If no such event has been generated,
2417
+ /// an [`Event::PaymentFailed`] event will be generated as soon as there are no remaining
2418
+ /// pending HTLCs for this payment.
2413
2419
///
2414
2420
/// [`retry_payment`]: Self::retry_payment
2421
+ /// [`Event::PaymentFailed`]: events::Event::PaymentFailed
2415
2422
pub fn no_further_payment_retries ( & self , payment_id : PaymentId ) {
2416
2423
let _persistence_guard = PersistenceNotifierGuard :: notify_on_drop ( & self . total_consistency_lock , & self . persistence_notifier ) ;
2417
2424
2418
2425
let mut outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
2419
2426
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
+ }
2421
2436
}
2422
2437
}
2423
2438
@@ -3248,22 +3263,28 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
3248
3263
final_cltv_expiry_delta : path_last_hop. cltv_expiry_delta ,
3249
3264
} )
3250
3265
} else { None } ;
3251
- self . pending_events . lock ( ) . unwrap ( ) . push (
3252
- events:: Event :: PaymentPathFailed {
3253
- payment_id : Some ( payment_id) ,
3254
- payment_hash,
3255
- rejected_by_dest : false ,
3256
- network_update : None ,
3257
- all_paths_failed : payment. get ( ) . remaining_parts ( ) == 0 ,
3258
- path : path. clone ( ) ,
3259
- short_channel_id : None ,
3260
- retry,
3261
- #[ cfg( test) ]
3262
- error_code : None ,
3263
- #[ cfg( test) ]
3264
- error_data : None ,
3265
- }
3266
- ) ;
3266
+ let mut pending_events = self . pending_events . lock ( ) . unwrap ( ) ;
3267
+ pending_events. push ( events:: Event :: PaymentPathFailed {
3268
+ payment_id : Some ( payment_id) ,
3269
+ payment_hash,
3270
+ rejected_by_dest : false ,
3271
+ network_update : None ,
3272
+ all_paths_failed : payment. get ( ) . remaining_parts ( ) == 0 ,
3273
+ path : path. clone ( ) ,
3274
+ short_channel_id : None ,
3275
+ retry,
3276
+ #[ cfg( test) ]
3277
+ error_code : None ,
3278
+ #[ cfg( test) ]
3279
+ error_data : None ,
3280
+ } ) ;
3281
+ if payment. get ( ) . retries_exceeded ( ) && payment. get ( ) . remaining_parts ( ) == 0 {
3282
+ pending_events. push ( events:: Event :: PaymentFailed {
3283
+ payment_id,
3284
+ payment_hash : payment. get ( ) . payment_hash ( ) . expect ( "RetriesExceeded PendintOutboundPayments always have a payment hash set" ) ,
3285
+ } ) ;
3286
+ payment. remove ( ) ;
3287
+ }
3267
3288
}
3268
3289
} else {
3269
3290
log_trace ! ( self . logger, "Received duplicative fail for HTLC with payment_hash {}" , log_bytes!( payment_hash. 0 ) ) ;
@@ -3294,6 +3315,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
3294
3315
session_priv_bytes. copy_from_slice ( & session_priv[ ..] ) ;
3295
3316
let mut outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
3296
3317
let mut all_paths_failed = false ;
3318
+ let mut full_failure_ev = None ;
3297
3319
if let hash_map:: Entry :: Occupied ( mut payment) = outbounds. entry ( payment_id) {
3298
3320
if !payment. get_mut ( ) . remove ( & session_priv_bytes, Some ( & path) ) {
3299
3321
log_trace ! ( self . logger, "Received duplicative fail for HTLC with payment_hash {}" , log_bytes!( payment_hash. 0 ) ) ;
@@ -3305,6 +3327,13 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
3305
3327
}
3306
3328
if payment. get ( ) . remaining_parts ( ) == 0 {
3307
3329
all_paths_failed = true ;
3330
+ if payment. get ( ) . retries_exceeded ( ) {
3331
+ full_failure_ev = Some ( events:: Event :: PaymentFailed {
3332
+ payment_id,
3333
+ payment_hash : payment. get ( ) . payment_hash ( ) . expect ( "RetriesExceeded PendintOutboundPayments always have a payment hash set" ) ,
3334
+ } ) ;
3335
+ payment. remove ( ) ;
3336
+ }
3308
3337
}
3309
3338
} else {
3310
3339
log_trace ! ( self . logger, "Received duplicative fail for HTLC with payment_hash {}" , log_bytes!( payment_hash. 0 ) ) ;
@@ -3320,6 +3349,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
3320
3349
} )
3321
3350
} else { None } ;
3322
3351
log_trace ! ( self . logger, "Failing outbound payment HTLC with payment_hash {}" , log_bytes!( payment_hash. 0 ) ) ;
3352
+
3323
3353
match & onion_error {
3324
3354
& HTLCFailReason :: LightningError { ref err } => {
3325
3355
#[ cfg( test) ]
@@ -3329,22 +3359,22 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
3329
3359
// TODO: If we decided to blame ourselves (or one of our channels) in
3330
3360
// process_onion_failure we should close that channel as it implies our
3331
3361
// next-hop is needlessly blaming us!
3332
- self . pending_events . lock ( ) . unwrap ( ) . push (
3333
- events:: Event :: PaymentPathFailed {
3334
- payment_id : Some ( payment_id) ,
3335
- payment_hash : payment_hash. clone ( ) ,
3336
- rejected_by_dest : !payment_retryable,
3337
- network_update,
3338
- all_paths_failed,
3339
- path : path. clone ( ) ,
3340
- short_channel_id,
3341
- retry,
3362
+ let mut pending_events = self . pending_events . lock ( ) . unwrap ( ) ;
3363
+ pending_events . push ( events:: Event :: PaymentPathFailed {
3364
+ payment_id : Some ( payment_id) ,
3365
+ payment_hash : payment_hash. clone ( ) ,
3366
+ rejected_by_dest : !payment_retryable,
3367
+ network_update,
3368
+ all_paths_failed,
3369
+ path : path. clone ( ) ,
3370
+ short_channel_id,
3371
+ retry,
3342
3372
#[ cfg( test) ]
3343
- error_code : onion_error_code,
3373
+ error_code : onion_error_code,
3344
3374
#[ cfg( test) ]
3345
- error_data : onion_error_data
3346
- }
3347
- ) ;
3375
+ error_data : onion_error_data
3376
+ } ) ;
3377
+ if let Some ( ev ) = full_failure_ev { pending_events . push ( ev ) ; }
3348
3378
} ,
3349
3379
& HTLCFailReason :: Reason {
3350
3380
#[ cfg( test) ]
@@ -3359,22 +3389,22 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
3359
3389
// ChannelDetails.
3360
3390
// TODO: For non-temporary failures, we really should be closing the
3361
3391
// channel here as we apparently can't relay through them anyway.
3362
- self . pending_events . lock ( ) . unwrap ( ) . push (
3363
- events:: Event :: PaymentPathFailed {
3364
- payment_id : Some ( payment_id) ,
3365
- payment_hash : payment_hash. clone ( ) ,
3366
- rejected_by_dest : path. len ( ) == 1 ,
3367
- network_update : None ,
3368
- all_paths_failed,
3369
- path : path. clone ( ) ,
3370
- short_channel_id : Some ( path. first ( ) . unwrap ( ) . short_channel_id ) ,
3371
- retry,
3392
+ let mut pending_events = self . pending_events . lock ( ) . unwrap ( ) ;
3393
+ pending_events . push ( events:: Event :: PaymentPathFailed {
3394
+ payment_id : Some ( payment_id) ,
3395
+ payment_hash : payment_hash. clone ( ) ,
3396
+ rejected_by_dest : path. len ( ) == 1 ,
3397
+ network_update : None ,
3398
+ all_paths_failed,
3399
+ path : path. clone ( ) ,
3400
+ short_channel_id : Some ( path. first ( ) . unwrap ( ) . short_channel_id ) ,
3401
+ retry,
3372
3402
#[ cfg( test) ]
3373
- error_code : Some ( * failure_code) ,
3403
+ error_code : Some ( * failure_code) ,
3374
3404
#[ cfg( test) ]
3375
- error_data : Some ( data. clone ( ) ) ,
3376
- }
3377
- ) ;
3405
+ error_data : Some ( data. clone ( ) ) ,
3406
+ } ) ;
3407
+ if let Some ( ev ) = full_failure_ev { pending_events . push ( ev ) ; }
3378
3408
}
3379
3409
}
3380
3410
} ,
@@ -4905,14 +4935,19 @@ where
4905
4935
inbound_payment. expiry_time > header. time as u64
4906
4936
} ) ;
4907
4937
4938
+ let mut pending_events = self . pending_events . lock ( ) . unwrap ( ) ;
4908
4939
let mut outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
4909
- outbounds. retain ( |_, payment| {
4910
- const PAYMENT_EXPIRY_BLOCKS : u32 = 3 ;
4940
+ outbounds. retain ( |payment_id, payment| {
4911
4941
if payment. remaining_parts ( ) != 0 { return true }
4912
- if let PendingOutboundPayment :: Retryable { starting_block_height, .. } = payment {
4913
- return * starting_block_height + PAYMENT_EXPIRY_BLOCKS > height
4914
- }
4915
- true
4942
+ if let PendingOutboundPayment :: Retryable { starting_block_height, payment_hash, .. } = payment {
4943
+ if * starting_block_height + PAYMENT_EXPIRY_BLOCKS <= height {
4944
+ log_info ! ( self . logger, "Timing out payment with id {} and hash {}" , log_bytes!( payment_id. 0 ) , log_bytes!( payment_hash. 0 ) ) ;
4945
+ pending_events. push ( events:: Event :: PaymentFailed {
4946
+ payment_id : * payment_id, payment_hash : * payment_hash,
4947
+ } ) ;
4948
+ false
4949
+ } else { true }
4950
+ } else { true }
4916
4951
} ) ;
4917
4952
}
4918
4953
0 commit comments