Skip to content

Commit 31d39df

Browse files
committed
Add LSPS2 client config
Expose LSPS2 client settings in so nodes can be configured to source just-in-time liquidity from an LSP. Co-Authored-By: HAL 9000 Signed-off-by: Elias Rohrer <dev@tnull.de>
1 parent 9b33ccd commit 31d39df

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
@@ -41,6 +41,15 @@ server_url = "https://mempool.space/api" # Esplora endpoint
4141
connection_string = "" # RabbitMQ connection string
4242
exchange_name = ""
4343

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

ldk-server/src/main.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,14 @@ fn main() {
163163
},
164164
}
165165

166+
if let Some(lsps2_client_config) = config_file.lsps2_client_config {
167+
builder.set_liquidity_source_lsps2(
168+
lsps2_client_config.node_id,
169+
lsps2_client_config.address,
170+
lsps2_client_config.token,
171+
);
172+
}
173+
166174
// LSPS2 support is highly experimental and for testing purposes only.
167175
#[cfg(feature = "experimental-lsps2-support")]
168176
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;
@@ -46,13 +47,24 @@ pub struct Config {
4647
pub rest_service_addr: SocketAddr,
4748
pub storage_dir_path: Option<String>,
4849
pub chain_source: ChainSource,
50+
#[cfg_attr(not(feature = "events-rabbitmq"), allow(dead_code))]
4951
pub rabbitmq_connection_string: String,
52+
#[cfg_attr(not(feature = "events-rabbitmq"), allow(dead_code))]
5053
pub rabbitmq_exchange_name: String,
54+
pub lsps2_client_config: Option<LSPSClientConfig>,
55+
#[cfg_attr(not(feature = "experimental-lsps2-support"), allow(dead_code))]
5156
pub lsps2_service_config: Option<LSPS2ServiceConfig>,
5257
pub log_level: LevelFilter,
5358
pub log_file_path: Option<String>,
5459
}
5560

61+
#[derive(Debug, Clone, PartialEq, Eq)]
62+
pub struct LSPSClientConfig {
63+
pub node_id: PublicKey,
64+
pub address: SocketAddress,
65+
pub token: Option<String>,
66+
}
67+
5668
#[derive(Debug, Clone, PartialEq, Eq)]
5769
pub struct TlsConfig {
5870
pub cert_path: Option<String>,
@@ -314,6 +326,13 @@ impl ConfigBuilder {
314326
#[cfg(not(feature = "events-rabbitmq"))]
315327
let (rabbitmq_connection_string, rabbitmq_exchange_name) = (String::new(), String::new());
316328

329+
let lsps2_client_config = self
330+
.lsps2
331+
.as_ref()
332+
.and_then(|liquidity| liquidity.lsps2_client.as_ref())
333+
.map(LSPSClientConfig::try_from)
334+
.transpose()?;
335+
317336
#[cfg(feature = "experimental-lsps2-support")]
318337
let lsps2_service_config = {
319338
let liquidity = self.lsps2.ok_or_else(|| io::Error::new(
@@ -341,6 +360,7 @@ impl ConfigBuilder {
341360
chain_source,
342361
rabbitmq_connection_string,
343362
rabbitmq_exchange_name,
363+
lsps2_client_config,
344364
lsps2_service_config,
345365
log_level,
346366
log_file_path: self.log_file_path,
@@ -419,9 +439,17 @@ struct TomlTlsConfig {
419439

420440
#[derive(Deserialize, Serialize)]
421441
struct LiquidityConfig {
442+
lsps2_client: Option<LSPSClientTomlConfig>,
422443
lsps2_service: Option<LSPS2ServiceTomlConfig>,
423444
}
424445

446+
#[derive(Deserialize, Serialize, Debug)]
447+
struct LSPSClientTomlConfig {
448+
node_pubkey: String,
449+
address: String,
450+
token: Option<String>,
451+
}
452+
425453
#[derive(Deserialize, Serialize, Debug)]
426454
struct LSPS2ServiceTomlConfig {
427455
advertise_service: bool,
@@ -466,6 +494,27 @@ impl From<LSPS2ServiceTomlConfig> for LSPS2ServiceConfig {
466494
}
467495
}
468496

497+
impl TryFrom<&LSPSClientTomlConfig> for LSPSClientConfig {
498+
type Error = io::Error;
499+
500+
fn try_from(value: &LSPSClientTomlConfig) -> Result<Self, Self::Error> {
501+
let node_id = PublicKey::from_str(&value.node_pubkey).map_err(|e| {
502+
io::Error::new(
503+
io::ErrorKind::InvalidInput,
504+
format!("Invalid liquidity client node pubkey configured: {e}"),
505+
)
506+
})?;
507+
let address = SocketAddress::from_str(&value.address).map_err(|e| {
508+
io::Error::new(
509+
io::ErrorKind::InvalidInput,
510+
format!("Invalid liquidity client address configured: {e}"),
511+
)
512+
})?;
513+
514+
Ok(Self { node_id, address, token: value.token.clone() })
515+
}
516+
}
517+
469518
#[derive(Parser, Debug)]
470519
#[command(
471520
version,
@@ -606,6 +655,7 @@ fn parse_host_port(addr: &str) -> io::Result<(String, u16)> {
606655
mod tests {
607656
use std::str::FromStr;
608657

658+
use ldk_node::bitcoin::secp256k1::PublicKey;
609659
use ldk_node::bitcoin::Network;
610660
use ldk_node::lightning::ln::msgs::SocketAddress;
611661

@@ -640,6 +690,11 @@ mod tests {
640690
connection_string = "rabbitmq_connection_string"
641691
exchange_name = "rabbitmq_exchange_name"
642692
693+
[liquidity.lsps2_client]
694+
node_pubkey = "0217890e3aad8d35bc054f43acc00084b25229ecff0ab68debd82883ad65ee8266"
695+
address = "127.0.0.1:39735"
696+
token = "lsps2-token"
697+
643698
[liquidity.lsps2_service]
644699
advertise_service = false
645700
channel_opening_fee_ppm = 1000 # 0.1% fee
@@ -731,6 +786,14 @@ mod tests {
731786
},
732787
rabbitmq_connection_string: expected_rabbit_conn,
733788
rabbitmq_exchange_name: expected_rabbit_exchange,
789+
lsps2_client_config: Some(LSPSClientConfig {
790+
node_id: PublicKey::from_str(
791+
"0217890e3aad8d35bc054f43acc00084b25229ecff0ab68debd82883ad65ee8266",
792+
)
793+
.unwrap(),
794+
address: SocketAddress::from_str("127.0.0.1:39735").unwrap(),
795+
token: Some("lsps2-token".to_string()),
796+
}),
734797
lsps2_service_config: Some(LSPS2ServiceConfig {
735798
require_token: None,
736799
advertise_service: false,
@@ -756,6 +819,7 @@ mod tests {
756819
assert_eq!(config.chain_source, expected.chain_source);
757820
assert_eq!(config.rabbitmq_connection_string, expected.rabbitmq_connection_string);
758821
assert_eq!(config.rabbitmq_exchange_name, expected.rabbitmq_exchange_name);
822+
assert_eq!(config.lsps2_client_config, expected.lsps2_client_config);
759823
#[cfg(feature = "experimental-lsps2-support")]
760824
assert_eq!(config.lsps2_service_config.is_some(), expected.lsps2_service_config.is_some());
761825
assert_eq!(config.log_level, expected.log_level);
@@ -790,6 +854,10 @@ mod tests {
790854
connection_string = "rabbitmq_connection_string"
791855
exchange_name = "rabbitmq_exchange_name"
792856
857+
[liquidity.lsps2_client]
858+
node_pubkey = "0217890e3aad8d35bc054f43acc00084b25229ecff0ab68debd82883ad65ee8266"
859+
address = "127.0.0.1:39735"
860+
793861
[liquidity.lsps2_service]
794862
advertise_service = false
795863
channel_opening_fee_ppm = 1000 # 0.1% fee
@@ -842,6 +910,10 @@ mod tests {
842910
connection_string = "rabbitmq_connection_string"
843911
exchange_name = "rabbitmq_exchange_name"
844912
913+
[liquidity.lsps2_client]
914+
node_pubkey = "0217890e3aad8d35bc054f43acc00084b25229ecff0ab68debd82883ad65ee8266"
915+
address = "127.0.0.1:39735"
916+
845917
[liquidity.lsps2_service]
846918
advertise_service = false
847919
channel_opening_fee_ppm = 1000 # 0.1% fee
@@ -901,6 +973,10 @@ mod tests {
901973
connection_string = "rabbitmq_connection_string"
902974
exchange_name = "rabbitmq_exchange_name"
903975
976+
[liquidity.lsps2_client]
977+
node_pubkey = "0217890e3aad8d35bc054f43acc00084b25229ecff0ab68debd82883ad65ee8266"
978+
address = "127.0.0.1:39735"
979+
904980
[liquidity.lsps2_service]
905981
advertise_service = false
906982
channel_opening_fee_ppm = 1000 # 0.1% fee
@@ -1045,6 +1121,7 @@ mod tests {
10451121
},
10461122
rabbitmq_connection_string: String::new(),
10471123
rabbitmq_exchange_name: String::new(),
1124+
lsps2_client_config: None,
10481125
lsps2_service_config: None,
10491126
log_level: LevelFilter::Trace,
10501127
log_file_path: Some("/var/log/ldk-server.log".to_string()),
@@ -1134,6 +1211,14 @@ mod tests {
11341211
},
11351212
rabbitmq_connection_string: expected_rabbit_conn,
11361213
rabbitmq_exchange_name: expected_rabbit_exchange,
1214+
lsps2_client_config: Some(LSPSClientConfig {
1215+
node_id: PublicKey::from_str(
1216+
"0217890e3aad8d35bc054f43acc00084b25229ecff0ab68debd82883ad65ee8266",
1217+
)
1218+
.unwrap(),
1219+
address: SocketAddress::from_str("127.0.0.1:39735").unwrap(),
1220+
token: Some("lsps2-token".to_string()),
1221+
}),
11371222
lsps2_service_config: Some(LSPS2ServiceConfig {
11381223
require_token: None,
11391224
advertise_service: false,
@@ -1158,6 +1243,7 @@ mod tests {
11581243
assert_eq!(config.chain_source, expected.chain_source);
11591244
assert_eq!(config.rabbitmq_connection_string, expected.rabbitmq_connection_string);
11601245
assert_eq!(config.rabbitmq_exchange_name, expected.rabbitmq_exchange_name);
1246+
assert_eq!(config.lsps2_client_config, expected.lsps2_client_config);
11611247
#[cfg(feature = "experimental-lsps2-support")]
11621248
assert_eq!(config.lsps2_service_config.is_some(), expected.lsps2_service_config.is_some());
11631249
}

0 commit comments

Comments
 (0)