mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-03 00:31:50 +00:00
Implement VC API (#1657)
## Issue Addressed
NA
## Proposed Changes
- Implements a HTTP API for the validator client.
- Creates EIP-2335 keystores with an empty `description` field, instead of a missing `description` field. Adds option to set name.
- Be more graceful with setups without any validators (yet)
- Remove an error log when there are no validators.
- Create the `validator` dir if it doesn't exist.
- Allow building a `ValidatorDir` without a withdrawal keystore (required for the API method where we only post a voting keystore).
- Add optional `description` field to `validator_definitions.yml`
## TODO
- [x] Signature header, as per https://github.com/sigp/lighthouse/issues/1269#issuecomment-649879855
- [x] Return validator descriptions
- [x] Return deposit data
- [x] Respect the mnemonic offset
- [x] Check that mnemonic can derive returned keys
- [x] Be strict about non-localhost
- [x] Allow graceful start without any validators (+ create validator dir)
- [x] Docs final pass
- [x] Swap to EIP-2335 description field.
- [x] Fix Zerioze TODO in VC api types.
- [x] Zeroize secp256k1 key
## Endpoints
- [x] `GET /lighthouse/version`
- [x] `GET /lighthouse/health`
- [x] `GET /lighthouse/validators`
- [x] `POST /lighthouse/validators/hd`
- [x] `POST /lighthouse/validators/keystore`
- [x] `PATCH /lighthouse/validators/:validator_pubkey`
- [ ] ~~`POST /lighthouse/validators/:validator_pubkey/exit/:epoch`~~ Future works
## Additional Info
TBC
This commit is contained in:
@@ -40,6 +40,7 @@ pub enum Error {
|
||||
UninitializedWithdrawalKeystore,
|
||||
#[cfg(feature = "insecure_keys")]
|
||||
InsecureKeysError(String),
|
||||
MissingPasswordDir,
|
||||
}
|
||||
|
||||
impl From<KeystoreError> for Error {
|
||||
@@ -51,7 +52,7 @@ impl From<KeystoreError> for Error {
|
||||
/// A builder for creating a `ValidatorDir`.
|
||||
pub struct Builder<'a> {
|
||||
base_validators_dir: PathBuf,
|
||||
password_dir: PathBuf,
|
||||
password_dir: Option<PathBuf>,
|
||||
pub(crate) voting_keystore: Option<(Keystore, PlainText)>,
|
||||
pub(crate) withdrawal_keystore: Option<(Keystore, PlainText)>,
|
||||
store_withdrawal_keystore: bool,
|
||||
@@ -60,10 +61,10 @@ pub struct Builder<'a> {
|
||||
|
||||
impl<'a> Builder<'a> {
|
||||
/// Instantiate a new builder.
|
||||
pub fn new(base_validators_dir: PathBuf, password_dir: PathBuf) -> Self {
|
||||
pub fn new(base_validators_dir: PathBuf) -> Self {
|
||||
Self {
|
||||
base_validators_dir,
|
||||
password_dir,
|
||||
password_dir: None,
|
||||
voting_keystore: None,
|
||||
withdrawal_keystore: None,
|
||||
store_withdrawal_keystore: true,
|
||||
@@ -71,6 +72,12 @@ impl<'a> Builder<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Supply a directory in which to store the passwords for the validator keystores.
|
||||
pub fn password_dir<P: Into<PathBuf>>(mut self, password_dir: P) -> Self {
|
||||
self.password_dir = Some(password_dir.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Build the `ValidatorDir` use the given `keystore` which can be unlocked with `password`.
|
||||
///
|
||||
/// The builder will not necessarily check that `password` can unlock `keystore`.
|
||||
@@ -215,26 +222,35 @@ impl<'a> Builder<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
// Only the withdrawal keystore if explicitly required.
|
||||
if self.store_withdrawal_keystore {
|
||||
// Write the withdrawal password to file.
|
||||
write_password_to_file(
|
||||
self.password_dir
|
||||
.join(withdrawal_keypair.pk.to_hex_string()),
|
||||
withdrawal_password.as_bytes(),
|
||||
)?;
|
||||
if self.password_dir.is_none() && self.store_withdrawal_keystore {
|
||||
return Err(Error::MissingPasswordDir);
|
||||
}
|
||||
|
||||
// Write the withdrawal keystore to file.
|
||||
write_keystore_to_file(dir.join(WITHDRAWAL_KEYSTORE_FILE), &withdrawal_keystore)?;
|
||||
if let Some(password_dir) = self.password_dir.as_ref() {
|
||||
// Only the withdrawal keystore if explicitly required.
|
||||
if self.store_withdrawal_keystore {
|
||||
// Write the withdrawal password to file.
|
||||
write_password_to_file(
|
||||
password_dir.join(withdrawal_keypair.pk.to_hex_string()),
|
||||
withdrawal_password.as_bytes(),
|
||||
)?;
|
||||
|
||||
// Write the withdrawal keystore to file.
|
||||
write_keystore_to_file(
|
||||
dir.join(WITHDRAWAL_KEYSTORE_FILE),
|
||||
&withdrawal_keystore,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write the voting password to file.
|
||||
write_password_to_file(
|
||||
self.password_dir
|
||||
.join(format!("0x{}", voting_keystore.pubkey())),
|
||||
voting_password.as_bytes(),
|
||||
)?;
|
||||
if let Some(password_dir) = self.password_dir.as_ref() {
|
||||
// Write the voting password to file.
|
||||
write_password_to_file(
|
||||
password_dir.join(format!("0x{}", voting_keystore.pubkey())),
|
||||
voting_password.as_bytes(),
|
||||
)?;
|
||||
}
|
||||
|
||||
// Write the voting keystore to file.
|
||||
write_keystore_to_file(dir.join(VOTING_KEYSTORE_FILE), &voting_keystore)?;
|
||||
|
||||
@@ -73,7 +73,8 @@ pub fn build_deterministic_validator_dirs(
|
||||
indices: &[usize],
|
||||
) -> Result<(), String> {
|
||||
for &i in indices {
|
||||
Builder::new(validators_dir.clone(), password_dir.clone())
|
||||
Builder::new(validators_dir.clone())
|
||||
.password_dir(password_dir.clone())
|
||||
.insecure_voting_keypair(i)
|
||||
.map_err(|e| format!("Unable to generate insecure keypair: {:?}", e))?
|
||||
.store_withdrawal_keystore(false)
|
||||
|
||||
@@ -129,6 +129,11 @@ impl ValidatorDir {
|
||||
&self.dir
|
||||
}
|
||||
|
||||
/// Returns the path to the voting keystore JSON file.
|
||||
pub fn voting_keystore_path(&self) -> PathBuf {
|
||||
self.dir.join(VOTING_KEYSTORE_FILE)
|
||||
}
|
||||
|
||||
/// Attempts to read the keystore in `self.dir` and decrypt the keypair using a password file
|
||||
/// in `password_dir`.
|
||||
///
|
||||
|
||||
Reference in New Issue
Block a user