Added Capella Data Structures to consensus/types (#3637)

* Ran Cargo fmt

* Added Capella Data Structures to consensus/types
This commit is contained in:
ethDreamer 2022-10-13 09:37:20 -05:00 committed by GitHub
parent 1430b561c3
commit 255fdf0724
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 1602 additions and 180 deletions

20
Cargo.lock generated
View File

@ -428,7 +428,7 @@ dependencies = [
"state_processing",
"store",
"strum",
"superstruct",
"superstruct 0.5.0",
"task_executor",
"tempfile",
"tokio",
@ -3692,7 +3692,7 @@ dependencies = [
"smallvec",
"snap",
"strum",
"superstruct",
"superstruct 0.5.0",
"task_executor",
"tempfile",
"tiny-keccak",
@ -6395,6 +6395,20 @@ dependencies = [
"syn",
]
[[package]]
name = "superstruct"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75b9e5728aa1a87141cefd4e7509903fc01fa0dcb108022b1e841a67c5159fc5"
dependencies = [
"darling",
"itertools",
"proc-macro2",
"quote",
"smallvec",
"syn",
]
[[package]]
name = "swap_or_not_shuffle"
version = "0.2.0"
@ -7125,7 +7139,7 @@ dependencies = [
"slog",
"smallvec",
"state_processing",
"superstruct",
"superstruct 0.6.0",
"swap_or_not_shuffle",
"tempfile",
"test_random_derive",

View File

@ -25,8 +25,8 @@ use std::sync::Arc;
use tokio::task::JoinHandle;
use tree_hash::TreeHash;
use types::{
BeaconBlockRef, BeaconState, BeaconStateError, Blob, EthSpec, ExecPayload,
ExecutionBlockHash, Hash256, KzgCommitment, SignedBeaconBlock, Slot,
BeaconBlockRef, BeaconState, BeaconStateError, Blob, EthSpec, ExecPayload, ExecutionBlockHash,
Hash256, KzgCommitment, SignedBeaconBlock, Slot,
};
pub type PreparePayloadResult<Payload, E> =

View File

@ -3,12 +3,10 @@ use beacon_chain::validator_monitor::{get_slot_delay_ms, timestamp_now};
use beacon_chain::{BeaconChain, BeaconChainTypes};
use lighthouse_network::PubsubMessage;
use network::NetworkMessage;
use slog::{Logger};
use slog::Logger;
use std::sync::Arc;
use tokio::sync::mpsc::UnboundedSender;
use types::{
SignedBlobsSidecar,
};
use types::SignedBlobsSidecar;
use warp::Rejection;
/// Handles a request from the HTTP API for full blocks.

View File

@ -2257,7 +2257,10 @@ impl<T: BeaconChainTypes> Worker<T> {
BlobError::ProposalSignatureInvalid => {
self.propagate_validation_result(message_id, peer_id, MessageAcceptance::Reject);
}
BlobError::RepeatSidecar { proposer: _, slot: _ } => {
BlobError::RepeatSidecar {
proposer: _,
slot: _,
} => {
self.propagate_validation_result(message_id, peer_id, MessageAcceptance::Ignore);
}
BlobError::UnknownHeadBlock { beacon_block_root } => {

View File

@ -44,7 +44,7 @@ regex = "1.5.5"
lazy_static = "1.4.0"
parking_lot = "0.12.0"
itertools = "0.10.0"
superstruct = "0.5.0"
superstruct = "0.6.0"
serde_json = "1.0.74"
smallvec = "1.8.0"
serde_with = "1.13.0"

View File

@ -17,7 +17,7 @@ use tree_hash_derive::TreeHash;
/// A block of the `BeaconChain`.
#[superstruct(
variants(Base, Altair, Merge, Eip4844),
variants(Base, Altair, Merge, Capella, Eip4844),
variant_attributes(
derive(
Debug,
@ -48,7 +48,7 @@ use tree_hash_derive::TreeHash;
#[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))]
#[tree_hash(enum_behaviour = "transparent")]
#[ssz(enum_behaviour = "transparent")]
pub struct BeaconBlock<T: EthSpec, Payload: ExecPayload<T> = FullPayload<T>> {
pub struct BeaconBlock<T: EthSpec, Payload: AbstractExecPayload<T> = FullPayload<T>> {
#[superstruct(getter(copy))]
pub slot: Slot,
#[superstruct(getter(copy))]
@ -64,16 +64,22 @@ pub struct BeaconBlock<T: EthSpec, Payload: ExecPayload<T> = FullPayload<T>> {
pub body: BeaconBlockBodyAltair<T, Payload>,
#[superstruct(only(Merge), partial_getter(rename = "body_merge"))]
pub body: BeaconBlockBodyMerge<T, Payload>,
#[superstruct(only(Capella), partial_getter(rename = "body_capella"))]
pub body: BeaconBlockBodyCapella<T, Payload>,
#[superstruct(only(Eip4844), partial_getter(rename = "body_eip4844"))]
pub body: BeaconBlockBodyEip4844<T, Payload>,
}
pub type BlindedBeaconBlock<E> = BeaconBlock<E, BlindedPayload<E>>;
impl<T: EthSpec, Payload: ExecPayload<T>> SignedRoot for BeaconBlock<T, Payload> {}
impl<'a, T: EthSpec, Payload: ExecPayload<T>> SignedRoot for BeaconBlockRef<'a, T, Payload> {}
impl<T: EthSpec, Payload: AbstractExecPayload<T>> SignedRoot for BeaconBlock<T, Payload> {}
impl<'a, T: EthSpec, Payload: AbstractExecPayload<T>> SignedRoot
for BeaconBlockRef<'a, T, Payload>
{
}
impl<T: EthSpec, Payload: ExecPayload<T>> BeaconBlock<T, Payload> {
impl<T: EthSpec, Payload: AbstractExecPayload<T>> BeaconBlock<T, Payload> {
// FIXME: deal with capella / eip4844 forks here as well
/// Returns an empty block to be used during genesis.
pub fn empty(spec: &ChainSpec) -> Self {
if spec.bellatrix_fork_epoch == Some(T::genesis_epoch()) {
@ -180,7 +186,7 @@ impl<T: EthSpec, Payload: ExecPayload<T>> BeaconBlock<T, Payload> {
}
}
impl<'a, T: EthSpec, Payload: ExecPayload<T>> BeaconBlockRef<'a, T, Payload> {
impl<'a, T: EthSpec, Payload: AbstractExecPayload<T>> BeaconBlockRef<'a, T, Payload> {
/// Returns the name of the fork pertaining to `self`.
///
/// Will return an `Err` if `self` has been instantiated to a variant conflicting with the fork
@ -191,6 +197,7 @@ impl<'a, T: EthSpec, Payload: ExecPayload<T>> BeaconBlockRef<'a, T, Payload> {
BeaconBlockRef::Base { .. } => ForkName::Base,
BeaconBlockRef::Altair { .. } => ForkName::Altair,
BeaconBlockRef::Merge { .. } => ForkName::Merge,
BeaconBlockRef::Capella { .. } => ForkName::Capella,
BeaconBlockRef::Eip4844 { .. } => ForkName::Eip4844,
};
@ -245,12 +252,12 @@ impl<'a, T: EthSpec, Payload: ExecPayload<T>> BeaconBlockRef<'a, T, Payload> {
/// Extracts a reference to an execution payload from a block, returning an error if the block
/// is pre-merge.
pub fn execution_payload(&self) -> Result<&Payload, Error> {
pub fn execution_payload(&self) -> Result<Payload::Ref<'a>, Error> {
self.body().execution_payload()
}
}
impl<'a, T: EthSpec, Payload: ExecPayload<T>> BeaconBlockRefMut<'a, T, Payload> {
impl<'a, T: EthSpec, Payload: AbstractExecPayload<T>> BeaconBlockRefMut<'a, T, Payload> {
/// Convert a mutable reference to a beacon block to a mutable ref to its body.
pub fn body_mut(self) -> BeaconBlockBodyRefMut<'a, T, Payload> {
map_beacon_block_ref_mut_into_beacon_block_body_ref_mut!(&'a _, self, |block, cons| cons(
@ -259,7 +266,7 @@ impl<'a, T: EthSpec, Payload: ExecPayload<T>> BeaconBlockRefMut<'a, T, Payload>
}
}
impl<T: EthSpec, Payload: ExecPayload<T>> BeaconBlockBase<T, Payload> {
impl<T: EthSpec, Payload: AbstractExecPayload<T>> BeaconBlockBase<T, Payload> {
/// Returns an empty block to be used during genesis.
pub fn empty(spec: &ChainSpec) -> Self {
BeaconBlockBase {
@ -380,7 +387,7 @@ impl<T: EthSpec, Payload: ExecPayload<T>> BeaconBlockBase<T, Payload> {
}
}
impl<T: EthSpec, Payload: ExecPayload<T>> BeaconBlockAltair<T, Payload> {
impl<T: EthSpec, Payload: AbstractExecPayload<T>> BeaconBlockAltair<T, Payload> {
/// Returns an empty Altair block to be used during genesis.
pub fn empty(spec: &ChainSpec) -> Self {
BeaconBlockAltair {
@ -439,7 +446,7 @@ impl<T: EthSpec, Payload: ExecPayload<T>> BeaconBlockAltair<T, Payload> {
}
}
impl<T: EthSpec, Payload: ExecPayload<T>> BeaconBlockMerge<T, Payload> {
impl<T: EthSpec, Payload: AbstractExecPayload<T>> BeaconBlockMerge<T, Payload> {
/// Returns an empty Merge block to be used during genesis.
pub fn empty(spec: &ChainSpec) -> Self {
BeaconBlockMerge {
@ -461,7 +468,7 @@ impl<T: EthSpec, Payload: ExecPayload<T>> BeaconBlockMerge<T, Payload> {
deposits: VariableList::empty(),
voluntary_exits: VariableList::empty(),
sync_aggregate: SyncAggregate::empty(),
execution_payload: Payload::default(),
execution_payload: Payload::Merge::default(),
},
}
}
@ -536,7 +543,7 @@ macro_rules! impl_from {
parent_root,
state_root,
body,
}, payload)
}, payload.map(Into::into))
}
}
}
@ -545,6 +552,7 @@ macro_rules! impl_from {
impl_from!(BeaconBlockBase, <E, FullPayload<E>>, <E, BlindedPayload<E>>, |body: BeaconBlockBodyBase<_, _>| body.into());
impl_from!(BeaconBlockAltair, <E, FullPayload<E>>, <E, BlindedPayload<E>>, |body: BeaconBlockBodyAltair<_, _>| body.into());
impl_from!(BeaconBlockMerge, <E, FullPayload<E>>, <E, BlindedPayload<E>>, |body: BeaconBlockBodyMerge<_, _>| body.into());
impl_from!(BeaconBlockCapella, <E, FullPayload<E>>, <E, BlindedPayload<E>>, |body: BeaconBlockBodyCapella<_, _>| body.into());
impl_from!(BeaconBlockEip4844, <E, FullPayload<E>>, <E, BlindedPayload<E>>, |body: BeaconBlockBodyEip4844<_, _>| body.into());
// We can clone blocks with payloads to blocks without payloads, without cloning the payload.
@ -576,6 +584,7 @@ macro_rules! impl_clone_as_blinded {
impl_clone_as_blinded!(BeaconBlockBase, <E, FullPayload<E>>, <E, BlindedPayload<E>>);
impl_clone_as_blinded!(BeaconBlockAltair, <E, FullPayload<E>>, <E, BlindedPayload<E>>);
impl_clone_as_blinded!(BeaconBlockMerge, <E, FullPayload<E>>, <E, BlindedPayload<E>>);
impl_clone_as_blinded!(BeaconBlockCapella, <E, FullPayload<E>>, <E, BlindedPayload<E>>);
impl_clone_as_blinded!(BeaconBlockEip4844, <E, FullPayload<E>>, <E, BlindedPayload<E>>);
// A reference to a full beacon block can be cloned into a blinded beacon block, without cloning the

View File

@ -14,7 +14,7 @@ use tree_hash_derive::TreeHash;
///
/// This *superstruct* abstracts over the hard-fork.
#[superstruct(
variants(Base, Altair, Merge, Eip4844),
variants(Base, Altair, Merge, Capella, Eip4844),
variant_attributes(
derive(
Debug,
@ -39,7 +39,7 @@ use tree_hash_derive::TreeHash;
#[serde(untagged)]
#[serde(bound = "T: EthSpec, Payload: ExecPayload<T>")]
#[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))]
pub struct BeaconBlockBody<T: EthSpec, Payload: ExecPayload<T> = FullPayload<T>> {
pub struct BeaconBlockBody<T: EthSpec, Payload: AbstractExecPayload<T> = FullPayload<T>> {
pub randao_reveal: Signature,
pub eth1_data: Eth1Data,
pub graffiti: Graffiti,
@ -48,14 +48,20 @@ pub struct BeaconBlockBody<T: EthSpec, Payload: ExecPayload<T> = FullPayload<T>>
pub attestations: VariableList<Attestation<T>, T::MaxAttestations>,
pub deposits: VariableList<Deposit, T::MaxDeposits>,
pub voluntary_exits: VariableList<SignedVoluntaryExit, T::MaxVoluntaryExits>,
#[superstruct(only(Altair, Merge, Eip4844))]
#[superstruct(only(Altair, Merge, Capella, Eip4844))]
pub sync_aggregate: SyncAggregate<T>,
// We flatten the execution payload so that serde can use the name of the inner type,
// either `execution_payload` for full payloads, or `execution_payload_header` for blinded
// payloads.
#[superstruct(only(Merge, Eip4844))]
#[superstruct(only(Merge), partial_getter(rename = "execution_payload_merge"))]
#[serde(flatten)]
pub execution_payload: Payload,
pub execution_payload: Payload::Merge,
#[superstruct(only(Capella), partial_getter(rename = "execution_payload_capella"))]
#[serde(flatten)]
pub execution_payload: Payload::Capella,
#[superstruct(only(Eip4844), partial_getter(rename = "execution_payload_eip4844"))]
#[serde(flatten)]
pub execution_payload: Payload::Eip4844,
#[superstruct(only(Eip4844))]
pub blob_kzg_commitments: VariableList<KzgCommitment, T::MaxBlobsPerBlock>,
#[superstruct(only(Base, Altair))]
@ -65,6 +71,23 @@ pub struct BeaconBlockBody<T: EthSpec, Payload: ExecPayload<T> = FullPayload<T>>
pub _phantom: PhantomData<Payload>,
}
impl<T: EthSpec, Payload: AbstractExecPayload<T>> BeaconBlockBody<T, Payload> {
pub fn execution_payload<'a>(&'a self) -> Result<Payload::Ref<'a>, Error> {
self.to_ref().execution_payload()
}
}
impl<'a, T: EthSpec, Payload: AbstractExecPayload<T>> BeaconBlockBodyRef<'a, T, Payload> {
pub fn execution_payload(&self) -> Result<Payload::Ref<'a>, Error> {
match self {
Self::Base(_) | Self::Altair(_) => Err(Error::IncorrectStateVariant),
Self::Merge(body) => Ok(Payload::Ref::from(&body.execution_payload)),
Self::Capella(body) => Ok(Payload::Ref::from(&body.execution_payload)),
Self::Eip4844(body) => Ok(Payload::Ref::from(&body.execution_payload)),
}
}
}
impl<'a, T: EthSpec> BeaconBlockBodyRef<'a, T> {
/// Get the fork_name of this object
pub fn fork_name(self) -> ForkName {
@ -72,6 +95,7 @@ impl<'a, T: EthSpec> BeaconBlockBodyRef<'a, T> {
BeaconBlockBodyRef::Base { .. } => ForkName::Base,
BeaconBlockBodyRef::Altair { .. } => ForkName::Altair,
BeaconBlockBodyRef::Merge { .. } => ForkName::Merge,
BeaconBlockBodyRef::Capella { .. } => ForkName::Capella,
BeaconBlockBodyRef::Eip4844 { .. } => ForkName::Eip4844,
}
}
@ -218,7 +242,7 @@ impl<E: EthSpec> From<BeaconBlockBodyAltair<E, FullPayload<E>>>
impl<E: EthSpec> From<BeaconBlockBodyMerge<E, FullPayload<E>>>
for (
BeaconBlockBodyMerge<E, BlindedPayload<E>>,
Option<ExecutionPayload<E>>,
Option<ExecutionPayloadMerge<E>>,
)
{
fn from(body: BeaconBlockBodyMerge<E, FullPayload<E>>) -> Self {
@ -232,7 +256,7 @@ impl<E: EthSpec> From<BeaconBlockBodyMerge<E, FullPayload<E>>>
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: FullPayload { execution_payload },
execution_payload: FullPayloadMerge { execution_payload },
} = body;
(
@ -246,8 +270,48 @@ impl<E: EthSpec> From<BeaconBlockBodyMerge<E, FullPayload<E>>>
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: BlindedPayload {
execution_payload_header: From::from(&execution_payload),
execution_payload: BlindedPayloadMerge {
execution_payload_header: From::from(execution_payload.clone()),
},
},
Some(execution_payload),
)
}
}
impl<E: EthSpec> From<BeaconBlockBodyCapella<E, FullPayload<E>>>
for (
BeaconBlockBodyCapella<E, BlindedPayload<E>>,
Option<ExecutionPayloadCapella<E>>,
)
{
fn from(body: BeaconBlockBodyCapella<E, FullPayload<E>>) -> Self {
let BeaconBlockBodyCapella {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: FullPayloadCapella { execution_payload },
} = body;
(
BeaconBlockBodyCapella {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: BlindedPayloadCapella {
execution_payload_header: From::from(execution_payload.clone()),
},
},
Some(execution_payload),
@ -258,7 +322,7 @@ impl<E: EthSpec> From<BeaconBlockBodyMerge<E, FullPayload<E>>>
impl<E: EthSpec> From<BeaconBlockBodyEip4844<E, FullPayload<E>>>
for (
BeaconBlockBodyEip4844<E, BlindedPayload<E>>,
Option<ExecutionPayload<E>>,
Option<ExecutionPayloadEip4844<E>>,
)
{
fn from(body: BeaconBlockBodyEip4844<E, FullPayload<E>>) -> Self {
@ -272,7 +336,7 @@ impl<E: EthSpec> From<BeaconBlockBodyEip4844<E, FullPayload<E>>>
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: FullPayload { execution_payload },
execution_payload: FullPayloadEip4844 { execution_payload },
blob_kzg_commitments,
} = body;
@ -287,12 +351,12 @@ impl<E: EthSpec> From<BeaconBlockBodyEip4844<E, FullPayload<E>>>
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: BlindedPayload {
execution_payload_header: From::from(&execution_payload),
execution_payload: BlindedPayloadEip4844 {
execution_payload_header: From::from(execution_payload.clone()),
},
blob_kzg_commitments,
},
None,
Some(execution_payload),
)
}
}
@ -324,7 +388,7 @@ impl<E: EthSpec> BeaconBlockBodyMerge<E, FullPayload<E>> {
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: FullPayload { execution_payload },
execution_payload: FullPayloadMerge { execution_payload },
} = self;
BeaconBlockBodyMerge {
@ -337,8 +401,40 @@ impl<E: EthSpec> BeaconBlockBodyMerge<E, FullPayload<E>> {
deposits: deposits.clone(),
voluntary_exits: voluntary_exits.clone(),
sync_aggregate: sync_aggregate.clone(),
execution_payload: BlindedPayload {
execution_payload_header: From::from(execution_payload),
execution_payload: BlindedPayloadMerge {
execution_payload_header: From::from(execution_payload.clone()),
},
}
}
}
impl<E: EthSpec> BeaconBlockBodyCapella<E, FullPayload<E>> {
pub fn clone_as_blinded(&self) -> BeaconBlockBodyCapella<E, BlindedPayload<E>> {
let BeaconBlockBodyCapella {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: FullPayloadCapella { execution_payload },
} = self;
BeaconBlockBodyCapella {
randao_reveal: randao_reveal.clone(),
eth1_data: eth1_data.clone(),
graffiti: *graffiti,
proposer_slashings: proposer_slashings.clone(),
attester_slashings: attester_slashings.clone(),
attestations: attestations.clone(),
deposits: deposits.clone(),
voluntary_exits: voluntary_exits.clone(),
sync_aggregate: sync_aggregate.clone(),
execution_payload: BlindedPayloadCapella {
execution_payload_header: From::from(execution_payload.clone()),
},
}
}
@ -356,7 +452,7 @@ impl<E: EthSpec> BeaconBlockBodyEip4844<E, FullPayload<E>> {
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: FullPayload { execution_payload },
execution_payload: FullPayloadEip4844 { execution_payload },
blob_kzg_commitments,
} = self;
@ -370,8 +466,8 @@ impl<E: EthSpec> BeaconBlockBodyEip4844<E, FullPayload<E>> {
deposits: deposits.clone(),
voluntary_exits: voluntary_exits.clone(),
sync_aggregate: sync_aggregate.clone(),
execution_payload: BlindedPayload {
execution_payload_header: From::from(execution_payload),
execution_payload: BlindedPayloadEip4844 {
execution_payload_header: From::from(execution_payload.clone()),
},
blob_kzg_commitments: blob_kzg_commitments.clone(),
}
@ -387,7 +483,7 @@ impl<E: EthSpec> From<BeaconBlockBody<E, FullPayload<E>>>
fn from(body: BeaconBlockBody<E, FullPayload<E>>) -> Self {
map_beacon_block_body!(body, |inner, cons| {
let (block, payload) = inner.into();
(cons(block), payload)
(cons(block), payload.map(Into::into))
})
}
}

View File

@ -172,7 +172,7 @@ impl From<BeaconStateHash> for Hash256 {
/// The state of the `BeaconChain` at some slot.
#[superstruct(
variants(Base, Altair, Merge, Eip4844),
variants(Base, Altair, Merge, Capella, Eip4844),
variant_attributes(
derive(
Derivative,
@ -250,9 +250,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
@ -267,18 +267,39 @@ where
// Inactivity
#[serde(with = "ssz_types::serde_utils::quoted_u64_var_list")]
#[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,
// Caching (not in the spec)
#[serde(skip_serializing, skip_deserializing)]
@ -389,6 +410,7 @@ impl<T: EthSpec> BeaconState<T> {
BeaconState::Base { .. } => ForkName::Base,
BeaconState::Altair { .. } => ForkName::Altair,
BeaconState::Merge { .. } => ForkName::Merge,
BeaconState::Capella { .. } => ForkName::Capella,
BeaconState::Eip4844 { .. } => ForkName::Eip4844,
};
@ -679,6 +701,23 @@ impl<T: EthSpec> BeaconState<T> {
.ok_or(Error::ShuffleIndexOutOfBounds(index))
}
// TODO: check this implementation
/// Convenience accessor for the `execution_payload_header` as an `ExecutionPayloadHeaderRef`.
pub fn latest_execution_payload_header(&self) -> Result<ExecutionPayloadHeaderRef<T>, Error> {
match self {
BeaconState::Base(_) | BeaconState::Altair(_) => Err(Error::IncorrectStateVariant),
BeaconState::Merge(state) => Ok(ExecutionPayloadHeaderRef::Merge(
&state.latest_execution_payload_header,
)),
BeaconState::Capella(state) => Ok(ExecutionPayloadHeaderRef::Capella(
&state.latest_execution_payload_header,
)),
BeaconState::Eip4844(state) => Ok(ExecutionPayloadHeaderRef::Eip4844(
&state.latest_execution_payload_header,
)),
}
}
/// Return `true` if the validator who produced `slot_signature` is eligible to aggregate.
///
/// Spec v0.12.1
@ -1103,6 +1142,7 @@ impl<T: EthSpec> BeaconState<T> {
BeaconState::Base(state) => (&mut state.validators, &mut state.balances),
BeaconState::Altair(state) => (&mut state.validators, &mut state.balances),
BeaconState::Merge(state) => (&mut state.validators, &mut state.balances),
BeaconState::Capella(state) => (&mut state.validators, &mut state.balances),
BeaconState::Eip4844(state) => (&mut state.validators, &mut state.balances),
}
}
@ -1300,6 +1340,7 @@ impl<T: EthSpec> BeaconState<T> {
BeaconState::Base(_) => Err(BeaconStateError::IncorrectStateVariant),
BeaconState::Altair(state) => Ok(&mut state.current_epoch_participation),
BeaconState::Merge(state) => Ok(&mut state.current_epoch_participation),
BeaconState::Capella(state) => Ok(&mut state.current_epoch_participation),
BeaconState::Eip4844(state) => Ok(&mut state.current_epoch_participation),
}
} else if epoch == self.previous_epoch() {
@ -1307,6 +1348,7 @@ impl<T: EthSpec> BeaconState<T> {
BeaconState::Base(_) => Err(BeaconStateError::IncorrectStateVariant),
BeaconState::Altair(state) => Ok(&mut state.previous_epoch_participation),
BeaconState::Merge(state) => Ok(&mut state.previous_epoch_participation),
BeaconState::Capella(state) => Ok(&mut state.previous_epoch_participation),
BeaconState::Eip4844(state) => Ok(&mut state.previous_epoch_participation),
}
} else {
@ -1612,6 +1654,7 @@ impl<T: EthSpec> BeaconState<T> {
BeaconState::Base(inner) => BeaconState::Base(inner.clone()),
BeaconState::Altair(inner) => BeaconState::Altair(inner.clone()),
BeaconState::Merge(inner) => BeaconState::Merge(inner.clone()),
BeaconState::Capella(inner) => BeaconState::Capella(inner.clone()),
BeaconState::Eip4844(inner) => BeaconState::Eip4844(inner.clone()),
};
if config.committee_caches {

View File

@ -1,4 +1,7 @@
use crate::{ChainSpec, EthSpec, ExecPayload, ExecutionPayloadHeader, SignedRoot, Uint256};
use crate::{
AbstractExecPayload, ChainSpec, EthSpec, ExecPayload, ExecutionPayloadHeader, SignedRoot,
Uint256,
};
use bls::PublicKeyBytes;
use bls::Signature;
use serde::{Deserialize as De, Deserializer, Serialize as Ser, Serializer};
@ -10,7 +13,7 @@ use tree_hash_derive::TreeHash;
#[serde_as]
#[derive(PartialEq, Debug, Serialize, Deserialize, TreeHash, Clone)]
#[serde(bound = "E: EthSpec, Payload: ExecPayload<E>")]
pub struct BuilderBid<E: EthSpec, Payload: ExecPayload<E>> {
pub struct BuilderBid<E: EthSpec, Payload: AbstractExecPayload<E>> {
#[serde_as(as = "BlindedPayloadAsHeader<E>")]
pub header: Payload,
#[serde(with = "eth2_serde_utils::quoted_u256")]
@ -21,12 +24,12 @@ pub struct BuilderBid<E: EthSpec, Payload: ExecPayload<E>> {
_phantom_data: PhantomData<E>,
}
impl<E: EthSpec, Payload: ExecPayload<E>> SignedRoot for BuilderBid<E, Payload> {}
impl<E: EthSpec, Payload: AbstractExecPayload<E>> SignedRoot for BuilderBid<E, Payload> {}
/// Validator registration, for use in interacting with servers implementing the builder API.
#[derive(PartialEq, Debug, Serialize, Deserialize, Clone)]
#[serde(bound = "E: EthSpec, Payload: ExecPayload<E>")]
pub struct SignedBuilderBid<E: EthSpec, Payload: ExecPayload<E>> {
pub struct SignedBuilderBid<E: EthSpec, Payload: AbstractExecPayload<E>> {
pub message: BuilderBid<E, Payload>,
pub signature: Signature,
}
@ -42,7 +45,7 @@ impl<E: EthSpec, Payload: ExecPayload<E>> SerializeAs<Payload> for BlindedPayloa
}
}
impl<'de, E: EthSpec, Payload: ExecPayload<E>> DeserializeAs<'de, Payload>
impl<'de, E: EthSpec, Payload: AbstractExecPayload<E>> DeserializeAs<'de, Payload>
for BlindedPayloadAsHeader<E>
{
fn deserialize_as<D>(deserializer: D) -> Result<Payload, D::Error>
@ -55,7 +58,7 @@ impl<'de, E: EthSpec, Payload: ExecPayload<E>> DeserializeAs<'de, Payload>
}
}
impl<E: EthSpec, Payload: ExecPayload<E>> SignedBuilderBid<E, Payload> {
impl<E: EthSpec, Payload: AbstractExecPayload<E>> SignedBuilderBid<E, Payload> {
pub fn verify_signature(&self, spec: &ChainSpec) -> bool {
self.message
.pubkey

View File

@ -11,6 +11,7 @@ use tree_hash::TreeHash;
/// Each of the BLS signature domains.
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Domain {
BlsToExecutionChange,
BeaconProposer,
BeaconAttester,
BlobsSideCar,
@ -152,6 +153,13 @@ pub struct ChainSpec {
pub terminal_block_hash_activation_epoch: Epoch,
pub safe_slots_to_import_optimistically: u64,
/*
* Capella hard fork params
*/
pub capella_fork_version: [u8; 4],
/// The Capella fork epoch is optional, with `None` representing "Merge never happens".
pub capella_fork_epoch: Option<Epoch>,
/*
* Eip4844 hard fork params
*/
@ -174,6 +182,11 @@ pub struct ChainSpec {
* Application params
*/
pub(crate) domain_application_mask: u32,
/*
* Capella params
*/
pub(crate) domain_bls_to_execution_change: u32,
}
impl ChainSpec {
@ -256,6 +269,7 @@ impl ChainSpec {
ForkName::Base => self.genesis_fork_version,
ForkName::Altair => self.altair_fork_version,
ForkName::Merge => self.bellatrix_fork_version,
ForkName::Capella => self.capella_fork_version,
ForkName::Eip4844 => self.eip4844_fork_version,
}
}
@ -266,6 +280,7 @@ impl ChainSpec {
ForkName::Base => Some(Epoch::new(0)),
ForkName::Altair => self.altair_fork_epoch,
ForkName::Merge => self.bellatrix_fork_epoch,
ForkName::Capella => self.capella_fork_epoch,
ForkName::Eip4844 => self.eip4844_fork_epoch,
}
}
@ -276,6 +291,7 @@ impl ChainSpec {
BeaconState::Base(_) => self.inactivity_penalty_quotient,
BeaconState::Altair(_) => self.inactivity_penalty_quotient_altair,
BeaconState::Merge(_) => self.inactivity_penalty_quotient_bellatrix,
BeaconState::Capella(_) => self.inactivity_penalty_quotient_bellatrix,
BeaconState::Eip4844(_) => self.inactivity_penalty_quotient_bellatrix,
}
}
@ -289,6 +305,7 @@ impl ChainSpec {
BeaconState::Base(_) => self.proportional_slashing_multiplier,
BeaconState::Altair(_) => self.proportional_slashing_multiplier_altair,
BeaconState::Merge(_) => self.proportional_slashing_multiplier_bellatrix,
BeaconState::Capella(_) => self.proportional_slashing_multiplier_bellatrix,
BeaconState::Eip4844(_) => self.proportional_slashing_multiplier_bellatrix,
}
}
@ -302,6 +319,7 @@ impl ChainSpec {
BeaconState::Base(_) => self.min_slashing_penalty_quotient,
BeaconState::Altair(_) => self.min_slashing_penalty_quotient_altair,
BeaconState::Merge(_) => self.min_slashing_penalty_quotient_bellatrix,
BeaconState::Capella(_) => self.min_slashing_penalty_quotient_bellatrix,
BeaconState::Eip4844(_) => self.min_slashing_penalty_quotient_bellatrix,
}
}
@ -351,6 +369,7 @@ impl ChainSpec {
Domain::ContributionAndProof => self.domain_contribution_and_proof,
Domain::SyncCommitteeSelectionProof => self.domain_sync_committee_selection_proof,
Domain::ApplicationMask(application_domain) => application_domain.get_domain_constant(),
Domain::BlsToExecutionChange => self.domain_bls_to_execution_change,
}
}
@ -586,6 +605,12 @@ impl ChainSpec {
terminal_block_hash_activation_epoch: Epoch::new(u64::MAX),
safe_slots_to_import_optimistically: 128u64,
/*
* Capella hard fork params
*/
capella_fork_version: [0x03, 00, 00, 00],
capella_fork_epoch: Some(Epoch::new(18446744073709551615)),
/*
* Eip4844 hard fork params
*/
@ -608,6 +633,11 @@ impl ChainSpec {
* Application specific
*/
domain_application_mask: APPLICATION_DOMAIN_BUILDER,
/*
* Capella params
*/
domain_bls_to_execution_change: 10,
}
}
@ -647,6 +677,9 @@ impl ChainSpec {
// `Uint256::MAX` which is `2*256- 1`.
.checked_add(Uint256::one())
.expect("addition does not overflow"),
// Capella
capella_fork_version: [0x03, 0x00, 0x00, 0x01],
capella_fork_epoch: None,
// Eip4844
eip4844_fork_version: [0x04, 0x00, 0x00, 0x01],
eip4844_fork_epoch: None,
@ -806,6 +839,15 @@ impl ChainSpec {
terminal_block_hash_activation_epoch: Epoch::new(u64::MAX),
safe_slots_to_import_optimistically: 128u64,
/*
* Capella hard fork params
*/
capella_fork_version: [0x03, 0x00, 0x00, 0x64],
capella_fork_epoch: None,
/*
* Eip4844 hard fork params
*/
eip4844_fork_version: [0x04, 0x00, 0x00, 0x64],
eip4844_fork_epoch: None,
@ -825,6 +867,11 @@ impl ChainSpec {
* Application specific
*/
domain_application_mask: APPLICATION_DOMAIN_BUILDER,
/*
* Capella params
*/
domain_bls_to_execution_change: 10,
}
}
}
@ -884,6 +931,14 @@ pub struct Config {
#[serde(deserialize_with = "deserialize_fork_epoch")]
pub bellatrix_fork_epoch: Option<MaybeQuoted<Epoch>>,
#[serde(default = "default_capella_fork_version")]
#[serde(with = "eth2_serde_utils::bytes_4_hex")]
capella_fork_version: [u8; 4],
#[serde(default)]
#[serde(serialize_with = "serialize_fork_epoch")]
#[serde(deserialize_with = "deserialize_fork_epoch")]
pub capella_fork_epoch: Option<MaybeQuoted<Epoch>>,
#[serde(default = "default_eip4844_fork_version")]
#[serde(with = "eth2_serde_utils::bytes_4_hex")]
eip4844_fork_version: [u8; 4],
@ -928,6 +983,11 @@ fn default_bellatrix_fork_version() -> [u8; 4] {
[0xff, 0xff, 0xff, 0xff]
}
fn default_capella_fork_version() -> [u8; 4] {
// TODO: determine if the bellatrix example should be copied like this
[0xff, 0xff, 0xff, 0xff]
}
fn default_eip4844_fork_version() -> [u8; 4] {
// This value shouldn't be used.
[0xff, 0xff, 0xff, 0xff]
@ -1029,6 +1089,10 @@ impl Config {
bellatrix_fork_epoch: spec
.bellatrix_fork_epoch
.map(|epoch| MaybeQuoted { value: epoch }),
capella_fork_version: spec.capella_fork_version,
capella_fork_epoch: spec
.capella_fork_epoch
.map(|epoch| MaybeQuoted { value: epoch }),
eip4844_fork_version: spec.eip4844_fork_version,
eip4844_fork_epoch: spec
.eip4844_fork_epoch
@ -1078,6 +1142,8 @@ impl Config {
altair_fork_epoch,
bellatrix_fork_epoch,
bellatrix_fork_version,
capella_fork_epoch,
capella_fork_version,
eip4844_fork_epoch,
eip4844_fork_version,
seconds_per_slot,
@ -1110,6 +1176,8 @@ impl Config {
altair_fork_epoch: altair_fork_epoch.map(|q| q.value),
bellatrix_fork_epoch: bellatrix_fork_epoch.map(|q| q.value),
bellatrix_fork_version,
capella_fork_epoch: capella_fork_epoch.map(|q| q.value),
capella_fork_version,
eip4844_fork_epoch: eip4844_fork_epoch.map(|q| q.value),
eip4844_fork_version,
seconds_per_slot,
@ -1204,6 +1272,14 @@ mod tests {
apply_bit_mask(builder_domain_pre_mask, &spec),
&spec,
);
test_domain(
Domain::BlsToExecutionChange,
spec.domain_bls_to_execution_change,
&spec,
);
test_domain(Domain::BlobsSideCar, spec.domain_blobs_sidecar, &spec);
}
fn apply_bit_mask(domain_bytes: [u8; 4], spec: &ChainSpec) -> u32 {

View File

@ -95,6 +95,13 @@ pub trait EthSpec: 'static + Default + Sync + Send + Clone + Debug + PartialEq +
type GasLimitDenominator: Unsigned + Clone + Sync + Send + Debug + PartialEq;
type MinGasLimit: Unsigned + Clone + Sync + Send + Debug + PartialEq;
type MaxExtraDataBytes: Unsigned + Clone + Sync + Send + Debug + PartialEq;
/*
* New in Capella
*/
type MaxPartialWithdrawalsPerEpoch: Unsigned + Clone + Sync + Send + Debug + PartialEq;
type WithdrawalQueueLimit: Unsigned + Clone + Sync + Send + Debug + PartialEq;
type MaxBlsToExecutionChanges: Unsigned + Clone + Sync + Send + Debug + PartialEq;
type MaxWithdrawalsPerPayload: Unsigned + Clone + Sync + Send + Debug + PartialEq;
/*
* New in Eip4844
*/
@ -228,10 +235,32 @@ pub trait EthSpec: 'static + Default + Sync + Send + Clone + Debug + PartialEq +
Self::BytesPerLogsBloom::to_usize()
}
/// Returns the `MAX_PARTIAL_WITHDRAWALS_PER_EPOCH` constant for this specification.
fn max_partial_withdrawals_per_epoch() -> usize {
Self::MaxPartialWithdrawalsPerEpoch::to_usize()
}
/// Returns the `WITHDRAWAL_QUEUE_LIMIT` constant for this specification.
fn withdrawal_queue_limit() -> usize {
Self::WithdrawalQueueLimit::to_usize()
}
/// Returns the `MAX_BLS_TO_EXECUTION_CHANGES` constant for this specification.
fn max_bls_to_execution_changes() -> usize {
Self::MaxBlsToExecutionChanges::to_usize()
}
/// Returns the `MAX_WITHDRAWALS_PER_PAYLOAD` constant for this specification.
fn max_withdrawals_per_payload() -> usize {
Self::MaxWithdrawalsPerPayload::to_usize()
}
/// Returns the `MAX_BLOBS_PER_BLOCK` constant for this specification.
fn max_blobs_per_block() -> usize {
Self::MaxBlobsPerBlock::to_usize()
}
/// FIXME: why is this called chunks_per_blob??
fn chunks_per_blob() -> usize {
Self::FieldElementsPerBlob::to_usize()
}
@ -280,6 +309,10 @@ impl EthSpec for MainnetEthSpec {
type SyncSubcommitteeSize = U128; // 512 committee size / 4 sync committee subnet count
type MaxPendingAttestations = U4096; // 128 max attestations * 32 slots per epoch
type SlotsPerEth1VotingPeriod = U2048; // 64 epochs * 32 slots per epoch
type MaxPartialWithdrawalsPerEpoch = U256;
type WithdrawalQueueLimit = U1099511627776;
type MaxBlsToExecutionChanges = U16;
type MaxWithdrawalsPerPayload = U16;
fn default_spec() -> ChainSpec {
ChainSpec::mainnet()
@ -325,6 +358,10 @@ impl EthSpec for MinimalEthSpec {
GasLimitDenominator,
MinGasLimit,
MaxExtraDataBytes,
MaxPartialWithdrawalsPerEpoch,
WithdrawalQueueLimit,
MaxBlsToExecutionChanges,
MaxWithdrawalsPerPayload,
MaxBlobsPerBlock,
FieldElementsPerBlob
});
@ -371,6 +408,10 @@ impl EthSpec for GnosisEthSpec {
type SyncSubcommitteeSize = U128; // 512 committee size / 4 sync committee subnet count
type MaxPendingAttestations = U2048; // 128 max attestations * 16 slots per epoch
type SlotsPerEth1VotingPeriod = U1024; // 64 epochs * 16 slots per epoch
type MaxPartialWithdrawalsPerEpoch = U256;
type WithdrawalQueueLimit = U1099511627776;
type MaxBlsToExecutionChanges = U16;
type MaxWithdrawalsPerPayload = U16;
type MaxBlobsPerBlock = U16; // 2**4 = 16
type FieldElementsPerBlob = U4096;

View File

@ -13,12 +13,35 @@ pub type Transactions<T> = VariableList<
<T as EthSpec>::MaxTransactionsPerPayload,
>;
#[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))]
#[derive(
Default, Debug, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom, Derivative,
#[superstruct(
variants(Merge, Capella, Eip4844),
variant_attributes(
derive(
Default,
Debug,
Clone,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
TestRandom,
Derivative,
),
derivative(PartialEq, Hash(bound = "T: EthSpec")),
serde(bound = "T: EthSpec", deny_unknown_fields),
cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))
),
cast_error(ty = "Error", expr = "BeaconStateError::IncorrectStateVariant"),
partial_getter_error(ty = "Error", expr = "BeaconStateError::IncorrectStateVariant")
)]
#[derive(Debug, Clone, Serialize, Encode, Deserialize, TreeHash, Derivative)]
#[derivative(PartialEq, Hash(bound = "T: EthSpec"))]
#[serde(untagged)]
#[serde(bound = "T: EthSpec")]
#[ssz(enum_behaviour = "transparent")]
#[tree_hash(enum_behaviour = "transparent")]
#[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))]
pub struct ExecutionPayload<T: EthSpec> {
pub parent_hash: ExecutionBlockHash,
pub fee_recipient: Address,
@ -39,28 +62,57 @@ pub struct ExecutionPayload<T: EthSpec> {
pub extra_data: VariableList<u8, T::MaxExtraDataBytes>,
#[serde(with = "eth2_serde_utils::quoted_u256")]
pub base_fee_per_gas: Uint256,
#[superstruct(only(Eip4844))]
#[serde(with = "eth2_serde_utils::quoted_u64")]
pub excess_blobs: u64,
pub block_hash: ExecutionBlockHash,
#[serde(with = "ssz_types::serde_utils::list_of_hex_var_list")]
pub transactions: Transactions<T>,
#[superstruct(only(Capella, Eip4844))]
pub withdrawals: VariableList<Withdrawal, T::MaxWithdrawalsPerPayload>,
}
impl<T: EthSpec> ExecutionPayload<T> {
pub fn empty() -> Self {
Self::default()
}
#[allow(clippy::integer_arithmetic)]
/// Returns the maximum size of an execution payload.
pub fn max_execution_payload_size() -> usize {
pub fn max_execution_payload_merge_size() -> usize {
// Fixed part
Self::empty().as_ssz_bytes().len()
ExecutionPayloadMerge::<T>::default().as_ssz_bytes().len()
// Max size of variable length `extra_data` field
+ (T::max_extra_data_bytes() * <u8 as Encode>::ssz_fixed_len())
// Max size of variable length `transactions` field
+ (T::max_transactions_per_payload() * (ssz::BYTES_PER_LENGTH_OFFSET + T::max_bytes_per_transaction()))
}
#[allow(clippy::integer_arithmetic)]
/// Returns the maximum size of an execution payload.
pub fn max_execution_payload_capella_size() -> usize {
// Fixed part
ExecutionPayloadCapella::<T>::default().as_ssz_bytes().len()
// Max size of variable length `extra_data` field
+ (T::max_extra_data_bytes() * <u8 as Encode>::ssz_fixed_len())
// Max size of variable length `transactions` field
+ (T::max_transactions_per_payload() * (ssz::BYTES_PER_LENGTH_OFFSET + T::max_bytes_per_transaction()))
// Max size of variable length `withdrawals` field
// TODO: check this
+ (T::max_withdrawals_per_payload() * (ssz::BYTES_PER_LENGTH_OFFSET + <Withdrawal as Encode>::ssz_fixed_len()))
}
#[allow(clippy::integer_arithmetic)]
/// Returns the maximum size of an execution payload.
pub fn max_execution_payload_eip4844_size() -> usize {
// Fixed part
ExecutionPayloadEip4844::<T>::default().as_ssz_bytes().len()
// Max size of variable length `extra_data` field
+ (T::max_extra_data_bytes() * <u8 as Encode>::ssz_fixed_len())
// Max size of variable length `transactions` field
+ (T::max_transactions_per_payload() * (ssz::BYTES_PER_LENGTH_OFFSET + T::max_bytes_per_transaction()))
// Max size of variable length `withdrawals` field
// TODO: check this
+ (T::max_withdrawals_per_payload() * (ssz::BYTES_PER_LENGTH_OFFSET + <Withdrawal as Encode>::ssz_fixed_len()))
}
pub fn blob_txns_iter(&self) -> Iter<'_, Transaction<T::MaxBytesPerTransaction>> {
self.transactions.iter()
self.transactions().iter()
}
}

View File

@ -5,12 +5,37 @@ use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash::TreeHash;
use tree_hash_derive::TreeHash;
use BeaconStateError;
#[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))]
#[derive(
Default, Debug, Clone, Serialize, Deserialize, Derivative, Encode, Decode, TreeHash, TestRandom,
#[superstruct(
variants(Merge, Capella, Eip4844),
variant_attributes(
derive(
Default,
Debug,
Clone,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
TestRandom,
Derivative,
),
derivative(PartialEq, Hash(bound = "T: EthSpec")),
serde(bound = "T: EthSpec", deny_unknown_fields),
cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))
),
ref_attributes(derive(PartialEq, TreeHash), tree_hash(enum_behaviour = "transparent")),
cast_error(ty = "Error", expr = "BeaconStateError::IncorrectStateVariant"),
partial_getter_error(ty = "Error", expr = "BeaconStateError::IncorrectStateVariant")
)]
#[derive(Debug, Clone, Serialize, Deserialize, Encode, TreeHash, Derivative)]
#[derivative(PartialEq, Hash(bound = "T: EthSpec"))]
#[serde(bound = "T: EthSpec")]
#[tree_hash(enum_behaviour = "transparent")]
#[ssz(enum_behaviour = "transparent")]
#[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))]
pub struct ExecutionPayloadHeader<T: EthSpec> {
pub parent_hash: ExecutionBlockHash,
pub fee_recipient: Address,
@ -31,33 +56,107 @@ pub struct ExecutionPayloadHeader<T: EthSpec> {
pub extra_data: VariableList<u8, T::MaxExtraDataBytes>,
#[serde(with = "eth2_serde_utils::quoted_u256")]
pub base_fee_per_gas: Uint256,
#[superstruct(only(Eip4844))]
#[serde(with = "eth2_serde_utils::quoted_u64")]
pub excess_blobs: u64,
pub block_hash: ExecutionBlockHash,
pub transactions_root: Hash256,
#[superstruct(only(Capella, Eip4844))]
pub withdrawals_root: Hash256,
}
impl<T: EthSpec> ExecutionPayloadHeader<T> {
pub fn empty() -> Self {
Self::default()
}
}
impl<'a, T: EthSpec> From<&'a ExecutionPayload<T>> for ExecutionPayloadHeader<T> {
fn from(payload: &'a ExecutionPayload<T>) -> Self {
ExecutionPayloadHeader {
impl<T: EthSpec> From<ExecutionPayloadMerge<T>> for ExecutionPayloadHeaderMerge<T> {
fn from(payload: ExecutionPayloadMerge<T>) -> Self {
Self {
parent_hash: payload.parent_hash,
fee_recipient: payload.fee_recipient,
state_root: payload.state_root,
receipts_root: payload.receipts_root,
logs_bloom: payload.logs_bloom.clone(),
logs_bloom: payload.logs_bloom,
prev_randao: payload.prev_randao,
block_number: payload.block_number,
gas_limit: payload.gas_limit,
gas_used: payload.gas_used,
timestamp: payload.timestamp,
extra_data: payload.extra_data.clone(),
extra_data: payload.extra_data,
base_fee_per_gas: payload.base_fee_per_gas,
block_hash: payload.block_hash,
transactions_root: payload.transactions.tree_hash_root(),
}
}
}
impl<T: EthSpec> From<ExecutionPayloadCapella<T>> for ExecutionPayloadHeaderCapella<T> {
fn from(payload: ExecutionPayloadCapella<T>) -> Self {
Self {
parent_hash: payload.parent_hash,
fee_recipient: payload.fee_recipient,
state_root: payload.state_root,
receipts_root: payload.receipts_root,
logs_bloom: payload.logs_bloom,
prev_randao: payload.prev_randao,
block_number: payload.block_number,
gas_limit: payload.gas_limit,
gas_used: payload.gas_used,
timestamp: payload.timestamp,
extra_data: payload.extra_data,
base_fee_per_gas: payload.base_fee_per_gas,
block_hash: payload.block_hash,
transactions_root: payload.transactions.tree_hash_root(),
withdrawals_root: payload.withdrawals.tree_hash_root(),
}
}
}
impl<T: EthSpec> From<ExecutionPayloadEip4844<T>> for ExecutionPayloadHeaderEip4844<T> {
fn from(payload: ExecutionPayloadEip4844<T>) -> Self {
Self {
parent_hash: payload.parent_hash,
fee_recipient: payload.fee_recipient,
state_root: payload.state_root,
receipts_root: payload.receipts_root,
logs_bloom: payload.logs_bloom,
prev_randao: payload.prev_randao,
block_number: payload.block_number,
gas_limit: payload.gas_limit,
gas_used: payload.gas_used,
timestamp: payload.timestamp,
extra_data: payload.extra_data,
base_fee_per_gas: payload.base_fee_per_gas,
excess_blobs: payload.excess_blobs,
block_hash: payload.block_hash,
transactions_root: payload.transactions.tree_hash_root(),
withdrawals_root: payload.withdrawals.tree_hash_root(),
}
}
}
impl<T: EthSpec> TryFrom<ExecutionPayloadHeader<T>> for ExecutionPayloadHeaderMerge<T> {
type Error = BeaconStateError;
fn try_from(header: ExecutionPayloadHeader<T>) -> Result<Self, Self::Error> {
match header {
ExecutionPayloadHeader::Merge(execution_payload_header) => Ok(execution_payload_header),
_ => Err(BeaconStateError::IncorrectStateVariant),
}
}
}
impl<T: EthSpec> TryFrom<ExecutionPayloadHeader<T>> for ExecutionPayloadHeaderCapella<T> {
type Error = BeaconStateError;
fn try_from(header: ExecutionPayloadHeader<T>) -> Result<Self, Self::Error> {
match header {
ExecutionPayloadHeader::Capella(execution_payload_header) => {
Ok(execution_payload_header)
}
_ => Err(BeaconStateError::IncorrectStateVariant),
}
}
}
impl<T: EthSpec> TryFrom<ExecutionPayloadHeader<T>> for ExecutionPayloadHeaderEip4844<T> {
type Error = BeaconStateError;
fn try_from(header: ExecutionPayloadHeader<T>) -> Result<Self, Self::Error> {
match header {
ExecutionPayloadHeader::Eip4844(execution_payload_header) => {
Ok(execution_payload_header)
}
_ => Err(BeaconStateError::IncorrectStateVariant),
}
}
}

View File

@ -11,6 +11,7 @@ pub enum ForkName {
Base,
Altair,
Merge,
Capella,
Eip4844,
}
@ -20,6 +21,7 @@ impl ForkName {
ForkName::Base,
ForkName::Altair,
ForkName::Merge,
ForkName::Capella,
ForkName::Eip4844,
]
}
@ -32,24 +34,35 @@ impl ForkName {
ForkName::Base => {
spec.altair_fork_epoch = None;
spec.bellatrix_fork_epoch = None;
spec.capella_fork_epoch = None;
spec.eip4844_fork_epoch = None;
spec
}
ForkName::Altair => {
spec.altair_fork_epoch = Some(Epoch::new(0));
spec.bellatrix_fork_epoch = None;
spec.capella_fork_epoch = None;
spec.eip4844_fork_epoch = None;
spec
}
ForkName::Merge => {
spec.altair_fork_epoch = Some(Epoch::new(0));
spec.bellatrix_fork_epoch = Some(Epoch::new(0));
spec.capella_fork_epoch = None;
spec.eip4844_fork_epoch = None;
spec
}
ForkName::Capella => {
spec.altair_fork_epoch = Some(Epoch::new(0));
spec.bellatrix_fork_epoch = Some(Epoch::new(0));
spec.capella_fork_epoch = Some(Epoch::new(0));
spec.eip4844_fork_epoch = None;
spec
}
ForkName::Eip4844 => {
spec.altair_fork_epoch = Some(Epoch::new(0));
spec.bellatrix_fork_epoch = Some(Epoch::new(0));
spec.capella_fork_epoch = Some(Epoch::new(0));
spec.eip4844_fork_epoch = Some(Epoch::new(0));
spec
}
@ -64,7 +77,8 @@ impl ForkName {
ForkName::Base => None,
ForkName::Altair => Some(ForkName::Base),
ForkName::Merge => Some(ForkName::Altair),
ForkName::Eip4844 => Some(ForkName::Merge),
ForkName::Capella => Some(ForkName::Merge),
ForkName::Eip4844 => Some(ForkName::Capella),
}
}
@ -75,7 +89,8 @@ impl ForkName {
match self {
ForkName::Base => Some(ForkName::Altair),
ForkName::Altair => Some(ForkName::Merge),
ForkName::Merge => Some(ForkName::Eip4844),
ForkName::Merge => Some(ForkName::Capella),
ForkName::Capella => Some(ForkName::Eip4844),
ForkName::Eip4844 => None,
}
}
@ -118,6 +133,10 @@ macro_rules! map_fork_name_with {
let (value, extra_data) = $body;
($t::Merge(value), extra_data)
}
ForkName::Capella => {
let (value, extra_data) = $body;
($t::Capella(value), extra_data)
}
ForkName::Eip4844 => {
let (value, extra_data) = $body;
($t::Eip4844(value), extra_data)
@ -134,6 +153,7 @@ impl FromStr for ForkName {
"phase0" | "base" => ForkName::Base,
"altair" => ForkName::Altair,
"bellatrix" | "merge" => ForkName::Merge,
"capella" => ForkName::Capella,
"eip4844" => ForkName::Eip4844,
_ => return Err(format!("unknown fork name: {}", fork_name)),
})
@ -146,6 +166,7 @@ impl Display for ForkName {
ForkName::Base => "phase0".fmt(f),
ForkName::Altair => "altair".fmt(f),
ForkName::Merge => "bellatrix".fmt(f),
ForkName::Capella => "capella".fmt(f),
ForkName::Eip4844 => "eip4844".fmt(f),
}
}

View File

@ -1,5 +1,5 @@
//! Ethereum 2.0 types
#![feature(generic_associated_types)]
// Required for big type-level numbers
#![recursion_limit = "128"]
// Clippy lint set up
@ -85,6 +85,7 @@ pub mod sync_selection_proof;
pub mod sync_subnet_id;
mod tree_hash_impls;
pub mod validator_registration_data;
pub mod withdrawal;
pub mod slot_data;
#[cfg(feature = "sqlite")]
@ -105,12 +106,12 @@ pub use crate::attestation_data::AttestationData;
pub use crate::attestation_duty::AttestationDuty;
pub use crate::attester_slashing::AttesterSlashing;
pub use crate::beacon_block::{
BeaconBlock, BeaconBlockAltair, BeaconBlockBase, BeaconBlockEip4844, BeaconBlockMerge,
BeaconBlockRef, BeaconBlockRefMut,
BeaconBlock, BeaconBlockAltair, BeaconBlockBase, BeaconBlockCapella, BeaconBlockEip4844,
BeaconBlockMerge, BeaconBlockRef, BeaconBlockRefMut, BlindedBeaconBlock,
};
pub use crate::beacon_block_body::{
BeaconBlockBody, BeaconBlockBodyAltair, BeaconBlockBodyBase, BeaconBlockBodyEip4844,
BeaconBlockBodyMerge, BeaconBlockBodyRef, BeaconBlockBodyRefMut,
BeaconBlockBody, BeaconBlockBodyAltair, BeaconBlockBodyBase, BeaconBlockBodyCapella,
BeaconBlockBodyEip4844, BeaconBlockBodyMerge, BeaconBlockBodyRef, BeaconBlockBodyRefMut,
};
pub use crate::beacon_block_header::BeaconBlockHeader;
pub use crate::beacon_committee::{BeaconCommittee, OwnedBeaconCommittee};
@ -129,8 +130,14 @@ pub use crate::enr_fork_id::EnrForkId;
pub use crate::eth1_data::Eth1Data;
pub use crate::eth_spec::EthSpecId;
pub use crate::execution_block_hash::ExecutionBlockHash;
pub use crate::execution_payload::{ExecutionPayload, Transaction, Transactions};
pub use crate::execution_payload_header::ExecutionPayloadHeader;
pub use crate::execution_payload::{
ExecutionPayload, ExecutionPayloadCapella, ExecutionPayloadEip4844, ExecutionPayloadMerge,
ExecutionPayloadRef, Transaction, Transactions,
};
pub use crate::execution_payload_header::{
ExecutionPayloadHeader, ExecutionPayloadHeaderCapella, ExecutionPayloadHeaderEip4844,
ExecutionPayloadHeaderMerge, ExecutionPayloadHeaderRef, ExecutionPayloadHeaderRefMut,
};
pub use crate::fork::Fork;
pub use crate::fork_context::ForkContext;
pub use crate::fork_data::ForkData;
@ -143,7 +150,11 @@ pub use crate::kzg_commitment::KzgCommitment;
pub use crate::kzg_proof::KzgProof;
pub use crate::participation_flags::ParticipationFlags;
pub use crate::participation_list::ParticipationList;
pub use crate::payload::{BlindedPayload, BlockType, ExecPayload, FullPayload};
pub use crate::payload::{
AbstractExecPayload, BlindedPayload, BlindedPayloadCapella, BlindedPayloadEip4844,
BlindedPayloadMerge, BlindedPayloadRef, BlockType, ExecPayload, FullPayload,
FullPayloadCapella, FullPayloadEip4844, FullPayloadMerge, FullPayloadRef,
};
pub use crate::pending_attestation::PendingAttestation;
pub use crate::preset::{AltairPreset, BasePreset, BellatrixPreset};
pub use crate::proposer_preparation_data::ProposerPreparationData;
@ -176,6 +187,7 @@ pub use crate::validator::Validator;
pub use crate::validator_registration_data::*;
pub use crate::validator_subscription::ValidatorSubscription;
pub use crate::voluntary_exit::VoluntaryExit;
pub use crate::withdrawal::Withdrawal;
use serde_big_array::BigArray;
pub type CommitteeIndex = u64;

File diff suppressed because it is too large Load Diff

View File

@ -38,7 +38,7 @@ impl From<SignedBeaconBlockHash> for Hash256 {
/// A `BeaconBlock` and a signature from its proposer.
#[superstruct(
variants(Base, Altair, Merge, Eip4844),
variants(Base, Altair, Merge, Capella, Eip4844),
variant_attributes(
derive(
Debug,
@ -65,13 +65,15 @@ impl From<SignedBeaconBlockHash> for Hash256 {
#[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))]
#[tree_hash(enum_behaviour = "transparent")]
#[ssz(enum_behaviour = "transparent")]
pub struct SignedBeaconBlock<E: EthSpec, Payload: ExecPayload<E> = FullPayload<E>> {
pub struct SignedBeaconBlock<E: EthSpec, Payload: AbstractExecPayload<E> = FullPayload<E>> {
#[superstruct(only(Base), partial_getter(rename = "message_base"))]
pub message: BeaconBlockBase<E, Payload>,
#[superstruct(only(Altair), partial_getter(rename = "message_altair"))]
pub message: BeaconBlockAltair<E, Payload>,
#[superstruct(only(Merge), partial_getter(rename = "message_merge"))]
pub message: BeaconBlockMerge<E, Payload>,
#[superstruct(only(Capella), partial_getter(rename = "message_capella"))]
pub message: BeaconBlockCapella<E, Payload>,
#[superstruct(only(Eip4844), partial_getter(rename = "message_eip4844"))]
pub message: BeaconBlockEip4844<E, Payload>,
pub signature: Signature,
@ -79,7 +81,7 @@ pub struct SignedBeaconBlock<E: EthSpec, Payload: ExecPayload<E> = FullPayload<E
pub type SignedBlindedBeaconBlock<E> = SignedBeaconBlock<E, BlindedPayload<E>>;
impl<E: EthSpec, Payload: ExecPayload<E>> SignedBeaconBlock<E, Payload> {
impl<E: EthSpec, Payload: AbstractExecPayload<E>> SignedBeaconBlock<E, Payload> {
/// Returns the name of the fork pertaining to `self`.
///
/// Will return an `Err` if `self` has been instantiated to a variant conflicting with the fork
@ -131,6 +133,9 @@ impl<E: EthSpec, Payload: ExecPayload<E>> SignedBeaconBlock<E, Payload> {
BeaconBlock::Merge(message) => {
SignedBeaconBlock::Merge(SignedBeaconBlockMerge { message, signature })
}
BeaconBlock::Capella(message) => {
SignedBeaconBlock::Capella(SignedBeaconBlockCapella { message, signature })
}
BeaconBlock::Eip4844(message) => {
SignedBeaconBlock::Eip4844(SignedBeaconBlockEip4844 { message, signature })
}
@ -263,7 +268,7 @@ impl<E: EthSpec> From<SignedBeaconBlockAltair<E, BlindedPayload<E>>>
impl<E: EthSpec> SignedBeaconBlockMerge<E, BlindedPayload<E>> {
pub fn into_full_block(
self,
execution_payload: ExecutionPayload<E>,
execution_payload: ExecutionPayloadMerge<E>,
) -> SignedBeaconBlockMerge<E, FullPayload<E>> {
let SignedBeaconBlockMerge {
message:
@ -283,7 +288,7 @@ impl<E: EthSpec> SignedBeaconBlockMerge<E, BlindedPayload<E>> {
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: BlindedPayload { .. },
execution_payload: BlindedPayloadMerge { .. },
},
},
signature,
@ -304,7 +309,59 @@ impl<E: EthSpec> SignedBeaconBlockMerge<E, BlindedPayload<E>> {
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: FullPayload { execution_payload },
execution_payload: FullPayloadMerge { execution_payload },
},
},
signature,
}
}
}
impl<E: EthSpec> SignedBeaconBlockCapella<E, BlindedPayload<E>> {
pub fn into_full_block(
self,
execution_payload: ExecutionPayloadCapella<E>,
) -> SignedBeaconBlockCapella<E, FullPayload<E>> {
let SignedBeaconBlockCapella {
message:
BeaconBlockCapella {
slot,
proposer_index,
parent_root,
state_root,
body:
BeaconBlockBodyCapella {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: BlindedPayloadCapella { .. },
},
},
signature,
} = self;
SignedBeaconBlockCapella {
message: BeaconBlockCapella {
slot,
proposer_index,
parent_root,
state_root,
body: BeaconBlockBodyCapella {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: FullPayloadCapella { execution_payload },
},
},
signature,
@ -315,7 +372,7 @@ impl<E: EthSpec> SignedBeaconBlockMerge<E, BlindedPayload<E>> {
impl<E: EthSpec> SignedBeaconBlockEip4844<E, BlindedPayload<E>> {
pub fn into_full_block(
self,
execution_payload: ExecutionPayload<E>,
execution_payload: ExecutionPayloadEip4844<E>,
) -> SignedBeaconBlockEip4844<E, FullPayload<E>> {
let SignedBeaconBlockEip4844 {
message:
@ -335,7 +392,7 @@ impl<E: EthSpec> SignedBeaconBlockEip4844<E, BlindedPayload<E>> {
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: BlindedPayload { .. },
execution_payload: BlindedPayloadEip4844 { .. },
blob_kzg_commitments,
},
},
@ -357,7 +414,7 @@ impl<E: EthSpec> SignedBeaconBlockEip4844<E, BlindedPayload<E>> {
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: FullPayload { execution_payload },
execution_payload: FullPayloadEip4844 { execution_payload },
blob_kzg_commitments,
},
},
@ -371,15 +428,23 @@ impl<E: EthSpec> SignedBeaconBlock<E, BlindedPayload<E>> {
self,
execution_payload: Option<ExecutionPayload<E>>,
) -> Option<SignedBeaconBlock<E, FullPayload<E>>> {
let full_block = match self {
SignedBeaconBlock::Base(block) => SignedBeaconBlock::Base(block.into()),
SignedBeaconBlock::Altair(block) => SignedBeaconBlock::Altair(block.into()),
SignedBeaconBlock::Merge(block) => {
SignedBeaconBlock::Merge(block.into_full_block(execution_payload?))
let full_block = match (self, execution_payload) {
(SignedBeaconBlock::Base(block), _) => SignedBeaconBlock::Base(block.into()),
(SignedBeaconBlock::Altair(block), _) => SignedBeaconBlock::Altair(block.into()),
(SignedBeaconBlock::Merge(block), Some(ExecutionPayload::Merge(payload))) => {
SignedBeaconBlock::Merge(block.into_full_block(payload))
}
SignedBeaconBlock::Eip4844(block) => {
SignedBeaconBlock::Eip4844(block.into_full_block(execution_payload?))
(SignedBeaconBlock::Capella(block), Some(ExecutionPayload::Capella(payload))) => {
SignedBeaconBlock::Capella(block.into_full_block(payload))
}
(SignedBeaconBlock::Eip4844(block), Some(ExecutionPayload::Eip4844(payload))) => {
SignedBeaconBlock::Eip4844(block.into_full_block(payload))
}
// avoid wildcard matching forks so that compiler will
// direct us here when a new fork has been added
(SignedBeaconBlock::Merge(_), _) => return None,
(SignedBeaconBlock::Capella(_), _) => return None,
(SignedBeaconBlock::Eip4844(_), _) => return None,
};
Some(full_block)
}

View File

@ -0,0 +1,27 @@
use crate::test_utils::TestRandom;
use crate::*;
use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash;
/// A deposit to potentially become a beacon chain validator.
///
/// Spec v0.12.1
#[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))]
#[derive(
Debug, PartialEq, Hash, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom,
)]
pub struct Withdrawal {
#[serde(with = "eth2_serde_utils::quoted_u64")]
pub index: u64,
pub address: Address,
pub amount: u64,
}
#[cfg(test)]
mod tests {
use super::*;
ssz_and_tree_hash_tests!(Withdrawal);
}