Skip to content

Commit 199d258

Browse files
committed
Check for invoice expiry in InvoicePayer before we send any HTLCs
1 parent 9c5dccd commit 199d258

File tree

1 file changed

+28
-1
lines changed

1 file changed

+28
-1
lines changed

lightning-invoice/src/payment.rs

+28-1
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,10 @@ where
253253
) -> Result<PaymentId, PaymentError> {
254254
debug_assert!(invoice.amount_milli_satoshis().is_some() ^ amount_msats.is_some());
255255
let payment_hash = PaymentHash(invoice.payment_hash().clone().into_inner());
256+
if invoice.is_expired() {
257+
log_trace!(self.logger, "Invoice expired prior to first send for payment {}", log_bytes!(payment_hash.0));
258+
return Err(PaymentError::Invoice("Invoice expired prior to send"));
259+
}
256260
let retry_data_payment_id = loop {
257261
let mut payment_cache = self.payment_cache.lock().unwrap();
258262
match payment_cache.entry(payment_hash) {
@@ -728,9 +732,32 @@ mod tests {
728732

729733
let payment_preimage = PaymentPreimage([1; 32]);
730734
let invoice = expired_invoice(payment_preimage);
735+
if let PaymentError::Invoice(msg) = invoice_payer.pay_invoice(&invoice).unwrap_err() {
736+
assert_eq!(msg, "Invoice expired prior to send");
737+
} else { panic!("Expected Invoice Error"); }
738+
}
739+
740+
#[test]
741+
fn fails_retrying_invoice_after_expiration() {
742+
let event_handled = core::cell::RefCell::new(false);
743+
let event_handler = |_: &_| { *event_handled.borrow_mut() = true; };
744+
745+
let payer = TestPayer::new();
746+
let router = TestRouter {};
747+
let scorer = RefCell::new(TestScorer::new());
748+
let logger = TestLogger::new();
749+
let invoice_payer =
750+
InvoicePayer::new(&payer, router, &scorer, &logger, event_handler, RetryAttempts(2));
751+
752+
let payment_preimage = PaymentPreimage([1; 32]);
753+
let invoice = invoice(payment_preimage);
731754
let payment_id = Some(invoice_payer.pay_invoice(&invoice).unwrap());
732755
assert_eq!(*payer.attempts.borrow(), 1);
733756

757+
let mut retry_data = TestRouter::retry_for_invoice(&invoice);
758+
retry_data.payee.expiry_time = Some(SystemTime::now()
759+
.checked_sub(Duration::from_secs(2)).unwrap()
760+
.duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs());
734761
let event = Event::PaymentPathFailed {
735762
payment_id,
736763
payment_hash: PaymentHash(invoice.payment_hash().clone().into_inner()),
@@ -739,7 +766,7 @@ mod tests {
739766
all_paths_failed: false,
740767
path: vec![],
741768
short_channel_id: None,
742-
retry: Some(TestRouter::retry_for_invoice(&invoice)),
769+
retry: Some(retry_data),
743770
};
744771
invoice_payer.handle_event(&event);
745772
assert_eq!(*event_handled.borrow(), true);

0 commit comments

Comments
 (0)