11//! Convenient utilities to create an invoice.
22
3- use { CreationError , Currency , DEFAULT_EXPIRY_TIME , Invoice , InvoiceBuilder , SignOrCreationError } ;
3+ use { CreationError , Currency , Invoice , InvoiceBuilder , SignOrCreationError } ;
44use payment:: { Payer , Router } ;
55
66use crate :: { prelude:: * , Description , InvoiceDescription , Sha256 } ;
@@ -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.
215219pub 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 < ( ) > >
219223where
220224 M :: Target : chain:: Watch < Signer > ,
@@ -227,7 +231,8 @@ 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,
235+ description, duration, invoice_expiry_delta_secs
231236 )
232237}
233238
@@ -238,9 +243,12 @@ where
238243/// doesn't have to store preimage/payment secret information and (b) `ChannelManager` can verify
239244/// that the payment secret is valid when the invoice is paid.
240245/// Use this variant if you want to pass the `description_hash` to the invoice.
246+ ///
247+ /// `invoice_expiry_delta_secs` describes the number of seconds that the invoice is valid for
248+ /// in excess of the current time.
241249pub fn create_invoice_from_channelmanager_with_description_hash < Signer : Sign , M : Deref , T : Deref , K : Deref , F : Deref , L : Deref > (
242250 channelmanager : & ChannelManager < Signer , M , T , K , F , L > , keys_manager : K , network : Currency ,
243- amt_msat : Option < u64 > , description_hash : Sha256 ,
251+ amt_msat : Option < u64 > , description_hash : Sha256 , invoice_expiry_delta_secs : u32
244252) -> Result < Invoice , SignOrCreationError < ( ) > >
245253where
246254 M :: Target : chain:: Watch < Signer > ,
@@ -256,7 +264,8 @@ where
256264 . expect ( "for the foreseeable future this shouldn't happen" ) ;
257265
258266 create_invoice_from_channelmanager_with_description_hash_and_duration_since_epoch (
259- channelmanager, keys_manager, network, amt_msat, description_hash, duration,
267+ channelmanager, keys_manager, network, amt_msat,
268+ description_hash, duration, invoice_expiry_delta_secs
260269 )
261270}
262271
@@ -266,6 +275,7 @@ where
266275pub fn create_invoice_from_channelmanager_with_description_hash_and_duration_since_epoch < Signer : Sign , M : Deref , T : Deref , K : Deref , F : Deref , L : Deref > (
267276 channelmanager : & ChannelManager < Signer , M , T , K , F , L > , keys_manager : K , network : Currency ,
268277 amt_msat : Option < u64 > , description_hash : Sha256 , duration_since_epoch : Duration ,
278+ invoice_expiry_delta_secs : u32
269279) -> Result < Invoice , SignOrCreationError < ( ) > >
270280where
271281 M :: Target : chain:: Watch < Signer > ,
@@ -277,7 +287,7 @@ where
277287 _create_invoice_from_channelmanager_and_duration_since_epoch (
278288 channelmanager, keys_manager, network, amt_msat,
279289 InvoiceDescription :: Hash ( & description_hash) ,
280- duration_since_epoch,
290+ duration_since_epoch, invoice_expiry_delta_secs
281291 )
282292}
283293
@@ -287,6 +297,7 @@ where
287297pub fn create_invoice_from_channelmanager_and_duration_since_epoch < Signer : Sign , M : Deref , T : Deref , K : Deref , F : Deref , L : Deref > (
288298 channelmanager : & ChannelManager < Signer , M , T , K , F , L > , keys_manager : K , network : Currency ,
289299 amt_msat : Option < u64 > , description : String , duration_since_epoch : Duration ,
300+ invoice_expiry_delta_secs : u32
290301) -> Result < Invoice , SignOrCreationError < ( ) > >
291302where
292303 M :: Target : chain:: Watch < Signer > ,
@@ -300,13 +311,14 @@ where
300311 InvoiceDescription :: Direct (
301312 & Description :: new ( description) . map_err ( SignOrCreationError :: CreationError ) ?,
302313 ) ,
303- duration_since_epoch,
314+ duration_since_epoch, invoice_expiry_delta_secs
304315 )
305316}
306317
307318fn _create_invoice_from_channelmanager_and_duration_since_epoch < Signer : Sign , M : Deref , T : Deref , K : Deref , F : Deref , L : Deref > (
308319 channelmanager : & ChannelManager < Signer , M , T , K , F , L > , keys_manager : K , network : Currency ,
309320 amt_msat : Option < u64 > , description : InvoiceDescription , duration_since_epoch : Duration ,
321+ invoice_expiry_delta_secs : u32
310322) -> Result < Invoice , SignOrCreationError < ( ) > >
311323where
312324 M :: Target : chain:: Watch < Signer > ,
@@ -320,7 +332,7 @@ where
320332 // `create_inbound_payment` only returns an error if the amount is greater than the total bitcoin
321333 // supply.
322334 let ( payment_hash, payment_secret) = channelmanager
323- . create_inbound_payment ( amt_msat, DEFAULT_EXPIRY_TIME . try_into ( ) . unwrap ( ) )
335+ . create_inbound_payment ( amt_msat, invoice_expiry_delta_secs )
324336 . map_err ( |( ) | SignOrCreationError :: CreationError ( CreationError :: InvalidAmount ) ) ?;
325337 let our_node_pubkey = channelmanager. get_our_node_id ( ) ;
326338
@@ -337,7 +349,8 @@ where
337349 . payment_hash ( Hash :: from_slice ( & payment_hash. 0 ) . unwrap ( ) )
338350 . payment_secret ( payment_secret)
339351 . basic_mpp ( )
340- . min_final_cltv_expiry ( MIN_FINAL_CLTV_EXPIRY . into ( ) ) ;
352+ . min_final_cltv_expiry ( MIN_FINAL_CLTV_EXPIRY . into ( ) )
353+ . expiry_time ( Duration :: from_secs ( invoice_expiry_delta_secs. into ( ) ) ) ;
341354 if let Some ( amt) = amt_msat {
342355 invoice = invoice. amount_milli_satoshis ( amt) ;
343356 }
@@ -528,10 +541,11 @@ mod test {
528541 create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
529542 let invoice = create_invoice_from_channelmanager_and_duration_since_epoch (
530543 & nodes[ 1 ] . node , nodes[ 1 ] . keys_manager , Currency :: BitcoinTestnet , Some ( 10_000 ) , "test" . to_string ( ) ,
531- Duration :: from_secs ( 1234567 ) ) . unwrap ( ) ;
544+ Duration :: from_secs ( 1234567 ) , 3600 ) . unwrap ( ) ;
532545 assert_eq ! ( invoice. amount_pico_btc( ) , Some ( 100_000 ) ) ;
533546 assert_eq ! ( invoice. min_final_cltv_expiry( ) , MIN_FINAL_CLTV_EXPIRY as u64 ) ;
534547 assert_eq ! ( invoice. description( ) , InvoiceDescription :: Direct ( & Description ( "test" . to_string( ) ) ) ) ;
548+ assert_eq ! ( invoice. expiry_time( ) , Duration :: from_secs( 3600 ) ) ;
535549
536550 // Invoice SCIDs should always use inbound SCID aliases over the real channel ID, if one is
537551 // available.
@@ -592,7 +606,7 @@ mod test {
592606 let description_hash = crate :: Sha256 ( Hash :: hash ( "Testing description_hash" . as_bytes ( ) ) ) ;
593607 let invoice = :: utils:: create_invoice_from_channelmanager_with_description_hash_and_duration_since_epoch (
594608 & nodes[ 1 ] . node , nodes[ 1 ] . keys_manager , Currency :: BitcoinTestnet , Some ( 10_000 ) ,
595- description_hash, Duration :: from_secs ( 1234567 ) ,
609+ description_hash, Duration :: from_secs ( 1234567 ) , 3600
596610 ) . unwrap ( ) ;
597611 assert_eq ! ( invoice. amount_pico_btc( ) , Some ( 100_000 ) ) ;
598612 assert_eq ! ( invoice. min_final_cltv_expiry( ) , MIN_FINAL_CLTV_EXPIRY as u64 ) ;
@@ -752,7 +766,7 @@ mod test {
752766 ) {
753767 let invoice = create_invoice_from_channelmanager_and_duration_since_epoch (
754768 & invoice_node. node , invoice_node. keys_manager , Currency :: BitcoinTestnet , invoice_amt, "test" . to_string ( ) ,
755- Duration :: from_secs ( 1234567 ) ) . unwrap ( ) ;
769+ Duration :: from_secs ( 1234567 ) , 3600 ) . unwrap ( ) ;
756770 let hints = invoice. private_routes ( ) ;
757771
758772 for hint in hints {
@@ -811,6 +825,7 @@ mod test {
811825 assert_eq ! ( invoice. min_final_cltv_expiry( ) , MIN_FINAL_CLTV_EXPIRY as u64 ) ;
812826 assert_eq ! ( invoice. description( ) , InvoiceDescription :: Direct ( & Description ( "test" . to_string( ) ) ) ) ;
813827 assert_eq ! ( invoice. route_hints( ) . len( ) , 2 ) ;
828+ assert_eq ! ( invoice. expiry_time( ) , Duration :: from_secs( 3600 ) ) ;
814829 assert ! ( !invoice. features( ) . unwrap( ) . supports_basic_mpp( ) ) ;
815830
816831 let payment_params = PaymentParameters :: from_node_id ( invoice. recover_payee_pub_key ( ) )
@@ -931,10 +946,23 @@ mod test {
931946 ] ;
932947
933948 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-
949+ let non_default_invoice_expiry_secs = 4200 ;
950+ let invoice = :: utils:: create_phantom_invoice_with_description_hash :: <
951+ EnforcingSigner ,
952+ & test_utils:: TestKeysInterface ,
953+ > (
954+ Some ( payment_amt) ,
955+ None ,
956+ non_default_invoice_expiry_secs,
957+ description_hash,
958+ route_hints,
959+ & nodes[ 1 ] . keys_manager ,
960+ Currency :: BitcoinTestnet ,
961+ )
962+ . unwrap ( ) ;
936963 assert_eq ! ( invoice. amount_pico_btc( ) , Some ( 200_000 ) ) ;
937964 assert_eq ! ( invoice. min_final_cltv_expiry( ) , MIN_FINAL_CLTV_EXPIRY as u64 ) ;
965+ assert_eq ! ( invoice. expiry_time( ) , Duration :: from_secs( non_default_invoice_expiry_secs. into( ) ) ) ;
938966 assert_eq ! ( invoice. description( ) , InvoiceDescription :: Hash ( & crate :: Sha256 ( Sha256 :: hash( "Description hash phantom invoice" . as_bytes( ) ) ) ) ) ;
939967 }
940968
0 commit comments