EIP-7732 Boiler Plate

This commit is contained in:
Mark Mackey
2024-08-27 12:38:00 -05:00
parent c042dc14d7
commit 13130dfa4f
52 changed files with 891 additions and 153 deletions

View File

@@ -57,7 +57,8 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
| BeaconState::Bellatrix(_) | BeaconState::Bellatrix(_)
| BeaconState::Capella(_) | BeaconState::Capella(_)
| BeaconState::Deneb(_) | BeaconState::Deneb(_)
| BeaconState::Electra(_) => self.compute_attestation_rewards_altair(state, validators), | BeaconState::Electra(_)
| BeaconState::EIP7732(_) => self.compute_attestation_rewards_altair(state, validators),
} }
} }

View File

@@ -10,8 +10,8 @@ use tokio::sync::{
}; };
use tokio_stream::{wrappers::UnboundedReceiverStream, Stream}; use tokio_stream::{wrappers::UnboundedReceiverStream, Stream};
use types::{ use types::{
ChainSpec, EthSpec, ExecPayload, ExecutionBlockHash, ForkName, Hash256, SignedBeaconBlock, ChainSpec, EthSpec, ExecPayload, ExecutionBlockHash, ExecutionPayloadEIP7732, ForkName,
SignedBlindedBeaconBlock, Slot, Hash256, SignedBeaconBlock, SignedBlindedBeaconBlock, Slot,
}; };
use types::{ use types::{
ExecutionPayload, ExecutionPayloadBellatrix, ExecutionPayloadCapella, ExecutionPayloadElectra, ExecutionPayload, ExecutionPayloadBellatrix, ExecutionPayloadCapella, ExecutionPayloadElectra,
@@ -99,6 +99,7 @@ fn reconstruct_default_header_block<E: EthSpec>(
ForkName::Capella => ExecutionPayloadCapella::default().into(), ForkName::Capella => ExecutionPayloadCapella::default().into(),
ForkName::Deneb => ExecutionPayloadDeneb::default().into(), ForkName::Deneb => ExecutionPayloadDeneb::default().into(),
ForkName::Electra => ExecutionPayloadElectra::default().into(), ForkName::Electra => ExecutionPayloadElectra::default().into(),
ForkName::EIP7732 => ExecutionPayloadEIP7732::default().into(),
ForkName::Base | ForkName::Altair => { ForkName::Base | ForkName::Altair => {
return Err(Error::PayloadReconstruction(format!( return Err(Error::PayloadReconstruction(format!(
"Block with fork variant {} has execution payload", "Block with fork variant {} has execution payload",

View File

@@ -5322,7 +5322,8 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
BeaconState::Bellatrix(_) BeaconState::Bellatrix(_)
| BeaconState::Capella(_) | BeaconState::Capella(_)
| BeaconState::Deneb(_) | BeaconState::Deneb(_)
| BeaconState::Electra(_) => { | BeaconState::Electra(_)
| BeaconState::EIP7732(_) => {
let prepare_payload_handle = get_execution_payload( let prepare_payload_handle = get_execution_payload(
self.clone(), self.clone(),
&state, &state,
@@ -5751,6 +5752,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
execution_payload_value, execution_payload_value,
) )
} }
BeaconState::EIP7732(_) => todo!("EIP-7732 block production"),
}; };
let block = SignedBeaconBlock::from_block( let block = SignedBeaconBlock::from_block(
@@ -6069,7 +6071,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
payload_attributes payload_attributes
} else { } else {
let prepare_slot_fork = self.spec.fork_name_at_slot::<T::EthSpec>(prepare_slot); let prepare_slot_fork = self.spec.fork_name_at_slot::<T::EthSpec>(prepare_slot);
let withdrawals = if prepare_slot_fork.capella_enabled() { let withdrawals = if prepare_slot_fork.capella_enabled() {
let chain = self.clone(); let chain = self.clone();
self.spawn_blocking_handle( self.spawn_blocking_handle(

View File

@@ -378,15 +378,18 @@ pub fn get_execution_payload<T: BeaconChainTypes>(
let latest_execution_payload_header_block_hash = let latest_execution_payload_header_block_hash =
state.latest_execution_payload_header()?.block_hash(); state.latest_execution_payload_header()?.block_hash();
let withdrawals = match state { let withdrawals = match state {
&BeaconState::Capella(_) | &BeaconState::Deneb(_) | &BeaconState::Electra(_) => { &BeaconState::Capella(_)
Some(get_expected_withdrawals(state, spec)?.0.into()) | &BeaconState::Deneb(_)
} | &BeaconState::Electra(_)
| &BeaconState::EIP7732(_) => Some(get_expected_withdrawals(state, spec)?.0.into()),
&BeaconState::Bellatrix(_) => None, &BeaconState::Bellatrix(_) => None,
// These shouldn't happen but they're here to make the pattern irrefutable // These shouldn't happen but they're here to make the pattern irrefutable
&BeaconState::Base(_) | &BeaconState::Altair(_) => None, &BeaconState::Base(_) | &BeaconState::Altair(_) => None,
}; };
let parent_beacon_block_root = match state { let parent_beacon_block_root = match state {
BeaconState::Deneb(_) | BeaconState::Electra(_) => Some(parent_block_root), BeaconState::Deneb(_) | BeaconState::Electra(_) | BeaconState::EIP7732(_) => {
Some(parent_block_root)
}
BeaconState::Bellatrix(_) | BeaconState::Capella(_) => None, BeaconState::Bellatrix(_) | BeaconState::Capella(_) => None,
// These shouldn't happen but they're here to make the pattern irrefutable // These shouldn't happen but they're here to make the pattern irrefutable
BeaconState::Base(_) | BeaconState::Altair(_) => None, BeaconState::Base(_) | BeaconState::Altair(_) => None,

View File

@@ -918,9 +918,9 @@ where
| SignedBeaconBlock::Altair(_) | SignedBeaconBlock::Altair(_)
| SignedBeaconBlock::Bellatrix(_) | SignedBeaconBlock::Bellatrix(_)
| SignedBeaconBlock::Capella(_) => (signed_block, None), | SignedBeaconBlock::Capella(_) => (signed_block, None),
SignedBeaconBlock::Deneb(_) | SignedBeaconBlock::Electra(_) => { SignedBeaconBlock::Deneb(_)
(signed_block, block_response.blob_items) | SignedBeaconBlock::Electra(_)
} | SignedBeaconBlock::EIP7732(_) => (signed_block, block_response.blob_items),
}; };
(block_contents, block_response.state) (block_contents, block_response.state)
@@ -982,9 +982,9 @@ where
| SignedBeaconBlock::Altair(_) | SignedBeaconBlock::Altair(_)
| SignedBeaconBlock::Bellatrix(_) | SignedBeaconBlock::Bellatrix(_)
| SignedBeaconBlock::Capella(_) => (signed_block, None), | SignedBeaconBlock::Capella(_) => (signed_block, None),
SignedBeaconBlock::Deneb(_) | SignedBeaconBlock::Electra(_) => { SignedBeaconBlock::Deneb(_)
(signed_block, block_response.blob_items) | SignedBeaconBlock::Electra(_)
} | SignedBeaconBlock::EIP7732(_) => (signed_block, block_response.blob_items),
}; };
(block_contents, pre_state) (block_contents, pre_state)
} }

View File

@@ -882,9 +882,14 @@ impl HttpJsonRpc {
.try_into() .try_into()
.map_err(Error::BadResponse) .map_err(Error::BadResponse)
} }
ForkName::Base | ForkName::Altair | ForkName::Deneb | ForkName::Electra => Err( ForkName::Base
Error::UnsupportedForkVariant(format!("called get_payload_v2 with {}", fork_name)), | ForkName::Altair
), | ForkName::Deneb
| ForkName::Electra
| ForkName::EIP7732 => Err(Error::UnsupportedForkVariant(format!(
"called get_payload_v2 with {}",
fork_name
))),
} }
} }
@@ -912,7 +917,8 @@ impl HttpJsonRpc {
| ForkName::Altair | ForkName::Altair
| ForkName::Bellatrix | ForkName::Bellatrix
| ForkName::Capella | ForkName::Capella
| ForkName::Electra => Err(Error::UnsupportedForkVariant(format!( | ForkName::Electra
| ForkName::EIP7732 => Err(Error::UnsupportedForkVariant(format!(
"called get_payload_v3 with {}", "called get_payload_v3 with {}",
fork_name fork_name
))), ))),
@@ -943,7 +949,8 @@ impl HttpJsonRpc {
| ForkName::Altair | ForkName::Altair
| ForkName::Bellatrix | ForkName::Bellatrix
| ForkName::Capella | ForkName::Capella
| ForkName::Deneb => Err(Error::UnsupportedForkVariant(format!( | ForkName::Deneb
| ForkName::EIP7732 => Err(Error::UnsupportedForkVariant(format!(
"called get_payload_v4 with {}", "called get_payload_v4 with {}",
fork_name fork_name
))), ))),
@@ -1249,6 +1256,7 @@ impl HttpJsonRpc {
Err(Error::RequiredMethodUnsupported("engine_getPayloadv4")) Err(Error::RequiredMethodUnsupported("engine_getPayloadv4"))
} }
} }
ForkName::EIP7732 => todo!("EIP-7732 Engine API get_payload"),
ForkName::Base | ForkName::Altair => Err(Error::UnsupportedForkVariant(format!( ForkName::Base | ForkName::Altair => Err(Error::UnsupportedForkVariant(format!(
"called get_payload with {}", "called get_payload with {}",
fork_name fork_name

View File

@@ -219,6 +219,9 @@ impl<E: EthSpec> From<ExecutionPayload<E>> for JsonExecutionPayload<E> {
ExecutionPayload::Capella(payload) => JsonExecutionPayload::V2(payload.into()), ExecutionPayload::Capella(payload) => JsonExecutionPayload::V2(payload.into()),
ExecutionPayload::Deneb(payload) => JsonExecutionPayload::V3(payload.into()), ExecutionPayload::Deneb(payload) => JsonExecutionPayload::V3(payload.into()),
ExecutionPayload::Electra(payload) => JsonExecutionPayload::V4(payload.into()), ExecutionPayload::Electra(payload) => JsonExecutionPayload::V4(payload.into()),
ExecutionPayload::EIP7732(_payload) => {
todo!("EIP-7732 Engine API: JsonExecutionPayload conversion")
}
} }
} }
} }

View File

@@ -187,6 +187,8 @@ impl<'a, E: EthSpec> TryFrom<BeaconBlockRef<'a, E>> for NewPayloadRequest<'a, E>
parent_beacon_block_root: block_ref.parent_root, parent_beacon_block_root: block_ref.parent_root,
execution_requests_list: &block_ref.body.execution_requests, execution_requests_list: &block_ref.body.execution_requests,
})), })),
//TODO(EIP7732): Need new method of constructing NewPayloadRequest
BeaconBlockRef::EIP7732(_) => Err(Self::Error::IncorrectStateVariant),
} }
} }
} }
@@ -206,6 +208,8 @@ impl<'a, E: EthSpec> TryFrom<ExecutionPayloadRef<'a, E>> for NewPayloadRequest<'
})), })),
ExecutionPayloadRef::Deneb(_) => Err(Self::Error::IncorrectStateVariant), ExecutionPayloadRef::Deneb(_) => Err(Self::Error::IncorrectStateVariant),
ExecutionPayloadRef::Electra(_) => Err(Self::Error::IncorrectStateVariant), ExecutionPayloadRef::Electra(_) => Err(Self::Error::IncorrectStateVariant),
//TODO(EIP7732): Probably time to just get rid of this
ExecutionPayloadRef::EIP7732(_) => Err(Self::Error::IncorrectStateVariant),
} }
} }
} }

View File

@@ -49,13 +49,12 @@ use types::builder_bid::BuilderBid;
use types::non_zero_usize::new_non_zero_usize; use types::non_zero_usize::new_non_zero_usize;
use types::payload::BlockProductionVersion; use types::payload::BlockProductionVersion;
use types::{ use types::{
AbstractExecPayload, BlobsList, ExecutionPayloadDeneb, ExecutionRequests, KzgProofs, AbstractExecPayload, BlobsList, ExecutionRequests, KzgProofs, SignedBlindedBeaconBlock,
SignedBlindedBeaconBlock,
}; };
use types::{ use types::{
BeaconStateError, BlindedPayload, ChainSpec, Epoch, ExecPayload, ExecutionPayloadBellatrix, BeaconStateError, BlindedPayload, ChainSpec, Epoch, ExecPayload, ExecutionPayloadBellatrix,
ExecutionPayloadCapella, ExecutionPayloadElectra, FullPayload, ProposerPreparationData, ExecutionPayloadCapella, ExecutionPayloadDeneb, ExecutionPayloadElectra, FullPayload,
PublicKeyBytes, Signature, Slot, ProposerPreparationData, PublicKeyBytes, Signature, Slot,
}; };
mod block_hash; mod block_hash;
@@ -1833,6 +1832,9 @@ impl<E: EthSpec> ExecutionLayer<E> {
ForkName::Base | ForkName::Altair => { ForkName::Base | ForkName::Altair => {
return Err(Error::InvalidForkForPayload); return Err(Error::InvalidForkForPayload);
} }
ForkName::EIP7732 => {
return Err(Error::InvalidForkForPayload);
}
}; };
return Ok(Some(payload)); return Ok(Some(payload));
} }

View File

@@ -800,6 +800,8 @@ pub fn generate_genesis_header<E: EthSpec>(
*header.transactions_root_mut() = empty_transactions_root; *header.transactions_root_mut() = empty_transactions_root;
Some(header) Some(header)
} }
// TODO(EIP-7732): need to look into this
ForkName::EIP7732 => None,
} }
} }

View File

@@ -348,6 +348,9 @@ pub fn serve<E: EthSpec>(
SignedBlindedBeaconBlock::Electra(block) => { SignedBlindedBeaconBlock::Electra(block) => {
block.message.body.execution_payload.tree_hash_root() block.message.body.execution_payload.tree_hash_root()
} }
SignedBlindedBeaconBlock::EIP7732(_) => {
return Err(reject("invalid fork EIP7732"));
}
}; };
let payload = builder let payload = builder
.el .el
@@ -498,6 +501,9 @@ pub fn serve<E: EthSpec>(
// first to avoid polluting the execution block generator with invalid payload attributes // first to avoid polluting the execution block generator with invalid payload attributes
// NOTE: this was part of an effort to add payload attribute uniqueness checks, // NOTE: this was part of an effort to add payload attribute uniqueness checks,
// which was abandoned because it broke too many tests in subtle ways. // which was abandoned because it broke too many tests in subtle ways.
ForkName::EIP7732 => {
return Err(reject("invalid fork"));
}
ForkName::Bellatrix | ForkName::Capella => PayloadAttributes::new( ForkName::Bellatrix | ForkName::Capella => PayloadAttributes::new(
timestamp, timestamp,
*prev_randao, *prev_randao,
@@ -551,6 +557,9 @@ pub fn serve<E: EthSpec>(
) = payload_response.into(); ) = payload_response.into();
match fork { match fork {
ForkName::EIP7732 => {
return Err(reject("invalid fork"));
}
ForkName::Electra => BuilderBid::Electra(BuilderBidElectra { ForkName::Electra => BuilderBid::Electra(BuilderBidElectra {
header: payload header: payload
.as_electra() .as_electra()
@@ -603,6 +612,9 @@ pub fn serve<E: EthSpec>(
Option<ExecutionRequests<E>>, Option<ExecutionRequests<E>>,
) = payload_response.into(); ) = payload_response.into();
match fork { match fork {
ForkName::EIP7732 => {
return Err(reject("invalid fork"));
}
ForkName::Electra => BuilderBid::Electra(BuilderBidElectra { ForkName::Electra => BuilderBid::Electra(BuilderBidElectra {
header: payload header: payload
.as_electra() .as_electra()

View File

@@ -20,7 +20,7 @@ use types::{
LightClientBootstrap, LightClientFinalityUpdate, LightClientOptimisticUpdate, LightClientBootstrap, LightClientFinalityUpdate, LightClientOptimisticUpdate,
LightClientUpdate, RuntimeVariableList, SignedBeaconBlock, SignedBeaconBlockAltair, LightClientUpdate, RuntimeVariableList, SignedBeaconBlock, SignedBeaconBlockAltair,
SignedBeaconBlockBase, SignedBeaconBlockBellatrix, SignedBeaconBlockCapella, SignedBeaconBlockBase, SignedBeaconBlockBellatrix, SignedBeaconBlockCapella,
SignedBeaconBlockDeneb, SignedBeaconBlockElectra, SignedBeaconBlockDeneb, SignedBeaconBlockEIP7732, SignedBeaconBlockElectra,
}; };
use unsigned_varint::codec::Uvi; use unsigned_varint::codec::Uvi;
@@ -458,6 +458,9 @@ fn context_bytes<E: EthSpec>(
return match **ref_box_block { return match **ref_box_block {
// NOTE: If you are adding another fork type here, be sure to modify the // NOTE: If you are adding another fork type here, be sure to modify the
// `fork_context.to_context_bytes()` function to support it as well! // `fork_context.to_context_bytes()` function to support it as well!
SignedBeaconBlock::EIP7732 { .. } => {
fork_context.to_context_bytes(ForkName::EIP7732)
}
SignedBeaconBlock::Electra { .. } => { SignedBeaconBlock::Electra { .. } => {
fork_context.to_context_bytes(ForkName::Electra) fork_context.to_context_bytes(ForkName::Electra)
} }
@@ -682,7 +685,7 @@ fn handle_rpc_response<E: EthSpec>(
SignedBeaconBlock::Base(SignedBeaconBlockBase::from_ssz_bytes(decoded_buffer)?), SignedBeaconBlock::Base(SignedBeaconBlockBase::from_ssz_bytes(decoded_buffer)?),
)))), )))),
SupportedProtocol::BlobsByRangeV1 => match fork_name { SupportedProtocol::BlobsByRangeV1 => match fork_name {
Some(ForkName::Deneb) | Some(ForkName::Electra) => { Some(ForkName::Deneb) | Some(ForkName::Electra) | Some(ForkName::EIP7732) => {
Ok(Some(RpcSuccessResponse::BlobsByRange(Arc::new( Ok(Some(RpcSuccessResponse::BlobsByRange(Arc::new(
BlobSidecar::from_ssz_bytes(decoded_buffer)?, BlobSidecar::from_ssz_bytes(decoded_buffer)?,
)))) ))))
@@ -703,7 +706,7 @@ fn handle_rpc_response<E: EthSpec>(
)), )),
}, },
SupportedProtocol::BlobsByRootV1 => match fork_name { SupportedProtocol::BlobsByRootV1 => match fork_name {
Some(ForkName::Deneb) | Some(ForkName::Electra) => { Some(ForkName::Deneb) | Some(ForkName::Electra) | Some(ForkName::EIP7732) => {
Ok(Some(RpcSuccessResponse::BlobsByRoot(Arc::new( Ok(Some(RpcSuccessResponse::BlobsByRoot(Arc::new(
BlobSidecar::from_ssz_bytes(decoded_buffer)?, BlobSidecar::from_ssz_bytes(decoded_buffer)?,
)))) ))))
@@ -864,6 +867,11 @@ fn handle_rpc_response<E: EthSpec>(
decoded_buffer, decoded_buffer,
)?), )?),
)))), )))),
Some(ForkName::EIP7732) => Ok(Some(RpcSuccessResponse::BlocksByRange(Arc::new(
SignedBeaconBlock::EIP7732(SignedBeaconBlockEIP7732::from_ssz_bytes(
decoded_buffer,
)?),
)))),
None => Err(RPCError::ErrorResponse( None => Err(RPCError::ErrorResponse(
RpcErrorResponse::InvalidRequest, RpcErrorResponse::InvalidRequest,
format!( format!(
@@ -897,6 +905,11 @@ fn handle_rpc_response<E: EthSpec>(
decoded_buffer, decoded_buffer,
)?), )?),
)))), )))),
Some(ForkName::EIP7732) => Ok(Some(RpcSuccessResponse::BlocksByRoot(Arc::new(
SignedBeaconBlock::EIP7732(SignedBeaconBlockEIP7732::from_ssz_bytes(
decoded_buffer,
)?),
)))),
None => Err(RPCError::ErrorResponse( None => Err(RPCError::ErrorResponse(
RpcErrorResponse::InvalidRequest, RpcErrorResponse::InvalidRequest,
format!( format!(
@@ -948,12 +961,14 @@ mod tests {
let capella_fork_epoch = Epoch::new(3); let capella_fork_epoch = Epoch::new(3);
let deneb_fork_epoch = Epoch::new(4); let deneb_fork_epoch = Epoch::new(4);
let electra_fork_epoch = Epoch::new(5); let electra_fork_epoch = Epoch::new(5);
let eip7732_fork_epoch = Epoch::new(6);
chain_spec.altair_fork_epoch = Some(altair_fork_epoch); chain_spec.altair_fork_epoch = Some(altair_fork_epoch);
chain_spec.bellatrix_fork_epoch = Some(bellatrix_fork_epoch); chain_spec.bellatrix_fork_epoch = Some(bellatrix_fork_epoch);
chain_spec.capella_fork_epoch = Some(capella_fork_epoch); chain_spec.capella_fork_epoch = Some(capella_fork_epoch);
chain_spec.deneb_fork_epoch = Some(deneb_fork_epoch); chain_spec.deneb_fork_epoch = Some(deneb_fork_epoch);
chain_spec.electra_fork_epoch = Some(electra_fork_epoch); chain_spec.electra_fork_epoch = Some(electra_fork_epoch);
chain_spec.eip7732_fork_epoch = Some(eip7732_fork_epoch);
let current_slot = match fork_name { let current_slot = match fork_name {
ForkName::Base => Slot::new(0), ForkName::Base => Slot::new(0),
@@ -962,6 +977,7 @@ mod tests {
ForkName::Capella => capella_fork_epoch.start_slot(Spec::slots_per_epoch()), ForkName::Capella => capella_fork_epoch.start_slot(Spec::slots_per_epoch()),
ForkName::Deneb => deneb_fork_epoch.start_slot(Spec::slots_per_epoch()), ForkName::Deneb => deneb_fork_epoch.start_slot(Spec::slots_per_epoch()),
ForkName::Electra => electra_fork_epoch.start_slot(Spec::slots_per_epoch()), ForkName::Electra => electra_fork_epoch.start_slot(Spec::slots_per_epoch()),
ForkName::EIP7732 => eip7732_fork_epoch.start_slot(Spec::slots_per_epoch()),
}; };
ForkContext::new::<Spec>(current_slot, Hash256::zero(), &chain_spec) ForkContext::new::<Spec>(current_slot, Hash256::zero(), &chain_spec)
} }

View File

@@ -209,6 +209,11 @@ pub fn rpc_block_limits_by_fork(current_fork: ForkName) -> RpcLimits {
*SIGNED_BEACON_BLOCK_BASE_MIN, // Base block is smaller than altair and bellatrix blocks *SIGNED_BEACON_BLOCK_BASE_MIN, // Base block is smaller than altair and bellatrix blocks
*SIGNED_BEACON_BLOCK_ELECTRA_MAX, // Electra block is larger than Deneb block *SIGNED_BEACON_BLOCK_ELECTRA_MAX, // Electra block is larger than Deneb block
), ),
// TODO(EIP7732): check this
ForkName::EIP7732 => RpcLimits::new(
*SIGNED_BEACON_BLOCK_BASE_MIN, // Base block is smaller than altair and bellatrix blocks
*SIGNED_BEACON_BLOCK_ELECTRA_MAX, // Electra block is larger than EIP7732 block
),
} }
} }
@@ -229,6 +234,9 @@ fn rpc_light_client_updates_by_range_limits_by_fork(current_fork: ForkName) -> R
ForkName::Electra => { ForkName::Electra => {
RpcLimits::new(altair_fixed_len, *LIGHT_CLIENT_UPDATES_BY_RANGE_ELECTRA_MAX) RpcLimits::new(altair_fixed_len, *LIGHT_CLIENT_UPDATES_BY_RANGE_ELECTRA_MAX)
} }
ForkName::EIP7732 => {
RpcLimits::new(altair_fixed_len, *LIGHT_CLIENT_UPDATES_BY_RANGE_ELECTRA_MAX)
}
} }
} }
@@ -249,6 +257,10 @@ fn rpc_light_client_finality_update_limits_by_fork(current_fork: ForkName) -> Rp
ForkName::Electra => { ForkName::Electra => {
RpcLimits::new(altair_fixed_len, *LIGHT_CLIENT_FINALITY_UPDATE_ELECTRA_MAX) RpcLimits::new(altair_fixed_len, *LIGHT_CLIENT_FINALITY_UPDATE_ELECTRA_MAX)
} }
// TODO(EIP7732): check this
ForkName::EIP7732 => {
RpcLimits::new(altair_fixed_len, *LIGHT_CLIENT_FINALITY_UPDATE_ELECTRA_MAX)
}
} }
} }
@@ -271,6 +283,11 @@ fn rpc_light_client_optimistic_update_limits_by_fork(current_fork: ForkName) ->
altair_fixed_len, altair_fixed_len,
*LIGHT_CLIENT_OPTIMISTIC_UPDATE_ELECTRA_MAX, *LIGHT_CLIENT_OPTIMISTIC_UPDATE_ELECTRA_MAX,
), ),
// TODO(EIP7732): check this
ForkName::EIP7732 => RpcLimits::new(
altair_fixed_len,
*LIGHT_CLIENT_OPTIMISTIC_UPDATE_ELECTRA_MAX,
),
} }
} }
@@ -285,6 +302,8 @@ fn rpc_light_client_bootstrap_limits_by_fork(current_fork: ForkName) -> RpcLimit
ForkName::Capella => RpcLimits::new(altair_fixed_len, *LIGHT_CLIENT_BOOTSTRAP_CAPELLA_MAX), ForkName::Capella => RpcLimits::new(altair_fixed_len, *LIGHT_CLIENT_BOOTSTRAP_CAPELLA_MAX),
ForkName::Deneb => RpcLimits::new(altair_fixed_len, *LIGHT_CLIENT_BOOTSTRAP_DENEB_MAX), ForkName::Deneb => RpcLimits::new(altair_fixed_len, *LIGHT_CLIENT_BOOTSTRAP_DENEB_MAX),
ForkName::Electra => RpcLimits::new(altair_fixed_len, *LIGHT_CLIENT_BOOTSTRAP_ELECTRA_MAX), ForkName::Electra => RpcLimits::new(altair_fixed_len, *LIGHT_CLIENT_BOOTSTRAP_ELECTRA_MAX),
// TODO(EIP7732): check this
ForkName::EIP7732 => RpcLimits::new(altair_fixed_len, *LIGHT_CLIENT_BOOTSTRAP_ELECTRA_MAX),
} }
} }

View File

@@ -13,8 +13,9 @@ use types::{
ProposerSlashing, SignedAggregateAndProof, SignedAggregateAndProofBase, ProposerSlashing, SignedAggregateAndProof, SignedAggregateAndProofBase,
SignedAggregateAndProofElectra, SignedBeaconBlock, SignedBeaconBlockAltair, SignedAggregateAndProofElectra, SignedBeaconBlock, SignedBeaconBlockAltair,
SignedBeaconBlockBase, SignedBeaconBlockBellatrix, SignedBeaconBlockCapella, SignedBeaconBlockBase, SignedBeaconBlockBellatrix, SignedBeaconBlockCapella,
SignedBeaconBlockDeneb, SignedBeaconBlockElectra, SignedBlsToExecutionChange, SignedBeaconBlockDeneb, SignedBeaconBlockEIP7732, SignedBeaconBlockElectra,
SignedContributionAndProof, SignedVoluntaryExit, SubnetId, SyncCommitteeMessage, SyncSubnetId, SignedBlsToExecutionChange, SignedContributionAndProof, SignedVoluntaryExit, SubnetId,
SyncCommitteeMessage, SyncSubnetId,
}; };
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
@@ -242,6 +243,10 @@ impl<E: EthSpec> PubsubMessage<E> {
SignedBeaconBlockElectra::from_ssz_bytes(data) SignedBeaconBlockElectra::from_ssz_bytes(data)
.map_err(|e| format!("{:?}", e))?, .map_err(|e| format!("{:?}", e))?,
), ),
Some(ForkName::EIP7732) => SignedBeaconBlock::<E>::EIP7732(
SignedBeaconBlockEIP7732::from_ssz_bytes(data)
.map_err(|e| format!("{:?}", e))?,
),
None => { None => {
return Err(format!( return Err(format!(
"Unknown gossipsub fork digest: {:?}", "Unknown gossipsub fork digest: {:?}",

View File

@@ -61,6 +61,7 @@ pub fn fork_core_topics<E: EthSpec>(fork_name: &ForkName, spec: &ChainSpec) -> V
deneb_topics deneb_topics
} }
ForkName::Electra => vec![], ForkName::Electra => vec![],
ForkName::EIP7732 => todo!("EIP-7732 core topics"),
} }
} }

View File

@@ -16,7 +16,7 @@ use types::*;
/// ///
/// This can be deleted once schema versions prior to V22 are no longer supported. /// This can be deleted once schema versions prior to V22 are no longer supported.
#[superstruct( #[superstruct(
variants(Base, Altair, Bellatrix, Capella, Deneb, Electra), variants(Base, Altair, Bellatrix, Capella, Deneb, Electra, EIP7732),
variant_attributes(derive(Debug, PartialEq, Clone, Encode, Decode)) variant_attributes(derive(Debug, PartialEq, Clone, Encode, Decode))
)] )]
#[derive(Debug, PartialEq, Clone, Encode)] #[derive(Debug, PartialEq, Clone, Encode)]
@@ -68,9 +68,9 @@ where
pub current_epoch_attestations: List<PendingAttestation<E>, E::MaxPendingAttestations>, pub current_epoch_attestations: List<PendingAttestation<E>, E::MaxPendingAttestations>,
// Participation (Altair and later) // Participation (Altair and later)
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra))] #[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra, EIP7732))]
pub previous_epoch_participation: List<ParticipationFlags, E::ValidatorRegistryLimit>, pub previous_epoch_participation: List<ParticipationFlags, E::ValidatorRegistryLimit>,
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra))] #[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra, EIP7732))]
pub current_epoch_participation: List<ParticipationFlags, E::ValidatorRegistryLimit>, pub current_epoch_participation: List<ParticipationFlags, E::ValidatorRegistryLimit>,
// Finality // Finality
@@ -80,13 +80,13 @@ where
pub finalized_checkpoint: Checkpoint, pub finalized_checkpoint: Checkpoint,
// Inactivity // Inactivity
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra))] #[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra, EIP7732))]
pub inactivity_scores: List<u64, E::ValidatorRegistryLimit>, pub inactivity_scores: List<u64, E::ValidatorRegistryLimit>,
// Light-client sync committees // Light-client sync committees
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra))] #[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra, EIP7732))]
pub current_sync_committee: Arc<SyncCommittee<E>>, pub current_sync_committee: Arc<SyncCommittee<E>>,
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra))] #[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra, EIP7732))]
pub next_sync_committee: Arc<SyncCommittee<E>>, pub next_sync_committee: Arc<SyncCommittee<E>>,
// Execution // Execution
@@ -110,37 +110,39 @@ where
partial_getter(rename = "latest_execution_payload_header_electra") partial_getter(rename = "latest_execution_payload_header_electra")
)] )]
pub latest_execution_payload_header: ExecutionPayloadHeaderElectra<E>, pub latest_execution_payload_header: ExecutionPayloadHeaderElectra<E>,
#[superstruct(only(EIP7732), partial_getter(rename = "latest_execution_bid_eip7732"))]
pub latest_execution_bid: ExecutionBid,
// Capella // Capella
#[superstruct(only(Capella, Deneb, Electra))] #[superstruct(only(Capella, Deneb, Electra, EIP7732))]
pub next_withdrawal_index: u64, pub next_withdrawal_index: u64,
#[superstruct(only(Capella, Deneb, Electra))] #[superstruct(only(Capella, Deneb, Electra, EIP7732))]
pub next_withdrawal_validator_index: u64, pub next_withdrawal_validator_index: u64,
#[ssz(skip_serializing, skip_deserializing)] #[ssz(skip_serializing, skip_deserializing)]
#[superstruct(only(Capella, Deneb, Electra))] #[superstruct(only(Capella, Deneb, Electra, EIP7732))]
pub historical_summaries: Option<List<HistoricalSummary, E::HistoricalRootsLimit>>, pub historical_summaries: Option<List<HistoricalSummary, E::HistoricalRootsLimit>>,
// Electra // Electra
#[superstruct(only(Electra))] #[superstruct(only(Electra, EIP7732))]
pub deposit_requests_start_index: u64, pub deposit_requests_start_index: u64,
#[superstruct(only(Electra))] #[superstruct(only(Electra, EIP7732))]
pub deposit_balance_to_consume: u64, pub deposit_balance_to_consume: u64,
#[superstruct(only(Electra))] #[superstruct(only(Electra, EIP7732))]
pub exit_balance_to_consume: u64, pub exit_balance_to_consume: u64,
#[superstruct(only(Electra))] #[superstruct(only(Electra, EIP7732))]
pub earliest_exit_epoch: Epoch, pub earliest_exit_epoch: Epoch,
#[superstruct(only(Electra))] #[superstruct(only(Electra, EIP7732))]
pub consolidation_balance_to_consume: u64, pub consolidation_balance_to_consume: u64,
#[superstruct(only(Electra))] #[superstruct(only(Electra, EIP7732))]
pub earliest_consolidation_epoch: Epoch, pub earliest_consolidation_epoch: Epoch,
#[superstruct(only(Electra))] #[superstruct(only(Electra, EIP7732))]
pub pending_balance_deposits: List<PendingBalanceDeposit, E::PendingBalanceDepositsLimit>, pub pending_balance_deposits: List<PendingBalanceDeposit, E::PendingBalanceDepositsLimit>,
#[superstruct(only(Electra))] #[superstruct(only(Electra, EIP7732))]
pub pending_partial_withdrawals: pub pending_partial_withdrawals:
List<PendingPartialWithdrawal, E::PendingPartialWithdrawalsLimit>, List<PendingPartialWithdrawal, E::PendingPartialWithdrawalsLimit>,
#[superstruct(only(Electra))] #[superstruct(only(Electra, EIP7732))]
pub pending_consolidations: List<PendingConsolidation, E::PendingConsolidationsLimit>, pub pending_consolidations: List<PendingConsolidation, E::PendingConsolidationsLimit>,
} }
@@ -409,6 +411,31 @@ impl<E: EthSpec> TryInto<BeaconState<E>> for PartialBeaconState<E> {
], ],
[historical_summaries] [historical_summaries]
), ),
PartialBeaconState::EIP7732(inner) => impl_try_into_beacon_state!(
inner,
EIP7732,
BeaconStateEIP7732,
[
previous_epoch_participation,
current_epoch_participation,
current_sync_committee,
next_sync_committee,
inactivity_scores,
latest_execution_bid,
next_withdrawal_index,
next_withdrawal_validator_index,
deposit_requests_start_index,
deposit_balance_to_consume,
exit_balance_to_consume,
earliest_exit_epoch,
consolidation_balance_to_consume,
earliest_consolidation_epoch,
pending_balance_deposits,
pending_partial_withdrawals,
pending_consolidations
],
[historical_summaries]
),
}; };
Ok(state) Ok(state)
} }

View File

@@ -1078,6 +1078,10 @@ impl ForkVersionDeserialize for SsePayloadAttributes {
ForkName::Electra => serde_json::from_value(value) ForkName::Electra => serde_json::from_value(value)
.map(Self::V3) .map(Self::V3)
.map_err(serde::de::Error::custom), .map_err(serde::de::Error::custom),
// TODO(EIP7732): check this
ForkName::EIP7732 => serde_json::from_value(value)
.map(Self::V3)
.map_err(serde::de::Error::custom),
ForkName::Base | ForkName::Altair => Err(serde::de::Error::custom(format!( ForkName::Base | ForkName::Altair => Err(serde::de::Error::custom(format!(
"SsePayloadAttributes deserialization for {fork_name} not implemented" "SsePayloadAttributes deserialization for {fork_name} not implemented"
))), ))),
@@ -1883,7 +1887,9 @@ impl<E: EthSpec> TryFrom<Arc<SignedBeaconBlock<E>>> for PublishBlockRequest<E> {
| SignedBeaconBlock::Altair(_) | SignedBeaconBlock::Altair(_)
| SignedBeaconBlock::Bellatrix(_) | SignedBeaconBlock::Bellatrix(_)
| SignedBeaconBlock::Capella(_) => Ok(PublishBlockRequest::Block(block)), | SignedBeaconBlock::Capella(_) => Ok(PublishBlockRequest::Block(block)),
SignedBeaconBlock::Deneb(_) | SignedBeaconBlock::Electra(_) => Err( SignedBeaconBlock::Deneb(_)
| SignedBeaconBlock::Electra(_)
| SignedBeaconBlock::EIP7732(_) => Err(
"post-Deneb block contents cannot be fully constructed from just the signed block", "post-Deneb block contents cannot be fully constructed from just the signed block",
), ),
} }
@@ -1993,9 +1999,12 @@ impl<E: EthSpec> ForkVersionDeserialize for FullPayloadContents<E> {
ForkName::Bellatrix | ForkName::Capella => serde_json::from_value(value) ForkName::Bellatrix | ForkName::Capella => serde_json::from_value(value)
.map(Self::Payload) .map(Self::Payload)
.map_err(serde::de::Error::custom), .map_err(serde::de::Error::custom),
ForkName::Deneb | ForkName::Electra => serde_json::from_value(value) // TODO(EIP7732): check this
.map(Self::PayloadAndBlobs) ForkName::Deneb | ForkName::Electra | ForkName::EIP7732 => {
.map_err(serde::de::Error::custom), serde_json::from_value(value)
.map(Self::PayloadAndBlobs)
.map_err(serde::de::Error::custom)
}
ForkName::Base | ForkName::Altair => Err(serde::de::Error::custom(format!( ForkName::Base | ForkName::Altair => Err(serde::de::Error::custom(format!(
"FullPayloadContents deserialization for {fork_name} not implemented" "FullPayloadContents deserialization for {fork_name} not implemented"
))), ))),

View File

@@ -756,7 +756,8 @@ where
(parent_justified, parent_finalized) (parent_justified, parent_finalized)
} else { } else {
let justification_and_finalization_state = match block { let justification_and_finalization_state = match block {
BeaconBlockRef::Electra(_) BeaconBlockRef::EIP7732(_)
| BeaconBlockRef::Electra(_)
| BeaconBlockRef::Deneb(_) | BeaconBlockRef::Deneb(_)
| BeaconBlockRef::Capella(_) | BeaconBlockRef::Capella(_)
| BeaconBlockRef::Bellatrix(_) | BeaconBlockRef::Bellatrix(_)

View File

@@ -53,7 +53,7 @@ pub fn get_attestation_participation_flag_indices<E: EthSpec>(
participation_flag_indices.push(TIMELY_TARGET_FLAG_INDEX); participation_flag_indices.push(TIMELY_TARGET_FLAG_INDEX);
} }
} }
&BeaconState::Deneb(_) | &BeaconState::Electra(_) => { &BeaconState::Deneb(_) | &BeaconState::Electra(_) | &BeaconState::EIP7732(_) => {
if is_matching_target { if is_matching_target {
// [Modified in Deneb:EIP7045] // [Modified in Deneb:EIP7045]
participation_flag_indices.push(TIMELY_TARGET_FLAG_INDEX); participation_flag_indices.push(TIMELY_TARGET_FLAG_INDEX);

View File

@@ -61,7 +61,8 @@ pub fn slash_validator<E: EthSpec>(
| BeaconState::Bellatrix(_) | BeaconState::Bellatrix(_)
| BeaconState::Capella(_) | BeaconState::Capella(_)
| BeaconState::Deneb(_) | BeaconState::Deneb(_)
| BeaconState::Electra(_) => whistleblower_reward | BeaconState::Electra(_)
| BeaconState::EIP7732(_) => whistleblower_reward
.safe_mul(PROPOSER_WEIGHT)? .safe_mul(PROPOSER_WEIGHT)?
.safe_div(WEIGHT_DENOMINATOR)?, .safe_div(WEIGHT_DENOMINATOR)?,
}; };

View File

@@ -462,6 +462,8 @@ pub fn is_merge_transition_complete<E: EthSpec>(state: &BeaconState<E>) -> bool
.unwrap_or(false), .unwrap_or(false),
BeaconState::Electra(_) | BeaconState::Deneb(_) | BeaconState::Capella(_) => true, BeaconState::Electra(_) | BeaconState::Deneb(_) | BeaconState::Capella(_) => true,
BeaconState::Base(_) | BeaconState::Altair(_) => false, BeaconState::Base(_) | BeaconState::Altair(_) => false,
// TODO(EIP7732): check this cause potuz modified this function for god knows what reason
BeaconState::EIP7732(_) => true,
} }
} }
/// https://github.com/ethereum/consensus-specs/blob/dev/specs/bellatrix/beacon-chain.md#is_merge_transition_block /// https://github.com/ethereum/consensus-specs/blob/dev/specs/bellatrix/beacon-chain.md#is_merge_transition_block
@@ -662,5 +664,6 @@ pub fn process_withdrawals<E: EthSpec, Payload: AbstractExecPayload<E>>(
} }
// these shouldn't even be encountered but they're here for completeness // these shouldn't even be encountered but they're here for completeness
BeaconState::Base(_) | BeaconState::Altair(_) | BeaconState::Bellatrix(_) => Ok(()), BeaconState::Base(_) | BeaconState::Altair(_) | BeaconState::Bellatrix(_) => Ok(()),
BeaconState::EIP7732(_) => todo!("implement potuz' changes to process_withdrawals()"),
} }
} }

View File

@@ -308,6 +308,9 @@ pub fn process_attestations<E: EthSpec, Payload: AbstractExecPayload<E>>(
spec, spec,
)?; )?;
} }
BeaconBlockBodyRef::EIP7732(_) => {
todo!("EIP-7732 implement process_operations()");
}
} }
Ok(()) Ok(())
} }

View File

@@ -398,11 +398,12 @@ where
state.genesis_validators_root(), state.genesis_validators_root(),
), ),
// EIP-7044 // EIP-7044
BeaconState::Deneb(_) | BeaconState::Electra(_) => spec.compute_domain( BeaconState::Deneb(_) | BeaconState::Electra(_) | BeaconState::EIP7732(_) => spec
Domain::VoluntaryExit, .compute_domain(
spec.capella_fork_version, Domain::VoluntaryExit,
state.genesis_validators_root(), spec.capella_fork_version,
), state.genesis_validators_root(),
),
}; };
let message = exit.signing_root(domain); let message = exit.signing_root(domain);

View File

@@ -46,7 +46,7 @@ pub fn verify_attestation_for_block_inclusion<'ctxt, E: EthSpec>(
); );
} }
// [Modified in Deneb:EIP7045] // [Modified in Deneb:EIP7045]
BeaconState::Deneb(_) | BeaconState::Electra(_) => {} BeaconState::Deneb(_) | BeaconState::Electra(_) | BeaconState::EIP7732(_) => {}
} }
verify_attestation_for_state(state, attestation, ctxt, verify_signatures, spec) verify_attestation_for_state(state, attestation, ctxt, verify_signatures, spec)

View File

@@ -47,7 +47,8 @@ pub fn process_epoch<E: EthSpec>(
| BeaconState::Bellatrix(_) | BeaconState::Bellatrix(_)
| BeaconState::Capella(_) | BeaconState::Capella(_)
| BeaconState::Deneb(_) | BeaconState::Deneb(_)
| BeaconState::Electra(_) => altair::process_epoch(state, spec), | BeaconState::Electra(_)
| BeaconState::EIP7732(_) => altair::process_epoch(state, spec),
} }
} }

View File

@@ -16,7 +16,7 @@ use self::indexed_attestation::{IndexedAttestationBase, IndexedAttestationElectr
/// A block of the `BeaconChain`. /// A block of the `BeaconChain`.
#[superstruct( #[superstruct(
variants(Base, Altair, Bellatrix, Capella, Deneb, Electra), variants(Base, Altair, Bellatrix, Capella, Deneb, Electra, EIP7732),
variant_attributes( variant_attributes(
derive( derive(
Debug, Debug,
@@ -75,6 +75,8 @@ pub struct BeaconBlock<E: EthSpec, Payload: AbstractExecPayload<E> = FullPayload
pub body: BeaconBlockBodyDeneb<E, Payload>, pub body: BeaconBlockBodyDeneb<E, Payload>,
#[superstruct(only(Electra), partial_getter(rename = "body_electra"))] #[superstruct(only(Electra), partial_getter(rename = "body_electra"))]
pub body: BeaconBlockBodyElectra<E, Payload>, pub body: BeaconBlockBodyElectra<E, Payload>,
#[superstruct(only(EIP7732), partial_getter(rename = "body_eip7732"))]
pub body: BeaconBlockBodyEIP7732<E, Payload>,
} }
pub type BlindedBeaconBlock<E> = BeaconBlock<E, BlindedPayload<E>>; pub type BlindedBeaconBlock<E> = BeaconBlock<E, BlindedPayload<E>>;
@@ -127,8 +129,9 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlock<E, Payload> {
/// Usually it's better to prefer `from_ssz_bytes` which will decode the correct variant based /// Usually it's better to prefer `from_ssz_bytes` which will decode the correct variant based
/// on the fork slot. /// on the fork slot.
pub fn any_from_ssz_bytes(bytes: &[u8]) -> Result<Self, ssz::DecodeError> { pub fn any_from_ssz_bytes(bytes: &[u8]) -> Result<Self, ssz::DecodeError> {
BeaconBlockElectra::from_ssz_bytes(bytes) BeaconBlockEIP7732::from_ssz_bytes(bytes)
.map(BeaconBlock::Electra) .map(BeaconBlock::EIP7732)
.or_else(|_| BeaconBlockElectra::from_ssz_bytes(bytes).map(BeaconBlock::Electra))
.or_else(|_| BeaconBlockDeneb::from_ssz_bytes(bytes).map(BeaconBlock::Deneb)) .or_else(|_| BeaconBlockDeneb::from_ssz_bytes(bytes).map(BeaconBlock::Deneb))
.or_else(|_| BeaconBlockCapella::from_ssz_bytes(bytes).map(BeaconBlock::Capella)) .or_else(|_| BeaconBlockCapella::from_ssz_bytes(bytes).map(BeaconBlock::Capella))
.or_else(|_| BeaconBlockBellatrix::from_ssz_bytes(bytes).map(BeaconBlock::Bellatrix)) .or_else(|_| BeaconBlockBellatrix::from_ssz_bytes(bytes).map(BeaconBlock::Bellatrix))
@@ -226,6 +229,7 @@ impl<'a, E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockRef<'a, E, Payl
BeaconBlockRef::Capella { .. } => ForkName::Capella, BeaconBlockRef::Capella { .. } => ForkName::Capella,
BeaconBlockRef::Deneb { .. } => ForkName::Deneb, BeaconBlockRef::Deneb { .. } => ForkName::Deneb,
BeaconBlockRef::Electra { .. } => ForkName::Electra, BeaconBlockRef::Electra { .. } => ForkName::Electra,
BeaconBlockRef::EIP7732 { .. } => ForkName::EIP7732,
} }
} }
@@ -673,6 +677,77 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockElectra<E, Payload>
} }
} }
impl<E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockEIP7732<E, Payload> {
/// Return a Electra block where the block has maximum size.
pub fn full(spec: &ChainSpec) -> Self {
let base_block: BeaconBlockBase<_, Payload> = BeaconBlockBase::full(spec);
let indexed_attestation: IndexedAttestationElectra<E> = IndexedAttestationElectra {
attesting_indices: VariableList::new(vec![0_u64; E::MaxValidatorsPerSlot::to_usize()])
.unwrap(),
data: AttestationData::default(),
signature: AggregateSignature::empty(),
};
let attester_slashings = vec![
AttesterSlashingElectra {
attestation_1: indexed_attestation.clone(),
attestation_2: indexed_attestation,
};
E::max_attester_slashings_electra()
]
.into();
let attestation = AttestationElectra {
aggregation_bits: BitList::with_capacity(E::MaxValidatorsPerSlot::to_usize()).unwrap(),
data: AttestationData::default(),
signature: AggregateSignature::empty(),
committee_bits: BitVector::new(),
};
let mut attestations_electra = vec![];
for _ in 0..E::MaxAttestationsElectra::to_usize() {
attestations_electra.push(attestation.clone());
}
let bls_to_execution_changes = vec![
SignedBlsToExecutionChange {
message: BlsToExecutionChange {
validator_index: 0,
from_bls_pubkey: PublicKeyBytes::empty(),
to_execution_address: Address::zero(),
},
signature: Signature::empty()
};
E::max_bls_to_execution_changes()
]
.into();
let sync_aggregate = SyncAggregate {
sync_committee_signature: AggregateSignature::empty(),
sync_committee_bits: BitVector::default(),
};
BeaconBlockEIP7732 {
slot: spec.genesis_slot,
proposer_index: 0,
parent_root: Hash256::zero(),
state_root: Hash256::zero(),
body: BeaconBlockBodyEIP7732 {
proposer_slashings: base_block.body.proposer_slashings,
attester_slashings,
attestations: attestations_electra.into(),
deposits: base_block.body.deposits,
voluntary_exits: base_block.body.voluntary_exits,
bls_to_execution_changes,
sync_aggregate,
randao_reveal: Signature::empty(),
eth1_data: Eth1Data {
deposit_root: Hash256::zero(),
block_hash: Hash256::zero(),
deposit_count: 0,
},
graffiti: Graffiti::default(),
_phantom: PhantomData,
},
}
}
}
impl<E: EthSpec, Payload: AbstractExecPayload<E>> EmptyBlock for BeaconBlockElectra<E, Payload> { impl<E: EthSpec, Payload: AbstractExecPayload<E>> EmptyBlock for BeaconBlockElectra<E, Payload> {
/// Returns an empty Electra block to be used during genesis. /// Returns an empty Electra block to be used during genesis.
fn empty(spec: &ChainSpec) -> Self { fn empty(spec: &ChainSpec) -> Self {
@@ -704,6 +779,35 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> EmptyBlock for BeaconBlockElec
} }
} }
impl<E: EthSpec, Payload: AbstractExecPayload<E>> EmptyBlock for BeaconBlockEIP7732<E, Payload> {
/// Returns an empty Electra block to be used during genesis.
fn empty(spec: &ChainSpec) -> Self {
BeaconBlockEIP7732 {
slot: spec.genesis_slot,
proposer_index: 0,
parent_root: Hash256::zero(),
state_root: Hash256::zero(),
body: BeaconBlockBodyEIP7732 {
randao_reveal: Signature::empty(),
eth1_data: Eth1Data {
deposit_root: Hash256::zero(),
block_hash: Hash256::zero(),
deposit_count: 0,
},
graffiti: Graffiti::default(),
proposer_slashings: VariableList::empty(),
attester_slashings: VariableList::empty(),
attestations: VariableList::empty(),
deposits: VariableList::empty(),
voluntary_exits: VariableList::empty(),
sync_aggregate: SyncAggregate::empty(),
bls_to_execution_changes: VariableList::empty(),
_phantom: PhantomData,
},
}
}
}
// We can convert pre-Bellatrix blocks without payloads into blocks "with" payloads. // We can convert pre-Bellatrix blocks without payloads into blocks "with" payloads.
impl<E: EthSpec> From<BeaconBlockBase<E, BlindedPayload<E>>> impl<E: EthSpec> From<BeaconBlockBase<E, BlindedPayload<E>>>
for BeaconBlockBase<E, FullPayload<E>> for BeaconBlockBase<E, FullPayload<E>>
@@ -749,6 +853,28 @@ impl<E: EthSpec> From<BeaconBlockAltair<E, BlindedPayload<E>>>
} }
} }
impl<E: EthSpec> From<BeaconBlockEIP7732<E, BlindedPayload<E>>>
for BeaconBlockEIP7732<E, FullPayload<E>>
{
fn from(block: BeaconBlockEIP7732<E, BlindedPayload<E>>) -> Self {
let BeaconBlockEIP7732 {
slot,
proposer_index,
parent_root,
state_root,
body,
} = block;
BeaconBlockEIP7732 {
slot,
proposer_index,
parent_root,
state_root,
body: body.into(),
}
}
}
// We can convert blocks with payloads to blocks without payloads, and an optional payload. // We can convert blocks with payloads to blocks without payloads, and an optional payload.
macro_rules! impl_from { macro_rules! impl_from {
($ty_name:ident, <$($from_params:ty),*>, <$($to_params:ty),*>, $body_expr:expr) => { ($ty_name:ident, <$($from_params:ty),*>, <$($to_params:ty),*>, $body_expr:expr) => {
@@ -785,6 +911,7 @@ impl_from!(BeaconBlockBellatrix, <E, FullPayload<E>>, <E, BlindedPayload<E>>, |b
impl_from!(BeaconBlockCapella, <E, FullPayload<E>>, <E, BlindedPayload<E>>, |body: BeaconBlockBodyCapella<_, _>| body.into()); impl_from!(BeaconBlockCapella, <E, FullPayload<E>>, <E, BlindedPayload<E>>, |body: BeaconBlockBodyCapella<_, _>| body.into());
impl_from!(BeaconBlockDeneb, <E, FullPayload<E>>, <E, BlindedPayload<E>>, |body: BeaconBlockBodyDeneb<_, _>| body.into()); impl_from!(BeaconBlockDeneb, <E, FullPayload<E>>, <E, BlindedPayload<E>>, |body: BeaconBlockBodyDeneb<_, _>| body.into());
impl_from!(BeaconBlockElectra, <E, FullPayload<E>>, <E, BlindedPayload<E>>, |body: BeaconBlockBodyElectra<_, _>| body.into()); impl_from!(BeaconBlockElectra, <E, FullPayload<E>>, <E, BlindedPayload<E>>, |body: BeaconBlockBodyElectra<_, _>| body.into());
impl_from!(BeaconBlockEIP7732, <E, FullPayload<E>>, <E, BlindedPayload<E>>, |body: BeaconBlockBodyEIP7732<_, _>| body.into());
// We can clone blocks with payloads to blocks without payloads, without cloning the payload. // We can clone blocks with payloads to blocks without payloads, without cloning the payload.
macro_rules! impl_clone_as_blinded { macro_rules! impl_clone_as_blinded {
@@ -818,6 +945,7 @@ impl_clone_as_blinded!(BeaconBlockBellatrix, <E, FullPayload<E>>, <E, BlindedPay
impl_clone_as_blinded!(BeaconBlockCapella, <E, FullPayload<E>>, <E, BlindedPayload<E>>); impl_clone_as_blinded!(BeaconBlockCapella, <E, FullPayload<E>>, <E, BlindedPayload<E>>);
impl_clone_as_blinded!(BeaconBlockDeneb, <E, FullPayload<E>>, <E, BlindedPayload<E>>); impl_clone_as_blinded!(BeaconBlockDeneb, <E, FullPayload<E>>, <E, BlindedPayload<E>>);
impl_clone_as_blinded!(BeaconBlockElectra, <E, FullPayload<E>>, <E, BlindedPayload<E>>); impl_clone_as_blinded!(BeaconBlockElectra, <E, FullPayload<E>>, <E, BlindedPayload<E>>);
impl_clone_as_blinded!(BeaconBlockEIP7732, <E, FullPayload<E>>, <E, BlindedPayload<E>>);
// A reference to a full beacon block can be cloned into a blinded beacon block, without cloning the // A reference to a full beacon block can be cloned into a blinded beacon block, without cloning the
// execution payload. // execution payload.

View File

@@ -30,7 +30,7 @@ pub const BLOB_KZG_COMMITMENTS_INDEX: usize = 11;
/// ///
/// This *superstruct* abstracts over the hard-fork. /// This *superstruct* abstracts over the hard-fork.
#[superstruct( #[superstruct(
variants(Base, Altair, Bellatrix, Capella, Deneb, Electra), variants(Base, Altair, Bellatrix, Capella, Deneb, Electra, EIP7732),
variant_attributes( variant_attributes(
derive( derive(
Debug, Debug,
@@ -58,6 +58,7 @@ pub const BLOB_KZG_COMMITMENTS_INDEX: usize = 11;
Capella(metastruct(mappings(beacon_block_body_capella_fields(groups(fields))))), Capella(metastruct(mappings(beacon_block_body_capella_fields(groups(fields))))),
Deneb(metastruct(mappings(beacon_block_body_deneb_fields(groups(fields))))), Deneb(metastruct(mappings(beacon_block_body_deneb_fields(groups(fields))))),
Electra(metastruct(mappings(beacon_block_body_electra_fields(groups(fields))))), Electra(metastruct(mappings(beacon_block_body_electra_fields(groups(fields))))),
EIP7732(metastruct(mappings(beacon_block_body_eip7732_fields(groups(fields))))),
), ),
cast_error(ty = "Error", expr = "Error::IncorrectStateVariant"), cast_error(ty = "Error", expr = "Error::IncorrectStateVariant"),
partial_getter_error(ty = "Error", expr = "Error::IncorrectStateVariant") partial_getter_error(ty = "Error", expr = "Error::IncorrectStateVariant")
@@ -77,7 +78,10 @@ pub struct BeaconBlockBody<E: EthSpec, Payload: AbstractExecPayload<E> = FullPay
partial_getter(rename = "attester_slashings_base") partial_getter(rename = "attester_slashings_base")
)] )]
pub attester_slashings: VariableList<AttesterSlashingBase<E>, E::MaxAttesterSlashings>, pub attester_slashings: VariableList<AttesterSlashingBase<E>, E::MaxAttesterSlashings>,
#[superstruct(only(Electra), partial_getter(rename = "attester_slashings_electra"))] #[superstruct(
only(Electra, EIP7732),
partial_getter(rename = "attester_slashings_electra")
)]
pub attester_slashings: pub attester_slashings:
VariableList<AttesterSlashingElectra<E>, E::MaxAttesterSlashingsElectra>, VariableList<AttesterSlashingElectra<E>, E::MaxAttesterSlashingsElectra>,
#[superstruct( #[superstruct(
@@ -85,11 +89,14 @@ pub struct BeaconBlockBody<E: EthSpec, Payload: AbstractExecPayload<E> = FullPay
partial_getter(rename = "attestations_base") partial_getter(rename = "attestations_base")
)] )]
pub attestations: VariableList<AttestationBase<E>, E::MaxAttestations>, pub attestations: VariableList<AttestationBase<E>, E::MaxAttestations>,
#[superstruct(only(Electra), partial_getter(rename = "attestations_electra"))] #[superstruct(
only(Electra, EIP7732),
partial_getter(rename = "attestations_electra")
)]
pub attestations: VariableList<AttestationElectra<E>, E::MaxAttestationsElectra>, pub attestations: VariableList<AttestationElectra<E>, E::MaxAttestationsElectra>,
pub deposits: VariableList<Deposit, E::MaxDeposits>, pub deposits: VariableList<Deposit, E::MaxDeposits>,
pub voluntary_exits: VariableList<SignedVoluntaryExit, E::MaxVoluntaryExits>, pub voluntary_exits: VariableList<SignedVoluntaryExit, E::MaxVoluntaryExits>,
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra))] #[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra, EIP7732))]
pub sync_aggregate: SyncAggregate<E>, pub sync_aggregate: SyncAggregate<E>,
// We flatten the execution payload so that serde can use the name of the inner type, // 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 // either `execution_payload` for full payloads, or `execution_payload_header` for blinded
@@ -109,14 +116,14 @@ pub struct BeaconBlockBody<E: EthSpec, Payload: AbstractExecPayload<E> = FullPay
#[superstruct(only(Electra), partial_getter(rename = "execution_payload_electra"))] #[superstruct(only(Electra), partial_getter(rename = "execution_payload_electra"))]
#[serde(flatten)] #[serde(flatten)]
pub execution_payload: Payload::Electra, pub execution_payload: Payload::Electra,
#[superstruct(only(Capella, Deneb, Electra))] #[superstruct(only(Capella, Deneb, Electra, EIP7732))]
pub bls_to_execution_changes: pub bls_to_execution_changes:
VariableList<SignedBlsToExecutionChange, E::MaxBlsToExecutionChanges>, VariableList<SignedBlsToExecutionChange, E::MaxBlsToExecutionChanges>,
#[superstruct(only(Deneb, Electra))] #[superstruct(only(Deneb, Electra))]
pub blob_kzg_commitments: KzgCommitments<E>, pub blob_kzg_commitments: KzgCommitments<E>,
#[superstruct(only(Electra))] #[superstruct(only(Electra))]
pub execution_requests: ExecutionRequests<E>, pub execution_requests: ExecutionRequests<E>,
#[superstruct(only(Base, Altair))] #[superstruct(only(Base, Altair, EIP7732))]
#[metastruct(exclude_from(fields))] #[metastruct(exclude_from(fields))]
#[ssz(skip_serializing, skip_deserializing)] #[ssz(skip_serializing, skip_deserializing)]
#[tree_hash(skip_hashing)] #[tree_hash(skip_hashing)]
@@ -144,6 +151,8 @@ impl<'a, E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBodyRef<'a, E,
Self::Capella(body) => Ok(Payload::Ref::from(&body.execution_payload)), Self::Capella(body) => Ok(Payload::Ref::from(&body.execution_payload)),
Self::Deneb(body) => Ok(Payload::Ref::from(&body.execution_payload)), Self::Deneb(body) => Ok(Payload::Ref::from(&body.execution_payload)),
Self::Electra(body) => Ok(Payload::Ref::from(&body.execution_payload)), Self::Electra(body) => Ok(Payload::Ref::from(&body.execution_payload)),
// TOOD: idk if this is right there's no more execution payload
Self::EIP7732(_) => Err(Error::IncorrectStateVariant),
} }
} }
@@ -174,6 +183,10 @@ impl<'a, E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBodyRef<'a, E,
beacon_block_body_electra_fields!(body, |_, field| leaves beacon_block_body_electra_fields!(body, |_, field| leaves
.push(field.tree_hash_root())); .push(field.tree_hash_root()));
} }
Self::EIP7732(body) => {
beacon_block_body_eip7732_fields!(body, |_, field| leaves
.push(field.tree_hash_root()));
}
} }
leaves leaves
} }
@@ -202,7 +215,7 @@ impl<'a, E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBodyRef<'a, E,
Self::Base(_) | Self::Altair(_) | Self::Bellatrix(_) | Self::Capella(_) => { Self::Base(_) | Self::Altair(_) | Self::Bellatrix(_) | Self::Capella(_) => {
Err(Error::IncorrectStateVariant) Err(Error::IncorrectStateVariant)
} }
Self::Deneb(_) | Self::Electra(_) => { Self::Deneb(_) | Self::Electra(_) | Self::EIP7732(_) => {
// We compute the branches by generating 2 merkle trees: // We compute the branches by generating 2 merkle trees:
// 1. Merkle tree for the `blob_kzg_commitments` List object // 1. Merkle tree for the `blob_kzg_commitments` List object
// 2. Merkle tree for the `BeaconBlockBody` container // 2. Merkle tree for the `BeaconBlockBody` container
@@ -294,6 +307,7 @@ impl<'a, E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBodyRef<'a, E,
Self::Capella(body) => body.attestations.len(), Self::Capella(body) => body.attestations.len(),
Self::Deneb(body) => body.attestations.len(), Self::Deneb(body) => body.attestations.len(),
Self::Electra(body) => body.attestations.len(), Self::Electra(body) => body.attestations.len(),
Self::EIP7732(body) => body.attestations.len(),
} }
} }
@@ -305,6 +319,7 @@ impl<'a, E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBodyRef<'a, E,
Self::Capella(body) => body.attester_slashings.len(), Self::Capella(body) => body.attester_slashings.len(),
Self::Deneb(body) => body.attester_slashings.len(), Self::Deneb(body) => body.attester_slashings.len(),
Self::Electra(body) => body.attester_slashings.len(), Self::Electra(body) => body.attester_slashings.len(),
Self::EIP7732(body) => body.attester_slashings.len(),
} }
} }
@@ -316,6 +331,7 @@ impl<'a, E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBodyRef<'a, E,
Self::Capella(body) => Box::new(body.attestations.iter().map(AttestationRef::Base)), Self::Capella(body) => Box::new(body.attestations.iter().map(AttestationRef::Base)),
Self::Deneb(body) => Box::new(body.attestations.iter().map(AttestationRef::Base)), Self::Deneb(body) => Box::new(body.attestations.iter().map(AttestationRef::Base)),
Self::Electra(body) => Box::new(body.attestations.iter().map(AttestationRef::Electra)), Self::Electra(body) => Box::new(body.attestations.iter().map(AttestationRef::Electra)),
Self::EIP7732(body) => Box::new(body.attestations.iter().map(AttestationRef::Electra)),
} }
} }
@@ -351,6 +367,11 @@ impl<'a, E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBodyRef<'a, E,
.iter() .iter()
.map(AttesterSlashingRef::Electra), .map(AttesterSlashingRef::Electra),
), ),
Self::EIP7732(body) => Box::new(
body.attester_slashings
.iter()
.map(AttesterSlashingRef::Electra),
),
} }
} }
} }
@@ -376,6 +397,9 @@ impl<'a, E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBodyRefMut<'a,
Self::Electra(body) => { Self::Electra(body) => {
Box::new(body.attestations.iter_mut().map(AttestationRefMut::Electra)) Box::new(body.attestations.iter_mut().map(AttestationRefMut::Electra))
} }
Self::EIP7732(body) => {
Box::new(body.attestations.iter_mut().map(AttestationRefMut::Electra))
}
} }
} }
} }
@@ -390,6 +414,7 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBodyRef<'_, E, Payl
BeaconBlockBodyRef::Capella { .. } => ForkName::Capella, BeaconBlockBodyRef::Capella { .. } => ForkName::Capella,
BeaconBlockBodyRef::Deneb { .. } => ForkName::Deneb, BeaconBlockBodyRef::Deneb { .. } => ForkName::Deneb,
BeaconBlockBodyRef::Electra { .. } => ForkName::Electra, BeaconBlockBodyRef::Electra { .. } => ForkName::Electra,
BeaconBlockBodyRef::EIP7732 { .. } => ForkName::EIP7732,
} }
} }
} }
@@ -704,6 +729,81 @@ impl<E: EthSpec> From<BeaconBlockBodyElectra<E, FullPayload<E>>>
} }
} }
// We can convert post EIP-7732 bodies without payloads into block bodies "with" payloads.
impl<E: EthSpec> From<BeaconBlockBodyEIP7732<E, BlindedPayload<E>>>
for BeaconBlockBodyEIP7732<E, FullPayload<E>>
{
fn from(body: BeaconBlockBodyEIP7732<E, BlindedPayload<E>>) -> Self {
let BeaconBlockBodyEIP7732 {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
bls_to_execution_changes,
_phantom,
} = body;
BeaconBlockBodyEIP7732 {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
bls_to_execution_changes,
_phantom: PhantomData,
}
}
}
impl<E: EthSpec> From<BeaconBlockBodyEIP7732<E, FullPayload<E>>>
for (
BeaconBlockBodyEIP7732<E, BlindedPayload<E>>,
Option<ExecutionPayload<E>>,
)
{
fn from(body: BeaconBlockBodyEIP7732<E, FullPayload<E>>) -> Self {
let BeaconBlockBodyEIP7732 {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
bls_to_execution_changes,
_phantom,
} = body;
(
BeaconBlockBodyEIP7732 {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
bls_to_execution_changes,
_phantom: PhantomData,
},
None,
)
}
}
// We can clone a full block into a blinded block, without cloning the payload. // We can clone a full block into a blinded block, without cloning the payload.
impl<E: EthSpec> BeaconBlockBodyBase<E, FullPayload<E>> { impl<E: EthSpec> BeaconBlockBodyBase<E, FullPayload<E>> {
pub fn clone_as_blinded(&self) -> BeaconBlockBodyBase<E, BlindedPayload<E>> { pub fn clone_as_blinded(&self) -> BeaconBlockBodyBase<E, BlindedPayload<E>> {
@@ -859,6 +959,13 @@ impl<E: EthSpec> BeaconBlockBodyElectra<E, FullPayload<E>> {
} }
} }
impl<E: EthSpec> BeaconBlockBodyEIP7732<E, FullPayload<E>> {
pub fn clone_as_blinded(&self) -> BeaconBlockBodyEIP7732<E, BlindedPayload<E>> {
let (block_body, _payload) = self.clone().into();
block_body
}
}
impl<E: EthSpec> From<BeaconBlockBody<E, FullPayload<E>>> impl<E: EthSpec> From<BeaconBlockBody<E, FullPayload<E>>>
for ( for (
BeaconBlockBody<E, BlindedPayload<E>>, BeaconBlockBody<E, BlindedPayload<E>>,

View File

@@ -222,7 +222,7 @@ impl From<BeaconStateHash> for Hash256 {
/// ///
/// https://github.com/sigp/milhouse/issues/43 /// https://github.com/sigp/milhouse/issues/43
#[superstruct( #[superstruct(
variants(Base, Altair, Bellatrix, Capella, Deneb, Electra), variants(Base, Altair, Bellatrix, Capella, Deneb, Electra, EIP7732),
variant_attributes( variant_attributes(
derive( derive(
Derivative, Derivative,
@@ -325,6 +325,20 @@ impl From<BeaconStateHash> for Hash256 {
groups(tree_lists) groups(tree_lists)
)), )),
num_fields(all()), num_fields(all()),
)),
EIP7732(metastruct(
mappings(
map_beacon_state_eip7732_fields(),
map_beacon_state_eip7732_tree_list_fields(mutable, fallible, groups(tree_lists)),
map_beacon_state_eip7732_tree_list_fields_immutable(groups(tree_lists)),
),
bimappings(bimap_beacon_state_eip7732_tree_list_fields(
other_type = "BeaconStateEIP7732",
self_mutable,
fallible,
groups(tree_lists)
)),
num_fields(all()),
)) ))
), ),
cast_error(ty = "Error", expr = "Error::IncorrectStateVariant"), cast_error(ty = "Error", expr = "Error::IncorrectStateVariant"),
@@ -407,11 +421,11 @@ where
// Participation (Altair and later) // Participation (Altair and later)
#[compare_fields(as_iter)] #[compare_fields(as_iter)]
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra))] #[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra, EIP7732))]
#[test_random(default)] #[test_random(default)]
#[compare_fields(as_iter)] #[compare_fields(as_iter)]
pub previous_epoch_participation: List<ParticipationFlags, E::ValidatorRegistryLimit>, pub previous_epoch_participation: List<ParticipationFlags, E::ValidatorRegistryLimit>,
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra))] #[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra, EIP7732))]
#[test_random(default)] #[test_random(default)]
pub current_epoch_participation: List<ParticipationFlags, E::ValidatorRegistryLimit>, pub current_epoch_participation: List<ParticipationFlags, E::ValidatorRegistryLimit>,
@@ -431,15 +445,15 @@ where
// Inactivity // Inactivity
#[serde(with = "ssz_types::serde_utils::quoted_u64_var_list")] #[serde(with = "ssz_types::serde_utils::quoted_u64_var_list")]
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra))] #[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra, EIP7732))]
#[test_random(default)] #[test_random(default)]
pub inactivity_scores: List<u64, E::ValidatorRegistryLimit>, pub inactivity_scores: List<u64, E::ValidatorRegistryLimit>,
// Light-client sync committees // Light-client sync committees
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra))] #[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra, EIP7732))]
#[metastruct(exclude_from(tree_lists))] #[metastruct(exclude_from(tree_lists))]
pub current_sync_committee: Arc<SyncCommittee<E>>, pub current_sync_committee: Arc<SyncCommittee<E>>,
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra))] #[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra, EIP7732))]
#[metastruct(exclude_from(tree_lists))] #[metastruct(exclude_from(tree_lists))]
pub next_sync_committee: Arc<SyncCommittee<E>>, pub next_sync_committee: Arc<SyncCommittee<E>>,
@@ -468,56 +482,59 @@ where
)] )]
#[metastruct(exclude_from(tree_lists))] #[metastruct(exclude_from(tree_lists))]
pub latest_execution_payload_header: ExecutionPayloadHeaderElectra<E>, pub latest_execution_payload_header: ExecutionPayloadHeaderElectra<E>,
#[superstruct(only(EIP7732), partial_getter(rename = "latest_execution_bid_eip7732"))]
#[metastruct(exclude_from(tree_lists))]
pub latest_execution_bid: ExecutionBid,
// Capella // Capella
#[superstruct(only(Capella, Deneb, Electra), partial_getter(copy))] #[superstruct(only(Capella, Deneb, Electra, EIP7732), partial_getter(copy))]
#[serde(with = "serde_utils::quoted_u64")] #[serde(with = "serde_utils::quoted_u64")]
#[metastruct(exclude_from(tree_lists))] #[metastruct(exclude_from(tree_lists))]
pub next_withdrawal_index: u64, pub next_withdrawal_index: u64,
#[superstruct(only(Capella, Deneb, Electra), partial_getter(copy))] #[superstruct(only(Capella, Deneb, Electra, EIP7732), partial_getter(copy))]
#[serde(with = "serde_utils::quoted_u64")] #[serde(with = "serde_utils::quoted_u64")]
#[metastruct(exclude_from(tree_lists))] #[metastruct(exclude_from(tree_lists))]
pub next_withdrawal_validator_index: u64, pub next_withdrawal_validator_index: u64,
// Deep history valid from Capella onwards. // Deep history valid from Capella onwards.
#[superstruct(only(Capella, Deneb, Electra))] #[superstruct(only(Capella, Deneb, Electra, EIP7732))]
#[test_random(default)] #[test_random(default)]
pub historical_summaries: List<HistoricalSummary, E::HistoricalRootsLimit>, pub historical_summaries: List<HistoricalSummary, E::HistoricalRootsLimit>,
// Electra // Electra
#[superstruct(only(Electra), partial_getter(copy))] #[superstruct(only(Electra, EIP7732), partial_getter(copy))]
#[metastruct(exclude_from(tree_lists))] #[metastruct(exclude_from(tree_lists))]
#[serde(with = "serde_utils::quoted_u64")] #[serde(with = "serde_utils::quoted_u64")]
pub deposit_requests_start_index: u64, pub deposit_requests_start_index: u64,
#[superstruct(only(Electra), partial_getter(copy))] #[superstruct(only(Electra, EIP7732), partial_getter(copy))]
#[metastruct(exclude_from(tree_lists))] #[metastruct(exclude_from(tree_lists))]
#[serde(with = "serde_utils::quoted_u64")] #[serde(with = "serde_utils::quoted_u64")]
pub deposit_balance_to_consume: u64, pub deposit_balance_to_consume: u64,
#[superstruct(only(Electra), partial_getter(copy))] #[superstruct(only(Electra, EIP7732), partial_getter(copy))]
#[metastruct(exclude_from(tree_lists))] #[metastruct(exclude_from(tree_lists))]
#[serde(with = "serde_utils::quoted_u64")] #[serde(with = "serde_utils::quoted_u64")]
pub exit_balance_to_consume: u64, pub exit_balance_to_consume: u64,
#[superstruct(only(Electra), partial_getter(copy))] #[superstruct(only(Electra, EIP7732), partial_getter(copy))]
#[metastruct(exclude_from(tree_lists))] #[metastruct(exclude_from(tree_lists))]
pub earliest_exit_epoch: Epoch, pub earliest_exit_epoch: Epoch,
#[superstruct(only(Electra), partial_getter(copy))] #[superstruct(only(Electra, EIP7732), partial_getter(copy))]
#[metastruct(exclude_from(tree_lists))] #[metastruct(exclude_from(tree_lists))]
#[serde(with = "serde_utils::quoted_u64")] #[serde(with = "serde_utils::quoted_u64")]
pub consolidation_balance_to_consume: u64, pub consolidation_balance_to_consume: u64,
#[superstruct(only(Electra), partial_getter(copy))] #[superstruct(only(Electra, EIP7732), partial_getter(copy))]
#[metastruct(exclude_from(tree_lists))] #[metastruct(exclude_from(tree_lists))]
pub earliest_consolidation_epoch: Epoch, pub earliest_consolidation_epoch: Epoch,
#[compare_fields(as_iter)] #[compare_fields(as_iter)]
#[test_random(default)] #[test_random(default)]
#[superstruct(only(Electra))] #[superstruct(only(Electra, EIP7732))]
pub pending_balance_deposits: List<PendingBalanceDeposit, E::PendingBalanceDepositsLimit>, pub pending_balance_deposits: List<PendingBalanceDeposit, E::PendingBalanceDepositsLimit>,
#[compare_fields(as_iter)] #[compare_fields(as_iter)]
#[test_random(default)] #[test_random(default)]
#[superstruct(only(Electra))] #[superstruct(only(Electra, EIP7732))]
pub pending_partial_withdrawals: pub pending_partial_withdrawals:
List<PendingPartialWithdrawal, E::PendingPartialWithdrawalsLimit>, List<PendingPartialWithdrawal, E::PendingPartialWithdrawalsLimit>,
#[compare_fields(as_iter)] #[compare_fields(as_iter)]
#[test_random(default)] #[test_random(default)]
#[superstruct(only(Electra))] #[superstruct(only(Electra, EIP7732))]
pub pending_consolidations: List<PendingConsolidation, E::PendingConsolidationsLimit>, pub pending_consolidations: List<PendingConsolidation, E::PendingConsolidationsLimit>,
// Caching (not in the spec) // Caching (not in the spec)
@@ -658,6 +675,7 @@ impl<E: EthSpec> BeaconState<E> {
BeaconState::Capella { .. } => ForkName::Capella, BeaconState::Capella { .. } => ForkName::Capella,
BeaconState::Deneb { .. } => ForkName::Deneb, BeaconState::Deneb { .. } => ForkName::Deneb,
BeaconState::Electra { .. } => ForkName::Electra, BeaconState::Electra { .. } => ForkName::Electra,
BeaconState::EIP7732 { .. } => ForkName::EIP7732,
} }
} }
@@ -947,6 +965,8 @@ impl<E: EthSpec> BeaconState<E> {
BeaconState::Electra(state) => Ok(ExecutionPayloadHeaderRef::Electra( BeaconState::Electra(state) => Ok(ExecutionPayloadHeaderRef::Electra(
&state.latest_execution_payload_header, &state.latest_execution_payload_header,
)), )),
// FIXME(EIP-7732): this is only to make the code compile, needs to be written later
BeaconState::EIP7732(_) => Err(Error::IncorrectStateVariant),
} }
} }
@@ -967,6 +987,8 @@ impl<E: EthSpec> BeaconState<E> {
BeaconState::Electra(state) => Ok(ExecutionPayloadHeaderRefMut::Electra( BeaconState::Electra(state) => Ok(ExecutionPayloadHeaderRefMut::Electra(
&mut state.latest_execution_payload_header, &mut state.latest_execution_payload_header,
)), )),
// FIXME(EIP-7732): this is only to make the code compile, needs to be written later
BeaconState::EIP7732(_) => Err(Error::IncorrectStateVariant),
} }
} }
@@ -1480,6 +1502,16 @@ impl<E: EthSpec> BeaconState<E> {
&mut state.exit_cache, &mut state.exit_cache,
&mut state.epoch_cache, &mut state.epoch_cache,
)), )),
BeaconState::EIP7732(state) => Ok((
&mut state.validators,
&mut state.balances,
&state.previous_epoch_participation,
&state.current_epoch_participation,
&mut state.inactivity_scores,
&mut state.progressive_balances_cache,
&mut state.exit_cache,
&mut state.epoch_cache,
)),
} }
} }
@@ -1644,10 +1676,13 @@ impl<E: EthSpec> BeaconState<E> {
| BeaconState::Altair(_) | BeaconState::Altair(_)
| BeaconState::Bellatrix(_) | BeaconState::Bellatrix(_)
| BeaconState::Capella(_) => self.get_validator_churn_limit(spec)?, | BeaconState::Capella(_) => self.get_validator_churn_limit(spec)?,
BeaconState::Deneb(_) | BeaconState::Electra(_) => std::cmp::min( // FIXME(EIP-7732): check this
spec.max_per_epoch_activation_churn_limit, BeaconState::Deneb(_) | BeaconState::Electra(_) | BeaconState::EIP7732(_) => {
self.get_validator_churn_limit(spec)?, std::cmp::min(
), spec.max_per_epoch_activation_churn_limit,
self.get_validator_churn_limit(spec)?,
)
}
}) })
} }
@@ -1765,6 +1800,7 @@ impl<E: EthSpec> BeaconState<E> {
BeaconState::Capella(state) => Ok(&mut state.current_epoch_participation), BeaconState::Capella(state) => Ok(&mut state.current_epoch_participation),
BeaconState::Deneb(state) => Ok(&mut state.current_epoch_participation), BeaconState::Deneb(state) => Ok(&mut state.current_epoch_participation),
BeaconState::Electra(state) => Ok(&mut state.current_epoch_participation), BeaconState::Electra(state) => Ok(&mut state.current_epoch_participation),
BeaconState::EIP7732(state) => Ok(&mut state.current_epoch_participation),
} }
} else if epoch == previous_epoch { } else if epoch == previous_epoch {
match self { match self {
@@ -1774,6 +1810,7 @@ impl<E: EthSpec> BeaconState<E> {
BeaconState::Capella(state) => Ok(&mut state.previous_epoch_participation), BeaconState::Capella(state) => Ok(&mut state.previous_epoch_participation),
BeaconState::Deneb(state) => Ok(&mut state.previous_epoch_participation), BeaconState::Deneb(state) => Ok(&mut state.previous_epoch_participation),
BeaconState::Electra(state) => Ok(&mut state.previous_epoch_participation), BeaconState::Electra(state) => Ok(&mut state.previous_epoch_participation),
BeaconState::EIP7732(state) => Ok(&mut state.previous_epoch_participation),
} }
} else { } else {
Err(BeaconStateError::EpochOutOfBounds) Err(BeaconStateError::EpochOutOfBounds)
@@ -2040,6 +2077,14 @@ impl<E: EthSpec> BeaconState<E> {
} }
); );
} }
Self::EIP7732(self_inner) => {
map_beacon_state_eip7732_tree_list_fields_immutable!(
self_inner,
|_, self_field| {
any_pending_mutations |= self_field.has_pending_updates();
}
);
}
}; };
any_pending_mutations any_pending_mutations
} }
@@ -2381,6 +2426,14 @@ impl<E: EthSpec> BeaconState<E> {
); );
} }
(Self::Electra(_), _) => (), (Self::Electra(_), _) => (),
(Self::EIP7732(self_inner), Self::EIP7732(base_inner)) => {
bimap_beacon_state_eip7732_tree_list_fields!(
self_inner,
base_inner,
|_, self_field, base_field| { self_field.rebase_on(base_field) }
);
}
(Self::EIP7732(_), _) => (),
} }
// Use sync committees from `base` if they are equal. // Use sync committees from `base` if they are equal.
@@ -2453,6 +2506,7 @@ impl<E: EthSpec> BeaconState<E> {
ForkName::Capella => BeaconStateCapella::<E>::NUM_FIELDS.next_power_of_two(), ForkName::Capella => BeaconStateCapella::<E>::NUM_FIELDS.next_power_of_two(),
ForkName::Deneb => BeaconStateDeneb::<E>::NUM_FIELDS.next_power_of_two(), ForkName::Deneb => BeaconStateDeneb::<E>::NUM_FIELDS.next_power_of_two(),
ForkName::Electra => BeaconStateElectra::<E>::NUM_FIELDS.next_power_of_two(), ForkName::Electra => BeaconStateElectra::<E>::NUM_FIELDS.next_power_of_two(),
ForkName::EIP7732 => BeaconStateEIP7732::<E>::NUM_FIELDS.next_power_of_two(),
} }
} }
@@ -2501,6 +2555,9 @@ impl<E: EthSpec> BeaconState<E> {
Self::Electra(inner) => { Self::Electra(inner) => {
map_beacon_state_electra_tree_list_fields!(inner, |_, x| { x.apply_updates() }) map_beacon_state_electra_tree_list_fields!(inner, |_, x| { x.apply_updates() })
} }
Self::EIP7732(inner) => {
map_beacon_state_eip7732_tree_list_fields!(inner, |_, x| { x.apply_updates() })
}
} }
Ok(()) Ok(())
} }
@@ -2596,6 +2653,11 @@ impl<E: EthSpec> BeaconState<E> {
leaves.push(field.tree_hash_root()); leaves.push(field.tree_hash_root());
}); });
} }
BeaconState::EIP7732(state) => {
map_beacon_state_eip7732_fields!(state, |_, field| {
leaves.push(field.tree_hash_root());
});
}
}; };
leaves leaves
@@ -2653,6 +2715,7 @@ impl<E: EthSpec> CompareFields for BeaconState<E> {
(BeaconState::Capella(x), BeaconState::Capella(y)) => x.compare_fields(y), (BeaconState::Capella(x), BeaconState::Capella(y)) => x.compare_fields(y),
(BeaconState::Deneb(x), BeaconState::Deneb(y)) => x.compare_fields(y), (BeaconState::Deneb(x), BeaconState::Deneb(y)) => x.compare_fields(y),
(BeaconState::Electra(x), BeaconState::Electra(y)) => x.compare_fields(y), (BeaconState::Electra(x), BeaconState::Electra(y)) => x.compare_fields(y),
(BeaconState::EIP7732(x), BeaconState::EIP7732(y)) => x.compare_fields(y),
_ => panic!("compare_fields: mismatched state variants",), _ => panic!("compare_fields: mismatched state variants",),
} }
} }

View File

@@ -291,6 +291,7 @@ pub fn is_progressive_balances_enabled<E: EthSpec>(state: &BeaconState<E>) -> bo
| BeaconState::Bellatrix(_) | BeaconState::Bellatrix(_)
| BeaconState::Capella(_) | BeaconState::Capella(_)
| BeaconState::Deneb(_) | BeaconState::Deneb(_)
| BeaconState::Electra(_) => true, | BeaconState::Electra(_)
| BeaconState::EIP7732(_) => true,
} }
} }

View File

@@ -85,7 +85,8 @@ impl<E: EthSpec> ForkVersionDeserialize for BuilderBid<E> {
ForkName::Capella => Self::Capella(serde_json::from_value(value).map_err(convert_err)?), ForkName::Capella => Self::Capella(serde_json::from_value(value).map_err(convert_err)?),
ForkName::Deneb => Self::Deneb(serde_json::from_value(value).map_err(convert_err)?), ForkName::Deneb => Self::Deneb(serde_json::from_value(value).map_err(convert_err)?),
ForkName::Electra => Self::Electra(serde_json::from_value(value).map_err(convert_err)?), ForkName::Electra => Self::Electra(serde_json::from_value(value).map_err(convert_err)?),
ForkName::Base | ForkName::Altair => { // FIXME(EIP-7732): Check this
ForkName::Base | ForkName::Altair | ForkName::EIP7732 => {
return Err(serde::de::Error::custom(format!( return Err(serde::de::Error::custom(format!(
"BuilderBid failed to deserialize: unsupported fork '{}'", "BuilderBid failed to deserialize: unsupported fork '{}'",
fork_name fork_name

View File

@@ -196,6 +196,12 @@ pub struct ChainSpec {
pub number_of_columns: usize, pub number_of_columns: usize,
pub samples_per_slot: u64, pub samples_per_slot: u64,
/*
* EIP-7732 params
*/
pub eip7732_fork_version: [u8; 4],
pub eip7732_fork_epoch: Option<Epoch>,
/* /*
* Networking * Networking
*/ */
@@ -308,17 +314,20 @@ impl ChainSpec {
/// Returns the name of the fork which is active at `epoch`. /// Returns the name of the fork which is active at `epoch`.
pub fn fork_name_at_epoch(&self, epoch: Epoch) -> ForkName { pub fn fork_name_at_epoch(&self, epoch: Epoch) -> ForkName {
match self.electra_fork_epoch { match self.eip7732_fork_epoch {
Some(fork_epoch) if epoch >= fork_epoch => ForkName::Electra, Some(fork_epoch) if epoch >= fork_epoch => ForkName::EIP7732,
_ => match self.deneb_fork_epoch { _ => match self.electra_fork_epoch {
Some(fork_epoch) if epoch >= fork_epoch => ForkName::Deneb, Some(fork_epoch) if epoch >= fork_epoch => ForkName::Electra,
_ => match self.capella_fork_epoch { _ => match self.deneb_fork_epoch {
Some(fork_epoch) if epoch >= fork_epoch => ForkName::Capella, Some(fork_epoch) if epoch >= fork_epoch => ForkName::Deneb,
_ => match self.bellatrix_fork_epoch { _ => match self.capella_fork_epoch {
Some(fork_epoch) if epoch >= fork_epoch => ForkName::Bellatrix, Some(fork_epoch) if epoch >= fork_epoch => ForkName::Capella,
_ => match self.altair_fork_epoch { _ => match self.bellatrix_fork_epoch {
Some(fork_epoch) if epoch >= fork_epoch => ForkName::Altair, Some(fork_epoch) if epoch >= fork_epoch => ForkName::Bellatrix,
_ => ForkName::Base, _ => match self.altair_fork_epoch {
Some(fork_epoch) if epoch >= fork_epoch => ForkName::Altair,
_ => ForkName::Base,
},
}, },
}, },
}, },
@@ -335,6 +344,7 @@ impl ChainSpec {
ForkName::Capella => self.capella_fork_version, ForkName::Capella => self.capella_fork_version,
ForkName::Deneb => self.deneb_fork_version, ForkName::Deneb => self.deneb_fork_version,
ForkName::Electra => self.electra_fork_version, ForkName::Electra => self.electra_fork_version,
ForkName::EIP7732 => self.eip7732_fork_version,
} }
} }
@@ -347,6 +357,7 @@ impl ChainSpec {
ForkName::Capella => self.capella_fork_epoch, ForkName::Capella => self.capella_fork_epoch,
ForkName::Deneb => self.deneb_fork_epoch, ForkName::Deneb => self.deneb_fork_epoch,
ForkName::Electra => self.electra_fork_epoch, ForkName::Electra => self.electra_fork_epoch,
ForkName::EIP7732 => self.eip7732_fork_epoch,
} }
} }
@@ -803,6 +814,12 @@ impl ChainSpec {
number_of_columns: 128, number_of_columns: 128,
samples_per_slot: 8, samples_per_slot: 8,
/*
* EIP-7732 params
*/
eip7732_fork_version: [0x09, 0x00, 0x00, 0x00],
eip7732_fork_epoch: None,
/* /*
* Network specific * Network specific
*/ */
@@ -911,6 +928,9 @@ impl ChainSpec {
.expect("calculation does not overflow"), .expect("calculation does not overflow"),
// PeerDAS // PeerDAS
eip7594_fork_epoch: None, eip7594_fork_epoch: None,
// EIP-7732
eip7732_fork_version: [0x09, 0x00, 0x00, 0x01],
eip7732_fork_epoch: None,
// Other // Other
network_id: 2, // lighthouse testnet network id network_id: 2, // lighthouse testnet network id
deposit_chain_id: 5, deposit_chain_id: 5,
@@ -1116,6 +1136,13 @@ impl ChainSpec {
data_column_sidecar_subnet_count: 128, data_column_sidecar_subnet_count: 128,
number_of_columns: 128, number_of_columns: 128,
samples_per_slot: 8, samples_per_slot: 8,
/*
* EIP-7732 params
*/
eip7732_fork_version: [0x09, 0x00, 0x00, 0x64],
eip7732_fork_epoch: None,
/* /*
* Network specific * Network specific
*/ */
@@ -1247,6 +1274,14 @@ pub struct Config {
#[serde(deserialize_with = "deserialize_fork_epoch")] #[serde(deserialize_with = "deserialize_fork_epoch")]
pub eip7594_fork_epoch: Option<MaybeQuoted<Epoch>>, pub eip7594_fork_epoch: Option<MaybeQuoted<Epoch>>,
#[serde(default = "default_eip7732_fork_version")]
#[serde(with = "serde_utils::bytes_4_hex")]
eip7732_fork_version: [u8; 4],
#[serde(default)]
#[serde(serialize_with = "serialize_fork_epoch")]
#[serde(deserialize_with = "deserialize_fork_epoch")]
pub eip7732_fork_epoch: Option<MaybeQuoted<Epoch>>,
#[serde(with = "serde_utils::quoted_u64")] #[serde(with = "serde_utils::quoted_u64")]
seconds_per_slot: u64, seconds_per_slot: u64,
#[serde(with = "serde_utils::quoted_u64")] #[serde(with = "serde_utils::quoted_u64")]
@@ -1375,6 +1410,11 @@ fn default_electra_fork_version() -> [u8; 4] {
[0xff, 0xff, 0xff, 0xff] [0xff, 0xff, 0xff, 0xff]
} }
fn default_eip7732_fork_version() -> [u8; 4] {
// This value shouldn't be used.
[0xff, 0xff, 0xff, 0xff]
}
/// Placeholder value: 2^256-2^10 (115792089237316195423570985008687907853269984665640564039457584007913129638912). /// Placeholder value: 2^256-2^10 (115792089237316195423570985008687907853269984665640564039457584007913129638912).
/// ///
/// Taken from https://github.com/ethereum/consensus-specs/blob/d5e4828aecafaf1c57ef67a5f23c4ae7b08c5137/configs/mainnet.yaml#L15-L16 /// Taken from https://github.com/ethereum/consensus-specs/blob/d5e4828aecafaf1c57ef67a5f23c4ae7b08c5137/configs/mainnet.yaml#L15-L16
@@ -1638,6 +1678,11 @@ impl Config {
.eip7594_fork_epoch .eip7594_fork_epoch
.map(|epoch| MaybeQuoted { value: epoch }), .map(|epoch| MaybeQuoted { value: epoch }),
eip7732_fork_version: spec.eip7732_fork_version,
eip7732_fork_epoch: spec
.eip7732_fork_epoch
.map(|epoch| MaybeQuoted { value: epoch }),
seconds_per_slot: spec.seconds_per_slot, seconds_per_slot: spec.seconds_per_slot,
seconds_per_eth1_block: spec.seconds_per_eth1_block, seconds_per_eth1_block: spec.seconds_per_eth1_block,
min_validator_withdrawability_delay: spec.min_validator_withdrawability_delay, min_validator_withdrawability_delay: spec.min_validator_withdrawability_delay,
@@ -1716,6 +1761,8 @@ impl Config {
electra_fork_epoch, electra_fork_epoch,
electra_fork_version, electra_fork_version,
eip7594_fork_epoch, eip7594_fork_epoch,
eip7732_fork_epoch,
eip7732_fork_version,
seconds_per_slot, seconds_per_slot,
seconds_per_eth1_block, seconds_per_eth1_block,
min_validator_withdrawability_delay, min_validator_withdrawability_delay,
@@ -1778,6 +1825,8 @@ impl Config {
electra_fork_epoch: electra_fork_epoch.map(|q| q.value), electra_fork_epoch: electra_fork_epoch.map(|q| q.value),
electra_fork_version, electra_fork_version,
eip7594_fork_epoch: eip7594_fork_epoch.map(|q| q.value), eip7594_fork_epoch: eip7594_fork_epoch.map(|q| q.value),
eip7732_fork_epoch: eip7732_fork_epoch.map(|q| q.value),
eip7732_fork_version,
seconds_per_slot, seconds_per_slot,
seconds_per_eth1_block, seconds_per_eth1_block,
min_validator_withdrawability_delay, min_validator_withdrawability_delay,

View File

@@ -0,0 +1,92 @@
// These would usually be created by superstuct but now there's no longer a 1:1 mapping between
// the variants for ExecutionPayload and the variants for
// - ExecutionPayloadHeader
// - FullPayload
// - BlindedPayload
#[macro_export]
macro_rules! map_execution_payload_into_full_payload {
($value:expr, $f:expr) => {
match $value {
ExecutionPayload::Bellatrix(inner) => {
let f: fn(ExecutionPayloadBellatrix<_>, fn(_) -> _) -> _ = $f;
f(inner, FullPayload::Bellatrix)
}
ExecutionPayload::Capella(inner) => {
let f: fn(ExecutionPayloadCapella<_>, fn(_) -> _) -> _ = $f;
f(inner, FullPayload::Capella)
}
ExecutionPayload::Deneb(inner) => {
let f: fn(ExecutionPayloadDeneb<_>, fn(_) -> _) -> _ = $f;
f(inner, FullPayload::Deneb)
}
ExecutionPayload::Electra(inner) => {
let f: fn(ExecutionPayloadElectra<_>, fn(_) -> _) -> _ = $f;
f(inner, FullPayload::Electra)
}
ExecutionPayload::EIP7732(_) => panic!("FullPayload::EIP7732 does not exist!"),
}
};
}
#[macro_export]
macro_rules! map_execution_payload_into_blinded_payload {
($value:expr, $f:expr) => {
match $value {
ExecutionPayload::Bellatrix(inner) => {
let f: fn(ExecutionPayloadBellatrix<_>, fn(_) -> _) -> _ = $f;
f(inner, BlindedPayload::Bellatrix)
}
ExecutionPayload::Capella(inner) => {
let f: fn(ExecutionPayloadCapella<_>, fn(_) -> _) -> _ = $f;
f(inner, BlindedPayload::Capella)
}
ExecutionPayload::Deneb(inner) => {
let f: fn(ExecutionPayloadDeneb<_>, fn(_) -> _) -> _ = $f;
f(inner, BlindedPayload::Deneb)
}
ExecutionPayload::Electra(inner) => {
let f: fn(ExecutionPayloadElectra<_>, fn(_) -> _) -> _ = $f;
f(inner, BlindedPayload::Electra)
}
ExecutionPayload::EIP7732(_) => panic!("BlindedPayload::EIP7732 does not exist!"),
}
};
}
#[macro_export]
macro_rules! map_execution_payload_ref_into_execution_payload_header {
(&$lifetime:tt _, $value:expr, $f:expr) => {
match $value {
ExecutionPayloadRef::Bellatrix(inner) => {
let f: fn(
&$lifetime ExecutionPayloadBellatrix<_>,
fn(_) -> _,
) -> _ = $f;
f(inner, ExecutionPayloadHeader::Bellatrix)
}
ExecutionPayloadRef::Capella(inner) => {
let f: fn(
&$lifetime ExecutionPayloadCapella<_>,
fn(_) -> _,
) -> _ = $f;
f(inner, ExecutionPayloadHeader::Capella)
}
ExecutionPayloadRef::Deneb(inner) => {
let f: fn(
&$lifetime ExecutionPayloadDeneb<_>,
fn(_) -> _,
) -> _ = $f;
f(inner, ExecutionPayloadHeader::Deneb)
}
ExecutionPayloadRef::Electra(inner) => {
let f: fn(
&$lifetime ExecutionPayloadElectra<_>,
fn(_) -> _,
) -> _ = $f;
f(inner, ExecutionPayloadHeader::Electra)
}
ExecutionPayloadRef::EIP7732(_) => panic!("ExecutionPayloadHeader::EIP7732 does not exist!"),
}
}
}

View File

@@ -0,0 +1,41 @@
use crate::{test_utils::TestRandom, *};
use derivative::Derivative;
use serde::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash;
#[derive(
arbitrary::Arbitrary,
Debug,
Clone,
PartialEq,
Serialize,
Encode,
Decode,
Deserialize,
TreeHash,
Derivative,
TestRandom,
)]
// This is what Potuz' spec calls an `ExecutionPayload` even though it's clearly a bid.
pub struct ExecutionBid {
parent_block_hash: ExecutionBlockHash,
parent_block_root: Hash256,
block_hash: ExecutionBlockHash,
#[serde(with = "serde_utils::quoted_u64")]
gas_limit: u64,
#[serde(with = "serde_utils::quoted_u64")]
builder_index: u64,
slot: Slot,
#[serde(with = "serde_utils::quoted_u64")]
value: u64,
blob_kzg_commitments_root: Hash256,
}
#[cfg(test)]
mod tests {
use super::*;
ssz_and_tree_hash_tests!(ExecutionBid);
}

View File

@@ -15,7 +15,7 @@ pub type Transactions<E> = VariableList<
pub type Withdrawals<E> = VariableList<Withdrawal, <E as EthSpec>::MaxWithdrawalsPerPayload>; pub type Withdrawals<E> = VariableList<Withdrawal, <E as EthSpec>::MaxWithdrawalsPerPayload>;
#[superstruct( #[superstruct(
variants(Bellatrix, Capella, Deneb, Electra), variants(Bellatrix, Capella, Deneb, Electra, EIP7732),
variant_attributes( variant_attributes(
derive( derive(
Default, Default,
@@ -35,9 +35,7 @@ pub type Withdrawals<E> = VariableList<Withdrawal, <E as EthSpec>::MaxWithdrawal
arbitrary(bound = "E: EthSpec") arbitrary(bound = "E: EthSpec")
), ),
cast_error(ty = "Error", expr = "BeaconStateError::IncorrectStateVariant"), cast_error(ty = "Error", expr = "BeaconStateError::IncorrectStateVariant"),
partial_getter_error(ty = "Error", expr = "BeaconStateError::IncorrectStateVariant"), partial_getter_error(ty = "Error", expr = "BeaconStateError::IncorrectStateVariant")
map_into(FullPayload, BlindedPayload),
map_ref_into(ExecutionPayloadHeader)
)] )]
#[derive( #[derive(
Debug, Clone, Serialize, Encode, Deserialize, TreeHash, Derivative, arbitrary::Arbitrary, Debug, Clone, Serialize, Encode, Deserialize, TreeHash, Derivative, arbitrary::Arbitrary,
@@ -82,12 +80,12 @@ pub struct ExecutionPayload<E: EthSpec> {
pub block_hash: ExecutionBlockHash, pub block_hash: ExecutionBlockHash,
#[serde(with = "ssz_types::serde_utils::list_of_hex_var_list")] #[serde(with = "ssz_types::serde_utils::list_of_hex_var_list")]
pub transactions: Transactions<E>, pub transactions: Transactions<E>,
#[superstruct(only(Capella, Deneb, Electra))] #[superstruct(only(Capella, Deneb, Electra, EIP7732))]
pub withdrawals: Withdrawals<E>, pub withdrawals: Withdrawals<E>,
#[superstruct(only(Deneb, Electra), partial_getter(copy))] #[superstruct(only(Deneb, Electra, EIP7732), partial_getter(copy))]
#[serde(with = "serde_utils::quoted_u64")] #[serde(with = "serde_utils::quoted_u64")]
pub blob_gas_used: u64, pub blob_gas_used: u64,
#[superstruct(only(Deneb, Electra), partial_getter(copy))] #[superstruct(only(Deneb, Electra, EIP7732), partial_getter(copy))]
#[serde(with = "serde_utils::quoted_u64")] #[serde(with = "serde_utils::quoted_u64")]
pub excess_blob_gas: u64, pub excess_blob_gas: u64,
} }
@@ -105,6 +103,7 @@ impl<'a, E: EthSpec> ExecutionPayloadRef<'a, E> {
impl<E: EthSpec> ExecutionPayload<E> { impl<E: EthSpec> ExecutionPayload<E> {
pub fn from_ssz_bytes(bytes: &[u8], fork_name: ForkName) -> Result<Self, ssz::DecodeError> { pub fn from_ssz_bytes(bytes: &[u8], fork_name: ForkName) -> Result<Self, ssz::DecodeError> {
match fork_name { match fork_name {
// FIXME(EIP7732): Check this
ForkName::Base | ForkName::Altair => Err(ssz::DecodeError::BytesInvalid(format!( ForkName::Base | ForkName::Altair => Err(ssz::DecodeError::BytesInvalid(format!(
"unsupported fork for ExecutionPayload: {fork_name}", "unsupported fork for ExecutionPayload: {fork_name}",
))), ))),
@@ -114,6 +113,7 @@ impl<E: EthSpec> ExecutionPayload<E> {
ForkName::Capella => ExecutionPayloadCapella::from_ssz_bytes(bytes).map(Self::Capella), ForkName::Capella => ExecutionPayloadCapella::from_ssz_bytes(bytes).map(Self::Capella),
ForkName::Deneb => ExecutionPayloadDeneb::from_ssz_bytes(bytes).map(Self::Deneb), ForkName::Deneb => ExecutionPayloadDeneb::from_ssz_bytes(bytes).map(Self::Deneb),
ForkName::Electra => ExecutionPayloadElectra::from_ssz_bytes(bytes).map(Self::Electra), ForkName::Electra => ExecutionPayloadElectra::from_ssz_bytes(bytes).map(Self::Electra),
ForkName::EIP7732 => ExecutionPayloadEIP7732::from_ssz_bytes(bytes).map(Self::EIP7732),
} }
} }
@@ -166,6 +166,17 @@ impl<E: EthSpec> ExecutionPayload<E> {
// Max size of variable length `withdrawals` field // Max size of variable length `withdrawals` field
+ (E::max_withdrawals_per_payload() * <Withdrawal as Encode>::ssz_fixed_len()) + (E::max_withdrawals_per_payload() * <Withdrawal as Encode>::ssz_fixed_len())
} }
#[allow(clippy::arithmetic_side_effects)]
pub fn max_execution_payload_eip7732_size() -> usize {
// Fixed part
ExecutionPayloadEIP7732::<E>::default().as_ssz_bytes().len()
+ (E::max_extra_data_bytes() * <u8 as Encode>::ssz_fixed_len())
// Max size of variable length `transactions` field
+ (E::max_transactions_per_payload() * (ssz::BYTES_PER_LENGTH_OFFSET + E::max_bytes_per_transaction()))
// Max size of variable length `withdrawals` field
+ (E::max_withdrawals_per_payload() * <Withdrawal as Encode>::ssz_fixed_len())
}
} }
impl<E: EthSpec> ForkVersionDeserialize for ExecutionPayload<E> { impl<E: EthSpec> ForkVersionDeserialize for ExecutionPayload<E> {
@@ -184,6 +195,7 @@ impl<E: EthSpec> ForkVersionDeserialize for ExecutionPayload<E> {
ForkName::Capella => Self::Capella(serde_json::from_value(value).map_err(convert_err)?), ForkName::Capella => Self::Capella(serde_json::from_value(value).map_err(convert_err)?),
ForkName::Deneb => Self::Deneb(serde_json::from_value(value).map_err(convert_err)?), ForkName::Deneb => Self::Deneb(serde_json::from_value(value).map_err(convert_err)?),
ForkName::Electra => Self::Electra(serde_json::from_value(value).map_err(convert_err)?), ForkName::Electra => Self::Electra(serde_json::from_value(value).map_err(convert_err)?),
ForkName::EIP7732 => Self::EIP7732(serde_json::from_value(value).map_err(convert_err)?),
ForkName::Base | ForkName::Altair => { ForkName::Base | ForkName::Altair => {
return Err(serde::de::Error::custom(format!( return Err(serde::de::Error::custom(format!(
"ExecutionPayload failed to deserialize: unsupported fork '{}'", "ExecutionPayload failed to deserialize: unsupported fork '{}'",
@@ -201,6 +213,7 @@ impl<E: EthSpec> ExecutionPayload<E> {
ExecutionPayload::Capella(_) => ForkName::Capella, ExecutionPayload::Capella(_) => ForkName::Capella,
ExecutionPayload::Deneb(_) => ForkName::Deneb, ExecutionPayload::Deneb(_) => ForkName::Deneb,
ExecutionPayload::Electra(_) => ForkName::Electra, ExecutionPayload::Electra(_) => ForkName::Electra,
ExecutionPayload::EIP7732(_) => ForkName::EIP7732,
} }
} }
} }

View File

@@ -108,6 +108,9 @@ impl<E: EthSpec> ExecutionPayloadHeader<E> {
ForkName::Electra => { ForkName::Electra => {
ExecutionPayloadHeaderElectra::from_ssz_bytes(bytes).map(Self::Electra) ExecutionPayloadHeaderElectra::from_ssz_bytes(bytes).map(Self::Electra)
} }
ForkName::EIP7732 => Err(ssz::DecodeError::BytesInvalid(format!(
"unsupported fork for ExecutionPayloadHeader: {fork_name}",
))),
} }
} }
@@ -120,6 +123,7 @@ impl<E: EthSpec> ExecutionPayloadHeader<E> {
// Max size of variable length `extra_data` field // Max size of variable length `extra_data` field
E::max_extra_data_bytes() * <u8 as Encode>::ssz_fixed_len() E::max_extra_data_bytes() * <u8 as Encode>::ssz_fixed_len()
} }
ForkName::EIP7732 => 0,
} }
} }
@@ -423,7 +427,8 @@ impl<E: EthSpec> ForkVersionDeserialize for ExecutionPayloadHeader<E> {
ForkName::Capella => Self::Capella(serde_json::from_value(value).map_err(convert_err)?), ForkName::Capella => Self::Capella(serde_json::from_value(value).map_err(convert_err)?),
ForkName::Deneb => Self::Deneb(serde_json::from_value(value).map_err(convert_err)?), ForkName::Deneb => Self::Deneb(serde_json::from_value(value).map_err(convert_err)?),
ForkName::Electra => Self::Electra(serde_json::from_value(value).map_err(convert_err)?), ForkName::Electra => Self::Electra(serde_json::from_value(value).map_err(convert_err)?),
ForkName::Base | ForkName::Altair => { // FIXME(EIP7732): Check this
ForkName::Base | ForkName::Altair | ForkName::EIP7732 => {
return Err(serde::de::Error::custom(format!( return Err(serde::de::Error::custom(format!(
"ExecutionPayloadHeader failed to deserialize: unsupported fork '{}'", "ExecutionPayloadHeader failed to deserialize: unsupported fork '{}'",
fork_name fork_name

View File

@@ -69,6 +69,13 @@ impl ForkContext {
)); ));
} }
if spec.eip7732_fork_epoch.is_some() {
fork_to_digest.push((
ForkName::EIP7732,
ChainSpec::compute_fork_digest(spec.eip7732_fork_version, genesis_validators_root),
));
}
let fork_to_digest: HashMap<ForkName, [u8; 4]> = fork_to_digest.into_iter().collect(); let fork_to_digest: HashMap<ForkName, [u8; 4]> = fork_to_digest.into_iter().collect();
let digest_to_fork = fork_to_digest let digest_to_fork = fork_to_digest

View File

@@ -17,6 +17,7 @@ pub enum ForkName {
Capella, Capella,
Deneb, Deneb,
Electra, Electra,
EIP7732,
} }
impl ForkName { impl ForkName {
@@ -28,6 +29,7 @@ impl ForkName {
ForkName::Capella, ForkName::Capella,
ForkName::Deneb, ForkName::Deneb,
ForkName::Electra, ForkName::Electra,
ForkName::EIP7732,
] ]
} }
@@ -38,6 +40,7 @@ impl ForkName {
(ForkName::Capella, spec.capella_fork_epoch), (ForkName::Capella, spec.capella_fork_epoch),
(ForkName::Deneb, spec.deneb_fork_epoch), (ForkName::Deneb, spec.deneb_fork_epoch),
(ForkName::Electra, spec.electra_fork_epoch), (ForkName::Electra, spec.electra_fork_epoch),
(ForkName::EIP7732, spec.eip7732_fork_epoch),
] ]
} }
@@ -57,6 +60,7 @@ impl ForkName {
spec.capella_fork_epoch = None; spec.capella_fork_epoch = None;
spec.deneb_fork_epoch = None; spec.deneb_fork_epoch = None;
spec.electra_fork_epoch = None; spec.electra_fork_epoch = None;
spec.eip7732_fork_epoch = None;
spec spec
} }
ForkName::Altair => { ForkName::Altair => {
@@ -65,6 +69,7 @@ impl ForkName {
spec.capella_fork_epoch = None; spec.capella_fork_epoch = None;
spec.deneb_fork_epoch = None; spec.deneb_fork_epoch = None;
spec.electra_fork_epoch = None; spec.electra_fork_epoch = None;
spec.eip7732_fork_epoch = None;
spec spec
} }
ForkName::Bellatrix => { ForkName::Bellatrix => {
@@ -73,6 +78,7 @@ impl ForkName {
spec.capella_fork_epoch = None; spec.capella_fork_epoch = None;
spec.deneb_fork_epoch = None; spec.deneb_fork_epoch = None;
spec.electra_fork_epoch = None; spec.electra_fork_epoch = None;
spec.eip7732_fork_epoch = None;
spec spec
} }
ForkName::Capella => { ForkName::Capella => {
@@ -81,6 +87,7 @@ impl ForkName {
spec.capella_fork_epoch = Some(Epoch::new(0)); spec.capella_fork_epoch = Some(Epoch::new(0));
spec.deneb_fork_epoch = None; spec.deneb_fork_epoch = None;
spec.electra_fork_epoch = None; spec.electra_fork_epoch = None;
spec.eip7732_fork_epoch = None;
spec spec
} }
ForkName::Deneb => { ForkName::Deneb => {
@@ -89,6 +96,7 @@ impl ForkName {
spec.capella_fork_epoch = Some(Epoch::new(0)); spec.capella_fork_epoch = Some(Epoch::new(0));
spec.deneb_fork_epoch = Some(Epoch::new(0)); spec.deneb_fork_epoch = Some(Epoch::new(0));
spec.electra_fork_epoch = None; spec.electra_fork_epoch = None;
spec.eip7732_fork_epoch = None;
spec spec
} }
ForkName::Electra => { ForkName::Electra => {
@@ -97,6 +105,16 @@ impl ForkName {
spec.capella_fork_epoch = Some(Epoch::new(0)); spec.capella_fork_epoch = Some(Epoch::new(0));
spec.deneb_fork_epoch = Some(Epoch::new(0)); spec.deneb_fork_epoch = Some(Epoch::new(0));
spec.electra_fork_epoch = Some(Epoch::new(0)); spec.electra_fork_epoch = Some(Epoch::new(0));
spec.eip7732_fork_epoch = None;
spec
}
ForkName::EIP7732 => {
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.deneb_fork_epoch = Some(Epoch::new(0));
spec.electra_fork_epoch = Some(Epoch::new(0));
spec.eip7732_fork_epoch = Some(Epoch::new(0));
spec spec
} }
} }
@@ -113,6 +131,7 @@ impl ForkName {
ForkName::Capella => Some(ForkName::Bellatrix), ForkName::Capella => Some(ForkName::Bellatrix),
ForkName::Deneb => Some(ForkName::Capella), ForkName::Deneb => Some(ForkName::Capella),
ForkName::Electra => Some(ForkName::Deneb), ForkName::Electra => Some(ForkName::Deneb),
ForkName::EIP7732 => Some(ForkName::Electra),
} }
} }
@@ -126,7 +145,8 @@ impl ForkName {
ForkName::Bellatrix => Some(ForkName::Capella), ForkName::Bellatrix => Some(ForkName::Capella),
ForkName::Capella => Some(ForkName::Deneb), ForkName::Capella => Some(ForkName::Deneb),
ForkName::Deneb => Some(ForkName::Electra), ForkName::Deneb => Some(ForkName::Electra),
ForkName::Electra => None, ForkName::Electra => Some(ForkName::EIP7732),
ForkName::EIP7732 => None,
} }
} }
@@ -149,6 +169,10 @@ impl ForkName {
pub fn electra_enabled(self) -> bool { pub fn electra_enabled(self) -> bool {
self >= ForkName::Electra self >= ForkName::Electra
} }
pub fn eip7732_enabled(self) -> bool {
self >= ForkName::EIP7732
}
} }
/// Map a fork name into a fork-versioned superstruct type like `BeaconBlock`. /// Map a fork name into a fork-versioned superstruct type like `BeaconBlock`.
@@ -200,6 +224,10 @@ macro_rules! map_fork_name_with {
let (value, extra_data) = $body; let (value, extra_data) = $body;
($t::Electra(value), extra_data) ($t::Electra(value), extra_data)
} }
ForkName::EIP7732 => {
let (value, extra_data) = $body;
($t::EIP7732(value), extra_data)
}
} }
}; };
} }
@@ -215,6 +243,7 @@ impl FromStr for ForkName {
"capella" => ForkName::Capella, "capella" => ForkName::Capella,
"deneb" => ForkName::Deneb, "deneb" => ForkName::Deneb,
"electra" => ForkName::Electra, "electra" => ForkName::Electra,
"eip7732" => ForkName::EIP7732,
_ => return Err(format!("unknown fork name: {}", fork_name)), _ => return Err(format!("unknown fork name: {}", fork_name)),
}) })
} }
@@ -229,6 +258,7 @@ impl Display for ForkName {
ForkName::Capella => "capella".fmt(f), ForkName::Capella => "capella".fmt(f),
ForkName::Deneb => "deneb".fmt(f), ForkName::Deneb => "deneb".fmt(f),
ForkName::Electra => "electra".fmt(f), ForkName::Electra => "electra".fmt(f),
ForkName::EIP7732 => "eip7732".fmt(f),
} }
} }
} }

View File

@@ -35,9 +35,11 @@ pub mod deposit_data;
pub mod deposit_message; pub mod deposit_message;
pub mod deposit_request; pub mod deposit_request;
pub mod deposit_tree_snapshot; pub mod deposit_tree_snapshot;
pub mod dumb_macros;
pub mod enr_fork_id; pub mod enr_fork_id;
pub mod eth1_data; pub mod eth1_data;
pub mod eth_spec; pub mod eth_spec;
pub mod execution_bid;
pub mod execution_block_hash; pub mod execution_block_hash;
pub mod execution_payload; pub mod execution_payload;
pub mod execution_payload_header; pub mod execution_payload_header;
@@ -126,13 +128,13 @@ pub use crate::attester_slashing::{
}; };
pub use crate::beacon_block::{ pub use crate::beacon_block::{
BeaconBlock, BeaconBlockAltair, BeaconBlockBase, BeaconBlockBellatrix, BeaconBlockCapella, BeaconBlock, BeaconBlockAltair, BeaconBlockBase, BeaconBlockBellatrix, BeaconBlockCapella,
BeaconBlockDeneb, BeaconBlockElectra, BeaconBlockRef, BeaconBlockRefMut, BlindedBeaconBlock, BeaconBlockDeneb, BeaconBlockEIP7732, BeaconBlockElectra, BeaconBlockRef, BeaconBlockRefMut,
BlockImportSource, EmptyBlock, BlindedBeaconBlock, BlockImportSource, EmptyBlock,
}; };
pub use crate::beacon_block_body::{ pub use crate::beacon_block_body::{
BeaconBlockBody, BeaconBlockBodyAltair, BeaconBlockBodyBase, BeaconBlockBodyBellatrix, BeaconBlockBody, BeaconBlockBodyAltair, BeaconBlockBodyBase, BeaconBlockBodyBellatrix,
BeaconBlockBodyCapella, BeaconBlockBodyDeneb, BeaconBlockBodyElectra, BeaconBlockBodyRef, BeaconBlockBodyCapella, BeaconBlockBodyDeneb, BeaconBlockBodyEIP7732, BeaconBlockBodyElectra,
BeaconBlockBodyRefMut, BeaconBlockBodyRef, BeaconBlockBodyRefMut,
}; };
pub use crate::beacon_block_header::BeaconBlockHeader; pub use crate::beacon_block_header::BeaconBlockHeader;
pub use crate::beacon_committee::{BeaconCommittee, OwnedBeaconCommittee}; pub use crate::beacon_committee::{BeaconCommittee, OwnedBeaconCommittee};
@@ -159,11 +161,13 @@ pub use crate::enr_fork_id::EnrForkId;
pub use crate::epoch_cache::{EpochCache, EpochCacheError, EpochCacheKey}; pub use crate::epoch_cache::{EpochCache, EpochCacheError, EpochCacheKey};
pub use crate::eth1_data::Eth1Data; pub use crate::eth1_data::Eth1Data;
pub use crate::eth_spec::EthSpecId; pub use crate::eth_spec::EthSpecId;
pub use crate::execution_bid::ExecutionBid;
pub use crate::execution_block_hash::ExecutionBlockHash; pub use crate::execution_block_hash::ExecutionBlockHash;
pub use crate::execution_block_header::{EncodableExecutionBlockHeader, ExecutionBlockHeader}; pub use crate::execution_block_header::{EncodableExecutionBlockHeader, ExecutionBlockHeader};
pub use crate::execution_payload::{ pub use crate::execution_payload::{
ExecutionPayload, ExecutionPayloadBellatrix, ExecutionPayloadCapella, ExecutionPayloadDeneb, ExecutionPayload, ExecutionPayloadBellatrix, ExecutionPayloadCapella, ExecutionPayloadDeneb,
ExecutionPayloadElectra, ExecutionPayloadRef, Transaction, Transactions, Withdrawals, ExecutionPayloadEIP7732, ExecutionPayloadElectra, ExecutionPayloadRef, Transaction,
Transactions, Withdrawals,
}; };
pub use crate::execution_payload_header::{ pub use crate::execution_payload_header::{
ExecutionPayloadHeader, ExecutionPayloadHeaderBellatrix, ExecutionPayloadHeaderCapella, ExecutionPayloadHeader, ExecutionPayloadHeaderBellatrix, ExecutionPayloadHeaderCapella,
@@ -228,8 +232,8 @@ pub use crate::signed_aggregate_and_proof::{
pub use crate::signed_beacon_block::{ pub use crate::signed_beacon_block::{
ssz_tagged_signed_beacon_block, ssz_tagged_signed_beacon_block_arc, SignedBeaconBlock, ssz_tagged_signed_beacon_block, ssz_tagged_signed_beacon_block_arc, SignedBeaconBlock,
SignedBeaconBlockAltair, SignedBeaconBlockBase, SignedBeaconBlockBellatrix, SignedBeaconBlockAltair, SignedBeaconBlockBase, SignedBeaconBlockBellatrix,
SignedBeaconBlockCapella, SignedBeaconBlockDeneb, SignedBeaconBlockElectra, SignedBeaconBlockCapella, SignedBeaconBlockDeneb, SignedBeaconBlockEIP7732,
SignedBeaconBlockHash, SignedBlindedBeaconBlock, SignedBeaconBlockElectra, SignedBeaconBlockHash, SignedBlindedBeaconBlock,
}; };
pub use crate::signed_beacon_block_header::SignedBeaconBlockHeader; pub use crate::signed_beacon_block_header::SignedBeaconBlockHeader;
pub use crate::signed_bls_to_execution_change::SignedBlsToExecutionChange; pub use crate::signed_bls_to_execution_change::SignedBlsToExecutionChange;

View File

@@ -102,6 +102,7 @@ impl<E: EthSpec> LightClientBootstrap<E> {
"LightClientBootstrap decoding for {fork_name} not implemented" "LightClientBootstrap decoding for {fork_name} not implemented"
))) )))
} }
ForkName::EIP7732 => todo!("EIP-7732 light client not implemented"),
}; };
Ok(bootstrap) Ok(bootstrap)
@@ -117,6 +118,7 @@ impl<E: EthSpec> LightClientBootstrap<E> {
ForkName::Capella => <LightClientBootstrapCapella<E> as Encode>::ssz_fixed_len(), ForkName::Capella => <LightClientBootstrapCapella<E> as Encode>::ssz_fixed_len(),
ForkName::Deneb => <LightClientBootstrapDeneb<E> as Encode>::ssz_fixed_len(), ForkName::Deneb => <LightClientBootstrapDeneb<E> as Encode>::ssz_fixed_len(),
ForkName::Electra => <LightClientBootstrapElectra<E> as Encode>::ssz_fixed_len(), ForkName::Electra => <LightClientBootstrapElectra<E> as Encode>::ssz_fixed_len(),
ForkName::EIP7732 => todo!("EIP-7732 light client not implemented"),
}; };
fixed_len + LightClientHeader::<E>::ssz_max_var_len_for_fork(fork_name) fixed_len + LightClientHeader::<E>::ssz_max_var_len_for_fork(fork_name)
} }
@@ -152,6 +154,7 @@ impl<E: EthSpec> LightClientBootstrap<E> {
current_sync_committee, current_sync_committee,
current_sync_committee_branch: current_sync_committee_branch.into(), current_sync_committee_branch: current_sync_committee_branch.into(),
}), }),
ForkName::EIP7732 => todo!("EIP-7732 light client not implemented"),
}; };
Ok(light_client_bootstrap) Ok(light_client_bootstrap)
@@ -192,6 +195,7 @@ impl<E: EthSpec> LightClientBootstrap<E> {
current_sync_committee, current_sync_committee,
current_sync_committee_branch: current_sync_committee_branch.into(), current_sync_committee_branch: current_sync_committee_branch.into(),
}), }),
ForkName::EIP7732 => todo!("EIP-7732 light client not implemented"),
}; };
Ok(light_client_bootstrap) Ok(light_client_bootstrap)

View File

@@ -135,6 +135,7 @@ impl<E: EthSpec> LightClientFinalityUpdate<E> {
sync_aggregate, sync_aggregate,
signature_slot, signature_slot,
}), }),
ForkName::EIP7732 => todo!("EIP-7732 light client not implemented"),
ForkName::Base => return Err(Error::AltairForkNotActive), ForkName::Base => return Err(Error::AltairForkNotActive),
}; };
@@ -178,6 +179,7 @@ impl<E: EthSpec> LightClientFinalityUpdate<E> {
"LightClientFinalityUpdate decoding for {fork_name} not implemented" "LightClientFinalityUpdate decoding for {fork_name} not implemented"
))) )))
} }
ForkName::EIP7732 => todo!("EIP-7732 light client not implemented"),
}; };
Ok(finality_update) Ok(finality_update)
@@ -193,6 +195,7 @@ impl<E: EthSpec> LightClientFinalityUpdate<E> {
ForkName::Capella => <LightClientFinalityUpdateCapella<E> as Encode>::ssz_fixed_len(), ForkName::Capella => <LightClientFinalityUpdateCapella<E> as Encode>::ssz_fixed_len(),
ForkName::Deneb => <LightClientFinalityUpdateDeneb<E> as Encode>::ssz_fixed_len(), ForkName::Deneb => <LightClientFinalityUpdateDeneb<E> as Encode>::ssz_fixed_len(),
ForkName::Electra => <LightClientFinalityUpdateElectra<E> as Encode>::ssz_fixed_len(), ForkName::Electra => <LightClientFinalityUpdateElectra<E> as Encode>::ssz_fixed_len(),
ForkName::EIP7732 => todo!("EIP-7732 light client not implemented"),
}; };
// `2 *` because there are two headers in the update // `2 *` because there are two headers in the update
fixed_size + 2 * LightClientHeader::<E>::ssz_max_var_len_for_fork(fork_name) fixed_size + 2 * LightClientHeader::<E>::ssz_max_var_len_for_fork(fork_name)

View File

@@ -92,6 +92,7 @@ impl<E: EthSpec> LightClientHeader<E> {
ForkName::Electra => LightClientHeader::Electra( ForkName::Electra => LightClientHeader::Electra(
LightClientHeaderElectra::block_to_light_client_header(block)?, LightClientHeaderElectra::block_to_light_client_header(block)?,
), ),
ForkName::EIP7732 => todo!("EIP-7732 light client not implemented"),
}; };
Ok(header) Ok(header)
} }
@@ -115,6 +116,7 @@ impl<E: EthSpec> LightClientHeader<E> {
"LightClientHeader decoding for {fork_name} not implemented" "LightClientHeader decoding for {fork_name} not implemented"
))) )))
} }
ForkName::EIP7732 => todo!("EIP-7732 light client not implemented"),
}; };
Ok(header) Ok(header)
@@ -129,6 +131,10 @@ impl<E: EthSpec> LightClientHeader<E> {
} }
pub fn ssz_max_var_len_for_fork(fork_name: ForkName) -> usize { pub fn ssz_max_var_len_for_fork(fork_name: ForkName) -> usize {
if fork_name.eip7732_enabled() {
// TODO(EIP7732): check this
return 0;
}
if fork_name.capella_enabled() { if fork_name.capella_enabled() {
ExecutionPayloadHeader::<E>::ssz_max_var_len_for_fork(fork_name) ExecutionPayloadHeader::<E>::ssz_max_var_len_for_fork(fork_name)
} else { } else {
@@ -301,6 +307,7 @@ impl<E: EthSpec> ForkVersionDeserialize for LightClientHeader<E> {
ForkName::Electra => serde_json::from_value(value) ForkName::Electra => serde_json::from_value(value)
.map(|light_client_header| Self::Electra(light_client_header)) .map(|light_client_header| Self::Electra(light_client_header))
.map_err(serde::de::Error::custom), .map_err(serde::de::Error::custom),
ForkName::EIP7732 => todo!("EIP-7732 light client not implemented"),
ForkName::Base => Err(serde::de::Error::custom(format!( ForkName::Base => Err(serde::de::Error::custom(format!(
"LightClientHeader deserialization for {fork_name} not implemented" "LightClientHeader deserialization for {fork_name} not implemented"
))), ))),

View File

@@ -102,6 +102,7 @@ impl<E: EthSpec> LightClientOptimisticUpdate<E> {
sync_aggregate, sync_aggregate,
signature_slot, signature_slot,
}), }),
ForkName::EIP7732 => todo!("EIP-7732 light client not implemented"),
ForkName::Base => return Err(Error::AltairForkNotActive), ForkName::Base => return Err(Error::AltairForkNotActive),
}; };
@@ -160,6 +161,7 @@ impl<E: EthSpec> LightClientOptimisticUpdate<E> {
"LightClientOptimisticUpdate decoding for {fork_name} not implemented" "LightClientOptimisticUpdate decoding for {fork_name} not implemented"
))) )))
} }
ForkName::EIP7732 => todo!("EIP-7732 light client not implemented"),
}; };
Ok(optimistic_update) Ok(optimistic_update)
@@ -175,6 +177,7 @@ impl<E: EthSpec> LightClientOptimisticUpdate<E> {
ForkName::Capella => <LightClientOptimisticUpdateCapella<E> as Encode>::ssz_fixed_len(), ForkName::Capella => <LightClientOptimisticUpdateCapella<E> as Encode>::ssz_fixed_len(),
ForkName::Deneb => <LightClientOptimisticUpdateDeneb<E> as Encode>::ssz_fixed_len(), ForkName::Deneb => <LightClientOptimisticUpdateDeneb<E> as Encode>::ssz_fixed_len(),
ForkName::Electra => <LightClientOptimisticUpdateElectra<E> as Encode>::ssz_fixed_len(), ForkName::Electra => <LightClientOptimisticUpdateElectra<E> as Encode>::ssz_fixed_len(),
ForkName::EIP7732 => todo!("EIP-7732 light client not implemented"),
}; };
fixed_len + LightClientHeader::<E>::ssz_max_var_len_for_fork(fork_name) fixed_len + LightClientHeader::<E>::ssz_max_var_len_for_fork(fork_name)
} }

View File

@@ -286,8 +286,9 @@ impl<E: EthSpec> LightClientUpdate<E> {
signature_slot: block_slot, signature_slot: block_slot,
}) })
} // To add a new fork, just append the new fork variant on the latest fork. Forks that } // To add a new fork, just append the new fork variant on the latest fork. Forks that
// have a distinct execution header will need a new LightClientUpdate variant only // have a distinct execution header will need a new LightClientUpdate variant only
// if you need to test or support lightclient usages // if you need to test or support lightclient usages
ForkName::EIP7732 => todo!("EIP-7732 light client not implemented"),
}; };
Ok(light_client_update) Ok(light_client_update)
@@ -306,6 +307,7 @@ impl<E: EthSpec> LightClientUpdate<E> {
"LightClientUpdate decoding for {fork_name} not implemented" "LightClientUpdate decoding for {fork_name} not implemented"
))) )))
} }
ForkName::EIP7732 => todo!("EIP-7732 light client not implemented"),
}; };
Ok(update) Ok(update)
@@ -445,6 +447,7 @@ impl<E: EthSpec> LightClientUpdate<E> {
ForkName::Capella => <LightClientUpdateCapella<E> as Encode>::ssz_fixed_len(), ForkName::Capella => <LightClientUpdateCapella<E> as Encode>::ssz_fixed_len(),
ForkName::Deneb => <LightClientUpdateDeneb<E> as Encode>::ssz_fixed_len(), ForkName::Deneb => <LightClientUpdateDeneb<E> as Encode>::ssz_fixed_len(),
ForkName::Electra => <LightClientUpdateElectra<E> as Encode>::ssz_fixed_len(), ForkName::Electra => <LightClientUpdateElectra<E> as Encode>::ssz_fixed_len(),
ForkName::EIP7732 => todo!("EIP-7732 light client not implemented"),
}; };
fixed_len + 2 * LightClientHeader::<E>::ssz_max_var_len_for_fork(fork_name) fixed_len + 2 * LightClientHeader::<E>::ssz_max_var_len_for_fork(fork_name)
} }

View File

@@ -305,6 +305,7 @@ impl<E: EthSpec> FullPayload<E> {
ForkName::Capella => Ok(FullPayloadCapella::default().into()), ForkName::Capella => Ok(FullPayloadCapella::default().into()),
ForkName::Deneb => Ok(FullPayloadDeneb::default().into()), ForkName::Deneb => Ok(FullPayloadDeneb::default().into()),
ForkName::Electra => Ok(FullPayloadElectra::default().into()), ForkName::Electra => Ok(FullPayloadElectra::default().into()),
ForkName::EIP7732 => Err(Error::IncorrectStateVariant),
} }
} }
} }

View File

@@ -38,7 +38,7 @@ impl From<SignedBeaconBlockHash> for Hash256 {
/// A `BeaconBlock` and a signature from its proposer. /// A `BeaconBlock` and a signature from its proposer.
#[superstruct( #[superstruct(
variants(Base, Altair, Bellatrix, Capella, Deneb, Electra), variants(Base, Altair, Bellatrix, Capella, Deneb, Electra, EIP7732),
variant_attributes( variant_attributes(
derive( derive(
Debug, Debug,
@@ -81,6 +81,8 @@ pub struct SignedBeaconBlock<E: EthSpec, Payload: AbstractExecPayload<E> = FullP
pub message: BeaconBlockDeneb<E, Payload>, pub message: BeaconBlockDeneb<E, Payload>,
#[superstruct(only(Electra), partial_getter(rename = "message_electra"))] #[superstruct(only(Electra), partial_getter(rename = "message_electra"))]
pub message: BeaconBlockElectra<E, Payload>, pub message: BeaconBlockElectra<E, Payload>,
#[superstruct(only(EIP7732), partial_getter(rename = "message_eip7732"))]
pub message: BeaconBlockEIP7732<E, Payload>,
pub signature: Signature, pub signature: Signature,
} }
@@ -163,6 +165,9 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> SignedBeaconBlock<E, Payload>
BeaconBlock::Electra(message) => { BeaconBlock::Electra(message) => {
SignedBeaconBlock::Electra(SignedBeaconBlockElectra { message, signature }) SignedBeaconBlock::Electra(SignedBeaconBlockElectra { message, signature })
} }
BeaconBlock::EIP7732(message) => {
SignedBeaconBlock::EIP7732(SignedBeaconBlockEIP7732 { message, signature })
}
} }
} }
@@ -570,6 +575,19 @@ impl<E: EthSpec> SignedBeaconBlockElectra<E, BlindedPayload<E>> {
} }
} }
// We can convert post-EIP7732 blocks without payloads into blocks "with" payloads.
impl<E: EthSpec> From<SignedBeaconBlockEIP7732<E, BlindedPayload<E>>>
for SignedBeaconBlockEIP7732<E, FullPayload<E>>
{
fn from(signed_block: SignedBeaconBlockEIP7732<E, BlindedPayload<E>>) -> Self {
let SignedBeaconBlockEIP7732 { message, signature } = signed_block;
SignedBeaconBlockEIP7732 {
message: message.into(),
signature,
}
}
}
impl<E: EthSpec> SignedBeaconBlock<E, BlindedPayload<E>> { impl<E: EthSpec> SignedBeaconBlock<E, BlindedPayload<E>> {
pub fn try_into_full_block( pub fn try_into_full_block(
self, self,
@@ -590,6 +608,7 @@ impl<E: EthSpec> SignedBeaconBlock<E, BlindedPayload<E>> {
(SignedBeaconBlock::Electra(block), Some(ExecutionPayload::Electra(payload))) => { (SignedBeaconBlock::Electra(block), Some(ExecutionPayload::Electra(payload))) => {
SignedBeaconBlock::Electra(block.into_full_block(payload)) SignedBeaconBlock::Electra(block.into_full_block(payload))
} }
(SignedBeaconBlock::EIP7732(block), _) => SignedBeaconBlock::EIP7732(block.into()),
// avoid wildcard matching forks so that compiler will // avoid wildcard matching forks so that compiler will
// direct us here when a new fork has been added // direct us here when a new fork has been added
(SignedBeaconBlock::Bellatrix(_), _) => return None, (SignedBeaconBlock::Bellatrix(_), _) => return None,
@@ -741,6 +760,9 @@ pub mod ssz_tagged_signed_beacon_block {
ForkName::Electra => Ok(SignedBeaconBlock::Electra( ForkName::Electra => Ok(SignedBeaconBlock::Electra(
SignedBeaconBlockElectra::from_ssz_bytes(body)?, SignedBeaconBlockElectra::from_ssz_bytes(body)?,
)), )),
ForkName::EIP7732 => Ok(SignedBeaconBlock::EIP7732(
SignedBeaconBlockEIP7732::from_ssz_bytes(body)?,
)),
} }
} }
} }
@@ -843,6 +865,10 @@ mod test {
BeaconBlock::Electra(BeaconBlockElectra::empty(spec)), BeaconBlock::Electra(BeaconBlockElectra::empty(spec)),
sig, sig,
), ),
SignedBeaconBlock::from_block(
BeaconBlock::EIP7732(BeaconBlockEIP7732::empty(spec)),
sig,
),
]; ];
for block in blocks { for block in blocks {

View File

@@ -2,7 +2,6 @@ use serde::Deserialize;
use ssz::Encode; use ssz::Encode;
use ssz_derive::{Decode, Encode}; use ssz_derive::{Decode, Encode};
use std::fmt::Debug; use std::fmt::Debug;
use types::ForkName;
/// Macro to wrap U128 and U256 so they deserialize correctly. /// Macro to wrap U128 and U256 so they deserialize correctly.
macro_rules! uint_wrapper { macro_rules! uint_wrapper {
@@ -57,18 +56,6 @@ impl<T> SszStaticType for T where
{ {
} }
/// Return the fork immediately prior to a fork.
pub fn previous_fork(fork_name: ForkName) -> ForkName {
match fork_name {
ForkName::Base => ForkName::Base,
ForkName::Altair => ForkName::Base,
ForkName::Bellatrix => ForkName::Altair,
ForkName::Capella => ForkName::Bellatrix,
ForkName::Deneb => ForkName::Capella,
ForkName::Electra => ForkName::Deneb,
}
}
#[macro_export] #[macro_export]
macro_rules! impl_bls_load_case { macro_rules! impl_bls_load_case {
($case_name:ident) => { ($case_name:ident) => {

View File

@@ -117,7 +117,8 @@ impl<E: EthSpec> EpochTransition<E> for JustificationAndFinalization {
| BeaconState::Bellatrix(_) | BeaconState::Bellatrix(_)
| BeaconState::Capella(_) | BeaconState::Capella(_)
| BeaconState::Deneb(_) | BeaconState::Deneb(_)
| BeaconState::Electra(_) => { | BeaconState::Electra(_)
| BeaconState::EIP7732(_) => {
initialize_progressive_balances_cache(state, spec)?; initialize_progressive_balances_cache(state, spec)?;
let justification_and_finalization_state = let justification_and_finalization_state =
altair::process_justification_and_finalization(state)?; altair::process_justification_and_finalization(state)?;
@@ -140,7 +141,8 @@ impl<E: EthSpec> EpochTransition<E> for RewardsAndPenalties {
| BeaconState::Bellatrix(_) | BeaconState::Bellatrix(_)
| BeaconState::Capella(_) | BeaconState::Capella(_)
| BeaconState::Deneb(_) | BeaconState::Deneb(_)
| BeaconState::Electra(_) => altair::process_rewards_and_penalties_slow(state, spec), | BeaconState::Electra(_)
| BeaconState::EIP7732(_) => altair::process_rewards_and_penalties_slow(state, spec),
} }
} }
} }
@@ -173,7 +175,8 @@ impl<E: EthSpec> EpochTransition<E> for Slashings {
| BeaconState::Bellatrix(_) | BeaconState::Bellatrix(_)
| BeaconState::Capella(_) | BeaconState::Capella(_)
| BeaconState::Deneb(_) | BeaconState::Deneb(_)
| BeaconState::Electra(_) => { | BeaconState::Electra(_)
| BeaconState::EIP7732(_) => {
process_slashings_slow(state, spec)?; process_slashings_slow(state, spec)?;
} }
}; };
@@ -278,7 +281,8 @@ impl<E: EthSpec> EpochTransition<E> for SyncCommitteeUpdates {
| BeaconState::Bellatrix(_) | BeaconState::Bellatrix(_)
| BeaconState::Capella(_) | BeaconState::Capella(_)
| BeaconState::Deneb(_) | BeaconState::Deneb(_)
| BeaconState::Electra(_) => altair::process_sync_committee_updates(state, spec), | BeaconState::Electra(_)
| BeaconState::EIP7732(_) => altair::process_sync_committee_updates(state, spec),
} }
} }
} }
@@ -291,7 +295,8 @@ impl<E: EthSpec> EpochTransition<E> for InactivityUpdates {
| BeaconState::Bellatrix(_) | BeaconState::Bellatrix(_)
| BeaconState::Capella(_) | BeaconState::Capella(_)
| BeaconState::Deneb(_) | BeaconState::Deneb(_)
| BeaconState::Electra(_) => altair::process_inactivity_updates_slow(state, spec), | BeaconState::Electra(_)
| BeaconState::EIP7732(_) => altair::process_inactivity_updates_slow(state, spec),
} }
} }
} }
@@ -304,7 +309,8 @@ impl<E: EthSpec> EpochTransition<E> for ParticipationFlagUpdates {
| BeaconState::Bellatrix(_) | BeaconState::Bellatrix(_)
| BeaconState::Capella(_) | BeaconState::Capella(_)
| BeaconState::Deneb(_) | BeaconState::Deneb(_)
| BeaconState::Electra(_) => altair::process_participation_flag_updates(state), | BeaconState::Electra(_)
| BeaconState::EIP7732(_) => altair::process_participation_flag_updates(state),
} }
} }
} }

View File

@@ -1,6 +1,5 @@
use super::*; use super::*;
use crate::case_result::compare_beacon_state_results_without_caches; use crate::case_result::compare_beacon_state_results_without_caches;
use crate::cases::common::previous_fork;
use crate::decode::{ssz_decode_state, yaml_decode_file}; use crate::decode::{ssz_decode_state, yaml_decode_file};
use serde::Deserialize; use serde::Deserialize;
use state_processing::upgrade::{ use state_processing::upgrade::{
@@ -33,8 +32,11 @@ impl<E: EthSpec> LoadCase for ForkTest<E> {
assert_eq!(metadata.fork_name(), fork_name); assert_eq!(metadata.fork_name(), fork_name);
// Decode pre-state with previous fork. // Decode pre-state with previous fork.
let pre_spec = &previous_fork(fork_name).make_genesis_spec(E::default_spec()); let pre_spec = fork_name
let pre = ssz_decode_state(&path.join("pre.ssz_snappy"), pre_spec)?; .previous_fork()
.unwrap_or(ForkName::Base)
.make_genesis_spec(E::default_spec());
let pre = ssz_decode_state(&path.join("pre.ssz_snappy"), &pre_spec)?;
// Decode post-state with target fork. // Decode post-state with target fork.
let post_spec = &fork_name.make_genesis_spec(E::default_spec()); let post_spec = &fork_name.make_genesis_spec(E::default_spec());
@@ -69,6 +71,7 @@ impl<E: EthSpec> Case for ForkTest<E> {
ForkName::Capella => upgrade_to_capella(&mut result_state, spec).map(|_| result_state), ForkName::Capella => upgrade_to_capella(&mut result_state, spec).map(|_| result_state),
ForkName::Deneb => upgrade_to_deneb(&mut result_state, spec).map(|_| result_state), ForkName::Deneb => upgrade_to_deneb(&mut result_state, spec).map(|_| result_state),
ForkName::Electra => upgrade_to_electra(&mut result_state, spec).map(|_| result_state), ForkName::Electra => upgrade_to_electra(&mut result_state, spec).map(|_| result_state),
ForkName::EIP7732 => todo!("upgrade_to_eip7732 not yet implemented"),
}; };
compare_beacon_state_results_without_caches(&mut result, &mut expected) compare_beacon_state_results_without_caches(&mut result, &mut expected)

View File

@@ -4,7 +4,8 @@ use serde::Deserialize;
use tree_hash::Hash256; use tree_hash::Hash256;
use types::{ use types::{
light_client_update, BeaconBlockBody, BeaconBlockBodyCapella, BeaconBlockBodyDeneb, light_client_update, BeaconBlockBody, BeaconBlockBodyCapella, BeaconBlockBodyDeneb,
BeaconBlockBodyElectra, BeaconState, FixedVector, FullPayload, Unsigned, BeaconBlockBodyEIP7732, BeaconBlockBodyElectra, BeaconState, FixedVector, FullPayload,
Unsigned,
}; };
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize)]
@@ -131,6 +132,11 @@ impl<E: EthSpec> LoadCase for KzgInclusionMerkleProofValidity<E> {
ssz_decode_file::<BeaconBlockBodyElectra<E>>(&path.join("object.ssz_snappy"))? ssz_decode_file::<BeaconBlockBodyElectra<E>>(&path.join("object.ssz_snappy"))?
.into() .into()
} }
// TODO(EIP7732): check this
ForkName::EIP7732 => {
ssz_decode_file::<BeaconBlockBodyEIP7732<E>>(&path.join("object.ssz_snappy"))?
.into()
}
}; };
let merkle_proof = yaml_decode_file(&path.join("proof.yaml"))?; let merkle_proof = yaml_decode_file(&path.join("proof.yaml"))?;
// Metadata does not exist in these tests but it is left like this just in case. // Metadata does not exist in these tests but it is left like this just in case.
@@ -246,6 +252,10 @@ impl<E: EthSpec> LoadCase for BeaconBlockBodyMerkleProofValidity<E> {
ssz_decode_file::<BeaconBlockBodyElectra<E>>(&path.join("object.ssz_snappy"))? ssz_decode_file::<BeaconBlockBodyElectra<E>>(&path.join("object.ssz_snappy"))?
.into() .into()
} }
ForkName::EIP7732 => {
ssz_decode_file::<BeaconBlockBodyEIP7732<E>>(&path.join("object.ssz_snappy"))?
.into()
}
}; };
let merkle_proof = yaml_decode_file(&path.join("proof.yaml"))?; let merkle_proof = yaml_decode_file(&path.join("proof.yaml"))?;
// Metadata does not exist in these tests but it is left like this just in case. // Metadata does not exist in these tests but it is left like this just in case.

View File

@@ -24,9 +24,9 @@ use state_processing::{
use std::fmt::Debug; use std::fmt::Debug;
use types::{ use types::{
Attestation, AttesterSlashing, BeaconBlock, BeaconBlockBody, BeaconBlockBodyBellatrix, Attestation, AttesterSlashing, BeaconBlock, BeaconBlockBody, BeaconBlockBodyBellatrix,
BeaconBlockBodyCapella, BeaconBlockBodyDeneb, BeaconBlockBodyElectra, BeaconState, BeaconBlockBodyCapella, BeaconBlockBodyDeneb, BeaconBlockBodyEIP7732, BeaconBlockBodyElectra,
BlindedPayload, ConsolidationRequest, Deposit, DepositRequest, ExecutionPayload, FullPayload, BeaconState, BlindedPayload, ConsolidationRequest, Deposit, DepositRequest, ExecutionPayload,
ProposerSlashing, SignedBlsToExecutionChange, SignedVoluntaryExit, SyncAggregate, FullPayload, ProposerSlashing, SignedBlsToExecutionChange, SignedVoluntaryExit, SyncAggregate,
WithdrawalRequest, WithdrawalRequest,
}; };
@@ -110,7 +110,8 @@ impl<E: EthSpec> Operation<E> for Attestation<E> {
| BeaconState::Bellatrix(_) | BeaconState::Bellatrix(_)
| BeaconState::Capella(_) | BeaconState::Capella(_)
| BeaconState::Deneb(_) | BeaconState::Deneb(_)
| BeaconState::Electra(_) => { | BeaconState::Electra(_)
| BeaconState::EIP7732(_) => {
initialize_progressive_balances_cache(state, spec)?; initialize_progressive_balances_cache(state, spec)?;
altair_deneb::process_attestation( altair_deneb::process_attestation(
state, state,
@@ -137,7 +138,7 @@ impl<E: EthSpec> Operation<E> for AttesterSlashing<E> {
| ForkName::Bellatrix | ForkName::Bellatrix
| ForkName::Capella | ForkName::Capella
| ForkName::Deneb => Self::Base(ssz_decode_file(path)?), | ForkName::Deneb => Self::Base(ssz_decode_file(path)?),
ForkName::Electra => Self::Electra(ssz_decode_file(path)?), ForkName::Electra | ForkName::EIP7732 => Self::Electra(ssz_decode_file(path)?),
}) })
} }
@@ -308,6 +309,7 @@ impl<E: EthSpec> Operation<E> for BeaconBlockBody<E, FullPayload<E>> {
ForkName::Capella => BeaconBlockBody::Capella(<_>::from_ssz_bytes(bytes)?), ForkName::Capella => BeaconBlockBody::Capella(<_>::from_ssz_bytes(bytes)?),
ForkName::Deneb => BeaconBlockBody::Deneb(<_>::from_ssz_bytes(bytes)?), ForkName::Deneb => BeaconBlockBody::Deneb(<_>::from_ssz_bytes(bytes)?),
ForkName::Electra => BeaconBlockBody::Electra(<_>::from_ssz_bytes(bytes)?), ForkName::Electra => BeaconBlockBody::Electra(<_>::from_ssz_bytes(bytes)?),
ForkName::EIP7732 => BeaconBlockBody::EIP7732(<_>::from_ssz_bytes(bytes)?),
_ => panic!(), _ => panic!(),
}) })
}) })
@@ -363,6 +365,10 @@ impl<E: EthSpec> Operation<E> for BeaconBlockBody<E, BlindedPayload<E>> {
let inner = <BeaconBlockBodyElectra<E, FullPayload<E>>>::from_ssz_bytes(bytes)?; let inner = <BeaconBlockBodyElectra<E, FullPayload<E>>>::from_ssz_bytes(bytes)?;
BeaconBlockBody::Electra(inner.clone_as_blinded()) BeaconBlockBody::Electra(inner.clone_as_blinded())
} }
ForkName::EIP7732 => {
let inner = <BeaconBlockBodyEIP7732<E, FullPayload<E>>>::from_ssz_bytes(bytes)?;
BeaconBlockBody::EIP7732(inner.clone_as_blinded())
}
_ => panic!(), _ => panic!(),
}) })
}) })

View File

@@ -60,6 +60,14 @@ impl<E: EthSpec> LoadCase for TransitionTest<E> {
spec.deneb_fork_epoch = Some(Epoch::new(0)); spec.deneb_fork_epoch = Some(Epoch::new(0));
spec.electra_fork_epoch = Some(metadata.fork_epoch); spec.electra_fork_epoch = Some(metadata.fork_epoch);
} }
ForkName::EIP7732 => {
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.deneb_fork_epoch = Some(Epoch::new(0));
spec.electra_fork_epoch = Some(Epoch::new(0));
spec.eip7732_fork_epoch = Some(metadata.fork_epoch);
}
} }
// Load blocks // Load blocks

View File

@@ -29,6 +29,7 @@ pub enum ForkName {
Capella, Capella,
Deneb, Deneb,
Electra, Electra,
EIP7732,
} }
#[derive(Debug, PartialEq, Serialize)] #[derive(Debug, PartialEq, Serialize)]
@@ -107,6 +108,11 @@ impl<'a, E: EthSpec, Payload: AbstractExecPayload<E>> Web3SignerObject<'a, E, Pa
block: None, block: None,
block_header: Some(block.block_header()), block_header: Some(block.block_header()),
}), }),
BeaconBlock::EIP7732(_) => Ok(Web3SignerObject::BeaconBlock {
version: ForkName::EIP7732,
block: None,
block_header: Some(block.block_header()),
}),
} }
} }