diff --git a/beacon_node/beacon_chain/src/beacon_chain.rs b/beacon_node/beacon_chain/src/beacon_chain.rs index bbbae1365a..ab3064f6f1 100644 --- a/beacon_node/beacon_chain/src/beacon_chain.rs +++ b/beacon_node/beacon_chain/src/beacon_chain.rs @@ -743,6 +743,7 @@ impl BeaconChain { if let Ok(current_fork) = self.current_fork() { current_fork.has_feature(feature) } else { + // TODO(superstruct_features): Is this safe? false } } @@ -5574,13 +5575,6 @@ impl BeaconChain { None }; - //let parent_beacon_block_root = match prepare_slot_fork { - // ForkName::Base | ForkName::Altair | ForkName::Bellatrix | ForkName::Capella => None, - // ForkName::Deneb | ForkName::Electra => { - // Some(pre_payload_attributes.parent_beacon_block_root) - // } - //}; - let payload_attributes = PayloadAttributes::new( self.slot_clock .start_of(prepare_slot) @@ -6616,17 +6610,12 @@ impl BeaconChain { .fork_name(&self.spec) .map_err(Error::InconsistentFork)?; - match fork_name { - ForkName::Altair - | ForkName::Bellatrix - | ForkName::Capella - | ForkName::Deneb - | ForkName::Electra => { - LightClientBootstrap::from_beacon_state(&mut state, &block, &self.spec) - .map(|bootstrap| Some((bootstrap, fork_name))) - .map_err(Error::LightClientError) - } - ForkName::Base => Err(Error::UnsupportedFork), + if fork_name.has_feature(FeatureName::Altair) { + LightClientBootstrap::from_beacon_state(&mut state, &block, &self.spec) + .map(|bootstrap| Some((bootstrap, fork_name))) + .map_err(Error::LightClientError) + } else { + Err(Error::UnsupportedFork) } } } diff --git a/beacon_node/beacon_chain/src/test_utils.rs b/beacon_node/beacon_chain/src/test_utils.rs index 8fbd5d575f..ba5b3bda33 100644 --- a/beacon_node/beacon_chain/src/test_utils.rs +++ b/beacon_node/beacon_chain/src/test_utils.rs @@ -877,15 +877,12 @@ where &self.spec, )); - let block_contents: SignedBlockContentsTuple = match *signed_block { - SignedBeaconBlock::Base(_) - | SignedBeaconBlock::Altair(_) - | SignedBeaconBlock::Bellatrix(_) - | SignedBeaconBlock::Capella(_) => (signed_block, None), - SignedBeaconBlock::Deneb(_) | SignedBeaconBlock::Electra(_) => { + let block_contents: SignedBlockContentsTuple = + if signed_block.has_feature(FeatureName::Deneb) { (signed_block, block_response.blob_items) - } - }; + } else { + (signed_block, None) + }; (block_contents, block_response.state) } @@ -941,15 +938,13 @@ where &self.spec, )); - let block_contents: SignedBlockContentsTuple = match *signed_block { - SignedBeaconBlock::Base(_) - | SignedBeaconBlock::Altair(_) - | SignedBeaconBlock::Bellatrix(_) - | SignedBeaconBlock::Capella(_) => (signed_block, None), - SignedBeaconBlock::Deneb(_) | SignedBeaconBlock::Electra(_) => { + let block_contents: SignedBlockContentsTuple = + if signed_block.has_feature(FeatureName::Deneb) { (signed_block, block_response.blob_items) - } - }; + } else { + (signed_block, None) + }; + (block_contents, pre_state) } diff --git a/beacon_node/beacon_chain/tests/attestation_verification.rs b/beacon_node/beacon_chain/tests/attestation_verification.rs index 1463d1c5c1..692d7d9ad2 100644 --- a/beacon_node/beacon_chain/tests/attestation_verification.rs +++ b/beacon_node/beacon_chain/tests/attestation_verification.rs @@ -20,7 +20,7 @@ use state_processing::{ use tree_hash::TreeHash; use types::{ test_utils::generate_deterministic_keypair, Address, AggregateSignature, Attestation, - BeaconStateError, BitList, ChainSpec, Epoch, EthSpec, ForkName, Hash256, Keypair, + BeaconStateError, BitList, ChainSpec, Epoch, EthSpec, FeatureName, ForkName, Hash256, Keypair, MainnetEthSpec, SecretKey, SelectionProof, SignedAggregateAndProof, Slot, SubnetId, Unsigned, }; @@ -335,22 +335,22 @@ impl GossipTester { } pub fn earliest_valid_attestation_slot(&self) -> Slot { - let offset = match self.harness.spec.fork_name_at_epoch(self.epoch()) { - ForkName::Base | ForkName::Altair | ForkName::Bellatrix | ForkName::Capella => { - // Subtract an additional slot since the harness will be exactly on the start of the - // slot and the propagation tolerance will allow an extra slot. - E::slots_per_epoch() + 1 - } - // EIP-7045 - ForkName::Deneb | ForkName::Electra => { - let epoch_slot_offset = (self.slot() % E::slots_per_epoch()).as_u64(); - if epoch_slot_offset != 0 { - E::slots_per_epoch() + epoch_slot_offset - } else { - // Here the propagation tolerance will cause the cutoff to be an entire epoch earlier - 2 * E::slots_per_epoch() - } + let offset = if self + .harness + .spec + .fork_name_at_epoch(self.epoch()) + .has_feature(FeatureName::Deneb) + { + //EIP-7045 + let epoch_slot_offset = (self.slot() % E::slots_per_epoch()).as_u64(); + if epoch_slot_offset != 0 { + E::slots_per_epoch() + epoch_slot_offset + } else { + // Here the propagation tolerance will cause the cutoff to be an entire epoch earlier + 2 * E::slots_per_epoch() } + } else { + E::slots_per_epoch() + 1 }; self.slot() diff --git a/beacon_node/execution_layer/src/engine_api/http.rs b/beacon_node/execution_layer/src/engine_api/http.rs index 85ef3a0d92..482f67f6e4 100644 --- a/beacon_node/execution_layer/src/engine_api/http.rs +++ b/beacon_node/execution_layer/src/engine_api/http.rs @@ -884,30 +884,34 @@ impl HttpJsonRpc { ) -> Result, Error> { let params = json!([JsonPayloadIdRequest::from(payload_id)]); - match fork_name { - ForkName::Bellatrix => { - let response: JsonGetPayloadResponseV1 = self - .rpc_request( - ENGINE_GET_PAYLOAD_V2, - params, - ENGINE_GET_PAYLOAD_TIMEOUT * self.execution_timeout_multiplier, - ) - .await?; - Ok(JsonGetPayloadResponse::V1(response).into()) - } - ForkName::Capella => { - let response: JsonGetPayloadResponseV2 = self - .rpc_request( - ENGINE_GET_PAYLOAD_V2, - params, - ENGINE_GET_PAYLOAD_TIMEOUT * self.execution_timeout_multiplier, - ) - .await?; - Ok(JsonGetPayloadResponse::V2(response).into()) - } - ForkName::Base | ForkName::Altair | ForkName::Deneb | ForkName::Electra => Err( - Error::UnsupportedForkVariant(format!("called get_payload_v2 with {}", fork_name)), - ), + if fork_name.has_feature(FeatureName::Deneb) { + Err(Error::UnsupportedForkVariant(format!( + "called get_payload_v2 with {}", + fork_name + ))) + } else if fork_name.has_feature(FeatureName::Capella) { + let response: JsonGetPayloadResponseV2 = self + .rpc_request( + ENGINE_GET_PAYLOAD_V2, + params, + ENGINE_GET_PAYLOAD_TIMEOUT * self.execution_timeout_multiplier, + ) + .await?; + Ok(JsonGetPayloadResponse::V2(response).into()) + } else if fork_name.has_feature(FeatureName::Bellatrix) { + let response: JsonGetPayloadResponseV1 = self + .rpc_request( + ENGINE_GET_PAYLOAD_V2, + params, + ENGINE_GET_PAYLOAD_TIMEOUT * self.execution_timeout_multiplier, + ) + .await?; + Ok(JsonGetPayloadResponse::V1(response).into()) + } else { + Err(Error::UnsupportedForkVariant(format!( + "called get_payload_v2 with {}", + fork_name + ))) } } @@ -918,30 +922,29 @@ impl HttpJsonRpc { ) -> Result, Error> { let params = json!([JsonPayloadIdRequest::from(payload_id)]); - match fork_name { - ForkName::Deneb => { - let response: JsonGetPayloadResponseV3 = self - .rpc_request( - ENGINE_GET_PAYLOAD_V3, - params, - ENGINE_GET_PAYLOAD_TIMEOUT * self.execution_timeout_multiplier, - ) - .await?; - Ok(JsonGetPayloadResponse::V3(response).into()) - } - ForkName::Electra => { - let response: JsonGetPayloadResponseV4 = self - .rpc_request( - ENGINE_GET_PAYLOAD_V3, - params, - ENGINE_GET_PAYLOAD_TIMEOUT * self.execution_timeout_multiplier, - ) - .await?; - Ok(JsonGetPayloadResponse::V4(response).into()) - } - ForkName::Base | ForkName::Altair | ForkName::Bellatrix | ForkName::Capella => Err( - Error::UnsupportedForkVariant(format!("called get_payload_v3 with {}", fork_name)), - ), + if fork_name.has_feature(FeatureName::Electra) { + let response: JsonGetPayloadResponseV4 = self + .rpc_request( + ENGINE_GET_PAYLOAD_V3, + params, + ENGINE_GET_PAYLOAD_TIMEOUT * self.execution_timeout_multiplier, + ) + .await?; + Ok(JsonGetPayloadResponse::V4(response).into()) + } else if fork_name.has_feature(FeatureName::Deneb) { + let response: JsonGetPayloadResponseV3 = self + .rpc_request( + ENGINE_GET_PAYLOAD_V3, + params, + ENGINE_GET_PAYLOAD_TIMEOUT * self.execution_timeout_multiplier, + ) + .await?; + Ok(JsonGetPayloadResponse::V3(response).into()) + } else { + Err(Error::UnsupportedForkVariant(format!( + "called get_payload_v3 with {}", + fork_name + ))) } } diff --git a/beacon_node/http_api/src/build_block_contents.rs b/beacon_node/http_api/src/build_block_contents.rs index 05a6735b32..be7e443955 100644 --- a/beacon_node/http_api/src/build_block_contents.rs +++ b/beacon_node/http_api/src/build_block_contents.rs @@ -1,6 +1,6 @@ use beacon_chain::{BeaconBlockResponse, BeaconBlockResponseWrapper, BlockProductionError}; use eth2::types::{BlockContents, FullBlockContents, ProduceBlockV3Response}; -use types::{EthSpec, ForkName}; +use types::{EthSpec, FeatureName, ForkName}; type Error = warp::reject::Rejection; pub fn build_block_contents( @@ -11,11 +11,8 @@ pub fn build_block_contents( BeaconBlockResponseWrapper::Blinded(block) => { Ok(ProduceBlockV3Response::Blinded(block.block)) } - BeaconBlockResponseWrapper::Full(block) => match fork_name { - ForkName::Base | ForkName::Altair | ForkName::Bellatrix | ForkName::Capella => Ok( - ProduceBlockV3Response::Full(FullBlockContents::Block(block.block)), - ), - ForkName::Deneb | ForkName::Electra => { + BeaconBlockResponseWrapper::Full(block) => { + if fork_name.has_feature(FeatureName::Deneb) { let BeaconBlockResponse { block, state: _, @@ -37,7 +34,11 @@ pub fn build_block_contents( blobs, }), )) + } else { + Ok(ProduceBlockV3Response::Full(FullBlockContents::Block( + block.block, + ))) } - }, + } } } diff --git a/beacon_node/http_api/src/publish_blocks.rs b/beacon_node/http_api/src/publish_blocks.rs index 0d176e6a53..2eaab0ef44 100644 --- a/beacon_node/http_api/src/publish_blocks.rs +++ b/beacon_node/http_api/src/publish_blocks.rs @@ -20,7 +20,7 @@ use tokio::sync::mpsc::UnboundedSender; use tree_hash::TreeHash; use types::{ AbstractExecPayload, BeaconBlockRef, BlobSidecarList, EthSpec, ExecPayload, ExecutionBlockHash, - ForkName, FullPayload, FullPayloadBellatrix, Hash256, SignedBeaconBlock, + FeatureName, ForkName, FullPayload, FullPayloadBellatrix, Hash256, SignedBeaconBlock, SignedBlindedBeaconBlock, VariableList, }; use warp::http::StatusCode; @@ -77,28 +77,22 @@ pub async fn publish_block block.slot(), "publish_delay" => ?publish_delay); - match block.as_ref() { - SignedBeaconBlock::Base(_) - | SignedBeaconBlock::Altair(_) - | SignedBeaconBlock::Bellatrix(_) - | SignedBeaconBlock::Capella(_) => { - crate::publish_pubsub_message(&sender, PubsubMessage::BeaconBlock(block)) - .map_err(|_| BlockError::BeaconChainError(BeaconChainError::UnableToPublish))?; - } - SignedBeaconBlock::Deneb(_) | SignedBeaconBlock::Electra(_) => { - let mut pubsub_messages = vec![PubsubMessage::BeaconBlock(block)]; - if let Some(blob_sidecars) = blobs_opt { - for (blob_index, blob) in blob_sidecars.into_iter().enumerate() { - pubsub_messages.push(PubsubMessage::BlobSidecar(Box::new(( - blob_index as u64, - blob, - )))); - } + if block.has_feature(FeatureName::Deneb) { + let mut pubsub_messages = vec![PubsubMessage::BeaconBlock(block)]; + if let Some(blob_sidecars) = blobs_opt { + for (blob_index, blob) in blob_sidecars.into_iter().enumerate() { + pubsub_messages.push(PubsubMessage::BlobSidecar(Box::new(( + blob_index as u64, + blob, + )))); } - crate::publish_pubsub_messages(&sender, pubsub_messages) - .map_err(|_| BlockError::BeaconChainError(BeaconChainError::UnableToPublish))?; } - }; + crate::publish_pubsub_messages(&sender, pubsub_messages) + .map_err(|_| BlockError::BeaconChainError(BeaconChainError::UnableToPublish))?; + } else { + crate::publish_pubsub_message(&sender, PubsubMessage::BeaconBlock(block)) + .map_err(|_| BlockError::BeaconChainError(BeaconChainError::UnableToPublish))?; + } Ok(()) }; diff --git a/beacon_node/network/src/sync/range_sync/range.rs b/beacon_node/network/src/sync/range_sync/range.rs index c8e8266684..ff8582c694 100644 --- a/beacon_node/network/src/sync/range_sync/range.rs +++ b/beacon_node/network/src/sync/range_sync/range.rs @@ -397,7 +397,7 @@ mod tests { use std::collections::HashSet; use store::MemoryStore; use tokio::sync::mpsc; - use types::{ForkName, MinimalEthSpec as E}; + use types::{FeatureName, ForkName, MinimalEthSpec as E}; #[derive(Debug)] struct FakeStorage { @@ -529,21 +529,20 @@ mod tests { } else { panic!("Should have sent a batch request to the peer") }; - let blob_req_id = match fork_name { - ForkName::Deneb | ForkName::Electra => { - if let Ok(NetworkMessage::SendRequest { - peer_id, - request: _, - request_id, - }) = self.network_rx.try_recv() - { - assert_eq!(&peer_id, expected_peer); - Some(request_id) - } else { - panic!("Should have sent a batch request to the peer") - } + let blob_req_id = if fork_name.has_feature(FeatureName::Deneb) { + if let Ok(NetworkMessage::SendRequest { + peer_id, + request: _, + request_id, + }) = self.network_rx.try_recv() + { + assert_eq!(&peer_id, expected_peer); + Some(request_id) + } else { + panic!("Should have sent a batch request to the peer") } - _ => None, + } else { + None }; (block_req_id, blob_req_id) } diff --git a/consensus/fork_choice/src/fork_choice.rs b/consensus/fork_choice/src/fork_choice.rs index 2846a0112c..08d8ee3a2c 100644 --- a/consensus/fork_choice/src/fork_choice.rs +++ b/consensus/fork_choice/src/fork_choice.rs @@ -15,8 +15,8 @@ use std::time::Duration; use types::{ consts::bellatrix::INTERVALS_PER_SLOT, AbstractExecPayload, AttestationShufflingId, AttesterSlashing, BeaconBlockRef, BeaconState, BeaconStateError, ChainSpec, Checkpoint, Epoch, - EthSpec, ExecPayload, ExecutionBlockHash, Hash256, IndexedAttestation, RelativeEpoch, - SignedBeaconBlock, Slot, + EthSpec, ExecPayload, ExecutionBlockHash, FeatureName, Hash256, IndexedAttestation, + RelativeEpoch, SignedBeaconBlock, Slot, }; #[derive(Debug)] @@ -747,20 +747,15 @@ where if let Some((parent_justified, parent_finalized)) = parent_checkpoints { (parent_justified, parent_finalized) } else { - let justification_and_finalization_state = match block { - BeaconBlockRef::Electra(_) - | BeaconBlockRef::Deneb(_) - | BeaconBlockRef::Capella(_) - | BeaconBlockRef::Bellatrix(_) - | BeaconBlockRef::Altair(_) => { + let justification_and_finalization_state = + if block.fork_name_unchecked().has_feature(FeatureName::Altair) { // NOTE: Processing justification & finalization requires the progressive // balances cache, but we cannot initialize it here as we only have an // immutable reference. The state *should* have come straight from block // processing, which initialises the cache, but if we add other `on_block` // calls in future it could be worth passing a mutable reference. per_epoch_processing::altair::process_justification_and_finalization(state)? - } - BeaconBlockRef::Base(_) => { + } else { let mut validator_statuses = per_epoch_processing::base::ValidatorStatuses::new(state, spec) .map_err(Error::ValidatorStatuses)?; @@ -772,8 +767,7 @@ where &validator_statuses.total_balances, spec, )? - } - }; + }; ( justification_and_finalization_state.current_justified_checkpoint(), diff --git a/consensus/types/src/fork_name.rs b/consensus/types/src/fork_name.rs index 980f26a31d..2a12805941 100644 --- a/consensus/types/src/fork_name.rs +++ b/consensus/types/src/fork_name.rs @@ -50,13 +50,13 @@ impl ForkName { } pub fn list_all_enabled_features(self) -> Vec { - let mut res = vec![]; + let mut all_features = vec![]; for (fork, features) in FORK_ORDER { if *fork <= self { - res.extend(features.iter()); + all_features.extend(features.iter()); } } - res + all_features } pub fn has_feature(self, feature: FeatureName) -> bool { diff --git a/consensus/types/src/signed_beacon_block.rs b/consensus/types/src/signed_beacon_block.rs index 4d3279a7f7..2a3b6f871f 100644 --- a/consensus/types/src/signed_beacon_block.rs +++ b/consensus/types/src/signed_beacon_block.rs @@ -37,7 +37,14 @@ impl From for Hash256 { /// A `BeaconBlock` and a signature from its proposer. #[superstruct( - variants(Base, Altair, Bellatrix, Capella, Deneb, Electra), + variants_and_features_from = "FORK_ORDER", + feature_dependencies = "FEATURE_DEPENDENCIES", + variant_type(name = "ForkName", getter = "fork_name_outer"), + feature_type( + name = "FeatureName", + list = "list_all_features", + check = "has_feature" + ), variant_attributes( derive( Debug,