Skip to content

Commit

Permalink
Use spawn_blocking for validator keystores
Browse files Browse the repository at this point in the history
  • Loading branch information
paulhauner committed Sep 5, 2020
1 parent 1f0e035 commit be4e7cf
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 10 deletions.
34 changes: 24 additions & 10 deletions validator_client/src/initialized_validators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ pub enum Error {
PasswordUnknown(PathBuf),
/// There was an error reading from stdin.
UnableToReadPasswordFromUser(String),
/// There was an error running a tokio async task.
TokioJoin(tokio::task::JoinError),
}

/// A method used by a validator to sign messages.
Expand Down Expand Up @@ -279,7 +281,7 @@ pub struct InitializedValidators {

impl InitializedValidators {
/// Instantiates `Self`, initializing all validators in `definitions`.
pub fn from_definitions(
pub async fn from_definitions(
definitions: ValidatorDefinitions,
validators_dir: PathBuf,
strict_lockfiles: bool,
Expand All @@ -292,7 +294,7 @@ impl InitializedValidators {
validators: HashMap::default(),
log,
};
this.update_validators()?;
this.update_validators().await?;
Ok(this)
}

Expand Down Expand Up @@ -328,7 +330,7 @@ impl InitializedValidators {
/// validator will be removed from `self.validators`.
///
/// Saves the `ValidatorDefinitions` to file, even if no definitions were changed.
pub fn set_validator_status(
pub async fn set_validator_status(
&mut self,
voting_public_key: &PublicKey,
enabled: bool,
Expand All @@ -342,7 +344,7 @@ impl InitializedValidators {
def.enabled = enabled;
}

self.update_validators()?;
self.update_validators().await?;

self.definitions
.save(&self.validators_dir)
Expand All @@ -362,7 +364,7 @@ impl InitializedValidators {
/// A validator is considered "already known" and skipped if the public key is already known.
/// I.e., if there are two different definitions with the same public key then the second will
/// be ignored.
fn update_validators(&mut self) -> Result<(), Error> {
async fn update_validators(&mut self) -> Result<(), Error> {
for def in self.definitions.as_slice() {
if def.enabled {
match &def.signing_definition {
Expand All @@ -371,11 +373,23 @@ impl InitializedValidators {
continue;
}

match InitializedValidator::from_definition(
def.clone(),
self.strict_lockfiles,
&self.log,
) {
// Decoding a local keystore can take several seconds, therefore it's best
// to keep if off the core executor. This also has the fortunate effect of
// interrupting the potentially long-running task during shut down.
let inner_def = def.clone();
let strict_lockfiles = self.strict_lockfiles;
let inner_log = self.log.clone();
let result = tokio::task::spawn_blocking(move || {
InitializedValidator::from_definition(
inner_def,
strict_lockfiles,
&inner_log,
)
})
.await
.map_err(Error::TokioJoin)?;

match result {
Ok(init) => {
self.validators
.insert(init.voting_public_key().clone(), init);
Expand Down
1 change: 1 addition & 0 deletions validator_client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ impl<T: EthSpec> ProductionValidatorClient<T> {
config.strict_lockfiles,
log.clone(),
)
.await
.map_err(|e| format!("Unable to initialize validators: {:?}", e))?;

info!(
Expand Down

0 comments on commit be4e7cf

Please sign in to comment.