{"record":{"id":"5b9d81229562d523","repo":"datahaven-xyz/datahaven","slug":"invalidexecutionheaderproof","errorCode":"InvalidExecutionHeaderProof","errorMessage":"InvalidExecutionHeaderProof","messagePattern":"InvalidExecutionHeaderProof","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"operator/pallets/ethereum-client/src/impls.rs","lineNumber":121,"sourceCode":"                // finalized header root at the expected slot.\n                let state = <FinalizedBeaconState<T>>::get(beacon_block_root)\n                    .ok_or(Error::<T>::ExpectedFinalizedHeaderNotStored)?;\n                if execution_proof.header.slot != state.slot {\n                    return Err(Error::<T>::ExpectedFinalizedHeaderNotStored.into());\n                }\n            }\n        }\n\n        // Gets the hash tree root of the execution header, in preparation for the execution\n        // header proof (used to check that the execution header is rooted in the beacon\n        // header body.\n        let execution_header_root: H256 = execution_proof\n            .execution_header\n            .hash_tree_root()\n            .map_err(|_| Error::<T>::BlockBodyHashTreeRootFailed)?;\n\n        let execution_header_gindex = Self::execution_header_gindex();\n        ensure!(\n            verify_merkle_branch(\n                execution_header_root,\n                &execution_proof.execution_branch,\n                subtree_index(execution_header_gindex),\n                generalized_index_length(execution_header_gindex),\n                execution_proof.header.body_root\n            ),\n            Error::<T>::InvalidExecutionHeaderProof\n        );\n        Ok(())\n    }\n\n    /// Verify that `block_root` is an ancestor of `finalized_block_root` Used to prove that\n    /// an execution header is an ancestor of a finalized header (i.e. the blocks are\n    /// on the same chain).\n    fn verify_ancestry_proof(\n        block_root: H256,\n        block_slot: u64,","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/datahaven-xyz/datahaven/blob/edcb13dbbcd3c29489eaa2480a6f60ee4cb1f3ec/operator/pallets/ethereum-client/src/impls.rs#L103-L139","documentation":"verify_execution_proof verifies that the execution header's hash_tree_root is a valid Merkle branch of the header's body_root, using the fixed generalized index for the execution header (execution_header_gindex) via SSZ verify_merkle_branch. If the branch is malformed, has wrong length, corresponds to a different leaf, or was computed against an incompatible spec, verification fails with InvalidExecutionHeaderProof.","triggerScenarios":"Submitting an execution proof whose execution_branch array is wrong-length, mis-ordered, computed for a different header/body_root, or generated with an incompatible SSZ/hash-tree-root implementation or spec version than execution_header_gindex expects.","commonSituations":"Relayer bugs building the branch (wrong gindex depth/leaf), hard-fork changes in Ethereum SSZ layouts vs the pallet's configured gindex, or truncating/copying branch arrays during serialization.","solutions":["Regenerate the execution_branch from the beacon block body using the exact generalized index returned by execution_header_gindex() and standard SSZ hash_tree_root.","Confirm the branch length equals generalized_index_length(execution_header_gindex) (expected 3 for the standard execution header gindex).","Verify the proof is built against the same header whose body_root is in execution_proof.header (not a different fork).","Update pallet gindex config if an Ethereum spec change altered the execution header's position in the block body tree."],"exampleFix":"// before: hand-built branch\nconst executionBranch = block.body.executionPayloadBranch; // wrong index\n// after: use the gindex-derived branch matching the pallet's config\nconst gIndex = EXECUTION_HEADER_GENERALIZED_INDEX; // must match execution_header_gindex()\nconst executionBranch = getMerkleBranch(block.body, gIndex);\nawait api.tx.ethereumClient.submitExecutionProof({ header, executionHeader, executionBranch }).signAndSend(relayer);","handlingStrategy":"validation","validationCode":"if (proof.executionBranch.length !== EXPECTED_EXECUTION_HEADER_GINDEX_LENGTH) throw new Error(`branch length must be ${EXPECTED_EXECUTION_HEADER_GINDEX_LENGTH}`);\nconst recomputed = ssz.BeaconBlockBody.hashTreeRoot(proof.body);\n// ensure branch is generated for this exact body_root","typeGuard":"const hasValidBranchShape = (p) => Array.isArray(p.executionBranch) && p.executionBranch.length === 3 && p.executionBranch.every(isHex32);","tryCatchPattern":"try {\n  await api.tx.ethereumClient.submitExecutionProof(proof).signAndSend(relayer);\n} catch (e) {\n  if (String(e).includes('InvalidExecutionHeaderProof')) regenerateProofAndAlert(proof);\n  else throw e;\n}","preventionTips":["Generate branches with the same SSZ library/spec version the pallet uses.","Assert branch length matches generalized_index_length(execution_header_gindex).","Verify proofs locally with verify_merkle_branch before submission.","Re-verify branch construction after Ethereum hard forks."],"tags":["merkle-proof","ssz","beacon","light-client"],"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"}