Skip to content

Commit

Permalink
docs: op-succinct End to End tutorial (#57)
Browse files Browse the repository at this point in the history
* correct links in tutorial

* update vkey generation in contracts/README

* cargo run --bin vkey --release

* docs: tutorial

* add

* add

* clean

* fix: verify key

* fix

* docs

* fix: tutorial

---------

Co-authored-by: Ratan Kaliani <[email protected]>
Co-authored-by: Ubuntu <[email protected]>
  • Loading branch information
3 people authored Aug 26, 2024
1 parent 5d83bfb commit 329daf8
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 14 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Standalone repo to use Kona & SP1 to verify OP Stack blocks.

## Running `op-succinct`

For instructions on generating validity proofs for an OP Stack chain, refer to the [`op-succinct` Guide](./op-succinct-proposer/OP_PROPOSER.md).
For instructions on how to upgrade an OP Stack chain to use ZK validity proofs, refer to the [`op-succinct` Guide](./op-succinct-proposer/TUTORIAL.md).

## Estimating Cycle Counts

Expand Down
2 changes: 1 addition & 1 deletion contracts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,5 @@ The `ZKL2OutputOracle.sol` contract requires a verification key to be able to ve
This key can be generated by running the following command from the root of the repo:

```shell
just generate-agg-vkey
cargo run --bin vkey --release
```
2 changes: 1 addition & 1 deletion contracts/zkconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@
"vkey": "0x0000000000000000000000000000000000000000000000000000000000000000",
"verifierGateway": "0x3B6041173B80E77f038f3F2C0f9744f04837185e",
"l2OutputOracleProxy": "0xdfe97868233d1aa22e815a266982f2cf17685a27"
}
}
20 changes: 20 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,23 @@ run-client-native l2_block_num l1_rpc='${L1_RPC}' l1_beacon_rpc='${L1_BEACON_RPC
# Output the data required for the ZKVM execution.
echo "$L1_HEAD $L2_OUTPUT_ROOT $L2_CLAIM $L2_BLOCK_NUMBER $L2_CHAIN_ID"

upgrade-l2oo l1_rpc admin_pk etherscan_api_key="":
#!/usr/bin/env bash
CHAIN_ID=$(jq -r '.chainId' contracts/zkconfig.json)
if [ "$CHAIN_ID" = "0" ] || [ -z "$CHAIN_ID" ]; then
echo "Are you sure you've filled out your zkconfig.json? Your chain ID is currently set to 0."
exit 1
fi

VERIFY=""
ETHERSCAN_API_KEY="{{etherscan_api_key}}"
if [ $ETHERSCAN_API_KEY != "" ]; then
VERIFY="--verify --verifier etherscan --etherscan-api-key $ETHERSCAN_API_KEY"
fi

L1_RPC="{{l1_rpc}}"
ADMIN_PK="{{admin_pk}}"

cd contracts && forge script script/ZKUpgrader.s.sol:ZKUpgrader --rpc-url $L1_RPC --private-key $ADMIN_PK $VERIFY --broadcast --slow
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Run OP Proposer
# Run the `op-succinct` Proposer

## Instructions

Expand Down
109 changes: 109 additions & 0 deletions op-succinct-proposer/TUTORIAL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# `op-succinct` Tutorial

This tutorial guides you through upgrading an existing OP Stack chain to a ZK-OP Stack chain. It assumes you already have a running OP Stack chain. If not, please follow [Optimism's tutorial](https://docs.optimism.io/builders/chain-operators/tutorials/create-l2-rollup) first.

## Prerequisites

Before starting, ensure you have:

1. Access to the Admin keys for upgrading L1 contracts of the OP Stack chain.
2. Fault proofs turned off (you should be using `L2OutputOracle`, not `FaultDisputeGameFactory` for output roots).
3. Stopped the original `op-proposer`.
4. At least 1 ETH in your `PROPOSER` wallet.
5. All dependencies from the Optimism tutorial installed.
6. Your L2 geth node running with `--gcmode=archive` and `--state.scheme=hash` flags. You can do this with [ops-anton](https://github.com/anton-rs/ops-anton/blob/main/L2/op-mainnet/op-geth/op-geth.sh).

## Overview

At a high level, the `op-succinct` upgrade focuses on replacing the `op-proposer` component and its associated contracts. This change allows the chain to progress only with ZK-proven blocks, while keeping the other components (`op-geth`, `op-batcher`, and `op-node`) unchanged.

When an OP Stack chain is running, there are 4 main components:
1. `op-geth` (Sequencer mode): Takes transactions from users and uses them to generate blocks and execute blocks.
2. `op-batcher`: Batches transactions from users and submits them to the L1.
3. `op-node`: Reads batch data from L1 and uses it to drive `op-geth` in non-sequencer mode to perform state transitions.
4. `op-proposer`: Posts an output root to L1 at regular intervals, which captures the L2 state so withdrawals can be processed.

## Step-by-Step Guide

### Step 1: Setup

1. Clone the `op-succinct` repo:
```
git clone https://github.com/succinctlabs/op-succinct.git
```

2. Create and fill in the environment files:
```
cp .env.example .env
cp .env.server.example .env.server
```

3. Fill in the `contracts/zkconfig.json` file with your chain's specific details.

<details>
<summary>Field Info</summary>

- `startingBlockNumber`: The L2 block number at which the rollup starts. Default should be 0.
- `l2RollupNode`: The URL of the L2 rollup node. (After the tutorial, this is `http://localhost:8545`)
- `submissionInterval`: The number of L2 blocks between each L1 output submission.
- `l2BlockTime`: The time in seconds between each L2 block.
- `proposer`: The Ethereum address of the proposer account. If `address(0)`, anyone can submit proofs.
- `challenger`: The Ethereum address of the challenger account. If `address(0)`, no one can dispute proofs.
- `finalizationPeriod`: The time period (in seconds) after which a proposed output becomes finalized. Specifically, the time period after
which you can withdraw your funds against the proposed output.
- `chainId`: The chain ID of the L2 network.
- `owner`: The Ethereum address of the `ZKL2OutputOracle` owner, who can update the verification key and verifier address.
- `vkey`: The verification key for the aggregate program. Run `cargo run --bin vkey --release` to generate this.
- `verifierGateway`: The address of the verifier gateway contract.
- `l2OutputOracleProxy`: The address of your OP Stack chain's L2 Output Oracle proxy contract which will be upgraded.

</details>

### Step 2: Deploy ZKL2OutputOracle

1. Navigate to the contracts directory:
```
cd contracts
```

2. Run the upgrade script:
```
forge script script/ZKUpgrader.s.sol:ZKUpgrader --rpc-url <L1 RPC> --private-key <ADMIN PK> --verify --verifier etherscan --etherscan-api-key <ETHERSCAN API> --broadcast --slow --vvvv
```
Alternatively, use:
```
just upgrade-l2oo <L1_RPC> <ADMIN_PK> <ETHERSCAN_API_KEY>
```

To run your OP Stack chain with ZK proofs you need to replace your chain's `L2OutputOracle` with `ZKL2OutputOracle`.

The existing `L2OutputOracle` allows a permissioned `proposer` role to submit output roots. The permissioned `challenger` role can dispute these output roots. There are no checks on the validity of these claims.

The ZKL2OutputOracle makes the following changes:
- Require a valid SP1 proof for each output root submission.
- If `proposer == address(0)`, anyone can submit a proof.

### Step 3: Launch `op-succinct`

1. Build and start the Docker container:
```
docker compose build
docker compose up -d
```

This launches a Docker container with `op-proposer` from a fork of the `optimism` monorepo which can be found [here](https://github.com/succinctlabs/optimism/tree/zk-proposer) as well as a server that generates ZK proofs using Kona (Optimism's state transition function library) and SP1 (a zkVM).

The modified `op-proposer` performs the following tasks:
- Monitors L1 state to determine when to request a proof.
- Requests proofs from the Kona SP1 server.
- Once proofs have been generated for a sufficiently large range (specified by `SUBMISSION_INTERVAL` in `zkconfig.json`), aggregates batch proofs and submits them on-chain.

## Verification

After completing these steps, your chain will be running as a ZK-OP chain:

- The L1 contract (ZKL2OutputOracle) verifies ZK proofs.
- The Kona SP1 server generates ZK proofs.
- The modified `op-proposer` submits ZK-proven output roots to L1.

🎉 Congratulations! 🎉 You've successfully upgraded to a ZK-OP chain with `op-succinct`.
12 changes: 2 additions & 10 deletions op-succinct-proposer/bin/vkey.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use std::str::FromStr;

use alloy::{providers::ProviderBuilder, sol, transports::http::reqwest::Url};
use alloy_primitives::{hex, keccak256, Address, B256};
use alloy::sol;
use alloy_primitives::{hex, keccak256};
use anyhow::Result;
use log::info;
use sp1_sdk::{utils, HashableKey, ProverClient};
Expand Down Expand Up @@ -37,8 +35,6 @@ async fn main() -> Result<()> {
dotenv::dotenv().ok();
utils::setup_logger();

let args = Args::parse();

let prover = ProverClient::new();

let (_, vkey) = prover.setup(MULTI_BLOCK_ELF);
Expand All @@ -55,10 +51,6 @@ async fn main() -> Result<()> {
let (_, agg_vk) = prover.setup(AGG_ELF);
info!("Aggregation ELF Verification Key: {}", agg_vk.bytes32());
println!("Aggregation ELF Verification Key: {}", agg_vk.bytes32());
let agg_vk_bytes: [u8; 32] = hex::decode(agg_vk.bytes32().replace("0x", ""))
.unwrap()
.try_into()
.unwrap();

Ok(())
}

0 comments on commit 329daf8

Please sign in to comment.