@@ -257,6 +257,10 @@ where
257
257
final_value_msat : invoice. amount_milli_satoshis ( ) . or ( amount_msats) . unwrap ( ) ,
258
258
final_cltv_expiry_delta : invoice. min_final_cltv_expiry ( ) as u32 ,
259
259
} ;
260
+ if has_expired ( & params) {
261
+ log_trace ! ( self . logger, "Invoice expired prior to first send for payment {}" , log_bytes!( payment_hash. 0 ) ) ;
262
+ return Err ( PaymentError :: Invoice ( "Invoice expired prior to send" ) ) ;
263
+ }
260
264
let first_hops = self . payer . first_hops ( ) ;
261
265
let route = self . router . find_route (
262
266
& payer,
@@ -506,6 +510,25 @@ mod tests {
506
510
. unwrap ( )
507
511
}
508
512
513
+ fn will_expire_in_1_sec_invoice ( payment_preimage : PaymentPreimage ) -> Invoice {
514
+ let payment_hash = Sha256 :: hash ( & payment_preimage. 0 ) ;
515
+ let private_key = SecretKey :: from_slice ( & [ 42 ; 32 ] ) . unwrap ( ) ;
516
+ let timestamp = SystemTime :: now ( )
517
+ . checked_sub ( Duration :: from_secs ( DEFAULT_EXPIRY_TIME - 1 ) )
518
+ . unwrap ( ) ;
519
+ InvoiceBuilder :: new ( Currency :: Bitcoin )
520
+ . description ( "test" . into ( ) )
521
+ . payment_hash ( payment_hash)
522
+ . payment_secret ( PaymentSecret ( [ 0 ; 32 ] ) )
523
+ . timestamp ( timestamp)
524
+ . min_final_cltv_expiry ( 144 )
525
+ . amount_milli_satoshis ( 128 )
526
+ . build_signed ( |hash| {
527
+ Secp256k1 :: new ( ) . sign_recoverable ( hash, & private_key)
528
+ } )
529
+ . unwrap ( )
530
+ }
531
+
509
532
#[ test]
510
533
fn pays_invoice_on_first_attempt ( ) {
511
534
let event_handled = core:: cell:: RefCell :: new ( false ) ;
@@ -721,7 +744,26 @@ mod tests {
721
744
722
745
let payment_preimage = PaymentPreimage ( [ 1 ; 32 ] ) ;
723
746
let invoice = expired_invoice ( payment_preimage) ;
747
+ if let PaymentError :: Invoice ( msg) = invoice_payer. pay_invoice ( & invoice) . unwrap_err ( ) {
748
+ assert_eq ! ( msg, "Invoice expired prior to send" ) ;
749
+ } else { panic ! ( "Expected Invoice Error" ) ; }
750
+ }
751
+
752
+ #[ test]
753
+ fn fails_retrying_invoice_after_expiration ( ) {
754
+ let event_handled = core:: cell:: RefCell :: new ( false ) ;
755
+ let event_handler = |_: & _ | { * event_handled. borrow_mut ( ) = true ; } ;
756
+
757
+ let payer = TestPayer :: new ( ) ;
758
+ let router = TestRouter { } ;
759
+ let logger = TestLogger :: new ( ) ;
760
+ let invoice_payer =
761
+ InvoicePayer :: new ( & payer, router, & logger, event_handler, RetryAttempts ( 2 ) ) ;
762
+
763
+ let payment_preimage = PaymentPreimage ( [ 1 ; 32 ] ) ;
764
+ let invoice = will_expire_in_1_sec_invoice ( payment_preimage) ;
724
765
let payment_id = Some ( invoice_payer. pay_invoice ( & invoice) . unwrap ( ) ) ;
766
+ std:: thread:: sleep ( Duration :: from_secs ( 2 ) ) ;
725
767
assert_eq ! ( * payer. attempts. borrow( ) , 1 ) ;
726
768
727
769
let event = Event :: PaymentPathFailed {
0 commit comments