BeaconState and BeaconBlockBody mods

This commit is contained in:
shane-moore
2025-08-04 17:46:34 -07:00
committed by Mark Mackey
parent 064e8fc23c
commit 4be0b3aaab
30 changed files with 580 additions and 637 deletions

View File

@@ -5726,6 +5726,9 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
execution_payload_value,
)
}
// Below is my attempt at handling the Gloas variant
// Note that Mark's implementation had this as:
// BeaconState::EIP7732(_) => todo!("EIP-7732 block production"),
BeaconState::Gloas(_) => {
// Gloas blocks contain execution bids, not execution payloads
let block_proposal_contents =
@@ -5752,8 +5755,8 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
sync_aggregate: sync_aggregate
.ok_or(BlockProductionError::MissingSyncAggregate)?,
bls_to_execution_changes: bls_to_execution_changes.into(),
// EIP-7732: Use actual execution bid data
signed_execution_payload_header: signed_execution_bid.clone(),
// Gloas: Use actual execution bid data
signed_execution_bid: signed_execution_bid.clone(),
payload_attestations,
_phantom: PhantomData,
},

View File

@@ -541,34 +541,6 @@ impl<E: EthSpec> ExecutionPayloadBodyV1<E> {
))
}
}
ExecutionPayloadHeader::Gloas(header) => {
if let Some(withdrawals) = self.withdrawals {
Ok(ExecutionPayload::Gloas(ExecutionPayloadGloas {
parent_hash: header.parent_hash,
fee_recipient: header.fee_recipient,
state_root: header.state_root,
receipts_root: header.receipts_root,
logs_bloom: header.logs_bloom,
prev_randao: header.prev_randao,
block_number: header.block_number,
gas_limit: header.gas_limit,
gas_used: header.gas_used,
timestamp: header.timestamp,
extra_data: header.extra_data,
base_fee_per_gas: header.base_fee_per_gas,
block_hash: header.block_hash,
transactions: self.transactions,
withdrawals,
blob_gas_used: header.blob_gas_used,
excess_blob_gas: header.excess_blob_gas,
}))
} else {
Err(format!(
"block {} is post capella but payload body doesn't have withdrawals",
header.block_hash
))
}
}
}
}
}

View File

@@ -172,12 +172,13 @@ impl<'block, E: EthSpec> NewPayloadRequest<'block, E> {
}
}
//TODO(EIP7732): Consider implmenting these as methods on the NewPayloadRequest struct
impl<'a, E: EthSpec> TryFrom<BeaconBlockRef<'a, E>> for NewPayloadRequest<'a, E> {
type Error = BeaconStateError;
fn try_from(block: BeaconBlockRef<'a, E>) -> Result<Self, Self::Error> {
match block {
BeaconBlockRef::Base(_) | BeaconBlockRef::Altair(_) | BeaconBlockRef::Gloas(_) => {
BeaconBlockRef::Base(_) | BeaconBlockRef::Altair(_) => {
Err(Self::Error::IncorrectStateVariant)
}
BeaconBlockRef::Bellatrix(block_ref) => {
@@ -220,6 +221,7 @@ impl<'a, E: EthSpec> TryFrom<BeaconBlockRef<'a, E>> for NewPayloadRequest<'a, E>
parent_beacon_block_root: block_ref.parent_root,
execution_requests: &block_ref.body.execution_requests,
})),
BeaconBlockRef::Gloas(_) => Err(Self::Error::IncorrectStateVariant),
}
}
}
@@ -240,11 +242,15 @@ impl<'a, E: EthSpec> TryFrom<ExecutionPayloadRef<'a, E>> for NewPayloadRequest<'
ExecutionPayloadRef::Deneb(_) => Err(Self::Error::IncorrectStateVariant),
ExecutionPayloadRef::Electra(_) => Err(Self::Error::IncorrectStateVariant),
ExecutionPayloadRef::Fulu(_) => Err(Self::Error::IncorrectStateVariant),
//TODO(EIP7732): Probably time to just get rid of this
ExecutionPayloadRef::Gloas(_) => Err(Self::Error::IncorrectStateVariant),
}
}
}
// TODO(EIP-7732) build out the following when it's needed like in Mark's branch
// impl<'a, E: EthSpec> TryFrom<ExecutionEnvelopeRef<'a, E>> for NewPayloadRequest<E> {
#[cfg(test)]
mod test {
use crate::versioned_hashes::Error as VersionedHashError;

View File

@@ -55,8 +55,8 @@ use types::{
};
use types::{
BeaconStateError, BlindedPayload, ChainSpec, Epoch, ExecPayload, ExecutionPayloadBellatrix,
ExecutionPayloadCapella, ExecutionPayloadElectra, ExecutionPayloadFulu, ExecutionPayloadGloas,
FullPayload, ProposerPreparationData, PublicKeyBytes, Signature, Slot,
ExecutionPayloadCapella, ExecutionPayloadElectra, ExecutionPayloadFulu, FullPayload,
ProposerPreparationData, PublicKeyBytes, Signature, Slot,
};
mod block_hash;
@@ -131,13 +131,6 @@ impl<E: EthSpec> TryFrom<BuilderBid<E>> for ProvenancedPayload<BlockProposalCont
blobs_and_proofs: None,
requests: Some(builder_bid.execution_requests),
},
BuilderBid::Gloas(builder_bid) => BlockProposalContents::PayloadAndBlobs {
payload: ExecutionPayloadHeader::Gloas(builder_bid.header).into(),
block_value: builder_bid.value,
kzg_commitments: builder_bid.blob_kzg_commitments,
blobs_and_proofs: None,
requests: Some(builder_bid.execution_requests),
},
};
Ok(ProvenancedPayload::Builder(
BlockProposalContentsType::Blinded(block_proposal_contents),
@@ -219,7 +212,7 @@ pub enum BlockProposalContents<E: EthSpec, Payload: AbstractExecPayload<E>> {
// See: https://github.com/sigp/lighthouse/issues/6981
requests: Option<ExecutionRequests<E>>,
},
/// EIP-7732: Execution bid and payload attestations for Gloas fork
/// Gloas: Execution bid and payload attestations
BidAndPayloadAttestations {
signed_execution_bid: SignedExecutionBid,
payload_attestations: VariableList<PayloadAttestation<E>, E::MaxPayloadAttestations>,
@@ -1399,6 +1392,7 @@ impl<E: EthSpec> ExecutionLayer<E> {
}
/// Maps to the `engine_newPayload` JSON-RPC call.
/// TODO(EIP-7732) figure out how and why Mark relaxed new_payload_request param's typ to NewPayloadRequest<E>
pub async fn notify_new_payload(
&self,
new_payload_request: NewPayloadRequest<'_, E>,
@@ -1870,10 +1864,12 @@ impl<E: EthSpec> ExecutionLayer<E> {
ForkName::Deneb => ExecutionPayloadDeneb::default().into(),
ForkName::Electra => ExecutionPayloadElectra::default().into(),
ForkName::Fulu => ExecutionPayloadFulu::default().into(),
ForkName::Gloas => ExecutionPayloadGloas::default().into(),
ForkName::Base | ForkName::Altair => {
return Err(Error::InvalidForkForPayload);
}
ForkName::Gloas => {
return Err(Error::InvalidForkForPayload);
}
};
return Ok(Some(payload));
}

View File

@@ -908,12 +908,8 @@ pub fn generate_genesis_header<E: EthSpec>(
*header.transactions_root_mut() = empty_transactions_root;
Some(header)
}
ForkName::Gloas => {
let mut header = ExecutionPayloadHeader::Gloas(<_>::default());
*header.block_hash_mut() = genesis_block_hash.unwrap_or_default();
*header.transactions_root_mut() = empty_transactions_root;
Some(header)
}
// TODO(EIP-7732): need to look into this
ForkName::Gloas => None,
}
}

View File

@@ -27,7 +27,7 @@ use tracing::{debug, error, info, warn};
use tree_hash::TreeHash;
use types::builder_bid::{
BuilderBid, BuilderBidBellatrix, BuilderBidCapella, BuilderBidDeneb, BuilderBidElectra,
BuilderBidFulu, BuilderBidGloas, SignedBuilderBid,
BuilderBidFulu, SignedBuilderBid,
};
use types::{
Address, BeaconState, ChainSpec, Epoch, EthSpec, ExecPayload, ExecutionPayload,
@@ -115,9 +115,6 @@ impl<E: EthSpec> BidStuff<E> for BuilderBid<E> {
ExecutionPayloadHeaderRefMut::Fulu(header) => {
header.fee_recipient = fee_recipient;
}
ExecutionPayloadHeaderRefMut::Gloas(header) => {
header.fee_recipient = fee_recipient;
}
}
}
@@ -138,9 +135,6 @@ impl<E: EthSpec> BidStuff<E> for BuilderBid<E> {
ExecutionPayloadHeaderRefMut::Fulu(header) => {
header.gas_limit = gas_limit;
}
ExecutionPayloadHeaderRefMut::Gloas(header) => {
header.gas_limit = gas_limit;
}
}
}
@@ -165,9 +159,6 @@ impl<E: EthSpec> BidStuff<E> for BuilderBid<E> {
ExecutionPayloadHeaderRefMut::Fulu(header) => {
header.parent_hash = ExecutionBlockHash::from_root(parent_hash);
}
ExecutionPayloadHeaderRefMut::Gloas(header) => {
header.parent_hash = ExecutionBlockHash::from_root(parent_hash);
}
}
}
@@ -188,9 +179,6 @@ impl<E: EthSpec> BidStuff<E> for BuilderBid<E> {
ExecutionPayloadHeaderRefMut::Fulu(header) => {
header.prev_randao = prev_randao;
}
ExecutionPayloadHeaderRefMut::Gloas(header) => {
header.prev_randao = prev_randao;
}
}
}
@@ -211,9 +199,6 @@ impl<E: EthSpec> BidStuff<E> for BuilderBid<E> {
ExecutionPayloadHeaderRefMut::Fulu(header) => {
header.block_number = block_number;
}
ExecutionPayloadHeaderRefMut::Gloas(header) => {
header.block_number = block_number;
}
}
}
@@ -234,9 +219,6 @@ impl<E: EthSpec> BidStuff<E> for BuilderBid<E> {
ExecutionPayloadHeaderRefMut::Fulu(header) => {
header.timestamp = timestamp;
}
ExecutionPayloadHeaderRefMut::Gloas(header) => {
header.timestamp = timestamp;
}
}
}
@@ -257,9 +239,6 @@ impl<E: EthSpec> BidStuff<E> for BuilderBid<E> {
ExecutionPayloadHeaderRefMut::Fulu(header) => {
header.withdrawals_root = withdrawals_root;
}
ExecutionPayloadHeaderRefMut::Gloas(header) => {
header.withdrawals_root = withdrawals_root;
}
}
}
@@ -293,10 +272,6 @@ impl<E: EthSpec> BidStuff<E> for BuilderBid<E> {
header.extra_data = extra_data;
header.block_hash = ExecutionBlockHash::from_root(header.tree_hash_root());
}
ExecutionPayloadHeaderRefMut::Gloas(header) => {
header.extra_data = extra_data;
header.block_hash = ExecutionBlockHash::from_root(header.tree_hash_root());
}
}
}
}
@@ -464,9 +439,7 @@ impl<E: EthSpec> MockBuilder<E> {
block: SignedBlindedBeaconBlock<E>,
) -> Result<FullPayloadContents<E>, String> {
let root = match &block {
SignedBlindedBeaconBlock::Base(_)
| SignedBlindedBeaconBlock::Altair(_)
| SignedBlindedBeaconBlock::Gloas(_) => {
SignedBlindedBeaconBlock::Base(_) | SignedBlindedBeaconBlock::Altair(_) => {
return Err("invalid fork".to_string());
}
SignedBlindedBeaconBlock::Bellatrix(block) => {
@@ -484,6 +457,10 @@ impl<E: EthSpec> MockBuilder<E> {
SignedBlindedBeaconBlock::Fulu(block) => {
block.message.body.execution_payload.tree_hash_root()
}
SignedBlindedBeaconBlock::Gloas(_) => {
// TODO(EIP7732) Check if this is how we want to do error handling for gloas
return Err("invalid fork".to_string());
}
};
info!(
block_hash = %root,
@@ -567,18 +544,10 @@ impl<E: EthSpec> MockBuilder<E> {
) = payload_response.into();
match fork {
ForkName::Gloas => BuilderBid::Gloas(BuilderBidGloas {
header: payload
.as_gloas()
.map_err(|_| "incorrect payload variant".to_string())?
.into(),
blob_kzg_commitments: maybe_blobs_bundle
.map(|b| b.commitments.clone())
.unwrap_or_default(),
value: self.get_bid_value(value),
pubkey: self.builder_sk.public_key().compress(),
execution_requests: maybe_requests.unwrap_or_default(),
}),
ForkName::Gloas => {
// TODO(EIP7732) Check if this is how we want to do error handling for gloas
return Err("invalid fork".to_string());
}
ForkName::Fulu => BuilderBid::Fulu(BuilderBidFulu {
header: payload
.as_fulu()
@@ -877,6 +846,10 @@ impl<E: EthSpec> MockBuilder<E> {
// first to avoid polluting the execution block generator with invalid payload attributes
// NOTE: this was part of an effort to add payload attribute uniqueness checks,
// which was abandoned because it broke too many tests in subtle ways.
ForkName::Gloas => {
// TODO(EIP7732) Check if this is how we want to do error handling for gloas
return Err("invalid fork".to_string());
}
ForkName::Bellatrix | ForkName::Capella => PayloadAttributes::new(
timestamp,
*prev_randao,
@@ -884,16 +857,11 @@ impl<E: EthSpec> MockBuilder<E> {
expected_withdrawals,
None,
),
ForkName::Deneb | ForkName::Electra | ForkName::Fulu | ForkName::Gloas => {
PayloadAttributes::new(
timestamp,
*prev_randao,
fee_recipient,
expected_withdrawals,
Some(head_block_root),
)
}
ForkName::Base | ForkName::Altair => {
ForkName::Deneb
| ForkName::Electra
| ForkName::Fulu
| ForkName::Base
| ForkName::Altair => {
return Err("invalid fork".to_string());
}
};

View File

@@ -115,11 +115,9 @@ where
partial_getter(rename = "latest_execution_payload_header_fulu")
)]
pub latest_execution_payload_header: ExecutionPayloadHeaderFulu<E>,
#[superstruct(
only(Gloas),
partial_getter(rename = "latest_execution_payload_header_gloas")
)]
pub latest_execution_payload_header: ExecutionPayloadHeaderGloas<E>,
#[superstruct(only(Gloas), partial_getter(rename = "latest_execution_bid_gloas"))]
pub latest_execution_bid: ExecutionBid,
// Capella
#[superstruct(only(Capella, Deneb, Electra, Fulu, Gloas))]
@@ -154,6 +152,27 @@ where
pub pending_consolidations: List<PendingConsolidation, E::PendingConsolidationsLimit>,
#[superstruct(only(Fulu, Gloas))]
pub proposer_lookahead: Vector<u64, E::ProposerLookaheadSlots>,
// Gloas
// Gloas
#[superstruct(only(Gloas))]
pub execution_payload_availability: BitVector<E::SlotsPerHistoricalRoot>,
#[superstruct(only(Gloas))]
pub builder_pending_payments: Vector<BuilderPendingPayment, E::BuilderPendingPaymentsLimit>,
#[superstruct(only(Gloas))]
pub builder_pending_withdrawals:
List<BuilderPendingWithdrawal, E::BuilderPendingWithdrawalsLimit>,
#[superstruct(only(Gloas))]
pub latest_block_hash: ExecutionBlockHash,
#[superstruct(only(Gloas))]
pub latest_full_slot: Slot,
#[superstruct(only(Gloas))]
pub latest_withdrawals_root: Hash256,
}
impl<E: EthSpec> PartialBeaconState<E> {
@@ -465,7 +484,7 @@ impl<E: EthSpec> TryInto<BeaconState<E>> for PartialBeaconState<E> {
current_sync_committee,
next_sync_committee,
inactivity_scores,
latest_execution_payload_header,
latest_execution_bid,
next_withdrawal_index,
next_withdrawal_validator_index,
deposit_requests_start_index,
@@ -477,7 +496,13 @@ impl<E: EthSpec> TryInto<BeaconState<E>> for PartialBeaconState<E> {
pending_deposits,
pending_partial_withdrawals,
pending_consolidations,
proposer_lookahead
proposer_lookahead,
execution_payload_availability,
builder_pending_payments,
builder_pending_withdrawals,
latest_block_hash,
latest_full_slot,
latest_withdrawals_root
],
[historical_summaries]
),

View File

@@ -167,9 +167,8 @@ pub fn initialize_beacon_state_from_eth1<E: EthSpec>(
state.fork_mut().previous_version = spec.gloas_fork_version;
// Override latest execution payload header.
if let Some(ExecutionPayloadHeader::Gloas(header)) = execution_payload_header {
*state.latest_execution_payload_header_gloas_mut()? = header.clone();
}
// Here's where we *would* clone the header but there is no header here so..
// TODO(EIP7732): check this
}
// Now that we have our validators, initialize the caches (including the committees)

View File

@@ -30,6 +30,7 @@ pub mod deneb;
pub mod errors;
mod is_valid_indexed_attestation;
pub mod process_operations;
pub mod process_withdrawals;
pub mod signature_sets;
pub mod tests;
mod verify_attestation;
@@ -39,8 +40,6 @@ mod verify_deposit;
mod verify_exit;
mod verify_proposer_slashing;
use crate::common::decrease_balance;
use crate::common::update_progressive_balances_cache::{
initialize_progressive_balances_cache, update_progressive_balances_metrics,
};
@@ -172,10 +171,21 @@ pub fn per_block_processing<E: EthSpec, Payload: AbstractExecPayload<E>>(
// previous block.
if is_execution_enabled(state, block.body()) {
let body = block.body();
process_withdrawals::<E, Payload>(state, body.execution_payload()?, spec)?;
process_execution_payload::<E, Payload>(state, body, spec)?;
if state.fork_name_unchecked().gloas_enabled() {
process_withdrawals::gloas::process_withdrawals::<E>(state, spec)?;
} else {
process_withdrawals::capella::process_withdrawals::<E, Payload>(
state,
body.execution_payload()?,
spec,
)?;
process_execution_payload::<E, Payload>(state, body, spec)?;
}
}
// TODO(EIP-7732): build out process_execution_bid
// process_execution_bid(state, block, verify_signatures, spec)?;
process_randao(state, block, verify_randao, ctxt, spec)?;
process_eth1_data(state, block.body().eth1_data())?;
process_operations(state, block.body(), verify_signatures, ctxt, spec)?;
@@ -452,12 +462,6 @@ pub fn process_execution_payload<E: EthSpec, Payload: AbstractExecPayload<E>>(
_ => return Err(BlockProcessingError::IncorrectStateType),
}
}
ExecutionPayloadHeaderRefMut::Gloas(header_mut) => {
match payload.to_execution_payload_header() {
ExecutionPayloadHeader::Gloas(header) => *header_mut = header,
_ => return Err(BlockProcessingError::IncorrectStateType),
}
}
}
Ok(())
@@ -469,6 +473,7 @@ 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 {
// TODO(EIP7732): check this cause potuz modified this function for god knows what reason
if state.fork_name_unchecked().capella_enabled() {
true
} else if state.fork_name_unchecked().bellatrix_enabled() {
@@ -630,68 +635,3 @@ pub fn get_expected_withdrawals<E: EthSpec>(
Ok((withdrawals.into(), processed_partial_withdrawals_count))
}
/// Apply withdrawals to the state.
pub fn process_withdrawals<E: EthSpec, Payload: AbstractExecPayload<E>>(
state: &mut BeaconState<E>,
payload: Payload::Ref<'_>,
spec: &ChainSpec,
) -> Result<(), BlockProcessingError> {
if state.fork_name_unchecked().capella_enabled() {
let (expected_withdrawals, processed_partial_withdrawals_count) =
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,
});
}
for withdrawal in expected_withdrawals.iter() {
decrease_balance(
state,
withdrawal.validator_index as usize,
withdrawal.amount,
)?;
}
// Update pending partial withdrawals [New in Electra:EIP7251]
if let Some(processed_partial_withdrawals_count) = processed_partial_withdrawals_count {
state
.pending_partial_withdrawals_mut()?
.pop_front(processed_partial_withdrawals_count)?;
}
// 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)?
.safe_rem(state.validators().len() as u64)?;
*state.next_withdrawal_validator_index_mut()? = next_validator_index;
}
Ok(())
} else {
// these shouldn't even be encountered but they're here for completeness
Ok(())
}
}

View File

@@ -0,0 +1,105 @@
use super::errors::BlockProcessingError;
use super::get_expected_withdrawals;
use crate::common::decrease_balance;
use safe_arith::SafeArith;
use tree_hash::TreeHash;
use types::{AbstractExecPayload, BeaconState, ChainSpec, EthSpec, ExecPayload, Withdrawals};
fn process_withdrawals_common<E: EthSpec>(
state: &mut BeaconState<E>,
expected_withdrawals: Withdrawals<E>,
partial_withdrawals_count: Option<usize>,
spec: &ChainSpec,
) -> Result<(), BlockProcessingError> {
match state {
BeaconState::Capella(_)
| BeaconState::Deneb(_)
| BeaconState::Electra(_)
| BeaconState::Fulu(_)
| BeaconState::Gloas(_) => {
for withdrawal in expected_withdrawals.iter() {
decrease_balance(
state,
withdrawal.validator_index as usize,
withdrawal.amount,
)?;
}
// Update pending partial withdrawals [New in Electra:EIP7251]
if let Some(partial_withdrawals_count) = partial_withdrawals_count {
state
.pending_partial_withdrawals_mut()?
.pop_front(partial_withdrawals_count)?;
}
// 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)?
.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(_) | BeaconState::Bellatrix(_) => Ok(()),
}
}
pub mod capella {
use super::*;
/// Apply withdrawals to the state.
pub fn process_withdrawals<E: EthSpec, Payload: AbstractExecPayload<E>>(
state: &mut BeaconState<E>,
payload: Payload::Ref<'_>,
spec: &ChainSpec,
) -> Result<(), BlockProcessingError> {
let (expected_withdrawals, partial_withdrawals_count) =
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,
});
}
process_withdrawals_common(state, expected_withdrawals, partial_withdrawals_count, spec)
}
}
pub mod gloas {
use super::*;
/// Apply withdrawals to the state.
pub fn process_withdrawals<E: EthSpec>(
state: &mut BeaconState<E>,
spec: &ChainSpec,
) -> Result<(), BlockProcessingError> {
if !state.is_parent_block_full() {
return Ok(());
}
let (expected_withdrawals, partial_withdrawals_count) =
get_expected_withdrawals(state, spec)?;
process_withdrawals_common(state, expected_withdrawals, partial_withdrawals_count, spec)
}
}

View File

@@ -1,5 +1,9 @@
use bls::Hash256;
use std::mem;
use types::{BeaconState, BeaconStateError as Error, BeaconStateGloas, ChainSpec, EthSpec, Fork};
use types::{
BeaconState, BeaconStateError as Error, BeaconStateGloas, BitVector, ChainSpec, EthSpec,
ExecutionBid, Fork, List, Vector,
};
/// Transform a `Fulu` state into a `Gloas` state.
pub fn upgrade_to_gloas<E: EthSpec>(
@@ -63,8 +67,8 @@ pub fn upgrade_state_to_gloas<E: EthSpec>(
// Sync committees
current_sync_committee: pre.current_sync_committee.clone(),
next_sync_committee: pre.next_sync_committee.clone(),
// Execution
latest_execution_payload_header: pre.latest_execution_payload_header.upgrade_to_gloas(),
// Execution Bid
latest_execution_bid: ExecutionBid::default(),
// Capella
next_withdrawal_index: pre.next_withdrawal_index,
next_withdrawal_validator_index: pre.next_withdrawal_validator_index,
@@ -79,6 +83,13 @@ pub fn upgrade_state_to_gloas<E: EthSpec>(
pending_deposits: pre.pending_deposits.clone(),
pending_partial_withdrawals: pre.pending_partial_withdrawals.clone(),
pending_consolidations: pre.pending_consolidations.clone(),
// Gloas
execution_payload_availability: BitVector::default(), // All bits set to false initially
builder_pending_payments: Vector::default(), // Empty vector initially,
builder_pending_withdrawals: List::default(), // Empty list initially,
latest_block_hash: pre.latest_execution_payload_header.block_hash,
latest_full_slot: pre.slot,
latest_withdrawals_root: Hash256::default(),
// Caches
total_active_balance: pre.total_active_balance,
progressive_balances_cache: mem::take(&mut pre.progressive_balances_cache),

View File

@@ -673,7 +673,7 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> EmptyBlock for BeaconBlockGloa
voluntary_exits: VariableList::empty(),
sync_aggregate: SyncAggregate::empty(),
bls_to_execution_changes: VariableList::empty(),
signed_execution_payload_header: SignedExecutionBid::empty(),
signed_execution_bid: SignedExecutionBid::empty(),
payload_attestations: VariableList::empty(),
_phantom: PhantomData,
},
@@ -681,6 +681,31 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> EmptyBlock for BeaconBlockGloa
}
}
/// TODO(EIP-7732) Mark's branch had the following implementation but not sure if it's needed so will just add header below for reference
// impl<E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockEIP7732<E, Payload> {
impl<E: EthSpec> From<BeaconBlockGloas<E, BlindedPayload<E>>>
for BeaconBlockGloas<E, FullPayload<E>>
{
fn from(block: BeaconBlockGloas<E, BlindedPayload<E>>) -> Self {
let BeaconBlockGloas {
slot,
proposer_index,
parent_root,
state_root,
body,
} = block;
BeaconBlockGloas {
slot,
proposer_index,
parent_root,
state_root,
body: body.into(),
}
}
}
// We can convert pre-Bellatrix blocks without payloads into blocks "with" payloads.
impl<E: EthSpec> From<BeaconBlockBase<E, BlindedPayload<E>>>
for BeaconBlockBase<E, FullPayload<E>>

View File

@@ -61,11 +61,7 @@ pub const BLOB_KZG_COMMITMENTS_INDEX: usize = 11;
Deneb(metastruct(mappings(beacon_block_body_deneb_fields(groups(fields))))),
Electra(metastruct(mappings(beacon_block_body_electra_fields(groups(fields))))),
Fulu(metastruct(mappings(beacon_block_body_fulu_fields(groups(fields))))),
// we relax the trait bounds for gloas since it doesn't contain a Payload
Gloas(
derivative(PartialEq, Hash(bound = "E: EthSpec")),
metastruct(mappings(beacon_block_body_gloas_fields(groups(fields))))
),
Gloas(metastruct(mappings(beacon_block_body_gloas_fields(groups(fields))))),
),
cast_error(ty = "Error", expr = "Error::IncorrectStateVariant"),
partial_getter_error(ty = "Error", expr = "Error::IncorrectStateVariant")
@@ -131,7 +127,7 @@ pub struct BeaconBlockBody<E: EthSpec, Payload: AbstractExecPayload<E> = FullPay
#[superstruct(only(Fulu), partial_getter(rename = "execution_payload_fulu"))]
#[serde(flatten)]
pub execution_payload: Payload::Fulu,
// execution_payload removed from Gloas, replaced with signed_execution_payload_header below
// execution_payload removed from Gloas, replaced with signed_execution_bid below
#[superstruct(only(Capella, Deneb, Electra, Fulu, Gloas))]
pub bls_to_execution_changes:
VariableList<SignedBlsToExecutionChange, E::MaxBlsToExecutionChanges>,
@@ -142,7 +138,7 @@ pub struct BeaconBlockBody<E: EthSpec, Payload: AbstractExecPayload<E> = FullPay
#[superstruct(only(Electra, Fulu))]
pub execution_requests: ExecutionRequests<E>,
#[superstruct(only(Gloas))]
pub signed_execution_payload_header: SignedExecutionBid,
pub signed_execution_bid: SignedExecutionBid,
#[superstruct(only(Gloas))]
pub payload_attestations: VariableList<PayloadAttestation<E>, E::MaxPayloadAttestations>,
#[superstruct(only(Base, Altair, Gloas))]
@@ -168,12 +164,14 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBody<E, Payload> {
impl<'a, E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBodyRef<'a, E, Payload> {
pub fn execution_payload(&self) -> Result<Payload::Ref<'a>, Error> {
match self {
Self::Base(_) | Self::Altair(_) | Self::Gloas(_) => Err(Error::IncorrectStateVariant),
Self::Base(_) | Self::Altair(_) => Err(Error::IncorrectStateVariant),
Self::Bellatrix(body) => Ok(Payload::Ref::from(&body.execution_payload)),
Self::Capella(body) => Ok(Payload::Ref::from(&body.execution_payload)),
Self::Deneb(body) => Ok(Payload::Ref::from(&body.execution_payload)),
Self::Electra(body) => Ok(Payload::Ref::from(&body.execution_payload)),
Self::Fulu(body) => Ok(Payload::Ref::from(&body.execution_payload)),
// TODO(eip-7732): idk if this is right there's no more execution payload
Self::Gloas(_) => Err(Error::IncorrectStateVariant),
}
}
@@ -242,6 +240,7 @@ impl<'a, E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBodyRef<'a, E,
| Self::Bellatrix(_)
| Self::Capella(_)
| Self::Gloas(_) => Err(Error::IncorrectStateVariant),
// TODO(eip-7732): Mark's impl had the Self::EIP-7732 variant below, but I think it should produce error instead since no self.blob_kzg_commitments in BeaconState for gloas
Self::Deneb(_) | Self::Electra(_) | Self::Fulu(_) => {
// We compute the branches by generating 2 merkle trees:
// 1. Merkle tree for the `blob_kzg_commitments` List object
@@ -537,7 +536,7 @@ impl<E: EthSpec> From<BeaconBlockBodyGloas<E, BlindedPayload<E>>>
voluntary_exits,
sync_aggregate,
bls_to_execution_changes,
signed_execution_payload_header,
signed_execution_bid,
payload_attestations,
_phantom,
} = body;
@@ -553,7 +552,7 @@ impl<E: EthSpec> From<BeaconBlockBodyGloas<E, BlindedPayload<E>>>
voluntary_exits,
sync_aggregate,
bls_to_execution_changes,
signed_execution_payload_header,
signed_execution_bid,
payload_attestations,
_phantom: PhantomData,
}
@@ -871,7 +870,7 @@ impl<E: EthSpec> From<BeaconBlockBodyGloas<E, FullPayload<E>>>
voluntary_exits,
sync_aggregate,
bls_to_execution_changes,
signed_execution_payload_header,
signed_execution_bid,
payload_attestations,
_phantom,
} = body;
@@ -888,7 +887,7 @@ impl<E: EthSpec> From<BeaconBlockBodyGloas<E, FullPayload<E>>>
voluntary_exits,
sync_aggregate,
bls_to_execution_changes,
signed_execution_payload_header,
signed_execution_bid,
payload_attestations,
_phantom: PhantomData,
},

View File

@@ -516,14 +516,9 @@ where
)]
#[metastruct(exclude_from(tree_lists))]
pub latest_execution_payload_header: ExecutionPayloadHeaderFulu<E>,
#[superstruct(
only(Gloas),
partial_getter(rename = "latest_execution_payload_header_gloas")
)]
#[superstruct(only(Gloas))]
#[metastruct(exclude_from(tree_lists))]
pub latest_execution_payload_header: ExecutionPayloadHeaderGloas<E>,
// Capella
pub latest_execution_bid: ExecutionBid,
#[superstruct(only(Capella, Deneb, Electra, Fulu, Gloas), partial_getter(copy))]
#[serde(with = "serde_utils::quoted_u64")]
#[metastruct(exclude_from(tree_lists))]
@@ -581,6 +576,36 @@ where
pub proposer_lookahead: Vector<u64, E::ProposerLookaheadSlots>,
// Gloas
#[test_random(default)]
#[superstruct(only(Gloas))]
#[metastruct(exclude_from(tree_lists))]
pub execution_payload_availability: BitVector<E::SlotsPerHistoricalRoot>,
#[compare_fields(as_iter)]
#[test_random(default)]
#[superstruct(only(Gloas))]
pub builder_pending_payments: Vector<BuilderPendingPayment, E::BuilderPendingPaymentsLimit>,
#[compare_fields(as_iter)]
#[test_random(default)]
#[superstruct(only(Gloas))]
pub builder_pending_withdrawals:
List<BuilderPendingWithdrawal, E::BuilderPendingWithdrawalsLimit>,
#[test_random(default)]
#[superstruct(only(Gloas))]
#[metastruct(exclude_from(tree_lists))]
pub latest_block_hash: ExecutionBlockHash,
#[test_random(default)]
#[superstruct(only(Gloas))]
#[metastruct(exclude_from(tree_lists))]
pub latest_full_slot: Slot,
#[test_random(default)]
#[superstruct(only(Gloas))]
#[metastruct(exclude_from(tree_lists))]
pub latest_withdrawals_root: Hash256,
// Caching (not in the spec)
#[serde(skip_serializing, skip_deserializing)]
@@ -1071,9 +1096,8 @@ impl<E: EthSpec> BeaconState<E> {
BeaconState::Fulu(state) => Ok(ExecutionPayloadHeaderRef::Fulu(
&state.latest_execution_payload_header,
)),
BeaconState::Gloas(state) => Ok(ExecutionPayloadHeaderRef::Gloas(
&state.latest_execution_payload_header,
)),
// FIXME(EIP-7732): this is only to make the code compile, needs to be written later
BeaconState::Gloas(_) => Err(Error::IncorrectStateVariant),
}
}
@@ -1097,9 +1121,8 @@ impl<E: EthSpec> BeaconState<E> {
BeaconState::Fulu(state) => Ok(ExecutionPayloadHeaderRefMut::Fulu(
&mut state.latest_execution_payload_header,
)),
BeaconState::Gloas(state) => Ok(ExecutionPayloadHeaderRefMut::Gloas(
&mut state.latest_execution_payload_header,
)),
// FIXME(EIP-7732): this is only to make the code compile, needs to be written later
BeaconState::Gloas(_) => Err(Error::IncorrectStateVariant),
}
}
@@ -1836,6 +1859,7 @@ impl<E: EthSpec> BeaconState<E> {
| BeaconState::Altair(_)
| BeaconState::Bellatrix(_)
| BeaconState::Capella(_) => self.get_validator_churn_limit(spec)?,
// FIXME(EIP-7732): check this
BeaconState::Deneb(_)
| BeaconState::Electra(_)
| BeaconState::Fulu(_)
@@ -2116,6 +2140,20 @@ impl<E: EthSpec> BeaconState<E> {
}
}
pub fn is_parent_block_full(&self) -> bool {
match self {
BeaconState::Base(_) | BeaconState::Altair(_) => false,
BeaconState::Bellatrix(_)
| BeaconState::Capella(_)
| BeaconState::Deneb(_)
| BeaconState::Electra(_)
| BeaconState::Fulu(_) => true,
BeaconState::Gloas(state) => {
state.latest_execution_bid.block_hash == state.latest_block_hash
}
}
}
/// Get the committee cache for some `slot`.
///
/// Return an error if the cache for the slot's epoch is not initialized.

View File

@@ -2,7 +2,7 @@ use crate::beacon_block_body::KzgCommitments;
use crate::{
ChainSpec, ContextDeserialize, EthSpec, ExecutionPayloadHeaderBellatrix,
ExecutionPayloadHeaderCapella, ExecutionPayloadHeaderDeneb, ExecutionPayloadHeaderElectra,
ExecutionPayloadHeaderFulu, ExecutionPayloadHeaderGloas, ExecutionPayloadHeaderRef,
ExecutionPayloadHeaderFulu, ExecutionPayloadHeaderRef,
ExecutionPayloadHeaderRefMut, ExecutionRequests, ForkName, ForkVersionDecode, SignedRoot,
Uint256, test_utils::TestRandom,
};
@@ -16,7 +16,7 @@ use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash;
#[superstruct(
variants(Bellatrix, Capella, Deneb, Electra, Fulu, Gloas),
variants(Bellatrix, Capella, Deneb, Electra, Fulu),
variant_attributes(
derive(
PartialEq,
@@ -49,11 +49,9 @@ pub struct BuilderBid<E: EthSpec> {
pub header: ExecutionPayloadHeaderElectra<E>,
#[superstruct(only(Fulu), partial_getter(rename = "header_fulu"))]
pub header: ExecutionPayloadHeaderFulu<E>,
#[superstruct(only(Gloas), partial_getter(rename = "header_gloas"))]
pub header: ExecutionPayloadHeaderGloas<E>,
#[superstruct(only(Deneb, Electra, Fulu, Gloas))]
#[superstruct(only(Deneb, Electra, Fulu))]
pub blob_kzg_commitments: KzgCommitments<E>,
#[superstruct(only(Electra, Fulu, Gloas))]
#[superstruct(only(Electra, Fulu))]
pub execution_requests: ExecutionRequests<E>,
#[serde(with = "serde_utils::quoted_u256")]
pub value: Uint256,
@@ -86,7 +84,7 @@ impl<E: EthSpec> ForkVersionDecode for BuilderBid<E> {
/// SSZ decode with explicit fork variant.
fn from_ssz_bytes_by_fork(bytes: &[u8], fork_name: ForkName) -> Result<Self, ssz::DecodeError> {
let builder_bid = match fork_name {
ForkName::Altair | ForkName::Base => {
ForkName::Altair | ForkName::Base | ForkName::Gloas => {
return Err(ssz::DecodeError::BytesInvalid(format!(
"unsupported fork for ExecutionPayloadHeader: {fork_name}",
)));
@@ -98,7 +96,6 @@ impl<E: EthSpec> ForkVersionDecode for BuilderBid<E> {
ForkName::Deneb => BuilderBid::Deneb(BuilderBidDeneb::from_ssz_bytes(bytes)?),
ForkName::Electra => BuilderBid::Electra(BuilderBidElectra::from_ssz_bytes(bytes)?),
ForkName::Fulu => BuilderBid::Fulu(BuilderBidFulu::from_ssz_bytes(bytes)?),
ForkName::Gloas => BuilderBid::Gloas(BuilderBidGloas::from_ssz_bytes(bytes)?),
};
Ok(builder_bid)
}
@@ -154,10 +151,7 @@ impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for BuilderBid<E> {
ForkName::Fulu => {
Self::Fulu(Deserialize::deserialize(deserializer).map_err(convert_err)?)
}
ForkName::Gloas => {
Self::Gloas(Deserialize::deserialize(deserializer).map_err(convert_err)?)
}
ForkName::Base | ForkName::Altair => {
ForkName::Base | ForkName::Altair | ForkName::Gloas => {
return Err(serde::de::Error::custom(format!(
"BuilderBid failed to deserialize: unsupported fork '{}'",
context

View File

@@ -6,7 +6,18 @@ use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash;
#[derive(
Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom,
Debug,
PartialEq,
Eq,
Hash,
Clone,
Default,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
TestRandom,
)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[context_deserialize(ForkName)]

View File

@@ -6,7 +6,18 @@ use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash;
#[derive(
Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom,
Debug,
PartialEq,
Eq,
Hash,
Clone,
Default,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
TestRandom,
)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[context_deserialize(ForkName)]

View File

@@ -0,0 +1,107 @@
// These would usually be created by superstuct but now there's no longer a 1:1 mapping between
// the variants for ExecutionPayload and the variants for
// - ExecutionPayloadHeader
// - FullPayload
// - BlindedPayload
#[macro_export]
macro_rules! map_execution_payload_into_full_payload {
($value:expr, $f:expr) => {
match $value {
ExecutionPayload::Bellatrix(inner) => {
let f: fn(ExecutionPayloadBellatrix<_>, fn(_) -> _) -> _ = $f;
f(inner, FullPayload::Bellatrix)
}
ExecutionPayload::Capella(inner) => {
let f: fn(ExecutionPayloadCapella<_>, fn(_) -> _) -> _ = $f;
f(inner, FullPayload::Capella)
}
ExecutionPayload::Deneb(inner) => {
let f: fn(ExecutionPayloadDeneb<_>, fn(_) -> _) -> _ = $f;
f(inner, FullPayload::Deneb)
}
ExecutionPayload::Electra(inner) => {
let f: fn(ExecutionPayloadElectra<_>, fn(_) -> _) -> _ = $f;
f(inner, FullPayload::Electra)
}
ExecutionPayload::Fulu(inner) => {
let f: fn(ExecutionPayloadFulu<_>, fn(_) -> _) -> _ = $f;
f(inner, FullPayload::Fulu)
}
ExecutionPayload::Gloas(_) => panic!("FullPayload::Gloas does not exist!"),
}
};
}
#[macro_export]
macro_rules! map_execution_payload_into_blinded_payload {
($value:expr, $f:expr) => {
match $value {
ExecutionPayload::Bellatrix(inner) => {
let f: fn(ExecutionPayloadBellatrix<_>, fn(_) -> _) -> _ = $f;
f(inner, BlindedPayload::Bellatrix)
}
ExecutionPayload::Capella(inner) => {
let f: fn(ExecutionPayloadCapella<_>, fn(_) -> _) -> _ = $f;
f(inner, BlindedPayload::Capella)
}
ExecutionPayload::Deneb(inner) => {
let f: fn(ExecutionPayloadDeneb<_>, fn(_) -> _) -> _ = $f;
f(inner, BlindedPayload::Deneb)
}
ExecutionPayload::Electra(inner) => {
let f: fn(ExecutionPayloadElectra<_>, fn(_) -> _) -> _ = $f;
f(inner, BlindedPayload::Electra)
}
ExecutionPayload::Fulu(inner) => {
let f: fn(ExecutionPayloadFulu<_>, fn(_) -> _) -> _ = $f;
f(inner, BlindedPayload::Fulu)
}
ExecutionPayload::Gloas(_) => panic!("BlindedPayload::Gloas does not exist!"),
}
};
}
#[macro_export]
macro_rules! map_execution_payload_ref_into_execution_payload_header {
(&$lifetime:tt _, $value:expr, $f:expr) => {
match $value {
ExecutionPayloadRef::Bellatrix(inner) => {
let f: fn(
&$lifetime ExecutionPayloadBellatrix<_>,
fn(_) -> _,
) -> _ = $f;
f(inner, ExecutionPayloadHeader::Bellatrix)
}
ExecutionPayloadRef::Capella(inner) => {
let f: fn(
&$lifetime ExecutionPayloadCapella<_>,
fn(_) -> _,
) -> _ = $f;
f(inner, ExecutionPayloadHeader::Capella)
}
ExecutionPayloadRef::Deneb(inner) => {
let f: fn(
&$lifetime ExecutionPayloadDeneb<_>,
fn(_) -> _,
) -> _ = $f;
f(inner, ExecutionPayloadHeader::Deneb)
}
ExecutionPayloadRef::Electra(inner) => {
let f: fn(
&$lifetime ExecutionPayloadElectra<_>,
fn(_) -> _,
) -> _ = $f;
f(inner, ExecutionPayloadHeader::Electra)
}
ExecutionPayloadRef::Fulu(inner) => {
let f: fn(
&$lifetime ExecutionPayloadFulu<_>,
fn(_) -> _,
) -> _ = $f;
f(inner, ExecutionPayloadHeader::Fulu)
}
ExecutionPayloadRef::Gloas(_) => panic!("ExecutionPayloadHeader::Gloas does not exist!"),
}
}
}

View File

@@ -170,6 +170,7 @@ pub trait EthSpec: 'static + Default + Sync + Send + Clone + Debug + PartialEq +
*/
type PTCSize: Unsigned + Clone + Sync + Send + Debug + PartialEq;
type MaxPayloadAttestations: Unsigned + Clone + Sync + Send + Debug + PartialEq;
type BuilderPendingPaymentsLimit: Unsigned + Clone + Sync + Send + Debug + PartialEq;
type BuilderPendingWithdrawalsLimit: Unsigned + Clone + Sync + Send + Debug + PartialEq;
fn default_spec() -> ChainSpec;
@@ -440,6 +441,7 @@ impl EthSpec for MainnetEthSpec {
type EpochsPerSlashingsVector = U8192;
type HistoricalRootsLimit = U16777216;
type ValidatorRegistryLimit = U1099511627776;
type BuilderPendingPaymentsLimit = U64; // 2 * SLOTS_PER_EPOCH = 2 * 32 = 64
type BuilderPendingWithdrawalsLimit = U1048576;
type MaxProposerSlashings = U16;
type MaxAttesterSlashings = U2;
@@ -525,6 +527,7 @@ impl EthSpec for MinimalEthSpec {
type CellsPerExtBlob = U128;
type NumberOfColumns = U128;
type ProposerLookaheadSlots = U16; // Derived from (MIN_SEED_LOOKAHEAD + 1) * SLOTS_PER_EPOCH
type BuilderPendingPaymentsLimit = U16; // 2 * SLOTS_PER_EPOCH = 2 * 8 = 16
params_from_eth_spec!(MainnetEthSpec {
JustificationBitsLength,
@@ -587,6 +590,7 @@ impl EthSpec for GnosisEthSpec {
type EpochsPerSlashingsVector = U8192;
type HistoricalRootsLimit = U16777216;
type ValidatorRegistryLimit = U1099511627776;
type BuilderPendingPaymentsLimit = U32; // 2 * SLOTS_PER_EPOCH = 2 * 16 = 32
type BuilderPendingWithdrawalsLimit = U1048576;
type MaxProposerSlashings = U16;
type MaxAttesterSlashings = U2;

View File

@@ -39,9 +39,7 @@ pub type Withdrawals<E> = VariableList<Withdrawal, <E as EthSpec>::MaxWithdrawal
),
),
cast_error(ty = "Error", expr = "BeaconStateError::IncorrectStateVariant"),
partial_getter_error(ty = "Error", expr = "BeaconStateError::IncorrectStateVariant"),
map_into(FullPayload, BlindedPayload),
map_ref_into(ExecutionPayloadHeader)
partial_getter_error(ty = "Error", expr = "BeaconStateError::IncorrectStateVariant")
)]
#[cfg_attr(
feature = "arbitrary",
@@ -130,6 +128,7 @@ impl<E: EthSpec> ForkVersionDecode for ExecutionPayload<E> {
impl<E: EthSpec> ExecutionPayload<E> {
#[allow(clippy::arithmetic_side_effects)]
/// Returns the maximum size of an execution payload.
/// TODO(EIP-7732): this seems to only exist for the Bellatrix fork, but Mark's branch has it for all the forks, i.e. max_execution_payload_eip7732_size
pub fn max_execution_payload_bellatrix_size() -> usize {
// Fixed part
ExecutionPayloadBellatrix::<E>::default().as_ssz_bytes().len()

View File

@@ -8,7 +8,7 @@ use tree_hash::TreeHash;
use tree_hash_derive::TreeHash;
#[superstruct(
variants(Bellatrix, Capella, Deneb, Electra, Fulu, Gloas),
variants(Bellatrix, Capella, Deneb, Electra, Fulu),
variant_attributes(
derive(
Default,
@@ -84,12 +84,12 @@ pub struct ExecutionPayloadHeader<E: EthSpec> {
pub block_hash: ExecutionBlockHash,
#[superstruct(getter(copy))]
pub transactions_root: Hash256,
#[superstruct(only(Capella, Deneb, Electra, Fulu, Gloas), partial_getter(copy))]
#[superstruct(only(Capella, Deneb, Electra, Fulu), partial_getter(copy))]
pub withdrawals_root: Hash256,
#[superstruct(only(Deneb, Electra, Fulu, Gloas), partial_getter(copy))]
#[superstruct(only(Deneb, Electra, Fulu), partial_getter(copy))]
#[serde(with = "serde_utils::quoted_u64")]
pub blob_gas_used: u64,
#[superstruct(only(Deneb, Electra, Fulu, Gloas), partial_getter(copy))]
#[superstruct(only(Deneb, Electra, Fulu), partial_getter(copy))]
#[serde(with = "serde_utils::quoted_u64")]
pub excess_blob_gas: u64,
}
@@ -115,14 +115,19 @@ impl<E: EthSpec> ExecutionPayloadHeader<E> {
ExecutionPayloadHeaderElectra::from_ssz_bytes(bytes).map(Self::Electra)
}
ForkName::Fulu => ExecutionPayloadHeaderFulu::from_ssz_bytes(bytes).map(Self::Fulu),
ForkName::Gloas => ExecutionPayloadHeaderGloas::from_ssz_bytes(bytes).map(Self::Gloas),
ForkName::Gloas => Err(ssz::DecodeError::BytesInvalid(format!(
"unsupported fork for ExecutionPayloadHeader: {fork_name}",
))),
}
}
#[allow(clippy::arithmetic_side_effects)]
pub fn ssz_max_var_len_for_fork(fork_name: ForkName) -> usize {
// TODO(newfork): Add a new case here if there are new variable fields
if fork_name.bellatrix_enabled() {
if fork_name.gloas_enabled() {
// TODO(EIP7732): check this
return 0;
} else if fork_name.bellatrix_enabled() {
// Max size of variable length `extra_data` field
E::max_extra_data_bytes() * <u8 as Encode>::ssz_fixed_len()
} else {
@@ -137,7 +142,6 @@ impl<E: EthSpec> ExecutionPayloadHeader<E> {
ExecutionPayloadHeader::Deneb(_) => ForkName::Deneb,
ExecutionPayloadHeader::Electra(_) => ForkName::Electra,
ExecutionPayloadHeader::Fulu(_) => ForkName::Fulu,
ExecutionPayloadHeader::Gloas(_) => ForkName::Gloas,
}
}
}
@@ -245,30 +249,6 @@ impl<E: EthSpec> ExecutionPayloadHeaderElectra<E> {
}
}
impl<E: EthSpec> ExecutionPayloadHeaderFulu<E> {
pub fn upgrade_to_gloas(&self) -> ExecutionPayloadHeaderGloas<E> {
ExecutionPayloadHeaderGloas {
parent_hash: self.parent_hash,
fee_recipient: self.fee_recipient,
state_root: self.state_root,
receipts_root: self.receipts_root,
logs_bloom: self.logs_bloom.clone(),
prev_randao: self.prev_randao,
block_number: self.block_number,
gas_limit: self.gas_limit,
gas_used: self.gas_used,
timestamp: self.timestamp,
extra_data: self.extra_data.clone(),
base_fee_per_gas: self.base_fee_per_gas,
block_hash: self.block_hash,
transactions_root: self.transactions_root,
withdrawals_root: self.withdrawals_root,
blob_gas_used: self.blob_gas_used,
excess_blob_gas: self.excess_blob_gas,
}
}
}
impl<'a, E: EthSpec> From<&'a ExecutionPayloadBellatrix<E>> for ExecutionPayloadHeaderBellatrix<E> {
fn from(payload: &'a ExecutionPayloadBellatrix<E>) -> Self {
Self {
@@ -384,30 +364,6 @@ impl<'a, E: EthSpec> From<&'a ExecutionPayloadFulu<E>> for ExecutionPayloadHeade
}
}
impl<'a, E: EthSpec> From<&'a ExecutionPayloadGloas<E>> for ExecutionPayloadHeaderGloas<E> {
fn from(payload: &'a ExecutionPayloadGloas<E>) -> Self {
Self {
parent_hash: payload.parent_hash,
fee_recipient: payload.fee_recipient,
state_root: payload.state_root,
receipts_root: payload.receipts_root,
logs_bloom: payload.logs_bloom.clone(),
prev_randao: payload.prev_randao,
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,
transactions_root: payload.transactions.tree_hash_root(),
withdrawals_root: payload.withdrawals.tree_hash_root(),
blob_gas_used: payload.blob_gas_used,
excess_blob_gas: payload.excess_blob_gas,
}
}
}
// These impls are required to work around an inelegance in `to_execution_payload_header`.
// They only clone headers so they should be relatively cheap.
impl<'a, E: EthSpec> From<&'a Self> for ExecutionPayloadHeaderBellatrix<E> {
@@ -440,12 +396,6 @@ impl<'a, E: EthSpec> From<&'a Self> for ExecutionPayloadHeaderFulu<E> {
}
}
impl<'a, E: EthSpec> From<&'a Self> for ExecutionPayloadHeaderGloas<E> {
fn from(payload: &'a Self) -> Self {
payload.clone()
}
}
impl<'a, E: EthSpec> From<ExecutionPayloadRef<'a, E>> for ExecutionPayloadHeader<E> {
fn from(payload: ExecutionPayloadRef<'a, E>) -> Self {
map_execution_payload_ref_into_execution_payload_header!(
@@ -507,9 +457,6 @@ impl<E: EthSpec> ExecutionPayloadHeaderRefMut<'_, E> {
ExecutionPayloadHeaderRefMut::Fulu(mut_ref) => {
*mut_ref = header.try_into()?;
}
ExecutionPayloadHeaderRefMut::Gloas(mut_ref) => {
*mut_ref = header.try_into()?;
}
}
Ok(())
}
@@ -537,16 +484,6 @@ impl<E: EthSpec> TryFrom<ExecutionPayloadHeader<E>> for ExecutionPayloadHeaderFu
}
}
impl<E: EthSpec> TryFrom<ExecutionPayloadHeader<E>> for ExecutionPayloadHeaderGloas<E> {
type Error = BeaconStateError;
fn try_from(header: ExecutionPayloadHeader<E>) -> Result<Self, Self::Error> {
match header {
ExecutionPayloadHeader::Gloas(execution_payload_header) => Ok(execution_payload_header),
_ => Err(BeaconStateError::IncorrectStateVariant),
}
}
}
impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for ExecutionPayloadHeader<E> {
fn context_deserialize<D>(deserializer: D, context: ForkName) -> Result<Self, D::Error>
where
@@ -559,12 +496,6 @@ impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for ExecutionPayloadHead
))
};
Ok(match context {
ForkName::Base | ForkName::Altair => {
return Err(serde::de::Error::custom(format!(
"ExecutionPayloadHeader failed to deserialize: unsupported fork '{}'",
context
)));
}
ForkName::Bellatrix => {
Self::Bellatrix(Deserialize::deserialize(deserializer).map_err(convert_err)?)
}
@@ -580,8 +511,13 @@ impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for ExecutionPayloadHead
ForkName::Fulu => {
Self::Fulu(Deserialize::deserialize(deserializer).map_err(convert_err)?)
}
ForkName::Gloas => {
Self::Gloas(Deserialize::deserialize(deserializer).map_err(convert_err)?)
// FIXME(EIP7732): Check this
ForkName::Base | ForkName::Altair | ForkName::Gloas => {
return Err(serde::de::Error::custom(format!(
"ExecutionPayloadHeader failed to deserialize: unsupported fork '{}'",
context
)))
}
})
}

View File

@@ -38,6 +38,7 @@ pub mod deposit_data;
pub mod deposit_message;
pub mod deposit_request;
pub mod deposit_tree_snapshot;
pub mod dumb_macros;
pub mod enr_fork_id;
pub mod eth1_data;
pub mod eth_spec;
@@ -192,7 +193,7 @@ pub use crate::execution_payload_envelope::{
pub use crate::execution_payload_header::{
ExecutionPayloadHeader, ExecutionPayloadHeaderBellatrix, ExecutionPayloadHeaderCapella,
ExecutionPayloadHeaderDeneb, ExecutionPayloadHeaderElectra, ExecutionPayloadHeaderFulu,
ExecutionPayloadHeaderGloas, ExecutionPayloadHeaderRef, ExecutionPayloadHeaderRefMut,
ExecutionPayloadHeaderRef, ExecutionPayloadHeaderRefMut,
};
pub use crate::execution_requests::{ExecutionRequests, RequestType};
pub use crate::fork::Fork;
@@ -208,35 +209,32 @@ pub use crate::indexed_payload_attestation::IndexedPayloadAttestation;
pub use crate::light_client_bootstrap::{
LightClientBootstrap, LightClientBootstrapAltair, LightClientBootstrapCapella,
LightClientBootstrapDeneb, LightClientBootstrapElectra, LightClientBootstrapFulu,
LightClientBootstrapGloas,
};
pub use crate::light_client_finality_update::{
LightClientFinalityUpdate, LightClientFinalityUpdateAltair, LightClientFinalityUpdateCapella,
LightClientFinalityUpdateDeneb, LightClientFinalityUpdateElectra,
LightClientFinalityUpdateFulu, LightClientFinalityUpdateGloas,
LightClientFinalityUpdateFulu,
};
pub use crate::light_client_header::{
LightClientHeader, LightClientHeaderAltair, LightClientHeaderCapella, LightClientHeaderDeneb,
LightClientHeaderElectra, LightClientHeaderFulu, LightClientHeaderGloas,
LightClientHeaderElectra, LightClientHeaderFulu,
};
pub use crate::light_client_optimistic_update::{
LightClientOptimisticUpdate, LightClientOptimisticUpdateAltair,
LightClientOptimisticUpdateCapella, LightClientOptimisticUpdateDeneb,
LightClientOptimisticUpdateElectra, LightClientOptimisticUpdateFulu,
LightClientOptimisticUpdateGloas,
};
pub use crate::light_client_update::{
Error as LightClientUpdateError, LightClientUpdate, LightClientUpdateAltair,
LightClientUpdateCapella, LightClientUpdateDeneb, LightClientUpdateElectra,
LightClientUpdateFulu, LightClientUpdateGloas, MerkleProof,
LightClientUpdateFulu, MerkleProof,
};
pub use crate::participation_flags::ParticipationFlags;
pub use crate::payload::{
AbstractExecPayload, BlindedPayload, BlindedPayloadBellatrix, BlindedPayloadCapella,
BlindedPayloadDeneb, BlindedPayloadElectra, BlindedPayloadFulu, BlindedPayloadGloas,
BlindedPayloadRef, BlockType, ExecPayload, FullPayload, FullPayloadBellatrix,
FullPayloadCapella, FullPayloadDeneb, FullPayloadElectra, FullPayloadFulu, FullPayloadGloas,
FullPayloadRef, OwnedExecPayload,
BlindedPayloadDeneb, BlindedPayloadElectra, BlindedPayloadFulu, BlindedPayloadRef, BlockType,
ExecPayload, FullPayload, FullPayloadBellatrix, FullPayloadCapella, FullPayloadDeneb,
FullPayloadElectra, FullPayloadFulu, FullPayloadRef, OwnedExecPayload,
};
pub use crate::payload_attestation::PayloadAttestation;
pub use crate::payload_attestation_data::PayloadAttestationData;

View File

@@ -1,9 +1,9 @@
use crate::context_deserialize;
use crate::{
BeaconState, ChainSpec, ContextDeserialize, EthSpec, FixedVector, ForkName, Hash256,
LightClientHeader, LightClientHeaderAltair, LightClientHeaderCapella, LightClientHeaderDeneb,
LightClientHeaderElectra, LightClientHeaderFulu, LightClientHeaderGloas,
SignedBlindedBeaconBlock, Slot, SyncCommittee, light_client_update::*, test_utils::TestRandom,
light_client_update::*, test_utils::TestRandom, BeaconState, ChainSpec, ContextDeserialize,
EthSpec, FixedVector, ForkName, Hash256, LightClientHeader, LightClientHeaderAltair,
LightClientHeaderCapella, LightClientHeaderDeneb, LightClientHeaderElectra,
LightClientHeaderFulu, SignedBlindedBeaconBlock, Slot, SyncCommittee,
};
use derivative::Derivative;
use serde::{Deserialize, Deserializer, Serialize};
@@ -17,7 +17,7 @@ use tree_hash_derive::TreeHash;
/// A LightClientBootstrap is the initializer we send over to light_client nodes
/// that are trying to generate their basic storage when booting up.
#[superstruct(
variants(Altair, Capella, Deneb, Electra, Fulu, Gloas),
variants(Altair, Capella, Deneb, Electra, Fulu),
variant_attributes(
derive(
Debug,
@@ -62,8 +62,6 @@ pub struct LightClientBootstrap<E: EthSpec> {
pub header: LightClientHeaderElectra<E>,
#[superstruct(only(Fulu), partial_getter(rename = "header_fulu"))]
pub header: LightClientHeaderFulu<E>,
#[superstruct(only(Gloas), partial_getter(rename = "header_gloas"))]
pub header: LightClientHeaderGloas<E>,
/// The `SyncCommittee` used in the requested period.
pub current_sync_committee: Arc<SyncCommittee<E>>,
/// Merkle proof for sync committee
@@ -73,7 +71,7 @@ pub struct LightClientBootstrap<E: EthSpec> {
)]
pub current_sync_committee_branch: FixedVector<Hash256, CurrentSyncCommitteeProofLen>,
#[superstruct(
only(Electra, Fulu, Gloas),
only(Electra, Fulu),
partial_getter(rename = "current_sync_committee_branch_electra")
)]
pub current_sync_committee_branch: FixedVector<Hash256, CurrentSyncCommitteeProofLenElectra>,
@@ -90,7 +88,6 @@ impl<E: EthSpec> LightClientBootstrap<E> {
Self::Deneb(_) => func(ForkName::Deneb),
Self::Electra(_) => func(ForkName::Electra),
Self::Fulu(_) => func(ForkName::Fulu),
Self::Gloas(_) => func(ForkName::Gloas),
}
}
@@ -110,7 +107,7 @@ impl<E: EthSpec> LightClientBootstrap<E> {
ForkName::Deneb => Self::Deneb(LightClientBootstrapDeneb::from_ssz_bytes(bytes)?),
ForkName::Electra => Self::Electra(LightClientBootstrapElectra::from_ssz_bytes(bytes)?),
ForkName::Fulu => Self::Fulu(LightClientBootstrapFulu::from_ssz_bytes(bytes)?),
ForkName::Gloas => Self::Gloas(LightClientBootstrapGloas::from_ssz_bytes(bytes)?),
ForkName::Gloas => todo!("Gloas light client not implemented"),
ForkName::Base => {
return Err(ssz::DecodeError::BytesInvalid(format!(
"LightClientBootstrap decoding for {fork_name} not implemented"
@@ -132,7 +129,7 @@ impl<E: EthSpec> LightClientBootstrap<E> {
ForkName::Deneb => <LightClientBootstrapDeneb<E> as Encode>::ssz_fixed_len(),
ForkName::Electra => <LightClientBootstrapElectra<E> as Encode>::ssz_fixed_len(),
ForkName::Fulu => <LightClientBootstrapFulu<E> as Encode>::ssz_fixed_len(),
ForkName::Gloas => <LightClientBootstrapGloas<E> as Encode>::ssz_fixed_len(),
ForkName::Gloas => todo!("Gloas light client not implemented"),
};
fixed_len + LightClientHeader::<E>::ssz_max_var_len_for_fork(fork_name)
}
@@ -173,11 +170,7 @@ impl<E: EthSpec> LightClientBootstrap<E> {
current_sync_committee,
current_sync_committee_branch: current_sync_committee_branch.into(),
}),
ForkName::Gloas => Self::Gloas(LightClientBootstrapGloas {
header: LightClientHeaderGloas::block_to_light_client_header(block)?,
current_sync_committee,
current_sync_committee_branch: current_sync_committee_branch.into(),
}),
ForkName::Gloas => todo!("Gloas light client not implemented"),
};
Ok(light_client_bootstrap)
@@ -223,11 +216,7 @@ impl<E: EthSpec> LightClientBootstrap<E> {
current_sync_committee,
current_sync_committee_branch: current_sync_committee_branch.into(),
}),
ForkName::Gloas => Self::Gloas(LightClientBootstrapGloas {
header: LightClientHeaderGloas::block_to_light_client_header(block)?,
current_sync_committee,
current_sync_committee_branch: current_sync_committee_branch.into(),
}),
ForkName::Gloas => todo!("Gloas light client not implemented"),
};
Ok(light_client_bootstrap)
@@ -268,7 +257,11 @@ impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for LightClientBootstrap
Self::Fulu(Deserialize::deserialize(deserializer).map_err(convert_err)?)
}
ForkName::Gloas => {
Self::Gloas(Deserialize::deserialize(deserializer).map_err(convert_err)?)
// TODO(EIP-7732): check if this is correct
return Err(serde::de::Error::custom(format!(
"LightClientBootstrap failed to deserialize: unsupported fork '{}'",
context
)));
}
})
}
@@ -306,10 +299,4 @@ mod tests {
use crate::{LightClientBootstrapFulu, MainnetEthSpec};
ssz_tests!(LightClientBootstrapFulu<MainnetEthSpec>);
}
#[cfg(test)]
mod gloas {
use crate::{LightClientBootstrapGloas, MainnetEthSpec};
ssz_tests!(LightClientBootstrapGloas<MainnetEthSpec>);
}
}

View File

@@ -2,10 +2,9 @@ use super::{EthSpec, FixedVector, Hash256, LightClientHeader, Slot, SyncAggregat
use crate::ChainSpec;
use crate::context_deserialize;
use crate::{
ContextDeserialize, ForkName, LightClientHeaderAltair, LightClientHeaderCapella,
LightClientHeaderDeneb, LightClientHeaderElectra, LightClientHeaderFulu,
LightClientHeaderGloas, SignedBlindedBeaconBlock, light_client_update::*,
test_utils::TestRandom,
light_client_update::*, test_utils::TestRandom, ContextDeserialize, ForkName,
LightClientHeaderAltair, LightClientHeaderCapella, LightClientHeaderDeneb,
LightClientHeaderElectra, LightClientHeaderFulu, SignedBlindedBeaconBlock,
};
use derivative::Derivative;
use serde::{Deserialize, Deserializer, Serialize};
@@ -17,7 +16,7 @@ use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash;
#[superstruct(
variants(Altair, Capella, Deneb, Electra, Fulu, Gloas),
variants(Altair, Capella, Deneb, Electra, Fulu),
variant_attributes(
derive(
Debug,
@@ -62,8 +61,6 @@ pub struct LightClientFinalityUpdate<E: EthSpec> {
pub attested_header: LightClientHeaderElectra<E>,
#[superstruct(only(Fulu), partial_getter(rename = "attested_header_fulu"))]
pub attested_header: LightClientHeaderFulu<E>,
#[superstruct(only(Gloas), partial_getter(rename = "attested_header_gloas"))]
pub attested_header: LightClientHeaderGloas<E>,
/// The last `BeaconBlockHeader` from the last attested finalized block (end of epoch).
#[superstruct(only(Altair), partial_getter(rename = "finalized_header_altair"))]
pub finalized_header: LightClientHeaderAltair<E>,
@@ -75,8 +72,6 @@ pub struct LightClientFinalityUpdate<E: EthSpec> {
pub finalized_header: LightClientHeaderElectra<E>,
#[superstruct(only(Fulu), partial_getter(rename = "finalized_header_fulu"))]
pub finalized_header: LightClientHeaderFulu<E>,
#[superstruct(only(Gloas), partial_getter(rename = "finalized_header_gloas"))]
pub finalized_header: LightClientHeaderGloas<E>,
/// Merkle proof attesting finalized header.
#[superstruct(
only(Altair, Capella, Deneb),
@@ -84,7 +79,7 @@ pub struct LightClientFinalityUpdate<E: EthSpec> {
)]
pub finality_branch: FixedVector<Hash256, FinalizedRootProofLen>,
#[superstruct(
only(Electra, Fulu, Gloas),
only(Electra, Fulu),
partial_getter(rename = "finality_branch_electra")
)]
pub finality_branch: FixedVector<Hash256, FinalizedRootProofLenElectra>,
@@ -165,18 +160,7 @@ impl<E: EthSpec> LightClientFinalityUpdate<E> {
sync_aggregate,
signature_slot,
}),
ForkName::Gloas => Self::Gloas(LightClientFinalityUpdateGloas {
attested_header: LightClientHeaderGloas::block_to_light_client_header(
attested_block,
)?,
finalized_header: LightClientHeaderGloas::block_to_light_client_header(
finalized_block,
)?,
finality_branch: finality_branch.into(),
sync_aggregate,
signature_slot,
}),
ForkName::Gloas => todo!("Gloas light client not implemented"),
ForkName::Base => return Err(Error::AltairForkNotActive),
};
@@ -193,7 +177,6 @@ impl<E: EthSpec> LightClientFinalityUpdate<E> {
Self::Deneb(_) => func(ForkName::Deneb),
Self::Electra(_) => func(ForkName::Electra),
Self::Fulu(_) => func(ForkName::Fulu),
Self::Gloas(_) => func(ForkName::Gloas),
}
}
@@ -231,7 +214,7 @@ impl<E: EthSpec> LightClientFinalityUpdate<E> {
Self::Electra(LightClientFinalityUpdateElectra::from_ssz_bytes(bytes)?)
}
ForkName::Fulu => Self::Fulu(LightClientFinalityUpdateFulu::from_ssz_bytes(bytes)?),
ForkName::Gloas => Self::Gloas(LightClientFinalityUpdateGloas::from_ssz_bytes(bytes)?),
ForkName::Gloas => todo!("Gloas light client not implemented"),
ForkName::Base => {
return Err(ssz::DecodeError::BytesInvalid(format!(
"LightClientFinalityUpdate decoding for {fork_name} not implemented"
@@ -253,7 +236,7 @@ impl<E: EthSpec> LightClientFinalityUpdate<E> {
ForkName::Deneb => <LightClientFinalityUpdateDeneb<E> as Encode>::ssz_fixed_len(),
ForkName::Electra => <LightClientFinalityUpdateElectra<E> as Encode>::ssz_fixed_len(),
ForkName::Fulu => <LightClientFinalityUpdateFulu<E> as Encode>::ssz_fixed_len(),
ForkName::Gloas => <LightClientFinalityUpdateGloas<E> as Encode>::ssz_fixed_len(),
ForkName::Gloas => todo!("Gloas light client not implemented"),
};
// `2 *` because there are two headers in the update
fixed_size + 2 * LightClientHeader::<E>::ssz_max_var_len_for_fork(fork_name)
@@ -307,7 +290,11 @@ impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for LightClientFinalityU
Self::Fulu(Deserialize::deserialize(deserializer).map_err(convert_err)?)
}
ForkName::Gloas => {
Self::Gloas(Deserialize::deserialize(deserializer).map_err(convert_err)?)
// TODO(EIP-7732): check if this is correct
return Err(serde::de::Error::custom(format!(
"LightClientBootstrap failed to deserialize: unsupported fork '{}'",
context
)));
}
})
}
@@ -345,10 +332,4 @@ mod tests {
use crate::{LightClientFinalityUpdateFulu, MainnetEthSpec};
ssz_tests!(LightClientFinalityUpdateFulu<MainnetEthSpec>);
}
#[cfg(test)]
mod gloas {
use crate::{LightClientFinalityUpdateGloas, MainnetEthSpec};
ssz_tests!(LightClientFinalityUpdateGloas<MainnetEthSpec>);
}
}

View File

@@ -1,11 +1,11 @@
use crate::ChainSpec;
use crate::context_deserialize;
use crate::{BeaconBlockBody, light_client_update::*};
use crate::{light_client_update::*, BeaconBlockBody};
use crate::{BeaconBlockHeader, ExecutionPayloadHeader};
use crate::{ContextDeserialize, ForkName};
use crate::{
EthSpec, ExecutionPayloadHeaderCapella, ExecutionPayloadHeaderDeneb,
ExecutionPayloadHeaderElectra, ExecutionPayloadHeaderFulu, ExecutionPayloadHeaderGloas,
ExecutionPayloadHeaderElectra, ExecutionPayloadHeaderFulu,
FixedVector, Hash256, SignedBlindedBeaconBlock, test_utils::TestRandom,
};
use derivative::Derivative;
@@ -18,7 +18,7 @@ use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash;
#[superstruct(
variants(Altair, Capella, Deneb, Electra, Fulu, Gloas),
variants(Altair, Capella, Deneb, Electra, Fulu,),
variant_attributes(
derive(
Debug,
@@ -68,10 +68,8 @@ pub struct LightClientHeader<E: EthSpec> {
pub execution: ExecutionPayloadHeaderElectra<E>,
#[superstruct(only(Fulu), partial_getter(rename = "execution_payload_header_fulu"))]
pub execution: ExecutionPayloadHeaderFulu<E>,
#[superstruct(only(Gloas), partial_getter(rename = "execution_payload_header_gloas"))]
pub execution: ExecutionPayloadHeaderGloas<E>,
#[superstruct(only(Capella, Deneb, Electra, Fulu, Gloas))]
#[superstruct(only(Capella, Deneb, Electra, Fulu))]
pub execution_branch: FixedVector<Hash256, ExecutionPayloadProofLen>,
#[ssz(skip_serializing, skip_deserializing)]
@@ -106,9 +104,7 @@ impl<E: EthSpec> LightClientHeader<E> {
ForkName::Fulu => {
LightClientHeader::Fulu(LightClientHeaderFulu::block_to_light_client_header(block)?)
}
ForkName::Gloas => LightClientHeader::Gloas(
LightClientHeaderGloas::block_to_light_client_header(block)?,
),
ForkName::Gloas => todo!("Gloas light client not implemented"),
};
Ok(header)
}
@@ -130,9 +126,7 @@ impl<E: EthSpec> LightClientHeader<E> {
ForkName::Fulu => {
LightClientHeader::Fulu(LightClientHeaderFulu::from_ssz_bytes(bytes)?)
}
ForkName::Gloas => {
LightClientHeader::Gloas(LightClientHeaderGloas::from_ssz_bytes(bytes)?)
}
ForkName::Gloas => todo!("Gloas light client not implemented"),
ForkName::Base => {
return Err(ssz::DecodeError::BytesInvalid(format!(
"LightClientHeader decoding for {fork_name} not implemented"
@@ -152,7 +146,10 @@ impl<E: EthSpec> LightClientHeader<E> {
}
pub fn ssz_max_var_len_for_fork(fork_name: ForkName) -> usize {
if fork_name.capella_enabled() {
if fork_name.gloas_enabled() {
// TODO(EIP7732): check this
return 0;
} else if fork_name.capella_enabled() {
ExecutionPayloadHeader::<E>::ssz_max_var_len_for_fork(fork_name)
} else {
0
@@ -348,48 +345,6 @@ impl<E: EthSpec> Default for LightClientHeaderFulu<E> {
}
}
impl<E: EthSpec> LightClientHeaderGloas<E> {
pub fn block_to_light_client_header(
block: &SignedBlindedBeaconBlock<E>,
) -> Result<Self, Error> {
let payload = block
.message()
.execution_payload()?
.execution_payload_gloas()?;
let header = ExecutionPayloadHeaderGloas::from(payload);
let beacon_block_body = BeaconBlockBody::from(
block
.message()
.body_gloas()
.map_err(|_| Error::BeaconBlockBodyError)?
.to_owned(),
);
let execution_branch = beacon_block_body
.to_ref()
.block_body_merkle_proof(EXECUTION_PAYLOAD_INDEX)?;
Ok(LightClientHeaderGloas {
beacon: block.message().block_header(),
execution: header,
execution_branch: FixedVector::new(execution_branch)?,
_phantom_data: PhantomData,
})
}
}
impl<E: EthSpec> Default for LightClientHeaderGloas<E> {
fn default() -> Self {
Self {
beacon: BeaconBlockHeader::empty(),
execution: ExecutionPayloadHeaderGloas::default(),
execution_branch: FixedVector::default(),
_phantom_data: PhantomData,
}
}
}
impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for LightClientHeader<E> {
fn context_deserialize<D>(deserializer: D, context: ForkName) -> Result<Self, D::Error>
where
@@ -423,9 +378,7 @@ impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for LightClientHeader<E>
ForkName::Fulu => {
Self::Fulu(Deserialize::deserialize(deserializer).map_err(convert_err)?)
}
ForkName::Gloas => {
Self::Gloas(Deserialize::deserialize(deserializer).map_err(convert_err)?)
}
ForkName::Gloas => todo!("Gloas light client not implemented"),
})
}
}
@@ -462,10 +415,4 @@ mod tests {
use crate::{LightClientHeaderFulu, MainnetEthSpec};
ssz_tests!(LightClientHeaderFulu<MainnetEthSpec>);
}
#[cfg(test)]
mod gloas {
use crate::{LightClientHeaderGloas, MainnetEthSpec};
ssz_tests!(LightClientHeaderGloas<MainnetEthSpec>);
}
}

View File

@@ -2,9 +2,9 @@ use super::{ContextDeserialize, EthSpec, ForkName, LightClientHeader, Slot, Sync
use crate::context_deserialize;
use crate::test_utils::TestRandom;
use crate::{
ChainSpec, LightClientHeaderAltair, LightClientHeaderCapella, LightClientHeaderDeneb,
LightClientHeaderElectra, LightClientHeaderFulu, LightClientHeaderGloas,
SignedBlindedBeaconBlock, light_client_update::*,
light_client_update::*, ChainSpec, LightClientHeaderAltair, LightClientHeaderCapella,
LightClientHeaderDeneb, LightClientHeaderElectra, LightClientHeaderFulu,
SignedBlindedBeaconBlock,
};
use derivative::Derivative;
use serde::{Deserialize, Deserializer, Serialize};
@@ -19,7 +19,7 @@ use tree_hash_derive::TreeHash;
/// A LightClientOptimisticUpdate is the update we send on each slot,
/// it is based off the current unfinalized epoch is verified only against BLS signature.
#[superstruct(
variants(Altair, Capella, Deneb, Electra, Fulu, Gloas),
variants(Altair, Capella, Deneb, Electra, Fulu),
variant_attributes(
derive(
Debug,
@@ -64,8 +64,6 @@ pub struct LightClientOptimisticUpdate<E: EthSpec> {
pub attested_header: LightClientHeaderElectra<E>,
#[superstruct(only(Fulu), partial_getter(rename = "attested_header_fulu"))]
pub attested_header: LightClientHeaderFulu<E>,
#[superstruct(only(Gloas), partial_getter(rename = "attested_header_gloas"))]
pub attested_header: LightClientHeaderGloas<E>,
/// current sync aggregate
pub sync_aggregate: SyncAggregate<E>,
/// Slot of the sync aggregated signature
@@ -121,13 +119,7 @@ impl<E: EthSpec> LightClientOptimisticUpdate<E> {
sync_aggregate,
signature_slot,
}),
ForkName::Gloas => Self::Gloas(LightClientOptimisticUpdateGloas {
attested_header: LightClientHeaderGloas::block_to_light_client_header(
attested_block,
)?,
sync_aggregate,
signature_slot,
}),
ForkName::Gloas => todo!("Gloas light client not implemented"),
ForkName::Base => return Err(Error::AltairForkNotActive),
};
@@ -144,7 +136,6 @@ impl<E: EthSpec> LightClientOptimisticUpdate<E> {
Self::Deneb(_) => func(ForkName::Deneb),
Self::Electra(_) => func(ForkName::Electra),
Self::Fulu(_) => func(ForkName::Fulu),
Self::Gloas(_) => func(ForkName::Gloas),
}
}
@@ -184,9 +175,7 @@ impl<E: EthSpec> LightClientOptimisticUpdate<E> {
Self::Electra(LightClientOptimisticUpdateElectra::from_ssz_bytes(bytes)?)
}
ForkName::Fulu => Self::Fulu(LightClientOptimisticUpdateFulu::from_ssz_bytes(bytes)?),
ForkName::Gloas => {
Self::Gloas(LightClientOptimisticUpdateGloas::from_ssz_bytes(bytes)?)
}
ForkName::Gloas => todo!("Gloas light client not implemented"),
ForkName::Base => {
return Err(ssz::DecodeError::BytesInvalid(format!(
"LightClientOptimisticUpdate decoding for {fork_name} not implemented"
@@ -208,7 +197,7 @@ impl<E: EthSpec> LightClientOptimisticUpdate<E> {
ForkName::Deneb => <LightClientOptimisticUpdateDeneb<E> as Encode>::ssz_fixed_len(),
ForkName::Electra => <LightClientOptimisticUpdateElectra<E> as Encode>::ssz_fixed_len(),
ForkName::Fulu => <LightClientOptimisticUpdateFulu<E> as Encode>::ssz_fixed_len(),
ForkName::Gloas => <LightClientOptimisticUpdateGloas<E> as Encode>::ssz_fixed_len(),
ForkName::Gloas => todo!("Gloas light client not implemented"),
};
fixed_len + LightClientHeader::<E>::ssz_max_var_len_for_fork(fork_name)
}
@@ -261,7 +250,11 @@ impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for LightClientOptimisti
Self::Fulu(Deserialize::deserialize(deserializer).map_err(convert_err)?)
}
ForkName::Gloas => {
Self::Gloas(Deserialize::deserialize(deserializer).map_err(convert_err)?)
// TODO(EIP-7732): check if this is correct
return Err(serde::de::Error::custom(format!(
"LightClientBootstrap failed to deserialize: unsupported fork '{}'",
context
)));
}
})
}
@@ -299,10 +292,4 @@ mod tests {
use crate::{LightClientOptimisticUpdateFulu, MainnetEthSpec};
ssz_tests!(LightClientOptimisticUpdateFulu<MainnetEthSpec>);
}
#[cfg(test)]
mod gloas {
use crate::{LightClientOptimisticUpdateGloas, MainnetEthSpec};
ssz_tests!(LightClientOptimisticUpdateGloas<MainnetEthSpec>);
}
}

View File

@@ -3,9 +3,9 @@ use crate::LightClientHeader;
use crate::context_deserialize;
use crate::light_client_header::LightClientHeaderElectra;
use crate::{
ChainSpec, ContextDeserialize, Epoch, ForkName, LightClientHeaderAltair,
LightClientHeaderCapella, LightClientHeaderDeneb, LightClientHeaderFulu,
LightClientHeaderGloas, SignedBlindedBeaconBlock, beacon_state, test_utils::TestRandom,
beacon_state, test_utils::TestRandom, ChainSpec, ContextDeserialize, Epoch, ForkName,
LightClientHeaderAltair, LightClientHeaderCapella, LightClientHeaderDeneb,
LightClientHeaderFulu, SignedBlindedBeaconBlock,
};
use derivative::Derivative;
use safe_arith::ArithError;
@@ -100,7 +100,7 @@ impl From<milhouse::Error> for Error {
/// or to sync up to the last committee period, we need to have one ready for each ALTAIR period
/// we go over, note: there is no need to keep all of the updates from [ALTAIR_PERIOD, CURRENT_PERIOD].
#[superstruct(
variants(Altair, Capella, Deneb, Electra, Fulu, Gloas),
variants(Altair, Capella, Deneb, Electra, Fulu),
variant_attributes(
derive(
Debug,
@@ -145,8 +145,6 @@ pub struct LightClientUpdate<E: EthSpec> {
pub attested_header: LightClientHeaderElectra<E>,
#[superstruct(only(Fulu), partial_getter(rename = "attested_header_fulu"))]
pub attested_header: LightClientHeaderFulu<E>,
#[superstruct(only(Gloas), partial_getter(rename = "attested_header_gloas"))]
pub attested_header: LightClientHeaderGloas<E>,
/// The `SyncCommittee` used in the next period.
pub next_sync_committee: Arc<SyncCommittee<E>>,
// Merkle proof for next sync committee
@@ -156,7 +154,7 @@ pub struct LightClientUpdate<E: EthSpec> {
)]
pub next_sync_committee_branch: NextSyncCommitteeBranch,
#[superstruct(
only(Electra, Fulu, Gloas),
only(Electra, Fulu),
partial_getter(rename = "next_sync_committee_branch_electra")
)]
pub next_sync_committee_branch: NextSyncCommitteeBranchElectra,
@@ -171,8 +169,6 @@ pub struct LightClientUpdate<E: EthSpec> {
pub finalized_header: LightClientHeaderElectra<E>,
#[superstruct(only(Fulu), partial_getter(rename = "finalized_header_fulu"))]
pub finalized_header: LightClientHeaderFulu<E>,
#[superstruct(only(Gloas), partial_getter(rename = "finalized_header_gloas"))]
pub finalized_header: LightClientHeaderGloas<E>,
/// Merkle proof attesting finalized header.
#[superstruct(
only(Altair, Capella, Deneb),
@@ -180,7 +176,7 @@ pub struct LightClientUpdate<E: EthSpec> {
)]
pub finality_branch: FinalityBranch,
#[superstruct(
only(Electra, Fulu, Gloas),
only(Electra, Fulu),
partial_getter(rename = "finality_branch_electra")
)]
pub finality_branch: FinalityBranchElectra,
@@ -220,9 +216,7 @@ impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for LightClientUpdate<E>
ForkName::Fulu => {
Self::Fulu(Deserialize::deserialize(deserializer).map_err(convert_err)?)
}
ForkName::Gloas => {
Self::Gloas(Deserialize::deserialize(deserializer).map_err(convert_err)?)
}
ForkName::Gloas => todo!("Gloas light client not implemented"),
})
}
}
@@ -364,32 +358,10 @@ impl<E: EthSpec> LightClientUpdate<E> {
signature_slot: block_slot,
})
}
fork_name @ ForkName::Gloas => {
let attested_header =
LightClientHeaderGloas::block_to_light_client_header(attested_block)?;
let finalized_header = if let Some(finalized_block) = finalized_block {
if finalized_block.fork_name_unchecked() == fork_name {
LightClientHeaderGloas::block_to_light_client_header(finalized_block)?
} else {
LightClientHeaderGloas::default()
}
} else {
LightClientHeaderGloas::default()
};
Self::Gloas(LightClientUpdateGloas {
attested_header,
next_sync_committee,
next_sync_committee_branch: next_sync_committee_branch.into(),
finalized_header,
finality_branch: finality_branch.into(),
sync_aggregate: sync_aggregate.clone(),
signature_slot: block_slot,
})
} // To add a new fork, just append the new fork variant on the latest fork. Forks that
// have a distinct execution header will need a new LightClientUpdate variant only
// if you need to test or support lightclient usages
// To add a new fork, just append the new fork variant on the latest fork. Forks that
// have a distinct execution header will need a new LightClientUpdate variant only
// if you need to test or support lightclient usages
ForkName::Gloas => todo!("Gloas light client not implemented"),
};
Ok(light_client_update)
@@ -404,7 +376,8 @@ impl<E: EthSpec> LightClientUpdate<E> {
ForkName::Deneb => Self::Deneb(LightClientUpdateDeneb::from_ssz_bytes(bytes)?),
ForkName::Electra => Self::Electra(LightClientUpdateElectra::from_ssz_bytes(bytes)?),
ForkName::Fulu => Self::Fulu(LightClientUpdateFulu::from_ssz_bytes(bytes)?),
ForkName::Gloas => Self::Gloas(LightClientUpdateGloas::from_ssz_bytes(bytes)?),
ForkName::Gloas => todo!("Gloas light client not implemented"),
ForkName::Base => {
return Err(ssz::DecodeError::BytesInvalid(format!(
"LightClientUpdate decoding for {fork_name} not implemented"
@@ -422,7 +395,6 @@ impl<E: EthSpec> LightClientUpdate<E> {
LightClientUpdate::Deneb(update) => update.attested_header.beacon.slot,
LightClientUpdate::Electra(update) => update.attested_header.beacon.slot,
LightClientUpdate::Fulu(update) => update.attested_header.beacon.slot,
LightClientUpdate::Gloas(update) => update.attested_header.beacon.slot,
}
}
@@ -433,7 +405,6 @@ impl<E: EthSpec> LightClientUpdate<E> {
LightClientUpdate::Deneb(update) => update.finalized_header.beacon.slot,
LightClientUpdate::Electra(update) => update.finalized_header.beacon.slot,
LightClientUpdate::Fulu(update) => update.finalized_header.beacon.slot,
LightClientUpdate::Gloas(update) => update.finalized_header.beacon.slot,
}
}
@@ -554,7 +525,7 @@ impl<E: EthSpec> LightClientUpdate<E> {
ForkName::Deneb => <LightClientUpdateDeneb<E> as Encode>::ssz_fixed_len(),
ForkName::Electra => <LightClientUpdateElectra<E> as Encode>::ssz_fixed_len(),
ForkName::Fulu => <LightClientUpdateFulu<E> as Encode>::ssz_fixed_len(),
ForkName::Gloas => <LightClientUpdateGloas<E> as Encode>::ssz_fixed_len(),
ForkName::Gloas => todo!("Gloas light client not implemented"),
};
fixed_len + 2 * LightClientHeader::<E>::ssz_max_var_len_for_fork(fork_name)
}
@@ -569,7 +540,6 @@ impl<E: EthSpec> LightClientUpdate<E> {
Self::Deneb(_) => func(ForkName::Deneb),
Self::Electra(_) => func(ForkName::Electra),
Self::Fulu(_) => func(ForkName::Fulu),
Self::Gloas(_) => func(ForkName::Gloas),
}
}
}
@@ -632,13 +602,6 @@ mod tests {
ssz_tests!(LightClientUpdateFulu<MainnetEthSpec>);
}
#[cfg(test)]
mod gloas {
use super::*;
use crate::MainnetEthSpec;
ssz_tests!(LightClientUpdateGloas<MainnetEthSpec>);
}
#[test]
fn finalized_root_params() {
assert!(2usize.pow(FINALIZED_ROOT_PROOF_LEN as u32) <= FINALIZED_ROOT_INDEX);

View File

@@ -105,7 +105,6 @@ pub trait AbstractExecPayload<E: EthSpec>:
+ TryInto<Self::Deneb>
+ TryInto<Self::Electra>
+ TryInto<Self::Fulu>
+ TryInto<Self::Gloas>
+ Sync
{
type Ref<'a>: ExecPayload<E>
@@ -114,8 +113,7 @@ pub trait AbstractExecPayload<E: EthSpec>:
+ From<&'a Self::Capella>
+ From<&'a Self::Deneb>
+ From<&'a Self::Electra>
+ From<&'a Self::Fulu>
+ From<&'a Self::Gloas>;
+ From<&'a Self::Fulu>;
type Bellatrix: OwnedExecPayload<E>
+ Into<Self>
@@ -142,15 +140,10 @@ pub trait AbstractExecPayload<E: EthSpec>:
+ for<'a> From<Cow<'a, ExecutionPayloadFulu<E>>>
+ TryFrom<ExecutionPayloadHeaderFulu<E>>
+ Sync;
type Gloas: OwnedExecPayload<E>
+ Into<Self>
+ for<'a> From<Cow<'a, ExecutionPayloadGloas<E>>>
+ TryFrom<ExecutionPayloadHeaderGloas<E>>
+ Sync;
}
#[superstruct(
variants(Bellatrix, Capella, Deneb, Electra, Fulu, Gloas),
variants(Bellatrix, Capella, Deneb, Electra, Fulu),
variant_attributes(
derive(
Debug,
@@ -205,8 +198,6 @@ pub struct FullPayload<E: EthSpec> {
pub execution_payload: ExecutionPayloadElectra<E>,
#[superstruct(only(Fulu), partial_getter(rename = "execution_payload_fulu"))]
pub execution_payload: ExecutionPayloadFulu<E>,
#[superstruct(only(Gloas), partial_getter(rename = "execution_payload_gloas"))]
pub execution_payload: ExecutionPayloadGloas<E>,
}
impl<E: EthSpec> From<FullPayload<E>> for ExecutionPayload<E> {
@@ -314,11 +305,18 @@ impl<E: EthSpec> ExecPayload<E> for FullPayload<E> {
fn withdrawals_root(&self) -> Result<Hash256, Error> {
match self {
FullPayload::Bellatrix(_) => Err(Error::IncorrectStateVariant),
FullPayload::Capella(inner) => Ok(inner.execution_payload.withdrawals.tree_hash_root()),
FullPayload::Deneb(inner) => Ok(inner.execution_payload.withdrawals.tree_hash_root()),
FullPayload::Electra(inner) => Ok(inner.execution_payload.withdrawals.tree_hash_root()),
FullPayload::Fulu(inner) => Ok(inner.execution_payload.withdrawals.tree_hash_root()),
FullPayload::Gloas(inner) => Ok(inner.execution_payload.withdrawals.tree_hash_root()),
FullPayload::Capella(ref inner) => {
Ok(inner.execution_payload.withdrawals.tree_hash_root())
}
FullPayload::Deneb(ref inner) => {
Ok(inner.execution_payload.withdrawals.tree_hash_root())
}
FullPayload::Electra(ref inner) => {
Ok(inner.execution_payload.withdrawals.tree_hash_root())
}
FullPayload::Fulu(ref inner) => {
Ok(inner.execution_payload.withdrawals.tree_hash_root())
}
}
}
@@ -327,10 +325,9 @@ impl<E: EthSpec> ExecPayload<E> for FullPayload<E> {
FullPayload::Bellatrix(_) | FullPayload::Capella(_) => {
Err(Error::IncorrectStateVariant)
}
FullPayload::Deneb(inner) => Ok(inner.execution_payload.blob_gas_used),
FullPayload::Electra(inner) => Ok(inner.execution_payload.blob_gas_used),
FullPayload::Fulu(inner) => Ok(inner.execution_payload.blob_gas_used),
FullPayload::Gloas(inner) => Ok(inner.execution_payload.blob_gas_used),
FullPayload::Deneb(ref inner) => Ok(inner.execution_payload.blob_gas_used),
FullPayload::Electra(ref inner) => Ok(inner.execution_payload.blob_gas_used),
FullPayload::Fulu(ref inner) => Ok(inner.execution_payload.blob_gas_used),
}
}
@@ -362,7 +359,7 @@ impl<E: EthSpec> FullPayload<E> {
ForkName::Deneb => Ok(FullPayloadDeneb::default().into()),
ForkName::Electra => Ok(FullPayloadElectra::default().into()),
ForkName::Fulu => Ok(FullPayloadFulu::default().into()),
ForkName::Gloas => Ok(FullPayloadGloas::default().into()),
ForkName::Gloas => Err(Error::IncorrectStateVariant),
}
}
}
@@ -463,9 +460,6 @@ impl<E: EthSpec> ExecPayload<E> for FullPayloadRef<'_, E> {
Ok(inner.execution_payload.withdrawals.tree_hash_root())
}
FullPayloadRef::Fulu(inner) => Ok(inner.execution_payload.withdrawals.tree_hash_root()),
FullPayloadRef::Gloas(inner) => {
Ok(inner.execution_payload.withdrawals.tree_hash_root())
}
}
}
@@ -477,7 +471,6 @@ impl<E: EthSpec> ExecPayload<E> for FullPayloadRef<'_, E> {
FullPayloadRef::Deneb(inner) => Ok(inner.execution_payload.blob_gas_used),
FullPayloadRef::Electra(inner) => Ok(inner.execution_payload.blob_gas_used),
FullPayloadRef::Fulu(inner) => Ok(inner.execution_payload.blob_gas_used),
FullPayloadRef::Gloas(inner) => Ok(inner.execution_payload.blob_gas_used),
}
}
@@ -501,7 +494,6 @@ impl<E: EthSpec> AbstractExecPayload<E> for FullPayload<E> {
type Deneb = FullPayloadDeneb<E>;
type Electra = FullPayloadElectra<E>;
type Fulu = FullPayloadFulu<E>;
type Gloas = FullPayloadGloas<E>;
}
impl<E: EthSpec> From<ExecutionPayload<E>> for FullPayload<E> {
@@ -520,7 +512,7 @@ impl<E: EthSpec> TryFrom<ExecutionPayloadHeader<E>> for FullPayload<E> {
}
#[superstruct(
variants(Bellatrix, Capella, Deneb, Electra, Fulu, Gloas),
variants(Bellatrix, Capella, Deneb, Electra, Fulu),
variant_attributes(
derive(
Debug,
@@ -574,8 +566,6 @@ pub struct BlindedPayload<E: EthSpec> {
pub execution_payload_header: ExecutionPayloadHeaderElectra<E>,
#[superstruct(only(Fulu), partial_getter(rename = "execution_payload_fulu"))]
pub execution_payload_header: ExecutionPayloadHeaderFulu<E>,
#[superstruct(only(Gloas), partial_getter(rename = "execution_payload_gloas"))]
pub execution_payload_header: ExecutionPayloadHeaderGloas<E>,
}
impl<'a, E: EthSpec> From<BlindedPayloadRef<'a, E>> for BlindedPayload<E> {
@@ -661,11 +651,14 @@ impl<E: EthSpec> ExecPayload<E> for BlindedPayload<E> {
fn withdrawals_root(&self) -> Result<Hash256, Error> {
match self {
BlindedPayload::Bellatrix(_) => Err(Error::IncorrectStateVariant),
BlindedPayload::Capella(inner) => Ok(inner.execution_payload_header.withdrawals_root),
BlindedPayload::Deneb(inner) => Ok(inner.execution_payload_header.withdrawals_root),
BlindedPayload::Electra(inner) => Ok(inner.execution_payload_header.withdrawals_root),
BlindedPayload::Fulu(inner) => Ok(inner.execution_payload_header.withdrawals_root),
BlindedPayload::Gloas(inner) => Ok(inner.execution_payload_header.withdrawals_root),
BlindedPayload::Capella(ref inner) => {
Ok(inner.execution_payload_header.withdrawals_root)
}
BlindedPayload::Deneb(ref inner) => Ok(inner.execution_payload_header.withdrawals_root),
BlindedPayload::Electra(ref inner) => {
Ok(inner.execution_payload_header.withdrawals_root)
}
BlindedPayload::Fulu(ref inner) => Ok(inner.execution_payload_header.withdrawals_root),
}
}
@@ -674,10 +667,9 @@ impl<E: EthSpec> ExecPayload<E> for BlindedPayload<E> {
BlindedPayload::Bellatrix(_) | BlindedPayload::Capella(_) => {
Err(Error::IncorrectStateVariant)
}
BlindedPayload::Deneb(inner) => Ok(inner.execution_payload_header.blob_gas_used),
BlindedPayload::Electra(inner) => Ok(inner.execution_payload_header.blob_gas_used),
BlindedPayload::Fulu(inner) => Ok(inner.execution_payload_header.blob_gas_used),
BlindedPayload::Gloas(inner) => Ok(inner.execution_payload_header.blob_gas_used),
BlindedPayload::Deneb(ref inner) => Ok(inner.execution_payload_header.blob_gas_used),
BlindedPayload::Electra(ref inner) => Ok(inner.execution_payload_header.blob_gas_used),
BlindedPayload::Fulu(ref inner) => Ok(inner.execution_payload_header.blob_gas_used),
}
}
@@ -777,7 +769,6 @@ impl<'b, E: EthSpec> ExecPayload<E> for BlindedPayloadRef<'b, E> {
Ok(inner.execution_payload_header.withdrawals_root)
}
BlindedPayloadRef::Fulu(inner) => Ok(inner.execution_payload_header.withdrawals_root),
BlindedPayloadRef::Gloas(inner) => Ok(inner.execution_payload_header.withdrawals_root),
}
}
@@ -789,7 +780,6 @@ impl<'b, E: EthSpec> ExecPayload<E> for BlindedPayloadRef<'b, E> {
BlindedPayloadRef::Deneb(inner) => Ok(inner.execution_payload_header.blob_gas_used),
BlindedPayloadRef::Electra(inner) => Ok(inner.execution_payload_header.blob_gas_used),
BlindedPayloadRef::Fulu(inner) => Ok(inner.execution_payload_header.blob_gas_used),
BlindedPayloadRef::Gloas(inner) => Ok(inner.execution_payload_header.blob_gas_used),
}
}
@@ -1100,13 +1090,6 @@ impl_exec_payload_for_fork!(
ExecutionPayloadFulu,
Fulu
);
impl_exec_payload_for_fork!(
BlindedPayloadGloas,
FullPayloadGloas,
ExecutionPayloadHeaderGloas,
ExecutionPayloadGloas,
Gloas
);
impl<E: EthSpec> AbstractExecPayload<E> for BlindedPayload<E> {
type Ref<'a> = BlindedPayloadRef<'a, E>;
@@ -1115,7 +1098,6 @@ impl<E: EthSpec> AbstractExecPayload<E> for BlindedPayload<E> {
type Deneb = BlindedPayloadDeneb<E>;
type Electra = BlindedPayloadElectra<E>;
type Fulu = BlindedPayloadFulu<E>;
type Gloas = BlindedPayloadGloas<E>;
}
impl<E: EthSpec> From<ExecutionPayload<E>> for BlindedPayload<E> {
@@ -1157,11 +1139,6 @@ impl<E: EthSpec> From<ExecutionPayloadHeader<E>> for BlindedPayload<E> {
execution_payload_header,
})
}
ExecutionPayloadHeader::Gloas(execution_payload_header) => {
Self::Gloas(BlindedPayloadGloas {
execution_payload_header,
})
}
}
}
}
@@ -1184,9 +1161,6 @@ impl<E: EthSpec> From<BlindedPayload<E>> for ExecutionPayloadHeader<E> {
BlindedPayload::Fulu(blinded_payload) => {
ExecutionPayloadHeader::Fulu(blinded_payload.execution_payload_header)
}
BlindedPayload::Gloas(blinded_payload) => {
ExecutionPayloadHeader::Gloas(blinded_payload.execution_payload_header)
}
}
}
}

View File

@@ -6,7 +6,6 @@ use merkle_proof::MerkleTree;
use serde::{Deserialize, Deserializer, Serialize};
use ssz_derive::{Decode, Encode};
use std::fmt;
use std::marker::PhantomData;
use superstruct::superstruct;
use test_random_derive::TestRandom;
use tree_hash::TreeHash;
@@ -649,60 +648,14 @@ impl<E: EthSpec> SignedBeaconBlockFulu<E, BlindedPayload<E>> {
}
}
/// Gloas doesn't support BlindedPayload, but we keep this impl for compatibility purposes of the SignedBeaconBlock type
impl<E: EthSpec> SignedBeaconBlockGloas<E, BlindedPayload<E>> {
pub fn into_full_block(
self,
_execution_payload: ExecutionPayloadGloas<E>,
) -> SignedBeaconBlockGloas<E, FullPayload<E>> {
let SignedBeaconBlockGloas {
message:
BeaconBlockGloas {
slot,
proposer_index,
parent_root,
state_root,
body:
BeaconBlockBodyGloas {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
bls_to_execution_changes,
signed_execution_payload_header,
payload_attestations,
..
},
},
signature,
} = self;
// We can convert gloas blocks without payloads into blocks "with" payloads.
impl<E: EthSpec> From<SignedBeaconBlockGloas<E, BlindedPayload<E>>>
for SignedBeaconBlockGloas<E, FullPayload<E>>
{
fn from(signed_block: SignedBeaconBlockGloas<E, BlindedPayload<E>>) -> Self {
let SignedBeaconBlockGloas { message, signature } = signed_block;
SignedBeaconBlockGloas {
message: BeaconBlockGloas {
slot,
proposer_index,
parent_root,
state_root,
body: BeaconBlockBodyGloas {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
bls_to_execution_changes,
signed_execution_payload_header,
payload_attestations,
_phantom: PhantomData,
},
},
message: message.into(),
signature,
}
}
@@ -731,9 +684,7 @@ impl<E: EthSpec> SignedBeaconBlock<E, BlindedPayload<E>> {
(SignedBeaconBlock::Fulu(block), Some(ExecutionPayload::Fulu(payload))) => {
SignedBeaconBlock::Fulu(block.into_full_block(payload))
}
(SignedBeaconBlock::Gloas(block), Some(ExecutionPayload::Gloas(payload))) => {
SignedBeaconBlock::Gloas(block.into_full_block(payload))
}
(SignedBeaconBlock::Gloas(block), _) => SignedBeaconBlock::Gloas(block.into()),
// avoid wildcard matching forks so that compiler will
// direct us here when a new fork has been added
(SignedBeaconBlock::Bellatrix(_), _) => return None,
@@ -741,7 +692,7 @@ impl<E: EthSpec> SignedBeaconBlock<E, BlindedPayload<E>> {
(SignedBeaconBlock::Deneb(_), _) => return None,
(SignedBeaconBlock::Electra(_), _) => return None,
(SignedBeaconBlock::Fulu(_), _) => return None,
(SignedBeaconBlock::Gloas(_), _) => return None,
// TODO(EIP-7732) Determine if need a match arm for gloas here
};
Some(full_block)
}

View File

@@ -307,6 +307,7 @@ impl<E: EthSpec> Operation<E> for BeaconBlockBody<E, FullPayload<E>> {
ForkName::Deneb => BeaconBlockBody::Deneb(<_>::from_ssz_bytes(bytes)?),
ForkName::Electra => BeaconBlockBody::Electra(<_>::from_ssz_bytes(bytes)?),
ForkName::Fulu => BeaconBlockBody::Fulu(<_>::from_ssz_bytes(bytes)?),
// TODO(EIP-7732): See if we need to handle Gloas here
_ => panic!(),
})
})
@@ -366,6 +367,7 @@ impl<E: EthSpec> Operation<E> for BeaconBlockBody<E, BlindedPayload<E>> {
let inner = <BeaconBlockBodyFulu<E, FullPayload<E>>>::from_ssz_bytes(bytes)?;
BeaconBlockBody::Fulu(inner.clone_as_blinded())
}
// TODO(EIP-7732): See if we need to handle Gloas here
_ => panic!(),
})
})
@@ -417,7 +419,15 @@ impl<E: EthSpec> Operation<E> for WithdrawalsPayload<E> {
spec: &ChainSpec,
_: &Operations<E, Self>,
) -> Result<(), BlockProcessingError> {
process_withdrawals::<_, FullPayload<_>>(state, self.payload.to_ref(), spec)
if state.fork_name_unchecked().gloas_enabled() {
process_withdrawals::gloas::process_withdrawals(state, spec)
} else {
process_withdrawals::capella::process_withdrawals::<_, FullPayload<_>>(
state,
self.payload.to_ref(),
spec,
)
}
}
}