mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-07 08:52:54 +00:00
fix: gloas from genesis
- Fix forkchoice update sending zero-hash head to EL at genesis by reading latest_block_hash from state when the genesis bid hashes are all zeros - Simplify genesis block construction — the genesis block body is empty per spec, remove the incorrect bid-copying logic and body root override in initialize_beacon_state_from_eth1
This commit is contained in:
committed by
Eitan Seri-Levi
parent
effcd08223
commit
0078b6be89
@@ -416,11 +416,24 @@ where
|
|||||||
|
|
||||||
let (execution_status, execution_payload_parent_hash, execution_payload_block_hash) =
|
let (execution_status, execution_payload_parent_hash, execution_payload_block_hash) =
|
||||||
if let Ok(signed_bid) = anchor_block.message().body().signed_execution_payload_bid() {
|
if let Ok(signed_bid) = anchor_block.message().body().signed_execution_payload_bid() {
|
||||||
// Gloas: execution status is irrelevant post-Gloas; payload validation
|
// At Gloas genesis the block bid is empty (all zeros) per spec, but the
|
||||||
// is decoupled from beacon blocks.
|
// state holds the EL genesis hash in `latest_block_hash`. Use it so the
|
||||||
|
// first forkchoice update sends a valid head to the EL.
|
||||||
|
let parent_hash = if anchor_block.slot() == spec.genesis_slot
|
||||||
|
&& anchor_state.slot() == spec.genesis_slot
|
||||||
|
&& signed_bid.message.parent_block_hash.into_root().is_zero()
|
||||||
|
&& signed_bid.message.block_hash.into_root().is_zero()
|
||||||
|
{
|
||||||
|
*anchor_state
|
||||||
|
.latest_block_hash()
|
||||||
|
.map_err(Error::BeaconStateError)?
|
||||||
|
} else {
|
||||||
|
signed_bid.message.parent_block_hash
|
||||||
|
};
|
||||||
|
|
||||||
(
|
(
|
||||||
ExecutionStatus::irrelevant(),
|
ExecutionStatus::irrelevant(),
|
||||||
Some(signed_bid.message.parent_block_hash),
|
Some(parent_hash),
|
||||||
Some(signed_bid.message.block_hash),
|
Some(signed_bid.message.block_hash),
|
||||||
)
|
)
|
||||||
} else if let Ok(execution_payload) = anchor_block.message().execution_payload() {
|
} else if let Ok(execution_payload) = anchor_block.message().execution_payload() {
|
||||||
|
|||||||
@@ -167,19 +167,12 @@ 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)
|
||||||
@@ -191,25 +184,16 @@ pub fn initialize_beacon_state_from_eth1<E: EthSpec>(
|
|||||||
Ok(state)
|
Ok(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create an unsigned genesis `BeaconBlock`.
|
/// Create an unsigned genesis `BeaconBlock` matching the genesis state.
|
||||||
///
|
///
|
||||||
/// Per spec, the genesis block body is empty (all default fields) except for Gloas,
|
/// Per spec, the genesis block body is empty (all default fields).
|
||||||
/// where `body.signed_execution_payload_bid.message` is initialised from
|
/// `state.latest_block_header.body_root` is set from `BeaconBlock::empty()`,
|
||||||
/// `state.latest_execution_payload_bid` so that the first post-genesis proposer can
|
/// so this function must return the same empty block to keep roots consistent.
|
||||||
/// 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>(
|
||||||
state: &BeaconState<E>,
|
_genesis_state: &BeaconState<E>,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<BeaconBlock<E>, BeaconStateError> {
|
) -> Result<BeaconBlock<E>, BeaconStateError> {
|
||||||
let mut block = BeaconBlock::empty(spec);
|
Ok(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.
|
||||||
|
|||||||
Reference in New Issue
Block a user