@@ -314,6 +314,8 @@ where
314
314
log_trace ! ( self . logger, "Payment {} has no id; not retrying (attempts: {})" , log_bytes!( payment_hash. 0 ) , attempts) ;
315
315
} else if * attempts >= max_payment_attempts {
316
316
log_trace ! ( self . logger, "Payment {} exceeded maximum attempts; not retrying (attempts: {})" , log_bytes!( payment_hash. 0 ) , attempts) ;
317
+ } else if invoice. is_expired ( ) {
318
+ log_trace ! ( self . logger, "Invoice expired for payment {}; not retrying (attempts: {})" , log_bytes!( payment_hash. 0 ) , attempts) ;
317
319
} else if path. is_empty ( ) {
318
320
log_trace ! ( self . logger, "Payment {} has empty path; not retrying (attempts: {})" , log_bytes!( payment_hash. 0 ) , attempts) ;
319
321
} else if self . retry_payment ( * payment_id. as_ref ( ) . unwrap ( ) , invoice, path. last ( ) . unwrap ( ) . fee_msat ) . is_err ( ) {
@@ -348,7 +350,7 @@ where
348
350
#[ cfg( test) ]
349
351
mod tests {
350
352
use super :: * ;
351
- use crate :: { InvoiceBuilder , Currency } ;
353
+ use crate :: { DEFAULT_EXPIRY_TIME , InvoiceBuilder , Currency } ;
352
354
use bitcoin_hashes:: sha256:: Hash as Sha256 ;
353
355
use lightning:: ln:: PaymentPreimage ;
354
356
use lightning:: ln:: features:: { ChannelFeatures , NodeFeatures } ;
@@ -358,6 +360,7 @@ mod tests {
358
360
use lightning:: util:: errors:: APIError ;
359
361
use lightning:: util:: events:: Event ;
360
362
use secp256k1:: { SecretKey , PublicKey , Secp256k1 } ;
363
+ use std:: time:: { SystemTime , Duration } ;
361
364
362
365
fn invoice ( payment_preimage : PaymentPreimage ) -> Invoice {
363
366
let payment_hash = Sha256 :: hash ( & payment_preimage. 0 ) ;
@@ -390,6 +393,25 @@ mod tests {
390
393
. unwrap ( )
391
394
}
392
395
396
+ fn expired_invoice ( payment_preimage : PaymentPreimage ) -> Invoice {
397
+ let payment_hash = Sha256 :: hash ( & payment_preimage. 0 ) ;
398
+ let private_key = SecretKey :: from_slice ( & [ 42 ; 32 ] ) . unwrap ( ) ;
399
+ let timestamp = SystemTime :: now ( )
400
+ . checked_sub ( Duration :: from_secs ( DEFAULT_EXPIRY_TIME * 2 ) )
401
+ . unwrap ( ) ;
402
+ InvoiceBuilder :: new ( Currency :: Bitcoin )
403
+ . description ( "test" . into ( ) )
404
+ . payment_hash ( payment_hash)
405
+ . payment_secret ( PaymentSecret ( [ 0 ; 32 ] ) )
406
+ . timestamp ( timestamp)
407
+ . min_final_cltv_expiry ( 144 )
408
+ . amount_milli_satoshis ( 128 )
409
+ . build_signed ( |hash| {
410
+ Secp256k1 :: new ( ) . sign_recoverable ( hash, & private_key)
411
+ } )
412
+ . unwrap ( )
413
+ }
414
+
393
415
#[ test]
394
416
fn pays_invoice_on_first_attempt ( ) {
395
417
let event_handled = core:: cell:: RefCell :: new ( false ) ;
@@ -504,6 +526,36 @@ mod tests {
504
526
assert_eq ! ( * payer. attempts. borrow( ) , 3 ) ;
505
527
}
506
528
529
+ #[ test]
530
+ fn fails_paying_invoice_after_expiration ( ) {
531
+ let event_handled = core:: cell:: RefCell :: new ( false ) ;
532
+ let event_handler = |_: & _ | { * event_handled. borrow_mut ( ) = true ; } ;
533
+
534
+ let payer = TestPayer :: new ( ) ;
535
+ let router = TestRouter { } ;
536
+ let logger = TestLogger :: new ( ) ;
537
+ let invoice_payer =
538
+ InvoicePayer :: new ( & payer, router, & logger, event_handler, RetryAttempts ( 2 ) ) ;
539
+
540
+ let payment_preimage = PaymentPreimage ( [ 1 ; 32 ] ) ;
541
+ let invoice = expired_invoice ( payment_preimage) ;
542
+ let payment_id = Some ( invoice_payer. pay_invoice ( & invoice) . unwrap ( ) ) ;
543
+ assert_eq ! ( * payer. attempts. borrow( ) , 1 ) ;
544
+
545
+ let event = Event :: PaymentPathFailed {
546
+ payment_id,
547
+ payment_hash : PaymentHash ( invoice. payment_hash ( ) . clone ( ) . into_inner ( ) ) ,
548
+ network_update : None ,
549
+ rejected_by_dest : false ,
550
+ all_paths_failed : false ,
551
+ path : vec ! [ ] ,
552
+ short_channel_id : None ,
553
+ } ;
554
+ invoice_payer. handle_event ( & event) ;
555
+ assert_eq ! ( * event_handled. borrow( ) , true ) ;
556
+ assert_eq ! ( * payer. attempts. borrow( ) , 1 ) ;
557
+ }
558
+
507
559
#[ test]
508
560
fn fails_paying_invoice_with_empty_failed_path ( ) {
509
561
let event_handled = core:: cell:: RefCell :: new ( false ) ;
@@ -681,6 +733,7 @@ mod tests {
681
733
682
734
let payment_preimage = PaymentPreimage ( [ 1 ; 32 ] ) ;
683
735
let invoice = zero_value_invoice ( payment_preimage) ;
736
+ let payment_hash = PaymentHash ( invoice. payment_hash ( ) . clone ( ) . into_inner ( ) ) ;
684
737
let final_value_msat = 100 ;
685
738
686
739
let payer = TestPayer :: new ( ) . expect_value_msat ( final_value_msat) ;
@@ -691,7 +744,7 @@ mod tests {
691
744
assert ! ( invoice_payer. pay_zero_value_invoice( & invoice, final_value_msat) . is_ok( ) ) ;
692
745
assert_eq ! ( * payer. attempts. borrow( ) , 1 ) ;
693
746
694
- invoice_payer. handle_event ( & Event :: PaymentSent { payment_preimage } ) ;
747
+ invoice_payer. handle_event ( & Event :: PaymentSent { payment_preimage, payment_hash } ) ;
695
748
assert_eq ! ( * event_handled. borrow( ) , true ) ;
696
749
assert_eq ! ( * payer. attempts. borrow( ) , 1 ) ;
697
750
}
0 commit comments