Skip to content

feat: add electra types #1799

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -101,15 +101,16 @@ build-release-tarballs: ## Create a series of `.tar.gz` files in the BIN_DIR dir

EF_TESTS_TARGET = mainnet.tar.gz
EF_TESTS_DIR = ./testing/ef-tests/mainnet
LATEST_RELEASE_URL = https://api.github.com/repos/ethereum/consensus-spec-tests/releases/latest
ALL_RELEASES_URL = https://api.github.com/repos/ethereum/consensus-spec-tests/releases

download_test_data:
@if [ -d $(EF_TESTS_DIR) ]; then \
echo "$(EF_TESTS_DIR) already downloaded. Skipping download."; \
else \
echo "Fetching the latest release URL for $(EF_TESTS_TARGET)..."; \
curl -s $(LATEST_RELEASE_URL) \
echo "Fetching the latest release (including pre-releases) for $(EF_TESTS_TARGET)..."; \
curl -s $(ALL_RELEASES_URL) \
| grep "browser_download_url.*$(EF_TESTS_TARGET)" \
| head -n 1 \
| cut -d : -f 2,3 \
| tr -d \" \
| wget -qi -; \
Expand Down
48 changes: 47 additions & 1 deletion bin/trin-execution/src/era/beacon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use alloy::{
use ethportal_api::consensus::{
beacon_block::{
SignedBeaconBlock, SignedBeaconBlockBellatrix, SignedBeaconBlockCapella,
SignedBeaconBlockDeneb,
SignedBeaconBlockDeneb, SignedBeaconBlockElectra,
},
body::Transactions,
};
Expand All @@ -32,6 +32,7 @@ impl ProcessBeaconBlock for SignedBeaconBlock {
SignedBeaconBlock::Bellatrix(block) => block.process_beacon_block(),
SignedBeaconBlock::Capella(block) => block.process_beacon_block(),
SignedBeaconBlock::Deneb(block) => block.process_beacon_block(),
SignedBeaconBlock::Electra(block) => block.process_beacon_block(),
}
}
}
Expand Down Expand Up @@ -167,6 +168,51 @@ impl ProcessBeaconBlock for SignedBeaconBlockDeneb {
}
}

impl ProcessBeaconBlock for SignedBeaconBlockElectra {
fn process_beacon_block(&self) -> anyhow::Result<ProcessedBlock> {
let payload = &self.message.body.execution_payload;

let transactions = decode_transactions(&payload.transactions)?;
let transactions_root = calculate_transaction_root(&transactions);
let transactions = process_transactions(transactions)?;

let withdrawals: Vec<Withdrawal> =
payload.withdrawals.iter().map(Withdrawal::from).collect();
let withdrawals_root = calculate_withdrawals_root(&withdrawals);

let header = Header {
parent_hash: payload.parent_hash,
ommers_hash: EMPTY_UNCLE_ROOT_HASH,
beneficiary: payload.fee_recipient,
state_root: payload.state_root,
transactions_root,
receipts_root: payload.receipts_root,
logs_bloom: Bloom::from_slice(payload.logs_bloom.to_vec().as_slice()),
difficulty: U256::ZERO,
number: payload.block_number,
gas_limit: payload.gas_limit,
gas_used: payload.gas_used,
timestamp: payload.timestamp,
extra_data: payload.extra_data.to_vec().into(),
mix_hash: payload.prev_randao,
nonce: B64::ZERO,
base_fee_per_gas: Some(payload.base_fee_per_gas.to()),
withdrawals_root: Some(withdrawals_root),
blob_gas_used: Some(payload.blob_gas_used),
excess_blob_gas: Some(payload.excess_blob_gas),
parent_beacon_block_root: Some(self.message.parent_root),
requests_hash: Some(self.message.body.execution_requests.requests_hash()),
};

Ok(ProcessedBlock {
header: header.clone(),
uncles: None,
withdrawals: Some(withdrawals),
transactions,
})
}
}

pub fn decode_transactions(transactions: &Transactions) -> anyhow::Result<Vec<TxEnvelope>> {
transactions
.into_par_iter()
Expand Down
19 changes: 16 additions & 3 deletions crates/ethportal-api/src/types/consensus/beacon_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,18 @@ use tree_hash::TreeHash;
use tree_hash_derive::TreeHash;

use crate::consensus::{
body::{BeaconBlockBodyBellatrix, BeaconBlockBodyCapella, BeaconBlockBodyDeneb},
body::{
BeaconBlockBodyBellatrix, BeaconBlockBodyCapella, BeaconBlockBodyDeneb,
BeaconBlockBodyElectra,
},
fork::ForkName,
proof::build_merkle_proof_for_index,
signature::BlsSignature,
};

/// A block of the `BeaconChain`.
#[superstruct(
variants(Bellatrix, Capella, Deneb),
variants(Bellatrix, Capella, Deneb, Electra),
variant_attributes(
derive(
Debug,
Expand Down Expand Up @@ -57,6 +60,8 @@ pub struct BeaconBlock {
pub body: BeaconBlockBodyCapella,
#[superstruct(only(Deneb), partial_getter(rename = "body_deneb"))]
pub body: BeaconBlockBodyDeneb,
#[superstruct(only(Electra), partial_getter(rename = "body_electra"))]
pub body: BeaconBlockBodyElectra,
}

impl BeaconBlock {
Expand All @@ -65,6 +70,7 @@ impl BeaconBlock {
ForkName::Bellatrix => BeaconBlockBellatrix::from_ssz_bytes(bytes).map(Self::Bellatrix),
ForkName::Capella => BeaconBlockCapella::from_ssz_bytes(bytes).map(Self::Capella),
ForkName::Deneb => BeaconBlockDeneb::from_ssz_bytes(bytes).map(Self::Deneb),
ForkName::Electra => BeaconBlockElectra::from_ssz_bytes(bytes).map(Self::Electra),
}
}
}
Expand Down Expand Up @@ -140,7 +146,7 @@ impl BeaconBlockDeneb {

/// A `BeaconBlock` and a signature from its proposer.
#[superstruct(
variants(Bellatrix, Capella, Deneb),
variants(Bellatrix, Capella, Deneb, Electra),
variant_attributes(derive(
Debug,
Clone,
Expand All @@ -163,6 +169,8 @@ pub struct SignedBeaconBlock {
pub message: BeaconBlockCapella,
#[superstruct(only(Deneb), partial_getter(rename = "message_deneb"))]
pub message: BeaconBlockDeneb,
#[superstruct(only(Electra), partial_getter(rename = "message_electra"))]
pub message: BeaconBlockElectra,
pub signature: BlsSignature,
}

Expand Down Expand Up @@ -205,6 +213,9 @@ impl SignedBeaconBlock {
BeaconBlock::Deneb(message) => {
SignedBeaconBlock::Deneb(SignedBeaconBlockDeneb { message, signature })
}
BeaconBlock::Electra(message) => {
SignedBeaconBlock::Electra(SignedBeaconBlockElectra { message, signature })
}
}
}

Expand All @@ -214,6 +225,7 @@ impl SignedBeaconBlock {
SignedBeaconBlock::Bellatrix(block) => block.message.slot,
SignedBeaconBlock::Capella(block) => block.message.slot,
SignedBeaconBlock::Deneb(block) => block.message.slot,
SignedBeaconBlock::Electra(block) => block.message.slot,
}
}

Expand All @@ -225,6 +237,7 @@ impl SignedBeaconBlock {
}
SignedBeaconBlock::Capella(block) => block.message.body.execution_payload.block_number,
SignedBeaconBlock::Deneb(block) => block.message.body.execution_payload.block_number,
SignedBeaconBlock::Electra(block) => block.message.body.execution_payload.block_number,
}
}
}
60 changes: 49 additions & 11 deletions crates/ethportal-api/src/types/consensus/beacon_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use serde_utils;
use ssz::{Decode, DecodeError, Encode};
use ssz_derive::{Decode, Encode};
use ssz_types::{
typenum::{U1099511627776, U16777216, U2048, U4, U65536, U8192},
typenum::{U1099511627776, U134217728, U16777216, U2048, U262144, U4, U65536, U8192},
BitVector, FixedVector, VariableList,
};
use superstruct::superstruct;
Expand All @@ -18,12 +18,16 @@ use tree_hash_derive::TreeHash;
use crate::consensus::{
body::{Checkpoint, Eth1Data},
execution_payload::{
ExecutionPayloadHeaderBellatrix, ExecutionPayloadHeaderCapella, ExecutionPayloadHeaderDeneb,
ExecutionPayloadHeaderBellatrix, ExecutionPayloadHeaderCapella,
ExecutionPayloadHeaderDeneb, ExecutionPayloadHeaderElectra,
},
fork::ForkName,
header::BeaconBlockHeader,
historical_summaries::HistoricalSummaries,
participation_flags::ParticipationFlags,
pending_balance_deposit::PendingDeposit,
pending_consolidation::PendingConsolidation,
pending_partial_withdrawal::PendingPartialWithdrawal,
proof::build_merkle_proof_for_index,
pubkey::PubKey,
sync_committee::SyncCommittee,
Expand All @@ -39,10 +43,13 @@ type JustificationBitsLength = U4;

pub type RootsPerHistoricalRoot = FixedVector<B256, SlotsPerHistoricalRoot>;
pub type HistoricalRoots = VariableList<B256, HistoricalRootsLimit>;
pub type PendingDepositsLimit = U134217728;
pub type PendingPartialWithdrawalsLimit = U134217728;
pub type PendingConsolidationsLimit = U262144;

/// The state of the `BeaconChain` at some slot.
#[superstruct(
variants(Bellatrix, Capella, Deneb),
variants(Bellatrix, Capella, Deneb, Electra),
variant_attributes(
derive(
Clone,
Expand Down Expand Up @@ -101,9 +108,9 @@ pub struct BeaconState {
pub slashings: FixedVector<u64, EpochsPerSlashingsVector>,

// Participation (Altair and later)
#[superstruct(only(Bellatrix, Capella, Deneb))]
#[superstruct(only(Bellatrix, Capella, Deneb, Electra))]
pub previous_epoch_participation: VariableList<ParticipationFlags, ValidatorRegistryLimit>,
#[superstruct(only(Bellatrix, Capella, Deneb))]
#[superstruct(only(Bellatrix, Capella, Deneb, Electra))]
pub current_epoch_participation: VariableList<ParticipationFlags, ValidatorRegistryLimit>,

// Finality
Expand All @@ -116,14 +123,14 @@ pub struct BeaconState {
pub finalized_checkpoint: Checkpoint,

// Inactivity
#[superstruct(only(Bellatrix, Capella, Deneb))]
#[superstruct(only(Bellatrix, Capella, Deneb, Electra))]
#[serde(deserialize_with = "ssz_types::serde_utils::quoted_u64_var_list::deserialize")]
pub inactivity_scores: VariableList<u64, ValidatorRegistryLimit>,

// Light-client sync committees
#[superstruct(only(Bellatrix, Capella, Deneb))]
#[superstruct(only(Bellatrix, Capella, Deneb, Electra))]
pub current_sync_committee: Arc<SyncCommittee>,
#[superstruct(only(Bellatrix, Capella, Deneb))]
#[superstruct(only(Bellatrix, Capella, Deneb, Electra))]
pub next_sync_committee: Arc<SyncCommittee>,

// Execution
Expand All @@ -142,17 +149,47 @@ pub struct BeaconState {
partial_getter(rename = "latest_execution_payload_header_deneb")
)]
pub latest_execution_payload_header: ExecutionPayloadHeaderDeneb,
#[superstruct(
only(Electra),
partial_getter(rename = "latest_execution_payload_header_electra")
)]
pub latest_execution_payload_header: ExecutionPayloadHeaderElectra,

// Capella
#[superstruct(only(Capella, Deneb), partial_getter(copy))]
#[superstruct(only(Capella, Deneb, Electra), partial_getter(copy))]
#[serde(deserialize_with = "as_u64")]
pub next_withdrawal_index: u64,
#[superstruct(only(Capella, Deneb), partial_getter(copy))]
#[superstruct(only(Capella, Deneb, Electra), partial_getter(copy))]
#[serde(deserialize_with = "as_u64")]
pub next_withdrawal_validator_index: u64,
// Deep history valid from Capella onwards.
#[superstruct(only(Capella, Deneb))]
#[superstruct(only(Capella, Deneb, Electra))]
pub historical_summaries: HistoricalSummaries,

// Electra
#[superstruct(only(Electra), partial_getter(copy))]
#[serde(deserialize_with = "as_u64")]
pub deposit_requests_start_index: u64,
#[superstruct(only(Electra), partial_getter(copy))]
#[serde(deserialize_with = "as_u64")]
pub deposit_balance_to_consume: u64,
#[superstruct(only(Electra), partial_getter(copy))]
#[serde(deserialize_with = "as_u64")]
pub exit_balance_to_consume: u64,
#[superstruct(only(Electra), partial_getter(copy))]
pub earliest_exit_epoch: Epoch,
#[superstruct(only(Electra), partial_getter(copy))]
#[serde(deserialize_with = "as_u64")]
pub consolidation_balance_to_consume: u64,
#[superstruct(only(Electra), partial_getter(copy))]
pub earliest_consolidation_epoch: Epoch,
#[superstruct(only(Electra))]
pub pending_deposits: VariableList<PendingDeposit, PendingDepositsLimit>,
#[superstruct(only(Electra))]
pub pending_partial_withdrawals:
VariableList<PendingPartialWithdrawal, PendingPartialWithdrawalsLimit>,
#[superstruct(only(Electra))]
pub pending_consolidations: VariableList<PendingConsolidation, PendingConsolidationsLimit>,
}

impl BeaconState {
Expand All @@ -161,6 +198,7 @@ impl BeaconState {
ForkName::Bellatrix => BeaconStateBellatrix::from_ssz_bytes(bytes).map(Self::Bellatrix),
ForkName::Capella => BeaconStateCapella::from_ssz_bytes(bytes).map(Self::Capella),
ForkName::Deneb => BeaconStateDeneb::from_ssz_bytes(bytes).map(Self::Deneb),
ForkName::Electra => BeaconStateElectra::from_ssz_bytes(bytes).map(Self::Electra),
}
}
}
Expand Down
Loading