Merge branch 'glamsterdam-devnet-2' of https://github.com/sigp/lighthouse into glamsterdam-devnet-2

This commit is contained in:
Eitan Seri-Levi
2026-05-01 12:04:23 +02:00
2 changed files with 36 additions and 8 deletions

View File

@@ -47,8 +47,8 @@ use tracing::{debug, error, info, warn};
use tree_hash::TreeHash; use tree_hash::TreeHash;
use types::data::CustodyIndex; use types::data::CustodyIndex;
use types::{ use types::{
BeaconState, BlobSidecarList, ChainSpec, ColumnIndex, DataColumnSidecarList, Epoch, EthSpec, BeaconBlock, BeaconState, BlobSidecarList, ChainSpec, ColumnIndex, DataColumnSidecarList,
Hash256, SignedBeaconBlock, Slot, Epoch, EthSpec, Hash256, SignedBeaconBlock, Slot,
}; };
/// An empty struct used to "witness" all the `BeaconChainTypes` traits. It has no user-facing /// An empty struct used to "witness" all the `BeaconChainTypes` traits. It has no user-facing
@@ -1187,9 +1187,21 @@ fn make_genesis_block<E: EthSpec>(
genesis_state: &mut BeaconState<E>, genesis_state: &mut BeaconState<E>,
spec: &ChainSpec, spec: &ChainSpec,
) -> Result<SignedBeaconBlock<E>, String> { ) -> Result<SignedBeaconBlock<E>, String> {
// For Gloas, genesis_block() populates the bid in the block body. However, if
// the genesis state was produced by an external tool (e.g. ethereum-genesis-generator),
// its latest_block_header.body_root may correspond to an empty block. In that case,
// use an empty block so the stored block root matches what fork choice derives from
// the state's latest_block_header.
let mut block = genesis_block(genesis_state, spec) let mut block = genesis_block(genesis_state, spec)
.map_err(|e| format!("Error building genesis block: {:?}", e))?; .map_err(|e| format!("Error building genesis block: {:?}", e))?;
let state_body_root = genesis_state.latest_block_header().body_root;
if state_body_root != block.body_root()
&& state_body_root == BeaconBlock::<E>::empty(spec).body_root()
{
block = BeaconBlock::empty(spec);
}
*block.state_root_mut() = genesis_state *block.state_root_mut() = genesis_state
.update_tree_hash_cache() .update_tree_hash_cache()
.map_err(|e| format!("Error hashing genesis state: {:?}", e))?; .map_err(|e| format!("Error hashing genesis state: {:?}", e))?;

View File

@@ -167,12 +167,19 @@ pub fn initialize_beacon_state_from_eth1<E: EthSpec>(
// Remove intermediate Fulu fork from `state.fork`. // Remove intermediate Fulu fork from `state.fork`.
state.fork_mut().previous_version = spec.gloas_fork_version; state.fork_mut().previous_version = spec.gloas_fork_version;
// The genesis block's bid must have block_hash = 0x00 per spec (empty payload).
// Retain the EL genesis hash in latest_block_hash and parent_block_hash so the // Retain the EL genesis hash in latest_block_hash and parent_block_hash so the
// first post-genesis proposer can build on the correct EL head. // first post-genesis proposer can build on the correct EL head.
let el_genesis_hash = state.latest_execution_payload_bid()?.block_hash; let el_genesis_hash = state.latest_execution_payload_bid()?.block_hash;
let bid = state.latest_execution_payload_bid_mut()?; let bid = state.latest_execution_payload_bid_mut()?;
bid.parent_block_hash = el_genesis_hash; bid.parent_block_hash = el_genesis_hash;
bid.block_hash = ExecutionBlockHash::default(); bid.block_hash = ExecutionBlockHash::default();
// Update the `latest_block_header.body_root` so that it matches the body of the
// Gloas genesis block, which embeds `state.latest_execution_payload_bid` in its
// `signed_execution_payload_bid` field (see `genesis_block`).
let genesis_body_root = genesis_block(&state, spec)?.body_root();
state.latest_block_header_mut().body_root = genesis_body_root;
} }
// Now that we have our validators, initialize the caches (including the committees) // Now that we have our validators, initialize the caches (including the committees)
@@ -184,16 +191,25 @@ pub fn initialize_beacon_state_from_eth1<E: EthSpec>(
Ok(state) Ok(state)
} }
/// Create an unsigned genesis `BeaconBlock` matching the genesis state. /// Create an unsigned genesis `BeaconBlock`.
/// ///
/// Per spec, the genesis block body is empty (all default fields). /// Per spec, the genesis block body is empty (all default fields) except for Gloas,
/// `state.latest_block_header.body_root` is set from `BeaconBlock::empty()`, /// where `body.signed_execution_payload_bid.message` is initialised from
/// so this function must return the same empty block to keep roots consistent. /// `state.latest_execution_payload_bid` so that the first post-genesis proposer can
/// build on the correct execution layer head.
///
/// `state.latest_block_header.body_root` is set from this same block's body, so the
/// two must stay in sync.
pub fn genesis_block<E: EthSpec>( pub fn genesis_block<E: EthSpec>(
_genesis_state: &BeaconState<E>, state: &BeaconState<E>,
spec: &ChainSpec, spec: &ChainSpec,
) -> Result<BeaconBlock<E>, BeaconStateError> { ) -> Result<BeaconBlock<E>, BeaconStateError> {
Ok(BeaconBlock::empty(spec)) let mut block = BeaconBlock::empty(spec);
if let BeaconBlock::Gloas(ref mut gloas_block) = block {
let bid = state.latest_execution_payload_bid()?.clone();
gloas_block.body.signed_execution_payload_bid.message = bid;
}
Ok(block)
} }
/// Determine whether a candidate genesis state is suitable for starting the chain. /// Determine whether a candidate genesis state is suitable for starting the chain.