# Risc Zero's Zeth The RISC Zero zero-knowledge virtual machine (zkVM) lets you prove correct execution of arbitrary Rust code. ![from-rust-to-receipt-23117368c4f46d78c8cac3b753245a5a](https://hackmd.io/_uploads/HkWJP7ar6.png) --- In the case of Zeth (a type-1 zkEVM), Ethereum and Bedrock blocks can be proven to be correctly executed by running a Reth (a rust Ethereum client implementation) ELF binary along with state inputs, to produce a receipt, which can be verifed using a smart contract on L1 (or any EVM execution layer). ![resized_image](https://hackmd.io/_uploads/B1TJtQpB6.png) Bonsai provides an easy to use REST API to which you provide a program to be proved alongside inputs. This negates the need to setup the complex GPU environment required. ## Zeth High Level Architecture Zeth is an application running on Risc0's zkVM. It is a type-1 zkEVM which breaks down the Rust program that is the target of proving into segments in a Operating Systems type architecture and proves these segments in parallel, similar to a Incremental Verifiable Computation (IVC) scheme. Risc0 proving happens using a FRI based STARK system and finally for cheaper succinct proof size a Groth16 proof is generated which can then be verified onchain for a constant gas cost (~250k gas). ![resized_smaller_new_image](https://hackmd.io/_uploads/HJvsY7pr6.png) ## Zeth Architecture ### Overview ![](https://hackmd.io/_uploads/rk60_yJ7a.png) The Network and DB components of an Ethereum client are stubbed out. REVM is the main component used from [Reth](https://github.com/paradigmxyz/reth). REVM is the core EVM interpreter component of RETH. There is no concept of consensus with the proof system, just a stateless EVM interpreter and public inputs (transactions and state). Zeth relies on other systems (archive nodes etc.) to provide these inputs. Still uses (and requires) Reth/Geth as an archive node. Proving Bedrock blocks also requires access to a full node. In a future [planned release](https://github.com/risc0/zeth/pull/51), the Bedrock deriviation process logic will be included as part of the proof, providing a stronger proof about the L2 state. ## Sub State Risc Zero operates on required sub-state (partial Merkle tree). This is harder to construct/verify but much smaller than the alternatives (syncing/proving from genesis (having the entire state tree). The BlockBuilder component, which runs as a pre-cursor to the proving stage, constructs this sub state tree and supplies it as an input to the prover. ### Steps 1. The first step takes a block N already propagated in the network. a. we are interested in getting state from N-1 AND N for the inputs (to ensure updates were done correctly) 3. Execute it again in the EVM (EVM I) and track what state it touches 4. Using information from step 2, prepare the input for zkVM (a unioned Merkle tree of the state reads from N-1 and updates in block N) 5. Verification of state input happens 6. Run EVM II "inside the proving system". Ensuring and constraing correct execution. 7. Get a proof out (proof of block creation) ## Guest Host Code review This is the program that runs inside Bonsai. For proving an Optimistic Block it is three lines of code: ```rust // Read the input previous block and transaction data let input = env::read(); // Build the resulting block let output = OptimismBlockBuilder::build_from(&OP_MAINNET_CHAIN_SPEC, input) .expect("Failed to build the resulting block"); // Output the resulting block's hash to the journal env::commit(&output.hash()); ``` The imported OptimismBlockBuilder library does most of the interesting work. This library is found in the base level of the Zeth project. ## Integration with OpMantle ### Design Integration can be done in parallel as shown below, but would require an upgrade to the Mantle bridge in order to recognize if a withdraw transaction has been included in a block that has been proven and verified on Ethereum mainnet. ![](https://hackmd.io/_uploads/HJ-7Bxk76.png) ### Spectulation Code Changes Optimism Bedrock support was added to Zeth in this [PR](https://github.com/risc0/zeth/pull/31). Expect it to be a similar workflow, depending on MNT native token integration mechanism. The following would potentially need to change to prove a Mantle V2 block (**noting: it seems like it would take very large code changes to go straigh from Mantle V1**): #### 1. Implement a new [MantleBlockBuilder](https://github.com/risc0/zeth/blob/main/lib/src/block_builder.rs#L201) The `OptimismBlockBuilder::build_from()` function creates a new ConfiguredBlockBuilder from a given chain spec (OP_MAINNET_CHAIN_SPEC) and input and does the following: 1. Initializes the database 2. Prepares the block header 3. Executes the transactions 4. Builds the block This function returns the block appropriate as an input for the prover. #### 2. Implement a new [TxEssence](https://github.com/risc0/zeth/blob/main/primitives/src/transactions/optimism.rs#L30) type for Mantle transactions. This must include a way to handle the MNT native gas token. The Mantle Block Builder above will call this TxEssence when parsing/preparing transactions for input to the prover. #### Constants chainId and EIP1559 denominator settings: ```rust /// The optimism mainnet specification. pub static OP_MAINNET_CHAIN_SPEC: Lazy<ChainSpec> = Lazy::new(|| ChainSpec { chain_id: 10, hard_forks: BTreeMap::from([(SpecId::MERGE, ForkCondition::Block(0))]), eip_1559_constants: Eip1559Constants { base_fee_change_denominator: uint!(50_U256), base_fee_max_increase_denominator: uint!(10_U256), base_fee_max_decrease_denominator: uint!(50_U256), elasticity_multiplier: uint!(6_U256), }, }); ``` ## Alternative Architecture Options ### AltLayer AltLayer (a Rollup As A Service project) have also proposed an alternative hybrid design to producing a validity proof per block - producing a validity proof for a block *only* when the block is suspected to be faulty (within the Optimistic challenge window). ![Screenshot 2023-11-01 at 1.42.34 PM.png](https://hackmd.io/_uploads/S1kIONxQ6.png) Note: AltLayers design uses the Sputnik Rust Ethereum client, compiled to WASM, which in turn is compiled to RISCV (?). ### Kroma Kroma is an OPStack fork that aims to gradually switch the withdraw time from 7 days to 1 hour. Kroma have taken a pragmatic zk proving forward compatible approach modifying the OpStack to allow for zk proofs for entire blocks to be submitted when the proving stacks are performant enough: https://github.com/kroma-network/kroma/blob/dev/specs/differences-from-optimism.md ![Screenshot 2023-12-05 at 4.48.38 PM](https://hackmd.io/_uploads/H1dxHBTrp.png) To do this they introduce the concept of a `Validator` that produces zkProofs for invalid state transitions (fraud) *after* the L2 state has been optimistically posted on L1. This provides a mechanism by which the withdrawal period can be shortened, the presence (or lackof) of a fraud proof (without the need for an interactive fraud proof game) heightens the trust that the L2 state is valid and thus withdrawals hastened. ## Performance Still slow - a typical Ethereum block requires 2-4 billion zkVM cycles to construct. Proving a Bedrock block on average takes 64 GPU's 35 mins. OpStack blocks typically are produced every 2 seconds, so roughly 1000 times faster. However the design of Risc0 Continuations allows for parallelism. *todo*: see how many GPU's would allow keeping the proving system in sync with the tip of a Bedrock chain. ### Cost Cost is the main prohibitor for adopting Zeth, with proving an average Ethereum block said to be ~$22. The GROTH16 proofs are cheap to verify onchain (245k gas @30GWei ~$6). ## Testing Prerequiste: build Zeth locally following the instructions in the Zeth repo. Se the BONSAI_API_KEY and BONSAI_API_URL. Block: https://optimistic.etherscan.io/block/111639325 uses ~2.6 million gas, 9 transactions, 0 withdrawals (deposits show up as a regular transaction?) Run: ``` zeth -r="https://optimism-mainnet.infura.io/v3/<API_KEY>" -n="optimism" -b=111639325 -s --cache ``` This pulls all the data Zeth needs to construct the Sub state tree from the RPC provider (using eth_getStorage, eth_getBlock etc. ) and gives this as an input to the Bonsai API. The `--cache` option writes the data fetched to a local file stored by block number. This file compressed is ~2MB and uncompressed ~5MB. For Block 111639325: The partial state trie consists of 406 nodes The partial storage tries consist of 1371 nodes The Bonsai proving time took ~12mins wallclock time. Almost instantaneous verifying the block using: ``` RUST_LOG=info ./target/release/zeth -r="https://optimism-mainnet.infura.io/v3/0d224fb035b2481bb3982ffd585da0e9" -n="optimism" -b=111639325 --cache -v=080aadbc-49e7-4181-a808-b0987e6ebabf ``` where the final param was the UUID returned from the above proving step. ## Resources Zeth release post with high level architecture and some proving costs: https://www.risczero.com/news/zeth-release AltLayer and RiscZero architecture blog post: https://www.risczero.com/news/altlayer-zkfraudproofs RiscZero study club "Intro to Zeth" details the Sub state tree approach: https://www.youtube.com/watch?v=4pBmf839eOA RiscZero's OP Foundation Mission RFP: https://github.com/ethereum-optimism/ecosystem-contributions/issues/61#issuecomment-1611869982