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 crate::{Error as ValidatorDirError, ValidatorDir};
|
||||||
use bls::Keypair;
|
use bls::Keypair;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use slog::{info, Logger};
|
use slog::{info, warn, Logger};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fs::read_dir;
|
use std::fs::read_dir;
|
||||||
use std::io;
|
use std::io;
|
||||||
@ -81,6 +81,50 @@ impl Manager {
|
|||||||
.collect()
|
.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.
|
/// 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.
|
/// If `log.is_some()`, an `info` log will be generated for each decrypted validator.
|
||||||
|
@ -93,6 +93,37 @@ impl ValidatorDir {
|
|||||||
Ok(Self { dir })
|
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`.
|
/// Returns the `dir` provided to `Self::open`.
|
||||||
pub fn dir(&self) -> &PathBuf {
|
pub fn dir(&self) -> &PathBuf {
|
||||||
&self.dir
|
&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 \
|
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 \
|
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 \
|
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(
|
||||||
Arg::with_name("allow-unsynced")
|
Arg::with_name("allow-unsynced")
|
||||||
.long("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
|
/// If true, the validator client will still poll for duties and produce blocks even if the
|
||||||
/// beacon node is not synced at startup.
|
/// beacon node is not synced at startup.
|
||||||
pub allow_unsynced_beacon_node: bool,
|
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.
|
/// If true, register new validator keys with the slashing protection database.
|
||||||
pub auto_register: bool,
|
pub auto_register: bool,
|
||||||
}
|
}
|
||||||
@ -42,6 +44,7 @@ impl Default for Config {
|
|||||||
http_server: DEFAULT_HTTP_SERVER.to_string(),
|
http_server: DEFAULT_HTTP_SERVER.to_string(),
|
||||||
allow_unsynced_beacon_node: false,
|
allow_unsynced_beacon_node: false,
|
||||||
auto_register: false,
|
auto_register: false,
|
||||||
|
strict: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -71,6 +74,12 @@ impl Config {
|
|||||||
|
|
||||||
config.allow_unsynced_beacon_node = cli_args.is_present("allow-unsynced");
|
config.allow_unsynced_beacon_node = cli_args.is_present("allow-unsynced");
|
||||||
config.auto_register = cli_args.is_present("auto-register");
|
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")? {
|
if let Some(secrets_dir) = parse_optional(cli_args, "secrets-dir")? {
|
||||||
config.secrets_dir = secrets_dir;
|
config.secrets_dir = secrets_dir;
|
||||||
|
@ -76,9 +76,16 @@ impl<T: EthSpec> ProductionValidatorClient<T> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let validators = ValidatorManager::open(&config.data_dir)
|
let validator_manager = ValidatorManager::open(&config.data_dir)
|
||||||
.map_err(|e| format!("unable to read data_dir: {:?}", e))?
|
.map_err(|e| format!("unable to read data_dir: {:?}", e))?;
|
||||||
.decrypt_all_validators(config.secrets_dir.clone(), Some(&log))
|
|
||||||
|
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))?;
|
.map_err(|e| format!("unable to decrypt all validator directories: {:?}", e))?;
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
|
Loading…
Reference in New Issue
Block a user