Fixed a ton of state_processing stuff (#3642)

FIXME's:
 * consensus/fork_choice/src/fork_choice.rs
 * consensus/state_processing/src/per_epoch_processing/capella.rs
 * consensus/types/src/execution_payload_header.rs
 
TODO's:
 * consensus/state_processing/src/per_epoch_processing/capella/partial_withdrawals.rs
 * consensus/state_processing/src/per_epoch_processing/capella/full_withdrawals.rs
This commit is contained in:
ethDreamer
2022-10-14 17:35:10 -05:00
committed by GitHub
parent c1c5dc0a64
commit 221c433d62
21 changed files with 538 additions and 55 deletions

View File

@@ -45,11 +45,12 @@ pub fn slash_validator<T: EthSpec>(
validator_effective_balance.safe_div(spec.whistleblower_reward_quotient)?;
let proposer_reward = match state {
BeaconState::Base(_) => whistleblower_reward.safe_div(spec.proposer_reward_quotient)?,
BeaconState::Altair(_) | BeaconState::Merge(_) | BeaconState::Eip4844(_) => {
whistleblower_reward
.safe_mul(PROPOSER_WEIGHT)?
.safe_div(WEIGHT_DENOMINATOR)?
}
BeaconState::Altair(_)
| BeaconState::Merge(_)
| BeaconState::Capella(_)
| BeaconState::Eip4844(_) => whistleblower_reward
.safe_mul(PROPOSER_WEIGHT)?
.safe_div(WEIGHT_DENOMINATOR)?,
};
// Ensure the whistleblower index is in the validator registry.

View File

@@ -2,7 +2,9 @@ use super::per_block_processing::{
errors::BlockProcessingError, process_operations::process_deposit,
};
use crate::common::DepositDataTree;
use crate::upgrade::{upgrade_to_altair, upgrade_to_bellatrix};
use crate::upgrade::{
upgrade_to_altair, upgrade_to_bellatrix, upgrade_to_capella, upgrade_to_eip4844,
};
use safe_arith::{ArithError, SafeArith};
use tree_hash::TreeHash;
use types::DEPOSIT_TREE_DEPTH;
@@ -61,6 +63,7 @@ pub fn initialize_beacon_state_from_eth1<T: EthSpec>(
.bellatrix_fork_epoch
.map_or(false, |fork_epoch| fork_epoch == T::genesis_epoch())
{
// this will set state.latest_execution_payload_header = ExecutionPayloadHeaderMerge::default()
upgrade_to_bellatrix(&mut state, spec)?;
// Remove intermediate Altair fork from `state.fork`.
@@ -68,8 +71,43 @@ pub fn initialize_beacon_state_from_eth1<T: EthSpec>(
// Override latest execution payload header.
// See https://github.com/ethereum/consensus-specs/blob/v1.1.0/specs/bellatrix/beacon-chain.md#testing
*state.latest_execution_payload_header_mut()? =
execution_payload_header.unwrap_or_default();
if let Some(ExecutionPayloadHeader::Merge(ref header)) = execution_payload_header {
*state.latest_execution_payload_header_merge_mut()? = header.clone();
}
}
// Upgrade to capella if configured from genesis
if spec
.capella_fork_epoch
.map_or(false, |fork_epoch| fork_epoch == T::genesis_epoch())
{
upgrade_to_capella(&mut state, spec)?;
// Remove intermediate Bellatrix fork from `state.fork`.
state.fork_mut().previous_version = spec.capella_fork_version;
// Override latest execution payload header.
// See https://github.com/ethereum/consensus-specs/blob/dev/specs/capella/beacon-chain.md#testing
if let Some(ExecutionPayloadHeader::Capella(ref header)) = execution_payload_header {
*state.latest_execution_payload_header_capella_mut()? = header.clone();
}
}
// Upgrade to eip4844 if configured from genesis
if spec
.eip4844_fork_epoch
.map_or(false, |fork_epoch| fork_epoch == T::genesis_epoch())
{
upgrade_to_eip4844(&mut state, spec)?;
// Remove intermediate Capella fork from `state.fork`.
state.fork_mut().previous_version = spec.eip4844_fork_version;
// Override latest execution payload header.
// See https://github.com/ethereum/consensus-specs/blob/dev/specs/eip4844/beacon-chain.md#testing
if let Some(ExecutionPayloadHeader::Eip4844(header)) = execution_payload_header {
*state.latest_execution_payload_header_eip4844_mut()? = header;
}
}
// Now that we have our validators, initialize the caches (including the committees)

View File

@@ -154,7 +154,7 @@ pub fn per_block_processing<T: EthSpec, Payload: AbstractExecPayload<T>>(
// previous block.
if is_execution_enabled(state, block.body()) {
let payload = block.body().execution_payload()?;
process_execution_payload(state, payload, spec)?;
process_execution_payload::<T, Payload>(state, payload, spec)?;
}
process_randao(state, block, verify_randao, spec)?;
@@ -319,16 +319,16 @@ pub fn get_new_eth1_data<T: EthSpec>(
/// Contains a partial set of checks from the `process_execution_payload` function:
///
/// https://github.com/ethereum/consensus-specs/blob/v1.1.5/specs/merge/beacon-chain.md#process_execution_payload
pub fn partially_verify_execution_payload<T: EthSpec, Payload: ExecPayload<T>>(
pub fn partially_verify_execution_payload<'payload, T: EthSpec, Payload: AbstractExecPayload<T>>(
state: &BeaconState<T>,
payload: &Payload,
payload: Payload::Ref<'payload>,
spec: &ChainSpec,
) -> Result<(), BlockProcessingError> {
if is_merge_transition_complete(state) {
block_verify!(
payload.parent_hash() == state.latest_execution_payload_header()?.block_hash,
payload.parent_hash() == *state.latest_execution_payload_header()?.block_hash(),
BlockProcessingError::ExecutionHashChainIncontiguous {
expected: state.latest_execution_payload_header()?.block_hash,
expected: *state.latest_execution_payload_header()?.block_hash(),
found: payload.parent_hash(),
}
);
@@ -360,14 +360,33 @@ pub fn partially_verify_execution_payload<T: EthSpec, Payload: ExecPayload<T>>(
/// Partially equivalent to the `process_execution_payload` function:
///
/// https://github.com/ethereum/consensus-specs/blob/v1.1.5/specs/merge/beacon-chain.md#process_execution_payload
pub fn process_execution_payload<T: EthSpec, Payload: ExecPayload<T>>(
pub fn process_execution_payload<'payload, T: EthSpec, Payload: AbstractExecPayload<T>>(
state: &mut BeaconState<T>,
payload: &Payload,
payload: Payload::Ref<'payload>,
spec: &ChainSpec,
) -> Result<(), BlockProcessingError> {
partially_verify_execution_payload(state, payload, spec)?;
partially_verify_execution_payload::<T, Payload>(state, payload, spec)?;
*state.latest_execution_payload_header_mut()? = payload.to_execution_payload_header();
match state.latest_execution_payload_header_mut()? {
ExecutionPayloadHeaderRefMut::Merge(header_mut) => {
match payload.to_execution_payload_header() {
ExecutionPayloadHeader::Merge(header) => *header_mut = header,
_ => return Err(BlockProcessingError::IncorrectStateType),
}
}
ExecutionPayloadHeaderRefMut::Capella(header_mut) => {
match payload.to_execution_payload_header() {
ExecutionPayloadHeader::Capella(header) => *header_mut = header,
_ => return Err(BlockProcessingError::IncorrectStateType),
}
}
ExecutionPayloadHeaderRefMut::Eip4844(header_mut) => {
match payload.to_execution_payload_header() {
ExecutionPayloadHeader::Eip4844(header) => *header_mut = header,
_ => return Err(BlockProcessingError::IncorrectStateType),
}
}
}
Ok(())
}
@@ -380,7 +399,7 @@ pub fn process_execution_payload<T: EthSpec, Payload: ExecPayload<T>>(
pub fn is_merge_transition_complete<T: EthSpec>(state: &BeaconState<T>) -> bool {
state
.latest_execution_payload_header()
.map(|header| *header != <ExecutionPayloadHeader<T>>::default())
.map(|header| !header.is_default())
.unwrap_or(false)
}
/// https://github.com/ethereum/consensus-specs/blob/dev/specs/bellatrix/beacon-chain.md#is_merge_transition_block

View File

@@ -232,6 +232,7 @@ pub fn process_attestations<'a, T: EthSpec, Payload: AbstractExecPayload<T>>(
}
BeaconBlockBodyRef::Altair(_)
| BeaconBlockBodyRef::Merge(_)
| BeaconBlockBodyRef::Capella(_)
| BeaconBlockBodyRef::Eip4844(_) => {
altair::process_attestations(
state,

View File

@@ -8,7 +8,7 @@ use std::borrow::Cow;
use tree_hash::TreeHash;
use types::{
AbstractExecPayload, AggregateSignature, AttesterSlashing, BeaconBlockRef, BeaconState,
BeaconStateError, ChainSpec, DepositData, Domain, Epoch, EthSpec, ExecPayload, Fork, Hash256,
BeaconStateError, ChainSpec, DepositData, Domain, Epoch, EthSpec, Fork, Hash256,
InconsistentFork, IndexedAttestation, ProposerSlashing, PublicKey, PublicKeyBytes, Signature,
SignedAggregateAndProof, SignedBeaconBlock, SignedBeaconBlockHeader,
SignedContributionAndProof, SignedRoot, SignedVoluntaryExit, SigningData, Slot, SyncAggregate,

View File

@@ -11,6 +11,7 @@ pub use weigh_justification_and_finalization::weigh_justification_and_finalizati
pub mod altair;
pub mod base;
pub mod capella;
pub mod effective_balance_updates;
pub mod epoch_processing_summary;
pub mod errors;
@@ -37,9 +38,8 @@ pub fn process_epoch<T: EthSpec>(
match state {
BeaconState::Base(_) => base::process_epoch(state, spec),
BeaconState::Altair(_) | BeaconState::Merge(_) | BeaconState::Eip4844(_) => {
altair::process_epoch(state, spec)
}
BeaconState::Altair(_) | BeaconState::Merge(_) => altair::process_epoch(state, spec),
BeaconState::Capella(_) | BeaconState::Eip4844(_) => capella::process_epoch(state, spec),
}
}

View File

@@ -0,0 +1,81 @@
use super::{process_registry_updates, process_slashings, EpochProcessingSummary, Error};
use crate::per_epoch_processing::{
altair,
effective_balance_updates::process_effective_balance_updates,
historical_roots_update::process_historical_roots_update,
resets::{process_eth1_data_reset, process_randao_mixes_reset, process_slashings_reset},
};
pub use full_withdrawals::process_full_withdrawals;
pub use partial_withdrawals::process_partial_withdrawals;
use types::{BeaconState, ChainSpec, EthSpec, RelativeEpoch};
pub mod full_withdrawals;
pub mod partial_withdrawals;
pub fn process_epoch<T: EthSpec>(
state: &mut BeaconState<T>,
spec: &ChainSpec,
) -> Result<EpochProcessingSummary<T>, Error> {
// Ensure the committee caches are built.
state.build_committee_cache(RelativeEpoch::Previous, spec)?;
state.build_committee_cache(RelativeEpoch::Current, spec)?;
state.build_committee_cache(RelativeEpoch::Next, spec)?;
// Pre-compute participating indices and total balances.
let participation_cache = altair::ParticipationCache::new(state, spec)?;
let sync_committee = state.current_sync_committee()?.clone();
// Justification and finalization.
let justification_and_finalization_state =
altair::process_justification_and_finalization(state, &participation_cache)?;
justification_and_finalization_state.apply_changes_to_state(state);
altair::process_inactivity_updates(state, &participation_cache, spec)?;
// Rewards and Penalties.
altair::process_rewards_and_penalties(state, &participation_cache, spec)?;
// Registry Updates.
process_registry_updates(state, spec)?;
// Slashings.
process_slashings(
state,
participation_cache.current_epoch_total_active_balance(),
spec,
)?;
// Reset eth1 data votes.
process_eth1_data_reset(state)?;
// Update effective balances with hysteresis (lag).
process_effective_balance_updates(state, spec)?;
// Reset slashings
process_slashings_reset(state)?;
// Set randao mix
process_randao_mixes_reset(state)?;
// Set historical root accumulator
process_historical_roots_update(state)?;
// Rotate current/previous epoch participation
altair::process_participation_flag_updates(state)?;
altair::process_sync_committee_updates(state, spec)?;
// Withdrawals
process_full_withdrawals(state)?;
process_partial_withdrawals(state)?;
// Rotate the epoch caches to suit the epoch transition.
state.advance_caches(spec)?;
// FIXME: do we need a Capella variant for this?
Ok(EpochProcessingSummary::Altair {
participation_cache,
sync_committee,
})
}

View File

@@ -0,0 +1,10 @@
use crate::EpochProcessingError;
use types::beacon_state::BeaconState;
use types::eth_spec::EthSpec;
pub fn process_full_withdrawals<T: EthSpec>(
state: &mut BeaconState<T>,
) -> Result<(), EpochProcessingError> {
todo!("implement this");
Ok(())
}

View File

@@ -0,0 +1,10 @@
use crate::EpochProcessingError;
use types::beacon_state::BeaconState;
use types::eth_spec::EthSpec;
pub fn process_partial_withdrawals<T: EthSpec>(
state: &mut BeaconState<T>,
) -> Result<(), EpochProcessingError> {
todo!("implement this");
Ok(())
}

View File

@@ -1,5 +1,9 @@
pub mod altair;
pub mod capella;
pub mod eip4844;
pub mod merge;
pub use altair::upgrade_to_altair;
pub use capella::upgrade_to_capella;
pub use eip4844::upgrade_to_eip4844;
pub use merge::upgrade_to_bellatrix;

View File

@@ -0,0 +1,74 @@
use ssz_types::VariableList;
use std::mem;
use types::{BeaconState, BeaconStateCapella, BeaconStateError as Error, ChainSpec, EthSpec, Fork};
/// Transform a `Merge` state into an `Capella` state.
pub fn upgrade_to_capella<E: EthSpec>(
pre_state: &mut BeaconState<E>,
spec: &ChainSpec,
) -> Result<(), Error> {
let epoch = pre_state.current_epoch();
let pre = pre_state.as_merge_mut()?;
// Where possible, use something like `mem::take` to move fields from behind the &mut
// reference. For other fields that don't have a good default value, use `clone`.
//
// Fixed size vectors get cloned because replacing them would require the same size
// allocation as cloning.
let post = BeaconState::Capella(BeaconStateCapella {
// Versioning
genesis_time: pre.genesis_time,
genesis_validators_root: pre.genesis_validators_root,
slot: pre.slot,
fork: Fork {
previous_version: pre.fork.current_version,
current_version: spec.capella_fork_version,
epoch,
},
// History
latest_block_header: pre.latest_block_header.clone(),
block_roots: pre.block_roots.clone(),
state_roots: pre.state_roots.clone(),
historical_roots: mem::take(&mut pre.historical_roots),
// Eth1
eth1_data: pre.eth1_data.clone(),
eth1_data_votes: mem::take(&mut pre.eth1_data_votes),
eth1_deposit_index: pre.eth1_deposit_index,
// Registry
validators: mem::take(&mut pre.validators),
balances: mem::take(&mut pre.balances),
// Randomness
randao_mixes: pre.randao_mixes.clone(),
// Slashings
slashings: pre.slashings.clone(),
// `Participation
previous_epoch_participation: mem::take(&mut pre.previous_epoch_participation),
current_epoch_participation: mem::take(&mut pre.current_epoch_participation),
// Finality
justification_bits: pre.justification_bits.clone(),
previous_justified_checkpoint: pre.previous_justified_checkpoint,
current_justified_checkpoint: pre.current_justified_checkpoint,
finalized_checkpoint: pre.finalized_checkpoint,
// Inactivity
inactivity_scores: mem::take(&mut pre.inactivity_scores),
// Sync committees
current_sync_committee: pre.current_sync_committee.clone(),
next_sync_committee: pre.next_sync_committee.clone(),
// Execution
latest_execution_payload_header: pre.latest_execution_payload_header.upgrade_to_capella(),
// Withdrawals
withdrawal_queue: VariableList::empty(),
next_withdrawal_index: 0,
next_partial_withdrawal_validator_index: 0,
// Caches
total_active_balance: pre.total_active_balance,
committee_caches: mem::take(&mut pre.committee_caches),
pubkey_cache: mem::take(&mut pre.pubkey_cache),
exit_cache: mem::take(&mut pre.exit_cache),
tree_hash_cache: mem::take(&mut pre.tree_hash_cache),
});
*pre_state = post;
Ok(())
}

View File

@@ -0,0 +1,73 @@
use std::mem;
use types::{BeaconState, BeaconStateEip4844, BeaconStateError as Error, ChainSpec, EthSpec, Fork};
/// Transform a `Capella` state into an `Eip4844` state.
pub fn upgrade_to_eip4844<E: EthSpec>(
pre_state: &mut BeaconState<E>,
spec: &ChainSpec,
) -> Result<(), Error> {
let epoch = pre_state.current_epoch();
let pre = pre_state.as_capella_mut()?;
// Where possible, use something like `mem::take` to move fields from behind the &mut
// reference. For other fields that don't have a good default value, use `clone`.
//
// Fixed size vectors get cloned because replacing them would require the same size
// allocation as cloning.
let post = BeaconState::Eip4844(BeaconStateEip4844 {
// Versioning
genesis_time: pre.genesis_time,
genesis_validators_root: pre.genesis_validators_root,
slot: pre.slot,
fork: Fork {
previous_version: pre.fork.current_version,
current_version: spec.eip4844_fork_version,
epoch,
},
// History
latest_block_header: pre.latest_block_header.clone(),
block_roots: pre.block_roots.clone(),
state_roots: pre.state_roots.clone(),
historical_roots: mem::take(&mut pre.historical_roots),
// Eth1
eth1_data: pre.eth1_data.clone(),
eth1_data_votes: mem::take(&mut pre.eth1_data_votes),
eth1_deposit_index: pre.eth1_deposit_index,
// Registry
validators: mem::take(&mut pre.validators),
balances: mem::take(&mut pre.balances),
// Randomness
randao_mixes: pre.randao_mixes.clone(),
// Slashings
slashings: pre.slashings.clone(),
// `Participation
previous_epoch_participation: mem::take(&mut pre.previous_epoch_participation),
current_epoch_participation: mem::take(&mut pre.current_epoch_participation),
// Finality
justification_bits: pre.justification_bits.clone(),
previous_justified_checkpoint: pre.previous_justified_checkpoint,
current_justified_checkpoint: pre.current_justified_checkpoint,
finalized_checkpoint: pre.finalized_checkpoint,
// Inactivity
inactivity_scores: mem::take(&mut pre.inactivity_scores),
// Sync committees
current_sync_committee: pre.current_sync_committee.clone(),
next_sync_committee: pre.next_sync_committee.clone(),
// Execution
latest_execution_payload_header: pre.latest_execution_payload_header.upgrade_to_eip4844(),
// Withdrawals
withdrawal_queue: mem::take(&mut pre.withdrawal_queue),
next_withdrawal_index: pre.next_withdrawal_index,
next_partial_withdrawal_validator_index: pre.next_partial_withdrawal_validator_index,
// Caches
total_active_balance: pre.total_active_balance,
committee_caches: mem::take(&mut pre.committee_caches),
pubkey_cache: mem::take(&mut pre.pubkey_cache),
exit_cache: mem::take(&mut pre.exit_cache),
tree_hash_cache: mem::take(&mut pre.tree_hash_cache),
});
*pre_state = post;
Ok(())
}

View File

@@ -1,7 +1,7 @@
use std::mem;
use types::{
BeaconState, BeaconStateError as Error, BeaconStateMerge, ChainSpec, EthSpec,
ExecutionPayloadHeader, Fork,
ExecutionPayloadHeaderMerge, Fork,
};
/// Transform a `Altair` state into an `Merge` state.
@@ -57,7 +57,7 @@ pub fn upgrade_to_bellatrix<E: EthSpec>(
current_sync_committee: pre.current_sync_committee.clone(),
next_sync_committee: pre.next_sync_committee.clone(),
// Execution
latest_execution_payload_header: <ExecutionPayloadHeader<E>>::default(),
latest_execution_payload_header: <ExecutionPayloadHeaderMerge<E>>::default(),
// Caches
total_active_balance: pre.total_active_balance,
committee_caches: mem::take(&mut pre.committee_caches),