Skip to content

Commit

Permalink
refactor: update error management and config/process (#460)
Browse files Browse the repository at this point in the history
  • Loading branch information
Freyskeyd committed Mar 5, 2024
1 parent b2e4cf8 commit cc0c7b5
Show file tree
Hide file tree
Showing 7 changed files with 182 additions and 98 deletions.
18 changes: 14 additions & 4 deletions crates/topos-config/src/genesis/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,34 @@ use topos_core::types::ValidatorId;
use topos_p2p::{Multiaddr, PeerId};
use tracing::info;

use crate::node::NodeConfig;

#[cfg(test)]
pub(crate) mod tests;

/// From the Edge format
pub struct Genesis {
pub path: PathBuf,
pub json: Value,
}

#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Failed to parse validators")]
ParseValidators,

#[error("Invalid genesis file on path {0}: {1}")]
InvalidGenesisFile(String, String),
}

impl Genesis {
pub fn new(path: PathBuf) -> Result<Self, Error> {
pub fn new(path: &PathBuf) -> Result<Self, Error> {
info!("Reading subnet genesis file {}", path.display());
let genesis_file = fs::File::open(&path)
let genesis_file = fs::File::open(path)
.map_err(|e| Error::InvalidGenesisFile(path.display().to_string(), e.to_string()))?;

let json: Value = serde_json::from_reader(genesis_file).expect("genesis json parsed");

Ok(Self { path, json })
Ok(Self { json })
}

// TODO: parse directly with serde
Expand Down Expand Up @@ -103,3 +105,11 @@ impl Genesis {
)
}
}

impl TryFrom<&NodeConfig> for Genesis {
type Error = Error;

fn try_from(config: &NodeConfig) -> Result<Self, Self::Error> {
Genesis::new(&config.edge_path)
}
}
2 changes: 1 addition & 1 deletion crates/topos-config/src/genesis/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ macro_rules! test_case {
#[fixture]
#[once]
pub fn genesis() -> Genesis {
Genesis::new(test_case!("genesis-example.json").into())
Genesis::new(&test_case!("genesis-example.json").into())
.expect("Expected valid test genesis file")
}

Expand Down
83 changes: 76 additions & 7 deletions crates/topos-config/src/node.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use std::path::Path;
use std::path::{Path, PathBuf};

use figment::{
providers::{Format, Toml},
Figment,
};

use serde::{Deserialize, Serialize};
use topos_wallet::SecretManager;
use tracing::{debug, error};

use crate::{
base::BaseConfig, edge::EdgeConfig, load_config, sequencer::SequencerConfig, tce::TceConfig,
Expand All @@ -26,28 +28,86 @@ pub struct NodeConfig {
pub tce: Option<TceConfig>,
pub sequencer: Option<SequencerConfig>,
pub edge: Option<EdgeConfig>,

#[serde(skip)]
pub home_path: PathBuf,

#[serde(skip)]
pub node_path: PathBuf,

#[serde(skip)]
pub edge_path: PathBuf,
}

impl NodeConfig {
pub fn new<S: Serialize>(home: &Path, config: Option<S>) -> Self {
let base = load_config::<BaseConfig, _>(home, config);
/// Try to create a new node config struct from the given home path and node name.
/// It expects a config file to be present in the node's folder.
///
/// This `config.toml` can be generated using: `topos node init` command
pub fn try_from<S: Serialize>(
home_path: &Path,
node_name: &str,
config: Option<S>,
) -> Result<Self, std::io::Error> {
let node_path = home_path.join("node").join(node_name);
let config_path = node_path.join("config.toml");

// TODO: Move this to `topos-node` when migrated
if !Path::new(&config_path).exists() {
error!(
"Please run 'topos node init --name {node_name}' to create a config file first \
for {node_name}."
);
std::process::exit(1);
}

Ok(Self::build_config(node_path, home_path, config))
}

/// Create a new node config struct from the given home path and node name.
///
/// It doesn't check the existence of the config file.
/// It's useful for creating a config file for a new node, relying on the default values.
pub fn create<S: Serialize>(home_path: &Path, node_name: &str, config: Option<S>) -> Self {
let node_path = home_path.join("node").join(node_name);

Self::build_config(node_path, home_path, config)
}

/// Common function to build a node config struct from the given home path and node name.
fn build_config<S: Serialize>(node_path: PathBuf, home_path: &Path, config: Option<S>) -> Self {
let node_folder = node_path.as_path();
let base = load_config::<BaseConfig, _>(node_folder, config);

// Load genesis pointed by the local config
let edge_path = home_path
.join("subnet")
.join(base.subnet.clone())
.join("genesis.json");

let mut config = NodeConfig {
node_path: node_path.to_path_buf(),
edge_path,
home_path: home_path.to_path_buf(),
base: base.clone(),
sequencer: base
.need_sequencer()
.then(|| load_config::<SequencerConfig, ()>(home, None)),
.then(|| load_config::<SequencerConfig, ()>(node_folder, None)),
tce: base
.need_tce()
.then(|| load_config::<TceConfig, ()>(home, None)),
.then(|| load_config::<TceConfig, ()>(node_folder, None)),
edge: base
.need_edge()
.then(|| load_config::<EdgeConfig, ()>(home, None)),
.then(|| load_config::<EdgeConfig, ()>(node_folder, None)),
};

// Make the TCE DB path relative to the folder
if let Some(config) = config.tce.as_mut() {
config.db_path = home.join(&config.db_path);
config.db_path = node_folder.join(&config.db_path);
debug!(
"Maked TCE DB path relative to the node folder -> {:?}",
config.db_path
);
}

config
Expand All @@ -71,3 +131,12 @@ impl Config for NodeConfig {
"default".to_string()
}
}

impl From<&NodeConfig> for SecretManager {
fn from(val: &NodeConfig) -> Self {
match val.base.secrets_config.as_ref() {
Some(secrets_config) => SecretManager::from_aws(secrets_config),
None => SecretManager::from_fs(val.node_path.clone()),
}
}
}
Loading

0 comments on commit cc0c7b5

Please sign in to comment.