ldk_node/
liquidity.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//! Objects related to liquidity management.
9
10use std::collections::HashMap;
11use std::ops::Deref;
12use std::sync::{Arc, Mutex, RwLock};
13use std::time::Duration;
14
15use bitcoin::hashes::{sha256, Hash};
16use bitcoin::secp256k1::{PublicKey, Secp256k1};
17use bitcoin::Transaction;
18use chrono::Utc;
19use lightning::events::HTLCHandlingFailureType;
20use lightning::ln::channelmanager::{InterceptId, MIN_FINAL_CLTV_EXPIRY_DELTA};
21use lightning::ln::msgs::SocketAddress;
22use lightning::ln::types::ChannelId;
23use lightning::routing::router::{RouteHint, RouteHintHop};
24use lightning_invoice::{Bolt11Invoice, Bolt11InvoiceDescription, InvoiceBuilder, RoutingFees};
25use lightning_liquidity::events::LiquidityEvent;
26use lightning_liquidity::lsps0::ser::{LSPSDateTime, LSPSRequestId};
27use lightning_liquidity::lsps1::client::LSPS1ClientConfig as LdkLSPS1ClientConfig;
28use lightning_liquidity::lsps1::event::LSPS1ClientEvent;
29use lightning_liquidity::lsps1::msgs::{
30	LSPS1ChannelInfo, LSPS1Options, LSPS1OrderId, LSPS1OrderParams,
31};
32use lightning_liquidity::lsps2::client::LSPS2ClientConfig as LdkLSPS2ClientConfig;
33use lightning_liquidity::lsps2::event::{LSPS2ClientEvent, LSPS2ServiceEvent};
34use lightning_liquidity::lsps2::msgs::{LSPS2OpeningFeeParams, LSPS2RawOpeningFeeParams};
35use lightning_liquidity::lsps2::service::LSPS2ServiceConfig as LdkLSPS2ServiceConfig;
36use lightning_liquidity::lsps2::utils::compute_opening_fee;
37use lightning_liquidity::{LiquidityClientConfig, LiquidityServiceConfig};
38use lightning_types::payment::PaymentHash;
39use rand::Rng;
40use tokio::sync::oneshot;
41
42use crate::builder::BuildError;
43use crate::chain::ChainSource;
44use crate::connection::ConnectionManager;
45use crate::logger::{log_debug, log_error, log_info, LdkLogger, Logger};
46use crate::runtime::Runtime;
47use crate::types::{
48	Broadcaster, ChannelManager, DynStore, KeysManager, LiquidityManager, PeerManager, Wallet,
49};
50use crate::{total_anchor_channels_reserve_sats, Config, Error};
51
52const LIQUIDITY_REQUEST_TIMEOUT_SECS: u64 = 5;
53
54const LSPS2_GETINFO_REQUEST_EXPIRY: Duration = Duration::from_secs(60 * 60 * 24);
55const LSPS2_CHANNEL_CLTV_EXPIRY_DELTA: u32 = 72;
56
57struct LSPS1Client {
58	lsp_node_id: PublicKey,
59	lsp_address: SocketAddress,
60	token: Option<String>,
61	ldk_client_config: LdkLSPS1ClientConfig,
62	pending_opening_params_requests:
63		Mutex<HashMap<LSPSRequestId, oneshot::Sender<LSPS1OpeningParamsResponse>>>,
64	pending_create_order_requests: Mutex<HashMap<LSPSRequestId, oneshot::Sender<LSPS1OrderStatus>>>,
65	pending_check_order_status_requests:
66		Mutex<HashMap<LSPSRequestId, oneshot::Sender<LSPS1OrderStatus>>>,
67}
68
69#[derive(Debug, Clone)]
70pub(crate) struct LSPS1ClientConfig {
71	pub node_id: PublicKey,
72	pub address: SocketAddress,
73	pub token: Option<String>,
74}
75
76struct LSPS2Client {
77	lsp_node_id: PublicKey,
78	lsp_address: SocketAddress,
79	token: Option<String>,
80	ldk_client_config: LdkLSPS2ClientConfig,
81	pending_fee_requests: Mutex<HashMap<LSPSRequestId, oneshot::Sender<LSPS2FeeResponse>>>,
82	pending_buy_requests: Mutex<HashMap<LSPSRequestId, oneshot::Sender<LSPS2BuyResponse>>>,
83}
84
85#[derive(Debug, Clone)]
86pub(crate) struct LSPS2ClientConfig {
87	pub node_id: PublicKey,
88	pub address: SocketAddress,
89	pub token: Option<String>,
90}
91
92struct LSPS2Service {
93	service_config: LSPS2ServiceConfig,
94	ldk_service_config: LdkLSPS2ServiceConfig,
95}
96
97/// Represents the configuration of the LSPS2 service.
98///
99/// See [bLIP-52 / LSPS2] for more information.
100///
101/// [bLIP-52 / LSPS2]: https://github.com/lightning/blips/blob/master/blip-0052.md
102#[derive(Debug, Clone)]
103pub struct LSPS2ServiceConfig {
104	/// A token we may require to be sent by the clients.
105	///
106	/// If set, only requests matching this token will be accepted.
107	pub require_token: Option<String>,
108	/// Indicates whether the LSPS service will be announced via the gossip network.
109	pub advertise_service: bool,
110	/// The fee we withhold for the channel open from the initial payment.
111	///
112	/// This fee is proportional to the client-requested amount, in parts-per-million.
113	pub channel_opening_fee_ppm: u32,
114	/// The proportional overprovisioning for the channel.
115	///
116	/// This determines, in parts-per-million, how much value we'll provision on top of the amount
117	/// we need to forward the payment to the client.
118	///
119	/// For example, setting this to `100_000` will result in a channel being opened that is 10%
120	/// larger than then the to-be-forwarded amount (i.e., client-requested amount minus the
121	/// channel opening fee fee).
122	pub channel_over_provisioning_ppm: u32,
123	/// The minimum fee required for opening a channel.
124	pub min_channel_opening_fee_msat: u64,
125	/// The minimum number of blocks after confirmation we promise to keep the channel open.
126	pub min_channel_lifetime: u32,
127	/// The maximum number of blocks that the client is allowed to set its `to_self_delay` parameter.
128	pub max_client_to_self_delay: u32,
129	/// The minimum payment size that we will accept when opening a channel.
130	pub min_payment_size_msat: u64,
131	/// The maximum payment size that we will accept when opening a channel.
132	pub max_payment_size_msat: u64,
133	/// Use the 'client-trusts-LSP' trust model.
134	///
135	/// When set, the service will delay *broadcasting* the JIT channel's funding transaction until
136	/// the client claimed sufficient HTLC parts to pay for the channel open.
137	///
138	/// Note this will render the flow incompatible with clients utilizing the 'LSP-trust-client'
139	/// trust model, i.e., in turn delay *claiming* any HTLCs until they see the funding
140	/// transaction in the mempool.
141	///
142	/// Please refer to [`bLIP-52`] for more information.
143	///
144	/// [`bLIP-52`]: https://github.com/lightning/blips/blob/master/blip-0052.md#trust-models
145	pub client_trusts_lsp: bool,
146}
147
148pub(crate) struct LiquiditySourceBuilder<L: Deref>
149where
150	L::Target: LdkLogger,
151{
152	lsps1_client: Option<LSPS1Client>,
153	lsps2_client: Option<LSPS2Client>,
154	lsps2_service: Option<LSPS2Service>,
155	wallet: Arc<Wallet>,
156	channel_manager: Arc<ChannelManager>,
157	keys_manager: Arc<KeysManager>,
158	chain_source: Arc<ChainSource>,
159	tx_broadcaster: Arc<Broadcaster>,
160	kv_store: Arc<DynStore>,
161	config: Arc<Config>,
162	logger: L,
163}
164
165impl<L: Deref> LiquiditySourceBuilder<L>
166where
167	L::Target: LdkLogger,
168{
169	pub(crate) fn new(
170		wallet: Arc<Wallet>, channel_manager: Arc<ChannelManager>, keys_manager: Arc<KeysManager>,
171		chain_source: Arc<ChainSource>, tx_broadcaster: Arc<Broadcaster>, kv_store: Arc<DynStore>,
172		config: Arc<Config>, logger: L,
173	) -> Self {
174		let lsps1_client = None;
175		let lsps2_client = None;
176		let lsps2_service = None;
177		Self {
178			lsps1_client,
179			lsps2_client,
180			lsps2_service,
181			wallet,
182			channel_manager,
183			keys_manager,
184			chain_source,
185			tx_broadcaster,
186			kv_store,
187			config,
188			logger,
189		}
190	}
191
192	pub(crate) fn lsps1_client(
193		&mut self, lsp_node_id: PublicKey, lsp_address: SocketAddress, token: Option<String>,
194	) -> &mut Self {
195		// TODO: allow to set max_channel_fees_msat
196		let ldk_client_config = LdkLSPS1ClientConfig { max_channel_fees_msat: None };
197		let pending_opening_params_requests = Mutex::new(HashMap::new());
198		let pending_create_order_requests = Mutex::new(HashMap::new());
199		let pending_check_order_status_requests = Mutex::new(HashMap::new());
200		self.lsps1_client = Some(LSPS1Client {
201			lsp_node_id,
202			lsp_address,
203			token,
204			ldk_client_config,
205			pending_opening_params_requests,
206			pending_create_order_requests,
207			pending_check_order_status_requests,
208		});
209		self
210	}
211
212	pub(crate) fn lsps2_client(
213		&mut self, lsp_node_id: PublicKey, lsp_address: SocketAddress, token: Option<String>,
214	) -> &mut Self {
215		let ldk_client_config = LdkLSPS2ClientConfig {};
216		let pending_fee_requests = Mutex::new(HashMap::new());
217		let pending_buy_requests = Mutex::new(HashMap::new());
218		self.lsps2_client = Some(LSPS2Client {
219			lsp_node_id,
220			lsp_address,
221			token,
222			ldk_client_config,
223			pending_fee_requests,
224			pending_buy_requests,
225		});
226		self
227	}
228
229	pub(crate) fn lsps2_service(
230		&mut self, promise_secret: [u8; 32], service_config: LSPS2ServiceConfig,
231	) -> &mut Self {
232		let ldk_service_config = LdkLSPS2ServiceConfig { promise_secret };
233		self.lsps2_service = Some(LSPS2Service { service_config, ldk_service_config });
234		self
235	}
236
237	pub(crate) async fn build(self) -> Result<LiquiditySource<L>, BuildError> {
238		let liquidity_service_config = self.lsps2_service.as_ref().map(|s| {
239			let lsps2_service_config = Some(s.ldk_service_config.clone());
240			let lsps5_service_config = None;
241			let advertise_service = s.service_config.advertise_service;
242			LiquidityServiceConfig { lsps2_service_config, lsps5_service_config, advertise_service }
243		});
244
245		let lsps1_client_config = self.lsps1_client.as_ref().map(|s| s.ldk_client_config.clone());
246		let lsps2_client_config = self.lsps2_client.as_ref().map(|s| s.ldk_client_config.clone());
247		let lsps5_client_config = None;
248		let liquidity_client_config = Some(LiquidityClientConfig {
249			lsps1_client_config,
250			lsps2_client_config,
251			lsps5_client_config,
252		});
253
254		let liquidity_manager = Arc::new(
255			LiquidityManager::new(
256				Arc::clone(&self.keys_manager),
257				Arc::clone(&self.keys_manager),
258				Arc::clone(&self.channel_manager),
259				Some(Arc::clone(&self.chain_source)),
260				None,
261				Arc::clone(&self.kv_store),
262				Arc::clone(&self.tx_broadcaster),
263				liquidity_service_config,
264				liquidity_client_config,
265			)
266			.await
267			.map_err(|_| BuildError::ReadFailed)?,
268		);
269
270		Ok(LiquiditySource {
271			lsps1_client: self.lsps1_client,
272			lsps2_client: self.lsps2_client,
273			lsps2_service: self.lsps2_service,
274			wallet: self.wallet,
275			channel_manager: self.channel_manager,
276			peer_manager: RwLock::new(None),
277			keys_manager: self.keys_manager,
278			liquidity_manager,
279			config: self.config,
280			logger: self.logger,
281		})
282	}
283}
284
285pub(crate) struct LiquiditySource<L: Deref>
286where
287	L::Target: LdkLogger,
288{
289	lsps1_client: Option<LSPS1Client>,
290	lsps2_client: Option<LSPS2Client>,
291	lsps2_service: Option<LSPS2Service>,
292	wallet: Arc<Wallet>,
293	channel_manager: Arc<ChannelManager>,
294	peer_manager: RwLock<Option<Arc<PeerManager>>>,
295	keys_manager: Arc<KeysManager>,
296	liquidity_manager: Arc<LiquidityManager>,
297	config: Arc<Config>,
298	logger: L,
299}
300
301impl<L: Deref> LiquiditySource<L>
302where
303	L::Target: LdkLogger,
304{
305	pub(crate) fn set_peer_manager(&self, peer_manager: Arc<PeerManager>) {
306		*self.peer_manager.write().unwrap() = Some(peer_manager);
307	}
308
309	pub(crate) fn liquidity_manager(&self) -> Arc<LiquidityManager> {
310		Arc::clone(&self.liquidity_manager)
311	}
312
313	pub(crate) fn get_lsps1_lsp_details(&self) -> Option<(PublicKey, SocketAddress)> {
314		self.lsps1_client.as_ref().map(|s| (s.lsp_node_id, s.lsp_address.clone()))
315	}
316
317	pub(crate) fn get_lsps2_lsp_details(&self) -> Option<(PublicKey, SocketAddress)> {
318		self.lsps2_client.as_ref().map(|s| (s.lsp_node_id, s.lsp_address.clone()))
319	}
320
321	pub(crate) fn lsps2_channel_needs_manual_broadcast(
322		&self, counterparty_node_id: PublicKey, user_channel_id: u128,
323	) -> bool {
324		self.lsps2_service.as_ref().map_or(false, |lsps2_service| {
325			lsps2_service.service_config.client_trusts_lsp
326				&& self
327					.liquidity_manager()
328					.lsps2_service_handler()
329					.and_then(|handler| {
330						handler
331							.channel_needs_manual_broadcast(user_channel_id, &counterparty_node_id)
332							.ok()
333					})
334					.unwrap_or(false)
335		})
336	}
337
338	pub(crate) fn lsps2_store_funding_transaction(
339		&self, user_channel_id: u128, counterparty_node_id: PublicKey, funding_tx: Transaction,
340	) {
341		if self.lsps2_service.as_ref().map_or(false, |svc| !svc.service_config.client_trusts_lsp) {
342			// Only necessary for client-trusts-LSP flow
343			return;
344		}
345
346		let lsps2_service_handler = self.liquidity_manager.lsps2_service_handler();
347		if let Some(handler) = lsps2_service_handler {
348			handler
349				.store_funding_transaction(user_channel_id, &counterparty_node_id, funding_tx)
350				.unwrap_or_else(|e| {
351					debug_assert!(false, "Failed to store funding transaction: {:?}", e);
352					log_error!(self.logger, "Failed to store funding transaction: {:?}", e);
353				});
354		} else {
355			log_error!(self.logger, "LSPS2 service handler is not available.");
356		}
357	}
358
359	pub(crate) fn lsps2_funding_tx_broadcast_safe(
360		&self, user_channel_id: u128, counterparty_node_id: PublicKey,
361	) {
362		if self.lsps2_service.as_ref().map_or(false, |svc| !svc.service_config.client_trusts_lsp) {
363			// Only necessary for client-trusts-LSP flow
364			return;
365		}
366
367		let lsps2_service_handler = self.liquidity_manager.lsps2_service_handler();
368		if let Some(handler) = lsps2_service_handler {
369			handler
370				.set_funding_tx_broadcast_safe(user_channel_id, &counterparty_node_id)
371				.unwrap_or_else(|e| {
372					debug_assert!(
373						false,
374						"Failed to mark funding transaction safe to broadcast: {:?}",
375						e
376					);
377					log_error!(
378						self.logger,
379						"Failed to mark funding transaction safe to broadcast: {:?}",
380						e
381					);
382				});
383		} else {
384			log_error!(self.logger, "LSPS2 service handler is not available.");
385		}
386	}
387
388	pub(crate) async fn handle_next_event(&self) {
389		match self.liquidity_manager.next_event_async().await {
390			LiquidityEvent::LSPS1Client(LSPS1ClientEvent::SupportedOptionsReady {
391				request_id,
392				counterparty_node_id,
393				supported_options,
394			}) => {
395				if let Some(lsps1_client) = self.lsps1_client.as_ref() {
396					if counterparty_node_id != lsps1_client.lsp_node_id {
397						debug_assert!(
398							false,
399							"Received response from unexpected LSP counterparty. This should never happen."
400						);
401						log_error!(
402							self.logger,
403							"Received response from unexpected LSP counterparty. This should never happen."
404						);
405						return;
406					}
407
408					if let Some(sender) = lsps1_client
409						.pending_opening_params_requests
410						.lock()
411						.unwrap()
412						.remove(&request_id)
413					{
414						let response = LSPS1OpeningParamsResponse { supported_options };
415
416						match sender.send(response) {
417							Ok(()) => (),
418							Err(_) => {
419								log_error!(
420									self.logger,
421									"Failed to handle response for request {:?} from liquidity service",
422									request_id
423								);
424							},
425						}
426					} else {
427						debug_assert!(
428							false,
429							"Received response from liquidity service for unknown request."
430						);
431						log_error!(
432							self.logger,
433							"Received response from liquidity service for unknown request."
434						);
435					}
436				} else {
437					log_error!(
438						self.logger,
439						"Received unexpected LSPS1Client::SupportedOptionsReady event!"
440					);
441				}
442			},
443			LiquidityEvent::LSPS1Client(LSPS1ClientEvent::OrderCreated {
444				request_id,
445				counterparty_node_id,
446				order_id,
447				order,
448				payment,
449				channel,
450			}) => {
451				if let Some(lsps1_client) = self.lsps1_client.as_ref() {
452					if counterparty_node_id != lsps1_client.lsp_node_id {
453						debug_assert!(
454							false,
455							"Received response from unexpected LSP counterparty. This should never happen."
456						);
457						log_error!(
458							self.logger,
459							"Received response from unexpected LSP counterparty. This should never happen."
460						);
461						return;
462					}
463
464					if let Some(sender) = lsps1_client
465						.pending_create_order_requests
466						.lock()
467						.unwrap()
468						.remove(&request_id)
469					{
470						let response = LSPS1OrderStatus {
471							order_id,
472							order_params: order,
473							payment_options: payment.into(),
474							channel_state: channel,
475						};
476
477						match sender.send(response) {
478							Ok(()) => (),
479							Err(_) => {
480								log_error!(
481									self.logger,
482									"Failed to handle response for request {:?} from liquidity service",
483									request_id
484								);
485							},
486						}
487					} else {
488						debug_assert!(
489							false,
490							"Received response from liquidity service for unknown request."
491						);
492						log_error!(
493							self.logger,
494							"Received response from liquidity service for unknown request."
495						);
496					}
497				} else {
498					log_error!(self.logger, "Received unexpected LSPS1Client::OrderCreated event!");
499				}
500			},
501			LiquidityEvent::LSPS1Client(LSPS1ClientEvent::OrderStatus {
502				request_id,
503				counterparty_node_id,
504				order_id,
505				order,
506				payment,
507				channel,
508			}) => {
509				if let Some(lsps1_client) = self.lsps1_client.as_ref() {
510					if counterparty_node_id != lsps1_client.lsp_node_id {
511						debug_assert!(
512							false,
513							"Received response from unexpected LSP counterparty. This should never happen."
514						);
515						log_error!(
516							self.logger,
517							"Received response from unexpected LSP counterparty. This should never happen."
518						);
519						return;
520					}
521
522					if let Some(sender) = lsps1_client
523						.pending_check_order_status_requests
524						.lock()
525						.unwrap()
526						.remove(&request_id)
527					{
528						let response = LSPS1OrderStatus {
529							order_id,
530							order_params: order,
531							payment_options: payment.into(),
532							channel_state: channel,
533						};
534
535						match sender.send(response) {
536							Ok(()) => (),
537							Err(_) => {
538								log_error!(
539									self.logger,
540									"Failed to handle response for request {:?} from liquidity service",
541									request_id
542								);
543							},
544						}
545					} else {
546						debug_assert!(
547							false,
548							"Received response from liquidity service for unknown request."
549						);
550						log_error!(
551							self.logger,
552							"Received response from liquidity service for unknown request."
553						);
554					}
555				} else {
556					log_error!(self.logger, "Received unexpected LSPS1Client::OrderStatus event!");
557				}
558			},
559			LiquidityEvent::LSPS2Service(LSPS2ServiceEvent::GetInfo {
560				request_id,
561				counterparty_node_id,
562				token,
563			}) => {
564				if let Some(lsps2_service_handler) =
565					self.liquidity_manager.lsps2_service_handler().as_ref()
566				{
567					let service_config = if let Some(service_config) =
568						self.lsps2_service.as_ref().map(|s| s.service_config.clone())
569					{
570						service_config
571					} else {
572						log_error!(self.logger, "Failed to handle LSPS2ServiceEvent as LSPS2 liquidity service was not configured.",);
573						return;
574					};
575
576					if let Some(required) = service_config.require_token {
577						if token != Some(required) {
578							log_error!(
579								self.logger,
580								"Rejecting LSPS2 request {:?} from counterparty {} as the client provided an invalid token.",
581								request_id,
582								counterparty_node_id
583							);
584							lsps2_service_handler.invalid_token_provided(&counterparty_node_id, request_id.clone()).unwrap_or_else(|e| {
585								debug_assert!(false, "Failed to reject LSPS2 request. This should never happen.");
586								log_error!(
587									self.logger,
588									"Failed to reject LSPS2 request {:?} from counterparty {} due to: {:?}. This should never happen.",
589									request_id,
590									counterparty_node_id,
591									e
592								);
593							});
594							return;
595						}
596					}
597
598					let valid_until = LSPSDateTime(Utc::now() + LSPS2_GETINFO_REQUEST_EXPIRY);
599					let opening_fee_params = LSPS2RawOpeningFeeParams {
600						min_fee_msat: service_config.min_channel_opening_fee_msat,
601						proportional: service_config.channel_opening_fee_ppm,
602						valid_until,
603						min_lifetime: service_config.min_channel_lifetime,
604						max_client_to_self_delay: service_config.max_client_to_self_delay,
605						min_payment_size_msat: service_config.min_payment_size_msat,
606						max_payment_size_msat: service_config.max_payment_size_msat,
607					};
608
609					let opening_fee_params_menu = vec![opening_fee_params];
610
611					if let Err(e) = lsps2_service_handler.opening_fee_params_generated(
612						&counterparty_node_id,
613						request_id,
614						opening_fee_params_menu,
615					) {
616						log_error!(
617							self.logger,
618							"Failed to handle generated opening fee params: {:?}",
619							e
620						);
621					}
622				} else {
623					log_error!(self.logger, "Failed to handle LSPS2ServiceEvent as LSPS2 liquidity service was not configured.",);
624					return;
625				}
626			},
627			LiquidityEvent::LSPS2Service(LSPS2ServiceEvent::BuyRequest {
628				request_id,
629				counterparty_node_id,
630				opening_fee_params: _,
631				payment_size_msat,
632			}) => {
633				if let Some(lsps2_service_handler) =
634					self.liquidity_manager.lsps2_service_handler().as_ref()
635				{
636					let service_config = if let Some(service_config) =
637						self.lsps2_service.as_ref().map(|s| s.service_config.clone())
638					{
639						service_config
640					} else {
641						log_error!(self.logger, "Failed to handle LSPS2ServiceEvent as LSPS2 liquidity service was not configured.",);
642						return;
643					};
644
645					let user_channel_id: u128 = rand::rng().random();
646					let intercept_scid = self.channel_manager.get_intercept_scid();
647
648					if let Some(payment_size_msat) = payment_size_msat {
649						// We already check this in `lightning-liquidity`, but better safe than
650						// sorry.
651						//
652						// TODO: We might want to eventually send back an error here, but we
653						// currently can't and have to trust `lightning-liquidity` is doing the
654						// right thing.
655						//
656						// TODO: Eventually we also might want to make sure that we have sufficient
657						// liquidity for the channel opening here.
658						if payment_size_msat > service_config.max_payment_size_msat
659							|| payment_size_msat < service_config.min_payment_size_msat
660						{
661							log_error!(
662								self.logger,
663								"Rejecting to handle LSPS2 buy request {:?} from counterparty {} as the client requested an invalid payment size.",
664								request_id,
665								counterparty_node_id
666							);
667							return;
668						}
669					}
670
671					match lsps2_service_handler
672						.invoice_parameters_generated(
673							&counterparty_node_id,
674							request_id,
675							intercept_scid,
676							LSPS2_CHANNEL_CLTV_EXPIRY_DELTA,
677							service_config.client_trusts_lsp,
678							user_channel_id,
679						)
680						.await
681					{
682						Ok(()) => {},
683						Err(e) => {
684							log_error!(
685								self.logger,
686								"Failed to provide invoice parameters: {:?}",
687								e
688							);
689							return;
690						},
691					}
692				} else {
693					log_error!(self.logger, "Failed to handle LSPS2ServiceEvent as LSPS2 liquidity service was not configured.",);
694					return;
695				}
696			},
697			LiquidityEvent::LSPS2Service(LSPS2ServiceEvent::OpenChannel {
698				their_network_key,
699				amt_to_forward_msat,
700				opening_fee_msat: _,
701				user_channel_id,
702				intercept_scid: _,
703			}) => {
704				if self.liquidity_manager.lsps2_service_handler().is_none() {
705					log_error!(self.logger, "Failed to handle LSPS2ServiceEvent as LSPS2 liquidity service was not configured.",);
706					return;
707				};
708
709				let service_config = if let Some(service_config) =
710					self.lsps2_service.as_ref().map(|s| s.service_config.clone())
711				{
712					service_config
713				} else {
714					log_error!(self.logger, "Failed to handle LSPS2ServiceEvent as LSPS2 liquidity service was not configured.",);
715					return;
716				};
717
718				let init_features = if let Some(peer_manager) =
719					self.peer_manager.read().unwrap().as_ref()
720				{
721					// Fail if we're not connected to the prospective channel partner.
722					if let Some(peer) = peer_manager.peer_by_node_id(&their_network_key) {
723						peer.init_features
724					} else {
725						// TODO: We just silently fail here. Eventually we will need to remember
726						// the pending requests and regularly retry opening the channel until we
727						// succeed.
728						log_error!(
729							self.logger,
730							"Failed to open LSPS2 channel to {} due to peer not being not connected.",
731							their_network_key,
732						);
733						return;
734					}
735				} else {
736					debug_assert!(false, "Failed to handle LSPS2ServiceEvent as peer manager isn't available. This should never happen.",);
737					log_error!(self.logger, "Failed to handle LSPS2ServiceEvent as peer manager isn't available. This should never happen.",);
738					return;
739				};
740
741				// Fail if we have insufficient onchain funds available.
742				let over_provisioning_msat = (amt_to_forward_msat
743					* service_config.channel_over_provisioning_ppm as u64)
744					/ 1_000_000;
745				let channel_amount_sats = (amt_to_forward_msat + over_provisioning_msat) / 1000;
746				let cur_anchor_reserve_sats =
747					total_anchor_channels_reserve_sats(&self.channel_manager, &self.config);
748				let spendable_amount_sats =
749					self.wallet.get_spendable_amount_sats(cur_anchor_reserve_sats).unwrap_or(0);
750				let required_funds_sats = channel_amount_sats
751					+ self.config.anchor_channels_config.as_ref().map_or(0, |c| {
752						if init_features.requires_anchors_zero_fee_htlc_tx()
753							&& !c.trusted_peers_no_reserve.contains(&their_network_key)
754						{
755							c.per_channel_reserve_sats
756						} else {
757							0
758						}
759					});
760				if spendable_amount_sats < required_funds_sats {
761					log_error!(self.logger,
762						"Unable to create channel due to insufficient funds. Available: {}sats, Required: {}sats",
763						spendable_amount_sats, channel_amount_sats
764					);
765					// TODO: We just silently fail here. Eventually we will need to remember
766					// the pending requests and regularly retry opening the channel until we
767					// succeed.
768					return;
769				}
770
771				let mut config = self.channel_manager.get_current_config().clone();
772
773				// We set these LSP-specific values during Node building, here we're making sure it's actually set.
774				debug_assert_eq!(
775					config
776						.channel_handshake_config
777						.max_inbound_htlc_value_in_flight_percent_of_channel,
778					100
779				);
780				debug_assert!(config.accept_forwards_to_priv_channels);
781
782				// We set the forwarding fee to 0 for now as we're getting paid by the channel fee.
783				//
784				// TODO: revisit this decision eventually.
785				config.channel_config.forwarding_fee_base_msat = 0;
786				config.channel_config.forwarding_fee_proportional_millionths = 0;
787
788				match self.channel_manager.create_channel(
789					their_network_key,
790					channel_amount_sats,
791					0,
792					user_channel_id,
793					None,
794					Some(config),
795				) {
796					Ok(_) => {},
797					Err(e) => {
798						// TODO: We just silently fail here. Eventually we will need to remember
799						// the pending requests and regularly retry opening the channel until we
800						// succeed.
801						log_error!(
802							self.logger,
803							"Failed to open LSPS2 channel to {}: {:?}",
804							their_network_key,
805							e
806						);
807						return;
808					},
809				}
810			},
811			LiquidityEvent::LSPS2Client(LSPS2ClientEvent::OpeningParametersReady {
812				request_id,
813				counterparty_node_id,
814				opening_fee_params_menu,
815			}) => {
816				if let Some(lsps2_client) = self.lsps2_client.as_ref() {
817					if counterparty_node_id != lsps2_client.lsp_node_id {
818						debug_assert!(
819							false,
820							"Received response from unexpected LSP counterparty. This should never happen."
821						);
822						log_error!(
823							self.logger,
824							"Received response from unexpected LSP counterparty. This should never happen."
825						);
826						return;
827					}
828
829					if let Some(sender) =
830						lsps2_client.pending_fee_requests.lock().unwrap().remove(&request_id)
831					{
832						let response = LSPS2FeeResponse { opening_fee_params_menu };
833
834						match sender.send(response) {
835							Ok(()) => (),
836							Err(_) => {
837								log_error!(
838									self.logger,
839									"Failed to handle response for request {:?} from liquidity service",
840									request_id
841								);
842							},
843						}
844					} else {
845						debug_assert!(
846							false,
847							"Received response from liquidity service for unknown request."
848						);
849						log_error!(
850							self.logger,
851							"Received response from liquidity service for unknown request."
852						);
853					}
854				} else {
855					log_error!(
856						self.logger,
857						"Received unexpected LSPS2Client::OpeningParametersReady event!"
858					);
859				}
860			},
861			LiquidityEvent::LSPS2Client(LSPS2ClientEvent::InvoiceParametersReady {
862				request_id,
863				counterparty_node_id,
864				intercept_scid,
865				cltv_expiry_delta,
866				..
867			}) => {
868				if let Some(lsps2_client) = self.lsps2_client.as_ref() {
869					if counterparty_node_id != lsps2_client.lsp_node_id {
870						debug_assert!(
871							false,
872							"Received response from unexpected LSP counterparty. This should never happen."
873						);
874						log_error!(
875							self.logger,
876							"Received response from unexpected LSP counterparty. This should never happen."
877						);
878						return;
879					}
880
881					if let Some(sender) =
882						lsps2_client.pending_buy_requests.lock().unwrap().remove(&request_id)
883					{
884						let response = LSPS2BuyResponse { intercept_scid, cltv_expiry_delta };
885
886						match sender.send(response) {
887							Ok(()) => (),
888							Err(_) => {
889								log_error!(
890									self.logger,
891									"Failed to handle response for request {:?} from liquidity service",
892									request_id
893								);
894							},
895						}
896					} else {
897						debug_assert!(
898							false,
899							"Received response from liquidity service for unknown request."
900						);
901						log_error!(
902							self.logger,
903							"Received response from liquidity service for unknown request."
904						);
905					}
906				} else {
907					log_error!(
908						self.logger,
909						"Received unexpected LSPS2Client::InvoiceParametersReady event!"
910					);
911				}
912			},
913			e => {
914				log_error!(self.logger, "Received unexpected liquidity event: {:?}", e);
915			},
916		}
917	}
918
919	pub(crate) async fn lsps1_request_opening_params(
920		&self,
921	) -> Result<LSPS1OpeningParamsResponse, Error> {
922		let lsps1_client = self.lsps1_client.as_ref().ok_or(Error::LiquiditySourceUnavailable)?;
923
924		let client_handler = self.liquidity_manager.lsps1_client_handler().ok_or_else(|| {
925			log_error!(self.logger, "LSPS1 liquidity client was not configured.",);
926			Error::LiquiditySourceUnavailable
927		})?;
928
929		let (request_sender, request_receiver) = oneshot::channel();
930		{
931			let mut pending_opening_params_requests_lock =
932				lsps1_client.pending_opening_params_requests.lock().unwrap();
933			let request_id = client_handler.request_supported_options(lsps1_client.lsp_node_id);
934			pending_opening_params_requests_lock.insert(request_id, request_sender);
935		}
936
937		tokio::time::timeout(Duration::from_secs(LIQUIDITY_REQUEST_TIMEOUT_SECS), request_receiver)
938			.await
939			.map_err(|e| {
940				log_error!(self.logger, "Liquidity request timed out: {}", e);
941				Error::LiquidityRequestFailed
942			})?
943			.map_err(|e| {
944				log_error!(self.logger, "Failed to handle response from liquidity service: {}", e);
945				Error::LiquidityRequestFailed
946			})
947	}
948
949	pub(crate) async fn lsps1_request_channel(
950		&self, lsp_balance_sat: u64, client_balance_sat: u64, channel_expiry_blocks: u32,
951		announce_channel: bool, refund_address: bitcoin::Address,
952	) -> Result<LSPS1OrderStatus, Error> {
953		let lsps1_client = self.lsps1_client.as_ref().ok_or(Error::LiquiditySourceUnavailable)?;
954		let client_handler = self.liquidity_manager.lsps1_client_handler().ok_or_else(|| {
955			log_error!(self.logger, "LSPS1 liquidity client was not configured.",);
956			Error::LiquiditySourceUnavailable
957		})?;
958
959		let lsp_limits = self.lsps1_request_opening_params().await?.supported_options;
960		let channel_size_sat = lsp_balance_sat + client_balance_sat;
961
962		if channel_size_sat < lsp_limits.min_channel_balance_sat
963			|| channel_size_sat > lsp_limits.max_channel_balance_sat
964		{
965			log_error!(
966				self.logger,
967				"Requested channel size of {}sat doesn't meet the LSP-provided limits (min: {}sat, max: {}sat).",
968				channel_size_sat,
969				lsp_limits.min_channel_balance_sat,
970				lsp_limits.max_channel_balance_sat
971			);
972			return Err(Error::LiquidityRequestFailed);
973		}
974
975		if lsp_balance_sat < lsp_limits.min_initial_lsp_balance_sat
976			|| lsp_balance_sat > lsp_limits.max_initial_lsp_balance_sat
977		{
978			log_error!(
979				self.logger,
980				"Requested LSP-side balance of {}sat doesn't meet the LSP-provided limits (min: {}sat, max: {}sat).",
981				lsp_balance_sat,
982				lsp_limits.min_initial_lsp_balance_sat,
983				lsp_limits.max_initial_lsp_balance_sat
984			);
985			return Err(Error::LiquidityRequestFailed);
986		}
987
988		if client_balance_sat < lsp_limits.min_initial_client_balance_sat
989			|| client_balance_sat > lsp_limits.max_initial_client_balance_sat
990		{
991			log_error!(
992				self.logger,
993				"Requested client-side balance of {}sat doesn't meet the LSP-provided limits (min: {}sat, max: {}sat).",
994				client_balance_sat,
995				lsp_limits.min_initial_client_balance_sat,
996				lsp_limits.max_initial_client_balance_sat
997			);
998			return Err(Error::LiquidityRequestFailed);
999		}
1000
1001		let order_params = LSPS1OrderParams {
1002			lsp_balance_sat,
1003			client_balance_sat,
1004			required_channel_confirmations: lsp_limits.min_required_channel_confirmations,
1005			funding_confirms_within_blocks: lsp_limits.min_funding_confirms_within_blocks,
1006			channel_expiry_blocks,
1007			token: lsps1_client.token.clone(),
1008			announce_channel,
1009		};
1010
1011		let (request_sender, request_receiver) = oneshot::channel();
1012		let request_id;
1013		{
1014			let mut pending_create_order_requests_lock =
1015				lsps1_client.pending_create_order_requests.lock().unwrap();
1016			request_id = client_handler.create_order(
1017				&lsps1_client.lsp_node_id,
1018				order_params.clone(),
1019				Some(refund_address),
1020			);
1021			pending_create_order_requests_lock.insert(request_id.clone(), request_sender);
1022		}
1023
1024		let response = tokio::time::timeout(
1025			Duration::from_secs(LIQUIDITY_REQUEST_TIMEOUT_SECS),
1026			request_receiver,
1027		)
1028		.await
1029		.map_err(|e| {
1030			log_error!(self.logger, "Liquidity request with ID {:?} timed out: {}", request_id, e);
1031			Error::LiquidityRequestFailed
1032		})?
1033		.map_err(|e| {
1034			log_error!(self.logger, "Failed to handle response from liquidity service: {}", e);
1035			Error::LiquidityRequestFailed
1036		})?;
1037
1038		if response.order_params != order_params {
1039			log_error!(
1040				self.logger,
1041				"Aborting LSPS1 request as LSP-provided parameters don't match our order. Expected: {:?}, Received: {:?}", order_params, response.order_params
1042			);
1043			return Err(Error::LiquidityRequestFailed);
1044		}
1045
1046		Ok(response)
1047	}
1048
1049	pub(crate) async fn lsps1_check_order_status(
1050		&self, order_id: LSPS1OrderId,
1051	) -> Result<LSPS1OrderStatus, Error> {
1052		let lsps1_client = self.lsps1_client.as_ref().ok_or(Error::LiquiditySourceUnavailable)?;
1053		let client_handler = self.liquidity_manager.lsps1_client_handler().ok_or_else(|| {
1054			log_error!(self.logger, "LSPS1 liquidity client was not configured.",);
1055			Error::LiquiditySourceUnavailable
1056		})?;
1057
1058		let (request_sender, request_receiver) = oneshot::channel();
1059		{
1060			let mut pending_check_order_status_requests_lock =
1061				lsps1_client.pending_check_order_status_requests.lock().unwrap();
1062			let request_id = client_handler.check_order_status(&lsps1_client.lsp_node_id, order_id);
1063			pending_check_order_status_requests_lock.insert(request_id, request_sender);
1064		}
1065
1066		let response = tokio::time::timeout(
1067			Duration::from_secs(LIQUIDITY_REQUEST_TIMEOUT_SECS),
1068			request_receiver,
1069		)
1070		.await
1071		.map_err(|e| {
1072			log_error!(self.logger, "Liquidity request timed out: {}", e);
1073			Error::LiquidityRequestFailed
1074		})?
1075		.map_err(|e| {
1076			log_error!(self.logger, "Failed to handle response from liquidity service: {}", e);
1077			Error::LiquidityRequestFailed
1078		})?;
1079
1080		Ok(response)
1081	}
1082
1083	pub(crate) async fn lsps2_receive_to_jit_channel(
1084		&self, amount_msat: u64, description: &Bolt11InvoiceDescription, expiry_secs: u32,
1085		max_total_lsp_fee_limit_msat: Option<u64>, payment_hash: Option<PaymentHash>,
1086	) -> Result<(Bolt11Invoice, u64), Error> {
1087		let fee_response = self.lsps2_request_opening_fee_params().await?;
1088
1089		let (min_total_fee_msat, min_opening_params) = fee_response
1090			.opening_fee_params_menu
1091			.into_iter()
1092			.filter_map(|params| {
1093				if amount_msat < params.min_payment_size_msat
1094					|| amount_msat > params.max_payment_size_msat
1095				{
1096					log_debug!(self.logger,
1097						"Skipping LSP-offered JIT parameters as the payment of {}msat doesn't meet LSP limits (min: {}msat, max: {}msat)",
1098						amount_msat,
1099						params.min_payment_size_msat,
1100						params.max_payment_size_msat
1101					);
1102					None
1103				} else {
1104					compute_opening_fee(amount_msat, params.min_fee_msat, params.proportional as u64)
1105						.map(|fee| (fee, params))
1106				}
1107			})
1108			.min_by_key(|p| p.0)
1109			.ok_or_else(|| {
1110				log_error!(self.logger, "Failed to handle response from liquidity service",);
1111				Error::LiquidityRequestFailed
1112			})?;
1113
1114		if let Some(max_total_lsp_fee_limit_msat) = max_total_lsp_fee_limit_msat {
1115			if min_total_fee_msat > max_total_lsp_fee_limit_msat {
1116				log_error!(self.logger,
1117					"Failed to request inbound JIT channel as LSP's requested total opening fee of {}msat exceeds our fee limit of {}msat",
1118					min_total_fee_msat, max_total_lsp_fee_limit_msat
1119				);
1120				return Err(Error::LiquidityFeeTooHigh);
1121			}
1122		}
1123
1124		log_debug!(
1125			self.logger,
1126			"Choosing cheapest liquidity offer, will pay {}msat in total LSP fees",
1127			min_total_fee_msat
1128		);
1129
1130		let buy_response =
1131			self.lsps2_send_buy_request(Some(amount_msat), min_opening_params).await?;
1132		let invoice = self.lsps2_create_jit_invoice(
1133			buy_response,
1134			Some(amount_msat),
1135			description,
1136			expiry_secs,
1137			payment_hash,
1138		)?;
1139
1140		log_info!(self.logger, "JIT-channel invoice created: {}", invoice);
1141		Ok((invoice, min_total_fee_msat))
1142	}
1143
1144	pub(crate) async fn lsps2_receive_variable_amount_to_jit_channel(
1145		&self, description: &Bolt11InvoiceDescription, expiry_secs: u32,
1146		max_proportional_lsp_fee_limit_ppm_msat: Option<u64>, payment_hash: Option<PaymentHash>,
1147	) -> Result<(Bolt11Invoice, u64), Error> {
1148		let fee_response = self.lsps2_request_opening_fee_params().await?;
1149
1150		let (min_prop_fee_ppm_msat, min_opening_params) = fee_response
1151			.opening_fee_params_menu
1152			.into_iter()
1153			.map(|params| (params.proportional as u64, params))
1154			.min_by_key(|p| p.0)
1155			.ok_or_else(|| {
1156				log_error!(self.logger, "Failed to handle response from liquidity service",);
1157				Error::LiquidityRequestFailed
1158			})?;
1159
1160		if let Some(max_proportional_lsp_fee_limit_ppm_msat) =
1161			max_proportional_lsp_fee_limit_ppm_msat
1162		{
1163			if min_prop_fee_ppm_msat > max_proportional_lsp_fee_limit_ppm_msat {
1164				log_error!(self.logger,
1165					"Failed to request inbound JIT channel as LSP's requested proportional opening fee of {} ppm msat exceeds our fee limit of {} ppm msat",
1166					min_prop_fee_ppm_msat,
1167					max_proportional_lsp_fee_limit_ppm_msat
1168				);
1169				return Err(Error::LiquidityFeeTooHigh);
1170			}
1171		}
1172
1173		log_debug!(
1174			self.logger,
1175			"Choosing cheapest liquidity offer, will pay {}ppm msat in proportional LSP fees",
1176			min_prop_fee_ppm_msat
1177		);
1178
1179		let buy_response = self.lsps2_send_buy_request(None, min_opening_params).await?;
1180		let invoice = self.lsps2_create_jit_invoice(
1181			buy_response,
1182			None,
1183			description,
1184			expiry_secs,
1185			payment_hash,
1186		)?;
1187
1188		log_info!(self.logger, "JIT-channel invoice created: {}", invoice);
1189		Ok((invoice, min_prop_fee_ppm_msat))
1190	}
1191
1192	async fn lsps2_request_opening_fee_params(&self) -> Result<LSPS2FeeResponse, Error> {
1193		let lsps2_client = self.lsps2_client.as_ref().ok_or(Error::LiquiditySourceUnavailable)?;
1194
1195		let client_handler = self.liquidity_manager.lsps2_client_handler().ok_or_else(|| {
1196			log_error!(self.logger, "Liquidity client was not configured.",);
1197			Error::LiquiditySourceUnavailable
1198		})?;
1199
1200		let (fee_request_sender, fee_request_receiver) = oneshot::channel();
1201		{
1202			let mut pending_fee_requests_lock = lsps2_client.pending_fee_requests.lock().unwrap();
1203			let request_id = client_handler
1204				.request_opening_params(lsps2_client.lsp_node_id, lsps2_client.token.clone());
1205			pending_fee_requests_lock.insert(request_id, fee_request_sender);
1206		}
1207
1208		tokio::time::timeout(
1209			Duration::from_secs(LIQUIDITY_REQUEST_TIMEOUT_SECS),
1210			fee_request_receiver,
1211		)
1212		.await
1213		.map_err(|e| {
1214			log_error!(self.logger, "Liquidity request timed out: {}", e);
1215			Error::LiquidityRequestFailed
1216		})?
1217		.map_err(|e| {
1218			log_error!(self.logger, "Failed to handle response from liquidity service: {}", e);
1219			Error::LiquidityRequestFailed
1220		})
1221	}
1222
1223	async fn lsps2_send_buy_request(
1224		&self, amount_msat: Option<u64>, opening_fee_params: LSPS2OpeningFeeParams,
1225	) -> Result<LSPS2BuyResponse, Error> {
1226		let lsps2_client = self.lsps2_client.as_ref().ok_or(Error::LiquiditySourceUnavailable)?;
1227
1228		let client_handler = self.liquidity_manager.lsps2_client_handler().ok_or_else(|| {
1229			log_error!(self.logger, "Liquidity client was not configured.",);
1230			Error::LiquiditySourceUnavailable
1231		})?;
1232
1233		let (buy_request_sender, buy_request_receiver) = oneshot::channel();
1234		{
1235			let mut pending_buy_requests_lock = lsps2_client.pending_buy_requests.lock().unwrap();
1236			let request_id = client_handler
1237				.select_opening_params(lsps2_client.lsp_node_id, amount_msat, opening_fee_params)
1238				.map_err(|e| {
1239					log_error!(
1240						self.logger,
1241						"Failed to send buy request to liquidity service: {:?}",
1242						e
1243					);
1244					Error::LiquidityRequestFailed
1245				})?;
1246			pending_buy_requests_lock.insert(request_id, buy_request_sender);
1247		}
1248
1249		let buy_response = tokio::time::timeout(
1250			Duration::from_secs(LIQUIDITY_REQUEST_TIMEOUT_SECS),
1251			buy_request_receiver,
1252		)
1253		.await
1254		.map_err(|e| {
1255			log_error!(self.logger, "Liquidity request timed out: {}", e);
1256			Error::LiquidityRequestFailed
1257		})?
1258		.map_err(|e| {
1259			log_error!(self.logger, "Failed to handle response from liquidity service: {:?}", e);
1260			Error::LiquidityRequestFailed
1261		})?;
1262
1263		Ok(buy_response)
1264	}
1265
1266	fn lsps2_create_jit_invoice(
1267		&self, buy_response: LSPS2BuyResponse, amount_msat: Option<u64>,
1268		description: &Bolt11InvoiceDescription, expiry_secs: u32,
1269		payment_hash: Option<PaymentHash>,
1270	) -> Result<Bolt11Invoice, Error> {
1271		let lsps2_client = self.lsps2_client.as_ref().ok_or(Error::LiquiditySourceUnavailable)?;
1272
1273		// LSPS2 requires min_final_cltv_expiry_delta to be at least 2 more than usual.
1274		let min_final_cltv_expiry_delta = MIN_FINAL_CLTV_EXPIRY_DELTA + 2;
1275		let (payment_hash, payment_secret) = match payment_hash {
1276			Some(payment_hash) => {
1277				let payment_secret = self
1278					.channel_manager
1279					.create_inbound_payment_for_hash(
1280						payment_hash,
1281						None,
1282						expiry_secs,
1283						Some(min_final_cltv_expiry_delta),
1284					)
1285					.map_err(|e| {
1286						log_error!(self.logger, "Failed to register inbound payment: {:?}", e);
1287						Error::InvoiceCreationFailed
1288					})?;
1289				(payment_hash, payment_secret)
1290			},
1291			None => self
1292				.channel_manager
1293				.create_inbound_payment(None, expiry_secs, Some(min_final_cltv_expiry_delta))
1294				.map_err(|e| {
1295					log_error!(self.logger, "Failed to register inbound payment: {:?}", e);
1296					Error::InvoiceCreationFailed
1297				})?,
1298		};
1299
1300		let route_hint = RouteHint(vec![RouteHintHop {
1301			src_node_id: lsps2_client.lsp_node_id,
1302			short_channel_id: buy_response.intercept_scid,
1303			fees: RoutingFees { base_msat: 0, proportional_millionths: 0 },
1304			cltv_expiry_delta: buy_response.cltv_expiry_delta as u16,
1305			htlc_minimum_msat: None,
1306			htlc_maximum_msat: None,
1307		}]);
1308
1309		let payment_hash = sha256::Hash::from_slice(&payment_hash.0).map_err(|e| {
1310			log_error!(self.logger, "Invalid payment hash: {:?}", e);
1311			Error::InvoiceCreationFailed
1312		})?;
1313
1314		let currency = self.config.network.into();
1315		let mut invoice_builder = InvoiceBuilder::new(currency)
1316			.invoice_description(description.clone())
1317			.payment_hash(payment_hash)
1318			.payment_secret(payment_secret)
1319			.current_timestamp()
1320			.min_final_cltv_expiry_delta(min_final_cltv_expiry_delta.into())
1321			.expiry_time(Duration::from_secs(expiry_secs.into()))
1322			.private_route(route_hint);
1323
1324		if let Some(amount_msat) = amount_msat {
1325			invoice_builder = invoice_builder.amount_milli_satoshis(amount_msat).basic_mpp();
1326		}
1327
1328		invoice_builder
1329			.build_signed(|hash| {
1330				Secp256k1::new()
1331					.sign_ecdsa_recoverable(hash, &self.keys_manager.get_node_secret_key())
1332			})
1333			.map_err(|e| {
1334				log_error!(self.logger, "Failed to build and sign invoice: {}", e);
1335				Error::InvoiceCreationFailed
1336			})
1337	}
1338
1339	pub(crate) async fn handle_channel_ready(
1340		&self, user_channel_id: u128, channel_id: &ChannelId, counterparty_node_id: &PublicKey,
1341	) {
1342		if let Some(lsps2_service_handler) = self.liquidity_manager.lsps2_service_handler() {
1343			if let Err(e) = lsps2_service_handler
1344				.channel_ready(user_channel_id, channel_id, counterparty_node_id)
1345				.await
1346			{
1347				log_error!(
1348					self.logger,
1349					"LSPS2 service failed to handle ChannelReady event: {:?}",
1350					e
1351				);
1352			}
1353		}
1354	}
1355
1356	pub(crate) async fn handle_htlc_intercepted(
1357		&self, intercept_scid: u64, intercept_id: InterceptId, expected_outbound_amount_msat: u64,
1358		payment_hash: PaymentHash,
1359	) {
1360		if let Some(lsps2_service_handler) = self.liquidity_manager.lsps2_service_handler() {
1361			if let Err(e) = lsps2_service_handler
1362				.htlc_intercepted(
1363					intercept_scid,
1364					intercept_id,
1365					expected_outbound_amount_msat,
1366					payment_hash,
1367				)
1368				.await
1369			{
1370				log_error!(
1371					self.logger,
1372					"LSPS2 service failed to handle HTLCIntercepted event: {:?}",
1373					e
1374				);
1375			}
1376		}
1377	}
1378
1379	pub(crate) async fn handle_htlc_handling_failed(&self, failure_type: HTLCHandlingFailureType) {
1380		if let Some(lsps2_service_handler) = self.liquidity_manager.lsps2_service_handler() {
1381			if let Err(e) = lsps2_service_handler.htlc_handling_failed(failure_type).await {
1382				log_error!(
1383					self.logger,
1384					"LSPS2 service failed to handle HTLCHandlingFailed event: {:?}",
1385					e
1386				);
1387			}
1388		}
1389	}
1390
1391	pub(crate) async fn handle_payment_forwarded(
1392		&self, next_channel_id: Option<ChannelId>, skimmed_fee_msat: u64,
1393	) {
1394		if let Some(next_channel_id) = next_channel_id {
1395			if let Some(lsps2_service_handler) = self.liquidity_manager.lsps2_service_handler() {
1396				if let Err(e) =
1397					lsps2_service_handler.payment_forwarded(next_channel_id, skimmed_fee_msat).await
1398				{
1399					log_error!(
1400						self.logger,
1401						"LSPS2 service failed to handle PaymentForwarded: {:?}",
1402						e
1403					);
1404				}
1405			}
1406		}
1407	}
1408}
1409
1410#[derive(Debug, Clone)]
1411pub(crate) struct LSPS1OpeningParamsResponse {
1412	supported_options: LSPS1Options,
1413}
1414
1415/// Represents the status of an LSPS1 channel request.
1416#[derive(Debug, Clone)]
1417pub struct LSPS1OrderStatus {
1418	/// The id of the channel order.
1419	pub order_id: LSPS1OrderId,
1420	/// The parameters of channel order.
1421	pub order_params: LSPS1OrderParams,
1422	/// Contains details about how to pay for the order.
1423	pub payment_options: LSPS1PaymentInfo,
1424	/// Contains information about the channel state.
1425	pub channel_state: Option<LSPS1ChannelInfo>,
1426}
1427
1428#[cfg(not(feature = "uniffi"))]
1429type LSPS1PaymentInfo = lightning_liquidity::lsps1::msgs::LSPS1PaymentInfo;
1430
1431#[cfg(feature = "uniffi")]
1432type LSPS1PaymentInfo = crate::ffi::LSPS1PaymentInfo;
1433
1434#[derive(Debug, Clone)]
1435pub(crate) struct LSPS2FeeResponse {
1436	opening_fee_params_menu: Vec<LSPS2OpeningFeeParams>,
1437}
1438
1439#[derive(Debug, Clone)]
1440pub(crate) struct LSPS2BuyResponse {
1441	intercept_scid: u64,
1442	cltv_expiry_delta: u32,
1443}
1444
1445/// A liquidity handler allowing to request channels via the [bLIP-51 / LSPS1] protocol.
1446///
1447/// Should be retrieved by calling [`Node::lsps1_liquidity`].
1448///
1449/// To open [bLIP-52 / LSPS2] JIT channels, please refer to
1450/// [`Bolt11Payment::receive_via_jit_channel`].
1451///
1452/// [bLIP-51 / LSPS1]: https://github.com/lightning/blips/blob/master/blip-0051.md
1453/// [bLIP-52 / LSPS2]: https://github.com/lightning/blips/blob/master/blip-0052.md
1454/// [`Node::lsps1_liquidity`]: crate::Node::lsps1_liquidity
1455/// [`Bolt11Payment::receive_via_jit_channel`]: crate::payment::Bolt11Payment::receive_via_jit_channel
1456#[derive(Clone)]
1457pub struct LSPS1Liquidity {
1458	runtime: Arc<Runtime>,
1459	wallet: Arc<Wallet>,
1460	connection_manager: Arc<ConnectionManager<Arc<Logger>>>,
1461	liquidity_source: Option<Arc<LiquiditySource<Arc<Logger>>>>,
1462	logger: Arc<Logger>,
1463}
1464
1465impl LSPS1Liquidity {
1466	pub(crate) fn new(
1467		runtime: Arc<Runtime>, wallet: Arc<Wallet>,
1468		connection_manager: Arc<ConnectionManager<Arc<Logger>>>,
1469		liquidity_source: Option<Arc<LiquiditySource<Arc<Logger>>>>, logger: Arc<Logger>,
1470	) -> Self {
1471		Self { runtime, wallet, connection_manager, liquidity_source, logger }
1472	}
1473
1474	/// Connects to the configured LSP and places an order for an inbound channel.
1475	///
1476	/// The channel will be opened after one of the returned payment options has successfully been
1477	/// paid.
1478	pub fn request_channel(
1479		&self, lsp_balance_sat: u64, client_balance_sat: u64, channel_expiry_blocks: u32,
1480		announce_channel: bool,
1481	) -> Result<LSPS1OrderStatus, Error> {
1482		let liquidity_source =
1483			self.liquidity_source.as_ref().ok_or(Error::LiquiditySourceUnavailable)?;
1484
1485		let (lsp_node_id, lsp_address) =
1486			liquidity_source.get_lsps1_lsp_details().ok_or(Error::LiquiditySourceUnavailable)?;
1487
1488		let con_node_id = lsp_node_id;
1489		let con_addr = lsp_address.clone();
1490		let con_cm = Arc::clone(&self.connection_manager);
1491
1492		// We need to use our main runtime here as a local runtime might not be around to poll
1493		// connection futures going forward.
1494		self.runtime.block_on(async move {
1495			con_cm.connect_peer_if_necessary(con_node_id, con_addr).await
1496		})?;
1497
1498		log_info!(self.logger, "Connected to LSP {}@{}. ", lsp_node_id, lsp_address);
1499
1500		let refund_address = self.wallet.get_new_address()?;
1501
1502		let liquidity_source = Arc::clone(&liquidity_source);
1503		let response = self.runtime.block_on(async move {
1504			liquidity_source
1505				.lsps1_request_channel(
1506					lsp_balance_sat,
1507					client_balance_sat,
1508					channel_expiry_blocks,
1509					announce_channel,
1510					refund_address,
1511				)
1512				.await
1513		})?;
1514
1515		Ok(response)
1516	}
1517
1518	/// Connects to the configured LSP and checks for the status of a previously-placed order.
1519	pub fn check_order_status(&self, order_id: LSPS1OrderId) -> Result<LSPS1OrderStatus, Error> {
1520		let liquidity_source =
1521			self.liquidity_source.as_ref().ok_or(Error::LiquiditySourceUnavailable)?;
1522
1523		let (lsp_node_id, lsp_address) =
1524			liquidity_source.get_lsps1_lsp_details().ok_or(Error::LiquiditySourceUnavailable)?;
1525
1526		let con_node_id = lsp_node_id;
1527		let con_addr = lsp_address.clone();
1528		let con_cm = Arc::clone(&self.connection_manager);
1529
1530		// We need to use our main runtime here as a local runtime might not be around to poll
1531		// connection futures going forward.
1532		self.runtime.block_on(async move {
1533			con_cm.connect_peer_if_necessary(con_node_id, con_addr).await
1534		})?;
1535
1536		let liquidity_source = Arc::clone(&liquidity_source);
1537		let response = self
1538			.runtime
1539			.block_on(async move { liquidity_source.lsps1_check_order_status(order_id).await })?;
1540		Ok(response)
1541	}
1542}