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 committeeEthHistoricBlockProof
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.
Block Root Inclusion: Start with the target
block_rootto 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.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.State Root Proof: Continue the Merkle proof from the
historical_summariestree up to thestate_rootof the BeaconState. This step links the historical proof chain to the current verified state.Consensus Verification: Finally, use the BeaconBlockHeader associated with the current state. Match the derived
state_rootwith 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 underdata/{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 committeeReferenced 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 committeeReferenced 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 bodyLast updated