datahaven-xyz/datahaven · error

InvalidAncestryMerkleProof

InvalidAncestryMerkleProof

Error message

InvalidAncestryMerkleProof

What it means

verify_ancestry_proof validates, via verify_merkle_branch, that the provided block_root is a valid Merkle leaf at leaf_index = SLOTS_PER_HISTORICAL_ROOT + (block_slot % SLOTS_PER_HISTORICAL_ROOT) within the state's block_roots_root, at depth config::BLOCK_ROOT_AT_INDEX_DEPTH. A wrong or tampered proof fails with InvalidAncestryMerkleProof.

Solutions

  1. Rebuild block_root_proof from state.block_roots[block_slot % SLOTS_PER_HISTORICAL_ROOT] using depth config::BLOCK_ROOT_AT_INDEX_DEPTH.
  2. Ensure the leaf index used is SLOTS_PER_HISTORICAL_ROOT + (block_slot % SLOTS_PER_HISTORICAL_ROOT), matching the pallet's block_roots_root tree layout.
  3. Confirm the client and pallet agree on SLOTS_PER_HISTORICAL_ROOT and BLOCK_ROOT_AT_INDEX_DEPTH constants.
  4. Re-fetch the beacon state and regenerate the proof if it was fetched from a different fork/state.

Example fix

// before: index into state.block_roots directly
const proof = getBranch(state.blockRoots, blockSlot % SLOTS_PER_HISTORICAL_ROOT);
// after: offset into block_roots_root tree and correct depth
const idx = SLOTS_PER_HISTORICAL_ROOT + (blockSlot % SLOTS_PER_HISTORICAL_ROOT);
const proof = getBranch(state.blockRoots, idx - SLOTS_PER_HISTORICAL_ROOT, BLOCK_ROOT_AT_INDEX_DEPTH);
await submitAncestryProof(blockRoot, blockSlot, proof, finalizedRoot);
Defensive patterns

Strategy: validation

Validate before calling

const idx = blockSlot % SLOTS_PER_HISTORICAL_ROOT;
if (proof.blockRootProof.length !== BLOCK_ROOT_AT_INDEX_DEPTH) throw new Error('ancestry proof depth mismatch');
const ok = verifyMerkleBranch(blockRoot, proof.blockRootProof, SLOTS_PER_HISTORICAL_ROOT + idx, BLOCK_ROOT_AT_INDEX_DEPTH, state.blockRootsRoot);
if (!ok) throw new Error('local ancestry verification failed');

Type guard

const hasValidAncestryShape = (p) => Array.isArray(p.blockRootProof) && p.blockRootProof.every(isHex32) && p.blockRootProof.length === BLOCK_ROOT_AT_INDEX_DEPTH;

Try / catch

try {
  await submitAncestryProof(blockRoot, blockSlot, proof, finalizedRoot);
} catch (e) {
  if (String(e).includes('InvalidAncestryMerkleProof')) refetchStateAndRebuildProof();
  else throw e;
}

Prevention

When it happens

Trigger: Submitting an ancestry proof whose block_root_proof is wrong-length, built for a different slot/block_root, computed with the wrong depth (not BLOCK_ROOT_AT_INDEX_DEPTH), or taken from a different beacon state's block_roots array.

Common situations: Relayer slicing the wrong section of block_roots (leaf index must include the +SLOTS_PER_HISTORICAL_ROOT offset into block_roots_root), spec/config drift between client and pallet constants, or proof corruption during transport/serialization.

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


AI-assisted analysis of datahaven-xyz/datahaven@edcb13dbbc (2026-09-13). Data as JSON: /api/errors/d09e9ba8d0a48613. Report an issue: GitHub.

Appendix: source

Thrown at operator/pallets/ethereum-client/src/impls.rs:151

    /// Verify that `block_root` is an ancestor of `finalized_block_root` Used to prove that
    /// an execution header is an ancestor of a finalized header (i.e. the blocks are
    /// on the same chain).
    fn verify_ancestry_proof(
        block_root: H256,
        block_slot: u64,
        block_root_proof: &[H256],
        finalized_block_root: H256,
    ) -> DispatchResult {
        let state = <FinalizedBeaconState<T>>::get(finalized_block_root)
            .ok_or(Error::<T>::ExpectedFinalizedHeaderNotStored)?;

        ensure!(block_slot < state.slot, Error::<T>::HeaderNotFinalized);

        let index_in_array = block_slot % (SLOTS_PER_HISTORICAL_ROOT as u64);
        let leaf_index = (SLOTS_PER_HISTORICAL_ROOT as u64) + index_in_array;

        ensure!(
            verify_merkle_branch(
                block_root,
                block_root_proof,
                leaf_index as usize,
                config::BLOCK_ROOT_AT_INDEX_DEPTH,
                state.block_roots_root
            ),
            Error::<T>::InvalidAncestryMerkleProof
        );

        Ok(())
    }
}

View on GitHub (pinned to edcb13dbbc)