Realized unrealized experimentation (#3322)

## Issue Addressed

Add a flag that optionally enables unrealized vote tracking.  Would like to test out on testnets and benchmark differences in methods of vote tracking. This PR includes a DB schema upgrade to enable to new vote tracking style.


Co-authored-by: realbigsean <sean@sigmaprime.io>
Co-authored-by: Paul Hauner <paul@paulhauner.com>
Co-authored-by: sean <seananderson33@gmail.com>
Co-authored-by: Mac L <mjladson@pm.me>
This commit is contained in:
realbigsean
2022-07-25 23:53:26 +00:00
parent bb5a6d2cca
commit 20ebf1f3c1
47 changed files with 1254 additions and 338 deletions

View File

@@ -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;
@@ -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;

View File

@@ -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)?;

View File

@@ -1,17 +1,21 @@
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};
/// Update the justified and finalized checkpoints for matching target attestations.
pub fn process_justification_and_finalization<T: EthSpec>(
state: &mut BeaconState<T>,
state: &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();
@@ -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,

View File

@@ -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)?;

View File

@@ -1,21 +1,25 @@
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};
/// Update the justified and finalized checkpoints for matching target attestations.
pub fn process_justification_and_finalization<T: EthSpec>(
state: &mut BeaconState<T>,
state: &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(),

View File

@@ -0,0 +1,115 @@
use types::{BeaconState, BeaconStateError, BitVector, Checkpoint, Epoch, EthSpec, Hash256};
/// This is a subset of the `BeaconState` which is used to compute justification and finality
/// without modifying the `BeaconState`.
///
/// A `JustificationAndFinalizationState` can be created from a `BeaconState` to compute
/// justification/finality changes and then applied to a `BeaconState` to enshrine those changes.
#[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: Result<Hash256, BeaconStateError>,
current_epoch: Epoch,
current_epoch_target_root: Result<Hash256, BeaconStateError>,
/*
* 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>) -> Self {
let previous_epoch = state.previous_epoch();
let current_epoch = state.current_epoch();
Self {
previous_epoch,
previous_epoch_target_root: state.get_block_root_at_epoch(previous_epoch).copied(),
current_epoch,
current_epoch_target_root: state.get_block_root_at_epoch(current_epoch).copied(),
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 {
self.previous_epoch_target_root.clone()
} else if epoch == self.current_epoch {
self.current_epoch_target_root.clone()
} 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
}
}

View File

@@ -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();
@@ -24,7 +24,7 @@ pub fn weigh_justification_and_finalization<T: EthSpec>(
if previous_target_balance.safe_mul(3)? >= total_active_balance.safe_mul(2)? {
*state.current_justified_checkpoint_mut() = Checkpoint {
epoch: previous_epoch,
root: *state.get_block_root_at_epoch(previous_epoch)?,
root: state.get_block_root_at_epoch(previous_epoch)?,
};
state.justification_bits_mut().set(1, true)?;
}
@@ -32,7 +32,7 @@ pub fn weigh_justification_and_finalization<T: EthSpec>(
if current_target_balance.safe_mul(3)? >= total_active_balance.safe_mul(2)? {
*state.current_justified_checkpoint_mut() = Checkpoint {
epoch: current_epoch,
root: *state.get_block_root_at_epoch(current_epoch)?,
root: state.get_block_root_at_epoch(current_epoch)?,
};
state.justification_bits_mut().set(0, true)?;
}
@@ -66,5 +66,5 @@ pub fn weigh_justification_and_finalization<T: EthSpec>(
*state.finalized_checkpoint_mut() = old_current_justified_checkpoint;
}
Ok(())
Ok(state)
}