diff --git a/account_manager/src/validator/create.rs b/account_manager/src/validator/create.rs index 26178e966c3..78332c209d6 100644 --- a/account_manager/src/validator/create.rs +++ b/account_manager/src/validator/create.rs @@ -7,6 +7,7 @@ use directory::{ use environment::Environment; use eth2_wallet::PlainText; use eth2_wallet_manager::WalletManager; +use slashing_protection::{SlashingDatabase, SLASHING_PROTECTION_FILENAME}; use std::ffi::OsStr; use std::fs; use std::path::{Path, PathBuf}; @@ -169,6 +170,16 @@ pub fn cli_run( .wallet_by_name(&name) .map_err(|e| format!("Unable to open wallet: {:?}", e))?; + let slashing_protection_path = validator_dir.join(SLASHING_PROTECTION_FILENAME); + let slashing_protection = + SlashingDatabase::open_or_create(&slashing_protection_path).map_err(|e| { + format!( + "Unable to open or create slashing protection database at {}: {:?}", + slashing_protection_path.display(), + e + ) + })?; + for i in 0..n { let voting_password = random_password(); let withdrawal_password = random_password(); @@ -181,7 +192,22 @@ pub fn cli_run( ) .map_err(|e| format!("Unable to create validator keys: {:?}", e))?; - let voting_pubkey = keystores.voting.pubkey().to_string(); + let voting_pubkey = keystores.voting.public_key().ok_or_else(|| { + format!( + "Keystore public key is invalid: {}", + keystores.voting.pubkey() + ) + })?; + + slashing_protection + .register_validator(&voting_pubkey) + .map_err(|e| { + format!( + "Error registering validator {}: {:?}", + voting_pubkey.to_hex_string(), + e + ) + })?; ValidatorDirBuilder::new(validator_dir.clone(), secrets_dir.clone()) .voting_keystore(keystores.voting, voting_password.as_bytes()) @@ -191,7 +217,7 @@ pub fn cli_run( .build() .map_err(|e| format!("Unable to build validator directory: {:?}", e))?; - println!("{}/{}\t0x{}", i + 1, n, voting_pubkey); + println!("{}/{}\t0x{}", i + 1, n, voting_pubkey.to_hex_string()); } Ok(()) diff --git a/account_manager/src/validator/import.rs b/account_manager/src/validator/import.rs index 88ed85039bc..526a6b95b10 100644 --- a/account_manager/src/validator/import.rs +++ b/account_manager/src/validator/import.rs @@ -8,6 +8,7 @@ use account_utils::{ ZeroizeString, }; use clap::{App, Arg, ArgMatches}; +use slashing_protection::{SlashingDatabase, SLASHING_PROTECTION_FILENAME}; use std::fs; use std::path::PathBuf; use std::thread::sleep; @@ -75,6 +76,16 @@ pub fn cli_run(matches: &ArgMatches, validator_dir: PathBuf) -> Result<(), Strin let mut defs = ValidatorDefinitions::open_or_create(&validator_dir) .map_err(|e| format!("Unable to open {}: {:?}", CONFIG_FILENAME, e))?; + let slashing_protection_path = validator_dir.join(SLASHING_PROTECTION_FILENAME); + let slashing_protection = + SlashingDatabase::open_or_create(&slashing_protection_path).map_err(|e| { + format!( + "Unable to open or create slashing protection database at {}: {:?}", + slashing_protection_path.display(), + e + ) + })?; + // Collect the paths for the keystores that should be imported. let keystore_paths = match (keystore, keystores_dir) { (Some(keystore), None) => vec![keystore], @@ -105,6 +116,7 @@ pub fn cli_run(matches: &ArgMatches, validator_dir: PathBuf) -> Result<(), Strin // // - Obtain the keystore password, if the user desires. // - Copy the keystore into the `validator_dir`. + // - Register the voting key with the slashing protection database. // - Add the keystore to the validator definitions file. // // Skip keystores that already exist, but exit early if any operation fails. @@ -185,6 +197,20 @@ pub fn cli_run(matches: &ArgMatches, validator_dir: PathBuf) -> Result<(), Strin fs::copy(&src_keystore, &dest_keystore) .map_err(|e| format!("Unable to copy keystore: {:?}", e))?; + // Register with slashing protection. + let voting_pubkey = keystore + .public_key() + .ok_or_else(|| format!("Keystore public key is invalid: {}", keystore.pubkey()))?; + slashing_protection + .register_validator(&voting_pubkey) + .map_err(|e| { + format!( + "Error registering validator {}: {:?}", + voting_pubkey.to_hex_string(), + e + ) + })?; + eprintln!("Successfully imported keystore."); num_imported_keystores += 1; diff --git a/validator_client/slashing_protection/src/lib.rs b/validator_client/slashing_protection/src/lib.rs index 9571ecd9a51..a576743aa51 100644 --- a/validator_client/slashing_protection/src/lib.rs +++ b/validator_client/slashing_protection/src/lib.rs @@ -17,6 +17,9 @@ use std::io::{Error as IOError, ErrorKind}; use std::string::ToString; use types::{Hash256, PublicKey}; +/// The filename within the `validators` directory that contains the slashing protection DB. +pub const SLASHING_PROTECTION_FILENAME: &str = "slashing_protection.sqlite"; + /// The attestation or block is not safe to sign. /// /// This could be because it's slashable, or because an error occurred. diff --git a/validator_client/src/config.rs b/validator_client/src/config.rs index 1e55ef1804c..222909f3bf0 100644 --- a/validator_client/src/config.rs +++ b/validator_client/src/config.rs @@ -9,8 +9,6 @@ use std::path::PathBuf; use types::{Graffiti, GRAFFITI_BYTES_LEN}; pub const DEFAULT_HTTP_SERVER: &str = "http://localhost:5052/"; -/// Path to the slashing protection database within the datadir. -pub const SLASHING_PROTECTION_FILENAME: &str = "slashing_protection.sqlite"; /// Stores the core configuration for this validator instance. #[derive(Clone, Serialize, Deserialize)] diff --git a/validator_client/src/validator_store.rs b/validator_client/src/validator_store.rs index 66a616ff336..6bf2f211d0d 100644 --- a/validator_client/src/validator_store.rs +++ b/validator_client/src/validator_store.rs @@ -1,10 +1,8 @@ use crate::{ - config::{Config, SLASHING_PROTECTION_FILENAME}, - fork_service::ForkService, - initialized_validators::InitializedValidators, + config::Config, fork_service::ForkService, initialized_validators::InitializedValidators, }; use parking_lot::RwLock; -use slashing_protection::{NotSafe, Safe, SlashingDatabase}; +use slashing_protection::{NotSafe, Safe, SlashingDatabase, SLASHING_PROTECTION_FILENAME}; use slog::{crit, error, warn, Logger}; use slot_clock::SlotClock; use std::marker::PhantomData;