mirror of
https://github.com/sigp/lighthouse.git
synced 2026-06-15 17:58:23 +00:00
Compare commits
11 Commits
v7.0.0-bet
...
superstruc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a4be377d4 | ||
|
|
d9a0c3d6c2 | ||
|
|
689cdaef61 | ||
|
|
b68d08c847 | ||
|
|
4e3839ec98 | ||
|
|
9a49efc854 | ||
|
|
2bac4b8a19 | ||
|
|
5c80d92b22 | ||
|
|
3b92e0bd9a | ||
|
|
e862e5613c | ||
|
|
7b8a7c0497 |
5
Cargo.lock
generated
5
Cargo.lock
generated
@@ -8022,13 +8022,14 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
|
||||
[[package]]
|
||||
name = "superstruct"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f4e1f478a7728f8855d7e620e9a152cf8932c6614f86564c886f9b8141f3201"
|
||||
source = "git+https://github.com/sigp/superstruct?branch=features#822403d4d415c181aa7f4765e118606c6772dc58"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"itertools",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"smallvec",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
@@ -162,7 +162,7 @@ smallvec = "1.11.2"
|
||||
snap = "1"
|
||||
ssz_types = "0.6"
|
||||
strum = { version = "0.24", features = ["derive"] }
|
||||
superstruct = "0.7"
|
||||
superstruct = { git = "https://github.com/sigp/superstruct", branch = "features" }
|
||||
syn = "1"
|
||||
sysinfo = "0.26"
|
||||
tempfile = "3"
|
||||
|
||||
@@ -30,7 +30,7 @@ use store::consts::altair::{
|
||||
TIMELY_TARGET_FLAG_INDEX,
|
||||
};
|
||||
use types::consts::altair::WEIGHT_DENOMINATOR;
|
||||
use types::{BeaconState, Epoch, EthSpec, RelativeEpoch};
|
||||
use types::{BeaconState, Epoch, EthSpec, FeatureName, RelativeEpoch};
|
||||
|
||||
impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
pub fn compute_attestation_rewards(
|
||||
@@ -51,13 +51,10 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
.get_state(&state_root, Some(state_slot))?
|
||||
.ok_or(BeaconChainError::MissingBeaconState(state_root))?;
|
||||
|
||||
match state {
|
||||
BeaconState::Base(_) => self.compute_attestation_rewards_base(state, validators),
|
||||
BeaconState::Altair(_)
|
||||
| BeaconState::Bellatrix(_)
|
||||
| BeaconState::Capella(_)
|
||||
| BeaconState::Deneb(_)
|
||||
| BeaconState::Electra(_) => self.compute_attestation_rewards_altair(state, validators),
|
||||
if state.has_feature(FeatureName::Altair) {
|
||||
self.compute_attestation_rewards_altair(state, validators)
|
||||
} else {
|
||||
self.compute_attestation_rewards_base(state, validators)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -733,6 +733,21 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
.map(|slot| slot.epoch(T::EthSpec::slots_per_epoch()))
|
||||
}
|
||||
|
||||
/// Returns the latest fork for the current slot.
|
||||
pub fn current_fork(&self) -> Result<ForkName, Error> {
|
||||
Ok(self.spec.fork_name_at_slot::<T::EthSpec>(self.slot()?))
|
||||
}
|
||||
|
||||
/// Checks if a feature is enabled on the current fork.
|
||||
pub fn has_feature(&self, feature: FeatureName) -> bool {
|
||||
if let Ok(current_fork) = self.current_fork() {
|
||||
current_fork.has_feature(feature)
|
||||
} else {
|
||||
// TODO(superstruct_features): Is this safe?
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterates across all `(block_root, slot)` pairs from `start_slot`
|
||||
/// to the head of the chain (inclusive).
|
||||
///
|
||||
@@ -2523,7 +2538,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
bls_to_execution_change: SignedBlsToExecutionChange,
|
||||
) -> Result<ObservationOutcome<SignedBlsToExecutionChange, T::EthSpec>, Error> {
|
||||
// Ignore BLS to execution changes on gossip prior to Capella.
|
||||
if !self.current_slot_is_post_capella()? {
|
||||
if !self.has_feature(FeatureName::Capella) {
|
||||
return Err(Error::BlsToExecutionPriorToCapella);
|
||||
}
|
||||
self.verify_bls_to_execution_change_for_http_api(bls_to_execution_change)
|
||||
@@ -2536,16 +2551,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Check if the current slot is greater than or equal to the Capella fork epoch.
|
||||
pub fn current_slot_is_post_capella(&self) -> Result<bool, Error> {
|
||||
let current_fork = self.spec.fork_name_at_slot::<T::EthSpec>(self.slot()?);
|
||||
if let ForkName::Base | ForkName::Altair | ForkName::Bellatrix = current_fork {
|
||||
Ok(false)
|
||||
} else {
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
|
||||
/// Import a BLS to execution change to the op pool.
|
||||
///
|
||||
/// Return `true` if the change was added to the pool.
|
||||
@@ -4833,23 +4838,19 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
|
||||
// If required, start the process of loading an execution payload from the EL early. This
|
||||
// allows it to run concurrently with things like attestation packing.
|
||||
let prepare_payload_handle = match &state {
|
||||
BeaconState::Base(_) | BeaconState::Altair(_) => None,
|
||||
BeaconState::Bellatrix(_)
|
||||
| BeaconState::Capella(_)
|
||||
| BeaconState::Deneb(_)
|
||||
| BeaconState::Electra(_) => {
|
||||
let prepare_payload_handle = get_execution_payload(
|
||||
self.clone(),
|
||||
&state,
|
||||
parent_root,
|
||||
proposer_index,
|
||||
builder_params,
|
||||
builder_boost_factor,
|
||||
block_production_version,
|
||||
)?;
|
||||
Some(prepare_payload_handle)
|
||||
}
|
||||
let prepare_payload_handle = if state.has_feature(FeatureName::Bellatrix) {
|
||||
let prepare_payload_handle = get_execution_payload(
|
||||
self.clone(),
|
||||
&state,
|
||||
parent_root,
|
||||
proposer_index,
|
||||
builder_params,
|
||||
builder_boost_factor,
|
||||
block_production_version,
|
||||
)?;
|
||||
Some(prepare_payload_handle)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let (mut proposer_slashings, mut attester_slashings, mut voluntary_exits) =
|
||||
@@ -5552,26 +5553,22 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
payload_attributes
|
||||
} else {
|
||||
let prepare_slot_fork = self.spec.fork_name_at_slot::<T::EthSpec>(prepare_slot);
|
||||
let withdrawals = match prepare_slot_fork {
|
||||
ForkName::Base | ForkName::Altair | ForkName::Bellatrix => None,
|
||||
ForkName::Capella | ForkName::Deneb | ForkName::Electra => {
|
||||
let chain = self.clone();
|
||||
self.spawn_blocking_handle(
|
||||
move || {
|
||||
chain.get_expected_withdrawals(&forkchoice_update_params, prepare_slot)
|
||||
},
|
||||
"prepare_beacon_proposer_withdrawals",
|
||||
)
|
||||
.await?
|
||||
.map(Some)?
|
||||
}
|
||||
let withdrawals = if prepare_slot_fork.has_feature(FeatureName::Capella) {
|
||||
let chain = self.clone();
|
||||
self.spawn_blocking_handle(
|
||||
move || chain.get_expected_withdrawals(&forkchoice_update_params, prepare_slot),
|
||||
"prepare_beacon_proposer_withdrawals",
|
||||
)
|
||||
.await?
|
||||
.map(Some)?
|
||||
} else {
|
||||
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 parent_beacon_block_root = if prepare_slot_fork.has_feature(FeatureName::Deneb) {
|
||||
Some(pre_payload_attributes.parent_beacon_block_root)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let payload_attributes = PayloadAttributes::new(
|
||||
@@ -6609,17 +6606,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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -411,19 +411,16 @@ pub fn get_execution_payload<T: BeaconChainTypes>(
|
||||
let random = *state.get_randao_mix(current_epoch)?;
|
||||
let latest_execution_payload_header_block_hash =
|
||||
state.latest_execution_payload_header()?.block_hash();
|
||||
let withdrawals = match state {
|
||||
&BeaconState::Capella(_) | &BeaconState::Deneb(_) | &BeaconState::Electra(_) => {
|
||||
Some(get_expected_withdrawals(state, spec)?.into())
|
||||
}
|
||||
&BeaconState::Bellatrix(_) => None,
|
||||
// These shouldn't happen but they're here to make the pattern irrefutable
|
||||
&BeaconState::Base(_) | &BeaconState::Altair(_) => None,
|
||||
let withdrawals = if state.has_feature(FeatureName::Capella) {
|
||||
Some(get_expected_withdrawals(state, spec)?.into())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let parent_beacon_block_root = match state {
|
||||
BeaconState::Deneb(_) | BeaconState::Electra(_) => Some(parent_block_root),
|
||||
BeaconState::Bellatrix(_) | BeaconState::Capella(_) => None,
|
||||
// These shouldn't happen but they're here to make the pattern irrefutable
|
||||
BeaconState::Base(_) | BeaconState::Altair(_) => None,
|
||||
|
||||
let parent_beacon_block_root = if state.has_feature(FeatureName::Deneb) {
|
||||
Some(parent_block_root)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Spawn a task to obtain the execution payload from the EL via a series of async calls. The
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
2
beacon_node/execution_layer/build.rs
Normal file
2
beacon_node/execution_layer/build.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
// Dummy build.rs file to enable OUT_DIR usage by superstruct
|
||||
fn main() {}
|
||||
@@ -45,8 +45,8 @@ pub fn calculate_execution_block_hash<E: EthSpec>(
|
||||
KECCAK_EMPTY_LIST_RLP.as_fixed_bytes().into(),
|
||||
rlp_transactions_root,
|
||||
rlp_withdrawals_root,
|
||||
rlp_blob_gas_used,
|
||||
rlp_excess_blob_gas,
|
||||
rlp_blob_gas_used.copied(),
|
||||
rlp_excess_blob_gas.copied(),
|
||||
parent_beacon_block_root,
|
||||
);
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ pub use types::{
|
||||
};
|
||||
use types::{
|
||||
ExecutionPayloadBellatrix, ExecutionPayloadCapella, ExecutionPayloadDeneb,
|
||||
ExecutionPayloadElectra, KzgProofs,
|
||||
ExecutionPayloadElectra, FeatureName, KzgProofs,
|
||||
};
|
||||
use types::{Graffiti, GRAFFITI_BYTES_LEN};
|
||||
|
||||
@@ -155,7 +155,15 @@ pub struct ExecutionBlock {
|
||||
|
||||
/// Representation of an execution block with enough detail to reconstruct a payload.
|
||||
#[superstruct(
|
||||
variants(Bellatrix, Capella, Deneb, Electra),
|
||||
feature(Bellatrix),
|
||||
variants_and_features_from = "FORK_ORDER",
|
||||
feature_dependencies = "FEATURE_DEPENDENCIES",
|
||||
variant_type(name = "ForkName", getter = "fork_name"),
|
||||
feature_type(
|
||||
name = "FeatureName",
|
||||
list = "list_all_features",
|
||||
check = "has_feature"
|
||||
),
|
||||
variant_attributes(
|
||||
derive(Clone, Debug, PartialEq, Serialize, Deserialize,),
|
||||
serde(bound = "E: EthSpec", rename_all = "camelCase"),
|
||||
@@ -189,12 +197,12 @@ pub struct ExecutionBlockWithTransactions<E: EthSpec> {
|
||||
#[serde(rename = "hash")]
|
||||
pub block_hash: ExecutionBlockHash,
|
||||
pub transactions: Vec<Transaction>,
|
||||
#[superstruct(only(Capella, Deneb, Electra))]
|
||||
#[superstruct(feature(Capella))]
|
||||
pub withdrawals: Vec<JsonWithdrawal>,
|
||||
#[superstruct(only(Deneb, Electra))]
|
||||
#[superstruct(feature(Deneb))]
|
||||
#[serde(with = "serde_utils::u64_hex_be")]
|
||||
pub blob_gas_used: u64,
|
||||
#[superstruct(only(Deneb, Electra))]
|
||||
#[superstruct(feature(Deneb))]
|
||||
#[serde(with = "serde_utils::u64_hex_be")]
|
||||
pub excess_blob_gas: u64,
|
||||
}
|
||||
@@ -425,7 +433,15 @@ pub struct ProposeBlindedBlockResponse {
|
||||
}
|
||||
|
||||
#[superstruct(
|
||||
variants(Bellatrix, Capella, Deneb, Electra),
|
||||
feature(Bellatrix),
|
||||
variants_and_features_from = "FORK_ORDER",
|
||||
feature_dependencies = "FEATURE_DEPENDENCIES",
|
||||
variant_type(name = "ForkName", getter = "fork_name"),
|
||||
feature_type(
|
||||
name = "FeatureName",
|
||||
list = "list_all_features",
|
||||
check = "has_feature"
|
||||
),
|
||||
variant_attributes(derive(Clone, Debug, PartialEq),),
|
||||
map_into(ExecutionPayload),
|
||||
map_ref_into(ExecutionPayloadRef),
|
||||
@@ -446,9 +462,9 @@ pub struct GetPayloadResponse<E: EthSpec> {
|
||||
#[superstruct(only(Electra), partial_getter(rename = "execution_payload_electra"))]
|
||||
pub execution_payload: ExecutionPayloadElectra<E>,
|
||||
pub block_value: Uint256,
|
||||
#[superstruct(only(Deneb, Electra))]
|
||||
#[superstruct(feature(Deneb))]
|
||||
pub blobs_bundle: BlobsBundle<E>,
|
||||
#[superstruct(only(Deneb, Electra), partial_getter(copy))]
|
||||
#[superstruct(feature(Deneb), partial_getter(copy))]
|
||||
pub should_override_builder: bool,
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1217,27 +1220,25 @@ impl HttpJsonRpc {
|
||||
payload_id: PayloadId,
|
||||
) -> Result<GetPayloadResponse<E>, Error> {
|
||||
let engine_capabilities = self.get_engine_capabilities(None).await?;
|
||||
match fork_name {
|
||||
ForkName::Bellatrix | ForkName::Capella => {
|
||||
if engine_capabilities.get_payload_v2 {
|
||||
self.get_payload_v2(fork_name, payload_id).await
|
||||
} else if engine_capabilities.new_payload_v1 {
|
||||
self.get_payload_v1(payload_id).await
|
||||
} else {
|
||||
Err(Error::RequiredMethodUnsupported("engine_getPayload"))
|
||||
}
|
||||
if fork_name.has_feature(FeatureName::Deneb) {
|
||||
if engine_capabilities.get_payload_v3 {
|
||||
self.get_payload_v3(fork_name, payload_id).await
|
||||
} else {
|
||||
Err(Error::RequiredMethodUnsupported("engine_getPayloadV3"))
|
||||
}
|
||||
ForkName::Deneb | ForkName::Electra => {
|
||||
if engine_capabilities.get_payload_v3 {
|
||||
self.get_payload_v3(fork_name, payload_id).await
|
||||
} else {
|
||||
Err(Error::RequiredMethodUnsupported("engine_getPayloadV3"))
|
||||
}
|
||||
} else if fork_name.has_feature(FeatureName::Bellatrix) {
|
||||
if engine_capabilities.get_payload_v2 {
|
||||
self.get_payload_v2(fork_name, payload_id).await
|
||||
} else if engine_capabilities.new_payload_v1 {
|
||||
self.get_payload_v1(payload_id).await
|
||||
} else {
|
||||
Err(Error::RequiredMethodUnsupported("engine_getPayload"))
|
||||
}
|
||||
ForkName::Base | ForkName::Altair => Err(Error::UnsupportedForkVariant(format!(
|
||||
} else {
|
||||
Err(Error::UnsupportedForkVariant(format!(
|
||||
"called get_payload with {}",
|
||||
fork_name
|
||||
))),
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ use state_processing::per_block_processing::deneb::kzg_commitment_to_versioned_h
|
||||
use superstruct::superstruct;
|
||||
use types::{
|
||||
BeaconBlockRef, BeaconStateError, EthSpec, ExecutionBlockHash, ExecutionPayload,
|
||||
ExecutionPayloadRef, Hash256, VersionedHash,
|
||||
ExecutionPayloadRef, FeatureName, ForkName, Hash256, VersionedHash,
|
||||
};
|
||||
use types::{
|
||||
ExecutionPayloadBellatrix, ExecutionPayloadCapella, ExecutionPayloadDeneb,
|
||||
@@ -13,7 +13,15 @@ use types::{
|
||||
};
|
||||
|
||||
#[superstruct(
|
||||
variants(Bellatrix, Capella, Deneb, Electra),
|
||||
feature(Bellatrix),
|
||||
variants_and_features_from = "FORK_ORDER",
|
||||
feature_dependencies = "FEATURE_DEPENDENCIES",
|
||||
variant_type(name = "ForkName", getter = "fork_name"),
|
||||
feature_type(
|
||||
name = "FeatureName",
|
||||
list = "list_all_features",
|
||||
check = "has_feature"
|
||||
),
|
||||
variant_attributes(derive(Clone, Debug, PartialEq),),
|
||||
map_into(ExecutionPayload),
|
||||
map_ref_into(ExecutionPayloadRef),
|
||||
@@ -39,9 +47,9 @@ pub struct NewPayloadRequest<'block, E: EthSpec> {
|
||||
pub execution_payload: &'block ExecutionPayloadDeneb<E>,
|
||||
#[superstruct(only(Electra), partial_getter(rename = "execution_payload_electra"))]
|
||||
pub execution_payload: &'block ExecutionPayloadElectra<E>,
|
||||
#[superstruct(only(Deneb, Electra))]
|
||||
#[superstruct(feature(Deneb))]
|
||||
pub versioned_hashes: Vec<VersionedHash>,
|
||||
#[superstruct(only(Deneb, Electra))]
|
||||
#[superstruct(feature(Deneb))]
|
||||
pub parent_beacon_block_root: Hash256,
|
||||
}
|
||||
|
||||
|
||||
@@ -20,9 +20,9 @@ use types::builder_bid::{
|
||||
};
|
||||
use types::{
|
||||
Address, BeaconState, ChainSpec, EthSpec, ExecPayload, ExecutionPayload,
|
||||
ExecutionPayloadHeaderRefMut, ForkName, ForkVersionedResponse, Hash256, PublicKeyBytes,
|
||||
Signature, SignedBlindedBeaconBlock, SignedRoot, SignedValidatorRegistrationData, Slot,
|
||||
Uint256,
|
||||
ExecutionPayloadHeaderRefMut, FeatureName, ForkName, ForkVersionedResponse, Hash256,
|
||||
PublicKeyBytes, Signature, SignedBlindedBeaconBlock, SignedRoot,
|
||||
SignedValidatorRegistrationData, Slot, Uint256,
|
||||
};
|
||||
use types::{ExecutionBlockHash, SecretKey};
|
||||
use warp::{Filter, Rejection};
|
||||
@@ -479,16 +479,17 @@ pub fn serve<E: EthSpec>(
|
||||
let prev_randao = head_state
|
||||
.get_randao_mix(head_state.current_epoch())
|
||||
.map_err(|_| reject("couldn't get prev randao"))?;
|
||||
let expected_withdrawals = match fork {
|
||||
ForkName::Base | ForkName::Altair | ForkName::Bellatrix => None,
|
||||
ForkName::Capella | ForkName::Deneb | ForkName::Electra => Some(
|
||||
let expected_withdrawals = if fork.has_feature(FeatureName::Capella) {
|
||||
Some(
|
||||
builder
|
||||
.beacon_client
|
||||
.get_expected_withdrawals(&StateId::Head)
|
||||
.await
|
||||
.unwrap()
|
||||
.data,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let payload_attributes = match fork {
|
||||
|
||||
@@ -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,
|
||||
)))
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,11 +79,11 @@ use tokio_stream::{
|
||||
};
|
||||
use types::{
|
||||
fork_versioned_response::EmptyMetadata, Attestation, AttestationData, AttestationShufflingId,
|
||||
AttesterSlashing, BeaconStateError, CommitteeCache, ConfigAndPreset, Epoch, EthSpec, ForkName,
|
||||
ForkVersionedResponse, Hash256, ProposerPreparationData, ProposerSlashing, RelativeEpoch,
|
||||
SignedAggregateAndProof, SignedBlindedBeaconBlock, SignedBlsToExecutionChange,
|
||||
SignedContributionAndProof, SignedValidatorRegistrationData, SignedVoluntaryExit, Slot,
|
||||
SyncCommitteeMessage, SyncContributionData,
|
||||
AttesterSlashing, BeaconStateError, CommitteeCache, ConfigAndPreset, Epoch, EthSpec,
|
||||
FeatureName, ForkName, ForkVersionedResponse, Hash256, ProposerPreparationData,
|
||||
ProposerSlashing, RelativeEpoch, SignedAggregateAndProof, SignedBlindedBeaconBlock,
|
||||
SignedBlsToExecutionChange, SignedContributionAndProof, SignedValidatorRegistrationData,
|
||||
SignedVoluntaryExit, Slot, SyncCommitteeMessage, SyncContributionData,
|
||||
};
|
||||
use validator::pubkey_to_validator_index;
|
||||
use version::{
|
||||
@@ -2046,7 +2046,7 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
.to_execution_address;
|
||||
|
||||
// New to P2P *and* op pool, gossip immediately if post-Capella.
|
||||
let received_pre_capella = if chain.current_slot_is_post_capella().unwrap_or(false) {
|
||||
let received_pre_capella = if chain.has_feature(FeatureName::Capella) {
|
||||
ReceivedPreCapella::No
|
||||
} else {
|
||||
ReceivedPreCapella::Yes
|
||||
|
||||
@@ -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(())
|
||||
};
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
2
beacon_node/store/build.rs
Normal file
2
beacon_node/store/build.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
// Dummy build.rs file to enable OUT_DIR usage by superstruct
|
||||
fn main() {}
|
||||
@@ -14,7 +14,14 @@ use types::*;
|
||||
///
|
||||
/// Utilises lazy-loading from separate storage for its vector fields.
|
||||
#[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"),
|
||||
feature_type(
|
||||
name = "FeatureName",
|
||||
list = "list_all_features",
|
||||
check = "has_feature"
|
||||
),
|
||||
variant_attributes(derive(Debug, PartialEq, Clone, Encode, Decode))
|
||||
)]
|
||||
#[derive(Debug, PartialEq, Clone, Encode)]
|
||||
@@ -66,9 +73,9 @@ where
|
||||
pub current_epoch_attestations: List<PendingAttestation<E>, E::MaxPendingAttestations>,
|
||||
|
||||
// Participation (Altair and later)
|
||||
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra))]
|
||||
#[superstruct(feature(Altair))]
|
||||
pub previous_epoch_participation: List<ParticipationFlags, E::ValidatorRegistryLimit>,
|
||||
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra))]
|
||||
#[superstruct(feature(Altair))]
|
||||
pub current_epoch_participation: List<ParticipationFlags, E::ValidatorRegistryLimit>,
|
||||
|
||||
// Finality
|
||||
@@ -78,13 +85,13 @@ where
|
||||
pub finalized_checkpoint: Checkpoint,
|
||||
|
||||
// Inactivity
|
||||
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra))]
|
||||
#[superstruct(feature(Altair))]
|
||||
pub inactivity_scores: List<u64, E::ValidatorRegistryLimit>,
|
||||
|
||||
// Light-client sync committees
|
||||
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra))]
|
||||
#[superstruct(feature(Altair))]
|
||||
pub current_sync_committee: Arc<SyncCommittee<E>>,
|
||||
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra))]
|
||||
#[superstruct(feature(Altair))]
|
||||
pub next_sync_committee: Arc<SyncCommittee<E>>,
|
||||
|
||||
// Execution
|
||||
@@ -110,36 +117,36 @@ where
|
||||
pub latest_execution_payload_header: ExecutionPayloadHeaderElectra<E>,
|
||||
|
||||
// Capella
|
||||
#[superstruct(only(Capella, Deneb, Electra))]
|
||||
#[superstruct(feature(Capella))]
|
||||
pub next_withdrawal_index: u64,
|
||||
#[superstruct(only(Capella, Deneb, Electra))]
|
||||
#[superstruct(feature(Capella))]
|
||||
pub next_withdrawal_validator_index: u64,
|
||||
|
||||
#[ssz(skip_serializing, skip_deserializing)]
|
||||
#[superstruct(only(Capella, Deneb, Electra))]
|
||||
#[superstruct(feature(Capella))]
|
||||
pub historical_summaries: Option<List<HistoricalSummary, E::HistoricalRootsLimit>>,
|
||||
|
||||
// Electra
|
||||
#[superstruct(only(Electra))]
|
||||
#[superstruct(feature(Electra))]
|
||||
pub deposit_receipts_start_index: u64,
|
||||
#[superstruct(only(Electra))]
|
||||
#[superstruct(feature(Electra))]
|
||||
pub deposit_balance_to_consume: u64,
|
||||
#[superstruct(only(Electra))]
|
||||
#[superstruct(feature(Electra))]
|
||||
pub exit_balance_to_consume: u64,
|
||||
#[superstruct(only(Electra))]
|
||||
#[superstruct(feature(Electra))]
|
||||
pub earliest_exit_epoch: Epoch,
|
||||
#[superstruct(only(Electra))]
|
||||
#[superstruct(feature(Electra))]
|
||||
pub consolidation_balance_to_consume: u64,
|
||||
#[superstruct(only(Electra))]
|
||||
#[superstruct(feature(Electra))]
|
||||
pub earliest_consolidation_epoch: Epoch,
|
||||
|
||||
// TODO(electra) should these be optional?
|
||||
#[superstruct(only(Electra))]
|
||||
#[superstruct(feature(Electra))]
|
||||
pub pending_balance_deposits: List<PendingBalanceDeposit, E::PendingBalanceDepositsLimit>,
|
||||
#[superstruct(only(Electra))]
|
||||
#[superstruct(feature(Electra))]
|
||||
pub pending_partial_withdrawals:
|
||||
List<PendingPartialWithdrawal, E::PendingPartialWithdrawalsLimit>,
|
||||
#[superstruct(only(Electra))]
|
||||
#[superstruct(feature(Electra))]
|
||||
pub pending_consolidations: List<PendingConsolidation, E::PendingConsolidationsLimit>,
|
||||
}
|
||||
|
||||
|
||||
@@ -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,32 +747,26 @@ 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(_) => {
|
||||
// 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(_) => {
|
||||
let mut validator_statuses =
|
||||
per_epoch_processing::base::ValidatorStatuses::new(state, spec)
|
||||
.map_err(Error::ValidatorStatuses)?;
|
||||
validator_statuses
|
||||
.process_attestations(state)
|
||||
let justification_and_finalization_state = if block.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)?
|
||||
} else {
|
||||
let mut validator_statuses =
|
||||
per_epoch_processing::base::ValidatorStatuses::new(state, spec)
|
||||
.map_err(Error::ValidatorStatuses)?;
|
||||
per_epoch_processing::base::process_justification_and_finalization(
|
||||
state,
|
||||
&validator_statuses.total_balances,
|
||||
spec,
|
||||
)?
|
||||
}
|
||||
validator_statuses
|
||||
.process_attestations(state)
|
||||
.map_err(Error::ValidatorStatuses)?;
|
||||
per_epoch_processing::base::process_justification_and_finalization(
|
||||
state,
|
||||
&validator_statuses.total_balances,
|
||||
spec,
|
||||
)?
|
||||
};
|
||||
|
||||
(
|
||||
|
||||
@@ -7,7 +7,7 @@ use types::{
|
||||
},
|
||||
BeaconStateError as Error,
|
||||
};
|
||||
use types::{AttestationData, BeaconState, ChainSpec, EthSpec};
|
||||
use types::{AttestationData, BeaconState, ChainSpec, EthSpec, FeatureName};
|
||||
|
||||
/// Get the participation flags for a valid attestation.
|
||||
///
|
||||
@@ -44,22 +44,14 @@ pub fn get_attestation_participation_flag_indices<E: EthSpec>(
|
||||
if is_matching_source && inclusion_delay <= E::slots_per_epoch().integer_sqrt() {
|
||||
participation_flag_indices.push(TIMELY_SOURCE_FLAG_INDEX);
|
||||
}
|
||||
match state {
|
||||
&BeaconState::Base(_)
|
||||
| &BeaconState::Altair(_)
|
||||
| &BeaconState::Bellatrix(_)
|
||||
| &BeaconState::Capella(_) => {
|
||||
if is_matching_target && inclusion_delay <= E::slots_per_epoch() {
|
||||
participation_flag_indices.push(TIMELY_TARGET_FLAG_INDEX);
|
||||
}
|
||||
}
|
||||
&BeaconState::Deneb(_) | &BeaconState::Electra(_) => {
|
||||
if is_matching_target {
|
||||
// [Modified in Deneb:EIP7045]
|
||||
participation_flag_indices.push(TIMELY_TARGET_FLAG_INDEX);
|
||||
}
|
||||
}
|
||||
|
||||
if state.has_feature(FeatureName::Deneb) && is_matching_target {
|
||||
// [Modified in Deneb:EIP7045]
|
||||
participation_flag_indices.push(TIMELY_TARGET_FLAG_INDEX);
|
||||
} else if is_matching_target && inclusion_delay <= E::slots_per_epoch() {
|
||||
participation_flag_indices.push(TIMELY_TARGET_FLAG_INDEX);
|
||||
}
|
||||
|
||||
if is_matching_head && inclusion_delay == spec.min_attestation_inclusion_delay {
|
||||
participation_flag_indices.push(TIMELY_HEAD_FLAG_INDEX);
|
||||
}
|
||||
|
||||
@@ -55,15 +55,12 @@ pub fn slash_validator<E: EthSpec>(
|
||||
let whistleblower_index = opt_whistleblower_index.unwrap_or(proposer_index);
|
||||
let whistleblower_reward =
|
||||
validator_effective_balance.safe_div(spec.whistleblower_reward_quotient)?;
|
||||
let proposer_reward = match state {
|
||||
BeaconState::Base(_) => whistleblower_reward.safe_div(spec.proposer_reward_quotient)?,
|
||||
BeaconState::Altair(_)
|
||||
| BeaconState::Bellatrix(_)
|
||||
| BeaconState::Capella(_)
|
||||
| BeaconState::Deneb(_)
|
||||
| BeaconState::Electra(_) => whistleblower_reward
|
||||
let proposer_reward = if state.has_feature(FeatureName::Altair) {
|
||||
whistleblower_reward
|
||||
.safe_mul(PROPOSER_WEIGHT)?
|
||||
.safe_div(WEIGHT_DENOMINATOR)?,
|
||||
.safe_div(WEIGHT_DENOMINATOR)?
|
||||
} else {
|
||||
whistleblower_reward.safe_div(spec.proposer_reward_quotient)?
|
||||
};
|
||||
|
||||
// Ensure the whistleblower index is in the validator registry.
|
||||
|
||||
@@ -6,8 +6,8 @@ use crate::metrics::{
|
||||
use crate::{BlockProcessingError, EpochProcessingError};
|
||||
use lighthouse_metrics::set_gauge;
|
||||
use types::{
|
||||
is_progressive_balances_enabled, BeaconState, BeaconStateError, ChainSpec, Epoch,
|
||||
EpochTotalBalances, EthSpec, ParticipationFlags, ProgressiveBalancesCache, Validator,
|
||||
BeaconState, BeaconStateError, ChainSpec, Epoch, EpochTotalBalances, EthSpec, FeatureName,
|
||||
ParticipationFlags, ProgressiveBalancesCache, Validator,
|
||||
};
|
||||
|
||||
/// Initializes the `ProgressiveBalancesCache` if it is unbuilt.
|
||||
@@ -15,7 +15,7 @@ pub fn initialize_progressive_balances_cache<E: EthSpec>(
|
||||
state: &mut BeaconState<E>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), BeaconStateError> {
|
||||
if !is_progressive_balances_enabled(state)
|
||||
if !state.has_feature(FeatureName::Altair)
|
||||
|| state.progressive_balances_cache().is_initialized()
|
||||
{
|
||||
return Ok(());
|
||||
@@ -92,7 +92,7 @@ pub fn update_progressive_balances_on_attestation<E: EthSpec>(
|
||||
validator_effective_balance: u64,
|
||||
validator_slashed: bool,
|
||||
) -> Result<(), BlockProcessingError> {
|
||||
if is_progressive_balances_enabled(state) {
|
||||
if state.has_feature(FeatureName::Altair) {
|
||||
state.progressive_balances_cache_mut().on_new_attestation(
|
||||
epoch,
|
||||
validator_slashed,
|
||||
@@ -109,7 +109,7 @@ pub fn update_progressive_balances_on_slashing<E: EthSpec>(
|
||||
validator_index: usize,
|
||||
validator_effective_balance: u64,
|
||||
) -> Result<(), BlockProcessingError> {
|
||||
if is_progressive_balances_enabled(state) {
|
||||
if state.has_feature(FeatureName::Altair) {
|
||||
let previous_epoch_participation = *state
|
||||
.previous_epoch_participation()?
|
||||
.get(validator_index)
|
||||
@@ -135,7 +135,7 @@ pub fn update_progressive_balances_on_epoch_transition<E: EthSpec>(
|
||||
state: &mut BeaconState<E>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), EpochProcessingError> {
|
||||
if is_progressive_balances_enabled(state) {
|
||||
if state.has_feature(FeatureName::Altair) {
|
||||
state
|
||||
.progressive_balances_cache_mut()
|
||||
.on_epoch_transition(spec)?;
|
||||
|
||||
@@ -188,7 +188,7 @@ pub fn per_block_processing<E: EthSpec, Payload: AbstractExecPayload<E>>(
|
||||
)?;
|
||||
}
|
||||
|
||||
if is_progressive_balances_enabled(state) {
|
||||
if state.has_feature(FeatureName::Altair) {
|
||||
update_progressive_balances_metrics(state.progressive_balances_cache())?;
|
||||
}
|
||||
|
||||
@@ -453,15 +453,17 @@ pub fn process_execution_payload<E: EthSpec, Payload: AbstractExecPayload<E>>(
|
||||
/// repeatedly write code to treat these errors as false.
|
||||
/// https://github.com/ethereum/consensus-specs/blob/dev/specs/bellatrix/beacon-chain.md#is_merge_transition_complete
|
||||
pub fn is_merge_transition_complete<E: EthSpec>(state: &BeaconState<E>) -> bool {
|
||||
match state {
|
||||
if state.has_feature(FeatureName::Capella) {
|
||||
true
|
||||
} else if state.has_feature(FeatureName::Bellatrix) {
|
||||
// We must check defaultness against the payload header with 0x0 roots, as that's what's meant
|
||||
// by `ExecutionPayloadHeader()` in the spec.
|
||||
BeaconState::Bellatrix(_) => state
|
||||
state
|
||||
.latest_execution_payload_header()
|
||||
.map(|header| !header.is_default_with_zero_roots())
|
||||
.unwrap_or(false),
|
||||
BeaconState::Electra(_) | BeaconState::Deneb(_) | BeaconState::Capella(_) => true,
|
||||
BeaconState::Base(_) | BeaconState::Altair(_) => false,
|
||||
.unwrap_or(false)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
/// https://github.com/ethereum/consensus-specs/blob/dev/specs/bellatrix/beacon-chain.md#is_merge_transition_block
|
||||
@@ -556,55 +558,52 @@ pub fn process_withdrawals<E: EthSpec, Payload: AbstractExecPayload<E>>(
|
||||
payload: Payload::Ref<'_>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), BlockProcessingError> {
|
||||
match state {
|
||||
BeaconState::Bellatrix(_) => Ok(()),
|
||||
BeaconState::Capella(_) | BeaconState::Deneb(_) | BeaconState::Electra(_) => {
|
||||
let expected_withdrawals = get_expected_withdrawals(state, spec)?;
|
||||
let expected_root = expected_withdrawals.tree_hash_root();
|
||||
let withdrawals_root = payload.withdrawals_root()?;
|
||||
if state.has_feature(FeatureName::Capella) {
|
||||
let expected_withdrawals = get_expected_withdrawals(state, spec)?;
|
||||
let expected_root = expected_withdrawals.tree_hash_root();
|
||||
let withdrawals_root = payload.withdrawals_root()?;
|
||||
|
||||
if expected_root != withdrawals_root {
|
||||
return Err(BlockProcessingError::WithdrawalsRootMismatch {
|
||||
expected: expected_root,
|
||||
found: withdrawals_root,
|
||||
});
|
||||
}
|
||||
if expected_root != withdrawals_root {
|
||||
return Err(BlockProcessingError::WithdrawalsRootMismatch {
|
||||
expected: expected_root,
|
||||
found: withdrawals_root,
|
||||
});
|
||||
}
|
||||
|
||||
for withdrawal in expected_withdrawals.iter() {
|
||||
decrease_balance(
|
||||
state,
|
||||
withdrawal.validator_index as usize,
|
||||
withdrawal.amount,
|
||||
)?;
|
||||
}
|
||||
for withdrawal in expected_withdrawals.iter() {
|
||||
decrease_balance(
|
||||
state,
|
||||
withdrawal.validator_index as usize,
|
||||
withdrawal.amount,
|
||||
)?;
|
||||
}
|
||||
|
||||
// Update the next withdrawal index if this block contained withdrawals
|
||||
if let Some(latest_withdrawal) = expected_withdrawals.last() {
|
||||
*state.next_withdrawal_index_mut()? = latest_withdrawal.index.safe_add(1)?;
|
||||
// Update the next withdrawal index if this block contained withdrawals
|
||||
if let Some(latest_withdrawal) = expected_withdrawals.last() {
|
||||
*state.next_withdrawal_index_mut()? = latest_withdrawal.index.safe_add(1)?;
|
||||
|
||||
// Update the next validator index to start the next withdrawal sweep
|
||||
if expected_withdrawals.len() == E::max_withdrawals_per_payload() {
|
||||
// Next sweep starts after the latest withdrawal's validator index
|
||||
let next_validator_index = latest_withdrawal
|
||||
.validator_index
|
||||
.safe_add(1)?
|
||||
.safe_rem(state.validators().len() as u64)?;
|
||||
*state.next_withdrawal_validator_index_mut()? = next_validator_index;
|
||||
}
|
||||
}
|
||||
|
||||
// Advance sweep by the max length of the sweep if there was not a full set of withdrawals
|
||||
if expected_withdrawals.len() != E::max_withdrawals_per_payload() {
|
||||
let next_validator_index = state
|
||||
.next_withdrawal_validator_index()?
|
||||
.safe_add(spec.max_validators_per_withdrawals_sweep)?
|
||||
// Update the next validator index to start the next withdrawal sweep
|
||||
if expected_withdrawals.len() == E::max_withdrawals_per_payload() {
|
||||
// Next sweep starts after the latest withdrawal's validator index
|
||||
let next_validator_index = latest_withdrawal
|
||||
.validator_index
|
||||
.safe_add(1)?
|
||||
.safe_rem(state.validators().len() as u64)?;
|
||||
*state.next_withdrawal_validator_index_mut()? = next_validator_index;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
// these shouldn't even be encountered but they're here for completeness
|
||||
BeaconState::Base(_) | BeaconState::Altair(_) => Ok(()),
|
||||
|
||||
// Advance sweep by the max length of the sweep if there was not a full set of withdrawals
|
||||
if expected_withdrawals.len() != E::max_withdrawals_per_payload() {
|
||||
let next_validator_index = state
|
||||
.next_withdrawal_validator_index()?
|
||||
.safe_add(spec.max_validators_per_withdrawals_sweep)?
|
||||
.safe_rem(state.validators().len() as u64)?;
|
||||
*state.next_withdrawal_validator_index_mut()? = next_validator_index;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,29 +262,22 @@ pub fn process_attestations<E: EthSpec, Payload: AbstractExecPayload<E>>(
|
||||
ctxt: &mut ConsensusContext<E>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), BlockProcessingError> {
|
||||
match block_body {
|
||||
BeaconBlockBodyRef::Base(_) => {
|
||||
base::process_attestations(
|
||||
state,
|
||||
block_body.attestations(),
|
||||
verify_signatures,
|
||||
ctxt,
|
||||
spec,
|
||||
)?;
|
||||
}
|
||||
BeaconBlockBodyRef::Altair(_)
|
||||
| BeaconBlockBodyRef::Bellatrix(_)
|
||||
| BeaconBlockBodyRef::Capella(_)
|
||||
| BeaconBlockBodyRef::Deneb(_)
|
||||
| BeaconBlockBodyRef::Electra(_) => {
|
||||
altair_deneb::process_attestations(
|
||||
state,
|
||||
block_body.attestations(),
|
||||
verify_signatures,
|
||||
ctxt,
|
||||
spec,
|
||||
)?;
|
||||
}
|
||||
if block_body.has_feature(FeatureName::Altair) {
|
||||
altair_deneb::process_attestations(
|
||||
state,
|
||||
block_body.attestations(),
|
||||
verify_signatures,
|
||||
ctxt,
|
||||
spec,
|
||||
)?;
|
||||
} else {
|
||||
base::process_attestations(
|
||||
state,
|
||||
block_body.attestations(),
|
||||
verify_signatures,
|
||||
ctxt,
|
||||
spec,
|
||||
)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ use std::borrow::Cow;
|
||||
use tree_hash::TreeHash;
|
||||
use types::{
|
||||
AbstractExecPayload, AggregateSignature, AttesterSlashing, BeaconBlockRef, BeaconState,
|
||||
BeaconStateError, ChainSpec, DepositData, Domain, Epoch, EthSpec, Fork, Hash256,
|
||||
BeaconStateError, ChainSpec, DepositData, Domain, Epoch, EthSpec, FeatureName, Fork, Hash256,
|
||||
InconsistentFork, IndexedAttestation, ProposerSlashing, PublicKey, PublicKeyBytes, Signature,
|
||||
SignedAggregateAndProof, SignedBeaconBlock, SignedBeaconBlockHeader,
|
||||
SignedBlsToExecutionChange, SignedContributionAndProof, SignedRoot, SignedVoluntaryExit,
|
||||
@@ -387,22 +387,20 @@ where
|
||||
let exit = &signed_exit.message;
|
||||
let proposer_index = exit.validator_index as usize;
|
||||
|
||||
let domain = match state {
|
||||
BeaconState::Base(_)
|
||||
| BeaconState::Altair(_)
|
||||
| BeaconState::Bellatrix(_)
|
||||
| BeaconState::Capella(_) => spec.get_domain(
|
||||
let domain = if state.has_feature(FeatureName::Deneb) {
|
||||
// EIP-7044
|
||||
spec.compute_domain(
|
||||
Domain::VoluntaryExit,
|
||||
spec.capella_fork_version,
|
||||
state.genesis_validators_root(),
|
||||
)
|
||||
} else {
|
||||
spec.get_domain(
|
||||
exit.epoch,
|
||||
Domain::VoluntaryExit,
|
||||
&state.fork(),
|
||||
state.genesis_validators_root(),
|
||||
),
|
||||
// EIP-7044
|
||||
BeaconState::Deneb(_) | BeaconState::Electra(_) => spec.compute_domain(
|
||||
Domain::VoluntaryExit,
|
||||
spec.capella_fork_version,
|
||||
state.genesis_validators_root(),
|
||||
),
|
||||
)
|
||||
};
|
||||
|
||||
let message = exit.signing_root(domain);
|
||||
|
||||
@@ -32,21 +32,17 @@ pub fn verify_attestation_for_block_inclusion<'ctxt, E: EthSpec>(
|
||||
attestation: data.slot,
|
||||
}
|
||||
);
|
||||
match state {
|
||||
BeaconState::Base(_)
|
||||
| BeaconState::Altair(_)
|
||||
| BeaconState::Bellatrix(_)
|
||||
| BeaconState::Capella(_) => {
|
||||
verify!(
|
||||
state.slot() <= data.slot.safe_add(E::slots_per_epoch())?,
|
||||
Invalid::IncludedTooLate {
|
||||
state: state.slot(),
|
||||
attestation: data.slot,
|
||||
}
|
||||
);
|
||||
}
|
||||
if state.has_feature(FeatureName::Deneb) {
|
||||
// [Modified in Deneb:EIP7045]
|
||||
BeaconState::Deneb(_) | BeaconState::Electra(_) => {}
|
||||
{}
|
||||
} else {
|
||||
verify!(
|
||||
state.slot() <= data.slot.safe_add(E::slots_per_epoch())?,
|
||||
Invalid::IncludedTooLate {
|
||||
state: state.slot(),
|
||||
attestation: data.slot,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
verify_attestation_for_state(state, attestation, ctxt, verify_signatures, spec)
|
||||
|
||||
@@ -5,7 +5,7 @@ pub use epoch_processing_summary::{EpochProcessingSummary, ParticipationEpochSum
|
||||
use errors::EpochProcessingError as Error;
|
||||
pub use justification_and_finalization_state::JustificationAndFinalizationState;
|
||||
use safe_arith::SafeArith;
|
||||
use types::{BeaconState, ChainSpec, EthSpec};
|
||||
use types::{BeaconState, ChainSpec, EthSpec, FeatureName};
|
||||
|
||||
pub use registry_updates::{process_registry_updates, process_registry_updates_slow};
|
||||
pub use slashings::{process_slashings, process_slashings_slow};
|
||||
@@ -41,13 +41,10 @@ pub fn process_epoch<E: EthSpec>(
|
||||
.fork_name(spec)
|
||||
.map_err(Error::InconsistentStateFork)?;
|
||||
|
||||
match state {
|
||||
BeaconState::Base(_) => base::process_epoch(state, spec),
|
||||
BeaconState::Altair(_)
|
||||
| BeaconState::Bellatrix(_)
|
||||
| BeaconState::Capella(_)
|
||||
| BeaconState::Deneb(_)
|
||||
| BeaconState::Electra(_) => altair::process_epoch(state, spec),
|
||||
if state.has_feature(FeatureName::Altair) {
|
||||
altair::process_epoch(state, spec)
|
||||
} else {
|
||||
base::process_epoch(state, spec)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
2
consensus/types/build.rs
Normal file
2
consensus/types/build.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
// Dummy build.rs file to enable OUT_DIR usage by superstruct
|
||||
fn main() {}
|
||||
@@ -12,7 +12,14 @@ use tree_hash_derive::TreeHash;
|
||||
|
||||
/// A block of the `BeaconChain`.
|
||||
#[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_unchecked"),
|
||||
feature_type(
|
||||
name = "FeatureName",
|
||||
list = "list_all_features",
|
||||
check = "has_feature"
|
||||
),
|
||||
variant_attributes(
|
||||
derive(
|
||||
Debug,
|
||||
@@ -228,6 +235,10 @@ impl<'a, E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockRef<'a, E, Payl
|
||||
}
|
||||
}
|
||||
|
||||
pub fn has_feature(self, feature: FeatureName) -> bool {
|
||||
self.fork_name_unchecked().has_feature(feature)
|
||||
}
|
||||
|
||||
/// Convenience accessor for the `body` as a `BeaconBlockBodyRef`.
|
||||
pub fn body(&self) -> BeaconBlockBodyRef<'a, E, Payload> {
|
||||
map_beacon_block_ref_into_beacon_block_body_ref!(&'a _, *self, |block, cons| cons(
|
||||
|
||||
@@ -29,7 +29,14 @@ pub const BLOB_KZG_COMMITMENTS_INDEX: usize = 11;
|
||||
///
|
||||
/// This *superstruct* abstracts over the hard-fork.
|
||||
#[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"),
|
||||
feature_type(
|
||||
name = "FeatureName",
|
||||
list = "list_all_features",
|
||||
check = "has_feature"
|
||||
),
|
||||
variant_attributes(
|
||||
derive(
|
||||
Debug,
|
||||
@@ -67,7 +74,7 @@ pub struct BeaconBlockBody<E: EthSpec, Payload: AbstractExecPayload<E> = FullPay
|
||||
pub attestations: VariableList<Attestation<E>, E::MaxAttestations>,
|
||||
pub deposits: VariableList<Deposit, E::MaxDeposits>,
|
||||
pub voluntary_exits: VariableList<SignedVoluntaryExit, E::MaxVoluntaryExits>,
|
||||
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra))]
|
||||
#[superstruct(feature(Altair))]
|
||||
pub sync_aggregate: SyncAggregate<E>,
|
||||
// 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
|
||||
@@ -87,12 +94,12 @@ pub struct BeaconBlockBody<E: EthSpec, Payload: AbstractExecPayload<E> = FullPay
|
||||
#[superstruct(only(Electra), partial_getter(rename = "execution_payload_electra"))]
|
||||
#[serde(flatten)]
|
||||
pub execution_payload: Payload::Electra,
|
||||
#[superstruct(only(Capella, Deneb, Electra))]
|
||||
#[superstruct(feature(Capella))]
|
||||
pub bls_to_execution_changes:
|
||||
VariableList<SignedBlsToExecutionChange, E::MaxBlsToExecutionChanges>,
|
||||
#[superstruct(only(Deneb, Electra))]
|
||||
#[superstruct(feature(Deneb))]
|
||||
pub blob_kzg_commitments: KzgCommitments<E>,
|
||||
#[superstruct(only(Base, Altair))]
|
||||
#[superstruct(feature(not(Bellatrix)))]
|
||||
#[ssz(skip_serializing, skip_deserializing)]
|
||||
#[tree_hash(skip_hashing)]
|
||||
#[serde(skip)]
|
||||
@@ -256,6 +263,10 @@ impl<'a, E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBodyRef<'a, E,
|
||||
self.blob_kzg_commitments()
|
||||
.map_or(false, |blobs| !blobs.is_empty())
|
||||
}
|
||||
|
||||
pub fn has_feature(self, feature: FeatureName) -> bool {
|
||||
self.fork_name().has_feature(feature)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBodyRef<'a, E, Payload> {
|
||||
|
||||
@@ -206,7 +206,14 @@ impl From<BeaconStateHash> for Hash256 {
|
||||
|
||||
/// The state of the `BeaconChain` at some slot.
|
||||
#[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_unchecked"),
|
||||
feature_type(
|
||||
name = "FeatureName",
|
||||
list = "list_all_features",
|
||||
check = "has_feature"
|
||||
),
|
||||
variant_attributes(
|
||||
derive(
|
||||
Derivative,
|
||||
@@ -384,18 +391,18 @@ where
|
||||
pub slashings: Vector<u64, E::EpochsPerSlashingsVector>,
|
||||
|
||||
// Attestations (genesis fork only)
|
||||
#[superstruct(only(Base))]
|
||||
#[superstruct(feature(not(Altair)))]
|
||||
#[test_random(default)]
|
||||
pub previous_epoch_attestations: List<PendingAttestation<E>, E::MaxPendingAttestations>,
|
||||
#[superstruct(only(Base))]
|
||||
#[superstruct(feature(not(Altair)))]
|
||||
#[test_random(default)]
|
||||
pub current_epoch_attestations: List<PendingAttestation<E>, E::MaxPendingAttestations>,
|
||||
|
||||
// Participation (Altair and later)
|
||||
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra))]
|
||||
#[superstruct(feature(Altair))]
|
||||
#[test_random(default)]
|
||||
pub previous_epoch_participation: List<ParticipationFlags, E::ValidatorRegistryLimit>,
|
||||
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra))]
|
||||
#[superstruct(feature(Altair))]
|
||||
#[test_random(default)]
|
||||
pub current_epoch_participation: List<ParticipationFlags, E::ValidatorRegistryLimit>,
|
||||
|
||||
@@ -415,15 +422,15 @@ where
|
||||
|
||||
// Inactivity
|
||||
#[serde(with = "ssz_types::serde_utils::quoted_u64_var_list")]
|
||||
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra))]
|
||||
#[superstruct(feature(Altair))]
|
||||
#[test_random(default)]
|
||||
pub inactivity_scores: List<u64, E::ValidatorRegistryLimit>,
|
||||
|
||||
// Light-client sync committees
|
||||
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra))]
|
||||
#[superstruct(feature(Altair))]
|
||||
#[metastruct(exclude_from(tree_lists))]
|
||||
pub current_sync_committee: Arc<SyncCommittee<E>>,
|
||||
#[superstruct(only(Altair, Bellatrix, Capella, Deneb, Electra))]
|
||||
#[superstruct(feature(Altair))]
|
||||
#[metastruct(exclude_from(tree_lists))]
|
||||
pub next_sync_committee: Arc<SyncCommittee<E>>,
|
||||
|
||||
@@ -454,51 +461,51 @@ where
|
||||
pub latest_execution_payload_header: ExecutionPayloadHeaderElectra<E>,
|
||||
|
||||
// Capella
|
||||
#[superstruct(only(Capella, Deneb, Electra), partial_getter(copy))]
|
||||
#[superstruct(feature(Capella), partial_getter(copy))]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
#[metastruct(exclude_from(tree_lists))]
|
||||
pub next_withdrawal_index: u64,
|
||||
#[superstruct(only(Capella, Deneb, Electra), partial_getter(copy))]
|
||||
#[superstruct(feature(Capella), partial_getter(copy))]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
#[metastruct(exclude_from(tree_lists))]
|
||||
pub next_withdrawal_validator_index: u64,
|
||||
// Deep history valid from Capella onwards.
|
||||
#[superstruct(only(Capella, Deneb, Electra))]
|
||||
#[superstruct(feature(Capella))]
|
||||
#[test_random(default)]
|
||||
pub historical_summaries: List<HistoricalSummary, E::HistoricalRootsLimit>,
|
||||
|
||||
// Electra
|
||||
#[superstruct(only(Electra), partial_getter(copy))]
|
||||
#[superstruct(feature(Electra), partial_getter(copy))]
|
||||
#[metastruct(exclude_from(tree_lists))]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub deposit_receipts_start_index: u64,
|
||||
#[superstruct(only(Electra), partial_getter(copy))]
|
||||
#[superstruct(feature(Electra), partial_getter(copy))]
|
||||
#[metastruct(exclude_from(tree_lists))]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub deposit_balance_to_consume: u64,
|
||||
#[superstruct(only(Electra), partial_getter(copy))]
|
||||
#[superstruct(feature(Electra), partial_getter(copy))]
|
||||
#[metastruct(exclude_from(tree_lists))]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub exit_balance_to_consume: u64,
|
||||
#[superstruct(only(Electra), partial_getter(copy))]
|
||||
#[superstruct(feature(Electra), partial_getter(copy))]
|
||||
#[metastruct(exclude_from(tree_lists))]
|
||||
pub earliest_exit_epoch: Epoch,
|
||||
#[superstruct(only(Electra), partial_getter(copy))]
|
||||
#[superstruct(feature(Electra), partial_getter(copy))]
|
||||
#[metastruct(exclude_from(tree_lists))]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub consolidation_balance_to_consume: u64,
|
||||
#[superstruct(only(Electra), partial_getter(copy))]
|
||||
#[superstruct(feature(Electra), partial_getter(copy))]
|
||||
#[metastruct(exclude_from(tree_lists))]
|
||||
pub earliest_consolidation_epoch: Epoch,
|
||||
#[test_random(default)]
|
||||
#[superstruct(only(Electra))]
|
||||
#[superstruct(feature(Electra))]
|
||||
pub pending_balance_deposits: List<PendingBalanceDeposit, E::PendingBalanceDepositsLimit>,
|
||||
#[test_random(default)]
|
||||
#[superstruct(only(Electra))]
|
||||
#[superstruct(feature(Electra))]
|
||||
pub pending_partial_withdrawals:
|
||||
List<PendingPartialWithdrawal, E::PendingPartialWithdrawalsLimit>,
|
||||
#[test_random(default)]
|
||||
#[superstruct(only(Electra))]
|
||||
#[superstruct(feature(Electra))]
|
||||
pub pending_consolidations: List<PendingConsolidation, E::PendingConsolidationsLimit>,
|
||||
|
||||
// Caching (not in the spec)
|
||||
@@ -628,20 +635,6 @@ impl<E: EthSpec> BeaconState<E> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the name of the fork pertaining to `self`.
|
||||
///
|
||||
/// Does not check if `self` is consistent with the fork dictated by `self.slot()`.
|
||||
pub fn fork_name_unchecked(&self) -> ForkName {
|
||||
match self {
|
||||
BeaconState::Base { .. } => ForkName::Base,
|
||||
BeaconState::Altair { .. } => ForkName::Altair,
|
||||
BeaconState::Bellatrix { .. } => ForkName::Bellatrix,
|
||||
BeaconState::Capella { .. } => ForkName::Capella,
|
||||
BeaconState::Deneb { .. } => ForkName::Deneb,
|
||||
BeaconState::Electra { .. } => ForkName::Electra,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the `tree_hash_root` of the state.
|
||||
///
|
||||
/// Spec v0.12.1
|
||||
@@ -1586,16 +1579,14 @@ impl<E: EthSpec> BeaconState<E> {
|
||||
///
|
||||
/// Uses the current epoch committee cache, and will error if it isn't initialized.
|
||||
pub fn get_activation_churn_limit(&self, spec: &ChainSpec) -> Result<u64, Error> {
|
||||
Ok(match self {
|
||||
BeaconState::Base(_)
|
||||
| BeaconState::Altair(_)
|
||||
| BeaconState::Bellatrix(_)
|
||||
| BeaconState::Capella(_) => self.get_validator_churn_limit(spec)?,
|
||||
BeaconState::Deneb(_) | BeaconState::Electra(_) => std::cmp::min(
|
||||
if self.has_feature(FeatureName::Deneb) {
|
||||
Ok(std::cmp::min(
|
||||
spec.max_per_epoch_activation_churn_limit,
|
||||
self.get_validator_churn_limit(spec)?,
|
||||
),
|
||||
})
|
||||
))
|
||||
} else {
|
||||
Ok(self.get_validator_churn_limit(spec)?)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the `slot`, `index`, `committee_position` and `committee_len` for which a validator must produce an
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::{
|
||||
NUM_FLAG_INDICES, TIMELY_HEAD_FLAG_INDEX, TIMELY_SOURCE_FLAG_INDEX,
|
||||
TIMELY_TARGET_FLAG_INDEX,
|
||||
},
|
||||
BeaconState, BeaconStateError, ChainSpec, Epoch, EthSpec, ParticipationFlags,
|
||||
BeaconStateError, ChainSpec, Epoch, ParticipationFlags,
|
||||
};
|
||||
use arbitrary::Arbitrary;
|
||||
use safe_arith::SafeArith;
|
||||
@@ -282,15 +282,3 @@ impl ProgressiveBalancesCache {
|
||||
.ok_or(BeaconStateError::ProgressiveBalancesCacheNotInitialized)
|
||||
}
|
||||
}
|
||||
|
||||
/// `ProgressiveBalancesCache` is only enabled from `Altair` as it uses Altair-specific logic.
|
||||
pub fn is_progressive_balances_enabled<E: EthSpec>(state: &BeaconState<E>) -> bool {
|
||||
match state {
|
||||
BeaconState::Base(_) => false,
|
||||
BeaconState::Altair(_)
|
||||
| BeaconState::Bellatrix(_)
|
||||
| BeaconState::Capella(_)
|
||||
| BeaconState::Deneb(_)
|
||||
| BeaconState::Electra(_) => true,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,8 @@ use crate::beacon_block_body::KzgCommitments;
|
||||
use crate::{
|
||||
ChainSpec, EthSpec, ExecutionPayloadHeaderBellatrix, ExecutionPayloadHeaderCapella,
|
||||
ExecutionPayloadHeaderDeneb, ExecutionPayloadHeaderElectra, ExecutionPayloadHeaderRef,
|
||||
ExecutionPayloadHeaderRefMut, ForkName, ForkVersionDeserialize, SignedRoot, Uint256,
|
||||
ExecutionPayloadHeaderRefMut, FeatureName, ForkName, ForkVersionDeserialize, SignedRoot,
|
||||
Uint256,
|
||||
};
|
||||
use bls::PublicKeyBytes;
|
||||
use bls::Signature;
|
||||
@@ -11,7 +12,15 @@ use superstruct::superstruct;
|
||||
use tree_hash_derive::TreeHash;
|
||||
|
||||
#[superstruct(
|
||||
variants(Bellatrix, Capella, Deneb, Electra),
|
||||
feature(Bellatrix),
|
||||
variants_and_features_from = "FORK_ORDER",
|
||||
feature_dependencies = "FEATURE_DEPENDENCIES",
|
||||
variant_type(name = "ForkName", getter = "fork_name"),
|
||||
feature_type(
|
||||
name = "FeatureName",
|
||||
list = "list_all_features",
|
||||
check = "has_feature"
|
||||
),
|
||||
variant_attributes(
|
||||
derive(PartialEq, Debug, Serialize, Deserialize, TreeHash, Clone),
|
||||
serde(bound = "E: EthSpec", deny_unknown_fields)
|
||||
@@ -31,7 +40,7 @@ pub struct BuilderBid<E: EthSpec> {
|
||||
pub header: ExecutionPayloadHeaderDeneb<E>,
|
||||
#[superstruct(only(Electra), partial_getter(rename = "header_electra"))]
|
||||
pub header: ExecutionPayloadHeaderElectra<E>,
|
||||
#[superstruct(only(Deneb, Electra))]
|
||||
#[superstruct(feature(Deneb))]
|
||||
pub blob_kzg_commitments: KzgCommitments<E>,
|
||||
#[serde(with = "serde_utils::quoted_u256")]
|
||||
pub value: Uint256,
|
||||
|
||||
@@ -303,22 +303,13 @@ impl ChainSpec {
|
||||
|
||||
/// Returns the name of the fork which is active at `epoch`.
|
||||
pub fn fork_name_at_epoch(&self, epoch: Epoch) -> ForkName {
|
||||
match self.electra_fork_epoch {
|
||||
Some(fork_epoch) if epoch >= fork_epoch => ForkName::Electra,
|
||||
_ => match self.deneb_fork_epoch {
|
||||
Some(fork_epoch) if epoch >= fork_epoch => ForkName::Deneb,
|
||||
_ => match self.capella_fork_epoch {
|
||||
Some(fork_epoch) if epoch >= fork_epoch => ForkName::Capella,
|
||||
_ => match self.bellatrix_fork_epoch {
|
||||
Some(fork_epoch) if epoch >= fork_epoch => ForkName::Bellatrix,
|
||||
_ => match self.altair_fork_epoch {
|
||||
Some(fork_epoch) if epoch >= fork_epoch => ForkName::Altair,
|
||||
_ => ForkName::Base,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
for (fork_name, _) in FORK_ORDER.iter().copied().rev() {
|
||||
match self.fork_epoch(fork_name) {
|
||||
Some(fork_epoch) if epoch >= fork_epoch => return fork_name,
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
ForkName::Base
|
||||
}
|
||||
|
||||
/// Returns the fork version for a named fork.
|
||||
@@ -346,9 +337,10 @@ impl ChainSpec {
|
||||
}
|
||||
|
||||
pub fn inactivity_penalty_quotient_for_fork(&self, fork_name: ForkName) -> u64 {
|
||||
if fork_name >= ForkName::Bellatrix {
|
||||
// TODO(superstruct_features) Is this a better pattern?
|
||||
if fork_name.has_feature(FeatureName::Bellatrix) {
|
||||
self.inactivity_penalty_quotient_bellatrix
|
||||
} else if fork_name >= ForkName::Altair {
|
||||
} else if fork_name.has_feature(FeatureName::Altair) {
|
||||
self.inactivity_penalty_quotient_altair
|
||||
} else {
|
||||
self.inactivity_penalty_quotient
|
||||
@@ -361,9 +353,9 @@ impl ChainSpec {
|
||||
state: &BeaconState<E>,
|
||||
) -> u64 {
|
||||
let fork_name = state.fork_name_unchecked();
|
||||
if fork_name >= ForkName::Bellatrix {
|
||||
if fork_name.has_feature(FeatureName::Bellatrix) {
|
||||
self.proportional_slashing_multiplier_bellatrix
|
||||
} else if fork_name >= ForkName::Altair {
|
||||
} else if fork_name.has_feature(FeatureName::Altair) {
|
||||
self.proportional_slashing_multiplier_altair
|
||||
} else {
|
||||
self.proportional_slashing_multiplier
|
||||
@@ -376,11 +368,11 @@ impl ChainSpec {
|
||||
state: &BeaconState<E>,
|
||||
) -> u64 {
|
||||
let fork_name = state.fork_name_unchecked();
|
||||
if fork_name >= ForkName::Electra {
|
||||
if fork_name.has_feature(FeatureName::Electra) {
|
||||
self.min_slashing_penalty_quotient_electra
|
||||
} else if fork_name >= ForkName::Bellatrix {
|
||||
} else if fork_name.has_feature(FeatureName::Bellatrix) {
|
||||
self.min_slashing_penalty_quotient_bellatrix
|
||||
} else if fork_name >= ForkName::Altair {
|
||||
} else if fork_name.has_feature(FeatureName::Altair) {
|
||||
self.min_slashing_penalty_quotient_altair
|
||||
} else {
|
||||
self.min_slashing_penalty_quotient
|
||||
@@ -546,7 +538,7 @@ impl ChainSpec {
|
||||
}
|
||||
|
||||
pub fn max_blocks_by_root_request(&self, fork_name: ForkName) -> usize {
|
||||
if fork_name >= ForkName::Deneb {
|
||||
if fork_name.has_feature(FeatureName::Deneb) {
|
||||
self.max_blocks_by_root_request_deneb
|
||||
} else {
|
||||
self.max_blocks_by_root_request
|
||||
@@ -554,7 +546,7 @@ impl ChainSpec {
|
||||
}
|
||||
|
||||
pub fn max_request_blocks(&self, fork_name: ForkName) -> usize {
|
||||
if fork_name >= ForkName::Deneb {
|
||||
if fork_name.has_feature(FeatureName::Deneb) {
|
||||
self.max_request_blocks_deneb as usize
|
||||
} else {
|
||||
self.max_request_blocks as usize
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
consts::altair, consts::deneb, AltairPreset, BasePreset, BellatrixPreset, CapellaPreset,
|
||||
ChainSpec, Config, DenebPreset, ElectraPreset, EthSpec, ForkName,
|
||||
ChainSpec, Config, DenebPreset, ElectraPreset, EthSpec, FeatureName, ForkName,
|
||||
};
|
||||
use maplit::hashmap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -12,7 +12,15 @@ use superstruct::superstruct;
|
||||
///
|
||||
/// Mostly useful for the API.
|
||||
#[superstruct(
|
||||
variants(Capella, Deneb, Electra),
|
||||
feature(Capella),
|
||||
variants_and_features_from = "FORK_ORDER",
|
||||
feature_dependencies = "FEATURE_DEPENDENCIES",
|
||||
variant_type(name = "ForkName", getter = "fork_name"),
|
||||
feature_type(
|
||||
name = "FeatureName",
|
||||
list = "list_all_features",
|
||||
check = "has_feature"
|
||||
),
|
||||
variant_attributes(derive(Serialize, Deserialize, Debug, PartialEq, Clone))
|
||||
)]
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
|
||||
@@ -29,10 +37,10 @@ pub struct ConfigAndPreset {
|
||||
pub bellatrix_preset: BellatrixPreset,
|
||||
#[serde(flatten)]
|
||||
pub capella_preset: CapellaPreset,
|
||||
#[superstruct(only(Deneb, Electra))]
|
||||
#[superstruct(feature(Deneb))]
|
||||
#[serde(flatten)]
|
||||
pub deneb_preset: DenebPreset,
|
||||
#[superstruct(only(Electra))]
|
||||
#[superstruct(feature(Electra))]
|
||||
#[serde(flatten)]
|
||||
pub electra_preset: ElectraPreset,
|
||||
/// The `extra_fields` map allows us to gracefully decode fields intended for future hard forks.
|
||||
|
||||
@@ -15,7 +15,15 @@ pub type Transactions<E> = VariableList<
|
||||
pub type Withdrawals<E> = VariableList<Withdrawal, <E as EthSpec>::MaxWithdrawalsPerPayload>;
|
||||
|
||||
#[superstruct(
|
||||
variants(Bellatrix, Capella, Deneb, Electra),
|
||||
feature(Bellatrix),
|
||||
variants_and_features_from = "FORK_ORDER",
|
||||
feature_dependencies = "FEATURE_DEPENDENCIES",
|
||||
variant_type(name = "ForkName", getter = "fork_name"),
|
||||
feature_type(
|
||||
name = "FeatureName",
|
||||
list = "list_all_features",
|
||||
check = "has_feature"
|
||||
),
|
||||
variant_attributes(
|
||||
derive(
|
||||
Default,
|
||||
@@ -81,12 +89,12 @@ pub struct ExecutionPayload<E: EthSpec> {
|
||||
pub block_hash: ExecutionBlockHash,
|
||||
#[serde(with = "ssz_types::serde_utils::list_of_hex_var_list")]
|
||||
pub transactions: Transactions<E>,
|
||||
#[superstruct(only(Capella, Deneb, Electra))]
|
||||
#[superstruct(feature(Capella))]
|
||||
pub withdrawals: Withdrawals<E>,
|
||||
#[superstruct(only(Deneb, Electra), partial_getter(copy))]
|
||||
#[superstruct(feature(Deneb))]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub blob_gas_used: u64,
|
||||
#[superstruct(only(Deneb, Electra), partial_getter(copy))]
|
||||
#[superstruct(feature(Deneb))]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub excess_blob_gas: u64,
|
||||
#[superstruct(only(Electra))]
|
||||
@@ -197,14 +205,3 @@ impl<E: EthSpec> ForkVersionDeserialize for ExecutionPayload<E> {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> ExecutionPayload<E> {
|
||||
pub fn fork_name(&self) -> ForkName {
|
||||
match self {
|
||||
ExecutionPayload::Bellatrix(_) => ForkName::Bellatrix,
|
||||
ExecutionPayload::Capella(_) => ForkName::Capella,
|
||||
ExecutionPayload::Deneb(_) => ForkName::Deneb,
|
||||
ExecutionPayload::Electra(_) => ForkName::Electra,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,15 @@ use tree_hash::TreeHash;
|
||||
use tree_hash_derive::TreeHash;
|
||||
|
||||
#[superstruct(
|
||||
variants(Bellatrix, Capella, Deneb, Electra),
|
||||
feature(Bellatrix),
|
||||
variants_and_features_from = "FORK_ORDER",
|
||||
feature_dependencies = "FEATURE_DEPENDENCIES",
|
||||
variant_type(name = "ForkName", getter = "fork_name"),
|
||||
feature_type(
|
||||
name = "FeatureName",
|
||||
list = "list_all_features",
|
||||
check = "has_feature"
|
||||
),
|
||||
variant_attributes(
|
||||
derive(
|
||||
Default,
|
||||
@@ -77,14 +85,14 @@ pub struct ExecutionPayloadHeader<E: EthSpec> {
|
||||
pub block_hash: ExecutionBlockHash,
|
||||
#[superstruct(getter(copy))]
|
||||
pub transactions_root: Hash256,
|
||||
#[superstruct(only(Capella, Deneb, Electra))]
|
||||
#[superstruct(feature(Capella))]
|
||||
#[superstruct(getter(copy))]
|
||||
pub withdrawals_root: Hash256,
|
||||
#[superstruct(only(Deneb, Electra))]
|
||||
#[superstruct(feature(Deneb))]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
#[superstruct(getter(copy))]
|
||||
pub blob_gas_used: u64,
|
||||
#[superstruct(only(Deneb, Electra))]
|
||||
#[superstruct(feature(Deneb))]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
#[superstruct(getter(copy))]
|
||||
pub excess_blob_gas: u64,
|
||||
|
||||
18
consensus/types/src/feature_name.rs
Normal file
18
consensus/types/src/feature_name.rs
Normal file
@@ -0,0 +1,18 @@
|
||||
// A list of all individual features that are available.
|
||||
// We can gate parts of the code behind checks that ensure a feature is active.
|
||||
//
|
||||
// For now, older Forks have a single "super-feature" which contains all features associated with
|
||||
// that Fork. It may be worth splitting these up at a later time.
|
||||
#[derive(PartialEq, Clone, Copy, Debug)]
|
||||
pub enum FeatureName {
|
||||
// Altair.
|
||||
Altair,
|
||||
// Bellatrix.
|
||||
Bellatrix,
|
||||
// Capella.
|
||||
Capella,
|
||||
// Deneb.
|
||||
Deneb,
|
||||
// Electra.
|
||||
Electra,
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
use crate::{ChainSpec, Epoch};
|
||||
use crate::fork_order::FORK_ORDER;
|
||||
use crate::{ChainSpec, Epoch, FeatureName};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use std::cmp::{Ord, Ordering};
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(
|
||||
Debug, Clone, Copy, Decode, Encode, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
|
||||
)]
|
||||
#[derive(Debug, Clone, Copy, Decode, Encode, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[serde(try_from = "String")]
|
||||
#[serde(into = "String")]
|
||||
#[ssz(enum_behaviour = "tag")]
|
||||
@@ -19,21 +19,48 @@ pub enum ForkName {
|
||||
Electra,
|
||||
}
|
||||
|
||||
impl PartialOrd for ForkName {
|
||||
fn partial_cmp(&self, other: &ForkName) -> Option<Ordering> {
|
||||
let self_idx = FORK_ORDER
|
||||
.iter()
|
||||
.position(|(fork_name, _)| fork_name == self);
|
||||
let other_idx = FORK_ORDER
|
||||
.iter()
|
||||
.position(|(fork_name, _)| fork_name == other);
|
||||
|
||||
// Forks that are not enabled will come back as `None`. Treat them as greater than all
|
||||
// enabled forks (and equal to each other).
|
||||
match (self_idx, other_idx) {
|
||||
(None, None) => None, // incomparable
|
||||
(None, Some(_)) => Some(Ordering::Greater),
|
||||
(Some(_), None) => Some(Ordering::Less),
|
||||
(Some(i), Some(j)) => Some(i.cmp(&j)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ForkName {
|
||||
pub fn list_all() -> Vec<ForkName> {
|
||||
vec![
|
||||
ForkName::Base,
|
||||
ForkName::Altair,
|
||||
ForkName::Bellatrix,
|
||||
ForkName::Capella,
|
||||
ForkName::Deneb,
|
||||
ForkName::Electra,
|
||||
]
|
||||
FORK_ORDER.iter().map(|(fork, _)| *fork).collect()
|
||||
}
|
||||
|
||||
pub fn latest() -> ForkName {
|
||||
// This unwrap is safe as long as we have 1+ forks. It is tested below.
|
||||
*ForkName::list_all().last().unwrap()
|
||||
pub const fn latest() -> ForkName {
|
||||
#[allow(clippy::arithmetic_side_effects, clippy::indexing_slicing)]
|
||||
FORK_ORDER[FORK_ORDER.len() - 1].0
|
||||
}
|
||||
|
||||
pub fn list_all_enabled_features(self) -> Vec<FeatureName> {
|
||||
let mut all_features = vec![];
|
||||
for (fork, features) in FORK_ORDER {
|
||||
if *fork <= self {
|
||||
all_features.extend(features.iter());
|
||||
}
|
||||
}
|
||||
all_features
|
||||
}
|
||||
|
||||
pub fn has_feature(self, feature: FeatureName) -> bool {
|
||||
self.list_all_enabled_features().contains(&feature)
|
||||
}
|
||||
|
||||
/// Set the activation slots in the given `ChainSpec` so that the fork named by `self`
|
||||
@@ -283,4 +310,51 @@ mod test {
|
||||
assert!(prev_fork < fork);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_fork_name_enabled_features() {
|
||||
let base = ForkName::Base;
|
||||
let altair = ForkName::Altair;
|
||||
let bellatrix = ForkName::Bellatrix;
|
||||
let capella = ForkName::Capella;
|
||||
let deneb = ForkName::Deneb;
|
||||
let electra = ForkName::Electra;
|
||||
|
||||
assert_eq!(base.list_all_enabled_features(), vec![]);
|
||||
assert_eq!(
|
||||
altair.list_all_enabled_features(),
|
||||
vec![FeatureName::Altair]
|
||||
);
|
||||
assert_eq!(
|
||||
bellatrix.list_all_enabled_features(),
|
||||
vec![FeatureName::Altair, FeatureName::Bellatrix]
|
||||
);
|
||||
assert_eq!(
|
||||
capella.list_all_enabled_features(),
|
||||
vec![
|
||||
FeatureName::Altair,
|
||||
FeatureName::Bellatrix,
|
||||
FeatureName::Capella
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
deneb.list_all_enabled_features(),
|
||||
vec![
|
||||
FeatureName::Altair,
|
||||
FeatureName::Bellatrix,
|
||||
FeatureName::Capella,
|
||||
FeatureName::Deneb
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
electra.list_all_enabled_features(),
|
||||
vec![
|
||||
FeatureName::Altair,
|
||||
FeatureName::Bellatrix,
|
||||
FeatureName::Capella,
|
||||
FeatureName::Deneb,
|
||||
FeatureName::Electra
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
36
consensus/types/src/fork_order.rs
Normal file
36
consensus/types/src/fork_order.rs
Normal file
@@ -0,0 +1,36 @@
|
||||
use crate::{FeatureName, ForkName};
|
||||
use superstruct::superstruct;
|
||||
|
||||
#[superstruct(variants_and_features_decl = "FORK_ORDER")]
|
||||
pub const FORK_ORDER: &[(ForkName, &[FeatureName])] = &[
|
||||
(ForkName::Base, &[]),
|
||||
(ForkName::Altair, &[FeatureName::Altair]),
|
||||
(ForkName::Bellatrix, &[FeatureName::Bellatrix]),
|
||||
(ForkName::Capella, &[FeatureName::Capella]),
|
||||
(ForkName::Deneb, &[FeatureName::Deneb]),
|
||||
(ForkName::Electra, &[FeatureName::Electra]),
|
||||
];
|
||||
|
||||
#[superstruct(feature_dependencies_decl = "FEATURE_DEPENDENCIES")]
|
||||
pub const FEATURE_DEPENDENCIES: &[(FeatureName, &[FeatureName])] = &[
|
||||
(FeatureName::Altair, &[]),
|
||||
(FeatureName::Bellatrix, &[FeatureName::Altair]),
|
||||
(FeatureName::Capella, &[FeatureName::Bellatrix]),
|
||||
(FeatureName::Deneb, &[FeatureName::Capella]),
|
||||
(FeatureName::Electra, &[FeatureName::Deneb]),
|
||||
];
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use itertools::Itertools;
|
||||
|
||||
#[test]
|
||||
fn partial_ord_sanity_check() {
|
||||
for (fork_a, fork_b) in FORK_ORDER.iter().map(|(fork, _)| fork).tuple_windows() {
|
||||
assert!(fork_a < fork_b, "{fork_a} < {fork_b}");
|
||||
assert_eq!(fork_a, fork_a);
|
||||
assert_eq!(fork_b, fork_b);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -44,9 +44,11 @@ pub mod execution_block_hash;
|
||||
pub mod execution_layer_withdrawal_request;
|
||||
pub mod execution_payload;
|
||||
pub mod execution_payload_header;
|
||||
pub mod feature_name;
|
||||
pub mod fork;
|
||||
pub mod fork_data;
|
||||
pub mod fork_name;
|
||||
pub mod fork_order;
|
||||
pub mod fork_versioned_response;
|
||||
pub mod graffiti;
|
||||
pub mod historical_batch;
|
||||
@@ -162,10 +164,12 @@ pub use crate::execution_payload_header::{
|
||||
ExecutionPayloadHeaderDeneb, ExecutionPayloadHeaderElectra, ExecutionPayloadHeaderRef,
|
||||
ExecutionPayloadHeaderRefMut,
|
||||
};
|
||||
pub use crate::feature_name::FeatureName;
|
||||
pub use crate::fork::Fork;
|
||||
pub use crate::fork_context::ForkContext;
|
||||
pub use crate::fork_data::ForkData;
|
||||
pub use crate::fork_name::{ForkName, InconsistentFork};
|
||||
pub use crate::fork_order::FORK_ORDER;
|
||||
pub use crate::fork_versioned_response::{ForkVersionDeserialize, ForkVersionedResponse};
|
||||
pub use crate::graffiti::{Graffiti, GRAFFITI_BYTES_LEN};
|
||||
pub use crate::historical_batch::HistoricalBatch;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use crate::ChainSpec;
|
||||
use crate::ForkName;
|
||||
use crate::ForkVersionDeserialize;
|
||||
use crate::{light_client_update::*, BeaconBlockBody};
|
||||
use crate::{
|
||||
@@ -7,6 +6,7 @@ use crate::{
|
||||
FixedVector, Hash256, SignedBeaconBlock,
|
||||
};
|
||||
use crate::{BeaconBlockHeader, ExecutionPayloadHeader};
|
||||
use crate::{FeatureName, ForkName};
|
||||
use derivative::Derivative;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz::Decode;
|
||||
@@ -17,7 +17,15 @@ use test_random_derive::TestRandom;
|
||||
use tree_hash_derive::TreeHash;
|
||||
|
||||
#[superstruct(
|
||||
variants(Altair, Capella, Deneb),
|
||||
feature(Altair),
|
||||
variants_and_features_from = "FORK_ORDER",
|
||||
feature_dependencies = "FEATURE_DEPENDENCIES",
|
||||
variant_type(name = "ForkName", getter = "fork_name"),
|
||||
feature_type(
|
||||
name = "FeatureName",
|
||||
list = "list_all_features",
|
||||
check = "has_feature"
|
||||
),
|
||||
variant_attributes(
|
||||
derive(
|
||||
Debug,
|
||||
@@ -55,7 +63,7 @@ pub struct LightClientHeader<E: EthSpec> {
|
||||
#[superstruct(only(Deneb), partial_getter(rename = "execution_payload_header_deneb"))]
|
||||
pub execution: ExecutionPayloadHeaderDeneb<E>,
|
||||
|
||||
#[superstruct(only(Capella, Deneb))]
|
||||
#[superstruct(feature(Capella))]
|
||||
pub execution_branch: FixedVector<Hash256, ExecutionPayloadProofLen>,
|
||||
|
||||
#[ssz(skip_serializing, skip_deserializing)]
|
||||
|
||||
@@ -110,7 +110,15 @@ pub trait AbstractExecPayload<E: EthSpec>:
|
||||
}
|
||||
|
||||
#[superstruct(
|
||||
variants(Bellatrix, Capella, Deneb, Electra),
|
||||
feature(Bellatrix),
|
||||
variants_and_features_from = "FORK_ORDER",
|
||||
feature_dependencies = "FEATURE_DEPENDENCIES",
|
||||
variant_type(name = "ForkName", getter = "fork_name"),
|
||||
feature_type(
|
||||
name = "FeatureName",
|
||||
list = "list_all_features",
|
||||
check = "has_feature"
|
||||
),
|
||||
variant_attributes(
|
||||
derive(
|
||||
Debug,
|
||||
@@ -447,7 +455,15 @@ impl<E: EthSpec> TryFrom<ExecutionPayloadHeader<E>> for FullPayload<E> {
|
||||
}
|
||||
|
||||
#[superstruct(
|
||||
variants(Bellatrix, Capella, Deneb, Electra),
|
||||
feature(Bellatrix),
|
||||
variants_and_features_from = "FORK_ORDER",
|
||||
feature_dependencies = "FEATURE_DEPENDENCIES",
|
||||
variant_type(name = "ForkName", getter = "fork_name"),
|
||||
feature_type(
|
||||
name = "FeatureName",
|
||||
list = "list_all_features",
|
||||
check = "has_feature"
|
||||
),
|
||||
variant_attributes(
|
||||
derive(
|
||||
Debug,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
test_utils::TestRandom, ChainSpec, Domain, Epoch, ForkName, Hash256, SecretKey, SignedRoot,
|
||||
SignedVoluntaryExit,
|
||||
test_utils::TestRandom, ChainSpec, Domain, Epoch, FeatureName, ForkName, Hash256, SecretKey,
|
||||
SignedRoot, SignedVoluntaryExit,
|
||||
};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -41,12 +41,11 @@ impl VoluntaryExit {
|
||||
spec: &ChainSpec,
|
||||
) -> SignedVoluntaryExit {
|
||||
let fork_name = spec.fork_name_at_epoch(self.epoch);
|
||||
let fork_version = match fork_name {
|
||||
ForkName::Base | ForkName::Altair | ForkName::Bellatrix | ForkName::Capella => {
|
||||
spec.fork_version_for_name(fork_name)
|
||||
}
|
||||
// EIP-7044
|
||||
ForkName::Deneb | ForkName::Electra => spec.fork_version_for_name(ForkName::Capella),
|
||||
// EIP-7044
|
||||
let fork_version = if fork_name.has_feature(FeatureName::Deneb) {
|
||||
spec.fork_version_for_name(ForkName::Capella)
|
||||
} else {
|
||||
spec.fork_version_for_name(fork_name)
|
||||
};
|
||||
let domain =
|
||||
spec.compute_domain(Domain::VoluntaryExit, fork_version, genesis_validators_root);
|
||||
|
||||
1
feature_deps.bak
Normal file
1
feature_deps.bak
Normal file
@@ -0,0 +1 @@
|
||||
[["Altair",[]],["Bellatrix",["Altair"]],["Capella",["Bellatrix"]],["Deneb",["Capella"]],["Electra",["Deneb"]]]
|
||||
1
fork_order.bak
Normal file
1
fork_order.bak
Normal file
@@ -0,0 +1 @@
|
||||
[["Base"],[]],["Altair",["Altair"]],["Bellatrix",["Bellatrix"]],["Capella",["Capella"]],["Deneb",["Deneb"]],["Electra",["Electra"]]]
|
||||
@@ -19,7 +19,7 @@ use state_processing::per_epoch_processing::{
|
||||
};
|
||||
use state_processing::EpochProcessingError;
|
||||
use std::marker::PhantomData;
|
||||
use types::BeaconState;
|
||||
use types::{BeaconState, FeatureName};
|
||||
|
||||
#[derive(Debug, Clone, Default, Deserialize)]
|
||||
pub struct Metadata {
|
||||
@@ -91,47 +91,35 @@ type_name!(ParticipationFlagUpdates, "participation_flag_updates");
|
||||
|
||||
impl<E: EthSpec> EpochTransition<E> for JustificationAndFinalization {
|
||||
fn run(state: &mut BeaconState<E>, spec: &ChainSpec) -> Result<(), EpochProcessingError> {
|
||||
match state {
|
||||
BeaconState::Base(_) => {
|
||||
let mut validator_statuses = base::ValidatorStatuses::new(state, spec)?;
|
||||
validator_statuses.process_attestations(state)?;
|
||||
let justification_and_finalization_state =
|
||||
base::process_justification_and_finalization(
|
||||
state,
|
||||
&validator_statuses.total_balances,
|
||||
spec,
|
||||
)?;
|
||||
justification_and_finalization_state.apply_changes_to_state(state);
|
||||
Ok(())
|
||||
}
|
||||
BeaconState::Altair(_)
|
||||
| BeaconState::Bellatrix(_)
|
||||
| BeaconState::Capella(_)
|
||||
| BeaconState::Deneb(_)
|
||||
| BeaconState::Electra(_) => {
|
||||
initialize_progressive_balances_cache(state, spec)?;
|
||||
let justification_and_finalization_state =
|
||||
altair::process_justification_and_finalization(state)?;
|
||||
justification_and_finalization_state.apply_changes_to_state(state);
|
||||
Ok(())
|
||||
}
|
||||
if state.has_feature(FeatureName::Altair) {
|
||||
initialize_progressive_balances_cache(state, spec)?;
|
||||
let justification_and_finalization_state =
|
||||
altair::process_justification_and_finalization(state)?;
|
||||
justification_and_finalization_state.apply_changes_to_state(state);
|
||||
Ok(())
|
||||
} else {
|
||||
let mut validator_statuses = base::ValidatorStatuses::new(state, spec)?;
|
||||
validator_statuses.process_attestations(state)?;
|
||||
let justification_and_finalization_state =
|
||||
base::process_justification_and_finalization(
|
||||
state,
|
||||
&validator_statuses.total_balances,
|
||||
spec,
|
||||
)?;
|
||||
justification_and_finalization_state.apply_changes_to_state(state);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> EpochTransition<E> for RewardsAndPenalties {
|
||||
fn run(state: &mut BeaconState<E>, spec: &ChainSpec) -> Result<(), EpochProcessingError> {
|
||||
match state {
|
||||
BeaconState::Base(_) => {
|
||||
let mut validator_statuses = base::ValidatorStatuses::new(state, spec)?;
|
||||
validator_statuses.process_attestations(state)?;
|
||||
base::process_rewards_and_penalties(state, &validator_statuses, spec)
|
||||
}
|
||||
BeaconState::Altair(_)
|
||||
| BeaconState::Bellatrix(_)
|
||||
| BeaconState::Capella(_)
|
||||
| BeaconState::Deneb(_)
|
||||
| BeaconState::Electra(_) => altair::process_rewards_and_penalties_slow(state, spec),
|
||||
if state.has_feature(FeatureName::Altair) {
|
||||
altair::process_rewards_and_penalties_slow(state, spec)
|
||||
} else {
|
||||
let mut validator_statuses = base::ValidatorStatuses::new(state, spec)?;
|
||||
validator_statuses.process_attestations(state)?;
|
||||
base::process_rewards_and_penalties(state, &validator_statuses, spec)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -150,24 +138,18 @@ impl<E: EthSpec> EpochTransition<E> for RegistryUpdates {
|
||||
|
||||
impl<E: EthSpec> EpochTransition<E> for Slashings {
|
||||
fn run(state: &mut BeaconState<E>, spec: &ChainSpec) -> Result<(), EpochProcessingError> {
|
||||
match state {
|
||||
BeaconState::Base(_) => {
|
||||
let mut validator_statuses = base::ValidatorStatuses::new(state, spec)?;
|
||||
validator_statuses.process_attestations(state)?;
|
||||
process_slashings(
|
||||
state,
|
||||
validator_statuses.total_balances.current_epoch(),
|
||||
spec,
|
||||
)?;
|
||||
}
|
||||
BeaconState::Altair(_)
|
||||
| BeaconState::Bellatrix(_)
|
||||
| BeaconState::Capella(_)
|
||||
| BeaconState::Deneb(_)
|
||||
| BeaconState::Electra(_) => {
|
||||
process_slashings_slow(state, spec)?;
|
||||
}
|
||||
};
|
||||
if state.has_feature(FeatureName::Altair) {
|
||||
process_slashings_slow(state, spec)?;
|
||||
} else {
|
||||
let mut validator_statuses = base::ValidatorStatuses::new(state, spec)?;
|
||||
validator_statuses.process_attestations(state)?;
|
||||
process_slashings(
|
||||
state,
|
||||
validator_statuses.total_balances.current_epoch(),
|
||||
spec,
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -202,22 +184,20 @@ impl<E: EthSpec> EpochTransition<E> for RandaoMixesReset {
|
||||
|
||||
impl<E: EthSpec> EpochTransition<E> for HistoricalRootsUpdate {
|
||||
fn run(state: &mut BeaconState<E>, _spec: &ChainSpec) -> Result<(), EpochProcessingError> {
|
||||
match state {
|
||||
BeaconState::Base(_) | BeaconState::Altair(_) | BeaconState::Bellatrix(_) => {
|
||||
process_historical_roots_update(state)
|
||||
}
|
||||
_ => Ok(()),
|
||||
if state.has_feature(FeatureName::Capella) {
|
||||
Ok(())
|
||||
} else {
|
||||
process_historical_roots_update(state)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> EpochTransition<E> for HistoricalSummariesUpdate {
|
||||
fn run(state: &mut BeaconState<E>, _spec: &ChainSpec) -> Result<(), EpochProcessingError> {
|
||||
match state {
|
||||
BeaconState::Capella(_) | BeaconState::Deneb(_) | BeaconState::Electra(_) => {
|
||||
process_historical_summaries_update(state)
|
||||
}
|
||||
_ => Ok(()),
|
||||
if state.has_feature(FeatureName::Capella) {
|
||||
process_historical_summaries_update(state)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -234,39 +214,30 @@ impl<E: EthSpec> EpochTransition<E> for ParticipationRecordUpdates {
|
||||
|
||||
impl<E: EthSpec> EpochTransition<E> for SyncCommitteeUpdates {
|
||||
fn run(state: &mut BeaconState<E>, spec: &ChainSpec) -> Result<(), EpochProcessingError> {
|
||||
match state {
|
||||
BeaconState::Base(_) => Ok(()),
|
||||
BeaconState::Altair(_)
|
||||
| BeaconState::Bellatrix(_)
|
||||
| BeaconState::Capella(_)
|
||||
| BeaconState::Deneb(_)
|
||||
| BeaconState::Electra(_) => altair::process_sync_committee_updates(state, spec),
|
||||
if state.has_feature(FeatureName::Altair) {
|
||||
altair::process_sync_committee_updates(state, spec)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> EpochTransition<E> for InactivityUpdates {
|
||||
fn run(state: &mut BeaconState<E>, spec: &ChainSpec) -> Result<(), EpochProcessingError> {
|
||||
match state {
|
||||
BeaconState::Base(_) => Ok(()),
|
||||
BeaconState::Altair(_)
|
||||
| BeaconState::Bellatrix(_)
|
||||
| BeaconState::Capella(_)
|
||||
| BeaconState::Deneb(_)
|
||||
| BeaconState::Electra(_) => altair::process_inactivity_updates_slow(state, spec),
|
||||
if state.has_feature(FeatureName::Altair) {
|
||||
altair::process_inactivity_updates_slow(state, spec)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> EpochTransition<E> for ParticipationFlagUpdates {
|
||||
fn run(state: &mut BeaconState<E>, _: &ChainSpec) -> Result<(), EpochProcessingError> {
|
||||
match state {
|
||||
BeaconState::Base(_) => Ok(()),
|
||||
BeaconState::Altair(_)
|
||||
| BeaconState::Bellatrix(_)
|
||||
| BeaconState::Capella(_)
|
||||
| BeaconState::Deneb(_)
|
||||
| BeaconState::Electra(_) => altair::process_participation_flag_updates(state),
|
||||
if state.has_feature(FeatureName::Altair) {
|
||||
altair::process_participation_flag_updates(state)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -304,23 +275,18 @@ impl<E: EthSpec, T: EpochTransition<E>> Case for EpochProcessing<E, T> {
|
||||
}
|
||||
|
||||
fn is_enabled_for_fork(fork_name: ForkName) -> bool {
|
||||
match fork_name {
|
||||
// No phase0 tests for Altair and later.
|
||||
if fork_name.has_feature(FeatureName::Capella) {
|
||||
T::name() != "participation_record_updates" && T::name() != "historical_roots_update"
|
||||
} else if fork_name.has_feature(FeatureName::Altair) {
|
||||
T::name() != "participation_record_updates"
|
||||
&& T::name() != "historical_summaries_update"
|
||||
} else {
|
||||
// No Altair tests for genesis fork.
|
||||
ForkName::Base => {
|
||||
T::name() != "sync_committee_updates"
|
||||
&& T::name() != "inactivity_updates"
|
||||
&& T::name() != "participation_flag_updates"
|
||||
&& T::name() != "historical_summaries_update"
|
||||
}
|
||||
// No phase0 tests for Altair and later.
|
||||
ForkName::Altair | ForkName::Bellatrix => {
|
||||
T::name() != "participation_record_updates"
|
||||
&& T::name() != "historical_summaries_update"
|
||||
}
|
||||
ForkName::Capella | ForkName::Deneb | ForkName::Electra => {
|
||||
T::name() != "participation_record_updates"
|
||||
&& T::name() != "historical_roots_update"
|
||||
}
|
||||
T::name() != "sync_committee_updates"
|
||||
&& T::name() != "inactivity_updates"
|
||||
&& T::name() != "participation_flag_updates"
|
||||
&& T::name() != "historical_summaries_update"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ use std::fmt::Debug;
|
||||
use types::{
|
||||
Attestation, AttesterSlashing, BeaconBlock, BeaconBlockBody, BeaconBlockBodyBellatrix,
|
||||
BeaconBlockBodyCapella, BeaconBlockBodyDeneb, BeaconState, BlindedPayload, Deposit,
|
||||
ExecutionPayload, FullPayload, ProposerSlashing, SignedBlsToExecutionChange,
|
||||
ExecutionPayload, FeatureName, FullPayload, ProposerSlashing, SignedBlsToExecutionChange,
|
||||
SignedVoluntaryExit, SyncAggregate,
|
||||
};
|
||||
|
||||
@@ -90,29 +90,24 @@ impl<E: EthSpec> Operation<E> for Attestation<E> {
|
||||
) -> Result<(), BlockProcessingError> {
|
||||
initialize_epoch_cache(state, spec)?;
|
||||
let mut ctxt = ConsensusContext::new(state.slot());
|
||||
match state {
|
||||
BeaconState::Base(_) => base::process_attestations(
|
||||
if state.has_feature(FeatureName::Altair) {
|
||||
initialize_progressive_balances_cache(state, spec)?;
|
||||
altair_deneb::process_attestation(
|
||||
state,
|
||||
self,
|
||||
0,
|
||||
&mut ctxt,
|
||||
VerifySignatures::True,
|
||||
spec,
|
||||
)
|
||||
} else {
|
||||
base::process_attestations(
|
||||
state,
|
||||
&[self.clone()],
|
||||
VerifySignatures::True,
|
||||
&mut ctxt,
|
||||
spec,
|
||||
),
|
||||
BeaconState::Altair(_)
|
||||
| BeaconState::Bellatrix(_)
|
||||
| BeaconState::Capella(_)
|
||||
| BeaconState::Deneb(_)
|
||||
| BeaconState::Electra(_) => {
|
||||
initialize_progressive_balances_cache(state, spec)?;
|
||||
altair_deneb::process_attestation(
|
||||
state,
|
||||
self,
|
||||
0,
|
||||
&mut ctxt,
|
||||
VerifySignatures::True,
|
||||
spec,
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ use task_executor::TaskExecutor;
|
||||
use types::{
|
||||
attestation::Error as AttestationError, graffiti::GraffitiString, AbstractExecPayload, Address,
|
||||
AggregateAndProof, Attestation, BeaconBlock, BlindedPayload, ChainSpec, ContributionAndProof,
|
||||
Domain, Epoch, EthSpec, Fork, ForkName, Graffiti, Hash256, PublicKeyBytes, SelectionProof,
|
||||
Domain, Epoch, EthSpec, FeatureName, Fork, Graffiti, Hash256, PublicKeyBytes, SelectionProof,
|
||||
Signature, SignedAggregateAndProof, SignedBeaconBlock, SignedContributionAndProof, SignedRoot,
|
||||
SignedValidatorRegistrationData, SignedVoluntaryExit, Slot, SyncAggregatorSelectionData,
|
||||
SyncCommitteeContribution, SyncCommitteeMessage, SyncSelectionProof, SyncSubnetId,
|
||||
@@ -359,17 +359,13 @@ impl<T: SlotClock + 'static, E: EthSpec> ValidatorStore<T, E> {
|
||||
|
||||
fn signing_context(&self, domain: Domain, signing_epoch: Epoch) -> SigningContext {
|
||||
if domain == Domain::VoluntaryExit {
|
||||
match self.spec.fork_name_at_epoch(signing_epoch) {
|
||||
ForkName::Base | ForkName::Altair | ForkName::Bellatrix | ForkName::Capella => {
|
||||
SigningContext {
|
||||
domain,
|
||||
epoch: signing_epoch,
|
||||
fork: self.fork(signing_epoch),
|
||||
genesis_validators_root: self.genesis_validators_root,
|
||||
}
|
||||
}
|
||||
// EIP-7044
|
||||
ForkName::Deneb | ForkName::Electra => SigningContext {
|
||||
// EIP-7044
|
||||
if self
|
||||
.spec
|
||||
.fork_name_at_epoch(signing_epoch)
|
||||
.has_feature(FeatureName::Deneb)
|
||||
{
|
||||
SigningContext {
|
||||
domain,
|
||||
epoch: signing_epoch,
|
||||
fork: Fork {
|
||||
@@ -378,7 +374,14 @@ impl<T: SlotClock + 'static, E: EthSpec> ValidatorStore<T, E> {
|
||||
epoch: signing_epoch,
|
||||
},
|
||||
genesis_validators_root: self.genesis_validators_root,
|
||||
},
|
||||
}
|
||||
} else {
|
||||
SigningContext {
|
||||
domain,
|
||||
epoch: signing_epoch,
|
||||
fork: self.fork(signing_epoch),
|
||||
genesis_validators_root: self.genesis_validators_root,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
SigningContext {
|
||||
|
||||
Reference in New Issue
Block a user