Allow VC to start without any validators (#1779)

## Issue Addressed

NA

## Proposed Changes

- Don't exit early if the VC is without any validators.
- When there are no validators, always create the slashing database (even without `--init-slashing-protection`).
This commit is contained in:
Paul Hauner 2020-10-21 04:29:24 +00:00
parent 2acf75785c
commit 02d94a70b7

View File

@ -29,7 +29,7 @@ use http_api::ApiSecret;
use initialized_validators::InitializedValidators; use initialized_validators::InitializedValidators;
use notifier::spawn_notifier; use notifier::spawn_notifier;
use slashing_protection::{SlashingDatabase, SLASHING_PROTECTION_FILENAME}; use slashing_protection::{SlashingDatabase, SLASHING_PROTECTION_FILENAME};
use slog::{error, info, Logger}; use slog::{error, info, warn, Logger};
use slot_clock::SlotClock; use slot_clock::SlotClock;
use slot_clock::SystemTimeSlotClock; use slot_clock::SystemTimeSlotClock;
use std::marker::PhantomData; use std::marker::PhantomData;
@ -107,6 +107,8 @@ impl<T: EthSpec> ProductionValidatorClient<T> {
.await .await
.map_err(|e| format!("Unable to initialize validators: {:?}", e))?; .map_err(|e| format!("Unable to initialize validators: {:?}", e))?;
let voting_pubkeys: Vec<_> = validators.iter_voting_pubkeys().collect();
info!( info!(
log, log,
"Initialized validators"; "Initialized validators";
@ -114,16 +116,21 @@ impl<T: EthSpec> ProductionValidatorClient<T> {
"enabled" => validators.num_enabled(), "enabled" => validators.num_enabled(),
); );
if validators.num_enabled() == 0 { if voting_pubkeys.is_empty() {
return Err("Cannot run with 0 enabled validators. \ warn!(
Please create or import validators before starting the validator client, \ log,
or check your datadir configuration" "No enabled validators";
.to_string()); "hint" => "create validators via the API, or the `lighthouse account` CLI command"
);
} }
// Initialize slashing protection. // Initialize slashing protection.
//
// Create the slashing database if there are no validators, even if
// `init_slashing_protection` is not supplied. There is no risk in creating a slashing
// database without any validators in it.
let slashing_db_path = config.validator_dir.join(SLASHING_PROTECTION_FILENAME); let slashing_db_path = config.validator_dir.join(SLASHING_PROTECTION_FILENAME);
let slashing_protection = if config.init_slashing_protection { let slashing_protection = if config.init_slashing_protection || voting_pubkeys.is_empty() {
SlashingDatabase::open_or_create(&slashing_db_path).map_err(|e| { SlashingDatabase::open_or_create(&slashing_db_path).map_err(|e| {
format!( format!(
"Failed to open or create slashing protection database: {:?}", "Failed to open or create slashing protection database: {:?}",
@ -143,11 +150,11 @@ impl<T: EthSpec> ProductionValidatorClient<T> {
// Check validator registration with slashing protection, or auto-register all validators. // Check validator registration with slashing protection, or auto-register all validators.
if config.init_slashing_protection { if config.init_slashing_protection {
slashing_protection slashing_protection
.register_validators(validators.iter_voting_pubkeys()) .register_validators(voting_pubkeys.iter().copied())
.map_err(|e| format!("Error while registering slashing protection: {:?}", e))?; .map_err(|e| format!("Error while registering slashing protection: {:?}", e))?;
} else { } else {
slashing_protection slashing_protection
.check_validator_registrations(validators.iter_voting_pubkeys()) .check_validator_registrations(voting_pubkeys.iter().copied())
.map_err(|e| { .map_err(|e| {
format!( format!(
"One or more validators not found in slashing protection database.\n\ "One or more validators not found in slashing protection database.\n\