From 04791dfc5826db5672ea9f6173c8ff96fc1c04bd Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Wed, 22 May 2019 11:41:15 +1000 Subject: [PATCH] Update `verify_exit` to spec v0.6.1 --- .../src/per_block_processing.rs | 4 +-- .../src/per_block_processing/errors.rs | 2 ++ .../src/per_block_processing/verify_exit.rs | 26 +++++++++++-------- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/eth2/state_processing/src/per_block_processing.rs b/eth2/state_processing/src/per_block_processing.rs index c66b8baea..1d729578e 100644 --- a/eth2/state_processing/src/per_block_processing.rs +++ b/eth2/state_processing/src/per_block_processing.rs @@ -1,4 +1,4 @@ -use crate::common::slash_validator; +use crate::common::{initiate_validator_exit, slash_validator}; use errors::{BlockInvalid as Invalid, BlockProcessingError as Error, IntoWithIndex}; use rayon::prelude::*; use tree_hash::{SignedRoot, TreeHash}; @@ -448,7 +448,7 @@ pub fn process_exits( // Update the state in series. for exit in voluntary_exits { - state.initiate_validator_exit(exit.validator_index as usize); + initiate_validator_exit(state, exit.validator_index as usize, spec)?; } Ok(()) diff --git a/eth2/state_processing/src/per_block_processing/errors.rs b/eth2/state_processing/src/per_block_processing/errors.rs index 747664b94..b6a1fd629 100644 --- a/eth2/state_processing/src/per_block_processing/errors.rs +++ b/eth2/state_processing/src/per_block_processing/errors.rs @@ -348,6 +348,8 @@ pub enum ExitValidationError { /// Describes why an object is invalid. #[derive(Debug, PartialEq)] pub enum ExitInvalid { + /// The specified validator is not active. + NotActive(u64), /// The specified validator is not in the state's validator registry. ValidatorUnknown(u64), /// The specified validator has a non-maximum exit epoch. diff --git a/eth2/state_processing/src/per_block_processing/verify_exit.rs b/eth2/state_processing/src/per_block_processing/verify_exit.rs index 865942ef4..2a3a29b3f 100644 --- a/eth2/state_processing/src/per_block_processing/verify_exit.rs +++ b/eth2/state_processing/src/per_block_processing/verify_exit.rs @@ -7,7 +7,7 @@ use types::*; /// /// Returns `Ok(())` if the `Exit` is valid, otherwise indicates the reason for invalidity. /// -/// Spec v0.5.1 +/// Spec v0.6.1 pub fn verify_exit( state: &BeaconState, exit: &VoluntaryExit, @@ -17,6 +17,8 @@ pub fn verify_exit( } /// Like `verify_exit` but doesn't run checks which may become true in future states. +/// +/// Spec v0.6.1 pub fn verify_exit_time_independent_only( state: &BeaconState, exit: &VoluntaryExit, @@ -26,6 +28,8 @@ pub fn verify_exit_time_independent_only( } /// Parametric version of `verify_exit` that skips some checks if `time_independent_only` is true. +/// +/// Spec v0.6.1 fn verify_exit_parametric( state: &BeaconState, exit: &VoluntaryExit, @@ -37,18 +41,18 @@ fn verify_exit_parametric( .get(exit.validator_index as usize) .ok_or_else(|| Error::Invalid(Invalid::ValidatorUnknown(exit.validator_index)))?; + // Verify the validator is active. + verify!( + validator.is_active_at(state.current_epoch()), + Invalid::NotActive(exit.validator_index) + ); + // Verify that the validator has not yet exited. verify!( validator.exit_epoch == spec.far_future_epoch, Invalid::AlreadyExited(exit.validator_index) ); - // Verify that the validator has not yet initiated. - verify!( - !validator.initiated_exit, - Invalid::AlreadyInitiatedExited(exit.validator_index) - ); - // Exits must specify an epoch when they become valid; they are not valid before then. verify!( time_independent_only || state.current_epoch() >= exit.epoch, @@ -58,8 +62,8 @@ fn verify_exit_parametric( } ); - // Must have been in the validator set long enough. - let lifespan = state.slot.epoch(spec.slots_per_epoch) - validator.activation_epoch; + // Verify the validator has been active long enough. + let lifespan = state.current_epoch() - validator.activation_epoch; verify!( lifespan >= spec.persistent_committee_period, Invalid::TooYoungToLeave { @@ -68,9 +72,9 @@ fn verify_exit_parametric( } ); + // Verify signature. let message = exit.signed_root(); - let domain = spec.get_domain(exit.epoch, Domain::Exit, &state.fork); - + let domain = spec.get_domain(exit.epoch, Domain::VoluntaryExit, &state.fork); verify!( exit.signature .verify(&message[..], domain, &validator.pubkey),