datahaven-xyz/datahaven · error · Error
InvalidBlockRootsRootMerkleProof
InvalidBlockRootsRootMerkleProof
Error message
InvalidBlockRootsRootMerkleProof
What it means
The `block_roots_branch` in the update fails to prove `block_roots_root` is part of the beacon state at `update.header.state_root`. This proof (via `process_checkpoint_update`, using the fork-dependent `block_roots` generalized index) is required so later execution-header updates can do ancestry proofs. A failed verification means the block-roots root or branch does not correspond to the update's beacon state.
Solutions
- Fetch `block_roots_root` and its branch from a beacon node at exactly `update.header.slot` with the correct `block_roots` generalized index.
- Ensure `block_roots_gindex_at_slot` in `T::ForkVersions` reflects the fork at the header slot.
- Regenerate the whole update from a single consistent beacon state snapshot rather than mixing fields from different slots.
- Verify chain identity (testnet vs mainnet beacon chain).
Example fix
// before
let branch = state.get_branch("block_roots")?; // fetched at state.slot
// after
let branch = consensus_client.get_block_roots_branch(header.slot)?; // same slot as header.state_root Defensive patterns
Strategy: validation
Validate before calling
const ok = verifyMerkleBranch(update.blockRootsRoot, update.blockRootsBranch, subtreeIndex(blockRootsGindex), generalizedIndexLength(blockRootsGindex), update.header.stateRoot);
if (!ok) throw new Error('block roots proof invalid'); Try / catch
try { await submit(update); } catch (e) { if (e.includes('InvalidBlockRootsRootMerkleProof')) { refetchProofsAt(headerSlot); } else throw e; } Prevention
- Always fetch branch and root at the header's slot
- Keep ForkVersions gindex table up to date
- Mirror verify_merkle_branch checks locally pre-submit
When it happens
Trigger: Submitting an `Update` where `verify_merkle_branch(update.block_roots_root, update.block_roots_branch, ...)` against `update.header.state_root` fails — wrong branch, wrong root, or state_root/branch from different states.
Common situations: Relayer computed the block_roots root itself instead of reading the state's field; branch taken at a different slot than the header; fork-specific gindex mismatch; relaying updates across a hard fork boundary with outdated fork version config.
Understand the failure class
Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.
Related errors
- InvalidSyncCommitteeMerkleProof
- InvalidHeaderMerkleProof
- InvalidExecutionHeaderProof
- InvalidAncestryMerkleProof
- InvalidUpdateSlot
AI-assisted analysis of datahaven-xyz/datahaven@edcb13dbbc (2026-09-13).
Data as JSON: /api/errors/3d4476032d88c7b0.
Report an issue: GitHub.
Appendix: source
Thrown at operator/pallets/ethereum-client/src/lib.rs:285
&update.current_sync_committee_branch,
subtree_index(sync_committee_gindex),
generalized_index_length(sync_committee_gindex),
update.header.state_root
),
Error::<T>::InvalidSyncCommitteeMerkleProof
);
let header_root: H256 = update
.header
.hash_tree_root()
.map_err(|_| Error::<T>::HeaderHashTreeRootFailed)?;
// This is used for ancestry proofs in ExecutionHeader updates. This verifies the
// BeaconState: the beacon state root is the tree root; the `block_roots` hash is the
// tree leaf.
let block_roots_gindex =
Self::block_roots_gindex_at_slot(update.header.slot, fork_versions);
ensure!(
verify_merkle_branch(
update.block_roots_root,
&update.block_roots_branch,
subtree_index(block_roots_gindex),
generalized_index_length(block_roots_gindex),
update.header.state_root
),
Error::<T>::InvalidBlockRootsRootMerkleProof
);
let sync_committee_prepared: SyncCommitteePrepared = (&update.current_sync_committee)
.try_into()
.map_err(|_| <Error<T>>::BLSPreparePublicKeysFailed)?;
<CurrentSyncCommittee<T>>::set(sync_committee_prepared);
<NextSyncCommittee<T>>::kill();
InitialCheckpointRoot::<T>::set(header_root);
Self::store_validators_root(update.validators_root);View on GitHub (pinned to edcb13dbbc)