Update account manager config parsing

This commit is contained in:
Paul Hauner 2019-06-09 04:34:56 -04:00
parent 3487b16ce5
commit ab12787610
No known key found for this signature in database
GPG Key ID: 303E4494BB28068C
12 changed files with 66 additions and 96 deletions
account_manager
beacon_node
eth2
state_processing/src
per_block_processing
per_epoch_processing
types/src
utils/eth2_config/src
validator_client

View File

@ -12,3 +12,4 @@ slog-term = "^2.4.0"
slog-async = "^2.3.0" slog-async = "^2.3.0"
validator_client = { path = "../validator_client" } validator_client = { path = "../validator_client" }
types = { path = "../eth2/types" } types = { path = "../eth2/types" }
eth2_config = { path = "../eth2/utils/eth2_config" }

View File

@ -1,9 +1,13 @@
use bls::Keypair; use bls::Keypair;
use clap::{App, Arg, SubCommand}; use clap::{App, Arg, SubCommand};
use slog::{debug, info, o, Drain}; use slog::{crit, debug, info, o, Drain};
use std::path::PathBuf; use std::path::PathBuf;
use types::test_utils::generate_deterministic_keypair; use types::test_utils::generate_deterministic_keypair;
use validator_client::Config as ValidatorClientConfig; use validator_client::Config as ValidatorClientConfig;
use eth2_config::{get_data_dir};
pub const DEFAULT_DATA_DIR: &str = ".lighthouse-account-manager";
pub const CLIENT_CONFIG_FILENAME: &str = "account-manager-config.toml";
fn main() { fn main() {
// Logging // Logging
@ -20,6 +24,7 @@ fn main() {
.arg( .arg(
Arg::with_name("datadir") Arg::with_name("datadir")
.long("datadir") .long("datadir")
.short("d")
.value_name("DIR") .value_name("DIR")
.help("Data directory for keys and databases.") .help("Data directory for keys and databases.")
.takes_value(true), .takes_value(true),
@ -52,19 +57,43 @@ fn main() {
.help("If supplied along with `index`, generates keys `i..i + n`.") .help("If supplied along with `index`, generates keys `i..i + n`.")
.takes_value(true) .takes_value(true)
.default_value("1"), .default_value("1"),
), )
) )
.get_matches(); .get_matches();
let config = ValidatorClientConfig::parse_args(&matches, &log) let data_dir = match get_data_dir(&matches, PathBuf::from(DEFAULT_DATA_DIR)) {
.expect("Unable to build a configuration for the account manager."); Ok(dir) => dir,
Err(e) => {
crit!(log, "Failed to initialize data dir"; "error" => format!("{:?}", e));
return
}
};
let mut client_config = ValidatorClientConfig::default();
if let Err(e) = client_config.apply_cli_args(&matches) {
crit!(log, "Failed to apply CLI args"; "error" => format!("{:?}", e));
return
};
// Ensure the `data_dir` in the config matches that supplied to the CLI.
client_config.data_dir = data_dir.clone();
// Update the client config with any CLI args.
match client_config.apply_cli_args(&matches) {
Ok(()) => (),
Err(s) => {
crit!(log, "Failed to parse ClientConfig CLI arguments"; "error" => s);
return;
}
};
// Log configuration // Log configuration
info!(log, ""; info!(log, "";
"data_dir" => &config.data_dir.to_str()); "data_dir" => &client_config.data_dir.to_str());
match matches.subcommand() { match matches.subcommand() {
("generate", Some(_)) => generate_random(&config, &log), ("generate", Some(_)) => generate_random(&client_config, &log),
("generate_deterministic", Some(m)) => { ("generate_deterministic", Some(m)) => {
if let Some(string) = m.value_of("validator index") { if let Some(string) = m.value_of("validator index") {
let i: usize = string.parse().expect("Invalid validator index"); let i: usize = string.parse().expect("Invalid validator index");
@ -72,9 +101,9 @@ fn main() {
let n: usize = string.parse().expect("Invalid end validator count"); let n: usize = string.parse().expect("Invalid end validator count");
let indices: Vec<usize> = (i..i + n).collect(); let indices: Vec<usize> = (i..i + n).collect();
generate_deterministic_multiple(&indices, &config, &log) generate_deterministic_multiple(&indices, &client_config, &log)
} else { } else {
generate_deterministic(i, &config, &log) generate_deterministic(i, &client_config, &log)
} }
} }
} }

View File

@ -5,7 +5,6 @@ authors = ["Paul Hauner <paul@paulhauner.com>", "Age Manning <Age@AgeManning.com
edition = "2018" edition = "2018"
[dependencies] [dependencies]
dirs = "1.0.3"
eth2_config = { path = "../eth2/utils/eth2_config" } eth2_config = { path = "../eth2/utils/eth2_config" }
types = { path = "../eth2/types" } types = { path = "../eth2/types" }
toml = "^0.5" toml = "^0.5"

View File

@ -4,7 +4,7 @@ mod run;
use clap::{App, Arg, ArgMatches}; use clap::{App, Arg, ArgMatches};
use client::{ClientConfig, Eth2Config}; use client::{ClientConfig, Eth2Config};
use eth2_config::{read_from_file, write_to_file}; use eth2_config::{get_data_dir, read_from_file, write_to_file};
use slog::{crit, o, Drain}; use slog::{crit, o, Drain};
use std::fs; use std::fs;
use std::path::PathBuf; use std::path::PathBuf;
@ -199,15 +199,3 @@ fn main() {
Err(e) => crit!(logger, "Beacon node failed to start"; "reason" => format!("{:}", e)), Err(e) => crit!(logger, "Beacon node failed to start"; "reason" => format!("{:}", e)),
} }
} }
fn get_data_dir(args: &ArgMatches) -> Result<PathBuf, &'static str> {
if let Some(data_dir) = args.value_of("data_dir") {
Ok(PathBuf::from(data_dir))
} else {
let path = dirs::home_dir()
.ok_or_else(|| "Unable to locate home directory")?
.join(&DEFAULT_DATA_DIR);
fs::create_dir_all(&path).map_err(|_| "Unable to create data_dir")?;
Ok(path)
}
}

View File

@ -22,7 +22,7 @@ impl<T: EthSpec> BlockProcessingBuilder<T> {
} }
} }
pub fn set_slot(&mut self, slot: Slot, spec: &ChainSpec) { pub fn set_slot(&mut self, slot: Slot) {
self.state_builder.teleport_to_slot(slot); self.state_builder.teleport_to_slot(slot);
} }

View File

@ -223,7 +223,7 @@ impl ValidatorStatuses {
if is_from_epoch(a, state.current_epoch()) { if is_from_epoch(a, state.current_epoch()) {
status.is_current_epoch_attester = true; status.is_current_epoch_attester = true;
if target_matches_epoch_start_block(a, state, state.current_epoch(), spec)? { if target_matches_epoch_start_block(a, state, state.current_epoch())? {
status.is_current_epoch_target_attester = true; status.is_current_epoch_target_attester = true;
} }
} else if is_from_epoch(a, state.previous_epoch()) { } else if is_from_epoch(a, state.previous_epoch()) {
@ -244,7 +244,7 @@ impl ValidatorStatuses {
)?, )?,
}); });
if target_matches_epoch_start_block(a, state, state.previous_epoch(), spec)? { if target_matches_epoch_start_block(a, state, state.previous_epoch())? {
status.is_previous_epoch_target_attester = true; status.is_previous_epoch_target_attester = true;
} }
@ -336,7 +336,6 @@ fn target_matches_epoch_start_block<T: EthSpec>(
a: &PendingAttestation, a: &PendingAttestation,
state: &BeaconState<T>, state: &BeaconState<T>,
epoch: Epoch, epoch: Epoch,
spec: &ChainSpec,
) -> Result<bool, BeaconStateError> { ) -> Result<bool, BeaconStateError> {
let slot = epoch.start_slot(T::slots_per_epoch()); let slot = epoch.start_slot(T::slots_per_epoch());
let state_boundary_root = *state.get_block_root(slot)?; let state_boundary_root = *state.get_block_root(slot)?;

View File

@ -453,11 +453,7 @@ impl<T: EthSpec> BeaconState<T> {
/// ///
/// Spec v0.6.0 /// Spec v0.6.0
// FIXME(sproul): name swap with get_block_root // FIXME(sproul): name swap with get_block_root
pub fn get_block_root_at_epoch( pub fn get_block_root_at_epoch(&self, epoch: Epoch) -> Result<&Hash256, BeaconStateError> {
&self,
epoch: Epoch,
spec: &ChainSpec,
) -> Result<&Hash256, BeaconStateError> {
self.get_block_root(epoch.start_slot(T::slots_per_epoch())) self.get_block_root(epoch.start_slot(T::slots_per_epoch()))
} }

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
test_utils::{fork_from_hex_str, TestRandom}, test_utils::{fork_from_hex_str, TestRandom},
ChainSpec, Epoch, Epoch,
}; };
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
@ -58,6 +58,7 @@ impl Fork {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::ChainSpec;
ssz_tests!(Fork); ssz_tests!(Fork);
cached_tree_hash_tests!(Fork); cached_tree_hash_tests!(Fork);

View File

@ -1,5 +1,6 @@
use clap::ArgMatches; use clap::ArgMatches;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use std::fs;
use std::fs::File; use std::fs::File;
use std::io::prelude::*; use std::io::prelude::*;
use std::path::PathBuf; use std::path::PathBuf;
@ -104,3 +105,15 @@ where
Ok(None) Ok(None)
} }
} }
pub fn get_data_dir(args: &ArgMatches, default_data_dir: PathBuf) -> Result<PathBuf, &'static str> {
if let Some(data_dir) = args.value_of("data_dir") {
Ok(PathBuf::from(data_dir))
} else {
let path = dirs::home_dir()
.ok_or_else(|| "Unable to locate home directory")?
.join(&default_data_dir);
fs::create_dir_all(&path).map_err(|_| "Unable to create data_dir")?;
Ok(path)
}
}

View File

@ -18,7 +18,6 @@ ssz = { path = "../eth2/utils/ssz" }
eth2_config = { path = "../eth2/utils/eth2_config" } eth2_config = { path = "../eth2/utils/eth2_config" }
tree_hash = { path = "../eth2/utils/tree_hash" } tree_hash = { path = "../eth2/utils/tree_hash" }
clap = "2.32.0" clap = "2.32.0"
dirs = "1.0.3"
grpcio = { version = "0.4", default-features = false, features = ["protobuf-codec"] } grpcio = { version = "0.4", default-features = false, features = ["protobuf-codec"] }
protobuf = "2.0.2" protobuf = "2.0.2"
protos = { path = "../protos" } protos = { path = "../protos" }

View File

@ -48,48 +48,8 @@ impl Config {
}; };
Ok(()) Ok(())
//
} }
/*
/// Build a new configuration from defaults, which are overrided by arguments provided.
pub fn parse_args(args: &ArgMatches, log: &slog::Logger) -> Result<Self, Error> {
let mut config = Config::default();
// Use the specified datadir, or default in the home directory
if let Some(datadir) = args.value_of("datadir") {
config.data_dir = PathBuf::from(datadir);
info!(log, "Using custom data dir: {:?}", &config.data_dir);
};
fs::create_dir_all(&config.data_dir)
.unwrap_or_else(|_| panic!("Unable to create {:?}", &config.data_dir));
if let Some(srv) = args.value_of("server") {
//TODO: Validate the server value, to ensure it makes sense.
config.server = srv.to_string();
info!(log, "Using custom server: {:?}", &config.server);
};
// TODO: Permit loading a custom spec from file.
if let Some(spec_str) = args.value_of("spec") {
info!(log, "Using custom spec: {:?}", spec_str);
config.spec = match spec_str {
"mainnet" => MainnetEthSpec::default_spec(),
"minimal" => MinimalEthSpec::default_spec(),
// Should be impossible due to clap's `possible_values(..)` function.
_ => unreachable!(),
};
};
// Log configuration
info!(log, "";
"data_dir" => &config.data_dir.to_str(),
"server" => &config.server);
Ok(config)
}
*/
/// Try to load keys from validator_dir, returning None if none are found or an error. /// Try to load keys from validator_dir, returning None if none are found or an error.
#[allow(dead_code)] #[allow(dead_code)]
pub fn fetch_keys(&self, log: &slog::Logger) -> Option<Vec<Keypair>> { pub fn fetch_keys(&self, log: &slog::Logger) -> Option<Vec<Keypair>> {

View File

@ -7,10 +7,9 @@ mod service;
mod signer; mod signer;
use crate::config::Config as ValidatorClientConfig; use crate::config::Config as ValidatorClientConfig;
use std::fs;
use crate::service::Service as ValidatorService; use crate::service::Service as ValidatorService;
use clap::{App, Arg, ArgMatches}; use clap::{App, Arg};
use eth2_config::{read_from_file, write_to_file, Eth2Config}; use eth2_config::{get_data_dir, read_from_file, write_to_file, Eth2Config};
use protos::services_grpc::ValidatorServiceClient; use protos::services_grpc::ValidatorServiceClient;
use slog::{crit, error, info, o, Drain}; use slog::{crit, error, info, o, Drain};
use std::path::PathBuf; use std::path::PathBuf;
@ -18,8 +17,8 @@ use types::{Keypair, MainnetEthSpec, MinimalEthSpec};
pub const DEFAULT_SPEC: &str = "minimal"; pub const DEFAULT_SPEC: &str = "minimal";
pub const DEFAULT_DATA_DIR: &str = ".lighthouse-validator"; pub const DEFAULT_DATA_DIR: &str = ".lighthouse-validator";
pub const CLIENT_CONFIG_FILENAME: &str = "client_config.toml"; pub const CLIENT_CONFIG_FILENAME: &str = "client-config.toml";
pub const ETH2_CONFIG_FILENAME: &str = "eth2_config.toml"; pub const ETH2_CONFIG_FILENAME: &str = "eth2-config.toml";
fn main() { fn main() {
// Logging // Logging
@ -38,7 +37,7 @@ fn main() {
.long("datadir") .long("datadir")
.value_name("DIR") .value_name("DIR")
.help("Data directory for keys and databases.") .help("Data directory for keys and databases.")
.takes_value(true) .takes_value(true),
) )
.arg( .arg(
Arg::with_name("eth-config") Arg::with_name("eth-config")
@ -68,11 +67,11 @@ fn main() {
) )
.get_matches(); .get_matches();
let data_dir = match get_data_dir(&matches) { let data_dir = match get_data_dir(&matches, PathBuf::from(DEFAULT_DATA_DIR)) {
Ok(dir) => dir, Ok(dir) => dir,
Err(e) => { Err(e) => {
crit!(log, "Failed to initialize data dir"; "error" => format!("{:?}", e)); crit!(log, "Failed to initialize data dir"; "error" => format!("{:?}", e));
return return;
} }
}; };
@ -119,9 +118,7 @@ fn main() {
// Attempt to load the `Eth2Config` from file. // Attempt to load the `Eth2Config` from file.
// //
// If the file doesn't exist, create a default one depending on the CLI flags. // If the file doesn't exist, create a default one depending on the CLI flags.
let mut eth2_config = match read_from_file::<Eth2Config>( let mut eth2_config = match read_from_file::<Eth2Config>(eth2_config_path.clone()) {
eth2_config_path.clone()
) {
Ok(Some(c)) => c, Ok(Some(c)) => c,
Ok(None) => { Ok(None) => {
let default = match matches.value_of("spec-constants") { let default = match matches.value_of("spec-constants") {
@ -181,15 +178,3 @@ fn main() {
Err(e) => crit!(log, "Validator client exited with error"; "error" => e.to_string()), Err(e) => crit!(log, "Validator client exited with error"; "error" => e.to_string()),
} }
} }
fn get_data_dir(args: &ArgMatches) -> Result<PathBuf, &'static str> {
if let Some(data_dir) = args.value_of("data_dir") {
Ok(PathBuf::from(data_dir))
} else {
let path = dirs::home_dir()
.ok_or_else(|| "Unable to locate home directory")?
.join(&DEFAULT_DATA_DIR);
fs::create_dir_all(&path).map_err(|_| "Unable to create data_dir")?;
Ok(path)
}
}