Skip to content
Merged
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
2 changes: 2 additions & 0 deletions e2e-tests/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ fn main() {
println!("cargo:rerun-if-changed=../ldk-server/Cargo.toml");
println!("cargo:rerun-if-changed=../ldk-server-cli/src");
println!("cargo:rerun-if-changed=../ldk-server-cli/Cargo.toml");
println!("cargo:rerun-if-changed=../ldk-server-client/src");
println!("cargo:rerun-if-changed=../ldk-server-client/Cargo.toml");
println!("cargo:rerun-if-changed=../ldk-server-grpc/src");
println!("cargo:rerun-if-changed=../ldk-server-grpc/Cargo.toml");
println!("cargo:rerun-if-changed=../ldk-server-mcp/src");
Expand Down
31 changes: 31 additions & 0 deletions e2e-tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ pub struct LdkServerHandle {
pub grpc_port: u16,
pub p2p_port: u16,
pub storage_dir: PathBuf,
pub config_path: PathBuf,
pub api_key: String,
pub tls_cert_path: PathBuf,
pub node_id: String,
Expand Down Expand Up @@ -214,6 +215,7 @@ poll_metrics_interval = 1
grpc_port,
p2p_port,
storage_dir,
config_path,
api_key,
tls_cert_path,
node_id: String::new(),
Expand Down Expand Up @@ -381,13 +383,42 @@ pub fn run_cli_raw(handle: &LdkServerHandle, args: &[&str]) -> String {
String::from_utf8(output.stdout).unwrap()
}

/// Run a CLI command using the server's config file for connection details.
pub fn run_cli_with_config_raw(handle: &LdkServerHandle, args: &[&str]) -> String {
let cli_path = cli_binary_path();
let output = Command::new(&cli_path)
.arg("--config")
.arg(handle.config_path.to_str().unwrap())
.args(args)
.output()
.unwrap_or_else(|e| panic!("Failed to run CLI at {:?}: {}", cli_path, e));

if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
let stdout = String::from_utf8_lossy(&output.stdout);
panic!(
"CLI command {:?} failed with status {}\nstdout: {}\nstderr: {}",
args, output.status, stdout, stderr
);
}

String::from_utf8(output.stdout).unwrap()
}

/// Run a CLI command against the given server handle and return parsed JSON output.
pub fn run_cli(handle: &LdkServerHandle, args: &[&str]) -> serde_json::Value {
let stdout = run_cli_raw(handle, args);
serde_json::from_str(&stdout)
.unwrap_or_else(|e| panic!("Failed to parse CLI output as JSON: {e}\nOutput: {stdout}"))
}

/// Run a CLI command using the server's config file and return parsed JSON output.
pub fn run_cli_with_config(handle: &LdkServerHandle, args: &[&str]) -> serde_json::Value {
let stdout = run_cli_with_config_raw(handle, args);
serde_json::from_str(&stdout)
.unwrap_or_else(|e| panic!("Failed to parse CLI output as JSON: {e}\nOutput: {stdout}"))
}

/// Mine blocks and wait for all servers to sync to the new chain tip.
pub async fn mine_and_sync(
bitcoind: &TestBitcoind, servers: &[&LdkServerHandle], block_count: u64,
Expand Down
15 changes: 12 additions & 3 deletions e2e-tests/tests/e2e.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ use std::str::FromStr;
use std::time::Duration;

use e2e_tests::{
find_available_port, mine_and_sync, run_cli, run_cli_raw, setup_funded_channel,
wait_for_onchain_balance, wait_for_usable_channel, LdkServerConfig, LdkServerHandle,
TestBitcoind,
find_available_port, mine_and_sync, run_cli, run_cli_raw, run_cli_with_config,
setup_funded_channel, wait_for_onchain_balance, wait_for_usable_channel, LdkServerConfig,
LdkServerHandle, TestBitcoind,
};
use hex_conservative::{DisplayHex, FromHex};
use ldk_node::bitcoin::hashes::{sha256, Hash};
Expand Down Expand Up @@ -57,6 +57,15 @@ async fn test_cli_get_node_info() {
assert_eq!(output["node_id"], server.node_id());
}

#[tokio::test]
async fn test_cli_get_node_info_with_server_config() {
let bitcoind = TestBitcoind::new();
let server = LdkServerHandle::start(&bitcoind).await;

let output = run_cli_with_config(&server, &["get-node-info"]);
assert_eq!(output["node_id"], server.node_id());
}

#[tokio::test]
async fn test_cli_onchain_receive() {
let bitcoind = TestBitcoind::new();
Expand Down
71 changes: 50 additions & 21 deletions ldk-server-client/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ pub fn cert_path_for_storage_dir(storage_dir: &str) -> PathBuf {

/// Top-level structure of the `ldk-server` configuration TOML file.
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Config {
/// Node-level configuration.
pub node: NodeConfig,
Expand All @@ -82,15 +81,13 @@ pub struct Config {

/// `[tls]` section of the configuration file.
#[derive(Debug, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct TlsConfig {
/// Path to the server's TLS certificate in PEM format.
pub cert_path: Option<String>,
}

/// `[node]` section of the configuration file.
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct NodeConfig {
/// Address of the `ldk-server` gRPC service.
#[serde(default = "default_grpc_service_address")]
Expand All @@ -100,15 +97,13 @@ pub struct NodeConfig {

/// `[storage]` section of the configuration file.
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct StorageConfig {
/// On-disk storage configuration.
pub disk: Option<DiskConfig>,
}

/// `[storage.disk]` section of the configuration file.
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct DiskConfig {
/// Directory used by the server to store its persistent data.
pub dir_path: Option<String>,
Expand Down Expand Up @@ -208,28 +203,62 @@ mod tests {
}

#[test]
fn config_rejects_unknown_fields() {
let top_level_err = toml::from_str::<Config>(
fn config_allows_server_config_fields() {
let config = toml::from_str::<Config>(
r#"
[node]
network = "regtest"

[unknown]
option = true
listening_addresses = ["localhost:3001"]
announcement_addresses = ["54.3.7.81:3001"]
grpc_service_address = "127.0.0.1:3002"
alias = "LDK Server"
rgs_server_url = "https://rapidsync.lightningdevkit.org/snapshot/v2/"
async_payments_role = "client"

[tls]
cert_path = "/path/to/tls.crt"
key_path = "/path/to/tls.key"
hosts = ["example.com", "ldk-server.local"]

[storage.disk]
dir_path = "/tmp"

[log]
level = "Trace"
file = "/var/log/ldk-server.log"

[bitcoind]
rpc_address = "127.0.0.1:8332"
rpc_user = "bitcoind-testuser"
rpc_password = "bitcoind-testpassword"

[liquidity.lsps2_client]
node_pubkey = "0217890e3aad8d35bc054f43acc00084b25229ecff0ab68debd82883ad65ee8266"
address = "127.0.0.1:39735"
token = "lsps2-token"

[liquidity.lsps2_service]
advertise_service = false
channel_opening_fee_ppm = 1000
channel_over_provisioning_ppm = 500000
min_channel_opening_fee_msat = 10000000
min_channel_lifetime = 4320
max_client_to_self_delay = 1440
min_payment_size_msat = 10000000
max_payment_size_msat = 25000000000
client_trusts_lsp = true
disable_client_reserve = false

[tor]
proxy_address = "127.0.0.1:9050"
"#,
)
.unwrap_err();
assert!(top_level_err.to_string().contains("unknown field `unknown`"));
.unwrap();

let node_err = toml::from_str::<Config>(
r#"
[node]
network = "regtest"
unknown = true
"#,
)
.unwrap_err();
assert!(node_err.to_string().contains("unknown field `unknown`"));
assert_eq!(config.network().unwrap(), "regtest");
assert_eq!(config.node.grpc_service_address, "127.0.0.1:3002");
assert_eq!(config.tls.unwrap().cert_path.unwrap(), "/path/to/tls.crt");
assert_eq!(config.storage.unwrap().disk.unwrap().dir_path.unwrap(), "/tmp");
}

#[test]
Expand Down