diff --git a/Cargo.lock b/Cargo.lock index 0452fa0e8c..d6ea152d6e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7905,14 +7905,15 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "superstruct" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b9e5728aa1a87141cefd4e7509903fc01fa0dcb108022b1e841a67c5159fc5" +version = "0.7.0" +source = "git+https://github.com/sigp/superstruct?branch=features#06132f875603d2985a414e6e3683c42bc9505f49" dependencies = [ "darling", "itertools", "proc-macro2", "quote", + "serde", + "serde_json", "smallvec", "syn 1.0.109", ] diff --git a/Cargo.toml b/Cargo.toml index 24775b728d..6afda83b63 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -158,7 +158,7 @@ smallvec = "1.11.2" snap = "1" ssz_types = "0.5" strum = { version = "0.24", features = ["derive"] } -superstruct = "0.6" +superstruct = { git = "https://github.com/sigp/superstruct", branch = "features" } syn = "1" sysinfo = "0.26" tempfile = "3" diff --git a/consensus/types/build.rs b/consensus/types/build.rs new file mode 100644 index 0000000000..76a1c67d1c --- /dev/null +++ b/consensus/types/build.rs @@ -0,0 +1,2 @@ +// Dummy build.rs file to enable OUT_DIR usage by superstruct +fn main() {} diff --git a/consensus/types/src/beacon_block_body.rs b/consensus/types/src/beacon_block_body.rs index a55c16b80d..73aeb2c025 100644 --- a/consensus/types/src/beacon_block_body.rs +++ b/consensus/types/src/beacon_block_body.rs @@ -29,7 +29,8 @@ pub const BLOB_KZG_COMMITMENTS_INDEX: usize = 11; /// /// This *superstruct* abstracts over the hard-fork. #[superstruct( - variants(Base, Altair, Merge, Capella, Deneb, Electra), + variants_and_features_from = "FORK_ORDER", + feature_dependencies = "FEATURE_DEPENDENCIES", variant_attributes( derive( Debug, @@ -67,7 +68,7 @@ pub struct BeaconBlockBody = FullPay pub attestations: VariableList, E::MaxAttestations>, pub deposits: VariableList, pub voluntary_exits: VariableList, - #[superstruct(only(Altair, Merge, Capella, Deneb, Electra))] + #[superstruct(feature(SyncCommittees))] pub sync_aggregate: SyncAggregate, // 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 @@ -84,12 +85,12 @@ pub struct BeaconBlockBody = FullPay #[superstruct(only(Electra), partial_getter(rename = "execution_payload_electra"))] #[serde(flatten)] pub execution_payload: Payload::Electra, - #[superstruct(only(Capella, Deneb, Electra))] + #[superstruct(feature(Withdrawals))] pub bls_to_execution_changes: VariableList, - #[superstruct(only(Deneb, Electra))] + #[superstruct(feature(Blobs))] pub blob_kzg_commitments: KzgCommitments, - #[superstruct(only(Base, Altair))] + #[superstruct(feature(not(Merge)))] #[ssz(skip_serializing, skip_deserializing)] #[tree_hash(skip_hashing)] #[serde(skip)] diff --git a/consensus/types/src/beacon_state.rs b/consensus/types/src/beacon_state.rs index 02572b0efb..88aec16126 100644 --- a/consensus/types/src/beacon_state.rs +++ b/consensus/types/src/beacon_state.rs @@ -194,7 +194,8 @@ impl From for Hash256 { /// The state of the `BeaconChain` at some slot. #[superstruct( - variants(Base, Altair, Merge, Capella, Deneb, Electra), + variants_and_features_from = "FORK_ORDER", + feature_dependencies = "FEATURE_DEPENDENCIES", variant_attributes( derive( Derivative, @@ -268,15 +269,15 @@ where pub slashings: FixedVector, // Attestations (genesis fork only) - #[superstruct(only(Base))] + #[superstruct(feature(not(SyncCommittees)))] pub previous_epoch_attestations: VariableList, E::MaxPendingAttestations>, - #[superstruct(only(Base))] + #[superstruct(feature(not(SyncCommittees)))] pub current_epoch_attestations: VariableList, E::MaxPendingAttestations>, // Participation (Altair and later) - #[superstruct(only(Altair, Merge, Capella, Deneb, Electra))] + #[superstruct(feature(SyncCommittees))] pub previous_epoch_participation: VariableList, - #[superstruct(only(Altair, Merge, Capella, Deneb, Electra))] + #[superstruct(feature(SyncCommittees))] pub current_epoch_participation: VariableList, // Finality @@ -291,13 +292,13 @@ where // Inactivity #[serde(with = "ssz_types::serde_utils::quoted_u64_var_list")] - #[superstruct(only(Altair, Merge, Capella, Deneb, Electra))] + #[superstruct(feature(SyncCommittees))] pub inactivity_scores: VariableList, // Light-client sync committees - #[superstruct(only(Altair, Merge, Capella, Deneb, Electra))] + #[superstruct(feature(SyncCommittees))] pub current_sync_committee: Arc>, - #[superstruct(only(Altair, Merge, Capella, Deneb, Electra))] + #[superstruct(feature(SyncCommittees))] pub next_sync_committee: Arc>, // Execution @@ -323,14 +324,14 @@ where pub latest_execution_payload_header: ExecutionPayloadHeaderElectra, // Capella - #[superstruct(only(Capella, Deneb, Electra), partial_getter(copy))] + #[superstruct(feature(Withdrawals), partial_getter(copy))] #[serde(with = "serde_utils::quoted_u64")] pub next_withdrawal_index: u64, - #[superstruct(only(Capella, Deneb, Electra), partial_getter(copy))] + #[superstruct(feature(Withdrawals), partial_getter(copy))] #[serde(with = "serde_utils::quoted_u64")] pub next_withdrawal_validator_index: u64, // Deep history valid from Capella onwards. - #[superstruct(only(Capella, Deneb, Electra))] + #[superstruct(feature(Withdrawals))] pub historical_summaries: VariableList, // Caching (not in the spec) diff --git a/consensus/types/src/feature_name.rs b/consensus/types/src/feature_name.rs new file mode 100644 index 0000000000..3bee5798bf --- /dev/null +++ b/consensus/types/src/feature_name.rs @@ -0,0 +1,12 @@ +pub enum FeatureName { + // Altair. + SyncCommittees, + // Bellatrix. + Merge, + // Capella. + Withdrawals, + // Deneb. + Blobs, + // Electra. + EIP6110, +} diff --git a/consensus/types/src/fork_order.rs b/consensus/types/src/fork_order.rs new file mode 100644 index 0000000000..adb6fce2a3 --- /dev/null +++ b/consensus/types/src/fork_order.rs @@ -0,0 +1,20 @@ +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::SyncCommittees]), + (ForkName::Merge, &[FeatureName::Merge]), + (ForkName::Capella, &[FeatureName::Withdrawals]), + (ForkName::Deneb, &[FeatureName::Blobs]), + (ForkName::Electra, &[]), +]; + +#[superstruct(feature_dependencies_decl = "FEATURE_DEPENDENCIES")] +pub const FEATURE_DEPENDENCIES: &[(FeatureName, &[FeatureName])] = &[ + (FeatureName::SyncCommittees, &[]), + (FeatureName::Merge, &[FeatureName::SyncCommittees]), + (FeatureName::Withdrawals, &[FeatureName::Merge]), + (FeatureName::Blobs, &[FeatureName::Withdrawals]), +]; diff --git a/consensus/types/src/lib.rs b/consensus/types/src/lib.rs index 6551ebc1dd..e0f549234c 100644 --- a/consensus/types/src/lib.rs +++ b/consensus/types/src/lib.rs @@ -41,9 +41,11 @@ pub mod eth_spec; pub mod execution_block_hash; 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; @@ -153,6 +155,7 @@ pub use crate::execution_payload_header::{ ExecutionPayloadHeaderElectra, ExecutionPayloadHeaderMerge, 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;