33use { CreationError , Currency , DEFAULT_EXPIRY_TIME , Invoice , InvoiceBuilder , SignOrCreationError } ;
44use payment:: { Payer , Router } ;
55
6- use crate :: { prelude:: * , Description , InvoiceDescription , Sha256 } ;
76use bech32:: ToBase32 ;
87use bitcoin_hashes:: { Hash , sha256} ;
8+ use crate :: prelude:: * ;
99use lightning:: chain;
1010use lightning:: chain:: chaininterface:: { BroadcasterInterface , FeeEstimator } ;
1111use lightning:: chain:: keysinterface:: { Recipient , KeysInterface , Sign } ;
@@ -50,77 +50,14 @@ use sync::Mutex;
5050/// [`ChannelManager::get_phantom_route_hints`]: lightning::ln::channelmanager::ChannelManager::get_phantom_route_hints
5151/// [`PhantomRouteHints::channels`]: lightning::ln::channelmanager::PhantomRouteHints::channels
5252pub fn create_phantom_invoice < Signer : Sign , K : Deref > (
53- amt_msat : Option < u64 > , description : String , payment_hash : PaymentHash , payment_secret : PaymentSecret ,
54- phantom_route_hints : Vec < PhantomRouteHints > , keys_manager : K , network : Currency ,
53+ amt_msat : Option < u64 > , description : String , payment_hash : PaymentHash , payment_secret :
54+ PaymentSecret , phantom_route_hints : Vec < PhantomRouteHints > , keys_manager : K , network : Currency
5555) -> Result < Invoice , SignOrCreationError < ( ) > > where K :: Target : KeysInterface {
56- let description = Description :: new ( description) . map_err ( SignOrCreationError :: CreationError ) ?;
57- let description = InvoiceDescription :: Direct ( & description, ) ;
58- _create_phantom_invoice :: < Signer , K > (
59- amt_msat, description, payment_hash, payment_secret, phantom_route_hints, keys_manager, network,
60- )
61- }
62-
63- #[ cfg( feature = "std" ) ]
64- /// Utility to create an invoice that can be paid to one of multiple nodes, or a "phantom invoice."
65- /// See [`PhantomKeysManager`] for more information on phantom node payments.
66- ///
67- /// `phantom_route_hints` parameter:
68- /// * Contains channel info for all nodes participating in the phantom invoice
69- /// * Entries are retrieved from a call to [`ChannelManager::get_phantom_route_hints`] on each
70- /// participating node
71- /// * It is fine to cache `phantom_route_hints` and reuse it across invoices, as long as the data is
72- /// updated when a channel becomes disabled or closes
73- /// * Note that if too many channels are included in [`PhantomRouteHints::channels`], the invoice
74- /// may be too long for QR code scanning. To fix this, `PhantomRouteHints::channels` may be pared
75- /// down
76- ///
77- /// `description_hash` is a SHA-256 hash of the description text
78- ///
79- /// `payment_hash` and `payment_secret` come from [`ChannelManager::create_inbound_payment`] or
80- /// [`ChannelManager::create_inbound_payment_for_hash`]. These values can be retrieved from any
81- /// participating node.
82- ///
83- /// Note that the provided `keys_manager`'s `KeysInterface` implementation must support phantom
84- /// invoices in its `sign_invoice` implementation ([`PhantomKeysManager`] satisfies this
85- /// requirement).
86- ///
87- /// [`PhantomKeysManager`]: lightning::chain::keysinterface::PhantomKeysManager
88- /// [`ChannelManager::get_phantom_route_hints`]: lightning::ln::channelmanager::ChannelManager::get_phantom_route_hints
89- /// [`PhantomRouteHints::channels`]: lightning::ln::channelmanager::PhantomRouteHints::channels
90- pub fn create_phantom_invoice_with_description_hash < Signer : Sign , K : Deref > (
91- amt_msat : Option < u64 > , description_hash : Sha256 , payment_hash : PaymentHash ,
92- payment_secret : PaymentSecret , phantom_route_hints : Vec < PhantomRouteHints > ,
93- keys_manager : K , network : Currency ,
94- ) -> Result < Invoice , SignOrCreationError < ( ) > > where K :: Target : KeysInterface
95- {
96-
97- _create_phantom_invoice :: < Signer , K > (
98- amt_msat,
99- InvoiceDescription :: Hash ( & description_hash) ,
100- payment_hash, payment_secret, phantom_route_hints, keys_manager, network,
101- )
102- }
103-
104- #[ cfg( feature = "std" ) ]
105- fn _create_phantom_invoice < Signer : Sign , K : Deref > (
106- amt_msat : Option < u64 > , description : InvoiceDescription , payment_hash : PaymentHash ,
107- payment_secret : PaymentSecret , phantom_route_hints : Vec < PhantomRouteHints > ,
108- keys_manager : K , network : Currency ,
109- ) -> Result < Invoice , SignOrCreationError < ( ) > > where K :: Target : KeysInterface
110- {
11156 if phantom_route_hints. len ( ) == 0 {
112- return Err ( SignOrCreationError :: CreationError (
113- CreationError :: MissingRouteHints ,
114- ) ) ;
57+ return Err ( SignOrCreationError :: CreationError ( CreationError :: MissingRouteHints ) )
11558 }
116- let invoice = match description {
117- InvoiceDescription :: Direct ( description) => {
118- InvoiceBuilder :: new ( network) . description ( description. 0 . clone ( ) )
119- }
120- InvoiceDescription :: Hash ( hash) => InvoiceBuilder :: new ( network) . description_hash ( hash. 0 ) ,
121- } ;
122-
123- let mut invoice = invoice
59+ let mut invoice = InvoiceBuilder :: new ( network)
60+ . description ( description)
12461 . current_timestamp ( )
12562 . payment_hash ( Hash :: from_slice ( & payment_hash. 0 ) . unwrap ( ) )
12663 . payment_secret ( payment_secret)
@@ -189,57 +126,12 @@ where
189126 let duration = SystemTime :: now ( ) . duration_since ( SystemTime :: UNIX_EPOCH )
190127 . expect ( "for the foreseeable future this shouldn't happen" ) ;
191128 create_invoice_from_channelmanager_and_duration_since_epoch (
192- channelmanager, keys_manager, network, amt_msat, description, duration
193- )
194- }
195-
196- #[ cfg( feature = "std" ) ]
197- /// Utility to construct an invoice. Generally, unless you want to do something like a custom
198- /// cltv_expiry, this is what you should be using to create an invoice. The reason being, this
199- /// method stores the invoice's payment secret and preimage in `ChannelManager`, so (a) the user
200- /// doesn't have to store preimage/payment secret information and (b) `ChannelManager` can verify
201- /// that the payment secret is valid when the invoice is paid.
202- /// Use this variant if you want to pass the `description_hash` to the invoice.
203- pub fn create_invoice_from_channelmanager_with_description_hash < Signer : Sign , M : Deref , T : Deref , K : Deref , F : Deref , L : Deref > (
204- channelmanager : & ChannelManager < Signer , M , T , K , F , L > , keys_manager : K , network : Currency ,
205- amt_msat : Option < u64 > , description_hash : Sha256 ,
206- ) -> Result < Invoice , SignOrCreationError < ( ) > >
207- where
208- M :: Target : chain:: Watch < Signer > ,
209- T :: Target : BroadcasterInterface ,
210- K :: Target : KeysInterface < Signer = Signer > ,
211- F :: Target : FeeEstimator ,
212- L :: Target : Logger ,
213- {
214- use std:: time:: SystemTime ;
215-
216- let duration = SystemTime :: now ( )
217- . duration_since ( SystemTime :: UNIX_EPOCH )
218- . expect ( "for the foreseeable future this shouldn't happen" ) ;
219-
220- create_invoice_from_channelmanager_with_description_hash_and_duration_since_epoch (
221- channelmanager, keys_manager, network, amt_msat, description_hash, duration,
222- )
223- }
224-
225- /// See [`create_invoice_from_channelmanager_with_description_hash`]
226- /// This version can be used in a `no_std` environment, where [`std::time::SystemTime`] is not
227- /// available and the current time is supplied by the caller.
228- 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 > (
229- channelmanager : & ChannelManager < Signer , M , T , K , F , L > , keys_manager : K , network : Currency ,
230- amt_msat : Option < u64 > , description_hash : Sha256 , duration_since_epoch : Duration ,
231- ) -> Result < Invoice , SignOrCreationError < ( ) > >
232- where
233- M :: Target : chain:: Watch < Signer > ,
234- T :: Target : BroadcasterInterface ,
235- K :: Target : KeysInterface < Signer = Signer > ,
236- F :: Target : FeeEstimator ,
237- L :: Target : Logger ,
238- {
239- _create_invoice_from_channelmanager_and_duration_since_epoch (
240- channelmanager, keys_manager, network, amt_msat,
241- InvoiceDescription :: Hash ( & description_hash) ,
242- duration_since_epoch,
129+ channelmanager,
130+ keys_manager,
131+ network,
132+ amt_msat,
133+ description,
134+ duration
243135 )
244136}
245137
@@ -250,26 +142,6 @@ pub fn create_invoice_from_channelmanager_and_duration_since_epoch<Signer: Sign,
250142 channelmanager : & ChannelManager < Signer , M , T , K , F , L > , keys_manager : K , network : Currency ,
251143 amt_msat : Option < u64 > , description : String , duration_since_epoch : Duration ,
252144) -> Result < Invoice , SignOrCreationError < ( ) > >
253- where
254- M :: Target : chain:: Watch < Signer > ,
255- T :: Target : BroadcasterInterface ,
256- K :: Target : KeysInterface < Signer = Signer > ,
257- F :: Target : FeeEstimator ,
258- L :: Target : Logger ,
259- {
260- _create_invoice_from_channelmanager_and_duration_since_epoch (
261- channelmanager, keys_manager, network, amt_msat,
262- InvoiceDescription :: Direct (
263- & Description :: new ( description) . map_err ( SignOrCreationError :: CreationError ) ?,
264- ) ,
265- duration_since_epoch,
266- )
267- }
268-
269- fn _create_invoice_from_channelmanager_and_duration_since_epoch < Signer : Sign , M : Deref , T : Deref , K : Deref , F : Deref , L : Deref > (
270- channelmanager : & ChannelManager < Signer , M , T , K , F , L > , keys_manager : K , network : Currency ,
271- amt_msat : Option < u64 > , description : InvoiceDescription , duration_since_epoch : Duration ,
272- ) -> Result < Invoice , SignOrCreationError < ( ) > >
273145where
274146 M :: Target : chain:: Watch < Signer > ,
275147 T :: Target : BroadcasterInterface ,
@@ -281,19 +153,12 @@ where
281153
282154 // `create_inbound_payment` only returns an error if the amount is greater than the total bitcoin
283155 // supply.
284- let ( payment_hash, payment_secret) = channelmanager
285- . create_inbound_payment ( amt_msat, DEFAULT_EXPIRY_TIME . try_into ( ) . unwrap ( ) )
156+ let ( payment_hash, payment_secret) = channelmanager. create_inbound_payment (
157+ amt_msat, DEFAULT_EXPIRY_TIME . try_into ( ) . unwrap ( ) )
286158 . map_err ( |( ) | SignOrCreationError :: CreationError ( CreationError :: InvalidAmount ) ) ?;
287159 let our_node_pubkey = channelmanager. get_our_node_id ( ) ;
288-
289- let invoice = match description {
290- InvoiceDescription :: Direct ( description) => {
291- InvoiceBuilder :: new ( network) . description ( description. 0 . clone ( ) )
292- }
293- InvoiceDescription :: Hash ( hash) => InvoiceBuilder :: new ( network) . description_hash ( hash. 0 ) ,
294- } ;
295-
296- let mut invoice = invoice
160+ let mut invoice = InvoiceBuilder :: new ( network)
161+ . description ( description)
297162 . duration_since_epoch ( duration_since_epoch)
298163 . payee_pub_key ( our_node_pubkey)
299164 . payment_hash ( Hash :: from_slice ( & payment_hash. 0 ) . unwrap ( ) )
@@ -542,22 +407,6 @@ mod test {
542407 assert_eq ! ( events. len( ) , 2 ) ;
543408 }
544409
545- #[ test]
546- fn test_create_invoice_with_description_hash ( ) {
547- let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
548- let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
549- let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None , None ] ) ;
550- let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
551- let description_hash = crate :: Sha256 ( Hash :: hash ( "Testing description_hash" . as_bytes ( ) ) ) ;
552- let invoice = :: utils:: create_invoice_from_channelmanager_with_description_hash_and_duration_since_epoch (
553- & nodes[ 1 ] . node , nodes[ 1 ] . keys_manager , Currency :: BitcoinTestnet , Some ( 10_000 ) ,
554- description_hash, Duration :: from_secs ( 1234567 ) ,
555- ) . unwrap ( ) ;
556- assert_eq ! ( invoice. amount_pico_btc( ) , Some ( 100_000 ) ) ;
557- assert_eq ! ( invoice. min_final_cltv_expiry( ) , MIN_FINAL_CLTV_EXPIRY as u64 ) ;
558- assert_eq ! ( invoice. description( ) , InvoiceDescription :: Hash ( & crate :: Sha256 ( Sha256 :: hash( "Testing description_hash" . as_bytes( ) ) ) ) ) ;
559- }
560-
561410 #[ test]
562411 fn test_hints_includes_single_channels_to_nodes ( ) {
563412 let chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
@@ -839,29 +688,6 @@ mod test {
839688 }
840689 }
841690
842- #[ test]
843- #[ cfg( feature = "std" ) ]
844- fn create_phantom_invoice_with_description_hash ( ) {
845- let chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
846- let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
847- let node_chanmgrs = create_node_chanmgrs ( 3 , & node_cfgs, & [ None , None , None ] ) ;
848- let nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
849-
850- let payment_amt = 20_000 ;
851- let ( payment_hash, payment_secret) = nodes[ 1 ] . node . create_inbound_payment ( Some ( payment_amt) , 3600 ) . unwrap ( ) ;
852- let route_hints = vec ! [
853- nodes[ 1 ] . node. get_phantom_route_hints( ) ,
854- nodes[ 2 ] . node. get_phantom_route_hints( ) ,
855- ] ;
856-
857- let description_hash = crate :: Sha256 ( Hash :: hash ( "Description hash phantom invoice" . as_bytes ( ) ) ) ;
858- let invoice = :: utils:: create_phantom_invoice_with_description_hash :: < EnforcingSigner , & test_utils:: TestKeysInterface > ( Some ( payment_amt) , description_hash, payment_hash, payment_secret, route_hints, & nodes[ 1 ] . keys_manager , Currency :: BitcoinTestnet ) . unwrap ( ) ;
859-
860- assert_eq ! ( invoice. amount_pico_btc( ) , Some ( 200_000 ) ) ;
861- assert_eq ! ( invoice. min_final_cltv_expiry( ) , MIN_FINAL_CLTV_EXPIRY as u64 ) ;
862- assert_eq ! ( invoice. description( ) , InvoiceDescription :: Hash ( & crate :: Sha256 ( Sha256 :: hash( "Description hash phantom invoice" . as_bytes( ) ) ) ) ) ;
863- }
864-
865691 #[ test]
866692 #[ cfg( feature = "std" ) ]
867693 fn test_multi_node_hints_includes_single_channels_to_participating_nodes ( ) {
0 commit comments