mirror of
https://github.com/sigp/lighthouse.git
synced 2026-04-18 21:38:31 +00:00
Support multiple BLS implementations (#1335)
## Issue Addressed NA ## Proposed Changes - Refactor the `bls` crate to support multiple BLS "backends" (e.g., milagro, blst, etc). - Removes some duplicate, unused code in `common/rest_types/src/validator.rs`. - Removes the old "upgrade legacy keypairs" functionality (these were unencrypted keys that haven't been supported for a few testnets, no one should be using them anymore). ## Additional Info Most of the files changed are just inconsequential changes to function names. ## TODO - [x] Optimization levels - [x] Infinity point: https://github.com/supranational/blst/issues/11 - [x] Ensure milagro *and* blst are tested via CI - [x] What to do with unsafe code? - [x] Test infinity point in signature sets
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
mod common;
|
||||
pub mod upgrade_legacy_keypairs;
|
||||
pub mod validator;
|
||||
pub mod wallet;
|
||||
|
||||
@@ -19,7 +18,6 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
|
||||
.about("Utilities for generating and managing Ethereum 2.0 accounts.")
|
||||
.subcommand(wallet::cli_app())
|
||||
.subcommand(validator::cli_app())
|
||||
.subcommand(upgrade_legacy_keypairs::cli_app())
|
||||
}
|
||||
|
||||
/// Run the account manager, returning an error if the operation did not succeed.
|
||||
@@ -27,7 +25,6 @@ pub fn run<T: EthSpec>(matches: &ArgMatches<'_>, env: Environment<T>) -> Result<
|
||||
match matches.subcommand() {
|
||||
(wallet::CMD, Some(matches)) => wallet::cli_run(matches)?,
|
||||
(validator::CMD, Some(matches)) => validator::cli_run(matches, env)?,
|
||||
(upgrade_legacy_keypairs::CMD, Some(matches)) => upgrade_legacy_keypairs::cli_run(matches)?,
|
||||
(unknown, _) => {
|
||||
return Err(format!(
|
||||
"{} is not a valid {} command. See --help.",
|
||||
|
||||
@@ -1,149 +0,0 @@
|
||||
//! This command allows migrating from the old method of storing keys (unencrypted SSZ) to the
|
||||
//! current method of using encrypted EIP-2335 keystores.
|
||||
//!
|
||||
//! This command should be completely removed once the `unencrypted_keys` feature is removed from
|
||||
//! the `validator_dir` command. This should hopefully be in mid-June 2020.
|
||||
//!
|
||||
//! ## Example
|
||||
//!
|
||||
//! This command will upgrade all keypairs in the `--validators-dir`, storing the newly-generated
|
||||
//! passwords in `--secrets-dir`.
|
||||
//!
|
||||
//! ```ignore
|
||||
//! lighthouse am upgrade-legacy-keypairs \
|
||||
//! --validators-dir ~/.lighthouse/validators \
|
||||
//! --secrets-dir ~/.lighthouse/secrets
|
||||
//! ```
|
||||
|
||||
use crate::{SECRETS_DIR_FLAG, VALIDATOR_DIR_FLAG};
|
||||
use clap::{App, Arg, ArgMatches};
|
||||
use clap_utils::parse_required;
|
||||
use eth2_keystore::KeystoreBuilder;
|
||||
use rand::{distributions::Alphanumeric, Rng};
|
||||
use std::fs::{create_dir_all, read_dir, write, File};
|
||||
use std::path::{Path, PathBuf};
|
||||
use types::Keypair;
|
||||
use validator_dir::{
|
||||
unencrypted_keys::load_unencrypted_keypair, VOTING_KEYSTORE_FILE, WITHDRAWAL_KEYSTORE_FILE,
|
||||
};
|
||||
|
||||
pub const CMD: &str = "upgrade-legacy-keypairs";
|
||||
pub const VOTING_KEYPAIR_FILE: &str = "voting_keypair";
|
||||
pub const WITHDRAWAL_KEYPAIR_FILE: &str = "withdrawal_keypair";
|
||||
|
||||
pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
|
||||
App::new(CMD)
|
||||
.about(
|
||||
"Converts legacy unencrypted SSZ keypairs into encrypted keystores.",
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name(VALIDATOR_DIR_FLAG)
|
||||
.long(VALIDATOR_DIR_FLAG)
|
||||
.value_name("VALIDATORS_DIRECTORY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.help("The directory containing legacy validators. Generally ~/.lighthouse/validators"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name(SECRETS_DIR_FLAG)
|
||||
.long(SECRETS_DIR_FLAG)
|
||||
.value_name("SECRETS_DIRECTORY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.help("The directory where keystore passwords will be stored. Generally ~/.lighthouse/secrets"),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn cli_run(matches: &ArgMatches) -> Result<(), String> {
|
||||
let validators_dir: PathBuf = parse_required(matches, VALIDATOR_DIR_FLAG)?;
|
||||
let secrets_dir: PathBuf = parse_required(matches, SECRETS_DIR_FLAG)?;
|
||||
|
||||
if !secrets_dir.exists() {
|
||||
create_dir_all(&secrets_dir)
|
||||
.map_err(|e| format!("Failed to create secrets dir {:?}: {:?}", secrets_dir, e))?;
|
||||
}
|
||||
|
||||
read_dir(&validators_dir)
|
||||
.map_err(|e| {
|
||||
format!(
|
||||
"Failed to read validators directory {:?}: {:?}",
|
||||
validators_dir, e
|
||||
)
|
||||
})?
|
||||
.try_for_each(|dir| {
|
||||
let path = dir
|
||||
.map_err(|e| format!("Unable to read dir: {}", e))?
|
||||
.path();
|
||||
|
||||
if path.is_dir() {
|
||||
if let Err(e) = upgrade_keypair(
|
||||
&path,
|
||||
&secrets_dir,
|
||||
VOTING_KEYPAIR_FILE,
|
||||
VOTING_KEYSTORE_FILE,
|
||||
) {
|
||||
println!("Validator {:?}: {:?}", path, e);
|
||||
} else {
|
||||
println!("Validator {:?} voting keys: success", path);
|
||||
}
|
||||
|
||||
if let Err(e) = upgrade_keypair(
|
||||
&path,
|
||||
&secrets_dir,
|
||||
WITHDRAWAL_KEYPAIR_FILE,
|
||||
WITHDRAWAL_KEYSTORE_FILE,
|
||||
) {
|
||||
println!("Validator {:?}: {:?}", path, e);
|
||||
} else {
|
||||
println!("Validator {:?} withdrawal keys: success", path);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
fn upgrade_keypair<P: AsRef<Path>>(
|
||||
validator_dir: P,
|
||||
secrets_dir: P,
|
||||
input_filename: &str,
|
||||
output_filename: &str,
|
||||
) -> Result<(), String> {
|
||||
let validator_dir = validator_dir.as_ref();
|
||||
let secrets_dir = secrets_dir.as_ref();
|
||||
|
||||
let keypair: Keypair = load_unencrypted_keypair(validator_dir.join(input_filename))?;
|
||||
|
||||
let password = rand::thread_rng()
|
||||
.sample_iter(&Alphanumeric)
|
||||
.take(48)
|
||||
.collect::<String>()
|
||||
.into_bytes();
|
||||
|
||||
let keystore = KeystoreBuilder::new(&keypair, &password, "".into())
|
||||
.map_err(|e| format!("Unable to create keystore builder: {:?}", e))?
|
||||
.build()
|
||||
.map_err(|e| format!("Unable to build keystore: {:?}", e))?;
|
||||
|
||||
let keystore_path = validator_dir.join(output_filename);
|
||||
|
||||
if keystore_path.exists() {
|
||||
return Err(format!("{:?} already exists", keystore_path));
|
||||
}
|
||||
|
||||
let mut file = File::create(&keystore_path).map_err(|e| format!("Cannot create: {:?}", e))?;
|
||||
keystore
|
||||
.to_json_writer(&mut file)
|
||||
.map_err(|e| format!("Cannot write keystore to {:?}: {:?}", keystore_path, e))?;
|
||||
|
||||
let password_path = secrets_dir.join(keypair.pk.as_hex_string());
|
||||
|
||||
if password_path.exists() {
|
||||
return Err(format!("{:?} already exists", password_path));
|
||||
}
|
||||
|
||||
write(&password_path, &password)
|
||||
.map_err(|e| format!("Unable to write password to {:?}: {:?}", password_path, e))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user