Skip to content

Commit 6474fbe

Browse files
committed
Add experimental LSPS2 support.
1 parent 96de892 commit 6474fbe

File tree

4 files changed

+108
-17
lines changed

4 files changed

+108
-17
lines changed

ldk-server/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ lapin = { version = "2.4.0", features = ["rustls"], default-features = false, op
2626
default = []
2727
events-rabbitmq = ["dep:lapin"]
2828

29+
# Experimental Features.
30+
experimental-lsps2-support = []
31+
2932
# Feature-flags related to integration tests.
3033
integration-tests-events-rabbitmq = ["events-rabbitmq"]
3134

ldk-server/ldk-server-config.toml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,18 @@ rpc_password = "polarpass" # RPC password
1717
# RabbitMQ settings (only required if using events-rabbitmq feature)
1818
[rabbitmq]
1919
connection_string = "" # RabbitMQ connection string
20-
exchange_name = "" # RabbitMQ exchange name
20+
exchange_name = ""
21+
22+
# Experimental LSPS2 Service Support
23+
# CAUTION: LSPS2 support is highly experimental and for testing purposes only.
24+
[liquidity.lsps2_service]
25+
advertise_service = false
26+
channel_opening_fee_ppm = 1000 # 0.1% fee
27+
channel_over_provisioning_ppm = 500000 # 50% extra capacity
28+
min_channel_opening_fee_msat = 10000000 # 10,000 satoshis
29+
min_channel_lifetime = 4320 # ~30 days
30+
max_client_to_self_delay = 1440 # ~10 days
31+
min_payment_size_msat = 10000000 # 10,000 satoshis
32+
max_payment_size_msat = 25000000000 # 0.25 BTC
33+
# Optional token for clients (uncomment and set if required)
34+
# require_token = ""

ldk-server/src/main.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ use crate::util::proto_adapter::{forwarded_payment_to_proto, payment_to_proto};
2929
use hex::DisplayHex;
3030
use ldk_node::config::Config;
3131
use ldk_node::lightning::ln::channelmanager::PaymentId;
32-
use ldk_node::logger::LogLevel;
32+
#[cfg(feature = "experimental-lsps2-support")]
33+
use ldk_node::liquidity::LSPS2ServiceConfig;
3334
use ldk_server_protos::events;
3435
use ldk_server_protos::events::{event_envelope, EventEnvelope};
3536
use ldk_server_protos::types::Payment;
@@ -81,6 +82,12 @@ fn main() {
8182
config_file.bitcoind_rpc_password,
8283
);
8384

85+
// LSPS2 support is highly experimental and for testing purposes only.
86+
#[cfg(feature = "experimental-lsps2-support")]
87+
builder.set_liquidity_provider_lsps2(
88+
config_file.lsps2_service_config.expect("Missing liquidity.lsps2_server config"),
89+
);
90+
8491
let runtime = match tokio::runtime::Builder::new_multi_thread().enable_all().build() {
8592
Ok(runtime) => Arc::new(runtime),
8693
Err(e) => {

ldk-server/src/util/config.rs

Lines changed: 82 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
use ldk_node::bitcoin::Network;
22
use ldk_node::lightning::ln::msgs::SocketAddress;
3+
use ldk_node::liquidity::LSPS2ServiceConfig;
34
use serde::{Deserialize, Serialize};
45
use std::net::SocketAddr;
56
use std::path::Path;
67
use std::str::FromStr;
78
use std::{fs, io};
89

910
/// Configuration for LDK Server.
10-
#[derive(PartialEq, Eq, Debug)]
11+
#[derive(Debug)]
1112
pub struct Config {
1213
pub listening_addr: SocketAddress,
1314
pub network: Network,
@@ -18,6 +19,7 @@ pub struct Config {
1819
pub bitcoind_rpc_password: String,
1920
pub rabbitmq_connection_string: String,
2021
pub rabbitmq_exchange_name: String,
22+
pub lsps2_service_config: Option<LSPS2ServiceConfig>,
2123
}
2224

2325
impl TryFrom<TomlConfig> for Config {
@@ -61,6 +63,11 @@ impl TryFrom<TomlConfig> for Config {
6163
(rabbitmq.connection_string, rabbitmq.exchange_name)
6264
};
6365

66+
#[cfg(not(feature = "experimental-lsps2-support"))]
67+
let lsps2_service_config: Option<LSPS2ServiceConfig> = None;
68+
#[cfg(feature = "experimental-lsps2-support")]
69+
let lsps2_service_config = Some(toml_config.liquidity.expect("`liquidity.lsps2_server` must be defined in config if enabling `experimental-lsps2-support` feature.").lsps2_service.into());
70+
6471
Ok(Config {
6572
listening_addr,
6673
network: toml_config.node.network,
@@ -71,6 +78,7 @@ impl TryFrom<TomlConfig> for Config {
7178
bitcoind_rpc_password: toml_config.bitcoind.rpc_password,
7279
rabbitmq_connection_string,
7380
rabbitmq_exchange_name,
81+
lsps2_service_config,
7482
})
7583
}
7684
}
@@ -82,6 +90,8 @@ pub struct TomlConfig {
8290
storage: StorageConfig,
8391
bitcoind: BitcoindConfig,
8492
rabbitmq: Option<RabbitmqConfig>,
93+
#[serde(default)]
94+
liquidity: Option<LiquidityConfig>,
8595
}
8696

8797
#[derive(Deserialize, Serialize)]
@@ -114,6 +124,53 @@ struct RabbitmqConfig {
114124
exchange_name: String,
115125
}
116126

127+
#[derive(Deserialize, Serialize)]
128+
struct LiquidityConfig {
129+
lsps2_service: LSPS2ServiceTomlConfig,
130+
}
131+
132+
#[derive(Deserialize, Serialize, Debug)]
133+
struct LSPS2ServiceTomlConfig {
134+
advertise_service: bool,
135+
channel_opening_fee_ppm: u32,
136+
channel_over_provisioning_ppm: u32,
137+
min_channel_opening_fee_msat: u64,
138+
min_channel_lifetime: u32,
139+
max_client_to_self_delay: u32,
140+
min_payment_size_msat: u64,
141+
max_payment_size_msat: u64,
142+
#[serde(default)] // Make require_token optional
143+
require_token: Option<String>,
144+
}
145+
146+
impl Into<LSPS2ServiceConfig> for LSPS2ServiceTomlConfig {
147+
fn into(self) -> LSPS2ServiceConfig {
148+
match self {
149+
LSPS2ServiceTomlConfig {
150+
advertise_service,
151+
channel_opening_fee_ppm,
152+
channel_over_provisioning_ppm,
153+
min_channel_opening_fee_msat,
154+
min_channel_lifetime,
155+
max_client_to_self_delay,
156+
min_payment_size_msat,
157+
max_payment_size_msat,
158+
require_token,
159+
} => LSPS2ServiceConfig {
160+
advertise_service,
161+
channel_opening_fee_ppm,
162+
channel_over_provisioning_ppm,
163+
min_channel_opening_fee_msat,
164+
min_channel_lifetime,
165+
min_payment_size_msat,
166+
max_client_to_self_delay,
167+
max_payment_size_msat,
168+
require_token,
169+
},
170+
}
171+
}
172+
}
173+
117174
/// Loads the configuration from a TOML file at the given path.
118175
pub fn load_config<P: AsRef<Path>>(config_path: P) -> io::Result<Config> {
119176
let file_contents = fs::read_to_string(config_path.as_ref()).map_err(|e| {
@@ -164,19 +221,29 @@ mod tests {
164221

165222
fs::write(storage_path.join(config_file_name), toml_config).unwrap();
166223

167-
assert_eq!(
168-
load_config(storage_path.join(config_file_name)).unwrap(),
169-
Config {
170-
listening_addr: SocketAddress::from_str("localhost:3001").unwrap(),
171-
network: Network::Regtest,
172-
rest_service_addr: SocketAddr::from_str("127.0.0.1:3002").unwrap(),
173-
storage_dir_path: "/tmp".to_string(),
174-
bitcoind_rpc_addr: SocketAddr::from_str("127.0.0.1:8332").unwrap(),
175-
bitcoind_rpc_user: "bitcoind-testuser".to_string(),
176-
bitcoind_rpc_password: "bitcoind-testpassword".to_string(),
177-
rabbitmq_connection_string: "rabbitmq_connection_string".to_string(),
178-
rabbitmq_exchange_name: "rabbitmq_exchange_name".to_string(),
179-
}
180-
)
224+
let config = load_config(storage_path.join(config_file_name)).unwrap();
225+
let expected = Config {
226+
listening_addr: SocketAddress::from_str("localhost:3001").unwrap(),
227+
network: Network::Regtest,
228+
rest_service_addr: SocketAddr::from_str("127.0.0.1:3002").unwrap(),
229+
storage_dir_path: "/tmp".to_string(),
230+
bitcoind_rpc_addr: SocketAddr::from_str("127.0.0.1:8332").unwrap(),
231+
bitcoind_rpc_user: "bitcoind-testuser".to_string(),
232+
bitcoind_rpc_password: "bitcoind-testpassword".to_string(),
233+
rabbitmq_connection_string: "rabbitmq_connection_string".to_string(),
234+
rabbitmq_exchange_name: "rabbitmq_exchange_name".to_string(),
235+
lsps2_service_config: None,
236+
};
237+
238+
assert_eq!(config.listening_addr.to_string(), expected.listening_addr.to_string());
239+
assert_eq!(config.network, expected.network);
240+
assert_eq!(config.rest_service_addr, expected.rest_service_addr);
241+
assert_eq!(config.storage_dir_path, expected.storage_dir_path);
242+
assert_eq!(config.bitcoind_rpc_addr, expected.bitcoind_rpc_addr);
243+
assert_eq!(config.bitcoind_rpc_user, expected.bitcoind_rpc_user);
244+
assert_eq!(config.bitcoind_rpc_password, expected.bitcoind_rpc_password);
245+
assert_eq!(config.rabbitmq_connection_string, expected.rabbitmq_connection_string);
246+
assert_eq!(config.rabbitmq_exchange_name, expected.rabbitmq_exchange_name);
247+
assert_eq!(config.lsps2_service_config.is_some(), expected.lsps2_service_config.is_some());
181248
}
182249
}

0 commit comments

Comments
 (0)