@@ -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;
@@ -2199,7 +2201,7 @@ where
2199
2201
L::Target: Logger,
2200
2202
{
2201
2203
default_configuration: UserConfig,
2202
- pub(super) chain_hash: ChainHash,
2204
+ chain_hash: ChainHash,
2203
2205
fee_estimator: LowerBoundedFeeEstimator<F>,
2204
2206
chain_monitor: M,
2205
2207
tx_broadcaster: T,
@@ -9093,6 +9095,145 @@ where
9093
9095
self.finish_close_channel(failure);
9094
9096
}
9095
9097
}
9098
+
9099
+ /// Utility for creating a BOLT11 invoice that can be verified by [`ChannelManager`] without
9100
+ /// storing any additional state. It achieves this by including a [`PaymentSecret`] in the
9101
+ /// invoice which it uses to verify that the invoice has not expired and the payment amount is
9102
+ /// sufficient, reproducing the [`PaymentPreimage`] if applicable.
9103
+ pub fn create_bolt11_invoice(
9104
+ &self, params: Bolt11InvoiceParameters,
9105
+ ) -> Result<Bolt11Invoice, SignOrCreationError<()>> {
9106
+ let Bolt11InvoiceParameters {
9107
+ amount_msats, description, invoice_expiry_delta_secs, min_final_cltv_expiry_delta,
9108
+ payment_hash,
9109
+ } = params;
9110
+
9111
+ let currency =
9112
+ Network::from_chain_hash(self.chain_hash).map(Into::into).unwrap_or(Currency::Bitcoin);
9113
+
9114
+ #[cfg(feature = "std")]
9115
+ let duration_since_epoch = {
9116
+ use std::time::SystemTime;
9117
+ SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)
9118
+ .expect("for the foreseeable future this shouldn't happen")
9119
+ };
9120
+ #[cfg(not(feature = "std"))]
9121
+ let duration_since_epoch =
9122
+ Duration::from_secs(self.highest_seen_timestamp.load(Ordering::Acquire) as u64);
9123
+
9124
+ if let Some(min_final_cltv_expiry_delta) = min_final_cltv_expiry_delta {
9125
+ if min_final_cltv_expiry_delta.saturating_add(3) < MIN_FINAL_CLTV_EXPIRY_DELTA {
9126
+ return Err(SignOrCreationError::CreationError(CreationError::MinFinalCltvExpiryDeltaTooShort));
9127
+ }
9128
+ }
9129
+
9130
+ let (payment_hash, payment_secret) = match payment_hash {
9131
+ Some(payment_hash) => {
9132
+ let payment_secret = self
9133
+ .create_inbound_payment_for_hash(
9134
+ payment_hash, amount_msats,
9135
+ invoice_expiry_delta_secs.unwrap_or(DEFAULT_EXPIRY_TIME as u32),
9136
+ min_final_cltv_expiry_delta,
9137
+ )
9138
+ .map_err(|()| SignOrCreationError::CreationError(CreationError::InvalidAmount))?;
9139
+ (payment_hash, payment_secret)
9140
+ },
9141
+ None => {
9142
+ self
9143
+ .create_inbound_payment(
9144
+ amount_msats, invoice_expiry_delta_secs.unwrap_or(DEFAULT_EXPIRY_TIME as u32),
9145
+ min_final_cltv_expiry_delta,
9146
+ )
9147
+ .map_err(|()| SignOrCreationError::CreationError(CreationError::InvalidAmount))?
9148
+ },
9149
+ };
9150
+
9151
+ log_trace!(self.logger, "Creating invoice with payment hash {}", &payment_hash);
9152
+
9153
+ let invoice = Bolt11InvoiceBuilder::new(currency);
9154
+ let invoice = match description {
9155
+ Bolt11InvoiceDescription::Direct(description) => invoice.description(description.into_inner().0),
9156
+ Bolt11InvoiceDescription::Hash(hash) => invoice.description_hash(hash.0),
9157
+ };
9158
+
9159
+ let mut invoice = invoice
9160
+ .duration_since_epoch(duration_since_epoch)
9161
+ .payee_pub_key(self.get_our_node_id())
9162
+ .payment_hash(Hash::from_slice(&payment_hash.0).unwrap())
9163
+ .payment_secret(payment_secret)
9164
+ .basic_mpp()
9165
+ .min_final_cltv_expiry_delta(
9166
+ // Add a buffer of 3 to the delta if present, otherwise use LDK's minimum.
9167
+ min_final_cltv_expiry_delta.map(|x| x.saturating_add(3)).unwrap_or(MIN_FINAL_CLTV_EXPIRY_DELTA).into()
9168
+ );
9169
+
9170
+ if let Some(invoice_expiry_delta_secs) = invoice_expiry_delta_secs{
9171
+ invoice = invoice.expiry_time(Duration::from_secs(invoice_expiry_delta_secs.into()));
9172
+ }
9173
+
9174
+ if let Some(amount_msats) = amount_msats {
9175
+ invoice = invoice.amount_milli_satoshis(amount_msats);
9176
+ }
9177
+
9178
+ let channels = self.list_channels();
9179
+ let route_hints = super::invoice_utils::sort_and_filter_channels(channels, amount_msats, &self.logger);
9180
+ for hint in route_hints {
9181
+ invoice = invoice.private_route(hint);
9182
+ }
9183
+
9184
+ let raw_invoice = invoice.build_raw().map_err(|e| SignOrCreationError::CreationError(e))?;
9185
+ let signature = self.node_signer.sign_invoice(&raw_invoice, Recipient::Node);
9186
+
9187
+ raw_invoice
9188
+ .sign(|_| signature)
9189
+ .map(|invoice| Bolt11Invoice::from_signed(invoice).unwrap())
9190
+ .map_err(|e| SignOrCreationError::SignError(e))
9191
+ }
9192
+ }
9193
+
9194
+ /// Parameters used with [`create_bolt11_invoice`].
9195
+ ///
9196
+ /// [`create_bolt11_invoice`]: ChannelManager::create_bolt11_invoice
9197
+ pub struct Bolt11InvoiceParameters {
9198
+ /// The amount for the invoice, if any.
9199
+ pub amount_msats: Option<u64>,
9200
+
9201
+ /// The description for what the invoice is for, or hash of such description.
9202
+ pub description: Bolt11InvoiceDescription,
9203
+
9204
+ /// The invoice expiration relative to its creation time. If not set, the invoice will expire in
9205
+ /// [`DEFAULT_EXPIRY_TIME`] by default.
9206
+ ///
9207
+ /// The creation time used is the duration since the Unix epoch for `std` builds. For non-`std`
9208
+ /// builds, the highest block timestamp seen is used instead.
9209
+ pub invoice_expiry_delta_secs: Option<u32>,
9210
+
9211
+ /// The minimum `cltv_expiry` for the last HTLC in the route. If not set, will use
9212
+ /// [`MIN_FINAL_CLTV_EXPIRY_DELTA`].
9213
+ ///
9214
+ /// If set, must be at least [`MIN_FINAL_CLTV_EXPIRY_DELTA`], and a three-block buffer will be
9215
+ /// added as well to allow for up to a few new block confirmations during routing.
9216
+ pub min_final_cltv_expiry_delta: Option<u16>,
9217
+
9218
+ /// The payment hash used in the invoice. If not set, a payment hash will be generated using a
9219
+ /// preimage that can be reproduced by [`ChannelManager`] without storing any state.
9220
+ ///
9221
+ /// Uses the payment hash if set. This may be useful if you're building an on-chain swap or
9222
+ /// involving another protocol where the payment hash is also involved outside the scope of
9223
+ /// lightning.
9224
+ pub payment_hash: Option<PaymentHash>,
9225
+ }
9226
+
9227
+ impl Default for Bolt11InvoiceParameters {
9228
+ fn default() -> Self {
9229
+ Self {
9230
+ amount_msats: None,
9231
+ description: Bolt11InvoiceDescription::Direct(Description::empty()),
9232
+ invoice_expiry_delta_secs: None,
9233
+ min_final_cltv_expiry_delta: None,
9234
+ payment_hash: None,
9235
+ }
9236
+ }
9096
9237
}
9097
9238
9098
9239
macro_rules! create_offer_builder { ($self: ident, $builder: ty) => {
0 commit comments