Skip to content

Commit

Permalink
Add JustificationAndFinalizationState
Browse files Browse the repository at this point in the history
  • Loading branch information
paulhauner committed Jun 28, 2022
1 parent 9212770 commit 6764608
Show file tree
Hide file tree
Showing 9 changed files with 164 additions and 24 deletions.
1 change: 0 additions & 1 deletion beacon_node/store/src/partial_beacon_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,6 @@ macro_rules! impl_try_into_beacon_state {
pubkey_cache: <_>::default(),
exit_cache: <_>::default(),
tree_hash_cache: <_>::default(),
previous_epoch_participation_cache: <_>::default(),

// Variant-specific fields
$(
Expand Down
32 changes: 24 additions & 8 deletions consensus/fork_choice/src/fork_choice.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::{ForkChoiceStore, InvalidationOperation};
use proto_array::{Block as ProtoBlock, ExecutionStatus, ProtoArrayForkChoice};
use ssz_derive::{Decode, Encode};
use state_processing::per_epoch_processing;
use std::cmp::Ordering;
use std::marker::PhantomData;
use std::time::Duration;
Expand Down Expand Up @@ -52,6 +53,8 @@ pub enum Error<T> {
finalized_checkpoint: Checkpoint,
},
UnrealizedVoteProcessing(state_processing::EpochProcessingError),
ParticipationCacheBuild(BeaconStateError),
ValidatorStatuses(BeaconStateError),
}

impl<T> From<InvalidAttestation> for Error<T> {
Expand Down Expand Up @@ -652,22 +655,35 @@ where

// Update unrealized justified/finalized checkpoints.
let (unrealized_justified_checkpoint, unrealized_finalized_checkpoint) = {
let justifiable_beacon_state = match block {
let justification_and_finalization_state = match block {
BeaconBlockRef::Merge(_) | BeaconBlockRef::Altair(_) => {
state_processing::per_epoch_processing::altair::process_justifiable(
state, spec,
let participation_cache =
per_epoch_processing::altair::ParticipationCache::new(state, spec)
.map_err(Error::ParticipationCacheBuild)?;
per_epoch_processing::altair::process_justification_and_finalization(
state,
&participation_cache,
)?
.0
}
BeaconBlockRef::Base(_) => {
state_processing::per_epoch_processing::base::process_justifiable(state, spec)?
.0
let mut validator_statuses =
per_epoch_processing::base::ValidatorStatuses::new(state, spec)
.map_err(Error::ValidatorStatuses)?;
validator_statuses
.process_attestations(state)
.map_err(Error::ValidatorStatuses)?;
per_epoch_processing::base::process_justification_and_finalization(
state,
&validator_statuses.total_balances,
spec,
)?
}
};

let unrealized_justified_checkpoint =
justifiable_beacon_state.current_justified_checkpoint;
let unrealized_finalized_checkpoint = justifiable_beacon_state.finalized_checkpoint;
justification_and_finalization_state.current_justified_checkpoint();
let unrealized_finalized_checkpoint =
justification_and_finalization_state.finalized_checkpoint();

// Update best known unrealized justified & finalized checkpoints
if unrealized_justified_checkpoint.epoch
Expand Down
2 changes: 2 additions & 0 deletions consensus/state_processing/src/per_epoch_processing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

pub use epoch_processing_summary::EpochProcessingSummary;
use errors::EpochProcessingError as Error;
pub use justification_and_finalization_state::JustificationAndFinalizationState;
pub use registry_updates::process_registry_updates;
use safe_arith::SafeArith;
pub use slashings::process_slashings;
Expand All @@ -14,6 +15,7 @@ pub mod effective_balance_updates;
pub mod epoch_processing_summary;
pub mod errors;
pub mod historical_roots_update;
pub mod justification_and_finalization_state;
pub mod registry_updates;
pub mod resets;
pub mod slashings;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ pub fn process_epoch<T: EthSpec>(
let sync_committee = state.current_sync_committee()?.clone();

// Justification and finalization.
process_justification_and_finalization(state, &participation_cache)?;
let justification_and_finalization_state =
process_justification_and_finalization(state, &participation_cache)?;
justification_and_finalization_state.apply_changes_to_state(state);

process_inactivity_updates(state, &participation_cache, spec)?;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use super::ParticipationCache;
use crate::per_epoch_processing::weigh_justification_and_finalization;
use crate::per_epoch_processing::Error;
use crate::per_epoch_processing::{
weigh_justification_and_finalization, JustificationAndFinalizationState,
};
use safe_arith::SafeArith;
use types::consts::altair::TIMELY_TARGET_FLAG_INDEX;
use types::{BeaconState, EthSpec};
Expand All @@ -9,9 +11,11 @@ use types::{BeaconState, EthSpec};
pub fn process_justification_and_finalization<T: EthSpec>(
state: &mut BeaconState<T>,
participation_cache: &ParticipationCache,
) -> Result<(), Error> {
) -> Result<JustificationAndFinalizationState<T>, Error> {
let justification_and_finalization_state = JustificationAndFinalizationState::new(state)?;

if state.current_epoch() <= T::genesis_epoch().safe_add(1)? {
return Ok(());
return Ok(justification_and_finalization_state);
}

let previous_epoch = state.previous_epoch();
Expand All @@ -24,7 +28,7 @@ pub fn process_justification_and_finalization<T: EthSpec>(
let previous_target_balance = previous_indices.total_balance()?;
let current_target_balance = current_indices.total_balance()?;
weigh_justification_and_finalization(
state,
justification_and_finalization_state,
total_active_balance,
previous_target_balance,
current_target_balance,
Expand Down
4 changes: 3 additions & 1 deletion consensus/state_processing/src/per_epoch_processing/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ pub fn process_epoch<T: EthSpec>(
validator_statuses.process_attestations(state)?;

// Justification and finalization.
process_justification_and_finalization(state, &validator_statuses.total_balances, spec)?;
let justification_and_finalization_state =
process_justification_and_finalization(state, &validator_statuses.total_balances, spec)?;
justification_and_finalization_state.apply_changes_to_state(state);

// Rewards and Penalties.
process_rewards_and_penalties(state, &mut validator_statuses, spec)?;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use crate::per_epoch_processing::base::TotalBalances;
use crate::per_epoch_processing::weigh_justification_and_finalization;
use crate::per_epoch_processing::Error;
use crate::per_epoch_processing::{
weigh_justification_and_finalization, JustificationAndFinalizationState,
};
use safe_arith::SafeArith;
use types::{BeaconState, ChainSpec, EthSpec};

Expand All @@ -9,13 +11,15 @@ pub fn process_justification_and_finalization<T: EthSpec>(
state: &mut BeaconState<T>,
total_balances: &TotalBalances,
_spec: &ChainSpec,
) -> Result<(), Error> {
) -> Result<JustificationAndFinalizationState<T>, Error> {
let justification_and_finalization_state = JustificationAndFinalizationState::new(state)?;

if state.current_epoch() <= T::genesis_epoch().safe_add(1)? {
return Ok(());
return Ok(justification_and_finalization_state);
}

weigh_justification_and_finalization(
state,
justification_and_finalization_state,
total_balances.current_epoch(),
total_balances.previous_epoch_target_attesters(),
total_balances.current_epoch_target_attesters(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
use crate::per_epoch_processing::Error;
use types::{BeaconState, BeaconStateError, BitVector, Checkpoint, Epoch, EthSpec, Hash256};

#[must_use = "this value must be applied to a state or explicitly dropped"]
pub struct JustificationAndFinalizationState<T: EthSpec> {
/*
* Immutable fields.
*/
previous_epoch: Epoch,
previous_epoch_target_root: Hash256,
current_epoch: Epoch,
current_epoch_target_root: Hash256,
/*
* Mutable fields.
*/
previous_justified_checkpoint: Checkpoint,
current_justified_checkpoint: Checkpoint,
finalized_checkpoint: Checkpoint,
justification_bits: BitVector<T::JustificationBitsLength>,
}

impl<T: EthSpec> JustificationAndFinalizationState<T> {
pub fn new(state: &BeaconState<T>) -> Result<Self, Error> {
let previous_epoch = state.previous_epoch();
let current_epoch = state.current_epoch();
Ok(Self {
previous_epoch,
previous_epoch_target_root: *state.get_block_root_at_epoch(previous_epoch)?,
current_epoch,
current_epoch_target_root: *state.get_block_root_at_epoch(current_epoch)?,
previous_justified_checkpoint: state.previous_justified_checkpoint(),
current_justified_checkpoint: state.current_justified_checkpoint(),
finalized_checkpoint: state.finalized_checkpoint(),
justification_bits: state.justification_bits().clone(),
})
}

pub fn apply_changes_to_state(self, state: &mut BeaconState<T>) {
let Self {
/*
* Immutable fields do not need to be used.
*/
previous_epoch: _,
previous_epoch_target_root: _,
current_epoch: _,
current_epoch_target_root: _,
/*
* Mutable fields *must* be used.
*/
previous_justified_checkpoint,
current_justified_checkpoint,
finalized_checkpoint,
justification_bits,
} = self;

*state.previous_justified_checkpoint_mut() = previous_justified_checkpoint;
*state.current_justified_checkpoint_mut() = current_justified_checkpoint;
*state.finalized_checkpoint_mut() = finalized_checkpoint;
*state.justification_bits_mut() = justification_bits;
}

pub fn previous_epoch(&self) -> Epoch {
self.previous_epoch
}

pub fn current_epoch(&self) -> Epoch {
self.current_epoch
}

pub fn get_block_root_at_epoch(&self, epoch: Epoch) -> Result<&Hash256, BeaconStateError> {
if epoch == self.previous_epoch {
Ok(&self.previous_epoch_target_root)
} else if epoch == self.current_epoch {
Ok(&self.current_epoch_target_root)
} else {
Err(BeaconStateError::SlotOutOfBounds)
}
}

pub fn previous_justified_checkpoint(&self) -> Checkpoint {
self.previous_justified_checkpoint
}

pub fn previous_justified_checkpoint_mut(&mut self) -> &mut Checkpoint {
&mut self.previous_justified_checkpoint
}

pub fn current_justified_checkpoint_mut(&mut self) -> &mut Checkpoint {
&mut self.current_justified_checkpoint
}

pub fn current_justified_checkpoint(&self) -> Checkpoint {
self.current_justified_checkpoint
}

pub fn finalized_checkpoint(&self) -> Checkpoint {
self.finalized_checkpoint
}

pub fn finalized_checkpoint_mut(&mut self) -> &mut Checkpoint {
&mut self.finalized_checkpoint
}

pub fn justification_bits(&self) -> &BitVector<T::JustificationBitsLength> {
&self.justification_bits
}

pub fn justification_bits_mut(&mut self) -> &mut BitVector<T::JustificationBitsLength> {
&mut self.justification_bits
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
use crate::per_epoch_processing::Error;
use crate::per_epoch_processing::{Error, JustificationAndFinalizationState};
use safe_arith::SafeArith;
use std::ops::Range;
use types::{BeaconState, Checkpoint, EthSpec};
use types::{Checkpoint, EthSpec};

/// Update the justified and finalized checkpoints for matching target attestations.
#[allow(clippy::if_same_then_else)] // For readability and consistency with spec.
pub fn weigh_justification_and_finalization<T: EthSpec>(
state: &mut BeaconState<T>,
mut state: JustificationAndFinalizationState<T>,
total_active_balance: u64,
previous_target_balance: u64,
current_target_balance: u64,
) -> Result<(), Error> {
) -> Result<JustificationAndFinalizationState<T>, Error> {
let previous_epoch = state.previous_epoch();
let current_epoch = state.current_epoch();

Expand Down Expand Up @@ -66,5 +66,5 @@ pub fn weigh_justification_and_finalization<T: EthSpec>(
*state.finalized_checkpoint_mut() = old_current_justified_checkpoint;
}

Ok(())
Ok(state)
}

0 comments on commit 6764608

Please sign in to comment.