mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-14 18:32:42 +00:00
Remove saturating arith from state_processing (#1644)
## 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.
This commit is contained in:
@@ -1,10 +1,18 @@
|
||||
use crate::{per_epoch_processing::EpochProcessingSummary, *};
|
||||
use safe_arith::{ArithError, SafeArith};
|
||||
use types::*;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Error {
|
||||
BeaconStateError(BeaconStateError),
|
||||
EpochProcessingError(EpochProcessingError),
|
||||
ArithError(ArithError),
|
||||
}
|
||||
|
||||
impl From<ArithError> for Error {
|
||||
fn from(e: ArithError) -> Self {
|
||||
Self::ArithError(e)
|
||||
}
|
||||
}
|
||||
|
||||
/// Advances a state forward by one slot, performing per-epoch processing if required.
|
||||
@@ -21,14 +29,15 @@ pub fn per_slot_processing<T: EthSpec>(
|
||||
) -> Result<Option<EpochProcessingSummary>, Error> {
|
||||
cache_state(state, state_root)?;
|
||||
|
||||
let summary = if state.slot > spec.genesis_slot && (state.slot + 1) % T::slots_per_epoch() == 0
|
||||
let summary = if state.slot > spec.genesis_slot
|
||||
&& state.slot.safe_add(1)?.safe_rem(T::slots_per_epoch())? == 0
|
||||
{
|
||||
Some(per_epoch_processing(state, spec)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
state.slot += 1;
|
||||
state.slot.safe_add_assign(1)?;
|
||||
|
||||
Ok(summary)
|
||||
}
|
||||
@@ -48,7 +57,7 @@ fn cache_state<T: EthSpec>(
|
||||
//
|
||||
// This is a bit hacky, however it gets the job safely without lots of code.
|
||||
let previous_slot = state.slot;
|
||||
state.slot += 1;
|
||||
state.slot.safe_add_assign(1)?;
|
||||
|
||||
// Store the previous slot's post state transition root.
|
||||
state.set_state_root(previous_slot, previous_state_root)?;
|
||||
@@ -63,7 +72,7 @@ fn cache_state<T: EthSpec>(
|
||||
state.set_block_root(previous_slot, latest_block_root)?;
|
||||
|
||||
// Set the state slot back to what it should be.
|
||||
state.slot -= 1;
|
||||
state.slot.safe_sub_assign(1)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user