2019-03-06 06:14:54 +00:00
|
|
|
use super::errors::{ExitInvalid as Invalid, ExitValidationError as Error};
|
2019-03-06 04:22:45 +00:00
|
|
|
use ssz::SignedRoot;
|
|
|
|
use types::*;
|
|
|
|
|
2019-03-06 05:24:56 +00:00
|
|
|
/// Indicates if an `Exit` is valid to be included in a block in the current epoch of the given
|
|
|
|
/// state.
|
2019-03-06 04:22:45 +00:00
|
|
|
///
|
2019-03-06 05:24:56 +00:00
|
|
|
/// Returns `Ok(())` if the `Exit` is valid, otherwise indicates the reason for invalidity.
|
2019-03-06 04:22:45 +00:00
|
|
|
///
|
|
|
|
/// Spec v0.4.0
|
|
|
|
pub fn verify_exit(
|
|
|
|
state: &BeaconState,
|
|
|
|
exit: &VoluntaryExit,
|
|
|
|
spec: &ChainSpec,
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
let validator = state
|
|
|
|
.validator_registry
|
|
|
|
.get(exit.validator_index as usize)
|
2019-03-07 05:15:38 +00:00
|
|
|
.ok_or_else(|| Error::Invalid(Invalid::ValidatorUnknown(exit.validator_index)))?;
|
2019-03-06 04:22:45 +00:00
|
|
|
|
|
|
|
verify!(
|
|
|
|
validator.exit_epoch
|
|
|
|
> state.get_delayed_activation_exit_epoch(state.current_epoch(spec), spec),
|
|
|
|
Invalid::AlreadyExited
|
|
|
|
);
|
|
|
|
|
|
|
|
verify!(
|
|
|
|
state.current_epoch(spec) >= exit.epoch,
|
2019-03-06 05:24:56 +00:00
|
|
|
Invalid::FutureEpoch(state.current_epoch(spec), exit.epoch)
|
2019-03-06 04:22:45 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
let message = exit.signed_root();
|
|
|
|
let domain = spec.get_domain(exit.epoch, Domain::Exit, &state.fork);
|
|
|
|
|
|
|
|
verify!(
|
|
|
|
exit.signature
|
|
|
|
.verify(&message[..], domain, &validator.pubkey),
|
|
|
|
Invalid::BadSignature
|
|
|
|
);
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|