This commit is contained in:
Mac L
2024-05-02 16:06:28 +10:00
parent 689cdaef61
commit d9a0c3d6c2
10 changed files with 139 additions and 157 deletions

View File

@@ -743,6 +743,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
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<T: BeaconChainTypes> BeaconChain<T> {
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<T: BeaconChainTypes> BeaconChain<T> {
.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)
}
}
}

View File

@@ -877,15 +877,12 @@ where
&self.spec,
));
let block_contents: SignedBlockContentsTuple<E> = match *signed_block {
SignedBeaconBlock::Base(_)
| SignedBeaconBlock::Altair(_)
| SignedBeaconBlock::Bellatrix(_)
| SignedBeaconBlock::Capella(_) => (signed_block, None),
SignedBeaconBlock::Deneb(_) | SignedBeaconBlock::Electra(_) => {
let block_contents: SignedBlockContentsTuple<E> =
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<E> = match *signed_block {
SignedBeaconBlock::Base(_)
| SignedBeaconBlock::Altair(_)
| SignedBeaconBlock::Bellatrix(_)
| SignedBeaconBlock::Capella(_) => (signed_block, None),
SignedBeaconBlock::Deneb(_) | SignedBeaconBlock::Electra(_) => {
let block_contents: SignedBlockContentsTuple<E> =
if signed_block.has_feature(FeatureName::Deneb) {
(signed_block, block_response.blob_items)
}
};
} else {
(signed_block, None)
};
(block_contents, pre_state)
}

View File

@@ -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()

View File

@@ -884,30 +884,34 @@ impl HttpJsonRpc {
) -> Result<GetPayloadResponse<E>, Error> {
let params = json!([JsonPayloadIdRequest::from(payload_id)]);
match fork_name {
ForkName::Bellatrix => {
let response: JsonGetPayloadResponseV1<E> = 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<E> = 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<E> = 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<E> = 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<GetPayloadResponse<E>, Error> {
let params = json!([JsonPayloadIdRequest::from(payload_id)]);
match fork_name {
ForkName::Deneb => {
let response: JsonGetPayloadResponseV3<E> = 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<E> = 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<E> = 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<E> = 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
)))
}
}

View File

@@ -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<E: EthSpec>(
@@ -11,11 +11,8 @@ pub fn build_block_contents<E: EthSpec>(
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<E: EthSpec>(
blobs,
}),
))
} else {
Ok(ProduceBlockV3Response::Full(FullBlockContents::Block(
block.block,
)))
}
},
}
}
}

View File

@@ -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<T: BeaconChainTypes, B: IntoGossipVerifiedBlockConten
info!(log, "Signed block published to network via HTTP API"; "slot" => 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(())
};

View File

@@ -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)
}

View File

@@ -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(),

View File

@@ -50,13 +50,13 @@ impl ForkName {
}
pub fn list_all_enabled_features(self) -> Vec<FeatureName> {
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 {

View File

@@ -37,7 +37,14 @@ impl From<SignedBeaconBlockHash> 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,