Skip to content

Commit

Permalink
Order-independent configuration for TOML serde (#1743)
Browse files Browse the repository at this point in the history
* most changes

* fix header

* lint fixes

* fixes

* renaming to client

* fmt

* clippy

* fmt
  • Loading branch information
tyshko5 authored Aug 2, 2022
1 parent c337825 commit 961ac23
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 92 deletions.
4 changes: 2 additions & 2 deletions forest/src/cli/auth_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ impl AuthCommands {
match auth_new((perms,)).await {
Ok(token) => {
let mut addr = Multiaddr::empty();
addr.push(cfg.rpc_address.ip().into());
addr.push(Protocol::Tcp(cfg.rpc_address.port()));
addr.push(cfg.client.rpc_address.ip().into());
addr.push(Protocol::Tcp(cfg.client.rpc_address.port()));
addr.push(Protocol::Http);
println!(
"FULLNODE_API_INFO=\"{}:{}\"",
Expand Down
54 changes: 54 additions & 0 deletions forest/src/cli/client.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2019-2022 ChainSafe Systems
// SPDX-License-Identifier: Apache-2.0, MIT

use directories::ProjectDirs;
use rpc_client::DEFAULT_PORT;
use serde::{Deserialize, Serialize};
use std::{
net::{IpAddr, Ipv4Addr, SocketAddr},
path::PathBuf,
str::FromStr,
};

#[derive(Serialize, Deserialize, PartialEq)]
#[serde(default)]
pub struct Client {
pub data_dir: PathBuf,
pub genesis_file: Option<String>,
pub enable_rpc: bool,
pub rpc_port: u16,
pub rpc_token: Option<String>,
/// If this is true, then we do not validate the imported snapshot.
/// Otherwise, we validate and compute the states.
pub snapshot: bool,
pub snapshot_height: Option<i64>,
pub snapshot_path: Option<String>,
/// Skips loading import CAR file and assumes it's already been loaded.
/// Will use the cids in the header of the file to index the chain.
pub skip_load: bool,
pub encrypt_keystore: bool,
/// Metrics bind, e.g. 127.0.0.1:6116
pub metrics_address: SocketAddr,
/// RPC bind, e.g. 127.0.0.1:1234
pub rpc_address: SocketAddr,
}

impl Default for Client {
fn default() -> Self {
let dir = ProjectDirs::from("com", "ChainSafe", "Forest").expect("failed to find project directories, please set FOREST_CONFIG_PATH environment variable manually.");
Self {
data_dir: dir.data_dir().to_path_buf(),
genesis_file: None,
enable_rpc: true,
rpc_port: DEFAULT_PORT,
rpc_token: None,
snapshot_path: None,
snapshot: false,
snapshot_height: None,
skip_load: false,
encrypt_keystore: true,
metrics_address: FromStr::from_str("127.0.0.1:6116").unwrap(),
rpc_address: SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), DEFAULT_PORT),
}
}
}
49 changes: 4 additions & 45 deletions forest/src/cli/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,60 +2,19 @@
// SPDX-License-Identifier: Apache-2.0, MIT

use chain_sync::SyncConfig;
use directories::ProjectDirs;
use forest_libp2p::Libp2pConfig;
use networks::ChainConfig;
use rpc_client::DEFAULT_PORT;
use serde::{Deserialize, Serialize};
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::path::PathBuf;
use std::sync::Arc;

#[derive(Serialize, Deserialize, PartialEq)]
use super::client::Client;

#[derive(Serialize, Deserialize, PartialEq, Default)]
#[serde(default)]
pub struct Config {
pub data_dir: PathBuf,
pub genesis_file: Option<String>,
pub enable_rpc: bool,
pub rpc_token: Option<String>,
/// If this is true, then we do not validate the imported snapshot.
/// Otherwise, we validate and compute the states.
pub snapshot: bool,
pub snapshot_height: Option<i64>,
pub snapshot_path: Option<String>,
/// Skips loading import CAR file and assumes it's already been loaded.
/// Will use the cids in the header of the file to index the chain.
pub skip_load: bool,
pub encrypt_keystore: bool,
/// Metrics bind, e.g. 127.0.0.1:6116
pub metrics_address: SocketAddr,
/// RPC bind, e.g. 127.0.0.1:1234
pub rpc_address: SocketAddr,
pub client: Client,
pub rocks_db: forest_db::rocks_config::RocksDbConfig,
pub network: Libp2pConfig,
pub sync: SyncConfig,
pub chain: Arc<ChainConfig>,
}

impl Default for Config {
fn default() -> Self {
let dir = ProjectDirs::from("com", "ChainSafe", "Forest").expect("failed to find project directories, please set FOREST_CONFIG_PATH environment variable manually.");
Self {
network: Libp2pConfig::default(),
data_dir: dir.data_dir().to_path_buf(),
genesis_file: None,
enable_rpc: true,
rpc_token: None,
snapshot_path: None,
snapshot: false,
snapshot_height: None,
skip_load: false,
sync: SyncConfig::default(),
encrypt_keystore: true,
metrics_address: SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 6116),
rpc_address: SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), DEFAULT_PORT),
rocks_db: forest_db::rocks_config::RocksDbConfig::default(),
chain: Arc::default(),
}
}
}
2 changes: 1 addition & 1 deletion forest/src/cli/fetch_params_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ impl FetchCommands {
panic!("Sector size option must be chosen. Choose between --all, --keys, or <size>");
};

get_params_default(&config.data_dir, sizes, self.verbose)
get_params_default(&config.client.data_dir, sizes, self.verbose)
.await
.unwrap();
}
Expand Down
30 changes: 16 additions & 14 deletions forest/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

mod auth_cmd;
mod chain_cmd;
mod client;
mod config;
mod config_cmd;
mod fetch_params_cmd;
Expand All @@ -15,6 +16,7 @@ mod wallet_cmd;

pub(super) use self::auth_cmd::AuthCommands;
pub(super) use self::chain_cmd::ChainCommands;
pub use self::client::Client;
pub use self::config::Config;
pub(super) use self::fetch_params_cmd::FetchCommands;
pub(super) use self::genesis_cmd::GenesisCommands;
Expand Down Expand Up @@ -186,37 +188,37 @@ impl CliOpts {
}

if let Some(genesis_file) = &self.genesis {
cfg.genesis_file = Some(genesis_file.to_owned());
cfg.client.genesis_file = Some(genesis_file.to_owned());
}
if self.rpc.unwrap_or(cfg.enable_rpc) {
cfg.enable_rpc = true;
if self.rpc.unwrap_or(cfg.client.enable_rpc) {
cfg.client.enable_rpc = true;
if let Some(rpc_address) = self.rpc_address {
cfg.rpc_address = rpc_address;
cfg.client.rpc_address = rpc_address;
}

if self.token.is_some() {
cfg.rpc_token = self.token.to_owned();
cfg.client.rpc_token = self.token.to_owned();
}
} else {
cfg.enable_rpc = false;
cfg.client.enable_rpc = false;
}
if let Some(metrics_address) = self.metrics_address {
cfg.metrics_address = metrics_address;
cfg.client.metrics_address = metrics_address;
}
if self.import_snapshot.is_some() && self.import_chain.is_some() {
panic!("Can't set import_snapshot and import_chain at the same time!");
} else {
if let Some(snapshot_path) = &self.import_snapshot {
cfg.snapshot_path = Some(snapshot_path.to_owned());
cfg.snapshot = true;
cfg.client.snapshot_path = Some(snapshot_path.to_owned());
cfg.client.snapshot = true;
}
if let Some(snapshot_path) = &self.import_chain {
cfg.snapshot_path = Some(snapshot_path.to_owned());
cfg.snapshot = false;
cfg.client.snapshot_path = Some(snapshot_path.to_owned());
cfg.client.snapshot = false;
}
cfg.snapshot_height = self.height;
cfg.client.snapshot_height = self.height;

cfg.skip_load = self.skip_load;
cfg.client.skip_load = self.skip_load;
}

cfg.network.kademlia = self.kademlia.unwrap_or(cfg.network.kademlia);
Expand All @@ -235,7 +237,7 @@ impl CliOpts {
cfg.sync.tipset_sample_size = tipset_sample_size.into();
}
if let Some(encrypt_keystore) = self.encrypt_keystore {
cfg.encrypt_keystore = encrypt_keystore;
cfg.client.encrypt_keystore = encrypt_keystore;
}

Ok(cfg)
Expand Down
57 changes: 35 additions & 22 deletions forest/src/daemon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub(super) async fn start(config: Config) {
option_env!("FOREST_VERSION").unwrap_or(env!("CARGO_PKG_VERSION"))
);

let path: PathBuf = config.data_dir.join("libp2p");
let path: PathBuf = config.client.data_dir.join("libp2p");
let net_keypair = get_keypair(&path.join("keypair")).unwrap_or_else(|| {
// Keypair not found, generate and save generated keypair
let gen_keypair = ed25519::Keypair::generate();
Expand All @@ -59,14 +59,14 @@ pub(super) async fn start(config: Config) {
Keypair::Ed25519(gen_keypair)
});

let mut ks = if config.encrypt_keystore {
let mut ks = if config.client.encrypt_keystore {
loop {
print!("Enter the keystore passphrase: ");
std::io::stdout().flush().unwrap();

let passphrase = read_password().expect("Error reading passphrase");

let data_dir = PathBuf::from(&config.data_dir).join(ENCRYPTED_KEYSTORE_NAME);
let data_dir = PathBuf::from(&config.client.data_dir).join(ENCRYPTED_KEYSTORE_NAME);
if !data_dir.exists() {
print!("Confirm passphrase: ");
std::io::stdout().flush().unwrap();
Expand All @@ -78,7 +78,7 @@ pub(super) async fn start(config: Config) {
}

let key_store_init_result = KeyStore::new(KeyStoreConfig::Encrypted(
PathBuf::from(&config.data_dir),
PathBuf::from(&config.client.data_dir),
passphrase,
));

Expand All @@ -91,8 +91,10 @@ pub(super) async fn start(config: Config) {
}
} else {
warn!("Warning: Keystore encryption disabled!");
KeyStore::new(KeyStoreConfig::Persistent(PathBuf::from(&config.data_dir)))
.expect("Error initializing keystore")
KeyStore::new(KeyStoreConfig::Persistent(PathBuf::from(
&config.client.data_dir,
)))
.expect("Error initializing keystore")
};

if ks.get(JWT_IDENTIFIER).is_err() {
Expand All @@ -101,12 +103,18 @@ pub(super) async fn start(config: Config) {
}

// Start Prometheus server port
let prometheus_listener = TcpListener::bind(config.metrics_address)
let prometheus_listener = TcpListener::bind(config.client.metrics_address)
.await
.unwrap_or_else(|_| {
cli_error_and_die(format!("could not bind to {}", config.metrics_address), 1)
cli_error_and_die(
format!("could not bind to {}", config.client.metrics_address),
1,
)
});
info!("Prometheus server started at {}", config.metrics_address);
info!(
"Prometheus server started at {}",
config.client.metrics_address
);
let prometheus_server_task = task::spawn(metrics::init_prometheus(
prometheus_listener,
db_path(&config)
Expand Down Expand Up @@ -135,7 +143,7 @@ pub(super) async fn start(config: Config) {
// Read Genesis file
// * When snapshot command implemented, this genesis does not need to be initialized
let genesis = read_genesis_header(
config.genesis_file.as_ref(),
config.client.genesis_file.as_ref(),
config.chain.genesis_bytes(),
&chain_store,
)
Expand Down Expand Up @@ -181,9 +189,9 @@ pub(super) async fn start(config: Config) {
#[cfg(all(feature = "fil_cns", not(any(feature = "deleg_cns"))))]
{
use paramfetch::{get_params_default, set_proofs_parameter_cache_dir_env, SectorSizeOpt};
set_proofs_parameter_cache_dir_env(&config.data_dir);
set_proofs_parameter_cache_dir_env(&config.client.data_dir);

get_params_default(&config.data_dir, SectorSizeOpt::Keys, false)
get_params_default(&config.client.data_dir, SectorSizeOpt::Keys, false)
.await
.unwrap();
}
Expand Down Expand Up @@ -299,14 +307,14 @@ pub(super) async fn start(config: Config) {
let p2p_task = task::spawn(async {
p2p_service.run().await;
});
let rpc_task = if config.enable_rpc {
let rpc_task = if config.client.enable_rpc {
let keystore_rpc = Arc::clone(&keystore);
let rpc_listen = TcpListener::bind(&config.rpc_address)
let rpc_listen = TcpListener::bind(&config.client.rpc_address)
.await
.unwrap_or_else(|_| cli_error_and_die("could not bind to {rpc_address}", 1));

Some(task::spawn(async move {
info!("JSON-RPC endpoint started at {}", config.rpc_address);
info!("JSON-RPC endpoint started at {}", config.client.rpc_address);
start_rpc::<_, _, FullVerifier, FullConsensus>(
Arc::new(RPCState {
state_manager: Arc::clone(&state_manager),
Expand Down Expand Up @@ -348,16 +356,21 @@ pub(super) async fn start(config: Config) {
}

async fn sync_from_snapshot(config: &Config, state_manager: &Arc<StateManager<RocksDb>>) {
if let Some(path) = &config.snapshot_path {
if let Some(path) = &config.client.snapshot_path {
let stopwatch = time::Instant::now();
let validate_height = if config.snapshot {
config.snapshot_height
let validate_height = if config.client.snapshot {
config.client.snapshot_height
} else {
Some(0)
};
import_chain::<FullVerifier, _>(state_manager, path, validate_height, config.skip_load)
.await
.expect("Failed miserably while importing chain from snapshot");
import_chain::<FullVerifier, _>(
state_manager,
path,
validate_height,
config.client.skip_load,
)
.await
.expect("Failed miserably while importing chain from snapshot");
debug!("Imported snapshot in: {}s", stopwatch.elapsed().as_secs());
}
}
Expand All @@ -373,7 +386,7 @@ fn db_path(config: &Config) -> PathBuf {
}

fn chain_path(config: &Config) -> PathBuf {
PathBuf::from(&config.data_dir).join(&config.chain.name)
PathBuf::from(&config.client.data_dir).join(&config.chain.name)
}

#[cfg(test)]
Expand Down
Loading

0 comments on commit 961ac23

Please sign in to comment.