mirror of
https://github.com/sigp/lighthouse.git
synced 2026-07-05 05:44:30 +00:00
Check key cache consistency in tests
This commit is contained in:
@@ -1,7 +1,8 @@
|
|||||||
use crate::doppelganger_service::DoppelgangerService;
|
use crate::doppelganger_service::DoppelgangerService;
|
||||||
|
use crate::key_cache::{KeyCache, CACHE_FILENAME};
|
||||||
use crate::{
|
use crate::{
|
||||||
http_api::{ApiSecret, Config as HttpConfig, Context},
|
http_api::{ApiSecret, Config as HttpConfig, Context},
|
||||||
initialized_validators::InitializedValidators,
|
initialized_validators::{InitializedValidators, OnDecryptFailure},
|
||||||
Config, ValidatorDefinitions, ValidatorStore,
|
Config, ValidatorDefinitions, ValidatorStore,
|
||||||
};
|
};
|
||||||
use account_utils::{
|
use account_utils::{
|
||||||
@@ -59,7 +60,7 @@ pub struct ApiTester {
|
|||||||
pub api_token: String,
|
pub api_token: String,
|
||||||
pub test_runtime: TestRuntime,
|
pub test_runtime: TestRuntime,
|
||||||
pub _server_shutdown: oneshot::Sender<()>,
|
pub _server_shutdown: oneshot::Sender<()>,
|
||||||
pub _validator_dir: TempDir,
|
pub validator_dir: TempDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApiTester {
|
impl ApiTester {
|
||||||
@@ -166,10 +167,26 @@ impl ApiTester {
|
|||||||
api_token: api_pubkey,
|
api_token: api_pubkey,
|
||||||
test_runtime,
|
test_runtime,
|
||||||
_server_shutdown: shutdown_tx,
|
_server_shutdown: shutdown_tx,
|
||||||
_validator_dir: validator_dir,
|
validator_dir,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks that the key cache exists and can be decrypted with the current
|
||||||
|
/// set of known validators.
|
||||||
|
pub async fn ensure_key_cache_consistency(&self) {
|
||||||
|
assert!(
|
||||||
|
self.validator_dir.as_ref().join(CACHE_FILENAME).exists(),
|
||||||
|
"the key cache should exist"
|
||||||
|
);
|
||||||
|
let key_cache =
|
||||||
|
KeyCache::open_or_create(self.validator_dir.as_ref()).expect("should open a key cache");
|
||||||
|
self.initialized_validators
|
||||||
|
.read()
|
||||||
|
.decrypt_key_cache(key_cache, &mut <_>::default(), OnDecryptFailure::Error)
|
||||||
|
.await
|
||||||
|
.expect("key cache should decypt");
|
||||||
|
}
|
||||||
|
|
||||||
pub fn invalid_token_client(&self) -> ValidatorClientHttpClient {
|
pub fn invalid_token_client(&self) -> ValidatorClientHttpClient {
|
||||||
let tmp = tempdir().unwrap();
|
let tmp = tempdir().unwrap();
|
||||||
let api_secret = ApiSecret::create_or_open(tmp.path()).unwrap();
|
let api_secret = ApiSecret::create_or_open(tmp.path()).unwrap();
|
||||||
|
|||||||
@@ -44,6 +44,14 @@ const DEFAULT_REMOTE_SIGNER_REQUEST_TIMEOUT: Duration = Duration::from_secs(12);
|
|||||||
// Use TTY instead of stdin to capture passwords from users.
|
// Use TTY instead of stdin to capture passwords from users.
|
||||||
const USE_STDIN: bool = false;
|
const USE_STDIN: bool = false;
|
||||||
|
|
||||||
|
pub enum OnDecryptFailure {
|
||||||
|
/// If the key cache fails to decrypt, create a new cache.
|
||||||
|
CreateNew,
|
||||||
|
/// Return an error if the key cache fails to decrypt. This should only be
|
||||||
|
/// used in testing.
|
||||||
|
Error,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct KeystoreAndPassword {
|
pub struct KeystoreAndPassword {
|
||||||
pub keystore: Keystore,
|
pub keystore: Keystore,
|
||||||
pub password: Option<ZeroizeString>,
|
pub password: Option<ZeroizeString>,
|
||||||
@@ -106,6 +114,7 @@ pub enum Error {
|
|||||||
UnableToReadValidatorPassword(String),
|
UnableToReadValidatorPassword(String),
|
||||||
UnableToReadKeystoreFile(eth2_keystore::Error),
|
UnableToReadKeystoreFile(eth2_keystore::Error),
|
||||||
UnableToSaveKeyCache(key_cache::Error),
|
UnableToSaveKeyCache(key_cache::Error),
|
||||||
|
UnableToDecryptKeyCache(key_cache::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<LockfileError> for Error {
|
impl From<LockfileError> for Error {
|
||||||
@@ -606,7 +615,7 @@ impl InitializedValidators {
|
|||||||
let key_cache = KeyCache::open_or_create(&self.validators_dir)
|
let key_cache = KeyCache::open_or_create(&self.validators_dir)
|
||||||
.map_err(Error::UnableToOpenKeyCache)?;
|
.map_err(Error::UnableToOpenKeyCache)?;
|
||||||
let mut decrypted_key_cache = self
|
let mut decrypted_key_cache = self
|
||||||
.decrypt_key_cache(key_cache, &mut <_>::default())
|
.decrypt_key_cache(key_cache, &mut <_>::default(), OnDecryptFailure::CreateNew)
|
||||||
.await?;
|
.await?;
|
||||||
decrypted_key_cache.remove(&uuid);
|
decrypted_key_cache.remove(&uuid);
|
||||||
decrypted_key_cache
|
decrypted_key_cache
|
||||||
@@ -949,10 +958,11 @@ impl InitializedValidators {
|
|||||||
/// filesystem accesses for keystores that are already known. In the case that a keystore
|
/// filesystem accesses for keystores that are already known. In the case that a keystore
|
||||||
/// from the validator definitions is not yet in this map, it will be loaded from disk and
|
/// from the validator definitions is not yet in this map, it will be loaded from disk and
|
||||||
/// inserted into the map.
|
/// inserted into the map.
|
||||||
async fn decrypt_key_cache(
|
pub async fn decrypt_key_cache(
|
||||||
&self,
|
&self,
|
||||||
mut cache: KeyCache,
|
mut cache: KeyCache,
|
||||||
key_stores: &mut HashMap<PathBuf, Keystore>,
|
key_stores: &mut HashMap<PathBuf, Keystore>,
|
||||||
|
on_failure: OnDecryptFailure,
|
||||||
) -> Result<KeyCache, Error> {
|
) -> Result<KeyCache, Error> {
|
||||||
// Read relevant key stores from the filesystem.
|
// Read relevant key stores from the filesystem.
|
||||||
let mut definitions_map = HashMap::new();
|
let mut definitions_map = HashMap::new();
|
||||||
@@ -1020,11 +1030,13 @@ impl InitializedValidators {
|
|||||||
|
|
||||||
//decrypt
|
//decrypt
|
||||||
tokio::task::spawn_blocking(move || match cache.decrypt(passwords, public_keys) {
|
tokio::task::spawn_blocking(move || match cache.decrypt(passwords, public_keys) {
|
||||||
Ok(_) | Err(key_cache::Error::AlreadyDecrypted) => cache,
|
Ok(_) | Err(key_cache::Error::AlreadyDecrypted) => Ok(cache),
|
||||||
_ => KeyCache::new(),
|
_ if matches!(on_failure, OnDecryptFailure::CreateNew) => Ok(KeyCache::new()),
|
||||||
|
Err(e) => Err(e),
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.map_err(Error::TokioJoin)
|
.map_err(Error::TokioJoin)?
|
||||||
|
.map_err(Error::UnableToDecryptKeyCache)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scans `self.definitions` and attempts to initialize and validators which are not already
|
/// Scans `self.definitions` and attempts to initialize and validators which are not already
|
||||||
@@ -1062,7 +1074,8 @@ impl InitializedValidators {
|
|||||||
// Only decrypt cache when there is at least one local definition.
|
// Only decrypt cache when there is at least one local definition.
|
||||||
// Decrypting cache is a very expensive operation which is never used for web3signer.
|
// Decrypting cache is a very expensive operation which is never used for web3signer.
|
||||||
let mut key_cache = if has_local_definitions {
|
let mut key_cache = if has_local_definitions {
|
||||||
self.decrypt_key_cache(cache, &mut key_stores).await?
|
self.decrypt_key_cache(cache, &mut key_stores, OnDecryptFailure::CreateNew)
|
||||||
|
.await?
|
||||||
} else {
|
} else {
|
||||||
// Assign an empty KeyCache if all definitions are of the Web3Signer type.
|
// Assign an empty KeyCache if all definitions are of the Web3Signer type.
|
||||||
KeyCache::new()
|
KeyCache::new()
|
||||||
|
|||||||
@@ -307,6 +307,8 @@ pub mod tests {
|
|||||||
let result = run(self.import_config.clone()).await;
|
let result = run(self.import_config.clone()).await;
|
||||||
|
|
||||||
if result.is_ok() {
|
if result.is_ok() {
|
||||||
|
self.vc.ensure_key_cache_consistency().await;
|
||||||
|
|
||||||
let local_validators: Vec<ValidatorSpecification> = {
|
let local_validators: Vec<ValidatorSpecification> = {
|
||||||
let contents =
|
let contents =
|
||||||
fs::read_to_string(&self.import_config.validators_file_path).unwrap();
|
fs::read_to_string(&self.import_config.validators_file_path).unwrap();
|
||||||
|
|||||||
@@ -754,6 +754,9 @@ mod test {
|
|||||||
let src_vc_final_keystores = src_vc_client.get_keystores().await.unwrap().data;
|
let src_vc_final_keystores = src_vc_client.get_keystores().await.unwrap().data;
|
||||||
let dest_vc_final_keystores = dest_vc_client.get_keystores().await.unwrap().data;
|
let dest_vc_final_keystores = dest_vc_client.get_keystores().await.unwrap().data;
|
||||||
|
|
||||||
|
src_vc.ensure_key_cache_consistency().await;
|
||||||
|
dest_vc.ensure_key_cache_consistency().await;
|
||||||
|
|
||||||
match validators {
|
match validators {
|
||||||
Validators::All => {
|
Validators::All => {
|
||||||
assert!(
|
assert!(
|
||||||
|
|||||||
Reference in New Issue
Block a user