protolambda/eth2-testnet-genesis

Altair genesis seems to use phase0 `BeaconBlockBody` in `latest_block_header`

Closed this issue ยท 4 comments

Altair genesis networks generated with this tool are incompatible with Lighthouse, failing due a mismatch between the genesis block root derived from the genesis state's latest_block_header and the genesis block root derived by creating an empty altair.BeaconBlock containing the genesis state's state_root.

For example, for the attached testnet-dir from Moshe Revah at @bloxapp the derived genesis block roots are:

  1. 0x49a68856395936166cdebb98e7d8e5b354ebe5a809dd7731021f6625b9b0b453 from the latest_block_header (wrong)
  2. 0xb03680d13635efb166b3a5a6f44e5d1d2b6cf78f6bbde1ecdff7cdbc7ff019a6 from an empty altair.BeaconBlock (correct)

The Lighthouse code for computing each root is:

  1. https://github.com/sigp/lighthouse/blob/564d7da656803f5e06e53a303972580be54500bf/beacon_node/beacon_chain/src/beacon_fork_choice_store.rs#L183-L188
  2. https://github.com/sigp/lighthouse/blob/564d7da656803f5e06e53a303972580be54500bf/beacon_node/beacon_chain/src/builder.rs#L903-L913

According to the spec, the latest_block_header should use an Altair block and should maintain the invariant that the block roots derived via these two methods are identical: https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/beacon-chain.md#initialize-state-for-pure-altair-testnets-and-test-vectors

Therefore I believe this is a bug in eth2-testnet-genesis, although I can't spot it in a quick skim of altair.go.

testnet-dir.zip

It seems that to fix this would require updating zrnt, which currently only supports phase0 genesis initialization here: https://github.com/protolambda/zrnt/blob/8b73fddbb938b8c5dbac14876d5f001f3d572425/eth2/beacon/phase0/genesis.go#L45-L48

It seems that to fix this would require updating zrnt, which currently only supports phase0 genesis initialization here: https://github.com/protolambda/zrnt/blob/8b73fddbb938b8c5dbac14876d5f001f3d572425/eth2/beacon/phase0/genesis.go#L45-L48

Genesis initialization seems to occur in eth2-testnet-genesis rather than in zrnt:

var emptyBody tree.HTR
switch state.(type) {
case *bellatrix.BeaconStateView:
emptyBody = bellatrix.BeaconBlockBodyType(configs.Mainnet).New()
case *altair.BeaconStateView:
emptyBody = altair.BeaconBlockBodyType(configs.Mainnet).New()
default:
emptyBody = phase0.BeaconBlockBodyType(configs.Mainnet).New()
}
latestHeader := &common.BeaconBlockHeader{
BodyRoot: emptyBody.HashTreeRoot(tree.GetHashFn()),
}
if err := state.SetLatestBlockHeader(latestHeader); err != nil {
return err
}

Closing as @moshe-blox found that the incompatibility was due to an old bundled version of eth2-testnet-genesis. Proto's spec code continues to be unrivalled in its correctness ;)

Fix is ready: ethpandaops/ethereum-genesis-generator#7
h/t @michaelsproul for helping me debug this
and @protolambda for correctness ๐Ÿ˜„