{"record":{"id":"2378618b28a4d0e0","repo":"datahaven-xyz/datahaven","slug":"invalidheadermerkleproof","errorCode":"InvalidHeaderMerkleProof","errorMessage":"InvalidHeaderMerkleProof","messagePattern":"InvalidHeaderMerkleProof","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"operator/pallets/ethereum-client/src/lib.rs","lineNumber":382,"sourceCode":"                latest_finalized_state\n                    .slot\n                    .saturating_add(config::SLOTS_PER_HISTORICAL_ROOT as u64)\n                    >= update.finalized_header.slot,\n                Error::<T>::InvalidFinalizedHeaderGap\n            );\n\n            let fork_versions = T::ForkVersions::get();\n            let finalized_root_gindex = Self::finalized_root_gindex_at_slot(\n                update.attested_header.slot,\n                fork_versions.clone(),\n            );\n            // Verify that the `finality_branch`, if present, confirms `finalized_header` to match\n            // the finalized checkpoint root saved in the state of `attested_header`.\n            let finalized_block_root: H256 = update\n                .finalized_header\n                .hash_tree_root()\n                .map_err(|_| Error::<T>::HeaderHashTreeRootFailed)?;\n            ensure!(\n                verify_merkle_branch(\n                    finalized_block_root,\n                    &update.finality_branch,\n                    subtree_index(finalized_root_gindex),\n                    generalized_index_length(finalized_root_gindex),\n                    update.attested_header.state_root\n                ),\n                Error::<T>::InvalidHeaderMerkleProof\n            );\n\n            // Though following check does not belong to ALC spec we verify block_roots_root to\n            // match the finalized checkpoint root saved in the state of `finalized_header` so to\n            // cache it for later use in `verify_ancestry_proof`.\n            let block_roots_gindex = Self::block_roots_gindex_at_slot(\n                update.finalized_header.slot,\n                fork_versions.clone(),\n            );\n            ensure!(","sourceCodeStart":364,"sourceCodeEnd":400,"githubUrl":"https://github.com/datahaven-xyz/datahaven/blob/edcb13dbbcd3c29489eaa2480a6f60ee4cb1f3ec/operator/pallets/ethereum-client/src/lib.rs#L364-L400","documentation":"The `finality_branch` fails to prove that `finalized_header`'s block root is the finalized checkpoint root recorded in the state of `attested_header`. `verify_update` hashes the finalized header (`hash_tree_root`) and runs `verify_merkle_branch` against `update.attested_header.state_root` using the finalized-root generalized index. A failure means the finalized header is not actually the one attested — inconsistent or forged update data.","triggerScenarios":"Submitting an `Update` whose `finality_branch` does not verify: branch from a different attested state, finalized header hash-tree-root encoding mismatch, wrong `finalized_root_gindex` for the fork, or fields assembled from different sources.","commonSituations":"Relayer mixed headers from two beacon nodes or different slots; SSZ `hash_tree_root` implementation divergence after a fork; proof built with a pre-fork generalized index; malicious/buggy relayer submitting fabricated finalized headers.","solutions":["Regenerate the full update (attested header, finalized header, finality branch) from a single beacon node response (`/eth/v1/beacon/light_client/updates`).","Verify the finalized-root generalized index matches the fork version of the attested header slot.","Confirm the SSZ `hash_tree_root` of the finalized header matches what a consensus client computes.","Check chain/network identity to rule out cross-chain header mixing."],"exampleFix":"// before\n let finalized = fetch_header(other_node, finalized_root); // different source\n// after\n let upd = client.get_light_client_update(slot);\n // attested, finalized, finality_branch all from the same response\n submit(upd.into());","handlingStrategy":"validation","validationCode":"const root = hashTreeRoot(update.finalizedHeader);\nif (!verifyMerkleBranch(root, update.finalityBranch, subtreeIndex(finalizedRootGindex), generalizedIndexLength(finalizedRootGindex), update.attestedHeader.stateRoot)) throw new Error('finality proof invalid');","typeGuard":null,"tryCatchPattern":"try { await submit(update); } catch (e) { if (e.includes('InvalidHeaderMerkleProof')) { refetchUpdateFromSingleSource(); } else throw e; }","preventionTips":["Take attested+finalized headers and branch from one response","Verify SSZ hash_tree_root parity with consensus clients","Validate full update locally before extrinsic"],"tags":["substrate","merkle-proof","beacon-consensus","ssz"],"backgroundTag":"checksum-mismatch","analyzedSha":"edcb13dbbcd3c29489eaa2480a6f60ee4cb1f3ec","analyzedAt":"2026-09-13T19:19:32.206Z","contentChangedAt":"2026-09-13T19:19:32.206Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}