Loose VC lockfile and slashing protection registers (#1314)
This commit is contained in:
parent
d4dd9fae07
commit
916a133043
@ -1,7 +1,7 @@
|
||||
use crate::{Error as ValidatorDirError, ValidatorDir};
|
||||
use bls::Keypair;
|
||||
use rayon::prelude::*;
|
||||
use slog::{info, Logger};
|
||||
use slog::{info, warn, Logger};
|
||||
use std::collections::HashMap;
|
||||
use std::fs::read_dir;
|
||||
use std::io;
|
||||
@ -81,6 +81,50 @@ impl Manager {
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Opens all the validator directories in `self` and decrypts the validator keypairs,
|
||||
/// regardless if a lockfile exists or not.
|
||||
///
|
||||
/// If `log.is_some()`, an `info` log will be generated for each decrypted validator.
|
||||
/// Additionally, a warning log will be created if a lockfile existed already.
|
||||
///
|
||||
/// ## Errors
|
||||
///
|
||||
/// Returns an error if any of the directories is unable to be opened.
|
||||
pub fn force_decrypt_all_validators(
|
||||
&self,
|
||||
secrets_dir: PathBuf,
|
||||
log_opt: Option<&Logger>,
|
||||
) -> Result<Vec<(Keypair, ValidatorDir)>, Error> {
|
||||
self.iter_dir()?
|
||||
.into_par_iter()
|
||||
.map(|path| {
|
||||
ValidatorDir::force_open(path)
|
||||
.and_then(|(v, existed)| {
|
||||
v.voting_keypair(&secrets_dir).map(|kp| (kp, v, existed))
|
||||
})
|
||||
.map(|(kp, v, lockfile_existed)| {
|
||||
if let Some(log) = log_opt {
|
||||
info!(
|
||||
log,
|
||||
"Decrypted validator keystore";
|
||||
"voting_pubkey" => kp.pk.as_hex_string()
|
||||
);
|
||||
if lockfile_existed {
|
||||
warn!(
|
||||
log,
|
||||
"Lockfile already existed";
|
||||
"msg" => "ensure no other validator client is running on this host",
|
||||
"voting_pubkey" => kp.pk.as_hex_string()
|
||||
);
|
||||
}
|
||||
}
|
||||
(kp, v)
|
||||
})
|
||||
.map_err(Error::ValidatorDirError)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Opens all the validator directories in `self` and decrypts the validator keypairs.
|
||||
///
|
||||
/// If `log.is_some()`, an `info` log will be generated for each decrypted validator.
|
||||
|
@ -93,6 +93,37 @@ impl ValidatorDir {
|
||||
Ok(Self { dir })
|
||||
}
|
||||
|
||||
/// Open `dir`, regardless or not if a lockfile exists.
|
||||
///
|
||||
/// Returns `(validator_dir, lockfile_existed)`, where `lockfile_existed == true` if a lockfile
|
||||
/// was already present before opening. Creates a lockfile if one did not already exist.
|
||||
///
|
||||
/// ## Errors
|
||||
///
|
||||
/// If there is a filesystem error.
|
||||
pub fn force_open<P: AsRef<Path>>(dir: P) -> Result<(Self, bool), Error> {
|
||||
let dir: &Path = dir.as_ref();
|
||||
let dir: PathBuf = dir.into();
|
||||
|
||||
if !dir.exists() {
|
||||
return Err(Error::DirectoryDoesNotExist(dir));
|
||||
}
|
||||
|
||||
let lockfile = dir.join(LOCK_FILE);
|
||||
|
||||
let lockfile_exists = lockfile.exists();
|
||||
|
||||
if !lockfile_exists {
|
||||
OpenOptions::new()
|
||||
.write(true)
|
||||
.create_new(true)
|
||||
.open(lockfile)
|
||||
.map_err(Error::UnableToCreateLockfile)?;
|
||||
}
|
||||
|
||||
Ok((Self { dir }, lockfile_exists))
|
||||
}
|
||||
|
||||
/// Returns the `dir` provided to `Self::open`.
|
||||
pub fn dir(&self) -> &PathBuf {
|
||||
&self.dir
|
||||
|
@ -34,8 +34,16 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
|
||||
enabling the same signing key on multiple validator clients WILL lead to \
|
||||
that validator getting slashed. Only use this flag the first time you run \
|
||||
the validator client, or if you're certain there are no other \
|
||||
nodes using the same key.",
|
||||
nodes using the same key. Automatically enabled unless `--strict` is specified",
|
||||
))
|
||||
.arg(
|
||||
Arg::with_name("strict")
|
||||
.long("strict")
|
||||
.help(
|
||||
"If present, require that validator keypairs are unlocked and that auto-register \
|
||||
is explicit before new validators are allowed to be used."
|
||||
)
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("allow-unsynced")
|
||||
.long("allow-unsynced")
|
||||
|
@ -23,6 +23,8 @@ pub struct Config {
|
||||
/// If true, the validator client will still poll for duties and produce blocks even if the
|
||||
/// beacon node is not synced at startup.
|
||||
pub allow_unsynced_beacon_node: bool,
|
||||
/// If true, we will be strict about concurrency and validator registration.
|
||||
pub strict: bool,
|
||||
/// If true, register new validator keys with the slashing protection database.
|
||||
pub auto_register: bool,
|
||||
}
|
||||
@ -42,6 +44,7 @@ impl Default for Config {
|
||||
http_server: DEFAULT_HTTP_SERVER.to_string(),
|
||||
allow_unsynced_beacon_node: false,
|
||||
auto_register: false,
|
||||
strict: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -71,6 +74,12 @@ impl Config {
|
||||
|
||||
config.allow_unsynced_beacon_node = cli_args.is_present("allow-unsynced");
|
||||
config.auto_register = cli_args.is_present("auto-register");
|
||||
config.strict = cli_args.is_present("strict");
|
||||
|
||||
if !config.strict {
|
||||
// Do not require an explicit `--auto-register` if `--strict` is disabled.
|
||||
config.auto_register = true
|
||||
}
|
||||
|
||||
if let Some(secrets_dir) = parse_optional(cli_args, "secrets-dir")? {
|
||||
config.secrets_dir = secrets_dir;
|
||||
|
@ -76,9 +76,16 @@ impl<T: EthSpec> ProductionValidatorClient<T> {
|
||||
);
|
||||
}
|
||||
|
||||
let validators = ValidatorManager::open(&config.data_dir)
|
||||
.map_err(|e| format!("unable to read data_dir: {:?}", e))?
|
||||
.decrypt_all_validators(config.secrets_dir.clone(), Some(&log))
|
||||
let validator_manager = ValidatorManager::open(&config.data_dir)
|
||||
.map_err(|e| format!("unable to read data_dir: {:?}", e))?;
|
||||
|
||||
let validators_result = if config.strict {
|
||||
validator_manager.decrypt_all_validators(config.secrets_dir.clone(), Some(&log))
|
||||
} else {
|
||||
validator_manager.force_decrypt_all_validators(config.secrets_dir.clone(), Some(&log))
|
||||
};
|
||||
|
||||
let validators = validators_result
|
||||
.map_err(|e| format!("unable to decrypt all validator directories: {:?}", e))?;
|
||||
|
||||
info!(
|
||||
|
Loading…
Reference in New Issue
Block a user