A first go at persisting validator keys and handling configuration. Addresses issue #253.
- Creates a keystore directory in the config - Fetches serialized keys from the keystore directory - If no keys, generates keys randomly, saves serialized keys to keystore dir.
This commit is contained in:
parent
b2926b4ed0
commit
e942d7533b
@ -14,4 +14,8 @@ impl Keypair {
|
|||||||
let pk = PublicKey::from_secret_key(&sk);
|
let pk = PublicKey::from_secret_key(&sk);
|
||||||
Keypair { sk, pk }
|
Keypair { sk, pk }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn identifier(&self) -> String {
|
||||||
|
self.pk.concatenated_hex_id()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,3 +18,4 @@ slog = "^2.2.3"
|
|||||||
slog-term = "^2.4.0"
|
slog-term = "^2.4.0"
|
||||||
slog-async = "^2.3.0"
|
slog-async = "^2.3.0"
|
||||||
ssz = { path = "../eth2/utils/ssz" }
|
ssz = { path = "../eth2/utils/ssz" }
|
||||||
|
bincode = "^1.1.2"
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
|
use bls::Keypair;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{Error, ErrorKind};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use types::ChainSpec;
|
use types::ChainSpec;
|
||||||
|
|
||||||
@ -6,27 +9,63 @@ use types::ChainSpec;
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ClientConfig {
|
pub struct ClientConfig {
|
||||||
pub data_dir: PathBuf,
|
pub data_dir: PathBuf,
|
||||||
|
pub key_dir: PathBuf,
|
||||||
pub server: String,
|
pub server: String,
|
||||||
pub spec: ChainSpec,
|
pub spec: ChainSpec,
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_LIGHTHOUSE_DIR: &str = ".lighthouse-validators";
|
const DEFAULT_LIGHTHOUSE_DIR: &str = ".lighthouse-validators";
|
||||||
|
const DEFAULT_KEYSTORE_SUBDIR: &str = "keystore";
|
||||||
|
|
||||||
impl ClientConfig {
|
impl ClientConfig {
|
||||||
/// Build a new configuration from defaults.
|
/// Build a new configuration from defaults.
|
||||||
pub fn default() -> Self {
|
pub fn default() -> Result<Self, Error> {
|
||||||
let data_dir = {
|
let data_dir = {
|
||||||
let home = dirs::home_dir().expect("Unable to determine home dir.");
|
let home = dirs::home_dir().expect("Unable to determine home dir.");
|
||||||
home.join(DEFAULT_LIGHTHOUSE_DIR)
|
home.join(DEFAULT_LIGHTHOUSE_DIR)
|
||||||
};
|
};
|
||||||
fs::create_dir_all(&data_dir)
|
fs::create_dir_all(&data_dir)?;
|
||||||
.unwrap_or_else(|_| panic!("Unable to create {:?}", &data_dir));
|
|
||||||
|
let key_dir = data_dir.join(DEFAULT_KEYSTORE_SUBDIR);
|
||||||
|
fs::create_dir_all(&key_dir)?;
|
||||||
|
|
||||||
let server = "localhost:50051".to_string();
|
let server = "localhost:50051".to_string();
|
||||||
let spec = ChainSpec::foundation();
|
let spec = ChainSpec::foundation();
|
||||||
Self {
|
Ok(Self {
|
||||||
data_dir,
|
data_dir,
|
||||||
|
key_dir,
|
||||||
server,
|
server,
|
||||||
spec,
|
spec,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Try to load keys from datadir, or fail
|
||||||
|
pub fn fetch_keys(&self) -> Result<Option<Vec<Keypair>>, Error> {
|
||||||
|
let mut key_files = fs::read_dir(&self.key_dir)?.peekable();
|
||||||
|
|
||||||
|
if key_files.peek().is_none() {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut key_pairs: Vec<Keypair> = Vec::new();
|
||||||
|
|
||||||
|
for key_filename in key_files {
|
||||||
|
let mut key_file = File::open(key_filename?.path())?;
|
||||||
|
|
||||||
|
let key: Keypair = bincode::deserialize_from(&mut key_file)
|
||||||
|
.map_err(|e| Error::new(ErrorKind::InvalidData, e))?;
|
||||||
|
|
||||||
|
key_pairs.push(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Some(key_pairs))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn save_key(&self, key: &Keypair) -> Result<(), Error> {
|
||||||
|
let key_path = self.key_dir.join(key.identifier() + ".key");
|
||||||
|
let mut key_file = File::create(&key_path)?;
|
||||||
|
bincode::serialize_into(&mut key_file, &key)
|
||||||
|
.map_err(|e| Error::new(ErrorKind::InvalidData, e))?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ use bls::Keypair;
|
|||||||
use clap::{App, Arg};
|
use clap::{App, Arg};
|
||||||
use grpcio::{ChannelBuilder, EnvBuilder};
|
use grpcio::{ChannelBuilder, EnvBuilder};
|
||||||
use protos::services_grpc::{BeaconBlockServiceClient, ValidatorServiceClient};
|
use protos::services_grpc::{BeaconBlockServiceClient, ValidatorServiceClient};
|
||||||
use slog::{error, info, o, Drain};
|
use slog::{debug, error, info, o, Drain};
|
||||||
use slot_clock::SystemTimeSlotClock;
|
use slot_clock::SystemTimeSlotClock;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@ -17,6 +17,8 @@ mod block_producer_service;
|
|||||||
mod config;
|
mod config;
|
||||||
mod duties;
|
mod duties;
|
||||||
|
|
||||||
|
const NUMBER_OF_VALIDATOR_TEST_KEYS: u16 = 3;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Logging
|
// Logging
|
||||||
let decorator = slog_term::TermDecorator::new().build();
|
let decorator = slog_term::TermDecorator::new().build();
|
||||||
@ -55,7 +57,7 @@ fn main() {
|
|||||||
)
|
)
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
let mut config = ClientConfig::default();
|
let mut config = ClientConfig::default().expect("Unable to create a default configuration.");
|
||||||
|
|
||||||
// Custom datadir
|
// Custom datadir
|
||||||
if let Some(dir) = matches.value_of("datadir") {
|
if let Some(dir) = matches.value_of("datadir") {
|
||||||
@ -123,9 +125,27 @@ fn main() {
|
|||||||
* Start threads.
|
* Start threads.
|
||||||
*/
|
*/
|
||||||
let mut threads = vec![];
|
let mut threads = vec![];
|
||||||
// TODO: keypairs are randomly generated; they should be loaded from a file or generated.
|
|
||||||
// https://github.com/sigp/lighthouse/issues/160
|
let keypairs = config
|
||||||
let keypairs = vec![Keypair::random()];
|
.fetch_keys()
|
||||||
|
.expect("Encountered an error while fetching saved keys.")
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
// TODO: Key generation should occur in a separate binary
|
||||||
|
let mut k = Vec::new();
|
||||||
|
info!(
|
||||||
|
log,
|
||||||
|
"No key pairs found, generating and saving 3 random key pairs."
|
||||||
|
);
|
||||||
|
for _n in 0..NUMBER_OF_VALIDATOR_TEST_KEYS {
|
||||||
|
let keypair = Keypair::random();
|
||||||
|
config
|
||||||
|
.save_key(&keypair)
|
||||||
|
.expect("Unable to save newly generated private key.");
|
||||||
|
debug!(log, "Keypair generated {:?}", keypair.identifier());
|
||||||
|
k.push(keypair);
|
||||||
|
}
|
||||||
|
k
|
||||||
|
});
|
||||||
|
|
||||||
for keypair in keypairs {
|
for keypair in keypairs {
|
||||||
info!(log, "Starting validator services"; "validator" => keypair.pk.concatenated_hex_id());
|
info!(log, "Starting validator services"; "validator" => keypair.pk.concatenated_hex_id());
|
||||||
|
Loading…
Reference in New Issue
Block a user