Header Proof

When creating the proof, we always need the header containing the state_root and the body_root, so we proof against those values. But we also need to verify the BeaconBlockHeader.

There are 3 different ways to proof the BeaconBlockHeader

EthSignatureBlockProof

A Signature Proof simply contains the BLS signature of the sync committee for the header to verify.

The Type is defined in src/chains/eth/ssz/verify_proof_types.h.

class EthSignatureBlockProof(Container):
    sync_committee_bits      : BitVector [512] # the bits of the validators that signed the header close to head
    sync_committee_signature : ByteVector [96] # the signature of the sync committee

EthHistoricBlockProof

Since Clients usually have the public keys of the last sync period and are able to verify blocks, verifying a ollder block gets complicated, because you would need the public keys of the sync committee at that period, which ar hardly available. In order to allow the verification of those historic blocks, we can use the the historic summaries of the current state.

  1. Block Root Inclusion: Start with the target block_root to verify. Combine it with all other 8192 block roots from the same period and generate a Merkle proof proving inclusion within that period’s block root list.

  2. Historical Summary Proof: Using the current BeaconState, locate the corresponding HistoricalSummary, which holds the summarized root (summary_root) of that 8192-block list. Extend the Merkle proof to show inclusion of this summary in the historical_summaries tree.

  3. State Root Proof: Continue the Merkle proof from the historical_summaries tree up to the state_root of the BeaconState. This step links the historical proof chain to the current verified state.

  4. Consensus Verification: Finally, use the BeaconBlockHeader associated with the current state. Match the derived state_root with the one referenced in the block header. Then verify the BLS signature of the Sync Committee corresponding to that block header. This signature confirms the authenticity of the BeaconBlock and thus of the complete historical proof chain. Building the historic proof In order to build a historic proof, we need data, which can not be provided directly by the standard beacon api. At the time of writing, only lodestar offers an endpoint providing the merkle proof and the full list of historical summaries at /eth/v1/lodestar/states/{state_id}/historical_summaries. For the blockroots itself, of course you get each single blockroot for all 8192 blocks of the period so you can build the merkle proof with a lot of requests to the header-endpoint, but this would take very long, so fetching them all and caching all blockroots allows to build them fast and efficient. Those blockroots are then stored in the chain_store under data/{chain_id}/{period}/blocks.ssz. When starting the prover with the -d option, it will use the fetched data. a proof using the historic summaries

The Type is defined in src/chains/eth/ssz/verify_proof_types.h.

class EthHistoricBlockProof(Container):
    proof                    : List [bytes32, 128] # merkle proof from thr blotroot over the historic_summaries to the state
    header                   : BeaconBlockHeader   # the header of the beacon block containing historic_summaries (usually close to head)
    gindex                   : Uint64              # the combined gindex of the proof
    sync_committee_bits      : BitVector [512]     # the bits of the validators that signed the header containing the historic_summaries
    sync_committee_signature : ByteVector [96]     # the signature of the sync committee

Referenced Types

EthHeadersBlockProof

If the header we want to proof is slightly older than the sync period, where the user has the key, the easiest way to proof it, is by providing a chain of header from the header for the data up to a header where the user has the keys of the sync committee. Header proof is a proof, using a list of following headers to verify a block in the past with a later header holding a signature.

The Type is defined in src/chains/eth/ssz/verify_proof_types.h.

class EthHeadersBlockProof(Container):
    headers                  : List [ProofHeader, 128] # list of headers
    header                   : BeaconBlockHeader       # the header of the beacon block containing the signature
    sync_committee_bits      : BitVector [512]         # the bits of the validators that signed the header close to head
    sync_committee_signature : ByteVector [96]         # the signature of the sync committee

Referenced Types

ProofHeader

a header structures used for a chain of headers in the Header Proof, by representing a header without the parentRoot used.

The Type is defined in src/chains/eth/ssz/verify_proof_types.h.

class ProofHeader(Container):
    slot          : Uint64  # the slot of the block or blocknumber
    proposerIndex : Uint64  # the index of the validator proposing the block
    stateRoot     : Bytes32 # the hash_tree_root of the state at the end of the block
    bodyRoot      : Bytes32 # the hash_tree_root of the block body

Last updated