Gloas spec v1.7.0-alpha.5 and beacon_chain tests (#8998)

Fix database pruning post-Gloas


  - Fix DB pruning logic (and state summaries DAG)
- Get the `beacon_chain` tests running with `FORK_NAME=gloas` 🎉


Co-Authored-By: Michael Sproul <michael@sigmaprime.io>

Co-Authored-By: Jimmy Chen <jchen.tc@gmail.com>

Co-Authored-By: Eitan Seri- Levi <eserilev@gmail.com>

Co-Authored-By: dapplion <35266934+dapplion@users.noreply.github.com>

Co-Authored-By: Eitan Seri-Levi <eserilev@ucsc.edu>
This commit is contained in:
Michael Sproul
2026-04-21 16:29:15 +10:00
committed by GitHub
parent c028bac28d
commit cf3d5e285e
82 changed files with 1513 additions and 1391 deletions

View File

@@ -716,6 +716,7 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> EmptyBlock for BeaconBlockGloa
voluntary_exits: VariableList::empty(),
sync_aggregate: SyncAggregate::empty(),
bls_to_execution_changes: VariableList::empty(),
parent_execution_requests: ExecutionRequests::default(),
signed_execution_payload_bid: SignedExecutionPayloadBid::empty(),
payload_attestations: VariableList::empty(),
_phantom: PhantomData,

View File

@@ -170,6 +170,8 @@ pub struct BeaconBlockBody<E: EthSpec, Payload: AbstractExecPayload<E> = FullPay
pub signed_execution_payload_bid: SignedExecutionPayloadBid<E>,
#[superstruct(only(Gloas))]
pub payload_attestations: VariableList<PayloadAttestation<E>, E::MaxPayloadAttestations>,
#[superstruct(only(Gloas))]
pub parent_execution_requests: ExecutionRequests<E>,
#[superstruct(only(Base, Altair, Gloas))]
#[metastruct(exclude_from(fields))]
#[ssz(skip_serializing, skip_deserializing)]
@@ -564,6 +566,7 @@ impl<E: EthSpec> From<BeaconBlockBodyGloas<E, BlindedPayload<E>>>
voluntary_exits,
sync_aggregate,
bls_to_execution_changes,
parent_execution_requests,
signed_execution_payload_bid,
payload_attestations,
_phantom,
@@ -580,6 +583,7 @@ impl<E: EthSpec> From<BeaconBlockBodyGloas<E, BlindedPayload<E>>>
voluntary_exits,
sync_aggregate,
bls_to_execution_changes,
parent_execution_requests,
signed_execution_payload_bid,
payload_attestations,
_phantom: PhantomData,
@@ -898,6 +902,7 @@ impl<E: EthSpec> From<BeaconBlockBodyGloas<E, FullPayload<E>>>
voluntary_exits,
sync_aggregate,
bls_to_execution_changes,
parent_execution_requests,
signed_execution_payload_bid,
payload_attestations,
_phantom,
@@ -915,6 +920,7 @@ impl<E: EthSpec> From<BeaconBlockBodyGloas<E, FullPayload<E>>>
voluntary_exits,
sync_aggregate,
bls_to_execution_changes,
parent_execution_requests,
signed_execution_payload_bid,
payload_attestations,
_phantom: PhantomData,

View File

@@ -394,13 +394,15 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> SignedBeaconBlock<E, Payload>
/// `block_hash` from the parent beacon block's bid. If the parent beacon state is available
/// this can alternatively be fetched from `state.latest_payload_bid`.
///
/// This function returns `false` for all blocks prior to Gloas.
/// This function returns `false` for all blocks prior to Gloas and for the zero
/// `parent_block_hash`.
pub fn is_parent_block_full(&self, parent_block_hash: ExecutionBlockHash) -> bool {
let Ok(signed_payload_bid) = self.message().body().signed_execution_payload_bid() else {
// Prior to Gloas.
return false;
};
signed_payload_bid.message.parent_block_hash == parent_block_hash
parent_block_hash != ExecutionBlockHash::zero()
&& signed_payload_bid.message.parent_block_hash == parent_block_hash
}
}

View File

@@ -10,7 +10,7 @@ use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash;
use crate::{
core::{Address, EthSpec, ExecutionBlockHash, Hash256},
core::{Address, EthSpec, ExecutionBlockHash, Hash256, Slot},
fork::{ForkName, ForkVersionDecode},
state::BeaconStateError,
test_utils::TestRandom,
@@ -109,6 +109,12 @@ pub struct ExecutionPayload<E: EthSpec> {
#[superstruct(only(Deneb, Electra, Fulu, Gloas), partial_getter(copy))]
#[serde(with = "serde_utils::quoted_u64")]
pub excess_blob_gas: u64,
/// EIP-7928: Block access list
#[superstruct(only(Gloas))]
#[serde(with = "ssz_types::serde_utils::hex_var_list")]
pub block_access_list: VariableList<u8, E::MaxBytesPerTransaction>,
#[superstruct(only(Gloas), partial_getter(copy))]
pub slot_number: Slot,
}
impl<'a, E: EthSpec> ExecutionPayloadRef<'a, E> {

View File

@@ -37,6 +37,7 @@ pub struct ExecutionPayloadBid<E: EthSpec> {
#[serde(with = "serde_utils::quoted_u64")]
pub execution_payment: u64,
pub blob_kzg_commitments: KzgCommitments<E>,
pub execution_requests_root: Hash256,
}
impl<E: EthSpec> SignedRoot for ExecutionPayloadBid<E> {}

View File

@@ -20,8 +20,6 @@ pub struct ExecutionPayloadEnvelope<E: EthSpec> {
#[serde(with = "serde_utils::quoted_u64")]
pub builder_index: u64,
pub beacon_block_root: Hash256,
pub slot: Slot,
pub state_root: Hash256,
}
impl<E: EthSpec> ExecutionPayloadEnvelope<E> {
@@ -32,8 +30,6 @@ impl<E: EthSpec> ExecutionPayloadEnvelope<E> {
execution_requests: ExecutionRequests::default(),
builder_index: 0,
beacon_block_root: Hash256::zero(),
slot: Slot::new(0),
state_root: Hash256::zero(),
}
}
@@ -60,6 +56,10 @@ impl<E: EthSpec> ExecutionPayloadEnvelope<E> {
+ (E::max_consolidation_requests_per_payload()
* <crate::ConsolidationRequest as SszEncode>::ssz_fixed_len())
}
pub fn slot(&self) -> Slot {
self.payload.slot_number
}
}
impl<E: EthSpec> SignedRoot for ExecutionPayloadEnvelope<E> {}

View File

@@ -12,7 +12,6 @@ mod payload;
mod signed_bls_to_execution_change;
mod signed_execution_payload_bid;
mod signed_execution_payload_envelope;
mod state_payload_status;
pub use bls_to_execution_change::BlsToExecutionChange;
pub use eth1_data::Eth1Data;
@@ -42,4 +41,3 @@ pub use payload::{
pub use signed_bls_to_execution_change::SignedBlsToExecutionChange;
pub use signed_execution_payload_bid::SignedExecutionPayloadBid;
pub use signed_execution_payload_envelope::SignedExecutionPayloadEnvelope;
pub use state_payload_status::StatePayloadStatus;

View File

@@ -42,7 +42,7 @@ impl<E: EthSpec> SignedExecutionPayloadEnvelope<E> {
}
pub fn slot(&self) -> Slot {
self.message.slot
self.message.slot()
}
pub fn epoch(&self) -> Epoch {

View File

@@ -1,18 +0,0 @@
use serde::{Deserialize, Serialize};
/// Payload status as it applies to a `BeaconState` post-Gloas.
///
/// A state can either be a post-state for a block (in which case we call it `Pending`) or a
/// payload envelope (`Full`). When handling states it is often necessary to know which of these
/// two variants is required.
///
/// Note that states at skipped slots could be either `Pending` or `Full`, depending on whether
/// the payload for the most-recently applied block was also applied.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum StatePayloadStatus {
/// For states produced by `process_block` executed on a `BeaconBlock`.
Pending,
/// For states produced by `process_execution_payload` on a `ExecutionPayloadEnvelope`.
Full,
}

View File

@@ -37,7 +37,7 @@ use crate::{
execution::{
Eth1Data, ExecutionPayloadHeaderBellatrix, ExecutionPayloadHeaderCapella,
ExecutionPayloadHeaderDeneb, ExecutionPayloadHeaderElectra, ExecutionPayloadHeaderFulu,
ExecutionPayloadHeaderRef, ExecutionPayloadHeaderRefMut, StatePayloadStatus,
ExecutionPayloadHeaderRef, ExecutionPayloadHeaderRefMut,
},
fork::{Fork, ForkName, ForkVersionDecode, InconsistentFork, map_fork_name},
light_client::consts::{
@@ -571,9 +571,10 @@ where
)]
#[metastruct(exclude_from(tree_lists))]
pub latest_execution_payload_header: ExecutionPayloadHeaderFulu<E>,
#[test_random(default)]
#[superstruct(only(Gloas))]
#[metastruct(exclude_from(tree_lists))]
pub latest_execution_payload_bid: ExecutionPayloadBid<E>,
pub latest_block_hash: ExecutionBlockHash,
#[superstruct(only(Capella, Deneb, Electra, Fulu, Gloas), partial_getter(copy))]
#[serde(with = "serde_utils::quoted_u64")]
#[metastruct(exclude_from(tree_lists))]
@@ -657,10 +658,9 @@ where
pub builder_pending_withdrawals:
List<BuilderPendingWithdrawal, E::BuilderPendingWithdrawalsLimit>,
#[test_random(default)]
#[superstruct(only(Gloas))]
#[metastruct(exclude_from(tree_lists))]
pub latest_block_hash: ExecutionBlockHash,
pub latest_execution_payload_bid: ExecutionPayloadBid<E>,
#[compare_fields(as_iter)]
#[test_random(default)]
@@ -1273,24 +1273,6 @@ impl<E: EthSpec> BeaconState<E> {
}
}
/// Determine the payload status of this state.
///
/// Prior to Gloas this is always `Pending`.
///
/// Post-Gloas, the definition of the `StatePayloadStatus` is:
///
/// - `Full` if this state is the result of envelope processing.
/// - `Pending` if this state is the result of block processing.
pub fn payload_status(&self) -> StatePayloadStatus {
if !self.fork_name_unchecked().gloas_enabled() {
StatePayloadStatus::Pending
} else if self.is_parent_block_full() {
StatePayloadStatus::Full
} else {
StatePayloadStatus::Pending
}
}
/// Return `true` if the validator who produced `slot_signature` is eligible to aggregate.
///
/// Spec v0.12.1
@@ -2507,22 +2489,6 @@ impl<E: EthSpec> BeaconState<E> {
}
}
/// Return true if the parent block was full (both beacon block and execution payload were present).
pub fn is_parent_block_full(&self) -> bool {
match self {
BeaconState::Base(_) | BeaconState::Altair(_) => false,
// TODO(EIP-7732): check the implications of this when we get to forkchoice modifications
BeaconState::Bellatrix(_)
| BeaconState::Capella(_)
| BeaconState::Deneb(_)
| BeaconState::Electra(_)
| BeaconState::Fulu(_) => true,
BeaconState::Gloas(state) => {
state.latest_execution_payload_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.