mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-15 02:42:38 +00:00
## Issue Addressed Resolves #1100 ## Proposed Changes * Implement the `SafeArith` trait for `Slot` and `Epoch`, so that methods like `safe_add` become available. * Tweak the `SafeArith` trait to allow a different `Rhs` type (analagous to `std::ops::Add`, etc). * Add a `legacy-arith` feature to `types` and `state_processing` that conditionally enables implementations of the `std` ops with saturating semantics. * Check compilation of `types` and `state_processing` _without_ `legacy-arith` on CI, thus guaranteeing that they only use the `SafeArith` primitives 🎉 ## Additional Info The `legacy-arith` feature gets turned on by all higher-level crates that depend on `state_processing` or `types`, thus allowing the beacon chain, networking, and other components to continue to rely on the availability of ops like `+`, `-`, `*`, etc. **This is a consensus-breaking change**, but brings us in line with the spec, and our incompatibilities shouldn't have been reachable with any valid configuration of Eth2 parameters.
44 lines
1.4 KiB
Rust
44 lines
1.4 KiB
Rust
use safe_arith::SafeArith;
|
|
use std::cmp::max;
|
|
use types::{BeaconStateError as Error, *};
|
|
|
|
/// Initiate the exit of the validator of the given `index`.
|
|
///
|
|
/// Spec v0.12.1
|
|
pub fn initiate_validator_exit<T: EthSpec>(
|
|
state: &mut BeaconState<T>,
|
|
index: usize,
|
|
spec: &ChainSpec,
|
|
) -> Result<(), Error> {
|
|
if index >= state.validators.len() {
|
|
return Err(Error::UnknownValidator(index as u64));
|
|
}
|
|
|
|
// Return if the validator already initiated exit
|
|
if state.validators[index].exit_epoch != spec.far_future_epoch {
|
|
return Ok(());
|
|
}
|
|
|
|
// Ensure the exit cache is built.
|
|
state.exit_cache.build(&state.validators, spec)?;
|
|
|
|
// Compute exit queue epoch
|
|
let delayed_epoch = state.compute_activation_exit_epoch(state.current_epoch(), spec)?;
|
|
let mut exit_queue_epoch = state
|
|
.exit_cache
|
|
.max_epoch()?
|
|
.map_or(delayed_epoch, |epoch| max(epoch, delayed_epoch));
|
|
let exit_queue_churn = state.exit_cache.get_churn_at(exit_queue_epoch)?;
|
|
|
|
if exit_queue_churn >= state.get_churn_limit(spec)? {
|
|
exit_queue_epoch.safe_add_assign(1)?;
|
|
}
|
|
|
|
state.exit_cache.record_validator_exit(exit_queue_epoch)?;
|
|
state.validators[index].exit_epoch = exit_queue_epoch;
|
|
state.validators[index].withdrawable_epoch =
|
|
exit_queue_epoch.safe_add(spec.min_validator_withdrawability_delay)?;
|
|
|
|
Ok(())
|
|
}
|