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:
parent
c1c5dc0a64
commit
221c433d62
@ -428,7 +428,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
|
||||
}
|
||||
|
||||
/// Fetch a block from the store, ignoring which fork variant it *should* be for.
|
||||
pub fn get_block_any_variant<Payload: ExecPayload<E>>(
|
||||
pub fn get_block_any_variant<Payload: AbstractExecPayload<E>>(
|
||||
&self,
|
||||
block_root: &Hash256,
|
||||
) -> Result<Option<SignedBeaconBlock<E, Payload>>, Error> {
|
||||
@ -439,7 +439,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
|
||||
///
|
||||
/// This is useful for e.g. ignoring the slot-indicated fork to forcefully load a block as if it
|
||||
/// were for a different fork.
|
||||
pub fn get_block_with<Payload: ExecPayload<E>>(
|
||||
pub fn get_block_with<Payload: AbstractExecPayload<E>>(
|
||||
&self,
|
||||
block_root: &Hash256,
|
||||
decoder: impl FnOnce(&[u8]) -> Result<SignedBeaconBlock<E, Payload>, ssz::DecodeError>,
|
||||
|
@ -1,7 +1,35 @@
|
||||
use crate::{DBColumn, Error, StoreItem};
|
||||
use ssz::{Decode, Encode};
|
||||
use types::{EthSpec, ExecutionPayload};
|
||||
use types::{
|
||||
EthSpec, ExecutionPayload, ExecutionPayloadCapella, ExecutionPayloadEip4844,
|
||||
ExecutionPayloadMerge,
|
||||
};
|
||||
|
||||
macro_rules! impl_store_item {
|
||||
($ty_name:ident) => {
|
||||
impl<E: EthSpec> StoreItem for $ty_name<E> {
|
||||
fn db_column() -> DBColumn {
|
||||
DBColumn::ExecPayload
|
||||
}
|
||||
|
||||
fn as_store_bytes(&self) -> Vec<u8> {
|
||||
self.as_ssz_bytes()
|
||||
}
|
||||
|
||||
fn from_store_bytes(bytes: &[u8]) -> Result<Self, Error> {
|
||||
Ok(Self::from_ssz_bytes(bytes)?)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
impl_store_item!(ExecutionPayloadMerge);
|
||||
impl_store_item!(ExecutionPayloadCapella);
|
||||
impl_store_item!(ExecutionPayloadEip4844);
|
||||
|
||||
/// This fork-agnostic implementation should be only used for writing.
|
||||
///
|
||||
/// It is very inefficient at reading, and decoding the desired fork-specific variant is recommended
|
||||
/// instead.
|
||||
impl<E: EthSpec> StoreItem for ExecutionPayload<E> {
|
||||
fn db_column() -> DBColumn {
|
||||
DBColumn::ExecPayload
|
||||
@ -12,6 +40,13 @@ impl<E: EthSpec> StoreItem for ExecutionPayload<E> {
|
||||
}
|
||||
|
||||
fn from_store_bytes(bytes: &[u8]) -> Result<Self, Error> {
|
||||
Ok(Self::from_ssz_bytes(bytes)?)
|
||||
ExecutionPayloadEip4844::from_ssz_bytes(bytes)
|
||||
.map(Self::Eip4844)
|
||||
.or_else(|_| {
|
||||
ExecutionPayloadCapella::from_ssz_bytes(bytes)
|
||||
.map(Self::Capella)
|
||||
.or_else(|_| ExecutionPayloadMerge::from_ssz_bytes(bytes).map(Self::Merge))
|
||||
})
|
||||
.map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ use types::*;
|
||||
///
|
||||
/// Utilises lazy-loading from separate storage for its vector fields.
|
||||
#[superstruct(
|
||||
variants(Base, Altair, Merge, Eip4844),
|
||||
variants(Base, Altair, Merge, Capella, Eip4844),
|
||||
variant_attributes(derive(Debug, PartialEq, Clone, Encode, Decode))
|
||||
)]
|
||||
#[derive(Debug, PartialEq, Clone, Encode)]
|
||||
@ -66,9 +66,9 @@ where
|
||||
pub current_epoch_attestations: VariableList<PendingAttestation<T>, T::MaxPendingAttestations>,
|
||||
|
||||
// Participation (Altair and later)
|
||||
#[superstruct(only(Altair, Merge, Eip4844))]
|
||||
#[superstruct(only(Altair, Merge, Capella, Eip4844))]
|
||||
pub previous_epoch_participation: VariableList<ParticipationFlags, T::ValidatorRegistryLimit>,
|
||||
#[superstruct(only(Altair, Merge, Eip4844))]
|
||||
#[superstruct(only(Altair, Merge, Capella, Eip4844))]
|
||||
pub current_epoch_participation: VariableList<ParticipationFlags, T::ValidatorRegistryLimit>,
|
||||
|
||||
// Finality
|
||||
@ -78,18 +78,39 @@ where
|
||||
pub finalized_checkpoint: Checkpoint,
|
||||
|
||||
// Inactivity
|
||||
#[superstruct(only(Altair, Merge, Eip4844))]
|
||||
#[superstruct(only(Altair, Merge, Capella, Eip4844))]
|
||||
pub inactivity_scores: VariableList<u64, T::ValidatorRegistryLimit>,
|
||||
|
||||
// Light-client sync committees
|
||||
#[superstruct(only(Altair, Merge, Eip4844))]
|
||||
#[superstruct(only(Altair, Merge, Capella, Eip4844))]
|
||||
pub current_sync_committee: Arc<SyncCommittee<T>>,
|
||||
#[superstruct(only(Altair, Merge, Eip4844))]
|
||||
#[superstruct(only(Altair, Merge, Capella, Eip4844))]
|
||||
pub next_sync_committee: Arc<SyncCommittee<T>>,
|
||||
|
||||
// Execution
|
||||
#[superstruct(only(Merge, Eip4844))]
|
||||
pub latest_execution_payload_header: ExecutionPayloadHeader<T>,
|
||||
#[superstruct(
|
||||
only(Merge),
|
||||
partial_getter(rename = "latest_execution_payload_header_merge")
|
||||
)]
|
||||
pub latest_execution_payload_header: ExecutionPayloadHeaderMerge<T>,
|
||||
#[superstruct(
|
||||
only(Capella),
|
||||
partial_getter(rename = "latest_execution_payload_header_capella")
|
||||
)]
|
||||
pub latest_execution_payload_header: ExecutionPayloadHeaderCapella<T>,
|
||||
#[superstruct(
|
||||
only(Eip4844),
|
||||
partial_getter(rename = "latest_execution_payload_header_eip4844")
|
||||
)]
|
||||
pub latest_execution_payload_header: ExecutionPayloadHeaderEip4844<T>,
|
||||
|
||||
// Withdrawals
|
||||
#[superstruct(only(Capella, Eip4844))]
|
||||
pub withdrawal_queue: VariableList<Withdrawal, T::WithdrawalQueueLimit>,
|
||||
#[superstruct(only(Capella, Eip4844))]
|
||||
pub next_withdrawal_index: u64,
|
||||
#[superstruct(only(Capella, Eip4844))]
|
||||
pub next_partial_withdrawal_validator_index: u64,
|
||||
}
|
||||
|
||||
/// Implement the conversion function from BeaconState -> PartialBeaconState.
|
||||
@ -178,6 +199,23 @@ impl<T: EthSpec> PartialBeaconState<T> {
|
||||
latest_execution_payload_header
|
||||
]
|
||||
),
|
||||
BeaconState::Capella(s) => impl_from_state_forgetful!(
|
||||
s,
|
||||
outer,
|
||||
Capella,
|
||||
PartialBeaconStateCapella,
|
||||
[
|
||||
previous_epoch_participation,
|
||||
current_epoch_participation,
|
||||
current_sync_committee,
|
||||
next_sync_committee,
|
||||
inactivity_scores,
|
||||
latest_execution_payload_header,
|
||||
withdrawal_queue,
|
||||
next_withdrawal_index,
|
||||
next_partial_withdrawal_validator_index
|
||||
]
|
||||
),
|
||||
BeaconState::Eip4844(s) => impl_from_state_forgetful!(
|
||||
s,
|
||||
outer,
|
||||
@ -189,7 +227,10 @@ impl<T: EthSpec> PartialBeaconState<T> {
|
||||
current_sync_committee,
|
||||
next_sync_committee,
|
||||
inactivity_scores,
|
||||
latest_execution_payload_header
|
||||
latest_execution_payload_header,
|
||||
withdrawal_queue,
|
||||
next_withdrawal_index,
|
||||
next_partial_withdrawal_validator_index
|
||||
]
|
||||
),
|
||||
}
|
||||
@ -379,6 +420,22 @@ impl<E: EthSpec> TryInto<BeaconState<E>> for PartialBeaconState<E> {
|
||||
latest_execution_payload_header
|
||||
]
|
||||
),
|
||||
PartialBeaconState::Capella(inner) => impl_try_into_beacon_state!(
|
||||
inner,
|
||||
Capella,
|
||||
BeaconStateCapella,
|
||||
[
|
||||
previous_epoch_participation,
|
||||
current_epoch_participation,
|
||||
current_sync_committee,
|
||||
next_sync_committee,
|
||||
inactivity_scores,
|
||||
latest_execution_payload_header,
|
||||
withdrawal_queue,
|
||||
next_withdrawal_index,
|
||||
next_partial_withdrawal_validator_index
|
||||
]
|
||||
),
|
||||
PartialBeaconState::Eip4844(inner) => impl_try_into_beacon_state!(
|
||||
inner,
|
||||
Eip4844,
|
||||
@ -389,7 +446,10 @@ impl<E: EthSpec> TryInto<BeaconState<E>> for PartialBeaconState<E> {
|
||||
current_sync_committee,
|
||||
next_sync_committee,
|
||||
inactivity_scores,
|
||||
latest_execution_payload_header
|
||||
latest_execution_payload_header,
|
||||
withdrawal_queue,
|
||||
next_withdrawal_index,
|
||||
next_partial_withdrawal_validator_index
|
||||
]
|
||||
),
|
||||
};
|
||||
|
@ -12,9 +12,10 @@ use std::collections::BTreeSet;
|
||||
use std::marker::PhantomData;
|
||||
use std::time::Duration;
|
||||
use types::{
|
||||
consts::merge::INTERVALS_PER_SLOT, AttestationShufflingId, AttesterSlashing, BeaconBlockRef,
|
||||
BeaconState, BeaconStateError, ChainSpec, Checkpoint, Epoch, EthSpec, ExecPayload,
|
||||
ExecutionBlockHash, Hash256, IndexedAttestation, RelativeEpoch, SignedBeaconBlock, Slot,
|
||||
consts::merge::INTERVALS_PER_SLOT, AbstractExecPayload, AttestationShufflingId,
|
||||
AttesterSlashing, BeaconBlockRef, BeaconState, BeaconStateError, ChainSpec, Checkpoint, Epoch,
|
||||
EthSpec, ExecPayload, ExecutionBlockHash, Hash256, IndexedAttestation, RelativeEpoch,
|
||||
SignedBeaconBlock, Slot,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -665,7 +666,7 @@ where
|
||||
/// The supplied block **must** pass the `state_transition` function as it will not be run
|
||||
/// here.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn on_block<Payload: ExecPayload<E>>(
|
||||
pub fn on_block<Payload: AbstractExecPayload<E>>(
|
||||
&mut self,
|
||||
system_time_current_slot: Slot,
|
||||
block: BeaconBlockRef<E, Payload>,
|
||||
@ -777,7 +778,10 @@ where
|
||||
(parent_justified, parent_finalized)
|
||||
} else {
|
||||
let justification_and_finalization_state = match block {
|
||||
// FIXME: verify this is correct for Capella/Eip4844 because
|
||||
// epoch processing changes in Capella..
|
||||
BeaconBlockRef::Eip4844(_)
|
||||
| BeaconBlockRef::Capella(_)
|
||||
| BeaconBlockRef::Merge(_)
|
||||
| BeaconBlockRef::Altair(_) => {
|
||||
let participation_cache =
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::collections::BTreeSet;
|
||||
use std::fmt::Debug;
|
||||
use types::{BeaconBlockRef, BeaconState, Checkpoint, EthSpec, ExecPayload, Hash256, Slot};
|
||||
use types::{AbstractExecPayload, BeaconBlockRef, BeaconState, Checkpoint, EthSpec, Hash256, Slot};
|
||||
|
||||
/// Approximates the `Store` in "Ethereum 2.0 Phase 0 -- Beacon Chain Fork Choice":
|
||||
///
|
||||
@ -33,7 +33,7 @@ pub trait ForkChoiceStore<T: EthSpec>: Sized {
|
||||
|
||||
/// Called whenever `ForkChoice::on_block` has verified a block, but not yet added it to fork
|
||||
/// choice. Allows the implementer to performing caching or other housekeeping duties.
|
||||
fn on_verified_block<Payload: ExecPayload<T>>(
|
||||
fn on_verified_block<Payload: AbstractExecPayload<T>>(
|
||||
&mut self,
|
||||
block: BeaconBlockRef<T, Payload>,
|
||||
block_root: Hash256,
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
})
|
||||
}
|
@ -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(())
|
||||
}
|
@ -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(())
|
||||
}
|
@ -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;
|
||||
|
74
consensus/state_processing/src/upgrade/capella.rs
Normal file
74
consensus/state_processing/src/upgrade/capella.rs
Normal 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(())
|
||||
}
|
73
consensus/state_processing/src/upgrade/eip4844.rs
Normal file
73
consensus/state_processing/src/upgrade/eip4844.rs
Normal 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(())
|
||||
}
|
@ -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),
|
||||
|
@ -718,6 +718,23 @@ impl<T: EthSpec> BeaconState<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn latest_execution_payload_header_mut(
|
||||
&mut self,
|
||||
) -> Result<ExecutionPayloadHeaderRefMut<T>, Error> {
|
||||
match self {
|
||||
BeaconState::Base(_) | BeaconState::Altair(_) => Err(Error::IncorrectStateVariant),
|
||||
BeaconState::Merge(state) => Ok(ExecutionPayloadHeaderRefMut::Merge(
|
||||
&mut state.latest_execution_payload_header,
|
||||
)),
|
||||
BeaconState::Capella(state) => Ok(ExecutionPayloadHeaderRefMut::Capella(
|
||||
&mut state.latest_execution_payload_header,
|
||||
)),
|
||||
BeaconState::Eip4844(state) => Ok(ExecutionPayloadHeaderRefMut::Eip4844(
|
||||
&mut state.latest_execution_payload_header,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Return `true` if the validator who produced `slot_signature` is eligible to aggregate.
|
||||
///
|
||||
/// Spec v0.12.1
|
||||
|
@ -65,6 +65,73 @@ pub struct ExecutionPayloadHeader<T: EthSpec> {
|
||||
pub withdrawals_root: Hash256,
|
||||
}
|
||||
|
||||
impl<'a, T: EthSpec> ExecutionPayloadHeaderRef<'a, T> {
|
||||
// FIXME: maybe this could be a derived trait..
|
||||
pub fn is_default(self) -> bool {
|
||||
match self {
|
||||
ExecutionPayloadHeaderRef::Merge(header) => {
|
||||
*header == ExecutionPayloadHeaderMerge::default()
|
||||
}
|
||||
ExecutionPayloadHeaderRef::Capella(header) => {
|
||||
*header == ExecutionPayloadHeaderCapella::default()
|
||||
}
|
||||
ExecutionPayloadHeaderRef::Eip4844(header) => {
|
||||
*header == ExecutionPayloadHeaderEip4844::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: EthSpec> ExecutionPayloadHeaderMerge<T> {
|
||||
pub fn upgrade_to_capella(&self) -> ExecutionPayloadHeaderCapella<T> {
|
||||
// TODO: if this is correct we should calculate and hardcode this..
|
||||
let empty_withdrawals_root =
|
||||
VariableList::<Withdrawal, T::MaxWithdrawalsPerPayload>::empty().tree_hash_root();
|
||||
ExecutionPayloadHeaderCapella {
|
||||
parent_hash: self.parent_hash,
|
||||
fee_recipient: self.fee_recipient,
|
||||
state_root: self.state_root,
|
||||
receipts_root: self.receipts_root,
|
||||
logs_bloom: self.logs_bloom.clone(),
|
||||
prev_randao: self.prev_randao,
|
||||
block_number: self.block_number,
|
||||
gas_limit: self.gas_limit,
|
||||
gas_used: self.gas_used,
|
||||
timestamp: self.timestamp,
|
||||
extra_data: self.extra_data.clone(),
|
||||
base_fee_per_gas: self.base_fee_per_gas,
|
||||
block_hash: self.block_hash,
|
||||
transactions_root: self.transactions_root,
|
||||
// FIXME: the spec doesn't seem to define what to do here..
|
||||
withdrawals_root: empty_withdrawals_root,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: EthSpec> ExecutionPayloadHeaderCapella<T> {
|
||||
pub fn upgrade_to_eip4844(&self) -> ExecutionPayloadHeaderEip4844<T> {
|
||||
ExecutionPayloadHeaderEip4844 {
|
||||
parent_hash: self.parent_hash,
|
||||
fee_recipient: self.fee_recipient,
|
||||
state_root: self.state_root,
|
||||
receipts_root: self.receipts_root,
|
||||
logs_bloom: self.logs_bloom.clone(),
|
||||
prev_randao: self.prev_randao,
|
||||
block_number: self.block_number,
|
||||
gas_limit: self.gas_limit,
|
||||
gas_used: self.gas_used,
|
||||
timestamp: self.timestamp,
|
||||
extra_data: self.extra_data.clone(),
|
||||
base_fee_per_gas: self.base_fee_per_gas,
|
||||
// TODO: verify if this is correct
|
||||
excess_blobs: 0,
|
||||
block_hash: self.block_hash,
|
||||
transactions_root: self.transactions_root,
|
||||
withdrawals_root: self.withdrawals_root,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: EthSpec> From<ExecutionPayloadMerge<T>> for ExecutionPayloadHeaderMerge<T> {
|
||||
fn from(payload: ExecutionPayloadMerge<T>) -> Self {
|
||||
Self {
|
||||
|
@ -621,17 +621,6 @@ impl<T: EthSpec> ExecPayload<T> for BlindedPayload<T> {
|
||||
// TODO: can this function be optimized?
|
||||
fn is_default(&self) -> bool {
|
||||
match self {
|
||||
/*
|
||||
Self::Merge(payload) => {
|
||||
payload.execution_payload_header == ExecutionPayloadHeaderMerge::default()
|
||||
}
|
||||
Self::Capella(payload) => {
|
||||
payload.execution_payload_header == ExecutionPayloadHeaderCapella::default()
|
||||
}
|
||||
Self::Eip4844(payload) => {
|
||||
payload.execution_payload_header == ExecutionPayloadHeaderEip4844::default()
|
||||
}
|
||||
*/
|
||||
Self::Merge(payload) => payload.is_default(),
|
||||
Self::Capella(payload) => payload.is_default(),
|
||||
Self::Eip4844(payload) => payload.is_default(),
|
||||
|
Loading…
Reference in New Issue
Block a user