@@ -8,20 +8,23 @@ use crate::error::Error;
8
8
use crate :: liquidity:: LiquiditySource ;
9
9
use crate :: logger:: { log_error, log_info, FilesystemLogger , Logger } ;
10
10
use crate :: payment:: store:: {
11
- LSPFeeLimits , PaymentDetails , PaymentDirection , PaymentKind , PaymentStatus , PaymentStore ,
11
+ LSPFeeLimits , PaymentDetails , PaymentDetailsUpdate , PaymentDirection , PaymentKind ,
12
+ PaymentStatus , PaymentStore ,
12
13
} ;
13
14
use crate :: peer_store:: { PeerInfo , PeerStore } ;
14
15
use crate :: types:: { ChannelManager , KeysManager } ;
15
16
16
17
use lightning:: ln:: channelmanager:: { PaymentId , RecipientOnionFields , Retry , RetryableSendFailure } ;
17
- use lightning:: ln:: PaymentHash ;
18
+ use lightning:: ln:: { PaymentHash , PaymentPreimage } ;
18
19
use lightning:: routing:: router:: { PaymentParameters , RouteParameters } ;
19
20
20
21
use lightning_invoice:: { payment, Bolt11Invoice , Currency } ;
21
22
23
+ use bitcoin:: hashes:: sha256:: Hash as Sha256 ;
22
24
use bitcoin:: hashes:: Hash ;
23
25
24
26
use std:: sync:: { Arc , RwLock } ;
27
+ use std:: time:: SystemTime ;
25
28
26
29
/// A payment handler allowing to create and pay [BOLT 11] invoices.
27
30
///
@@ -254,55 +257,227 @@ impl Bolt11Payment {
254
257
}
255
258
}
256
259
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
+
257
350
/// Returns a payable invoice that can be used to request and receive a payment of the amount
258
351
/// given.
352
+ ///
353
+ /// The inbound payment will be automatically claimed upon arrival.
259
354
pub fn receive (
260
355
& self , amount_msat : u64 , description : & str , expiry_secs : u32 ,
261
356
) -> 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) )
263
378
}
264
379
265
380
/// Returns a payable invoice that can be used to request and receive a payment for which the
266
381
/// 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.
267
384
pub fn receive_variable_amount (
268
385
& self , description : & str , expiry_secs : u32 ,
269
386
) -> 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) )
271
408
}
272
409
273
410
fn receive_inner (
274
411
& self , amount_msat : Option < u64 > , description : & str , expiry_secs : u32 ,
412
+ manual_claim_payment_hash : Option < PaymentHash > ,
275
413
) -> Result < Bolt11Invoice , Error > {
276
414
let currency = Currency :: from ( self . config . network ) ;
277
415
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
+ }
296
458
} ;
297
459
298
460
let payment_hash = PaymentHash ( invoice. payment_hash ( ) . to_byte_array ( ) ) ;
461
+ let payment_secret = invoice. payment_secret ( ) ;
299
462
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
+ } ;
300
475
let payment = PaymentDetails {
301
476
id,
302
477
kind : PaymentKind :: Bolt11 {
303
478
hash : payment_hash,
304
- preimage : None ,
305
- secret : Some ( invoice . payment_secret ( ) . clone ( ) ) ,
479
+ preimage,
480
+ secret : Some ( payment_secret. clone ( ) ) ,
306
481
} ,
307
482
308
483
amount_msat,
@@ -422,17 +597,20 @@ impl Bolt11Payment {
422
597
423
598
// Register payment in payment store.
424
599
let payment_hash = PaymentHash ( invoice. payment_hash ( ) . to_byte_array ( ) ) ;
600
+ let payment_secret = invoice. payment_secret ( ) ;
425
601
let lsp_fee_limits = LSPFeeLimits {
426
602
max_total_opening_fee_msat : lsp_total_opening_fee,
427
603
max_proportional_opening_fee_ppm_msat : lsp_prop_opening_fee,
428
604
} ;
429
605
let id = PaymentId ( payment_hash. 0 ) ;
606
+ let preimage =
607
+ self . channel_manager . get_payment_preimage ( payment_hash, payment_secret. clone ( ) ) . ok ( ) ;
430
608
let payment = PaymentDetails {
431
609
id,
432
610
kind : PaymentKind :: Bolt11Jit {
433
611
hash : payment_hash,
434
- preimage : None ,
435
- secret : Some ( invoice . payment_secret ( ) . clone ( ) ) ,
612
+ preimage,
613
+ secret : Some ( payment_secret. clone ( ) ) ,
436
614
lsp_fee_limits,
437
615
} ,
438
616
amount_msat,
0 commit comments