ZK Light Client
The ZK circuit for the Ethereum PoS light client primarily comprises two components:
This circuit computes the SSZ commitment for the 512 validators in the sync committee, requiring 1025 SHA-256 computations over a 64-byte public key. It is worth noting that SHA-256 is not ZK- friendly due to bitwise operations, leading to a large number of constraints in our implementation. Fortunately, since the Ethereum sync committee updates every 27 hours, this circuit is invoked only occasionally. However, the per-block aggregate BLS signature verification, which also necessitates calculating the sync committee commitment, is impractical at such a large number of constraints for a per-block frequency. To address this issue, we employ a technique by Succinct Labs, allowing the circuit to compute two commitments: one using the original SHA-256 hash function and the other utilizing a ZK-friendly hash function, such as Poseidon or Rescue hash.
This circuit first calculates the ZK-friendly commitment and compares it to the on-chain commitment mapping. Subsequently, it verifies the BLS12-381 signature, involving hash-to-curve calculations and BLS12-381 pairing over the BN254 scalar field (since the initial implementation requires light client verification in EVM, where BN254 pairing is supported as a pre-compile).
Our system utilizes the latest beacon chain light client APIs, which provide both sync committee and header updates. Proofs are submitted to on-chain light client contracts for sync committee and block signature verification.
Sync committee updates must be submitted every 27 hours to establish a chain of trust. Blocks, on the other hand, can be updated on-demand as long as they are attested by the current or the next committee. To support use cases like generic message passing, we also generate a Merkle proof for the execution state root in the beacon state and submit it to the light client to persist the latest execution state root on-chain. Consequently, other applications can easily call the Ethereum API eth getProof to obtain Merkle proofs for any state of interest, and the on-chain contract ensures that the state root matches the persisted root.