Skip to content

Commit b61a7a2

Browse files
committed
lightning-invoice/utils: Actually add expiry to invoices
1 parent dc8479a commit b61a7a2

File tree

2 files changed

+42
-18
lines changed

2 files changed

+42
-18
lines changed

lightning-invoice/src/payment.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1558,7 +1558,7 @@ mod tests {
15581558

15591559
assert!(invoice_payer.pay_invoice(&create_invoice_from_channelmanager_and_duration_since_epoch(
15601560
&nodes[1].node, nodes[1].keys_manager, Currency::Bitcoin, Some(100_010_000), "Invoice".to_string(),
1561-
duration_since_epoch()).unwrap())
1561+
duration_since_epoch(), 3600).unwrap())
15621562
.is_ok());
15631563
let htlc_msgs = nodes[0].node.get_and_clear_pending_msg_events();
15641564
assert_eq!(htlc_msgs.len(), 2);
@@ -1604,7 +1604,7 @@ mod tests {
16041604

16051605
assert!(invoice_payer.pay_invoice(&create_invoice_from_channelmanager_and_duration_since_epoch(
16061606
&nodes[1].node, nodes[1].keys_manager, Currency::Bitcoin, Some(100_010_000), "Invoice".to_string(),
1607-
duration_since_epoch()).unwrap())
1607+
duration_since_epoch(), 3600).unwrap())
16081608
.is_ok());
16091609
let htlc_msgs = nodes[0].node.get_and_clear_pending_msg_events();
16101610
assert_eq!(htlc_msgs.len(), 2);
@@ -1686,7 +1686,7 @@ mod tests {
16861686

16871687
assert!(invoice_payer.pay_invoice(&create_invoice_from_channelmanager_and_duration_since_epoch(
16881688
&nodes[1].node, nodes[1].keys_manager, Currency::Bitcoin, Some(100_010_000), "Invoice".to_string(),
1689-
duration_since_epoch()).unwrap())
1689+
duration_since_epoch(), 3600).unwrap())
16901690
.is_ok());
16911691
let htlc_updates = SendEvent::from_node(&nodes[0]);
16921692
check_added_monitors!(nodes[0], 1);

lightning-invoice/src/utils.rs

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,8 @@ fn _create_phantom_invoice<Signer: Sign, K: Deref>(
162162
.current_timestamp()
163163
.payment_hash(Hash::from_slice(&payment_hash.0).unwrap())
164164
.payment_secret(payment_secret)
165-
.min_final_cltv_expiry(MIN_FINAL_CLTV_EXPIRY.into());
165+
.min_final_cltv_expiry(MIN_FINAL_CLTV_EXPIRY.into())
166+
.expiry_time(Duration::from_secs(invoice_expiry_delta_secs.into()));
166167
if let Some(amt) = amt_msat {
167168
invoice = invoice.amount_milli_satoshis(amt);
168169
}
@@ -212,9 +213,12 @@ fn _create_phantom_invoice<Signer: Sign, K: Deref>(
212213
/// method stores the invoice's payment secret and preimage in `ChannelManager`, so (a) the user
213214
/// doesn't have to store preimage/payment secret information and (b) `ChannelManager` can verify
214215
/// that the payment secret is valid when the invoice is paid.
216+
///
217+
/// `invoice_expiry_delta_secs` describes the number of seconds that the invoice is valid for
218+
/// in excess of the current time.
215219
pub fn create_invoice_from_channelmanager<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>(
216220
channelmanager: &ChannelManager<Signer, M, T, K, F, L>, keys_manager: K, network: Currency,
217-
amt_msat: Option<u64>, description: String
221+
amt_msat: Option<u64>, description: String, invoice_expiry_delta_secs: u32
218222
) -> Result<Invoice, SignOrCreationError<()>>
219223
where
220224
M::Target: chain::Watch<Signer>,
@@ -227,7 +231,7 @@ where
227231
let duration = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)
228232
.expect("for the foreseeable future this shouldn't happen");
229233
create_invoice_from_channelmanager_and_duration_since_epoch(
230-
channelmanager, keys_manager, network, amt_msat, description, duration
234+
channelmanager, keys_manager, network, amt_msat, description, duration, invoice_expiry_delta_secs
231235
)
232236
}
233237

@@ -238,9 +242,12 @@ where
238242
/// doesn't have to store preimage/payment secret information and (b) `ChannelManager` can verify
239243
/// that the payment secret is valid when the invoice is paid.
240244
/// Use this variant if you want to pass the `description_hash` to the invoice.
245+
///
246+
/// `invoice_expiry_delta_secs` describes the number of seconds that the invoice is valid for
247+
/// in excess of the current time.
241248
pub fn create_invoice_from_channelmanager_with_description_hash<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>(
242249
channelmanager: &ChannelManager<Signer, M, T, K, F, L>, keys_manager: K, network: Currency,
243-
amt_msat: Option<u64>, description_hash: Sha256,
250+
amt_msat: Option<u64>, description_hash: Sha256, invoice_expiry_delta_secs: u32
244251
) -> Result<Invoice, SignOrCreationError<()>>
245252
where
246253
M::Target: chain::Watch<Signer>,
@@ -256,7 +263,7 @@ where
256263
.expect("for the foreseeable future this shouldn't happen");
257264

258265
create_invoice_from_channelmanager_with_description_hash_and_duration_since_epoch(
259-
channelmanager, keys_manager, network, amt_msat, description_hash, duration,
266+
channelmanager, keys_manager, network, amt_msat, description_hash, duration, invoice_expiry_delta_secs
260267
)
261268
}
262269

@@ -265,7 +272,7 @@ where
265272
/// available and the current time is supplied by the caller.
266273
pub fn create_invoice_from_channelmanager_with_description_hash_and_duration_since_epoch<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>(
267274
channelmanager: &ChannelManager<Signer, M, T, K, F, L>, keys_manager: K, network: Currency,
268-
amt_msat: Option<u64>, description_hash: Sha256, duration_since_epoch: Duration,
275+
amt_msat: Option<u64>, description_hash: Sha256, duration_since_epoch: Duration, invoice_expiry_delta_secs: u32
269276
) -> Result<Invoice, SignOrCreationError<()>>
270277
where
271278
M::Target: chain::Watch<Signer>,
@@ -277,7 +284,7 @@ where
277284
_create_invoice_from_channelmanager_and_duration_since_epoch(
278285
channelmanager, keys_manager, network, amt_msat,
279286
InvoiceDescription::Hash(&description_hash),
280-
duration_since_epoch,
287+
duration_since_epoch, invoice_expiry_delta_secs
281288
)
282289
}
283290

@@ -286,7 +293,7 @@ where
286293
/// available and the current time is supplied by the caller.
287294
pub fn create_invoice_from_channelmanager_and_duration_since_epoch<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>(
288295
channelmanager: &ChannelManager<Signer, M, T, K, F, L>, keys_manager: K, network: Currency,
289-
amt_msat: Option<u64>, description: String, duration_since_epoch: Duration,
296+
amt_msat: Option<u64>, description: String, duration_since_epoch: Duration, invoice_expiry_delta_secs: u32
290297
) -> Result<Invoice, SignOrCreationError<()>>
291298
where
292299
M::Target: chain::Watch<Signer>,
@@ -300,13 +307,14 @@ where
300307
InvoiceDescription::Direct(
301308
&Description::new(description).map_err(SignOrCreationError::CreationError)?,
302309
),
303-
duration_since_epoch,
310+
duration_since_epoch, invoice_expiry_delta_secs
304311
)
305312
}
306313

307314
fn _create_invoice_from_channelmanager_and_duration_since_epoch<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>(
308315
channelmanager: &ChannelManager<Signer, M, T, K, F, L>, keys_manager: K, network: Currency,
309316
amt_msat: Option<u64>, description: InvoiceDescription, duration_since_epoch: Duration,
317+
invoice_expiry_delta_secs: u32
310318
) -> Result<Invoice, SignOrCreationError<()>>
311319
where
312320
M::Target: chain::Watch<Signer>,
@@ -337,7 +345,8 @@ where
337345
.payment_hash(Hash::from_slice(&payment_hash.0).unwrap())
338346
.payment_secret(payment_secret)
339347
.basic_mpp()
340-
.min_final_cltv_expiry(MIN_FINAL_CLTV_EXPIRY.into());
348+
.min_final_cltv_expiry(MIN_FINAL_CLTV_EXPIRY.into())
349+
.expiry_time(Duration::from_secs(invoice_expiry_delta_secs.into()));
341350
if let Some(amt) = amt_msat {
342351
invoice = invoice.amount_milli_satoshis(amt);
343352
}
@@ -528,10 +537,11 @@ mod test {
528537
create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, InitFeatures::known(), InitFeatures::known());
529538
let invoice = create_invoice_from_channelmanager_and_duration_since_epoch(
530539
&nodes[1].node, nodes[1].keys_manager, Currency::BitcoinTestnet, Some(10_000), "test".to_string(),
531-
Duration::from_secs(1234567)).unwrap();
540+
Duration::from_secs(1234567), 3600).unwrap();
532541
assert_eq!(invoice.amount_pico_btc(), Some(100_000));
533542
assert_eq!(invoice.min_final_cltv_expiry(), MIN_FINAL_CLTV_EXPIRY as u64);
534543
assert_eq!(invoice.description(), InvoiceDescription::Direct(&Description("test".to_string())));
544+
assert_eq!(invoice.expiry_time(), Duration::from_secs(3600));
535545

536546
// Invoice SCIDs should always use inbound SCID aliases over the real channel ID, if one is
537547
// available.
@@ -592,7 +602,7 @@ mod test {
592602
let description_hash = crate::Sha256(Hash::hash("Testing description_hash".as_bytes()));
593603
let invoice = ::utils::create_invoice_from_channelmanager_with_description_hash_and_duration_since_epoch(
594604
&nodes[1].node, nodes[1].keys_manager, Currency::BitcoinTestnet, Some(10_000),
595-
description_hash, Duration::from_secs(1234567),
605+
description_hash, Duration::from_secs(1234567), 3600
596606
).unwrap();
597607
assert_eq!(invoice.amount_pico_btc(), Some(100_000));
598608
assert_eq!(invoice.min_final_cltv_expiry(), MIN_FINAL_CLTV_EXPIRY as u64);
@@ -752,7 +762,7 @@ mod test {
752762
) {
753763
let invoice = create_invoice_from_channelmanager_and_duration_since_epoch(
754764
&invoice_node.node, invoice_node.keys_manager, Currency::BitcoinTestnet, invoice_amt, "test".to_string(),
755-
Duration::from_secs(1234567)).unwrap();
765+
Duration::from_secs(1234567), 3600).unwrap();
756766
let hints = invoice.private_routes();
757767

758768
for hint in hints {
@@ -811,6 +821,7 @@ mod test {
811821
assert_eq!(invoice.min_final_cltv_expiry(), MIN_FINAL_CLTV_EXPIRY as u64);
812822
assert_eq!(invoice.description(), InvoiceDescription::Direct(&Description("test".to_string())));
813823
assert_eq!(invoice.route_hints().len(), 2);
824+
assert_eq!(invoice.expiry_time(), Duration::from_secs(3600));
814825
assert!(!invoice.features().unwrap().supports_basic_mpp());
815826

816827
let payment_params = PaymentParameters::from_node_id(invoice.recover_payee_pub_key())
@@ -931,10 +942,23 @@ mod test {
931942
];
932943

933944
let description_hash = crate::Sha256(Hash::hash("Description hash phantom invoice".as_bytes()));
934-
let invoice = ::utils::create_phantom_invoice_with_description_hash::<EnforcingSigner,&test_utils::TestKeysInterface>(Some(payment_amt), None, 3600, description_hash, route_hints, &nodes[1].keys_manager, Currency::BitcoinTestnet).unwrap();
935-
945+
let non_default_invoice_expiry_secs = 4200;
946+
let invoice = ::utils::create_phantom_invoice_with_description_hash::<
947+
EnforcingSigner,
948+
&test_utils::TestKeysInterface,
949+
>(
950+
Some(payment_amt),
951+
None,
952+
non_default_invoice_expiry_secs,
953+
description_hash,
954+
route_hints,
955+
&nodes[1].keys_manager,
956+
Currency::BitcoinTestnet,
957+
)
958+
.unwrap();
936959
assert_eq!(invoice.amount_pico_btc(), Some(200_000));
937960
assert_eq!(invoice.min_final_cltv_expiry(), MIN_FINAL_CLTV_EXPIRY as u64);
961+
assert_eq!(invoice.expiry_time(), Duration::from_secs(non_default_invoice_expiry_secs.into()));
938962
assert_eq!(invoice.description(), InvoiceDescription::Hash(&crate::Sha256(Sha256::hash("Description hash phantom invoice".as_bytes()))));
939963
}
940964

0 commit comments

Comments
 (0)