Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions bindings/ldk_node.udl
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ interface Builder {
void set_pathfinding_scores_source(string url);
void set_liquidity_source_lsps1(PublicKey node_id, SocketAddress address, string? token);
void set_liquidity_source_lsps2(PublicKey node_id, SocketAddress address, string? token);
void add_lsp(PublicKey node_id, SocketAddress address, string? token);
void set_storage_dir_path(string storage_dir_path);
void set_filesystem_logger(string? log_file_path, LogLevel? max_log_level);
void set_log_facade_logger();
Expand Down Expand Up @@ -299,6 +300,8 @@ interface LSPS1Liquidity {
[Throws=NodeError]
LSPS1OrderStatus request_channel(u64 lsp_balance_sat, u64 client_balance_sat, u32 channel_expiry_blocks, boolean announce_channel);
[Throws=NodeError]
LSPS1OrderStatus request_channel_from_lsp(u64 lsp_balance_sat, u64 client_balance_sat, u32 channel_expiry_blocks, boolean announce_channel, PublicKey node_id);
[Throws=NodeError]
LSPS1OrderStatus check_order_status(LSPS1OrderId order_id);
};

Expand Down
76 changes: 41 additions & 35 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,7 @@ use crate::io::{
PENDING_PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE,
PENDING_PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE,
};
use crate::liquidity::{
LSPS1ClientConfig, LSPS2ClientConfig, LSPS2ServiceConfig, LiquiditySourceBuilder,
};
use crate::liquidity::{LSPS2ServiceConfig, LiquiditySourceBuilder, LspConfig};
use crate::logger::{log_error, LdkLogger, LogLevel, LogWriter, Logger};
use crate::message_handler::NodeCustomMessageHandler;
use crate::payment::asynchronous::om_mailbox::OnionMessageMailbox;
Expand Down Expand Up @@ -119,10 +117,8 @@ struct PathfindingScoresSyncConfig {

#[derive(Debug, Clone, Default)]
struct LiquiditySourceConfig {
// Act as an LSPS1 client connecting to the given service.
lsps1_client: Option<LSPS1ClientConfig>,
// Act as an LSPS2 client connecting to the given service.
lsps2_client: Option<LSPS2ClientConfig>,
// Acts for both LSPS1 and LSPS2 clients connecting to the given service.
lsp_nodes: Vec<LspConfig>,
// Act as an LSPS2 service.
lsps2_service: Option<LSPS2ServiceConfig>,
}
Expand Down Expand Up @@ -401,17 +397,12 @@ impl NodeBuilder {
/// The given `token` will be used by the LSP to authenticate the user.
///
/// [bLIP-51 / LSPS1]: https://github.com/lightning/blips/blob/master/blip-0051.md
#[deprecated(note = "Use `add_lsp` instead")]
#[allow(dead_code)]
pub fn set_liquidity_source_lsps1(
&mut self, node_id: PublicKey, address: SocketAddress, token: Option<String>,
) -> &mut Self {
// Mark the LSP as trusted for 0conf
self.config.trusted_peers_0conf.push(node_id.clone());

let liquidity_source_config =
self.liquidity_source_config.get_or_insert(LiquiditySourceConfig::default());
let lsps1_client_config = LSPS1ClientConfig { node_id, address, token };
liquidity_source_config.lsps1_client = Some(lsps1_client_config);
self
self.add_lsp(node_id, address, token)
}

/// Configures the [`Node`] instance to source just-in-time inbound liquidity from the given
Expand All @@ -422,16 +413,32 @@ impl NodeBuilder {
/// The given `token` will be used by the LSP to authenticate the user.
///
/// [bLIP-52 / LSPS2]: https://github.com/lightning/blips/blob/master/blip-0052.md
#[deprecated(note = "Use `add_lsp` instead")]
#[allow(dead_code)]
pub fn set_liquidity_source_lsps2(
&mut self, node_id: PublicKey, address: SocketAddress, token: Option<String>,
) -> &mut Self {
self.add_lsp(node_id, address, token)
}

/// Configures the [`Node`] instance to source inbound liquidity from the given LSP, without specifying
/// the exact protocol used (e.g., LSPS1 or LSPS2).
///
/// Will mark the LSP as trusted for 0-confirmation channels, see [`Config::trusted_peers_0conf`].
///
/// The given `token` will be used by the LSP to authenticate the user.
/// This method is useful when the user wants to connect to an LSP but does not want to be concerned with
/// the specific protocol used for liquidity provision. The node will automatically detect and use the
/// appropriate protocol supported by the LSP.
pub fn add_lsp(
&mut self, node_id: PublicKey, address: SocketAddress, token: Option<String>,
) -> &mut Self {
// Mark the LSP as trusted for 0conf
self.config.trusted_peers_0conf.push(node_id.clone());
self.config.trusted_peers_0conf.push(node_id);

let liquidity_source_config =
self.liquidity_source_config.get_or_insert(LiquiditySourceConfig::default());
let lsps2_client_config = LSPS2ClientConfig { node_id, address, token };
liquidity_source_config.lsps2_client = Some(lsps2_client_config);
liquidity_source_config.lsp_nodes.push(LspConfig { node_id, address, token });
self
}

Expand Down Expand Up @@ -824,7 +831,7 @@ impl ArcedNodeBuilder {
pub fn set_liquidity_source_lsps1(
&self, node_id: PublicKey, address: SocketAddress, token: Option<String>,
) {
self.inner.write().unwrap().set_liquidity_source_lsps1(node_id, address, token);
self.inner.write().unwrap().add_lsp(node_id, address, token);
}

/// Configures the [`Node`] instance to source just-in-time inbound liquidity from the given
Expand All @@ -838,7 +845,20 @@ impl ArcedNodeBuilder {
pub fn set_liquidity_source_lsps2(
&self, node_id: PublicKey, address: SocketAddress, token: Option<String>,
) {
self.inner.write().unwrap().set_liquidity_source_lsps2(node_id, address, token);
self.inner.write().unwrap().add_lsp(node_id, address, token);
}

/// Configures the [`Node`] instance to source inbound liquidity from the given LSP, without specifying
/// the exact protocol used (e.g., LSPS1 or LSPS2).
///
/// Will mark the LSP as trusted for 0-confirmation channels, see [`Config::trusted_peers_0conf`].
///
/// The given `token` will be used by the LSP to authenticate the user.
/// This method is useful when the user wants to connect to an LSP but does not want to be concerned with
/// the specific protocol used for liquidity provision. The node will automatically detect and use the
/// appropriate protocol supported by the LSP.
pub fn add_lsp(&self, node_id: PublicKey, address: SocketAddress, token: Option<String>) {
self.inner.write().unwrap().add_lsp(node_id, address, token);
}

/// Configures the [`Node`] instance to provide an [LSPS2] service, issuing just-in-time
Expand Down Expand Up @@ -1598,21 +1618,7 @@ fn build_with_store_internal(
Arc::clone(&logger),
);

lsc.lsps1_client.as_ref().map(|config| {
liquidity_source_builder.lsps1_client(
config.node_id,
config.address.clone(),
config.token.clone(),
)
});

lsc.lsps2_client.as_ref().map(|config| {
liquidity_source_builder.lsps2_client(
config.node_id,
config.address.clone(),
config.token.clone(),
)
});
liquidity_source_builder.set_lsp_nodes(lsc.lsp_nodes.clone());

let promise_secret = {
let lsps_xpriv = derive_xprv(
Expand Down
8 changes: 2 additions & 6 deletions src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1221,12 +1221,8 @@ where
let user_channel_id: u128 = rng().random();
let allow_0conf = self.config.trusted_peers_0conf.contains(&counterparty_node_id);
let mut channel_override_config = None;
if let Some((lsp_node_id, _)) = self
.liquidity_source
.as_ref()
.and_then(|ls| ls.as_ref().get_lsps2_lsp_details())
{
if lsp_node_id == counterparty_node_id {
if let Some(ls) = self.liquidity_source.as_ref() {
if ls.as_ref().is_lsps_node(&counterparty_node_id) {
// When we're an LSPS2 client, allow claiming underpaying HTLCs as the LSP will skim off some fee. We'll
// check that they don't take too much before claiming.
//
Expand Down
23 changes: 23 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,29 @@ impl Node {
});
}

if let Some(liquidity_source) = self.liquidity_source.as_ref() {
let discovery_ls = Arc::clone(&liquidity_source);
let discovery_cm = Arc::clone(&self.connection_manager);
let discovery_logger = Arc::clone(&self.logger);
self.runtime.spawn_background_task(async move {
for (node_id, address) in discovery_ls.get_all_lsp_details() {
if let Err(e) =
discovery_cm.connect_peer_if_necessary(node_id, address.clone()).await
{
log_error!(
discovery_logger,
"Failed to connect to LSP {} for protocol discovery: {}",
node_id,
e
);
continue;
}
}

discovery_ls.discover_all_lsp_protocols().await;
});
}

log_info!(self.logger, "Startup complete.");
*is_running_lock = true;
Ok(())
Expand Down
Loading
Loading