-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,300 @@ | ||
use std::{ | ||
net::{IpAddr, SocketAddr}, | ||
path::PathBuf, | ||
time::Duration, | ||
}; | ||
|
||
use crate::Carnot; | ||
use clap::{Parser, ValueEnum}; | ||
use color_eyre::eyre::{self, eyre, Result}; | ||
use hex::FromHex; | ||
#[cfg(feature = "metrics")] | ||
use metrics::{backend::map::MapMetricsBackend, types::MetricsData, MetricsService}; | ||
use nomos_http::{backends::axum::AxumBackend, http::HttpService}; | ||
#[cfg(feature = "libp2p")] | ||
use nomos_libp2p::{secp256k1::SecretKey, Multiaddr}; | ||
use nomos_log::{Logger, LoggerBackend, LoggerFormat}; | ||
#[cfg(feature = "libp2p")] | ||
use nomos_network::backends::libp2p::Libp2p; | ||
#[cfg(feature = "waku")] | ||
use nomos_network::backends::waku::Waku; | ||
use nomos_network::NetworkService; | ||
use overwatch_rs::services::ServiceData; | ||
use serde::{Deserialize, Serialize}; | ||
use tracing::Level; | ||
#[cfg(feature = "waku")] | ||
use waku_bindings::{Multiaddr, SecretKey}; | ||
|
||
#[derive(ValueEnum, Clone, Debug, Default)] | ||
pub enum LoggerBackendType { | ||
Gelf, | ||
File, | ||
#[default] | ||
Stdout, | ||
Stderr, | ||
} | ||
|
||
#[derive(Parser, Debug, Clone)] | ||
pub struct LogArgs { | ||
/// Address for the Gelf backend | ||
#[clap(long = "log-addr", env = "LOG_ADDR", required_if_eq("backend", "Gelf"))] | ||
log_addr: Option<SocketAddr>, | ||
|
||
/// Directory for the File backend | ||
#[clap(long = "log-dir", env = "LOG_DIR", required_if_eq("backend", "File"))] | ||
directory: Option<PathBuf>, | ||
|
||
/// Prefix for the File backend | ||
#[clap(long = "log-path", env = "LOG_PATH", required_if_eq("backend", "File"))] | ||
prefix: Option<PathBuf>, | ||
|
||
/// Backend type | ||
#[clap(long = "log-backend", env = "LOG_BACKEND", value_enum)] | ||
backend: Option<LoggerBackendType>, | ||
|
||
#[clap(long = "log-format", env = "LOG_FORMAT")] | ||
format: Option<String>, | ||
|
||
#[clap(long = "log-level", env = "LOG_LEVEL")] | ||
level: Option<String>, | ||
} | ||
|
||
#[derive(Parser, Debug, Clone)] | ||
pub struct NetworkArgs { | ||
#[clap(long = "net-host", env = "NET_HOST")] | ||
host: Option<IpAddr>, | ||
|
||
#[clap(long = "net-port", env = "NET_PORT")] | ||
port: Option<usize>, | ||
|
||
#[clap(long = "net-node-key", env = "NET_NODE_KEY")] | ||
node_key: Option<String>, | ||
|
||
#[clap(long = "net-initial-peers", env = "NET_INITIAL_PEERS")] | ||
pub initial_peers: Option<Vec<Multiaddr>>, | ||
} | ||
|
||
#[derive(Parser, Debug, Clone)] | ||
pub struct HttpArgs { | ||
#[clap(long = "http-host", env = "HTTP_HOST")] | ||
http_addr: Option<SocketAddr>, | ||
|
||
#[clap(long = "http-cors-origin", env = "HTTP_CORS_ORIGIN")] | ||
pub cors_origins: Option<Vec<String>>, | ||
} | ||
|
||
#[derive(Parser, Debug, Clone)] | ||
pub struct ConsensusArgs { | ||
#[clap(long = "consensus-priv-key", env = "CONSENSUS_PRIV_KEY")] | ||
consensus_priv_key: Option<String>, | ||
|
||
#[clap(long = "consensus-timeout-secs", env = "CONSENSUS_TIMEOUT_SECS")] | ||
consensus_timeout_secs: Option<String>, | ||
} | ||
|
||
#[derive(ValueEnum, Clone, Debug, Default)] | ||
pub enum OverlayType { | ||
#[default] | ||
Flat, | ||
Tree, | ||
} | ||
|
||
#[derive(Parser, Debug, Clone)] | ||
pub struct OverlayArgs { | ||
// TODO: Act on type and support other overlays. | ||
#[clap(long = "overlay-type", env = "OVERLAY_TYPE")] | ||
pub overlay_type: Option<OverlayType>, | ||
|
||
#[clap(long = "overlay-nodes", env = "OVERLAY_NODES")] | ||
pub overlay_nodes: Option<Vec<String>>, | ||
|
||
#[clap(long = "overlay-leader", env = "OVERLAY_LEADER")] | ||
pub overlay_leader: Option<usize>, | ||
|
||
#[clap( | ||
long = "overlay-leader-super-majority-threshold", | ||
env = "OVERLAY_LEADER_SUPER_MAJORITY_THRESHOLD" | ||
)] | ||
pub overlay_leader_super_majority_threshold: Option<usize>, | ||
} | ||
|
||
#[derive(Deserialize, Debug, Clone, Serialize)] | ||
pub struct Config { | ||
pub log: <Logger as ServiceData>::Settings, | ||
#[cfg(feature = "waku")] | ||
pub network: <NetworkService<Waku> as ServiceData>::Settings, | ||
#[cfg(feature = "libp2p")] | ||
pub network: <NetworkService<Libp2p> as ServiceData>::Settings, | ||
pub http: <HttpService<AxumBackend> as ServiceData>::Settings, | ||
pub consensus: <Carnot as ServiceData>::Settings, | ||
#[cfg(feature = "metrics")] | ||
pub metrics: <MetricsService<MapMetricsBackend<MetricsData>> as ServiceData>::Settings, | ||
} | ||
|
||
impl Config { | ||
pub fn update_log(mut self, log_args: LogArgs) -> Result<Self> { | ||
let LogArgs { | ||
backend, | ||
log_addr: addr, | ||
directory, | ||
prefix, | ||
format, | ||
level, | ||
} = log_args; | ||
|
||
// Override the file config with the one from env variables. | ||
if let Some(backend) = backend { | ||
self.log.backend = match backend { | ||
LoggerBackendType::Gelf => LoggerBackend::Gelf { | ||
addr: addr.ok_or_else(|| eyre!("Gelf backend requires an address."))?, | ||
}, | ||
LoggerBackendType::File => LoggerBackend::File { | ||
directory: directory | ||
.ok_or_else(|| eyre!("File backend requires a directory."))?, | ||
prefix, | ||
}, | ||
LoggerBackendType::Stdout => LoggerBackend::Stdout, | ||
LoggerBackendType::Stderr => LoggerBackend::Stderr, | ||
} | ||
}; | ||
|
||
// Update parts of the config. | ||
if let Some(format_str) = format { | ||
self.log.format = match format_str.as_str() { | ||
"Json" => LoggerFormat::Json, | ||
"Plain" => LoggerFormat::Plain, | ||
_ => return Err(eyre!("Invalid log format provided.")), | ||
}; | ||
} | ||
if let Some(level_str) = level { | ||
self.log.level = match level_str.as_str() { | ||
"DEBUG" => Level::DEBUG, | ||
_ => return Err(eyre!("Invalid log level provided.")), | ||
}; | ||
} | ||
Ok(self) | ||
} | ||
|
||
#[cfg(feature = "waku")] | ||
pub fn update_network(mut self, network_args: NetworkArgs) -> Result<Self> { | ||
let NetworkArgs { | ||
host, | ||
port, | ||
node_key, | ||
initial_peers, | ||
} = network_args; | ||
|
||
if let Some(host) = host { | ||
self.network.backend.inner.host = Some(host); | ||
} | ||
|
||
if let Some(port) = port { | ||
self.network.backend.inner.port = Some(port); | ||
} | ||
|
||
if let Some(node_key) = node_key { | ||
use std::str::FromStr; | ||
self.network.backend.inner.node_key = Some(SecretKey::from_str(&node_key)?); | ||
} | ||
|
||
if let Some(peers) = initial_peers { | ||
self.network.backend.initial_peers = peers; | ||
} | ||
|
||
Ok(self) | ||
} | ||
|
||
#[cfg(feature = "libp2p")] | ||
pub fn update_network(mut self, network_args: NetworkArgs) -> Result<Self> { | ||
let NetworkArgs { | ||
host, | ||
port, | ||
node_key, | ||
initial_peers, | ||
} = network_args; | ||
|
||
if let Some(IpAddr::V4(h)) = host { | ||
self.network.backend.host = h; | ||
Check failure on line 217 in nodes/nomos-node/src/config.rs GitHub Actions / Check (libp2p)
Check failure on line 217 in nodes/nomos-node/src/config.rs GitHub Actions / Rust lints (libp2p)
Check failure on line 217 in nodes/nomos-node/src/config.rs GitHub Actions / Test Suite (libp2p, ubuntu-latest)
Check failure on line 217 in nodes/nomos-node/src/config.rs GitHub Actions / Test Suite (libp2p, macos-latest)
Check failure on line 217 in nodes/nomos-node/src/config.rs GitHub Actions / Test Suite (libp2p, windows-latest)
|
||
} else if host.is_some() { | ||
return Err(eyre!("Unsupported ip version")); | ||
} | ||
|
||
if let Some(port) = port { | ||
self.network.backend.port = port as u16; | ||
Check failure on line 223 in nodes/nomos-node/src/config.rs GitHub Actions / Check (libp2p)
Check failure on line 223 in nodes/nomos-node/src/config.rs GitHub Actions / Rust lints (libp2p)
Check failure on line 223 in nodes/nomos-node/src/config.rs GitHub Actions / Test Suite (libp2p, ubuntu-latest)
Check failure on line 223 in nodes/nomos-node/src/config.rs GitHub Actions / Test Suite (libp2p, macos-latest)
Check failure on line 223 in nodes/nomos-node/src/config.rs GitHub Actions / Test Suite (libp2p, windows-latest)
|
||
} | ||
|
||
if let Some(node_key) = node_key { | ||
let mut key_bytes = hex::decode(node_key)?; | ||
self.network.backend.node_key = SecretKey::try_from_bytes(key_bytes.as_mut_slice())?; | ||
Check failure on line 228 in nodes/nomos-node/src/config.rs GitHub Actions / Check (libp2p)
Check failure on line 228 in nodes/nomos-node/src/config.rs GitHub Actions / Rust lints (libp2p)
Check failure on line 228 in nodes/nomos-node/src/config.rs GitHub Actions / Test Suite (libp2p, ubuntu-latest)
Check failure on line 228 in nodes/nomos-node/src/config.rs GitHub Actions / Test Suite (libp2p, macos-latest)
Check failure on line 228 in nodes/nomos-node/src/config.rs GitHub Actions / Test Suite (libp2p, windows-latest)
|
||
} | ||
|
||
if let Some(peers) = initial_peers { | ||
self.network.backend.initial_peers = peers; | ||
Check failure on line 232 in nodes/nomos-node/src/config.rs GitHub Actions / Check (libp2p)
Check failure on line 232 in nodes/nomos-node/src/config.rs GitHub Actions / Rust lints (libp2p)
Check failure on line 232 in nodes/nomos-node/src/config.rs GitHub Actions / Test Suite (libp2p, ubuntu-latest)
Check failure on line 232 in nodes/nomos-node/src/config.rs GitHub Actions / Test Suite (libp2p, macos-latest)
Check failure on line 232 in nodes/nomos-node/src/config.rs GitHub Actions / Test Suite (libp2p, windows-latest)
|
||
} | ||
|
||
Ok(self) | ||
} | ||
|
||
pub fn update_http(mut self, http_args: HttpArgs) -> Result<Self> { | ||
let HttpArgs { | ||
http_addr, | ||
cors_origins, | ||
} = http_args; | ||
|
||
if let Some(addr) = http_addr { | ||
self.http.backend.address = addr; | ||
} | ||
|
||
if let Some(cors) = cors_origins { | ||
self.http.backend.cors_origins = cors; | ||
} | ||
|
||
Ok(self) | ||
} | ||
|
||
pub fn update_consensus(mut self, consensus_args: ConsensusArgs) -> Result<Self> { | ||
let ConsensusArgs { | ||
consensus_priv_key, | ||
consensus_timeout_secs, | ||
} = consensus_args; | ||
|
||
if let Some(private_key) = consensus_priv_key { | ||
let bytes = <[u8; 32]>::from_hex(private_key)?; | ||
self.consensus.private_key = bytes; | ||
} | ||
|
||
if let Some(timeout) = consensus_timeout_secs { | ||
let secs = timeout.parse::<u64>()?; | ||
self.consensus.timeout = Duration::from_secs(secs); | ||
} | ||
|
||
Ok(self) | ||
} | ||
|
||
pub fn update_overlay(mut self, overlay_args: OverlayArgs) -> Result<Self> { | ||
let OverlayArgs { | ||
overlay_nodes, | ||
overlay_leader_super_majority_threshold, | ||
.. | ||
} = overlay_args; | ||
|
||
if let Some(nodes) = overlay_nodes { | ||
self.consensus.overlay_settings.nodes = nodes | ||
.iter() | ||
.map(|n| { | ||
<[u8; 32]>::from_hex(n) | ||
.map_err(|e| eyre::eyre!("Failed to decode hex: {}", e)) | ||
.map(|b| b.into()) | ||
}) | ||
.collect::<Result<Vec<_>, eyre::Report>>()?; | ||
} | ||
|
||
if let Some(threshold) = overlay_leader_super_majority_threshold { | ||
self.consensus | ||
.overlay_settings | ||
.leader_super_majority_threshold = Some(threshold.into()); | ||
} | ||
|
||
Ok(self) | ||
} | ||
} |