@@ -102,6 +102,8 @@ use {
102
102
crate::offers::refund::RefundMaybeWithDerivedMetadataBuilder,
103
103
};
104
104
105
+ use lightning_invoice::{Bolt11Invoice, Bolt11InvoiceDescription, CreationError, Currency, Description, InvoiceBuilder as Bolt11InvoiceBuilder, SignOrCreationError, DEFAULT_EXPIRY_TIME};
106
+
105
107
use alloc::collections::{btree_map, BTreeMap};
106
108
107
109
use crate::io;
@@ -1857,56 +1859,58 @@ where
1857
1859
///
1858
1860
/// ## BOLT 11 Invoices
1859
1861
///
1860
- /// The [`lightning-invoice`] crate is useful for creating BOLT 11 invoices. Specifically, use the
1861
- /// functions in its `utils` module for constructing invoices that are compatible with
1862
- /// [`ChannelManager `]. These functions serve as a convenience for building invoices with the
1862
+ /// The [`lightning-invoice`] crate is useful for creating BOLT 11 invoices. However, in order to
1863
+ /// construct a [`Bolt11Invoice`] that is compatible with [`ChannelManager`], use
1864
+ /// [`create_bolt11_invoice `]. This method serves as a convenience for building invoices with the
1863
1865
/// [`PaymentHash`] and [`PaymentSecret`] returned from [`create_inbound_payment`]. To provide your
1864
- /// own [`PaymentHash`], use [`create_inbound_payment_for_hash`] or the corresponding functions in
1865
- /// the [`lightning-invoice`] `utils` module .
1866
+ /// own [`PaymentHash`], override the appropriate [`Bolt11InvoiceParameters`], which is equivalent
1867
+ /// to using [`create_inbound_payment_for_hash`] .
1866
1868
///
1867
1869
/// [`ChannelManager`] generates an [`Event::PaymentClaimable`] once the full payment has been
1868
1870
/// received. Call [`claim_funds`] to release the [`PaymentPreimage`], which in turn will result in
1869
1871
/// an [`Event::PaymentClaimed`].
1870
1872
///
1871
1873
/// ```
1872
1874
/// # use lightning::events::{Event, EventsProvider, PaymentPurpose};
1873
- /// # use lightning::ln::channelmanager::AChannelManager;
1875
+ /// # use lightning::ln::channelmanager::{ AChannelManager, Bolt11InvoiceParameters} ;
1874
1876
/// #
1875
1877
/// # fn example<T: AChannelManager>(channel_manager: T) {
1876
1878
/// # let channel_manager = channel_manager.get_cm();
1877
- /// // Or use utils::create_invoice_from_channelmanager
1878
- /// let known_payment_hash = match channel_manager.create_inbound_payment(
1879
- /// Some(10_000_000), 3600, None
1880
- /// ) {
1881
- /// Ok((payment_hash, _payment_secret)) => {
1882
- /// println!("Creating inbound payment {}", payment_hash);
1883
- /// payment_hash
1879
+ /// let params = Bolt11InvoiceParameters {
1880
+ /// amount_msats: Some(10_000_000),
1881
+ /// invoice_expiry_delta_secs: Some(3600),
1882
+ /// ..Default::default()
1883
+ /// };
1884
+ /// let invoice = match channel_manager.create_bolt11_invoice(params) {
1885
+ /// Ok(invoice) => {
1886
+ /// println!("Creating invoice with payment hash {}", invoice.payment_hash());
1887
+ /// invoice
1884
1888
/// },
1885
- /// Err(()) => panic!("Error creating inbound payment" ),
1889
+ /// Err(e) => panic!("Error creating invoice: {}", e ),
1886
1890
/// };
1887
1891
///
1888
1892
/// // On the event processing thread
1889
1893
/// channel_manager.process_pending_events(&|event| {
1890
1894
/// match event {
1891
1895
/// Event::PaymentClaimable { payment_hash, purpose, .. } => match purpose {
1892
1896
/// PaymentPurpose::Bolt11InvoicePayment { payment_preimage: Some(payment_preimage), .. } => {
1893
- /// assert_eq!(payment_hash, known_payment_hash );
1897
+ /// assert_eq!(payment_hash.0, invoice.payment_hash().as_ref() );
1894
1898
/// println!("Claiming payment {}", payment_hash);
1895
1899
/// channel_manager.claim_funds(payment_preimage);
1896
1900
/// },
1897
1901
/// PaymentPurpose::Bolt11InvoicePayment { payment_preimage: None, .. } => {
1898
1902
/// println!("Unknown payment hash: {}", payment_hash);
1899
1903
/// },
1900
1904
/// PaymentPurpose::SpontaneousPayment(payment_preimage) => {
1901
- /// assert_ne!(payment_hash, known_payment_hash );
1905
+ /// assert_ne!(payment_hash.0, invoice.payment_hash().as_ref() );
1902
1906
/// println!("Claiming spontaneous payment {}", payment_hash);
1903
1907
/// channel_manager.claim_funds(payment_preimage);
1904
1908
/// },
1905
1909
/// // ...
1906
1910
/// # _ => {},
1907
1911
/// },
1908
1912
/// Event::PaymentClaimed { payment_hash, amount_msat, .. } => {
1909
- /// assert_eq!(payment_hash, known_payment_hash );
1913
+ /// assert_eq!(payment_hash.0, invoice.payment_hash().as_ref() );
1910
1914
/// println!("Claimed {} msats", amount_msat);
1911
1915
/// },
1912
1916
/// // ...
@@ -1917,8 +1921,8 @@ where
1917
1921
/// # }
1918
1922
/// ```
1919
1923
///
1920
- /// For paying an invoice, [`lightning-invoice `] provides a `payment` module with convenience
1921
- /// functions for use with [`send_payment`].
1924
+ /// For paying an invoice, see the [`bolt11_payment `] module with convenience functions for use with
1925
+ /// [`send_payment`].
1922
1926
///
1923
1927
/// ```
1924
1928
/// # use lightning::events::{Event, EventsProvider};
@@ -2252,8 +2256,10 @@ where
2252
2256
/// [`list_recent_payments`]: Self::list_recent_payments
2253
2257
/// [`abandon_payment`]: Self::abandon_payment
2254
2258
/// [`lightning-invoice`]: https://docs.rs/lightning_invoice/latest/lightning_invoice
2259
+ /// [`create_bolt11_invoice`]: Self::create_bolt11_invoice
2255
2260
/// [`create_inbound_payment`]: Self::create_inbound_payment
2256
2261
/// [`create_inbound_payment_for_hash`]: Self::create_inbound_payment_for_hash
2262
+ /// [`bolt11_payment`]: crate::ln::bolt11_payment
2257
2263
/// [`claim_funds`]: Self::claim_funds
2258
2264
/// [`send_payment`]: Self::send_payment
2259
2265
/// [`offers`]: crate::offers
@@ -9240,6 +9246,145 @@ where
9240
9246
self.finish_close_channel(failure);
9241
9247
}
9242
9248
}
9249
+
9250
+ /// Utility for creating a BOLT11 invoice that can be verified by [`ChannelManager`] without
9251
+ /// storing any additional state. It achieves this by including a [`PaymentSecret`] in the
9252
+ /// invoice which it uses to verify that the invoice has not expired and the payment amount is
9253
+ /// sufficient, reproducing the [`PaymentPreimage`] if applicable.
9254
+ pub fn create_bolt11_invoice(
9255
+ &self, params: Bolt11InvoiceParameters,
9256
+ ) -> Result<Bolt11Invoice, SignOrCreationError<()>> {
9257
+ let Bolt11InvoiceParameters {
9258
+ amount_msats, description, invoice_expiry_delta_secs, min_final_cltv_expiry_delta,
9259
+ payment_hash,
9260
+ } = params;
9261
+
9262
+ let currency =
9263
+ Network::from_chain_hash(self.chain_hash).map(Into::into).unwrap_or(Currency::Bitcoin);
9264
+
9265
+ #[cfg(feature = "std")]
9266
+ let duration_since_epoch = {
9267
+ use std::time::SystemTime;
9268
+ SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)
9269
+ .expect("for the foreseeable future this shouldn't happen")
9270
+ };
9271
+ #[cfg(not(feature = "std"))]
9272
+ let duration_since_epoch =
9273
+ Duration::from_secs(self.highest_seen_timestamp.load(Ordering::Acquire) as u64);
9274
+
9275
+ if let Some(min_final_cltv_expiry_delta) = min_final_cltv_expiry_delta {
9276
+ if min_final_cltv_expiry_delta.saturating_add(3) < MIN_FINAL_CLTV_EXPIRY_DELTA {
9277
+ return Err(SignOrCreationError::CreationError(CreationError::MinFinalCltvExpiryDeltaTooShort));
9278
+ }
9279
+ }
9280
+
9281
+ let (payment_hash, payment_secret) = match payment_hash {
9282
+ Some(payment_hash) => {
9283
+ let payment_secret = self
9284
+ .create_inbound_payment_for_hash(
9285
+ payment_hash, amount_msats,
9286
+ invoice_expiry_delta_secs.unwrap_or(DEFAULT_EXPIRY_TIME as u32),
9287
+ min_final_cltv_expiry_delta,
9288
+ )
9289
+ .map_err(|()| SignOrCreationError::CreationError(CreationError::InvalidAmount))?;
9290
+ (payment_hash, payment_secret)
9291
+ },
9292
+ None => {
9293
+ self
9294
+ .create_inbound_payment(
9295
+ amount_msats, invoice_expiry_delta_secs.unwrap_or(DEFAULT_EXPIRY_TIME as u32),
9296
+ min_final_cltv_expiry_delta,
9297
+ )
9298
+ .map_err(|()| SignOrCreationError::CreationError(CreationError::InvalidAmount))?
9299
+ },
9300
+ };
9301
+
9302
+ log_trace!(self.logger, "Creating invoice with payment hash {}", &payment_hash);
9303
+
9304
+ let invoice = Bolt11InvoiceBuilder::new(currency);
9305
+ let invoice = match description {
9306
+ Bolt11InvoiceDescription::Direct(description) => invoice.description(description.into_inner().0),
9307
+ Bolt11InvoiceDescription::Hash(hash) => invoice.description_hash(hash.0),
9308
+ };
9309
+
9310
+ let mut invoice = invoice
9311
+ .duration_since_epoch(duration_since_epoch)
9312
+ .payee_pub_key(self.get_our_node_id())
9313
+ .payment_hash(Hash::from_slice(&payment_hash.0).unwrap())
9314
+ .payment_secret(payment_secret)
9315
+ .basic_mpp()
9316
+ .min_final_cltv_expiry_delta(
9317
+ // Add a buffer of 3 to the delta if present, otherwise use LDK's minimum.
9318
+ min_final_cltv_expiry_delta.map(|x| x.saturating_add(3)).unwrap_or(MIN_FINAL_CLTV_EXPIRY_DELTA).into()
9319
+ );
9320
+
9321
+ if let Some(invoice_expiry_delta_secs) = invoice_expiry_delta_secs{
9322
+ invoice = invoice.expiry_time(Duration::from_secs(invoice_expiry_delta_secs.into()));
9323
+ }
9324
+
9325
+ if let Some(amount_msats) = amount_msats {
9326
+ invoice = invoice.amount_milli_satoshis(amount_msats);
9327
+ }
9328
+
9329
+ let channels = self.list_channels();
9330
+ let route_hints = super::invoice_utils::sort_and_filter_channels(channels, amount_msats, &self.logger);
9331
+ for hint in route_hints {
9332
+ invoice = invoice.private_route(hint);
9333
+ }
9334
+
9335
+ let raw_invoice = invoice.build_raw().map_err(|e| SignOrCreationError::CreationError(e))?;
9336
+ let signature = self.node_signer.sign_invoice(&raw_invoice, Recipient::Node);
9337
+
9338
+ raw_invoice
9339
+ .sign(|_| signature)
9340
+ .map(|invoice| Bolt11Invoice::from_signed(invoice).unwrap())
9341
+ .map_err(|e| SignOrCreationError::SignError(e))
9342
+ }
9343
+ }
9344
+
9345
+ /// Parameters used with [`create_bolt11_invoice`].
9346
+ ///
9347
+ /// [`create_bolt11_invoice`]: ChannelManager::create_bolt11_invoice
9348
+ pub struct Bolt11InvoiceParameters {
9349
+ /// The amount for the invoice, if any.
9350
+ pub amount_msats: Option<u64>,
9351
+
9352
+ /// The description for what the invoice is for, or hash of such description.
9353
+ pub description: Bolt11InvoiceDescription,
9354
+
9355
+ /// The invoice expiration relative to its creation time. If not set, the invoice will expire in
9356
+ /// [`DEFAULT_EXPIRY_TIME`] by default.
9357
+ ///
9358
+ /// The creation time used is the duration since the Unix epoch for `std` builds. For non-`std`
9359
+ /// builds, the highest block timestamp seen is used instead.
9360
+ pub invoice_expiry_delta_secs: Option<u32>,
9361
+
9362
+ /// The minimum `cltv_expiry` for the last HTLC in the route. If not set, will use
9363
+ /// [`MIN_FINAL_CLTV_EXPIRY_DELTA`].
9364
+ ///
9365
+ /// If set, must be at least [`MIN_FINAL_CLTV_EXPIRY_DELTA`], and a three-block buffer will be
9366
+ /// added as well to allow for up to a few new block confirmations during routing.
9367
+ pub min_final_cltv_expiry_delta: Option<u16>,
9368
+
9369
+ /// The payment hash used in the invoice. If not set, a payment hash will be generated using a
9370
+ /// preimage that can be reproduced by [`ChannelManager`] without storing any state.
9371
+ ///
9372
+ /// Uses the payment hash if set. This may be useful if you're building an on-chain swap or
9373
+ /// involving another protocol where the payment hash is also involved outside the scope of
9374
+ /// lightning.
9375
+ pub payment_hash: Option<PaymentHash>,
9376
+ }
9377
+
9378
+ impl Default for Bolt11InvoiceParameters {
9379
+ fn default() -> Self {
9380
+ Self {
9381
+ amount_msats: None,
9382
+ description: Bolt11InvoiceDescription::Direct(Description::empty()),
9383
+ invoice_expiry_delta_secs: None,
9384
+ min_final_cltv_expiry_delta: None,
9385
+ payment_hash: None,
9386
+ }
9387
+ }
9243
9388
}
9244
9389
9245
9390
macro_rules! create_offer_builder { ($self: ident, $builder: ty) => {
0 commit comments