@@ -102,6 +102,8 @@ use {
102102 crate::offers::refund::RefundMaybeWithDerivedMetadataBuilder,
103103};
104104
105+ use lightning_invoice::{Bolt11Invoice, Bolt11InvoiceDescription, CreationError, Currency, Description, InvoiceBuilder as Bolt11InvoiceBuilder, SignOrCreationError, DEFAULT_EXPIRY_TIME};
106+
105107use alloc::collections::{btree_map, BTreeMap};
106108
107109use crate::io;
@@ -1857,56 +1859,58 @@ where
18571859///
18581860/// ## BOLT 11 Invoices
18591861///
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
18631865/// [`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`] .
18661868///
18671869/// [`ChannelManager`] generates an [`Event::PaymentClaimable`] once the full payment has been
18681870/// received. Call [`claim_funds`] to release the [`PaymentPreimage`], which in turn will result in
18691871/// an [`Event::PaymentClaimed`].
18701872///
18711873/// ```
18721874/// # use lightning::events::{Event, EventsProvider, PaymentPurpose};
1873- /// # use lightning::ln::channelmanager::AChannelManager;
1875+ /// # use lightning::ln::channelmanager::{ AChannelManager, Bolt11InvoiceParameters} ;
18741876/// #
18751877/// # fn example<T: AChannelManager>(channel_manager: T) {
18761878/// # 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
18841888/// },
1885- /// Err(()) => panic!("Error creating inbound payment" ),
1889+ /// Err(e) => panic!("Error creating invoice: {}", e ),
18861890/// };
18871891///
18881892/// // On the event processing thread
18891893/// channel_manager.process_pending_events(&|event| {
18901894/// match event {
18911895/// Event::PaymentClaimable { payment_hash, purpose, .. } => match purpose {
18921896/// 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() );
18941898/// println!("Claiming payment {}", payment_hash);
18951899/// channel_manager.claim_funds(payment_preimage);
18961900/// },
18971901/// PaymentPurpose::Bolt11InvoicePayment { payment_preimage: None, .. } => {
18981902/// println!("Unknown payment hash: {}", payment_hash);
18991903/// },
19001904/// PaymentPurpose::SpontaneousPayment(payment_preimage) => {
1901- /// assert_ne!(payment_hash, known_payment_hash );
1905+ /// assert_ne!(payment_hash.0, invoice.payment_hash().as_ref() );
19021906/// println!("Claiming spontaneous payment {}", payment_hash);
19031907/// channel_manager.claim_funds(payment_preimage);
19041908/// },
19051909/// // ...
19061910/// # _ => {},
19071911/// },
19081912/// 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() );
19101914/// println!("Claimed {} msats", amount_msat);
19111915/// },
19121916/// // ...
@@ -1917,8 +1921,8 @@ where
19171921/// # }
19181922/// ```
19191923///
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`].
19221926///
19231927/// ```
19241928/// # use lightning::events::{Event, EventsProvider};
@@ -2252,8 +2256,10 @@ where
22522256/// [`list_recent_payments`]: Self::list_recent_payments
22532257/// [`abandon_payment`]: Self::abandon_payment
22542258/// [`lightning-invoice`]: https://docs.rs/lightning_invoice/latest/lightning_invoice
2259+ /// [`create_bolt11_invoice`]: Self::create_bolt11_invoice
22552260/// [`create_inbound_payment`]: Self::create_inbound_payment
22562261/// [`create_inbound_payment_for_hash`]: Self::create_inbound_payment_for_hash
2262+ /// [`bolt11_payment`]: crate::ln::bolt11_payment
22572263/// [`claim_funds`]: Self::claim_funds
22582264/// [`send_payment`]: Self::send_payment
22592265/// [`offers`]: crate::offers
@@ -9240,6 +9246,145 @@ where
92409246 self.finish_close_channel(failure);
92419247 }
92429248 }
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+ }
92439388}
92449389
92459390macro_rules! create_offer_builder { ($self: ident, $builder: ty) => {
0 commit comments