diff --git a/ethereum-consensus/src/electra/beacon_block.rs b/ethereum-consensus/src/electra/beacon_block.rs new file mode 100644 index 000000000..c60b39c88 --- /dev/null +++ b/ethereum-consensus/src/electra/beacon_block.rs @@ -0,0 +1,153 @@ +use crate::{ + altair::SyncAggregate, + capella::SignedBlsToExecutionChange, + deneb::polynomial_commitments::KzgCommitment, + electra::{execution_payload::ExecutionPayload, operations::Attestation}, + phase0::{AttesterSlashing, Deposit, Eth1Data, ProposerSlashing, SignedVoluntaryExit}, + primitives::{BlsSignature, Bytes32, Root, Slot, ValidatorIndex}, + ssz::prelude::*, +}; + +#[derive( + Default, Debug, Clone, SimpleSerialize, PartialEq, Eq, serde::Serialize, serde::Deserialize, +)] +pub struct BeaconBlockBody< + const MAX_PROPOSER_SLASHINGS: usize, + const MAX_VALIDATORS_PER_COMMITTEE: usize, + const MAX_ATTESTER_SLASHINGS: usize, + const MAX_ATTESTATIONS: usize, + const MAX_DEPOSITS: usize, + const MAX_VOLUNTARY_EXITS: usize, + const SYNC_COMMITTEE_SIZE: usize, + const BYTES_PER_LOGS_BLOOM: usize, + const MAX_EXTRA_DATA_BYTES: usize, + const MAX_BYTES_PER_TRANSACTION: usize, + const MAX_TRANSACTIONS_PER_PAYLOAD: usize, + const MAX_WITHDRAWALS_PER_PAYLOAD: usize, + const MAX_BLS_TO_EXECUTION_CHANGES: usize, + const MAX_BLOB_COMMITMENTS_PER_BLOCK: usize, + const MAX_COMMITTEES_PER_SLOT: usize, + const MAX_VALIDATORS_PER_SLOT: usize, + const MAX_DEPOSIT_RECEIPTS_PER_PAYLOAD: usize, + const MAX_EXECUTION_LAYER_EXITS: usize, +> { + pub randao_reveal: BlsSignature, + pub eth1_data: Eth1Data, + pub graffiti: Bytes32, + pub proposer_slashings: List, + pub attester_slashings: + List, MAX_ATTESTER_SLASHINGS>, + pub attestations: + List, MAX_ATTESTATIONS>, + pub deposits: List, + pub voluntary_exits: List, + pub sync_aggregate: SyncAggregate, + pub execution_payload: ExecutionPayload< + BYTES_PER_LOGS_BLOOM, + MAX_EXTRA_DATA_BYTES, + MAX_BYTES_PER_TRANSACTION, + MAX_TRANSACTIONS_PER_PAYLOAD, + MAX_WITHDRAWALS_PER_PAYLOAD, + MAX_DEPOSIT_RECEIPTS_PER_PAYLOAD, + MAX_EXECUTION_LAYER_EXITS, + >, + pub bls_to_execution_changes: List, + pub blob_kzg_commitments: List, +} + +#[derive( + Default, Debug, Clone, SimpleSerialize, PartialEq, Eq, serde::Serialize, serde::Deserialize, +)] +pub struct BeaconBlock< + const MAX_PROPOSER_SLASHINGS: usize, + const MAX_VALIDATORS_PER_COMMITTEE: usize, + const MAX_ATTESTER_SLASHINGS: usize, + const MAX_ATTESTATIONS: usize, + const MAX_DEPOSITS: usize, + const MAX_VOLUNTARY_EXITS: usize, + const SYNC_COMMITTEE_SIZE: usize, + const BYTES_PER_LOGS_BLOOM: usize, + const MAX_EXTRA_DATA_BYTES: usize, + const MAX_BYTES_PER_TRANSACTION: usize, + const MAX_TRANSACTIONS_PER_PAYLOAD: usize, + const MAX_WITHDRAWALS_PER_PAYLOAD: usize, + const MAX_BLS_TO_EXECUTION_CHANGES: usize, + const MAX_BLOB_COMMITMENTS_PER_BLOCK: usize, + const MAX_COMMITTEES_PER_SLOT: usize, + const MAX_VALIDATORS_PER_SLOT: usize, + const MAX_DEPOSIT_RECEIPTS_PER_PAYLOAD: usize, + const MAX_EXECUTION_LAYER_EXITS: usize, +> { + #[serde(with = "crate::serde::as_str")] + pub slot: Slot, + #[serde(with = "crate::serde::as_str")] + pub proposer_index: ValidatorIndex, + pub parent_root: Root, + pub state_root: Root, + pub body: BeaconBlockBody< + MAX_PROPOSER_SLASHINGS, + MAX_VALIDATORS_PER_COMMITTEE, + MAX_ATTESTER_SLASHINGS, + MAX_ATTESTATIONS, + MAX_DEPOSITS, + MAX_VOLUNTARY_EXITS, + SYNC_COMMITTEE_SIZE, + BYTES_PER_LOGS_BLOOM, + MAX_EXTRA_DATA_BYTES, + MAX_BYTES_PER_TRANSACTION, + MAX_TRANSACTIONS_PER_PAYLOAD, + MAX_WITHDRAWALS_PER_PAYLOAD, + MAX_BLS_TO_EXECUTION_CHANGES, + MAX_BLOB_COMMITMENTS_PER_BLOCK, + MAX_COMMITTEES_PER_SLOT, + MAX_VALIDATORS_PER_SLOT, + MAX_DEPOSIT_RECEIPTS_PER_PAYLOAD, + MAX_EXECUTION_LAYER_EXITS, + >, +} + +#[derive( + Default, Debug, Clone, SimpleSerialize, PartialEq, Eq, serde::Serialize, serde::Deserialize, +)] +pub struct SignedBeaconBlock< + const MAX_PROPOSER_SLASHINGS: usize, + const MAX_VALIDATORS_PER_COMMITTEE: usize, + const MAX_ATTESTER_SLASHINGS: usize, + const MAX_ATTESTATIONS: usize, + const MAX_DEPOSITS: usize, + const MAX_VOLUNTARY_EXITS: usize, + const SYNC_COMMITTEE_SIZE: usize, + const BYTES_PER_LOGS_BLOOM: usize, + const MAX_EXTRA_DATA_BYTES: usize, + const MAX_BYTES_PER_TRANSACTION: usize, + const MAX_TRANSACTIONS_PER_PAYLOAD: usize, + const MAX_WITHDRAWALS_PER_PAYLOAD: usize, + const MAX_BLS_TO_EXECUTION_CHANGES: usize, + const MAX_BLOB_COMMITMENTS_PER_BLOCK: usize, + const MAX_COMMITTEES_PER_SLOT: usize, + const MAX_VALIDATORS_PER_SLOT: usize, + const MAX_DEPOSIT_RECEIPTS_PER_PAYLOAD: usize, + const MAX_EXECUTION_LAYER_EXITS: usize, +> { + pub message: BeaconBlock< + MAX_PROPOSER_SLASHINGS, + MAX_VALIDATORS_PER_COMMITTEE, + MAX_ATTESTER_SLASHINGS, + MAX_ATTESTATIONS, + MAX_DEPOSITS, + MAX_VOLUNTARY_EXITS, + SYNC_COMMITTEE_SIZE, + BYTES_PER_LOGS_BLOOM, + MAX_EXTRA_DATA_BYTES, + MAX_BYTES_PER_TRANSACTION, + MAX_TRANSACTIONS_PER_PAYLOAD, + MAX_WITHDRAWALS_PER_PAYLOAD, + MAX_BLS_TO_EXECUTION_CHANGES, + MAX_BLOB_COMMITMENTS_PER_BLOCK, + MAX_COMMITTEES_PER_SLOT, + MAX_VALIDATORS_PER_SLOT, + MAX_DEPOSIT_RECEIPTS_PER_PAYLOAD, + MAX_EXECUTION_LAYER_EXITS, + >, + pub signature: BlsSignature, +} diff --git a/ethereum-consensus/src/electra/beacon_state.rs b/ethereum-consensus/src/electra/beacon_state.rs new file mode 100644 index 000000000..80df9a282 --- /dev/null +++ b/ethereum-consensus/src/electra/beacon_state.rs @@ -0,0 +1,66 @@ +use crate::{ + altair::SyncCommittee, + capella::HistoricalSummary, + electra::ExecutionPayloadHeader, + phase0::{BeaconBlockHeader, Checkpoint, Eth1Data, Fork, Validator, JUSTIFICATION_BITS_LENGTH}, + primitives::{Bytes32, Gwei, ParticipationFlags, Root, Slot, ValidatorIndex, WithdrawalIndex}, + ssz::prelude::*, +}; + +#[derive( + Default, Debug, SimpleSerialize, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, +)] +pub struct BeaconState< + const SLOTS_PER_HISTORICAL_ROOT: usize, + const HISTORICAL_ROOTS_LIMIT: usize, + const ETH1_DATA_VOTES_BOUND: usize, + const VALIDATOR_REGISTRY_LIMIT: usize, + const EPOCHS_PER_HISTORICAL_VECTOR: usize, + const EPOCHS_PER_SLASHINGS_VECTOR: usize, + const MAX_VALIDATORS_PER_COMMITTEE: usize, + const SYNC_COMMITTEE_SIZE: usize, + const BYTES_PER_LOGS_BLOOM: usize, + const MAX_EXTRA_DATA_BYTES: usize, +> { + #[serde(with = "crate::serde::as_str")] + pub genesis_time: u64, + pub genesis_validators_root: Root, + #[serde(with = "crate::serde::as_str")] + pub slot: Slot, + pub fork: Fork, + pub latest_block_header: BeaconBlockHeader, + pub block_roots: Vector, + pub state_roots: Vector, + pub historical_roots: List, + pub eth1_data: Eth1Data, + pub eth1_data_votes: List, + #[serde(with = "crate::serde::as_str")] + pub eth1_deposit_index: u64, + pub validators: List, + #[serde(with = "crate::serde::seq_of_str")] + pub balances: List, + pub randao_mixes: Vector, + #[serde(with = "crate::serde::seq_of_str")] + pub slashings: Vector, + #[serde(with = "crate::serde::seq_of_str")] + pub previous_epoch_participation: List, + #[serde(with = "crate::serde::seq_of_str")] + pub current_epoch_participation: List, + pub justification_bits: Bitvector, + pub previous_justified_checkpoint: Checkpoint, + pub current_justified_checkpoint: Checkpoint, + pub finalized_checkpoint: Checkpoint, + #[serde(with = "crate::serde::seq_of_str")] + pub inactivity_scores: List, + pub current_sync_committee: SyncCommittee, + pub next_sync_committee: SyncCommittee, + pub latest_execution_payload_header: + ExecutionPayloadHeader, + #[serde(with = "crate::serde::as_str")] + pub next_withdrawal_index: WithdrawalIndex, + #[serde(with = "crate::serde::as_str")] + pub next_withdrawal_validator_index: ValidatorIndex, + pub historical_summaries: List, + #[serde(with = "crate::serde::as_str")] + pub deposit_receipts_start_index: u64, +} diff --git a/ethereum-consensus/src/electra/constants.rs b/ethereum-consensus/src/electra/constants.rs new file mode 100644 index 000000000..7ca9fae5e --- /dev/null +++ b/ethereum-consensus/src/electra/constants.rs @@ -0,0 +1 @@ +pub const UNSET_DEPOSIT_RECEIPTS_START_INDEX: u64 = u64::MAX; diff --git a/ethereum-consensus/src/electra/deposit_receipt.rs b/ethereum-consensus/src/electra/deposit_receipt.rs new file mode 100644 index 000000000..c260aee4c --- /dev/null +++ b/ethereum-consensus/src/electra/deposit_receipt.rs @@ -0,0 +1,17 @@ +use crate::{ + primitives::{BlsPublicKey, BlsSignature, Bytes32, Gwei}, + ssz::prelude::*, +}; + +#[derive( + Default, Debug, Clone, SimpleSerialize, PartialEq, Eq, serde::Serialize, serde::Deserialize, +)] +pub struct DepositReceipt { + pub pubkey: BlsPublicKey, + pub withdrawal_credentials: Bytes32, + #[serde(with = "crate::serde::as_str")] + pub amount: Gwei, + pub signature: BlsSignature, + #[serde(with = "crate::serde::as_str")] + pub index: u64, +} diff --git a/ethereum-consensus/src/electra/execution_layer_exit.rs b/ethereum-consensus/src/electra/execution_layer_exit.rs new file mode 100644 index 000000000..db2abc490 --- /dev/null +++ b/ethereum-consensus/src/electra/execution_layer_exit.rs @@ -0,0 +1,12 @@ +use crate::{ + primitives::{BlsPublicKey, ExecutionAddress}, + ssz::prelude::*, +}; + +#[derive( + Default, Debug, Clone, SimpleSerialize, PartialEq, Eq, serde::Serialize, serde::Deserialize, +)] +pub struct ExecutionLayerExit { + pub source_address: ExecutionAddress, + pub validator_pubkey: BlsPublicKey, +} diff --git a/ethereum-consensus/src/electra/execution_payload.rs b/ethereum-consensus/src/electra/execution_payload.rs new file mode 100644 index 000000000..28d3ac922 --- /dev/null +++ b/ethereum-consensus/src/electra/execution_payload.rs @@ -0,0 +1,148 @@ +use crate::{ + bellatrix::Transaction, + capella::Withdrawal, + electra::{DepositReceipt, ExecutionLayerExit}, + primitives::{Bytes32, ExecutionAddress, Hash32, Root}, + ssz::prelude::*, + Error, +}; + +#[derive( + Default, Debug, Clone, SimpleSerialize, PartialEq, Eq, serde::Serialize, serde::Deserialize, +)] +pub struct ExecutionPayload< + const BYTES_PER_LOGS_BLOOM: usize, + const MAX_EXTRA_DATA_BYTES: usize, + const MAX_BYTES_PER_TRANSACTION: usize, + const MAX_TRANSACTIONS_PER_PAYLOAD: usize, + const MAX_WITHDRAWALS_PER_PAYLOAD: usize, + const MAX_DEPOSIT_RECEIPTS_PER_PAYLOAD: usize, + const MAX_EXECUTION_LAYER_EXITS: usize, +> { + pub parent_hash: Hash32, + pub fee_recipient: ExecutionAddress, + pub state_root: Bytes32, + pub receipts_root: Bytes32, + pub logs_bloom: ByteVector, + pub prev_randao: Bytes32, + #[serde(with = "crate::serde::as_str")] + pub block_number: u64, + #[serde(with = "crate::serde::as_str")] + pub gas_limit: u64, + #[serde(with = "crate::serde::as_str")] + pub gas_used: u64, + #[serde(with = "crate::serde::as_str")] + pub timestamp: u64, + pub extra_data: ByteList, + #[serde(with = "crate::serde::as_str")] + pub base_fee_per_gas: U256, + pub block_hash: Hash32, + pub transactions: List, MAX_TRANSACTIONS_PER_PAYLOAD>, + pub withdrawals: List, + #[serde(with = "crate::serde::as_str")] + pub blob_gas_used: u64, + #[serde(with = "crate::serde::as_str")] + pub excess_blob_gas: u64, + pub deposit_receipts: List, + pub exits: List, +} + +#[derive( + Default, Debug, Clone, SimpleSerialize, PartialEq, Eq, serde::Serialize, serde::Deserialize, +)] +pub struct ExecutionPayloadHeader< + const BYTES_PER_LOGS_BLOOM: usize, + const MAX_EXTRA_DATA_BYTES: usize, +> { + pub parent_hash: Hash32, + pub fee_recipient: ExecutionAddress, + pub state_root: Bytes32, + pub receipts_root: Bytes32, + pub logs_bloom: ByteVector, + pub prev_randao: Bytes32, + #[serde(with = "crate::serde::as_str")] + pub block_number: u64, + #[serde(with = "crate::serde::as_str")] + pub gas_limit: u64, + #[serde(with = "crate::serde::as_str")] + pub gas_used: u64, + #[serde(with = "crate::serde::as_str")] + pub timestamp: u64, + pub extra_data: ByteList, + #[serde(with = "crate::serde::as_str")] + pub base_fee_per_gas: U256, + pub block_hash: Hash32, + pub transactions_root: Root, + pub withdrawals_root: Root, + #[serde(with = "crate::serde::as_str")] + pub blob_gas_used: u64, + #[serde(with = "crate::serde::as_str")] + pub excess_blob_gas: u64, + pub deposit_receipts_root: Root, + pub exits_root: Root, +} + +impl< + 'a, + const BYTES_PER_LOGS_BLOOM: usize, + const MAX_EXTRA_DATA_BYTES: usize, + const MAX_BYTES_PER_TRANSACTION: usize, + const MAX_TRANSACTIONS_PER_PAYLOAD: usize, + const MAX_WITHDRAWALS_PER_PAYLOAD: usize, + const MAX_DEPOSIT_RECEIPTS_PER_PAYLOAD: usize, + const MAX_EXECUTION_LAYER_EXITS: usize, + > + TryFrom< + &'a mut ExecutionPayload< + BYTES_PER_LOGS_BLOOM, + MAX_EXTRA_DATA_BYTES, + MAX_BYTES_PER_TRANSACTION, + MAX_TRANSACTIONS_PER_PAYLOAD, + MAX_WITHDRAWALS_PER_PAYLOAD, + MAX_DEPOSIT_RECEIPTS_PER_PAYLOAD, + MAX_EXECUTION_LAYER_EXITS, + >, + > for ExecutionPayloadHeader +{ + type Error = Error; + + fn try_from( + payload: &'a mut ExecutionPayload< + BYTES_PER_LOGS_BLOOM, + MAX_EXTRA_DATA_BYTES, + MAX_BYTES_PER_TRANSACTION, + MAX_TRANSACTIONS_PER_PAYLOAD, + MAX_WITHDRAWALS_PER_PAYLOAD, + MAX_DEPOSIT_RECEIPTS_PER_PAYLOAD, + MAX_EXECUTION_LAYER_EXITS, + >, + ) -> Result, Self::Error> + { + let transactions_root = payload.transactions.hash_tree_root()?; + let withdrawals_root = payload.withdrawals.hash_tree_root()?; + let deposit_receipts_root = payload.deposit_receipts.hash_tree_root()?; + let exits_root = payload.exits.hash_tree_root()?; + + Ok(ExecutionPayloadHeader { + parent_hash: payload.parent_hash.clone(), + fee_recipient: payload.fee_recipient.clone(), + state_root: payload.state_root.clone(), + receipts_root: payload.receipts_root.clone(), + logs_bloom: payload.logs_bloom.clone(), + prev_randao: payload.prev_randao.clone(), + block_number: payload.block_number, + gas_limit: payload.gas_limit, + gas_used: payload.gas_used, + timestamp: payload.timestamp, + extra_data: payload.extra_data.clone(), + base_fee_per_gas: payload.base_fee_per_gas, + block_hash: payload.block_hash.clone(), + transactions_root, + withdrawals_root, + blob_gas_used: payload.blob_gas_used, + excess_blob_gas: payload.excess_blob_gas, + deposit_receipts_root, + exits_root, + }) + } +} diff --git a/ethereum-consensus/src/electra/fork.rs b/ethereum-consensus/src/electra/fork.rs new file mode 100644 index 000000000..4364891c5 --- /dev/null +++ b/ethereum-consensus/src/electra/fork.rs @@ -0,0 +1,105 @@ +use crate::{ + deneb::{self, Fork}, + electra::{ + beacon_state::BeaconState, constants::UNSET_DEPOSIT_RECEIPTS_START_INDEX, + execution_payload::ExecutionPayloadHeader, + }, + state_transition::Context, +}; + +pub fn upgrade_to_electra< + const SLOTS_PER_HISTORICAL_ROOT: usize, + const HISTORICAL_ROOTS_LIMIT: usize, + const ETH1_DATA_VOTES_BOUND: usize, + const VALIDATOR_REGISTRY_LIMIT: usize, + const EPOCHS_PER_HISTORICAL_VECTOR: usize, + const EPOCHS_PER_SLASHINGS_VECTOR: usize, + const MAX_VALIDATORS_PER_COMMITTEE: usize, + const SYNC_COMMITTEE_SIZE: usize, + const BYTES_PER_LOGS_BLOOM: usize, + const MAX_EXTRA_DATA_BYTES: usize, +>( + state: &deneb::BeaconState< + SLOTS_PER_HISTORICAL_ROOT, + HISTORICAL_ROOTS_LIMIT, + ETH1_DATA_VOTES_BOUND, + VALIDATOR_REGISTRY_LIMIT, + EPOCHS_PER_HISTORICAL_VECTOR, + EPOCHS_PER_SLASHINGS_VECTOR, + MAX_VALIDATORS_PER_COMMITTEE, + SYNC_COMMITTEE_SIZE, + BYTES_PER_LOGS_BLOOM, + MAX_EXTRA_DATA_BYTES, + >, + context: &Context, +) -> BeaconState< + SLOTS_PER_HISTORICAL_ROOT, + HISTORICAL_ROOTS_LIMIT, + ETH1_DATA_VOTES_BOUND, + VALIDATOR_REGISTRY_LIMIT, + EPOCHS_PER_HISTORICAL_VECTOR, + EPOCHS_PER_SLASHINGS_VECTOR, + MAX_VALIDATORS_PER_COMMITTEE, + SYNC_COMMITTEE_SIZE, + BYTES_PER_LOGS_BLOOM, + MAX_EXTRA_DATA_BYTES, +> { + let epoch = deneb::get_current_epoch(state, context); + let latest_execution_payload_header = &state.latest_execution_payload_header; + let latest_execution_payload_header = ExecutionPayloadHeader { + parent_hash: latest_execution_payload_header.parent_hash.clone(), + fee_recipient: latest_execution_payload_header.fee_recipient.clone(), + state_root: latest_execution_payload_header.state_root.clone(), + receipts_root: latest_execution_payload_header.receipts_root.clone(), + logs_bloom: latest_execution_payload_header.logs_bloom.clone(), + prev_randao: latest_execution_payload_header.prev_randao.clone(), + block_number: latest_execution_payload_header.block_number, + gas_limit: latest_execution_payload_header.gas_limit, + gas_used: latest_execution_payload_header.gas_used, + timestamp: latest_execution_payload_header.timestamp, + extra_data: latest_execution_payload_header.extra_data.clone(), + base_fee_per_gas: latest_execution_payload_header.base_fee_per_gas, + block_hash: latest_execution_payload_header.block_hash.clone(), + transactions_root: latest_execution_payload_header.transactions_root, + withdrawals_root: latest_execution_payload_header.withdrawals_root, + blob_gas_used: latest_execution_payload_header.blob_gas_used, + excess_blob_gas: latest_execution_payload_header.excess_blob_gas, + deposit_receipts_root: Default::default(), + exits_root: Default::default(), + }; + BeaconState { + genesis_time: state.genesis_time, + genesis_validators_root: state.genesis_validators_root, + slot: state.slot, + fork: Fork { + previous_version: state.fork.current_version, + current_version: context.deneb_fork_version, + epoch, + }, + latest_block_header: state.latest_block_header.clone(), + block_roots: state.block_roots.clone(), + state_roots: state.state_roots.clone(), + historical_roots: state.historical_roots.clone(), + eth1_data: state.eth1_data.clone(), + eth1_data_votes: state.eth1_data_votes.clone(), + eth1_deposit_index: state.eth1_deposit_index, + validators: state.validators.clone(), + balances: state.balances.clone(), + randao_mixes: state.randao_mixes.clone(), + slashings: state.slashings.clone(), + previous_epoch_participation: state.previous_epoch_participation.clone(), + current_epoch_participation: state.current_epoch_participation.clone(), + justification_bits: state.justification_bits.clone(), + previous_justified_checkpoint: state.previous_justified_checkpoint.clone(), + current_justified_checkpoint: state.current_justified_checkpoint.clone(), + finalized_checkpoint: state.finalized_checkpoint.clone(), + inactivity_scores: state.inactivity_scores.clone(), + current_sync_committee: state.current_sync_committee.clone(), + next_sync_committee: state.next_sync_committee.clone(), + latest_execution_payload_header, + next_withdrawal_index: state.next_withdrawal_index, + next_withdrawal_validator_index: state.next_withdrawal_validator_index, + historical_summaries: state.historical_summaries.clone(), + deposit_receipts_start_index: UNSET_DEPOSIT_RECEIPTS_START_INDEX, + } +} diff --git a/ethereum-consensus/src/electra/helpers.rs b/ethereum-consensus/src/electra/helpers.rs new file mode 100644 index 000000000..4b91792ff --- /dev/null +++ b/ethereum-consensus/src/electra/helpers.rs @@ -0,0 +1,9 @@ +use ssz_rs::Bitvector; + +use crate::capella::CommitteeIndex; + +pub fn get_committee_indices( + committee_bits: Bitvector, +) -> Vec { + committee_bits.iter().enumerate().flat_map(|(i, bit)| bit.then_some(i)).collect() +} diff --git a/ethereum-consensus/src/electra/mod.rs b/ethereum-consensus/src/electra/mod.rs new file mode 100644 index 000000000..99e3d7960 --- /dev/null +++ b/ethereum-consensus/src/electra/mod.rs @@ -0,0 +1,12 @@ +pub mod beacon_block; +pub mod beacon_state; +pub mod constants; +pub mod deposit_receipt; +pub mod execution_layer_exit; +pub mod execution_payload; +pub mod fork; +pub mod helpers; +pub mod operations; +pub mod spec; + +pub use spec::*; diff --git a/ethereum-consensus/src/electra/operations.rs b/ethereum-consensus/src/electra/operations.rs new file mode 100644 index 000000000..64a868b8a --- /dev/null +++ b/ethereum-consensus/src/electra/operations.rs @@ -0,0 +1,25 @@ +use crate::{ + deneb::AttestationData, + primitives::{BlsSignature, ValidatorIndex}, + ssz::prelude::*, +}; + +#[derive( + Default, Debug, SimpleSerialize, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, +)] +pub struct IndexedAttestation { + #[serde(with = "crate::serde::seq_of_str")] + pub attesting_indices: List, + pub data: AttestationData, + pub signature: BlsSignature, +} + +#[derive( + Default, Debug, SimpleSerialize, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, +)] +pub struct Attestation { + pub aggregation_bits: Bitlist, + pub data: AttestationData, + pub committee_bits: Bitlist, + pub signature: BlsSignature, +} diff --git a/ethereum-consensus/src/electra/spec/mod.rs b/ethereum-consensus/src/electra/spec/mod.rs index fcb9373ba..6a6866695 100644 --- a/ethereum-consensus/src/electra/spec/mod.rs +++ b/ethereum-consensus/src/electra/spec/mod.rs @@ -1,194 +1,10 @@ -//! WARNING: This file was derived by the `spec-gen` utility. DO NOT EDIT MANUALLY. -pub use crate::primitives::*; -pub use crate::signing::*; -pub use crate::state_transition::{Result, Context, Validation}; -pub use crate::error::*; -use std::mem; -use std::collections::{HashSet, HashMap}; -use std::iter::zip; -use crate::ssz::prelude::*; -use integer_sqrt::IntegerSquareRoot; -use crate::crypto::{ - hash, fast_aggregate_verify, eth_aggregate_public_keys, eth_fast_aggregate_verify, +pub use crate::electra::{ + beacon_block::{BeaconBlock, BeaconBlockBody, SignedBeaconBlock}, + beacon_state::BeaconState, + constants::UNSET_DEPOSIT_RECEIPTS_START_INDEX, + deposit_receipt::DepositReceipt, + execution_layer_exit::ExecutionLayerExit, + execution_payload::{ExecutionPayload, ExecutionPayloadHeader}, + helpers::get_committee_indices, + operations::{Attestation, IndexedAttestation}, }; -pub use crate::deneb::blob_sidecar::VERSIONED_HASH_VERSION_KZG; -pub use crate::altair::constants::TIMELY_SOURCE_FLAG_INDEX; -pub use crate::altair::constants::TIMELY_TARGET_FLAG_INDEX; -pub use crate::altair::constants::TIMELY_HEAD_FLAG_INDEX; -pub use crate::altair::constants::TIMELY_SOURCE_WEIGHT; -pub use crate::altair::constants::TIMELY_TARGET_WEIGHT; -pub use crate::altair::constants::TIMELY_HEAD_WEIGHT; -pub use crate::altair::constants::SYNC_REWARD_WEIGHT; -pub use crate::altair::constants::PROPOSER_WEIGHT; -pub use crate::altair::constants::WEIGHT_DENOMINATOR; -pub use crate::altair::constants::PARTICIPATION_FLAG_WEIGHTS; -pub use crate::altair::constants::SYNC_COMMITTEE_SUBNET_COUNT; -pub use crate::phase0::constants::BASE_REWARDS_PER_EPOCH; -pub use crate::phase0::constants::DEPOSIT_CONTRACT_TREE_DEPTH; -pub use crate::phase0::constants::JUSTIFICATION_BITS_LENGTH; -pub use crate::phase0::constants::DEPOSIT_DATA_LIST_BOUND; -pub use crate::capella::light_client::EXECUTION_PAYLOAD_INDEX; -pub use crate::capella::light_client::EXECUTION_PAYLOAD_INDEX_FLOOR_LOG_2; -pub use crate::altair::light_client::FINALIZED_ROOT_INDEX; -pub use crate::altair::light_client::FINALIZED_ROOT_INDEX_FLOOR_LOG_2; -pub use crate::altair::light_client::CURRENT_SYNC_COMMITTEE_INDEX; -pub use crate::altair::light_client::CURRENT_SYNC_COMMITTEE_INDEX_FLOOR_LOG_2; -pub use crate::altair::light_client::NEXT_SYNC_COMMITTEE_INDEX; -pub use crate::altair::light_client::NEXT_SYNC_COMMITTEE_INDEX_FLOOR_LOG_2; -pub use crate::deneb::beacon_block::BeaconBlockBody; -pub use crate::deneb::beacon_block::BeaconBlock; -pub use crate::deneb::beacon_block::SignedBeaconBlock; -pub use crate::phase0::beacon_block::BeaconBlockHeader; -pub use crate::phase0::beacon_block::SignedBeaconBlockHeader; -pub use crate::deneb::beacon_state::BeaconState; -pub use crate::phase0::beacon_state::Fork; -pub use crate::phase0::beacon_state::ForkData; -pub use crate::phase0::beacon_state::HistoricalBatch; -pub use crate::phase0::beacon_state::HistoricalSummary; -pub use crate::deneb::blinded_beacon_block::BlindedBeaconBlockBody; -pub use crate::deneb::blinded_beacon_block::BlindedBeaconBlock; -pub use crate::deneb::blinded_beacon_block::SignedBlindedBeaconBlock; -pub use crate::deneb::blob_sidecar::BlobIdentifier; -pub use crate::deneb::blob_sidecar::BlobsBundle; -pub use crate::deneb::blob_sidecar::BlobSidecar; -pub use crate::capella::bls_to_execution_change::BlsToExecutionChange; -pub use crate::capella::bls_to_execution_change::SignedBlsToExecutionChange; -pub use crate::deneb::execution_engine::NewPayloadRequest; -pub use crate::deneb::execution_payload::ExecutionPayload; -pub use crate::deneb::execution_payload::ExecutionPayloadHeader; -pub use crate::bellatrix::fork_choice::PowBlock; -pub use crate::deneb::light_client::LightClientHeader; -pub use crate::deneb::light_client::LightClientBootstrap; -pub use crate::deneb::light_client::LightClientUpdate; -pub use crate::deneb::light_client::LightClientFinalityUpdate; -pub use crate::deneb::light_client::LightClientOptimisticUpdate; -pub use crate::phase0::operations::Checkpoint; -pub use crate::phase0::operations::AttestationData; -pub use crate::phase0::operations::IndexedAttestation; -pub use crate::phase0::operations::PendingAttestation; -pub use crate::phase0::operations::Attestation; -pub use crate::phase0::operations::Eth1Data; -pub use crate::phase0::operations::DepositMessage; -pub use crate::phase0::operations::DepositData; -pub use crate::phase0::operations::ProposerSlashing; -pub use crate::phase0::operations::AttesterSlashing; -pub use crate::phase0::operations::Deposit; -pub use crate::phase0::operations::VoluntaryExit; -pub use crate::phase0::operations::SignedVoluntaryExit; -pub use crate::altair::sync::SyncAggregate; -pub use crate::altair::sync::SyncCommittee; -pub use crate::altair::validator::SyncCommitteeMessage; -pub use crate::altair::validator::SyncCommitteeContribution; -pub use crate::altair::validator::ContributionAndProof; -pub use crate::altair::validator::SignedContributionAndProof; -pub use crate::altair::validator::SyncAggregatorSelectionData; -pub use crate::phase0::validator::Validator; -pub use crate::phase0::validator::Eth1Block; -pub use crate::phase0::validator::AggregateAndProof; -pub use crate::phase0::validator::SignedAggregateAndProof; -pub use crate::capella::withdrawal::Withdrawal; -pub use crate::deneb::blob_sidecar::Blob; -pub use crate::bellatrix::execution_payload::Transaction; -pub use crate::deneb::blob_sidecar::verify_blob_sidecar_inclusion_proof; -pub use crate::deneb::block_processing::process_attestation; -pub use crate::deneb::block_processing::process_execution_payload; -pub use crate::deneb::block_processing::process_voluntary_exit; -pub use crate::deneb::block_processing::process_block; -pub use crate::deneb::block_processing::process_bls_to_execution_change; -pub use crate::deneb::block_processing::process_operations; -pub use crate::deneb::block_processing::process_withdrawals; -pub use crate::deneb::block_processing::get_expected_withdrawals; -pub use crate::deneb::block_processing::add_validator_to_registry; -pub use crate::deneb::block_processing::process_sync_aggregate; -pub use crate::deneb::block_processing::process_proposer_slashing; -pub use crate::deneb::block_processing::process_attester_slashing; -pub use crate::phase0::block_processing::get_validator_from_deposit; -pub use crate::deneb::block_processing::apply_deposit; -pub use crate::deneb::block_processing::process_deposit; -pub use crate::deneb::block_processing::process_block_header; -pub use crate::phase0::block_processing::xor; -pub use crate::deneb::block_processing::process_randao; -pub use crate::deneb::block_processing::process_eth1_data; -pub use crate::deneb::epoch_processing::process_registry_updates; -pub use crate::deneb::epoch_processing::process_historical_summaries_update; -pub use crate::deneb::epoch_processing::process_epoch; -pub use crate::deneb::epoch_processing::process_slashings; -pub use crate::deneb::epoch_processing::get_base_reward; -pub use crate::deneb::epoch_processing::process_justification_and_finalization; -pub use crate::deneb::epoch_processing::process_inactivity_updates; -pub use crate::deneb::epoch_processing::process_rewards_and_penalties; -pub use crate::deneb::epoch_processing::process_participation_flag_updates; -pub use crate::deneb::epoch_processing::process_sync_committee_updates; -pub use crate::deneb::epoch_processing::process_eth1_data_reset; -pub use crate::deneb::epoch_processing::process_effective_balance_updates; -pub use crate::deneb::epoch_processing::process_slashings_reset; -pub use crate::deneb::epoch_processing::process_randao_mixes_reset; -pub use crate::deneb::epoch_processing::process_historical_roots_update; -pub use crate::deneb::epoch_processing::weigh_justification_and_finalization; -pub use crate::deneb::epoch_processing::get_proposer_reward; -pub use crate::deneb::epoch_processing::get_finality_delay; -pub use crate::deneb::epoch_processing::is_in_inactivity_leak; -pub use crate::deneb::genesis::initialize_beacon_state_from_eth1; -pub use crate::deneb::genesis::is_valid_genesis_state; -pub use crate::deneb::genesis::get_genesis_block; -pub use crate::deneb::helpers::kzg_commitment_to_versioned_hash; -pub use crate::deneb::helpers::get_attestation_participation_flag_indices; -pub use crate::deneb::helpers::get_validator_activation_churn_limit; -pub use crate::capella::helpers::has_eth1_withdrawal_credential; -pub use crate::capella::helpers::is_fully_withdrawable_validator; -pub use crate::capella::helpers::is_partially_withdrawable_validator; -pub use crate::deneb::helpers::get_inactivity_penalty_deltas; -pub use crate::deneb::helpers::slash_validator; -pub use crate::deneb::helpers::is_merge_transition_complete; -pub use crate::deneb::helpers::is_merge_transition_block; -pub use crate::deneb::helpers::is_execution_enabled; -pub use crate::deneb::helpers::compute_timestamp_at_slot; -pub use crate::altair::helpers::add_flag; -pub use crate::altair::helpers::has_flag; -pub use crate::deneb::helpers::get_next_sync_committee_indices; -pub use crate::deneb::helpers::get_next_sync_committee; -pub use crate::deneb::helpers::get_base_reward_per_increment; -pub use crate::deneb::helpers::get_unslashed_participating_indices; -pub use crate::deneb::helpers::get_flag_index_deltas; -pub use crate::phase0::helpers::is_active_validator; -pub use crate::phase0::helpers::is_eligible_for_activation_queue; -pub use crate::deneb::helpers::is_eligible_for_activation; -pub use crate::phase0::helpers::is_slashable_validator; -pub use crate::phase0::helpers::is_slashable_attestation_data; -pub use crate::deneb::helpers::is_valid_indexed_attestation; -pub use crate::deneb::helpers::verify_block_signature; -pub use crate::deneb::helpers::get_domain; -pub use crate::deneb::helpers::get_current_epoch; -pub use crate::phase0::helpers::compute_shuffled_index; -pub use crate::phase0::helpers::compute_shuffled_indices; -pub use crate::deneb::helpers::sample_proposer_index; -pub use crate::deneb::helpers::compute_proposer_index; -pub use crate::phase0::helpers::compute_committee; -pub use crate::phase0::helpers::compute_epoch_at_slot; -pub use crate::phase0::helpers::compute_start_slot_at_epoch; -pub use crate::phase0::helpers::compute_activation_exit_epoch; -pub use crate::phase0::helpers::compute_fork_digest; -pub use crate::phase0::helpers::compute_domain; -pub use crate::phase0::helpers::compute_fork_data_root; -pub use crate::deneb::helpers::get_previous_epoch; -pub use crate::deneb::helpers::get_block_root; -pub use crate::deneb::helpers::get_block_root_at_slot; -pub use crate::deneb::helpers::get_randao_mix; -pub use crate::deneb::helpers::get_active_validator_indices; -pub use crate::deneb::helpers::get_validator_churn_limit; -pub use crate::deneb::helpers::get_seed; -pub use crate::deneb::helpers::get_committee_count_per_slot; -pub use crate::deneb::helpers::get_beacon_committee; -pub use crate::deneb::helpers::get_beacon_proposer_index; -pub use crate::deneb::helpers::get_total_balance; -pub use crate::deneb::helpers::get_total_active_balance; -pub use crate::deneb::helpers::get_indexed_attestation; -pub use crate::deneb::helpers::get_attesting_indices; -pub use crate::deneb::helpers::increase_balance; -pub use crate::deneb::helpers::decrease_balance; -pub use crate::deneb::helpers::initiate_validator_exit; -pub use crate::deneb::helpers::get_eligible_validator_indices; -pub use crate::deneb::slot_processing::process_slots; -pub use crate::deneb::slot_processing::process_slot; -pub use crate::deneb::state_transition::state_transition_block_in_slot; -pub use crate::deneb::state_transition::state_transition; diff --git a/ethereum-consensus/src/lib.rs b/ethereum-consensus/src/lib.rs index 3dc72c253..53fcdd329 100644 --- a/ethereum-consensus/src/lib.rs +++ b/ethereum-consensus/src/lib.rs @@ -7,6 +7,7 @@ pub mod configs; pub mod crypto; pub mod deneb; pub mod domains; +pub mod electra; pub mod error; pub mod execution_engine; mod fork; diff --git a/spec-gen/src/generator.rs b/spec-gen/src/generator.rs index e66fea6c6..bfd87e1d7 100644 --- a/spec-gen/src/generator.rs +++ b/spec-gen/src/generator.rs @@ -93,6 +93,7 @@ impl Fork { "helpers", "light_client", ], + // TODO: electra Self::Electra => &[], } } @@ -181,6 +182,8 @@ impl Fork { use crate::ssz::prelude::*; use integer_sqrt::IntegerSquareRoot; use crate::crypto::{hash, fast_aggregate_verify, eth_aggregate_public_keys, eth_fast_aggregate_verify}; + + pub use crate::electra::fork::upgrade_to_electra; }; fragment.items } diff --git a/spec-gen/src/type_generator.rs b/spec-gen/src/type_generator.rs index 589393658..cf50a83f3 100644 --- a/spec-gen/src/type_generator.rs +++ b/spec-gen/src/type_generator.rs @@ -116,6 +116,7 @@ impl Type { } fn imports(&self) -> syn::Item { + // TODO: electra match self { Self::BeaconBlockBody => parse_quote! { use crate::{ @@ -827,7 +828,8 @@ fn render(target_type: &Type, items: Vec) { } pub fn run() { - let fork_sequence = &[Fork::Phase0, Fork::Altair, Fork::Bellatrix, Fork::Capella, Fork::Deneb]; + let fork_sequence = + &[Fork::Phase0, Fork::Altair, Fork::Bellatrix, Fork::Capella, Fork::Deneb, Fork::Electra]; let types = [ Type::BeaconBlockBody, Type::BeaconBlock, @@ -857,6 +859,8 @@ mod tests { fn test_fork_cmp() { assert_eq!(Fork::Phase0.cmp(&Fork::Altair), Ordering::Less); assert_eq!(Fork::Bellatrix.cmp(&Fork::Altair), Ordering::Greater); - assert_eq!(Fork::Deneb.cmp(&Fork::Altair), Ordering::Greater); + assert_eq!(Fork::Capella.cmp(&Fork::Bellatrix), Ordering::Greater); + assert_eq!(Fork::Deneb.cmp(&Fork::Capella), Ordering::Greater); + assert_eq!(Fork::Electra.cmp(&Fork::Deneb), Ordering::Greater); } }