diff --git a/e2e-tests/build.rs b/e2e-tests/build.rs index 6bfa0b6a..10ccd3a0 100644 --- a/e2e-tests/build.rs +++ b/e2e-tests/build.rs @@ -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"); diff --git a/e2e-tests/src/lib.rs b/e2e-tests/src/lib.rs index a2d5df9a..b90214fb 100644 --- a/e2e-tests/src/lib.rs +++ b/e2e-tests/src/lib.rs @@ -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, @@ -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(), @@ -381,6 +383,28 @@ 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); @@ -388,6 +412,13 @@ pub fn run_cli(handle: &LdkServerHandle, args: &[&str]) -> serde_json::Value { .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, diff --git a/e2e-tests/tests/e2e.rs b/e2e-tests/tests/e2e.rs index 641cf623..0fb634a8 100644 --- a/e2e-tests/tests/e2e.rs +++ b/e2e-tests/tests/e2e.rs @@ -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}; @@ -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(); diff --git a/ldk-server-client/src/config.rs b/ldk-server-client/src/config.rs index e2dca342..cbe9a38c 100644 --- a/ldk-server-client/src/config.rs +++ b/ldk-server-client/src/config.rs @@ -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, @@ -82,7 +81,6 @@ 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, @@ -90,7 +88,6 @@ pub struct TlsConfig { /// `[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")] @@ -100,7 +97,6 @@ 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, @@ -108,7 +104,6 @@ pub struct StorageConfig { /// `[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, @@ -208,28 +203,62 @@ mod tests { } #[test] - fn config_rejects_unknown_fields() { - let top_level_err = toml::from_str::( + fn config_allows_server_config_fields() { + let config = toml::from_str::( 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::( - 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]