Skip to content

Commit 609547b

Browse files
committed
Add LSPS2 client config to ldk-server
Expose LSPS2 client settings in `ldk-server-config.toml` so nodes can be configured to source just-in-time liquidity from an LSP. This also keeps the workspace green by fixing the existing `clippy` warning in `ldk-server-cli`. Generated with the assistance of AI. Co-Authored-By: HAL 9000
1 parent 733ffeb commit 609547b

3 files changed

Lines changed: 103 additions & 0 deletions

File tree

ldk-server/ldk-server-config.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,15 @@ server_url = "https://mempool.space/api" # Esplora endpoint
4343
connection_string = "" # RabbitMQ connection string
4444
exchange_name = ""
4545

46+
# LSPS2 Client Support
47+
[liquidity.lsps2_client]
48+
# The public key of the LSPS2 LSP we source just-in-time liquidity from.
49+
node_pubkey = "<lsp node pubkey>"
50+
# Address to connect to the LSPS2 LSP (IPv4:port, IPv6:port, OnionV3:port, or hostname:port).
51+
address = "<lsp ip address>:9735"
52+
# Optional token for authenticating to the LSP.
53+
# token = ""
54+
4655
# Experimental LSPS2 Service Support
4756
# CAUTION: LSPS2 support is highly experimental and for testing purposes only.
4857
[liquidity.lsps2_service]

ldk-server/src/main.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,14 @@ fn main() {
172172
builder.set_gossip_source_rgs(rgs_server_url);
173173
}
174174

175+
if let Some(lsps2_client_config) = config_file.lsps2_client_config {
176+
builder.set_liquidity_source_lsps2(
177+
lsps2_client_config.node_id,
178+
lsps2_client_config.address,
179+
lsps2_client_config.token,
180+
);
181+
}
182+
175183
// LSPS2 support is highly experimental and for testing purposes only.
176184
#[cfg(feature = "experimental-lsps2-support")]
177185
builder.set_liquidity_provider_lsps2(

ldk-server/src/util/config.rs

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use std::str::FromStr;
1313
use std::{fs, io};
1414

1515
use clap::Parser;
16+
use ldk_node::bitcoin::secp256k1::PublicKey;
1617
use ldk_node::bitcoin::Network;
1718
use ldk_node::lightning::ln::msgs::SocketAddress;
1819
use ldk_node::lightning::routing::gossip::NodeAlias;
@@ -47,14 +48,25 @@ pub struct Config {
4748
pub storage_dir_path: Option<String>,
4849
pub chain_source: ChainSource,
4950
pub rgs_server_url: Option<String>,
51+
#[cfg_attr(not(feature = "events-rabbitmq"), allow(dead_code))]
5052
pub rabbitmq_connection_string: String,
53+
#[cfg_attr(not(feature = "events-rabbitmq"), allow(dead_code))]
5154
pub rabbitmq_exchange_name: String,
55+
pub lsps2_client_config: Option<LSPSClientConfig>,
56+
#[cfg_attr(not(feature = "experimental-lsps2-support"), allow(dead_code))]
5257
pub lsps2_service_config: Option<LSPS2ServiceConfig>,
5358
pub log_level: LevelFilter,
5459
pub log_file_path: Option<String>,
5560
pub pathfinding_scores_source_url: Option<String>,
5661
}
5762

63+
#[derive(Debug, Clone, PartialEq, Eq)]
64+
pub struct LSPSClientConfig {
65+
pub node_id: PublicKey,
66+
pub address: SocketAddress,
67+
pub token: Option<String>,
68+
}
69+
5870
#[derive(Debug, Clone, PartialEq, Eq)]
5971
pub struct TlsConfig {
6072
pub cert_path: Option<String>,
@@ -325,6 +337,13 @@ impl ConfigBuilder {
325337
#[cfg(not(feature = "events-rabbitmq"))]
326338
let (rabbitmq_connection_string, rabbitmq_exchange_name) = (String::new(), String::new());
327339

340+
let lsps2_client_config = self
341+
.lsps2
342+
.as_ref()
343+
.and_then(|liquidity| liquidity.lsps2_client.as_ref())
344+
.map(LSPSClientConfig::try_from)
345+
.transpose()?;
346+
328347
#[cfg(feature = "experimental-lsps2-support")]
329348
let lsps2_service_config = {
330349
let liquidity = self.lsps2.ok_or_else(|| io::Error::new(
@@ -355,6 +374,7 @@ impl ConfigBuilder {
355374
rgs_server_url: self.rgs_server_url,
356375
rabbitmq_connection_string,
357376
rabbitmq_exchange_name,
377+
lsps2_client_config,
358378
lsps2_service_config,
359379
log_level,
360380
log_file_path: self.log_file_path,
@@ -436,9 +456,17 @@ struct TomlTlsConfig {
436456

437457
#[derive(Deserialize, Serialize)]
438458
struct LiquidityConfig {
459+
lsps2_client: Option<LSPSClientTomlConfig>,
439460
lsps2_service: Option<LSPS2ServiceTomlConfig>,
440461
}
441462

463+
#[derive(Deserialize, Serialize, Debug)]
464+
struct LSPSClientTomlConfig {
465+
node_pubkey: String,
466+
address: String,
467+
token: Option<String>,
468+
}
469+
442470
#[derive(Deserialize, Serialize, Debug)]
443471
struct LSPS2ServiceTomlConfig {
444472
advertise_service: bool,
@@ -483,6 +511,27 @@ impl From<LSPS2ServiceTomlConfig> for LSPS2ServiceConfig {
483511
}
484512
}
485513

514+
impl TryFrom<&LSPSClientTomlConfig> for LSPSClientConfig {
515+
type Error = io::Error;
516+
517+
fn try_from(value: &LSPSClientTomlConfig) -> Result<Self, Self::Error> {
518+
let node_id = PublicKey::from_str(&value.node_pubkey).map_err(|e| {
519+
io::Error::new(
520+
io::ErrorKind::InvalidInput,
521+
format!("Invalid liquidity client node pubkey configured: {e}"),
522+
)
523+
})?;
524+
let address = SocketAddress::from_str(&value.address).map_err(|e| {
525+
io::Error::new(
526+
io::ErrorKind::InvalidInput,
527+
format!("Invalid liquidity client address configured: {e}"),
528+
)
529+
})?;
530+
531+
Ok(Self { node_id, address, token: value.token.clone() })
532+
}
533+
}
534+
486535
#[derive(Parser, Debug)]
487536
#[command(
488537
version,
@@ -630,6 +679,7 @@ fn parse_host_port(addr: &str) -> io::Result<(String, u16)> {
630679
mod tests {
631680
use std::str::FromStr;
632681

682+
use ldk_node::bitcoin::secp256k1::PublicKey;
633683
use ldk_node::bitcoin::Network;
634684
use ldk_node::lightning::ln::msgs::SocketAddress;
635685

@@ -665,6 +715,11 @@ mod tests {
665715
connection_string = "rabbitmq_connection_string"
666716
exchange_name = "rabbitmq_exchange_name"
667717
718+
[liquidity.lsps2_client]
719+
node_pubkey = "0217890e3aad8d35bc054f43acc00084b25229ecff0ab68debd82883ad65ee8266"
720+
address = "127.0.0.1:39735"
721+
token = "lsps2-token"
722+
668723
[liquidity.lsps2_service]
669724
advertise_service = false
670725
channel_opening_fee_ppm = 1000 # 0.1% fee
@@ -759,6 +814,14 @@ mod tests {
759814
rgs_server_url: Some("https://rapidsync.lightningdevkit.org/snapshot/v2/".to_string()),
760815
rabbitmq_connection_string: expected_rabbit_conn,
761816
rabbitmq_exchange_name: expected_rabbit_exchange,
817+
lsps2_client_config: Some(LSPSClientConfig {
818+
node_id: PublicKey::from_str(
819+
"0217890e3aad8d35bc054f43acc00084b25229ecff0ab68debd82883ad65ee8266",
820+
)
821+
.unwrap(),
822+
address: SocketAddress::from_str("127.0.0.1:39735").unwrap(),
823+
token: Some("lsps2-token".to_string()),
824+
}),
762825
lsps2_service_config: Some(LSPS2ServiceConfig {
763826
require_token: None,
764827
advertise_service: false,
@@ -786,6 +849,7 @@ mod tests {
786849
assert_eq!(config.rgs_server_url, expected.rgs_server_url);
787850
assert_eq!(config.rabbitmq_connection_string, expected.rabbitmq_connection_string);
788851
assert_eq!(config.rabbitmq_exchange_name, expected.rabbitmq_exchange_name);
852+
assert_eq!(config.lsps2_client_config, expected.lsps2_client_config);
789853
#[cfg(feature = "experimental-lsps2-support")]
790854
assert_eq!(config.lsps2_service_config.is_some(), expected.lsps2_service_config.is_some());
791855
assert_eq!(config.log_level, expected.log_level);
@@ -822,6 +886,10 @@ mod tests {
822886
connection_string = "rabbitmq_connection_string"
823887
exchange_name = "rabbitmq_exchange_name"
824888
889+
[liquidity.lsps2_client]
890+
node_pubkey = "0217890e3aad8d35bc054f43acc00084b25229ecff0ab68debd82883ad65ee8266"
891+
address = "127.0.0.1:39735"
892+
825893
[liquidity.lsps2_service]
826894
advertise_service = false
827895
channel_opening_fee_ppm = 1000 # 0.1% fee
@@ -875,6 +943,10 @@ mod tests {
875943
connection_string = "rabbitmq_connection_string"
876944
exchange_name = "rabbitmq_exchange_name"
877945
946+
[liquidity.lsps2_client]
947+
node_pubkey = "0217890e3aad8d35bc054f43acc00084b25229ecff0ab68debd82883ad65ee8266"
948+
address = "127.0.0.1:39735"
949+
878950
[liquidity.lsps2_service]
879951
advertise_service = false
880952
channel_opening_fee_ppm = 1000 # 0.1% fee
@@ -935,6 +1007,10 @@ mod tests {
9351007
connection_string = "rabbitmq_connection_string"
9361008
exchange_name = "rabbitmq_exchange_name"
9371009
1010+
[liquidity.lsps2_client]
1011+
node_pubkey = "0217890e3aad8d35bc054f43acc00084b25229ecff0ab68debd82883ad65ee8266"
1012+
address = "127.0.0.1:39735"
1013+
9381014
[liquidity.lsps2_service]
9391015
advertise_service = false
9401016
channel_opening_fee_ppm = 1000 # 0.1% fee
@@ -1080,6 +1156,7 @@ mod tests {
10801156
rgs_server_url: None,
10811157
rabbitmq_connection_string: String::new(),
10821158
rabbitmq_exchange_name: String::new(),
1159+
lsps2_client_config: None,
10831160
lsps2_service_config: None,
10841161
log_level: LevelFilter::Trace,
10851162
log_file_path: Some("/var/log/ldk-server.log".to_string()),
@@ -1173,6 +1250,14 @@ mod tests {
11731250
rgs_server_url: Some("https://rapidsync.lightningdevkit.org/snapshot/v2/".to_string()),
11741251
rabbitmq_connection_string: expected_rabbit_conn,
11751252
rabbitmq_exchange_name: expected_rabbit_exchange,
1253+
lsps2_client_config: Some(LSPSClientConfig {
1254+
node_id: PublicKey::from_str(
1255+
"0217890e3aad8d35bc054f43acc00084b25229ecff0ab68debd82883ad65ee8266",
1256+
)
1257+
.unwrap(),
1258+
address: SocketAddress::from_str("127.0.0.1:39735").unwrap(),
1259+
token: Some("lsps2-token".to_string()),
1260+
}),
11761261
lsps2_service_config: Some(LSPS2ServiceConfig {
11771262
require_token: None,
11781263
advertise_service: false,
@@ -1199,6 +1284,7 @@ mod tests {
11991284
assert_eq!(config.rgs_server_url, expected.rgs_server_url);
12001285
assert_eq!(config.rabbitmq_connection_string, expected.rabbitmq_connection_string);
12011286
assert_eq!(config.rabbitmq_exchange_name, expected.rabbitmq_exchange_name);
1287+
assert_eq!(config.lsps2_client_config, expected.lsps2_client_config);
12021288
#[cfg(feature = "experimental-lsps2-support")]
12031289
assert_eq!(config.lsps2_service_config.is_some(), expected.lsps2_service_config.is_some());
12041290
assert_eq!(config.pathfinding_scores_source_url, expected.pathfinding_scores_source_url);

0 commit comments

Comments
 (0)