## Issue Addressed
Addresses #2557
## Proposed Changes
Adds the `lighthouse validator-manager` command, which provides:
- `lighthouse validator-manager create`
- Creates a `validators.json` file and a `deposits.json` (same format as https://github.com/ethereum/staking-deposit-cli)
- `lighthouse validator-manager import`
- Imports validators from a `validators.json` file to the VC via the HTTP API.
- `lighthouse validator-manager move`
- Moves validators from one VC to the other, utilizing only the VC API.
## Additional Info
In 98bcb947c I've reduced some VC `ERRO` and `CRIT` warnings to `WARN` or `DEBG` for the case where a pubkey is missing from the validator store. These were being triggered when we removed a validator but still had it in caches. It seems to me that `UnknownPubkey` will only happen in the case where we've removed a validator, so downgrading the logs is prudent. All the logs are `DEBG` apart from attestations and blocks which are `WARN`. I thought having *some* logging about this condition might help us down the track.
In 856cd7e37d I've made the VC delete the corresponding password file when it's deleting a keystore. This seemed like nice hygiene. Notably, it'll only delete that password file after it scans the validator definitions and finds that no other validator is also using that password file.
86 lines
3.2 KiB
Rust
86 lines
3.2 KiB
Rust
use clap::App;
|
|
use clap::ArgMatches;
|
|
use common::write_to_json_file;
|
|
use environment::Environment;
|
|
use serde::Serialize;
|
|
use std::path::PathBuf;
|
|
use types::EthSpec;
|
|
|
|
pub mod common;
|
|
pub mod create_validators;
|
|
pub mod import_validators;
|
|
pub mod move_validators;
|
|
|
|
pub const CMD: &str = "validator_manager";
|
|
|
|
/// This flag is on the top-level `lighthouse` binary.
|
|
const DUMP_CONFIGS_FLAG: &str = "dump-config";
|
|
|
|
/// Used only in testing, this allows a command to dump its configuration to a file and then exit
|
|
/// successfully. This allows for testing how the CLI arguments translate to some configuration.
|
|
pub enum DumpConfig {
|
|
Disabled,
|
|
Enabled(PathBuf),
|
|
}
|
|
|
|
impl DumpConfig {
|
|
/// Returns `Ok(true)` if the configuration was successfully written to a file and the
|
|
/// application should exit successfully without doing anything else.
|
|
pub fn should_exit_early<T: Serialize>(&self, config: &T) -> Result<bool, String> {
|
|
match self {
|
|
DumpConfig::Disabled => Ok(false),
|
|
DumpConfig::Enabled(dump_path) => {
|
|
dbg!(dump_path);
|
|
write_to_json_file(dump_path, config)?;
|
|
Ok(true)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
|
|
App::new(CMD)
|
|
.visible_aliases(&["vm", "validator-manager", CMD])
|
|
.about("Utilities for managing a Lighthouse validator client via the HTTP API.")
|
|
.subcommand(create_validators::cli_app())
|
|
.subcommand(import_validators::cli_app())
|
|
.subcommand(move_validators::cli_app())
|
|
}
|
|
|
|
/// Run the account manager, returning an error if the operation did not succeed.
|
|
pub fn run<'a, T: EthSpec>(matches: &'a ArgMatches<'a>, env: Environment<T>) -> Result<(), String> {
|
|
let context = env.core_context();
|
|
let spec = context.eth2_config.spec;
|
|
let dump_config = clap_utils::parse_optional(matches, DUMP_CONFIGS_FLAG)?
|
|
.map(DumpConfig::Enabled)
|
|
.unwrap_or_else(|| DumpConfig::Disabled);
|
|
|
|
context
|
|
.executor
|
|
// This `block_on_dangerous` call reasonable since it is at the very highest level of the
|
|
// application, the rest of which is all async. All other functions below this should be
|
|
// async and should never call `block_on_dangerous` themselves.
|
|
.block_on_dangerous(
|
|
async {
|
|
match matches.subcommand() {
|
|
(create_validators::CMD, Some(matches)) => {
|
|
create_validators::cli_run::<T>(matches, &spec, dump_config).await
|
|
}
|
|
(import_validators::CMD, Some(matches)) => {
|
|
import_validators::cli_run(matches, dump_config).await
|
|
}
|
|
(move_validators::CMD, Some(matches)) => {
|
|
move_validators::cli_run(matches, dump_config).await
|
|
}
|
|
("", _) => Err("No command supplied. See --help.".to_string()),
|
|
(unknown, _) => Err(format!(
|
|
"{} is not a valid {} command. See --help.",
|
|
unknown, CMD
|
|
)),
|
|
}
|
|
},
|
|
"validator_manager",
|
|
)
|
|
.ok_or("Shutting down")?
|
|
}
|