In order to create the most robust and secure network of interoperable L2 chains, the Optimism Collective is pursuing decentralization across many different tracks.
The OP Stack’s forthcoming fault proof system will be a huge step forward for technical decentralization and the open source and modular design of the OP Stack is setting the stage for unprecedented social decentralization of an L2 ecosystem.
In this blog post, we’ll explore the principle of social decentralization, how L2 architecture allows Layer 2s to extend this principle to include proof diversity as well as client diversity, and how the Optimism Collective is building its fault proof system to leverage this architecture.
Social Decentralization, inspired by Ethereum
The Ethereum protocol benefits from social decentralization by enabling a broad range of contributors to build a robust network by creating optionality in the solutions. For node software, this means client diversity: the more client implementations, the less impact a single point of failure can have on the validator network.
Core devs in L1 describe this contribution model as the “bazaar”; noisy and seemingly chaotic, but immensely productive and energizing. With a radical open approach to protocol development, the broadest set of contributors can improve the protocol.
The Optimism Collective is uniquely positioned to implement and iterate on the way Ethereum approaches social decentralization. The OP Stack enables social decentralization, with open specifications and MIT licensed open source software, and the Optimism Collective iterates on it with the creation of the Superchain.
A closer look at L2 architecture
L1 Ethereum has open specifications, and a modular client architecture that separates the consensus and execution layers. The OP-Stack implements this same architecture for L2:
- Consensus is backed by op-node and Magi, two clients that follow L1 and derive execution inputs.
- Execution is backed by op-geth, op-erigon, and op-reth.
L2 architecture adds a new layer to this stack however: the proving layer. This is the layer that securely bridges the L2 outputs back into L1. Just as having multiple clients is best practice for securing consensus and execution on L1 and L2, a multi-proof approach for an L2’s proving layer ensures the best security.
Similar to a client-diverse validator-set coming to consensus, a quorum of onchain proofs can signal that the L2 state claim has been validated in different ways, which significantly derisks the chance that a bug causes a total failure.
There are three common types of proofs; attestations, fault proofs (aka fraud proofs), and ZK validity proofs. The latter two share a common pattern. They express the L2 state-transition in a synchronous form, and prove the execution of it when given L1 data and L2 pre-state as input.
Isolating proof system components to enable proof diversity
Proof systems can be further split up into isolated components:
- A “program” defines the synchronous L2 state-transition.
- A “VM” runs and proves the program.
- A “pre-image oracle” gives the L1 data and L2 pre-state as inputs.
Many ZK-proofs today still tightly couple these components, creating a ZK-EVM that operates on singular L1 transaction data. The OP Stack, however, decouples them in order to isolate complexity and enable client diversity that makes the total more robust.
Interactive fault proofs add a bisection-game to the VM trace to verify the proof onchain, while VM-based ZK-proofs arithmetize and fold the execution in a validity proof. (See the VM-based ZK proofs that Risc0 and O(1)-Labs are designing in response to Optimism’s ZK RFPs).
The program defines the actual state-transition as a “client,” and the input-fetching (L1 data and L2 pre-state) as “server.” Running stand-alone with server/client but no VM, the program is very similar to a regular blockchain node, and shares a lot of the code. For example, the Go op-program client is built by importing the derivation from op-node and EVM from op-geth, and the server fetches its data from L1 and L2 ethereum RPC.
Functional Overview of the FPVM
The Fault Proof VM (FPVM) is one of the modules in the OP Stack’s fault proof stack.
The VM does not implement anything specific to Ethereum or L2, except for providing the right interfaces (most notably, the interface to the pre-image oracle). The Fault Proof Program (FPP) (client-side) that runs within the FPVM is the part that expresses the L2 state-transition.
Through this separation, the VM stays ultra-minimal: Ethereum protocol changes, like EVM op-code additions, do not affect the VM. Instead, when the protocol changes, the FPP can simply be updated to import the new state-transition components from the node software. Similar to playing a new version of a game on the same game console, the L1 proof system can be updated to prove a different program.
What the VM is tasked with is the lower-level instruction execution. The FPP needs to be emulated. The VM requirements are low: the program is synchronous, and all inputs are loaded through the same pre-image oracle, but all of this still has to be proven in the L1 EVM onchain!
To do this, only one instruction is proven at a time. The bisection game will narrow down the task of proving a full execution trace to just a single instruction.
Proving the instruction may look different for each FPVM, but generally it looks similar to Cannon, which proves the instruction as follows:
- To execute the instruction, the VM emulates something akin to an instruction-cycle of a thread-context: the instruction is read from memory, interpreted, and the register-file and memory may change a little.
- To support the pre-image oracle, and basic program runtime needs like memory-allocation, the execution also supports a subset of linux syscalls. Read/write syscalls allow interaction with the pre-image oracle: the program writes a hash as request for a pre-image, and then reads the value in small chunks at a time.
Cannon, the first FPVM, implements a MIPS VM this way. Please see the docs and cannon-specs for more information about the VM. The interface between FPVM and FP-program is standardized, and documented in the specs.
FPVM to ZKVM
Fault proofs are not the only type of state-transition proof. ZK validity-proofs are an attractive option because of the potential for fast bridging (since there is no onchain challenge game for ZK validity-proofs, there is no dispute window). To support an advanced Ethereum stack and host different client implementations, we still need to decouple the VM and program.
This is the approach the ZK RFP projects are taking, to prove a minimal RISC-V (by Risc0) or MIPS (by O(1) Labs) VM that can host the same program as used in the fault proofs.
Supporting the ZK-VM does require small adaptions to make the pre-image oracle load the data non-interactively, but by generalizing the VM the ZK-proof is a lot more future-proof to OP Stack changes.
Opportunities for External Contribution
The OP Stack welcomes additional VM and program options, as well as additional independent proof systems, from attestations to ZK. Like client diversity, proof diversity is a collective effort!
Current ongoing complements to the OP Stack proving layer include:
- A RISC-V FPVM “Asterisc” written in Go is in development by protolambda.
- A rust FP-program, based on Magi and op-reth, is being built with contributors from Base and OP Labs.
- A rust ZK-program, based on zeth, a ZK-reth fork, is being built by Risc0.
With the development of Cannon, the op-program, the bisection-game, the above, and the boundless ingenuity of the open source community, there will be many additional opportunities for contributing to the stack by testing implementations and participation in bug bounties! Anyone interested should bookmark Optimism’s Immunefi Bug Bounty page for new bounties related to the OP Stack’s Fault Proof System. 👀