Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions beacon_node/beacon_chain/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ use tracing::{debug, error, info, warn};
use tree_hash::TreeHash;
use types::data::CustodyIndex;
use types::{
BeaconState, BlobSidecarList, ChainSpec, ColumnIndex, DataColumnSidecarList, Epoch, EthSpec,
Hash256, SignedBeaconBlock, Slot,
BeaconBlock, BeaconState, BlobSidecarList, ChainSpec, ColumnIndex, DataColumnSidecarList,
Epoch, EthSpec, Hash256, SignedBeaconBlock, Slot,
};

/// An empty struct used to "witness" all the `BeaconChainTypes` traits. It has no user-facing
Expand Down Expand Up @@ -1177,9 +1177,19 @@ fn make_genesis_block<E: EthSpec>(
genesis_state: &mut BeaconState<E>,
spec: &ChainSpec,
) -> 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)
.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() {
block = BeaconBlock::empty(spec);
}

*block.state_root_mut() = genesis_state
.update_tree_hash_cache()
.map_err(|e| format!("Error hashing genesis state: {:?}", e))?;
Expand Down
28 changes: 22 additions & 6 deletions consensus/state_processing/src/genesis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,12 +167,19 @@ pub fn initialize_beacon_state_from_eth1<E: EthSpec>(
// Remove intermediate Fulu fork from `state.fork`.
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
// first post-genesis proposer can build on the correct EL head.
let el_genesis_hash = state.latest_execution_payload_bid()?.block_hash;
let bid = state.latest_execution_payload_bid_mut()?;
bid.parent_block_hash = el_genesis_hash;
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)
Expand All @@ -184,16 +191,25 @@ pub fn initialize_beacon_state_from_eth1<E: EthSpec>(
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) except for Gloas,
/// where `body.signed_execution_payload_bid.message` is initialised from
/// `state.latest_execution_payload_bid` so that the first post-genesis proposer can
/// build on the correct execution layer head.
///
/// Per spec, the genesis block body is empty (all default fields).
/// `state.latest_block_header.body_root` is set from `BeaconBlock::empty()`,
/// so this function must return the same empty block to keep roots consistent.
/// `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>(
_genesis_state: &BeaconState<E>,
state: &BeaconState<E>,
spec: &ChainSpec,
) -> 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.
Expand Down
Loading