@@ -8,20 +8,23 @@ use crate::error::Error;
88use crate :: liquidity:: LiquiditySource ;
99use crate :: logger:: { log_error, log_info, FilesystemLogger , Logger } ;
1010use crate :: payment:: store:: {
11- LSPFeeLimits , PaymentDetails , PaymentDirection , PaymentKind , PaymentStatus , PaymentStore ,
11+ LSPFeeLimits , PaymentDetails , PaymentDetailsUpdate , PaymentDirection , PaymentKind ,
12+ PaymentStatus , PaymentStore ,
1213} ;
1314use crate :: peer_store:: { PeerInfo , PeerStore } ;
1415use crate :: types:: { ChannelManager , KeysManager } ;
1516
1617use lightning:: ln:: channelmanager:: { PaymentId , RecipientOnionFields , Retry , RetryableSendFailure } ;
17- use lightning:: ln:: PaymentHash ;
18+ use lightning:: ln:: { PaymentHash , PaymentPreimage } ;
1819use lightning:: routing:: router:: { PaymentParameters , RouteParameters } ;
1920
2021use lightning_invoice:: { payment, Bolt11Invoice , Currency } ;
2122
23+ use bitcoin:: hashes:: sha256:: Hash as Sha256 ;
2224use bitcoin:: hashes:: Hash ;
2325
2426use std:: sync:: { Arc , RwLock } ;
27+ use std:: time:: SystemTime ;
2528
2629/// A payment handler allowing to create and pay [BOLT 11] invoices.
2730///
@@ -254,55 +257,227 @@ impl Bolt11Payment {
254257 }
255258 }
256259
260+ /// Allows to attempt manually claiming payments with the given preimage that have previously
261+ /// been registered via [`receive_for_hash`] or [`receive_variable_amount_for_hash`].
262+ ///
263+ /// This should be called in reponse to a [`PaymentClaimable`] event as soon as the preimage is
264+ /// available.
265+ ///
266+ /// Will check that the payment is known, and that the given preimage and claimable amount
267+ /// match our expectations before attempting to claim the payment, and will return an error
268+ /// otherwise.
269+ ///
270+ /// When claiming the payment has succeeded, a [`PaymentReceived`] event will be emitted.
271+ ///
272+ /// [`receive_for_hash`]: Self::receive_for_hash
273+ /// [`receive_variable_amount_for_hash`]: Self::receive_variable_amount_for_hash
274+ /// [`PaymentClaimable`]: crate::Event::PaymentClaimable
275+ /// [`PaymentReceived`]: crate::Event::PaymentReceived
276+ pub fn claim_for_hash (
277+ & self , payment_hash : PaymentHash , claimable_amount_msat : u64 , preimage : PaymentPreimage ,
278+ ) -> Result < ( ) , Error > {
279+ let payment_id = PaymentId ( payment_hash. 0 ) ;
280+
281+ let expected_payment_hash = PaymentHash ( Sha256 :: hash ( & preimage. 0 ) . to_byte_array ( ) ) ;
282+
283+ if expected_payment_hash != payment_hash {
284+ log_error ! (
285+ self . logger,
286+ "Failed to manually claim payment as the given preimage doesn't match the hash {}" ,
287+ payment_hash
288+ ) ;
289+ return Err ( Error :: InvalidPaymentPreimage ) ;
290+ }
291+
292+ if let Some ( details) = self . payment_store . get ( & payment_id) {
293+ if let Some ( expected_amount_msat) = details. amount_msat {
294+ if claimable_amount_msat < expected_amount_msat {
295+ log_error ! (
296+ self . logger,
297+ "Failed to manually claim payment {} as the claimable amount is less than expected" ,
298+ payment_id
299+ ) ;
300+ return Err ( Error :: InvalidAmount ) ;
301+ }
302+ }
303+ } else {
304+ log_error ! (
305+ self . logger,
306+ "Failed to manually claim unknown payment with hash: {}" ,
307+ payment_hash
308+ ) ;
309+ return Err ( Error :: InvalidPaymentHash ) ;
310+ }
311+
312+ self . channel_manager . claim_funds ( preimage) ;
313+ Ok ( ( ) )
314+ }
315+
316+ /// Allows to manually fail payments with the given hash that have previously
317+ /// been registered via [`receive_for_hash`] or [`receive_variable_amount_for_hash`].
318+ ///
319+ /// This should be called in reponse to a [`PaymentClaimable`] event if the payment needs to be
320+ /// failed back, e.g., if the correct preimage can't be retrieved in time before the claim
321+ /// deadline has been reached.
322+ ///
323+ /// Will check that the payment is known before failing the payment, and will return an error
324+ /// otherwise.
325+ ///
326+ /// [`receive_for_hash`]: Self::receive_for_hash
327+ /// [`receive_variable_amount_for_hash`]: Self::receive_variable_amount_for_hash
328+ /// [`PaymentClaimable`]: crate::Event::PaymentClaimable
329+ pub fn fail_for_hash ( & self , payment_hash : PaymentHash ) -> Result < ( ) , Error > {
330+ let payment_id = PaymentId ( payment_hash. 0 ) ;
331+
332+ let update = PaymentDetailsUpdate {
333+ status : Some ( PaymentStatus :: Failed ) ,
334+ ..PaymentDetailsUpdate :: new ( payment_id)
335+ } ;
336+
337+ if !self . payment_store . update ( & update) ? {
338+ log_error ! (
339+ self . logger,
340+ "Failed to manually fail unknown payment with hash: {}" ,
341+ payment_hash
342+ ) ;
343+ return Err ( Error :: InvalidPaymentHash ) ;
344+ }
345+
346+ self . channel_manager . fail_htlc_backwards ( & payment_hash) ;
347+ Ok ( ( ) )
348+ }
349+
257350 /// Returns a payable invoice that can be used to request and receive a payment of the amount
258351 /// given.
352+ ///
353+ /// The inbound payment will be automatically claimed upon arrival.
259354 pub fn receive (
260355 & self , amount_msat : u64 , description : & str , expiry_secs : u32 ,
261356 ) -> Result < Bolt11Invoice , Error > {
262- self . receive_inner ( Some ( amount_msat) , description, expiry_secs)
357+ self . receive_inner ( Some ( amount_msat) , description, expiry_secs, None )
358+ }
359+
360+ /// Returns a payable invoice that can be used to request a payment of the amount
361+ /// given for the given payment hash.
362+ ///
363+ /// We will register the given payment hash and emit a [`PaymentClaimable`] event once
364+ /// the inbound payment arrives.
365+ ///
366+ /// **Note:** users *MUST* handle this event and claim the payment manually via
367+ /// [`claim_for_hash`] as soon as they have obtained access to the preimage of the given
368+ /// payment hash. If they're unable to obtain the preimage, they *MUST* immediately fail the payment via
369+ /// [`fail_for_hash`].
370+ ///
371+ /// [`PaymentClaimable`]: crate::Event::PaymentClaimable
372+ /// [`claim_for_hash`]: Self::claim_for_hash
373+ /// [`fail_for_hash`]: Self::fail_for_hash
374+ pub fn receive_for_hash (
375+ & self , amount_msat : u64 , description : & str , expiry_secs : u32 , payment_hash : PaymentHash ,
376+ ) -> Result < Bolt11Invoice , Error > {
377+ self . receive_inner ( Some ( amount_msat) , description, expiry_secs, Some ( payment_hash) )
263378 }
264379
265380 /// Returns a payable invoice that can be used to request and receive a payment for which the
266381 /// amount is to be determined by the user, also known as a "zero-amount" invoice.
382+ ///
383+ /// The inbound payment will be automatically claimed upon arrival.
267384 pub fn receive_variable_amount (
268385 & self , description : & str , expiry_secs : u32 ,
269386 ) -> Result < Bolt11Invoice , Error > {
270- self . receive_inner ( None , description, expiry_secs)
387+ self . receive_inner ( None , description, expiry_secs, None )
388+ }
389+
390+ /// Returns a payable invoice that can be used to request a payment for the given payment hash
391+ /// and the amount to be determined by the user, also known as a "zero-amount" invoice.
392+ ///
393+ /// We will register the given payment hash and emit a [`PaymentClaimable`] event once
394+ /// the inbound payment arrives.
395+ ///
396+ /// **Note:** users *MUST* handle this event and claim the payment manually via
397+ /// [`claim_for_hash`] as soon as they have obtained access to the preimage of the given
398+ /// payment hash. If they're unable to obtain the preimage, they *MUST* immediately fail the payment via
399+ /// [`fail_for_hash`].
400+ ///
401+ /// [`PaymentClaimable`]: crate::Event::PaymentClaimable
402+ /// [`claim_for_hash`]: Self::claim_for_hash
403+ /// [`fail_for_hash`]: Self::fail_for_hash
404+ pub fn receive_variable_amount_for_hash (
405+ & self , description : & str , expiry_secs : u32 , payment_hash : PaymentHash ,
406+ ) -> Result < Bolt11Invoice , Error > {
407+ self . receive_inner ( None , description, expiry_secs, Some ( payment_hash) )
271408 }
272409
273410 fn receive_inner (
274411 & self , amount_msat : Option < u64 > , description : & str , expiry_secs : u32 ,
412+ manual_claim_payment_hash : Option < PaymentHash > ,
275413 ) -> Result < Bolt11Invoice , Error > {
276414 let currency = Currency :: from ( self . config . network ) ;
277415 let keys_manager = Arc :: clone ( & self . keys_manager ) ;
278- let invoice = match lightning_invoice:: utils:: create_invoice_from_channelmanager (
279- & self . channel_manager ,
280- keys_manager,
281- Arc :: clone ( & self . logger ) ,
282- currency,
283- amount_msat,
284- description. to_string ( ) ,
285- expiry_secs,
286- None ,
287- ) {
288- Ok ( inv) => {
289- log_info ! ( self . logger, "Invoice created: {}" , inv) ;
290- inv
291- } ,
292- Err ( e) => {
293- log_error ! ( self . logger, "Failed to create invoice: {}" , e) ;
294- return Err ( Error :: InvoiceCreationFailed ) ;
295- } ,
416+ let duration = SystemTime :: now ( )
417+ . duration_since ( SystemTime :: UNIX_EPOCH )
418+ . expect ( "for the foreseeable future this shouldn't happen" ) ;
419+
420+ let invoice = {
421+ let invoice_res = if let Some ( payment_hash) = manual_claim_payment_hash {
422+ lightning_invoice:: utils:: create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_hash (
423+ & self . channel_manager ,
424+ keys_manager,
425+ Arc :: clone ( & self . logger ) ,
426+ currency,
427+ amount_msat,
428+ description. to_string ( ) ,
429+ duration,
430+ expiry_secs,
431+ payment_hash,
432+ None ,
433+ )
434+ } else {
435+ lightning_invoice:: utils:: create_invoice_from_channelmanager_and_duration_since_epoch (
436+ & self . channel_manager ,
437+ keys_manager,
438+ Arc :: clone ( & self . logger ) ,
439+ currency,
440+ amount_msat,
441+ description. to_string ( ) ,
442+ duration,
443+ expiry_secs,
444+ None ,
445+ )
446+ } ;
447+
448+ match invoice_res {
449+ Ok ( inv) => {
450+ log_info ! ( self . logger, "Invoice created: {}" , inv) ;
451+ inv
452+ } ,
453+ Err ( e) => {
454+ log_error ! ( self . logger, "Failed to create invoice: {}" , e) ;
455+ return Err ( Error :: InvoiceCreationFailed ) ;
456+ } ,
457+ }
296458 } ;
297459
298460 let payment_hash = PaymentHash ( invoice. payment_hash ( ) . to_byte_array ( ) ) ;
461+ let payment_secret = invoice. payment_secret ( ) ;
299462 let id = PaymentId ( payment_hash. 0 ) ;
463+ let preimage = if manual_claim_payment_hash. is_none ( ) {
464+ // If the user hasn't registered a custom payment hash, we're positive ChannelManager
465+ // will know the preimage at this point.
466+ let res = self
467+ . channel_manager
468+ . get_payment_preimage ( payment_hash, payment_secret. clone ( ) )
469+ . ok ( ) ;
470+ debug_assert ! ( res. is_some( ) , "We just let ChannelManager create an inbound payment, it can't have forgotten the preimage by now." ) ;
471+ res
472+ } else {
473+ None
474+ } ;
300475 let payment = PaymentDetails {
301476 id,
302477 kind : PaymentKind :: Bolt11 {
303478 hash : payment_hash,
304- preimage : None ,
305- secret : Some ( invoice . payment_secret ( ) . clone ( ) ) ,
479+ preimage,
480+ secret : Some ( payment_secret. clone ( ) ) ,
306481 } ,
307482
308483 amount_msat,
@@ -422,17 +597,20 @@ impl Bolt11Payment {
422597
423598 // Register payment in payment store.
424599 let payment_hash = PaymentHash ( invoice. payment_hash ( ) . to_byte_array ( ) ) ;
600+ let payment_secret = invoice. payment_secret ( ) ;
425601 let lsp_fee_limits = LSPFeeLimits {
426602 max_total_opening_fee_msat : lsp_total_opening_fee,
427603 max_proportional_opening_fee_ppm_msat : lsp_prop_opening_fee,
428604 } ;
429605 let id = PaymentId ( payment_hash. 0 ) ;
606+ let preimage =
607+ self . channel_manager . get_payment_preimage ( payment_hash, payment_secret. clone ( ) ) . ok ( ) ;
430608 let payment = PaymentDetails {
431609 id,
432610 kind : PaymentKind :: Bolt11Jit {
433611 hash : payment_hash,
434- preimage : None ,
435- secret : Some ( invoice . payment_secret ( ) . clone ( ) ) ,
612+ preimage,
613+ secret : Some ( payment_secret. clone ( ) ) ,
436614 lsp_fee_limits,
437615 } ,
438616 amount_msat,
0 commit comments