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
52 changes: 52 additions & 0 deletions ldk-server-cli/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use serde::{Deserialize, Serialize};
const DEFAULT_CONFIG_FILE: &str = "config.toml";
const DEFAULT_CERT_FILE: &str = "tls.crt";
const API_KEY_FILE: &str = "api_key";
pub const DEFAULT_REST_SERVICE_ADDRESS: &str = "127.0.0.1:3536";

pub fn get_default_data_dir() -> Option<PathBuf> {
#[cfg(target_os = "macos")]
Expand Down Expand Up @@ -66,6 +67,7 @@ pub struct TlsConfig {

#[derive(Debug, Deserialize)]
pub struct NodeConfig {
#[serde(default = "default_rest_service_address")]
pub rest_service_address: String,
network: String,
}
Expand Down Expand Up @@ -99,3 +101,53 @@ pub fn load_config(path: &PathBuf) -> Result<Config, String> {
toml::from_str(&contents)
.map_err(|e| format!("Failed to parse config file '{}': {}", path.display(), e))
}

pub fn resolve_base_url(cli_base_url: Option<String>, config: Option<&Config>) -> String {
cli_base_url
.or_else(|| config.map(|config| config.node.rest_service_address.clone()))
.unwrap_or_else(default_rest_service_address)
}

fn default_rest_service_address() -> String {
DEFAULT_REST_SERVICE_ADDRESS.to_string()
}

#[cfg(test)]
mod tests {
use super::{resolve_base_url, Config, DEFAULT_REST_SERVICE_ADDRESS};

#[test]
fn config_defaults_rest_service_address() {
let config: Config = toml::from_str(
r#"
[node]
network = "regtest"
"#,
)
.unwrap();

assert_eq!(config.node.rest_service_address, DEFAULT_REST_SERVICE_ADDRESS);
}

#[test]
fn resolve_base_url_uses_cli_arg_first() {
let config: Config = toml::from_str(
r#"
[node]
network = "regtest"
rest_service_address = "127.0.0.1:3002"
"#,
)
.unwrap();

assert_eq!(
resolve_base_url(Some("127.0.0.1:4000".to_string()), Some(&config)),
"127.0.0.1:4000"
);
}

#[test]
fn resolve_base_url_falls_back_to_default() {
assert_eq!(resolve_base_url(None, None), DEFAULT_REST_SERVICE_ADDRESS);
}
}
18 changes: 10 additions & 8 deletions ldk-server-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ use clap::{CommandFactory, Parser, Subcommand};
use clap_complete::{generate, Shell};
use config::{
api_key_path_for_storage_dir, cert_path_for_storage_dir, get_default_api_key_path,
get_default_cert_path, get_default_config_path, load_config,
get_default_cert_path, get_default_config_path, load_config, resolve_base_url,
DEFAULT_REST_SERVICE_ADDRESS,
};
use hex_conservative::DisplayHex;
use ldk_server_client::client::LdkServerClient;
Expand Down Expand Up @@ -79,7 +80,13 @@ const DEFAULT_DIR: &str = if cfg!(target_os = "macos") {
override_usage = "ldk-server-cli [OPTIONS] <COMMAND>"
)]
struct Cli {
#[arg(short, long, help = "Base URL of the server. If not provided, reads from config file")]
#[arg(
short,
long,
help = format!(
"Base URL of the server. Defaults to config file or {DEFAULT_REST_SERVICE_ADDRESS}"
)
)]
base_url: Option<String>,

#[arg(short, long, help = format!("API key for authentication. Defaults by reading {DEFAULT_DIR}/[network]/api_key"))]
Expand Down Expand Up @@ -570,12 +577,7 @@ async fn main() {
});

// Get base URL from argument then from config file
let base_url =
cli.base_url.or_else(|| config.as_ref().map(|c| c.node.rest_service_address.clone()))
.unwrap_or_else(|| {
eprintln!("Base URL not provided. Use --base-url or ensure config file exists at {DEFAULT_DIR}/config.toml");
std::process::exit(1);
});
let base_url = resolve_base_url(cli.base_url, config.as_ref());

// Get TLS cert path from argument, then from config tls.cert_path, then from storage dir,
// then try default location.
Expand Down
2 changes: 1 addition & 1 deletion ldk-server/ldk-server-config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
network = "regtest" # Bitcoin network to use
listening_addresses = ["localhost:3001"] # Lightning node listening addresses
announcement_addresses = ["54.3.7.81:3001"] # Lightning node announcement addresses
rest_service_address = "127.0.0.1:3002" # LDK Server REST address
#rest_service_address = "127.0.0.1:3536" # LDK Server REST address (optional, defaults to 127.0.0.1:3536)
alias = "ldk_server" # Lightning node alias
#pathfinding_scores_source_url = "" # External Pathfinding Scores Source
#rgs_server_url = "https://rapidsync.lightningdevkit.org/snapshot/v2/" # Optional: RGS URL for rapid gossip sync
Expand Down
37 changes: 34 additions & 3 deletions ldk-server/src/util/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ use ldk_node::liquidity::LSPS2ServiceConfig;
use log::LevelFilter;
use serde::{Deserialize, Serialize};

const DEFAULT_REST_SERVICE_ADDRESS: &str = "127.0.0.1:3536";

#[cfg(not(test))]
const DEFAULT_CONFIG_FILE: &str = "config.toml";

Expand Down Expand Up @@ -211,7 +213,7 @@ impl ConfigBuilder {

let rest_service_addr = self
.rest_service_address
.ok_or_else(|| missing_field_err("rest_service_address"))?
.unwrap_or_else(|| DEFAULT_REST_SERVICE_ADDRESS.to_string())
.parse::<SocketAddr>()
.map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;

Expand Down Expand Up @@ -1109,7 +1111,6 @@ mod tests {
validate_missing!("rpc_password", missing_field_msg("bitcoind_rpc_password"));
validate_missing!("rpc_user", missing_field_msg("bitcoind_rpc_user"));
validate_missing!("rpc_address", missing_field_msg("bitcoind_rpc_address"));
validate_missing!("rest_service_address =", missing_field_msg("rest_service_address"));
validate_missing!("network =", missing_field_msg("network"));
}

Expand Down Expand Up @@ -1196,7 +1197,6 @@ mod tests {
validate_missing!(bitcoind_rpc_user, missing_field_msg("bitcoind_rpc_user"));
validate_missing!(bitcoind_rpc_address, missing_field_msg("bitcoind_rpc_address"));
validate_missing!(node_network, missing_field_msg("network"));
validate_missing!(node_rest_service_address, missing_field_msg("rest_service_address"));
}

#[test]
Expand Down Expand Up @@ -1309,4 +1309,35 @@ mod tests {
let err = result.unwrap_err();
assert_eq!(err.kind(), io::ErrorKind::InvalidInput);
}

#[test]
#[cfg(not(feature = "experimental-lsps2-support"))]
#[cfg(not(feature = "events-rabbitmq"))]
fn test_default_rest_service_address() {
let storage_path = std::env::temp_dir();
let config_file_name = "test_default_rest_service_address.toml";

// Config without rest_service_address
let toml_config = r#"
[node]
network = "regtest"
[bitcoind]
rpc_address = "127.0.0.1:8332"
rpc_user = "bitcoind-testuser"
rpc_password = "bitcoind-testpassword"
"#;

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

let mut args_config = empty_args_config();
args_config.config_file =
Some(storage_path.join(config_file_name).to_string_lossy().to_string());

let config = load_config(&args_config).unwrap();
assert_eq!(
config.rest_service_addr,
SocketAddr::from_str(DEFAULT_REST_SERVICE_ADDRESS).unwrap()
);
}
}
Loading