diff --git a/crates/core/src/bin/freenet.rs b/crates/core/src/bin/freenet.rs index 6e05eb083..fe3af155a 100644 --- a/crates/core/src/bin/freenet.rs +++ b/crates/core/src/bin/freenet.rs @@ -16,6 +16,7 @@ async fn run(config: Config) -> Result<(), DynError> { } async fn run_local(config: Config) -> Result<(), DynError> { + tracing::info!("Starting freenet node in local mode"); let port = config.ws_api.port; let ip = config.ws_api.address; let executor = Executor::from_config(Arc::new(config), None).await?; @@ -25,6 +26,7 @@ async fn run_local(config: Config) -> Result<(), DynError> { } async fn run_network(config: Config) -> Result<(), DynError> { + tracing::info!("Starting freenet node in network mode"); run_network_node(config).await } @@ -32,7 +34,11 @@ fn main() -> Result<(), DynError> { freenet::config::set_logger(None); let config = ConfigArgs::parse().build()?; let rt = tokio::runtime::Builder::new_multi_thread() - .worker_threads(4) + .worker_threads( + std::thread::available_parallelism() + .map(usize::from) + .unwrap_or(1), + ) .enable_all() .build() .unwrap(); diff --git a/crates/core/src/config.rs b/crates/core/src/config.rs index b111bab2a..a1901ef30 100644 --- a/crates/core/src/config.rs +++ b/crates/core/src/config.rs @@ -9,6 +9,7 @@ use std::{ }; use directories::ProjectDirs; +use either::Either; use once_cell::sync::Lazy; use pkcs1::DecodeRsaPrivateKey; use serde::{Deserialize, Serialize}; @@ -101,7 +102,7 @@ impl ConfigArgs { fn read_config(dir: &PathBuf) -> std::io::Result> { if dir.exists() { let mut read_dir = std::fs::read_dir(dir)?; - let config_args = read_dir.find_map(|f| { + let config_args: Option<(String, String)> = read_dir.find_map(|f| { if let Ok(f) = f { let filename = f.file_name().to_string_lossy().into_owned(); let ext = filename.rsplit('.').next().map(|s| s.to_owned()); @@ -203,8 +204,20 @@ impl ConfigArgs { Self::read_config(path)? } else { // find default application dir to see if there is a config file - let dir = ConfigPathsArgs::config_dir(self.id.as_deref())?; - Self::read_config(&dir).ok().flatten() + let (config, data) = { + match ConfigPathsArgs::default_dirs(self.id.as_deref())? { + Either::Left(defaults) => ( + defaults.config_local_dir().to_path_buf(), + defaults.data_local_dir().to_path_buf(), + ), + Either::Right(dir) => (dir.clone(), dir), + } + }; + self.config_paths.config_dir = Some(config.clone()); + if self.config_paths.data_dir.is_none() { + self.config_paths.data_dir = Some(data); + } + Self::read_config(&config).ok().flatten() }; let should_persist = cfg.is_none(); @@ -232,22 +245,7 @@ impl ConfigArgs { (transport_key_path, transport_key) } else { let transport_key = TransportKeypair::new(); - let transport_key_path = - config_paths.secrets_dir(mode).join("transport_keypair.pem"); - - // if the transport key file exists, then read it - if transport_key_path.exists() { - Self::read_transport_keypair(transport_key_path)? - } else { - let mut file = File::create(&transport_key_path)?; - file.write_all(&transport_key.secret().to_bytes().map_err(|e| { - std::io::Error::new( - std::io::ErrorKind::InvalidData, - format!("failed to write transport key: {e}"), - ) - })?)?; - (transport_key_path, transport_key) - } + (PathBuf::new(), transport_key) }; let peer_id = self @@ -257,8 +255,8 @@ impl ConfigArgs { .map(|(addr, port)| { PeerId::new((addr, port).into(), transport_keypair.public().clone()) }); - let gateways = config_paths.config_dir.join("gateways.toml"); - let gateways = match File::open(&*gateways) { + let gateways_file = config_paths.config_dir.join("gateways.toml"); + let gateways = match File::open(&*gateways_file) { Ok(mut file) => { let mut content = String::new(); file.read_to_string(&mut content)?; @@ -272,7 +270,7 @@ impl ConfigArgs { #[cfg(not(any(test, debug_assertions)))] { if peer_id.is_none() { - tracing::error!("Failed to read gateways file: {err}"); + tracing::error!(file = ?gateways_file, "Failed to read gateways file: {err}"); return Err(std::io::Error::new( std::io::ErrorKind::NotFound, "Cannot initialize node without gateways", @@ -315,6 +313,7 @@ impl ConfigArgs { fs::create_dir_all(this.config_dir())?; if should_persist { let mut file = File::create(this.config_dir().join("config.toml"))?; + tracing::info!("Persisting configuration to {:?}", file); file.write_all( toml::to_string(&this) .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))? @@ -576,44 +575,34 @@ impl ConfigPathsArgs { self.data_dir.get_or_insert(other.data_dir); } - pub fn app_data_dir(id: Option<&str>) -> std::io::Result { - let project_dir = ProjectDirs::from(QUALIFIER, ORGANIZATION, APPLICATION) - .ok_or(std::io::ErrorKind::NotFound)?; + fn default_dirs(id: Option<&str>) -> std::io::Result> { // if id is set, most likely we are running tests or in simulated mode - let app_data_dir: PathBuf = if cfg!(any(test, debug_assertions)) || id.is_some() { - std::env::temp_dir().join(if let Some(id) = id { + let default_dir: Either<_, _> = if cfg!(any(test, debug_assertions)) || id.is_some() { + Either::Right(std::env::temp_dir().join(if let Some(id) = id { format!("freenet-{id}") } else { "freenet".into() - }) + })) } else { - project_dir.data_dir().into() - }; - Ok(app_data_dir) - } - - pub fn config_dir(id: Option<&str>) -> std::io::Result { - let project_dir = ProjectDirs::from(QUALIFIER, ORGANIZATION, APPLICATION) - .ok_or(std::io::ErrorKind::NotFound)?; - let config_data_dir: PathBuf = if cfg!(any(test, debug_assertions)) || id.is_some() { - std::env::temp_dir() - .join(if let Some(id) = id { - format!("freenet-{id}") - } else { - "freenet".into() - }) - .join("config") - } else { - project_dir.config_dir().into() + Either::Left( + ProjectDirs::from(QUALIFIER, ORGANIZATION, APPLICATION) + .ok_or(std::io::ErrorKind::NotFound)?, + ) }; - Ok(config_data_dir) + Ok(default_dir) } pub fn build(self, id: Option<&str>) -> std::io::Result { let app_data_dir = self .data_dir - .map(Ok) - .unwrap_or_else(|| Self::app_data_dir(id))?; + .map(Ok::<_, std::io::Error>) + .unwrap_or_else(|| { + let default_dirs = Self::default_dirs(id)?; + let Either::Left(defaults) = default_dirs else { + unreachable!() + }; + Ok(defaults.data_dir().to_path_buf()) + })?; let contracts_dir = self .contracts_dir .unwrap_or_else(|| app_data_dir.join("contracts")); @@ -653,6 +642,17 @@ impl ConfigPathsArgs { fs::write(local_file, [])?; } + let config_dir = self + .config_dir + .map(Ok::<_, std::io::Error>) + .unwrap_or_else(|| { + let default_dirs = Self::default_dirs(id)?; + let Either::Left(defaults) = default_dirs else { + unreachable!() + }; + Ok(defaults.config_dir().to_path_buf()) + })?; + Ok(ConfigPaths { contracts_dir, delegates_dir, @@ -660,10 +660,7 @@ impl ConfigPathsArgs { db_dir, data_dir: app_data_dir, event_log, - config_dir: match self.config_dir { - Some(dir) => dir, - None => Self::config_dir(id)?, - }, + config_dir, }) } } diff --git a/crates/core/src/contract/executor.rs b/crates/core/src/contract/executor.rs index 4e434f85e..8ed0e5289 100644 --- a/crates/core/src/contract/executor.rs +++ b/crates/core/src/contract/executor.rs @@ -171,6 +171,15 @@ pub enum OperationMode { Network, } +impl Display for OperationMode { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + OperationMode::Local => write!(f, "local"), + OperationMode::Network => write!(f, "network"), + } + } +} + pub struct ExecutorToEventLoopChannel { op_manager: Arc, end: End, diff --git a/crates/core/src/contract/executor/runtime.rs b/crates/core/src/contract/executor/runtime.rs index 7eb180e1e..949be4866 100644 --- a/crates/core/src/contract/executor/runtime.rs +++ b/crates/core/src/contract/executor/runtime.rs @@ -160,7 +160,6 @@ impl Executor { Executor::new( state_store, move || { - // FIXME: potentially not cleaning up after exit crate::util::set_cleanup_on_exit(config.paths().clone())?; Ok(()) }, diff --git a/crates/core/src/node.rs b/crates/core/src/node.rs index 92eea4e52..c7565e43a 100644 --- a/crates/core/src/node.rs +++ b/crates/core/src/node.rs @@ -83,6 +83,7 @@ impl Node { /// If both are provided but also additional peers are added via the [`Self::add_gateway()`] method, this node will /// be listening but also try to connect to an existing peer. #[derive(Serialize, Deserialize, Clone, Debug)] +#[non_exhaustive] // avoid directly instantiating this struct pub struct NodeConfig { /// Determines if an initial connection should be attempted. /// Only true for an initial gateway/node. If false, the gateway will be disconnected unless other peers connect through it. @@ -112,6 +113,7 @@ pub struct NodeConfig { impl NodeConfig { pub async fn new(config: Config) -> anyhow::Result { + tracing::info!("Loading node configuration for mode {}", config.mode); let mut gateways = Vec::with_capacity(config.gateways.len()); for gw in &config.gateways { let GatewayConfig {