ldk_node/payment/
bolt11.rs

1// This file is Copyright its original authors, visible in version control history.
2//
3// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. You may not use this file except in
6// accordance with one or both of these licenses.
7
8//! Holds a payment handler allowing to create and pay [BOLT 11] invoices.
9//!
10//! [BOLT 11]: https://github.com/lightning/bolts/blob/master/11-payment-encoding.md
11
12use crate::config::{Config, LDK_PAYMENT_RETRY_TIMEOUT};
13use crate::connection::ConnectionManager;
14use crate::data_store::DataStoreUpdateResult;
15use crate::error::Error;
16use crate::liquidity::LiquiditySource;
17use crate::logger::{log_error, log_info, LdkLogger, Logger};
18use crate::payment::store::{
19	LSPFeeLimits, PaymentDetails, PaymentDetailsUpdate, PaymentDirection, PaymentKind,
20	PaymentStatus,
21};
22use crate::payment::SendingParameters;
23use crate::peer_store::{PeerInfo, PeerStore};
24use crate::types::{ChannelManager, PaymentStore};
25
26use lightning::ln::bolt11_payment;
27use lightning::ln::channelmanager::{
28	Bolt11InvoiceParameters, PaymentId, RecipientOnionFields, Retry, RetryableSendFailure,
29};
30use lightning::routing::router::{PaymentParameters, RouteParameters};
31
32use lightning_types::payment::{PaymentHash, PaymentPreimage};
33
34use lightning_invoice::Bolt11Invoice as LdkBolt11Invoice;
35use lightning_invoice::Bolt11InvoiceDescription as LdkBolt11InvoiceDescription;
36
37use bitcoin::hashes::sha256::Hash as Sha256;
38use bitcoin::hashes::Hash;
39
40use std::sync::{Arc, RwLock};
41
42#[cfg(not(feature = "uniffi"))]
43type Bolt11Invoice = LdkBolt11Invoice;
44#[cfg(feature = "uniffi")]
45type Bolt11Invoice = Arc<crate::uniffi_types::Bolt11Invoice>;
46
47#[cfg(not(feature = "uniffi"))]
48pub(crate) fn maybe_wrap_invoice(invoice: LdkBolt11Invoice) -> Bolt11Invoice {
49	invoice
50}
51#[cfg(feature = "uniffi")]
52pub(crate) fn maybe_wrap_invoice(invoice: LdkBolt11Invoice) -> Bolt11Invoice {
53	Arc::new(invoice.into())
54}
55
56#[cfg(not(feature = "uniffi"))]
57pub fn maybe_convert_invoice(invoice: &Bolt11Invoice) -> &LdkBolt11Invoice {
58	invoice
59}
60#[cfg(feature = "uniffi")]
61pub fn maybe_convert_invoice(invoice: &Bolt11Invoice) -> &LdkBolt11Invoice {
62	&invoice.inner
63}
64
65#[cfg(not(feature = "uniffi"))]
66type Bolt11InvoiceDescription = LdkBolt11InvoiceDescription;
67#[cfg(feature = "uniffi")]
68type Bolt11InvoiceDescription = crate::uniffi_types::Bolt11InvoiceDescription;
69
70macro_rules! maybe_convert_description {
71	($description: expr) => {{
72		#[cfg(not(feature = "uniffi"))]
73		{
74			$description
75		}
76		#[cfg(feature = "uniffi")]
77		{
78			&LdkBolt11InvoiceDescription::try_from($description)?
79		}
80	}};
81}
82
83/// A payment handler allowing to create and pay [BOLT 11] invoices.
84///
85/// Should be retrieved by calling [`Node::bolt11_payment`].
86///
87/// [BOLT 11]: https://github.com/lightning/bolts/blob/master/11-payment-encoding.md
88/// [`Node::bolt11_payment`]: crate::Node::bolt11_payment
89pub struct Bolt11Payment {
90	runtime: Arc<RwLock<Option<Arc<tokio::runtime::Runtime>>>>,
91	channel_manager: Arc<ChannelManager>,
92	connection_manager: Arc<ConnectionManager<Arc<Logger>>>,
93	liquidity_source: Option<Arc<LiquiditySource<Arc<Logger>>>>,
94	payment_store: Arc<PaymentStore>,
95	peer_store: Arc<PeerStore<Arc<Logger>>>,
96	config: Arc<Config>,
97	logger: Arc<Logger>,
98}
99
100impl Bolt11Payment {
101	pub(crate) fn new(
102		runtime: Arc<RwLock<Option<Arc<tokio::runtime::Runtime>>>>,
103		channel_manager: Arc<ChannelManager>,
104		connection_manager: Arc<ConnectionManager<Arc<Logger>>>,
105		liquidity_source: Option<Arc<LiquiditySource<Arc<Logger>>>>,
106		payment_store: Arc<PaymentStore>, peer_store: Arc<PeerStore<Arc<Logger>>>,
107		config: Arc<Config>, logger: Arc<Logger>,
108	) -> Self {
109		Self {
110			runtime,
111			channel_manager,
112			connection_manager,
113			liquidity_source,
114			payment_store,
115			peer_store,
116			config,
117			logger,
118		}
119	}
120
121	/// Send a payment given an invoice.
122	///
123	/// If `sending_parameters` are provided they will override the default as well as the
124	/// node-wide parameters configured via [`Config::sending_parameters`] on a per-field basis.
125	pub fn send(
126		&self, invoice: &Bolt11Invoice, sending_parameters: Option<SendingParameters>,
127	) -> Result<PaymentId, Error> {
128		let invoice = maybe_convert_invoice(invoice);
129		let rt_lock = self.runtime.read().unwrap();
130		if rt_lock.is_none() {
131			return Err(Error::NotRunning);
132		}
133
134		let (payment_hash, recipient_onion, mut route_params) = bolt11_payment::payment_parameters_from_invoice(&invoice).map_err(|_| {
135			log_error!(self.logger, "Failed to send payment due to the given invoice being \"zero-amount\". Please use send_using_amount instead.");
136			Error::InvalidInvoice
137		})?;
138
139		let payment_id = PaymentId(invoice.payment_hash().to_byte_array());
140		if let Some(payment) = self.payment_store.get(&payment_id) {
141			if payment.status == PaymentStatus::Pending
142				|| payment.status == PaymentStatus::Succeeded
143			{
144				log_error!(self.logger, "Payment error: an invoice must not be paid twice.");
145				return Err(Error::DuplicatePayment);
146			}
147		}
148
149		let override_params =
150			sending_parameters.as_ref().or(self.config.sending_parameters.as_ref());
151		if let Some(override_params) = override_params {
152			override_params
153				.max_total_routing_fee_msat
154				.map(|f| route_params.max_total_routing_fee_msat = f.into());
155			override_params
156				.max_total_cltv_expiry_delta
157				.map(|d| route_params.payment_params.max_total_cltv_expiry_delta = d);
158			override_params.max_path_count.map(|p| route_params.payment_params.max_path_count = p);
159			override_params
160				.max_channel_saturation_power_of_half
161				.map(|s| route_params.payment_params.max_channel_saturation_power_of_half = s);
162		};
163
164		let payment_secret = Some(*invoice.payment_secret());
165		let retry_strategy = Retry::Timeout(LDK_PAYMENT_RETRY_TIMEOUT);
166
167		match self.channel_manager.send_payment(
168			payment_hash,
169			recipient_onion,
170			payment_id,
171			route_params,
172			retry_strategy,
173		) {
174			Ok(()) => {
175				let payee_pubkey = invoice.recover_payee_pub_key();
176				let amt_msat = invoice.amount_milli_satoshis().unwrap();
177				log_info!(self.logger, "Initiated sending {}msat to {}", amt_msat, payee_pubkey);
178
179				let kind = PaymentKind::Bolt11 {
180					hash: payment_hash,
181					preimage: None,
182					secret: payment_secret,
183				};
184				let payment = PaymentDetails::new(
185					payment_id,
186					kind,
187					invoice.amount_milli_satoshis(),
188					None,
189					PaymentDirection::Outbound,
190					PaymentStatus::Pending,
191				);
192
193				self.payment_store.insert(payment)?;
194
195				Ok(payment_id)
196			},
197			Err(e) => {
198				log_error!(self.logger, "Failed to send payment: {:?}", e);
199				match e {
200					RetryableSendFailure::DuplicatePayment => Err(Error::DuplicatePayment),
201					_ => {
202						let kind = PaymentKind::Bolt11 {
203							hash: payment_hash,
204							preimage: None,
205							secret: payment_secret,
206						};
207						let payment = PaymentDetails::new(
208							payment_id,
209							kind,
210							invoice.amount_milli_satoshis(),
211							None,
212							PaymentDirection::Outbound,
213							PaymentStatus::Failed,
214						);
215
216						self.payment_store.insert(payment)?;
217						Err(Error::PaymentSendingFailed)
218					},
219				}
220			},
221		}
222	}
223
224	/// Send a payment given an invoice and an amount in millisatoshis.
225	///
226	/// This will fail if the amount given is less than the value required by the given invoice.
227	///
228	/// This can be used to pay a so-called "zero-amount" invoice, i.e., an invoice that leaves the
229	/// amount paid to be determined by the user.
230	///
231	/// If `sending_parameters` are provided they will override the default as well as the
232	/// node-wide parameters configured via [`Config::sending_parameters`] on a per-field basis.
233	pub fn send_using_amount(
234		&self, invoice: &Bolt11Invoice, amount_msat: u64,
235		sending_parameters: Option<SendingParameters>,
236	) -> Result<PaymentId, Error> {
237		let invoice = maybe_convert_invoice(invoice);
238		let rt_lock = self.runtime.read().unwrap();
239		if rt_lock.is_none() {
240			return Err(Error::NotRunning);
241		}
242
243		if let Some(invoice_amount_msat) = invoice.amount_milli_satoshis() {
244			if amount_msat < invoice_amount_msat {
245				log_error!(
246					self.logger,
247					"Failed to pay as the given amount needs to be at least the invoice amount: required {}msat, gave {}msat.", invoice_amount_msat, amount_msat);
248				return Err(Error::InvalidAmount);
249			}
250		}
251
252		let payment_hash = PaymentHash(invoice.payment_hash().to_byte_array());
253		let payment_id = PaymentId(invoice.payment_hash().to_byte_array());
254		if let Some(payment) = self.payment_store.get(&payment_id) {
255			if payment.status == PaymentStatus::Pending
256				|| payment.status == PaymentStatus::Succeeded
257			{
258				log_error!(self.logger, "Payment error: an invoice must not be paid twice.");
259				return Err(Error::DuplicatePayment);
260			}
261		}
262
263		let payment_secret = invoice.payment_secret();
264		let expiry_time = invoice.duration_since_epoch().saturating_add(invoice.expiry_time());
265		let mut payment_params = PaymentParameters::from_node_id(
266			invoice.recover_payee_pub_key(),
267			invoice.min_final_cltv_expiry_delta() as u32,
268		)
269		.with_expiry_time(expiry_time.as_secs())
270		.with_route_hints(invoice.route_hints())
271		.map_err(|_| Error::InvalidInvoice)?;
272		if let Some(features) = invoice.features() {
273			payment_params = payment_params
274				.with_bolt11_features(features.clone())
275				.map_err(|_| Error::InvalidInvoice)?;
276		}
277		let mut route_params =
278			RouteParameters::from_payment_params_and_value(payment_params, amount_msat);
279
280		let override_params =
281			sending_parameters.as_ref().or(self.config.sending_parameters.as_ref());
282		if let Some(override_params) = override_params {
283			override_params
284				.max_total_routing_fee_msat
285				.map(|f| route_params.max_total_routing_fee_msat = f.into());
286			override_params
287				.max_total_cltv_expiry_delta
288				.map(|d| route_params.payment_params.max_total_cltv_expiry_delta = d);
289			override_params.max_path_count.map(|p| route_params.payment_params.max_path_count = p);
290			override_params
291				.max_channel_saturation_power_of_half
292				.map(|s| route_params.payment_params.max_channel_saturation_power_of_half = s);
293		};
294
295		let retry_strategy = Retry::Timeout(LDK_PAYMENT_RETRY_TIMEOUT);
296		let recipient_fields = RecipientOnionFields::secret_only(*payment_secret);
297
298		match self.channel_manager.send_payment(
299			payment_hash,
300			recipient_fields,
301			payment_id,
302			route_params,
303			retry_strategy,
304		) {
305			Ok(()) => {
306				let payee_pubkey = invoice.recover_payee_pub_key();
307				log_info!(
308					self.logger,
309					"Initiated sending {} msat to {}",
310					amount_msat,
311					payee_pubkey
312				);
313
314				let kind = PaymentKind::Bolt11 {
315					hash: payment_hash,
316					preimage: None,
317					secret: Some(*payment_secret),
318				};
319
320				let payment = PaymentDetails::new(
321					payment_id,
322					kind,
323					Some(amount_msat),
324					None,
325					PaymentDirection::Outbound,
326					PaymentStatus::Pending,
327				);
328				self.payment_store.insert(payment)?;
329
330				Ok(payment_id)
331			},
332			Err(e) => {
333				log_error!(self.logger, "Failed to send payment: {:?}", e);
334
335				match e {
336					RetryableSendFailure::DuplicatePayment => Err(Error::DuplicatePayment),
337					_ => {
338						let kind = PaymentKind::Bolt11 {
339							hash: payment_hash,
340							preimage: None,
341							secret: Some(*payment_secret),
342						};
343						let payment = PaymentDetails::new(
344							payment_id,
345							kind,
346							Some(amount_msat),
347							None,
348							PaymentDirection::Outbound,
349							PaymentStatus::Failed,
350						);
351						self.payment_store.insert(payment)?;
352
353						Err(Error::PaymentSendingFailed)
354					},
355				}
356			},
357		}
358	}
359
360	/// Allows to attempt manually claiming payments with the given preimage that have previously
361	/// been registered via [`receive_for_hash`] or [`receive_variable_amount_for_hash`].
362	///
363	/// This should be called in reponse to a [`PaymentClaimable`] event as soon as the preimage is
364	/// available.
365	///
366	/// Will check that the payment is known, and that the given preimage and claimable amount
367	/// match our expectations before attempting to claim the payment, and will return an error
368	/// otherwise.
369	///
370	/// When claiming the payment has succeeded, a [`PaymentReceived`] event will be emitted.
371	///
372	/// [`receive_for_hash`]: Self::receive_for_hash
373	/// [`receive_variable_amount_for_hash`]: Self::receive_variable_amount_for_hash
374	/// [`PaymentClaimable`]: crate::Event::PaymentClaimable
375	/// [`PaymentReceived`]: crate::Event::PaymentReceived
376	pub fn claim_for_hash(
377		&self, payment_hash: PaymentHash, claimable_amount_msat: u64, preimage: PaymentPreimage,
378	) -> Result<(), Error> {
379		let payment_id = PaymentId(payment_hash.0);
380
381		let expected_payment_hash = PaymentHash(Sha256::hash(&preimage.0).to_byte_array());
382
383		if expected_payment_hash != payment_hash {
384			log_error!(
385				self.logger,
386				"Failed to manually claim payment as the given preimage doesn't match the hash {}",
387				payment_hash
388			);
389			return Err(Error::InvalidPaymentPreimage);
390		}
391
392		if let Some(details) = self.payment_store.get(&payment_id) {
393			if let Some(expected_amount_msat) = details.amount_msat {
394				if claimable_amount_msat < expected_amount_msat {
395					log_error!(
396						self.logger,
397						"Failed to manually claim payment {} as the claimable amount is less than expected",
398						payment_id
399					);
400					return Err(Error::InvalidAmount);
401				}
402			}
403		} else {
404			log_error!(
405				self.logger,
406				"Failed to manually claim unknown payment with hash: {}",
407				payment_hash
408			);
409			return Err(Error::InvalidPaymentHash);
410		}
411
412		self.channel_manager.claim_funds(preimage);
413		Ok(())
414	}
415
416	/// Allows to manually fail payments with the given hash that have previously
417	/// been registered via [`receive_for_hash`] or [`receive_variable_amount_for_hash`].
418	///
419	/// This should be called in reponse to a [`PaymentClaimable`] event if the payment needs to be
420	/// failed back, e.g., if the correct preimage can't be retrieved in time before the claim
421	/// deadline has been reached.
422	///
423	/// Will check that the payment is known before failing the payment, and will return an error
424	/// otherwise.
425	///
426	/// [`receive_for_hash`]: Self::receive_for_hash
427	/// [`receive_variable_amount_for_hash`]: Self::receive_variable_amount_for_hash
428	/// [`PaymentClaimable`]: crate::Event::PaymentClaimable
429	pub fn fail_for_hash(&self, payment_hash: PaymentHash) -> Result<(), Error> {
430		let payment_id = PaymentId(payment_hash.0);
431
432		let update = PaymentDetailsUpdate {
433			status: Some(PaymentStatus::Failed),
434			..PaymentDetailsUpdate::new(payment_id)
435		};
436
437		match self.payment_store.update(&update) {
438			Ok(DataStoreUpdateResult::Updated) | Ok(DataStoreUpdateResult::Unchanged) => (),
439			Ok(DataStoreUpdateResult::NotFound) => {
440				log_error!(
441					self.logger,
442					"Failed to manually fail unknown payment with hash {}",
443					payment_hash,
444				);
445				return Err(Error::InvalidPaymentHash);
446			},
447			Err(e) => {
448				log_error!(
449					self.logger,
450					"Failed to manually fail payment with hash {}: {}",
451					payment_hash,
452					e
453				);
454				return Err(e);
455			},
456		}
457
458		self.channel_manager.fail_htlc_backwards(&payment_hash);
459		Ok(())
460	}
461
462	/// Returns a payable invoice that can be used to request and receive a payment of the amount
463	/// given.
464	///
465	/// The inbound payment will be automatically claimed upon arrival.
466	pub fn receive(
467		&self, amount_msat: u64, description: &Bolt11InvoiceDescription, expiry_secs: u32,
468	) -> Result<Bolt11Invoice, Error> {
469		let description = maybe_convert_description!(description);
470		let invoice = self.receive_inner(Some(amount_msat), description, expiry_secs, None)?;
471		Ok(maybe_wrap_invoice(invoice))
472	}
473
474	/// Returns a payable invoice that can be used to request a payment of the amount
475	/// given for the given payment hash.
476	///
477	/// We will register the given payment hash and emit a [`PaymentClaimable`] event once
478	/// the inbound payment arrives.
479	///
480	/// **Note:** users *MUST* handle this event and claim the payment manually via
481	/// [`claim_for_hash`] as soon as they have obtained access to the preimage of the given
482	/// payment hash. If they're unable to obtain the preimage, they *MUST* immediately fail the payment via
483	/// [`fail_for_hash`].
484	///
485	/// [`PaymentClaimable`]: crate::Event::PaymentClaimable
486	/// [`claim_for_hash`]: Self::claim_for_hash
487	/// [`fail_for_hash`]: Self::fail_for_hash
488	pub fn receive_for_hash(
489		&self, amount_msat: u64, description: &Bolt11InvoiceDescription, expiry_secs: u32,
490		payment_hash: PaymentHash,
491	) -> Result<Bolt11Invoice, Error> {
492		let description = maybe_convert_description!(description);
493		let invoice =
494			self.receive_inner(Some(amount_msat), description, expiry_secs, Some(payment_hash))?;
495		Ok(maybe_wrap_invoice(invoice))
496	}
497
498	/// Returns a payable invoice that can be used to request and receive a payment for which the
499	/// amount is to be determined by the user, also known as a "zero-amount" invoice.
500	///
501	/// The inbound payment will be automatically claimed upon arrival.
502	pub fn receive_variable_amount(
503		&self, description: &Bolt11InvoiceDescription, expiry_secs: u32,
504	) -> Result<Bolt11Invoice, Error> {
505		let description = maybe_convert_description!(description);
506		let invoice = self.receive_inner(None, description, expiry_secs, None)?;
507		Ok(maybe_wrap_invoice(invoice))
508	}
509
510	/// Returns a payable invoice that can be used to request a payment for the given payment hash
511	/// and the amount to be determined by the user, also known as a "zero-amount" invoice.
512	///
513	/// We will register the given payment hash and emit a [`PaymentClaimable`] event once
514	/// the inbound payment arrives.
515	///
516	/// **Note:** users *MUST* handle this event and claim the payment manually via
517	/// [`claim_for_hash`] as soon as they have obtained access to the preimage of the given
518	/// payment hash. If they're unable to obtain the preimage, they *MUST* immediately fail the payment via
519	/// [`fail_for_hash`].
520	///
521	/// [`PaymentClaimable`]: crate::Event::PaymentClaimable
522	/// [`claim_for_hash`]: Self::claim_for_hash
523	/// [`fail_for_hash`]: Self::fail_for_hash
524	pub fn receive_variable_amount_for_hash(
525		&self, description: &Bolt11InvoiceDescription, expiry_secs: u32, payment_hash: PaymentHash,
526	) -> Result<Bolt11Invoice, Error> {
527		let description = maybe_convert_description!(description);
528		let invoice = self.receive_inner(None, description, expiry_secs, Some(payment_hash))?;
529		Ok(maybe_wrap_invoice(invoice))
530	}
531
532	pub(crate) fn receive_inner(
533		&self, amount_msat: Option<u64>, invoice_description: &LdkBolt11InvoiceDescription,
534		expiry_secs: u32, manual_claim_payment_hash: Option<PaymentHash>,
535	) -> Result<LdkBolt11Invoice, Error> {
536		let invoice = {
537			let invoice_params = Bolt11InvoiceParameters {
538				amount_msats: amount_msat,
539				description: invoice_description.clone(),
540				invoice_expiry_delta_secs: Some(expiry_secs),
541				payment_hash: manual_claim_payment_hash,
542				..Default::default()
543			};
544
545			match self.channel_manager.create_bolt11_invoice(invoice_params) {
546				Ok(inv) => {
547					log_info!(self.logger, "Invoice created: {}", inv);
548					inv
549				},
550				Err(e) => {
551					log_error!(self.logger, "Failed to create invoice: {}", e);
552					return Err(Error::InvoiceCreationFailed);
553				},
554			}
555		};
556
557		let payment_hash = PaymentHash(invoice.payment_hash().to_byte_array());
558		let payment_secret = invoice.payment_secret();
559		let id = PaymentId(payment_hash.0);
560		let preimage = if manual_claim_payment_hash.is_none() {
561			// If the user hasn't registered a custom payment hash, we're positive ChannelManager
562			// will know the preimage at this point.
563			let res = self
564				.channel_manager
565				.get_payment_preimage(payment_hash, payment_secret.clone())
566				.ok();
567			debug_assert!(res.is_some(), "We just let ChannelManager create an inbound payment, it can't have forgotten the preimage by now.");
568			res
569		} else {
570			None
571		};
572		let kind = PaymentKind::Bolt11 {
573			hash: payment_hash,
574			preimage,
575			secret: Some(payment_secret.clone()),
576		};
577		let payment = PaymentDetails::new(
578			id,
579			kind,
580			amount_msat,
581			None,
582			PaymentDirection::Inbound,
583			PaymentStatus::Pending,
584		);
585		self.payment_store.insert(payment)?;
586
587		Ok(invoice)
588	}
589
590	/// Returns a payable invoice that can be used to request a payment of the amount given and
591	/// receive it via a newly created just-in-time (JIT) channel.
592	///
593	/// When the returned invoice is paid, the configured [LSPS2]-compliant LSP will open a channel
594	/// to us, supplying just-in-time inbound liquidity.
595	///
596	/// If set, `max_total_lsp_fee_limit_msat` will limit how much fee we allow the LSP to take for opening the
597	/// channel to us. We'll use its cheapest offer otherwise.
598	///
599	/// [LSPS2]: https://github.com/BitcoinAndLightningLayerSpecs/lsp/blob/main/LSPS2/README.md
600	pub fn receive_via_jit_channel(
601		&self, amount_msat: u64, description: &Bolt11InvoiceDescription, expiry_secs: u32,
602		max_total_lsp_fee_limit_msat: Option<u64>,
603	) -> Result<Bolt11Invoice, Error> {
604		let description = maybe_convert_description!(description);
605		let invoice = self.receive_via_jit_channel_inner(
606			Some(amount_msat),
607			description,
608			expiry_secs,
609			max_total_lsp_fee_limit_msat,
610			None,
611		)?;
612		Ok(maybe_wrap_invoice(invoice))
613	}
614
615	/// Returns a payable invoice that can be used to request a variable amount payment (also known
616	/// as "zero-amount" invoice) and receive it via a newly created just-in-time (JIT) channel.
617	///
618	/// When the returned invoice is paid, the configured [LSPS2]-compliant LSP will open a channel
619	/// to us, supplying just-in-time inbound liquidity.
620	///
621	/// If set, `max_proportional_lsp_fee_limit_ppm_msat` will limit how much proportional fee, in
622	/// parts-per-million millisatoshis, we allow the LSP to take for opening the channel to us.
623	/// We'll use its cheapest offer otherwise.
624	///
625	/// [LSPS2]: https://github.com/BitcoinAndLightningLayerSpecs/lsp/blob/main/LSPS2/README.md
626	pub fn receive_variable_amount_via_jit_channel(
627		&self, description: &Bolt11InvoiceDescription, expiry_secs: u32,
628		max_proportional_lsp_fee_limit_ppm_msat: Option<u64>,
629	) -> Result<Bolt11Invoice, Error> {
630		let description = maybe_convert_description!(description);
631		let invoice = self.receive_via_jit_channel_inner(
632			None,
633			description,
634			expiry_secs,
635			None,
636			max_proportional_lsp_fee_limit_ppm_msat,
637		)?;
638		Ok(maybe_wrap_invoice(invoice))
639	}
640
641	fn receive_via_jit_channel_inner(
642		&self, amount_msat: Option<u64>, description: &LdkBolt11InvoiceDescription,
643		expiry_secs: u32, max_total_lsp_fee_limit_msat: Option<u64>,
644		max_proportional_lsp_fee_limit_ppm_msat: Option<u64>,
645	) -> Result<LdkBolt11Invoice, Error> {
646		let liquidity_source =
647			self.liquidity_source.as_ref().ok_or(Error::LiquiditySourceUnavailable)?;
648
649		let (node_id, address) =
650			liquidity_source.get_lsps2_lsp_details().ok_or(Error::LiquiditySourceUnavailable)?;
651
652		let rt_lock = self.runtime.read().unwrap();
653		let runtime = rt_lock.as_ref().unwrap();
654
655		let peer_info = PeerInfo { node_id, address };
656
657		let con_node_id = peer_info.node_id;
658		let con_addr = peer_info.address.clone();
659		let con_cm = Arc::clone(&self.connection_manager);
660
661		// We need to use our main runtime here as a local runtime might not be around to poll
662		// connection futures going forward.
663		tokio::task::block_in_place(move || {
664			runtime.block_on(async move {
665				con_cm.connect_peer_if_necessary(con_node_id, con_addr).await
666			})
667		})?;
668
669		log_info!(self.logger, "Connected to LSP {}@{}. ", peer_info.node_id, peer_info.address);
670
671		let liquidity_source = Arc::clone(&liquidity_source);
672		let (invoice, lsp_total_opening_fee, lsp_prop_opening_fee) =
673			tokio::task::block_in_place(move || {
674				runtime.block_on(async move {
675					if let Some(amount_msat) = amount_msat {
676						liquidity_source
677							.lsps2_receive_to_jit_channel(
678								amount_msat,
679								description,
680								expiry_secs,
681								max_total_lsp_fee_limit_msat,
682							)
683							.await
684							.map(|(invoice, total_fee)| (invoice, Some(total_fee), None))
685					} else {
686						liquidity_source
687							.lsps2_receive_variable_amount_to_jit_channel(
688								description,
689								expiry_secs,
690								max_proportional_lsp_fee_limit_ppm_msat,
691							)
692							.await
693							.map(|(invoice, prop_fee)| (invoice, None, Some(prop_fee)))
694					}
695				})
696			})?;
697
698		// Register payment in payment store.
699		let payment_hash = PaymentHash(invoice.payment_hash().to_byte_array());
700		let payment_secret = invoice.payment_secret();
701		let lsp_fee_limits = LSPFeeLimits {
702			max_total_opening_fee_msat: lsp_total_opening_fee,
703			max_proportional_opening_fee_ppm_msat: lsp_prop_opening_fee,
704		};
705		let id = PaymentId(payment_hash.0);
706		let preimage =
707			self.channel_manager.get_payment_preimage(payment_hash, payment_secret.clone()).ok();
708		let kind = PaymentKind::Bolt11Jit {
709			hash: payment_hash,
710			preimage,
711			secret: Some(payment_secret.clone()),
712			counterparty_skimmed_fee_msat: None,
713			lsp_fee_limits,
714		};
715		let payment = PaymentDetails::new(
716			id,
717			kind,
718			amount_msat,
719			None,
720			PaymentDirection::Inbound,
721			PaymentStatus::Pending,
722		);
723		self.payment_store.insert(payment)?;
724
725		// Persist LSP peer to make sure we reconnect on restart.
726		self.peer_store.add_peer(peer_info)?;
727
728		Ok(invoice)
729	}
730
731	/// Sends payment probes over all paths of a route that would be used to pay the given invoice.
732	///
733	/// This may be used to send "pre-flight" probes, i.e., to train our scorer before conducting
734	/// the actual payment. Note this is only useful if there likely is sufficient time for the
735	/// probe to settle before sending out the actual payment, e.g., when waiting for user
736	/// confirmation in a wallet UI.
737	///
738	/// Otherwise, there is a chance the probe could take up some liquidity needed to complete the
739	/// actual payment. Users should therefore be cautious and might avoid sending probes if
740	/// liquidity is scarce and/or they don't expect the probe to return before they send the
741	/// payment. To mitigate this issue, channels with available liquidity less than the required
742	/// amount times [`Config::probing_liquidity_limit_multiplier`] won't be used to send
743	/// pre-flight probes.
744	pub fn send_probes(&self, invoice: &Bolt11Invoice) -> Result<(), Error> {
745		let invoice = maybe_convert_invoice(invoice);
746		let rt_lock = self.runtime.read().unwrap();
747		if rt_lock.is_none() {
748			return Err(Error::NotRunning);
749		}
750
751		let (_payment_hash, _recipient_onion, route_params) = bolt11_payment::payment_parameters_from_invoice(&invoice).map_err(|_| {
752			log_error!(self.logger, "Failed to send probes due to the given invoice being \"zero-amount\". Please use send_probes_using_amount instead.");
753			Error::InvalidInvoice
754		})?;
755
756		let liquidity_limit_multiplier = Some(self.config.probing_liquidity_limit_multiplier);
757
758		self.channel_manager
759			.send_preflight_probes(route_params, liquidity_limit_multiplier)
760			.map_err(|e| {
761				log_error!(self.logger, "Failed to send payment probes: {:?}", e);
762				Error::ProbeSendingFailed
763			})?;
764
765		Ok(())
766	}
767
768	/// Sends payment probes over all paths of a route that would be used to pay the given
769	/// zero-value invoice using the given amount.
770	///
771	/// This can be used to send pre-flight probes for a so-called "zero-amount" invoice, i.e., an
772	/// invoice that leaves the amount paid to be determined by the user.
773	///
774	/// See [`Self::send_probes`] for more information.
775	pub fn send_probes_using_amount(
776		&self, invoice: &Bolt11Invoice, amount_msat: u64,
777	) -> Result<(), Error> {
778		let invoice = maybe_convert_invoice(invoice);
779		let rt_lock = self.runtime.read().unwrap();
780		if rt_lock.is_none() {
781			return Err(Error::NotRunning);
782		}
783
784		let (_payment_hash, _recipient_onion, route_params) = if let Some(invoice_amount_msat) =
785			invoice.amount_milli_satoshis()
786		{
787			if amount_msat < invoice_amount_msat {
788				log_error!(
789					self.logger,
790					"Failed to send probes as the given amount needs to be at least the invoice amount: required {}msat, gave {}msat.", invoice_amount_msat, amount_msat);
791				return Err(Error::InvalidAmount);
792			}
793
794			bolt11_payment::payment_parameters_from_invoice(&invoice).map_err(|_| {
795				log_error!(self.logger, "Failed to send probes due to the given invoice unexpectedly being \"zero-amount\".");
796				Error::InvalidInvoice
797			})?
798		} else {
799			bolt11_payment::payment_parameters_from_variable_amount_invoice(&invoice, amount_msat).map_err(|_| {
800				log_error!(self.logger, "Failed to send probes due to the given invoice unexpectedly being not \"zero-amount\".");
801				Error::InvalidInvoice
802			})?
803		};
804
805		let liquidity_limit_multiplier = Some(self.config.probing_liquidity_limit_multiplier);
806
807		self.channel_manager
808			.send_preflight_probes(route_params, liquidity_limit_multiplier)
809			.map_err(|e| {
810				log_error!(self.logger, "Failed to send payment probes: {:?}", e);
811				Error::ProbeSendingFailed
812			})?;
813
814		Ok(())
815	}
816}