Altair consensus changes and refactors (#2279)

## Proposed Changes

Implement the consensus changes necessary for the upcoming Altair hard fork.

## Additional Info

This is quite a heavy refactor, with pivotal types like the `BeaconState` and `BeaconBlock` changing from structs to enums. This ripples through the whole codebase with field accesses changing to methods, e.g. `state.slot` => `state.slot()`.


Co-authored-by: realbigsean <seananderson33@gmail.com>
This commit is contained in:
Michael Sproul
2021-07-09 06:15:32 +00:00
parent 89361573d4
commit b4689e20c6
271 changed files with 9652 additions and 8444 deletions

View File

@@ -1,3 +1,4 @@
use crate::upgrade::upgrade_to_altair;
use crate::{per_epoch_processing::EpochProcessingSummary, *};
use safe_arith::{ArithError, SafeArith};
use types::*;
@@ -7,6 +8,7 @@ pub enum Error {
BeaconStateError(BeaconStateError),
EpochProcessingError(EpochProcessingError),
ArithError(ArithError),
InconsistentStateFork(InconsistentFork),
}
impl From<ArithError> for Error {
@@ -20,24 +22,34 @@ impl From<ArithError> for Error {
/// If the root of the supplied `state` is known, then it can be passed as `state_root`. If
/// `state_root` is `None`, the root of `state` will be computed using a cached tree hash.
/// Providing the `state_root` makes this function several orders of magniude faster.
///
/// Spec v0.12.1
pub fn per_slot_processing<T: EthSpec>(
state: &mut BeaconState<T>,
state_root: Option<Hash256>,
spec: &ChainSpec,
) -> Result<Option<EpochProcessingSummary>, Error> {
// Verify that the `BeaconState` instantiation matches the fork at `state.slot()`.
state
.fork_name(spec)
.map_err(Error::InconsistentStateFork)?;
cache_state(state, state_root)?;
let summary = if state.slot > spec.genesis_slot
&& state.slot.safe_add(1)?.safe_rem(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.safe_add_assign(1)?;
state.slot_mut().safe_add_assign(1)?;
// If the Altair fork epoch is reached, perform an irregular state upgrade.
if state.slot().safe_rem(T::slots_per_epoch())? == 0
&& spec.altair_fork_epoch == Some(state.current_epoch())
{
upgrade_to_altair(state, spec)?;
}
Ok(summary)
}
@@ -56,23 +68,23 @@ fn cache_state<T: EthSpec>(
// getter/setter functions.
//
// This is a bit hacky, however it gets the job done safely without lots of code.
let previous_slot = state.slot;
state.slot.safe_add_assign(1)?;
let previous_slot = state.slot();
state.slot_mut().safe_add_assign(1)?;
// Store the previous slot's post state transition root.
state.set_state_root(previous_slot, previous_state_root)?;
// Cache latest block header state root
if state.latest_block_header.state_root == Hash256::zero() {
state.latest_block_header.state_root = previous_state_root;
if state.latest_block_header().state_root == Hash256::zero() {
state.latest_block_header_mut().state_root = previous_state_root;
}
// Cache block root
let latest_block_root = state.latest_block_header.canonical_root();
let latest_block_root = state.latest_block_header().canonical_root();
state.set_block_root(previous_slot, latest_block_root)?;
// Set the state slot back to what it should be.
state.slot.safe_sub_assign(1)?;
state.slot_mut().safe_sub_assign(1)?;
Ok(())
}