Automata <> Flashbots: TEE Validity Proof for OP-Stack

Disclaimer: Please note that the architecture of TEE validity proof is currently in its early design phase, and the architecture described here is subject to change as development progresses.

Acknowledgments: Special thanks to the Flashbots team (@dmarz, @ferranbt) for the collaborative discussions on the overall architecture design. This work is components of the design include elements from Kona, op-succinct, rollup-boost, rbuilder.

Purpose

This document aims to propose a method for integrating the TEE validity proof and the external block builder with the OP Stack.

Architecture

The overall architecture is further expanded based on rollup boost, illustrating the process of TEE Proof generation, submission, and verification.

Parties involved:

  • TEE Prover network - a network of entities that verify the correctness of the blocks by relying on the guarantees provided by TEEs.
  • TEE Proof Gateway - a proof provider to op-proposer for requesting TEE validity proofs and submit proposals to L1.
  • rollup-boost - a sidecar to op-node for requesting block production from an external party.
  • L1 Contract - where the updated state of the L2 is published
  • L1 Prover Registry Contract - TEE prover registry and TEE validity proof validator
  • L1 Attestation Verification Contract - Automata DCAP Attestation, use to verify the validity of attestation
  • rbuilder - a Ethereum MEV-Boost block builder written in Rust.

TEE Stack Integration

TEE validity proof

The TEE validity proof guarantees that blocks are executed correctly and provides on-chain verifiable states post-execution. This proof is generated by the TEE prover network. The TEE prover is responsible for executing blocks within the TEE and generating the TEE validity proof to attest to the execution.

The verification of the TEE validity proof involves two key checks: 1) whether the pre_state_root of the execution result matches the current state, 2) whether the execution was performed inside a TEE. For the second check, it is typically necessary to verify the attestation report produced by the TEE prover to ensure its legitimacy and confirm that the code matches expectations. However, this process usually consumes approximately 3M gas, making it unsuitable for verification every time a block is proposed to L1. To reduce this overhead, we have designed the ProverRegistry contract. The TEE prover must register its secp256k1 public key by submitting an attestation report and then use its key to sign the execution result, embedding the signature within the TEE validity proof. This way, the verification of the TEE validity proof only requires using ecrecover to extract the public key and checking if it has been registered. It is important to note that the TEE prover’s registration in the ProverRegistry is only valid for a specific time window, such as a half of month, and must be renewed before expiration.

During the registration of a TEE prover, the ProverRegistry verifies the attestation report. The attestation report’s validity is checked using automata-dcap-attestation, and additional runtime checks, such as the version of the running TEE prover code, are also performed.

TEE Prover Network

The TEE prover is designed to be stateless, providing the following benefits: 1) extremely short startup time, allowing for the deployment of multiple instances to improve availability and processing capacity, and 2) reduced maintenance and storage costs. Since the prover is stateless, it requires an external source to supply the state needed for block execution, which we refer to as the Proof of Block (PoB).

The TEE Prover Network consists of prover nodes running on various types of TEEs. Based on their types, these nodes are categorized into different groups. For any given task, each group must execute the task independently. Within each group, tasks can be subdivided based on the number of shards. This logic is managed by the TEE Proof Gateway.

TEE Proof Gateway

The TEE Proof Gateway does not need to run inside a TEE. It has two main roles: 1) collecting Proofs of Block (PoB) generated by the block builder and storing them in the database, and 2) receiving fetchTEEProof requests from the op-proposer, retrieving the PoB from the database, and sending it to the TEE Prover Network. The gateway then aggregates the proof and returns it to the op-proposer.

End-to-End Block Proposal Workflow

The following explains how the entire system utilizes the TEE validity proof for submit a block proposal to L1.

The op-node acts as the sequencer responsible for producing blocks. This block production process interacts with rollup-boost through the Ethereum Engine API. Rollup-boost forwards the request to rbuilder, which generates the block along with a Proof of Block (PoB) and returns them to rollup-boost. Rollup-boost then sends the new block and PoB to the TEE Proof Gateway for storage in the database.

The op-proposer periodically polls op-node to determine the time to submit a block proposal to L1. When it is time to submit, the op-proposer requests the OutputAtBlock from op-node to obtain the output data of the latest block and contacts the TEE Proof Gateway to generate the TEE validity proof for the new block range. The TEE Proof Gateway retrieves the PoB list from the database and send it to the provers for process. It then aggregates the proofs from different provers and returns them to the op-proposer. The op-proposer submits the output and the TEE validity proof to L1 for verification. The legality of the TEE validity proof can be verified through the ProverRegistry.

Integration with Op-Stack

This proposal requires some modifications to the existing system.

  • For the L1 Contract, we can modify the proposeL2Output method of the L2OutputOracle to include an additional parameter for passing the TEE validity proof, then the proof can be verified using the ProverRegistry.
  • For op-proposer, needs to access the TEE Proof Gateway to obtain the TEE validity proof before calling proposeOutput in the L2OutputSubmitter.
  • rbuilder needs to support the generation of Proof of Block (PoB) and send the PoB to the TEE Proof Gateway through rollup-boost.
4 Likes

Love the proposal!
One question that I’ve started to ponder lately is whether it’s interesting to include the identity of the operator along with the TEE pubkey during registration.
A TEE-generated pubkey is a good way to authenticate a TEE instance, as you are tying the pubkey to the instance’s measurement in attestation, but that does not allow tying the pubkey to whoever is operating the TEE prover. In some cases, for example misbehaviour or using outdated code/firmware, it could be beneficial to also tie the instance to a specific infrastructure provider.

This is a good idea, although we currently do not have a general way to verify the accuracy of the information the operator provided.

Although there is a 64-byte limit for report data, we have found a way to tie in more information. In practice, what we tie into the attestation report is not the TEE pubkey but a keccak256 hash of a struct. This struct contains the TEE pubkey along with other necessary information that we want to include. When the TEE Prover registers, it also provides this struct to the contract, thereby circumventing the 64-byte limitation.

Very nice. I like the ProverRegistry idea to allow cheaper verification. FYI the L2OutputOracle is deprecated though, it should probably use the DisputeGameFactory (which despite it’s name doesn’t need to be a dispute game).