OP Succinct
Documentation for OP Succinct users and developers.
OP Succinct transforms any OP Stack rollup into a fully type-1 ZK rollup using SP1. OP Succinct provides:
- 1 hour finality secured by ZKPs, a dramatic improvement over the 7-day withdrawal window of standard OP Stack rollups.
- Unlimited customization for rollup modifications in pure Rust and easy maintainability.
- Cost-effective proving with an average cost of proving only fractions of cent per transaction (with an expected 5-10x improvement by EOY), thanks to SP1's blazing fast performance.
All of this has been possible thanks to close collaboration with the core team at OP Labs.
Reach out today if you want a Type-1 zkEVM rollup powered by SP1 (either a new rollup or a conversion from an optimistic rollup).
Architecture
Prerequisites
Every OP Stack rollup is composed of four main components.
op-geth
: Takes transactions from users and uses them to generate blocks and execute blocks.op-batcher
: Batches transactions from users and submits them to the L1.op-node
: Reads batch data from L1 and uses it to driveop-geth
in non-sequencer mode to perform state transitions.op-proposer
: Posts an output root to L1 at regular intervals, which captures the L2 state so withdrawals can be processed.
You can read more about the components in the OP Stack Specification.
OP Succinct
OP Succinct is a lightweight upgrade to the OP Stack that allows the chain to progress only with ZK-proven blocks, while keeping the other components (op-geth
, op-batcher
, and op-node
) unchanged. Deploying OP Succinct requires deploying one contract, OPSuccinctL2OutputOracle
, and spinning up a lightweight modification to the op-proposer
that requests proofs to be submitted to the L1 contract.
Here is a high-level overview of the new components that are introduced in OP Succinct:
- Range Program. A program that derives and executes batches of blocks. The program is written in Rust and designed to be executed inside the zkVM.
- Aggregation Program. Aggregates proofs of range programs to reduce on-chain verification costs. This program is also written in Rust and designed to be executed inside the zkVM.
- OP Succinct L2 Output Oracle. A solidity smart contract that contains an array of L2 state outputs, where each output is a commit to the state of the L2 chain. This contract already exists in Optimism's original system but is modified to verify proofs as the authentication mechanism.
- OP Succinct Proposer. Observes the posted batches on L1 and controls the proving of the range and aggregation programs.
Getting Started
In this section, we'll guide you through upgrading an OP Stack chain to a fully type-1 ZK rollup using SP1 and OP Succinct.
The steps are the following:
- Run the cost estimator to confirm that all of your endpoints are set up correctly. The cost estimator will simulate the proving of the chain and return the estimated "costs" of proving.
- Run OP Succinct in mock mode to confirm that your on-chain configuration is correct.
- Run OP Succinct in full mode to begin generating proofs of
op-succinct
. - Upgrade your OP Stack configuration to upgrade the
L2OutputOracle
contract to the newOPSuccinctL2OutputOracle
contract using yourADMIN
key.
Prerequisites
Requirements
You must have the following installed:
You must have the following RPCs available:
- L1 Archive Node
- L1 Consensus (Beacon) Node
- L2 Execution Node (
op-geth
) - L2 Rollup Node (
op-node
)
The following RPC endpoints must be accessible:
- L1 Archive Node.
debug_getRawHeader
,debug_getRawReceipts
,debug_getRawBlock
- L2 Execution Node (
op-geth
): Archive node with hash state scheme.debug_getRawHeader
,debug_getRawTransaction
,debug_getRawBlock
,debug_dbGet
- L2 Optimism Node (
op-node
)optimism_outputAtBlock
,optimism_rollupConfig
,optimism_syncStatus
,optimism_safeHeadAtL1Block
.
If you do not have access to an L2 OP Geth node + rollup node for your OP Stack chain, you can follow the L2 node setup instructions to spin them up.
OP Stack Chain
The rest of this section will assume you have an existing OP Stack Chain running. If you do not have one, there are two ways you can get started:
- Self-hosted. If you want to run your own OP Stack Chain, please follow Optimism's tutorial first.
- Rollup-as-a-service providers. You can also use an existing RaaS provider, such as Conduit, Caldera, Alchemy, AltLayer or Gelato. Contact them to upgrade your rollup to use OP Succinct.
Cost Estimator
The cost estimator is a convenient CLI tool to determine the costs of running OP Succinct. The tool simulates proving the validity of a range of blocks and returns the "costs" in terms of RISC-V cycles.
Machines with fast network connectivity (500+ Mbps) are recommended because witness generation is bandwidth-intensive.
Overview
In the root directory, add the following RPCs to your .env
file for your rollup:
Parameter | Description |
---|---|
L1_RPC | L1 Archive Node. |
L1_BEACON_RPC | L1 Consensus (Beacon) Node. |
L2_RPC | L2 Execution Node (op-geth ). |
L2_NODE_RPC | L2 Rollup Node (op-node ). |
More details on the RPC requirements can be found in the prerequisites section.
By running the cost estimator, you can validate that your endpoints are configured correctly.
Running the Cost Estimator
Overview
The cost estimator:
- Splits large block ranges into smaller batches
- Simulates proving each batch (similar to
op-succinct
) - Outputs aggregate statistics to a CSV.
⚠️ First run with a small block range - execution can be slow for large ranges.
Basic Usage
Run for the last 5 finalized blocks:
RUST_LOG=info just cost-estimator
Run for a specific block range:
RUST_LOG=info just cost-estimator <start_l2_block> <end_l2_block>
Configuration Options
Flag | Default | Description |
---|---|---|
batch-size | 300 | Blocks per batch. Chain-specific defaults: - Base: 5 - OP Mainnet: 10 - OP Sepolia: 30 |
env-file | .env | Custom env file path (e.g. .env.opmainnet ) |
use-cache | false | Reuse previously generated witness data |
Advanced Usage
Full command with all options:
RUST_LOG=info cargo run --bin cost-estimator --release \
--start <start_l2_block> \
--end <end_l2_block> \
--env-file <path_to_env_file> \
--batch-size <batch_size> \
--use-cache
Block Number Helpers
cast
is a CLI tool installed with Foundry that can be used to fetch the latest/finalized block number of an OP Stack chain.
# Get latest finalized block
cast block finalized -f number --rpc-url <L2_RPC>
# Get latest block
cast bn --rpc-url <L2_RPC>
Sample Output
stdout
Executing blocks 5,484,100 to 5,484,200 on World Chain Mainnet:
Aggregate Execution Stats for Chain 480:
+--------------------------------+---------------------------+
| Metric | Value |
+--------------------------------+---------------------------+
| Batch Start | 5,484,100 |
| Batch End | 5,484,200 |
| Witness Generation (seconds) | 66 |
| Execution Duration (seconds) | 458 |
| Total Instruction Count | 19,707,995,043 |
| Oracle Verify Cycles | 1,566,560,795 |
| Derivation Cycles | 2,427,683,234 |
| Block Execution Cycles | 15,442,479,993 |
| Blob Verification Cycles | 674,091,948 |
| Total SP1 Gas | 22,520,841,820 |
| Number of Blocks | 101 |
| Number of Transactions | 1,977 |
| Ethereum Gas Used | 546,370,916 |
| Cycles per Block | 195,128,663 |
| Cycles per Transaction | 9,968,636 |
| Transactions per Block | 19 |
| Gas Used per Block | 5,409,613 |
| Gas Used per Transaction | 276,363 |
| BN Pair Cycles | 7,874,860,533 |
| BN Add Cycles | 310,550,754 |
| BN Mul Cycles | 1,636,223,094 |
| KZG Eval Cycles | 0 |
| EC Recover Cycles | 96,983,901 |
+--------------------------------+---------------------------+
csv
The CSV associated with the range will have the columns from the ExecutionStats
struct. The aggregate data for executing each "batch" within the block range will be included in the CSV.
Here, the CSV is execution-reports/480/5484100-5484200.csv
:
batch_start,batch_end,witness_generation_time_sec,total_execution_time_sec,total_instruction_count,oracle_verify_instruction_count,derivation_instruction_count,block_execution_instruction_count,blob_verification_instruction_count,total_sp1_gas,nb_blocks,nb_transactions,eth_gas_used,l1_fees,total_tx_fees,cycles_per_block,cycles_per_transaction,transactions_per_block,gas_used_per_block,gas_used_per_transaction,bn_pair_cycles,bn_add_cycles,bn_mul_cycles,kzg_eval_cycles,ec_recover_cycles
5484184,5484200,0,0,2877585481,299740342,462008456,2066943417,134844448,3304337522,17,316,81926057,540908658541982,596950839845253,169269734,9106283,18,4819179,259259,1017572318,40106182,211873811,0,11948870
5484100,5484120,0,0,3754402331,308914395,461086557,2932162167,134779302,4287957207,21,350,106933244,710095197624994,783053876268826,178781063,10726863,16,5092059,305523,1561122615,61455811,324588766,0,14705709
5484163,5484183,0,0,4005997705,311171459,435265918,3206173584,134844448,4570091686,21,365,110883055,690170871678571,779801718014140,190761795,10975336,17,5280145,303789,1676711949,66155955,346844998,0,17337504
5484121,5484141,0,0,4152572226,316652487,486166806,3293854188,134779302,4746305028,21,440,117222955,767310117504021,846733606470274,197741534,9437664,20,5582045,266415,1584230563,62520537,329178548,0,25124445
5484142,5484162,0,0,4917437300,330082112,583155497,3943346637,134844448,5612150377,21,506,129405605,935016666707488,1031433531465147,234163680,9718255,24,6162171,255742,2035223088,80312269,423736971,0,27867373
Mock OP Succinct
Running OP Succinct in mock mode is useful for testing your configuration is correct before generating proofs.
Overview
1) Set environment variables.
In the root directory, create a file called .env
and set the following environment variables:
Parameter | Description |
---|---|
L1_RPC | L1 Archive Node. |
L1_BEACON_RPC | L1 Beacon Node. |
L2_RPC | L2 Execution Node (op-geth ). |
L2_NODE_RPC | L2 Rollup Node (op-node ). |
PRIVATE_KEY | Private key for the account that will be deploying the contract. |
ETHERSCAN_API_KEY | Etherscan API key for verifying the deployed contracts. |
There are additional optional parameters that you can set in the .env
file. See the Advanced Parameters section for more information.
2) Deploy an SP1MockVerifier
for verifying mock proofs
just deploy-mock-verifier
If successful, you should see the following output:
% just deploy-mock-verifier
[⠊] Compiling...
[⠑] Compiling 1 files with Solc 0.8.15
[⠘] Solc 0.8.15 finished in 615.84ms
Compiler run successful!
Script ran successfully.
== Return ==
0: address 0x4cb20fa9e6FdFE8FDb6CE0942c5f40d49c898646
## Setting up 1 EVM.
==========================
Chain 11155111
Estimated gas price: 3.851705636 gwei
Estimated total gas used for script: 171869
Estimated amount required: 0.000661988795953684 ETH
==========================
....
In these deployment logs, 0x4cb20fa9e6FdFE8FDb6CE0942c5f40d49c898646
is the address of the SP1MockVerifier
contract.
Custom Environment
If you have multiple environments, you can pass the environment file to the deploy-mock-verifier
command.
just deploy-mock-verifier <env_file>
3) Deploy the OPSuccinctL2OutputOracle
contract.
This contract is a modification of the L2OutputOracle
contract which verifies a proof along with the proposed state root.
First, add the address of the SP1MockVerifier
contract from the previous step to the .env
file in the root directory.
Parameter | Description |
---|---|
VERIFIER_ADDRESS | The address of the SP1MockVerifier contract. |
Then, deploy the OPSuccinctL2OutputOracle
contract.
just deploy-oracle
If successful, you should see the following output:
% just deploy-oracle
warning: op-succinct-scripts@0.1.0: fault-proof built with release-client-lto profile
warning: op-succinct-scripts@0.1.0: range built with release-client-lto profile
warning: op-succinct-scripts@0.1.0: native_host_runner built with release profile
Finished `release` profile [optimized] target(s) in 9.00s
Running `target/release/fetch-rollup-config --env-file .env`
[⠊] Compiling...
[⠘] Compiling 2 files with Solc 0.8.15
[⠃] Solc 0.8.15 finished in 1.72s
Compiler run successful!
Script ran successfully.
== Return ==
0: address 0xde4656D4FbeaC0c0863Ab428727e3414Fa251A4C
## Setting up 1 EVM.
==========================
Chain 11155111
Estimated gas price: 1.57226658 gwei
Estimated total gas used for script: 2746913
Estimated amount required: 0.00431887950806754 ETH
==========================
In these deployment logs, 0xde4656D4FbeaC0c0863Ab428727e3414Fa251A4C
is the address of the proxy for the OPSuccinctL2OutputOracle
contract. This deployed proxy contract is used to track the verified state roots of the OP Stack chain on L1.
4) Set op-succinct
service environment variables
To start the mock op-succinct
service, add the following parameters to the .env
file in the root directory:
Parameter | Description |
---|---|
L2OO_ADDRESS | The address of the OPSuccinctL2OutputOracle contract from the previous step. |
OP_SUCCINCT_MOCK | Set to true for mock mode. |
Now, you should have the following in your .env
file:
Parameter | Description |
---|---|
L1_RPC | L1 Archive Node. |
L1_BEACON_RPC | L1 Beacon Node. |
L2_RPC | L2 Execution Node (op-geth ). |
L2_NODE_RPC | L2 Rollup Node (op-node ). |
PRIVATE_KEY | Private key for the account that will be deploying the contract and relaying proofs on-chain. |
ETHERSCAN_API_KEY | Etherscan API key for verifying the deployed contracts. |
L2OO_ADDRESS | The address of the OPSuccinctL2OutputOracle contract from the previous step. |
OP_SUCCINCT_MOCK | Set to true for mock mode. |
5) Start the op-succinct
service in mock mode.
We provide a Docker Compose file for running the op-succinct
service.
Build the Docker Compose setup.
docker compose build
Run the Proposer
This command launches the op-succinct service in the background. It launches two containers: one container that manages proof generation and another container that is a small fork of the original op-proposer service.
After a few minutes, you should see the op-succinct-proposer service start to generate mock range proofs. Once enough range proofs have been generated, a mock aggregate proof will be created and submitted to the L1.
docker compose up
To see the logs of the op-succinct
service, run:
docker compose logs -f
To stop the op-succinct
service, run:
docker compose stop
Full OP Succinct
Running OP Succinct in full mode will generate proofs of valid OP Stack L2 outputs and submit them to the L1.
Prerequisites
You will need a whitelisted key on the Succinct Prover Network. Follow the instructions here to get your key whitelisted.
To get access to the Succinct Prover Network for OP Succinct, fill out this form. The Succinct team will reach out to you with an RPC endpoint you can use.
Overview
1) Contract deployment environment variables
In the root directory, create a file called .env
and set the following environment variables:
Parameter | Description |
---|---|
L1_RPC | L1 Archive Node. |
L1_BEACON_RPC | L1 Beacon Node. |
L2_RPC | L2 Execution Node (op-geth ). |
L2_NODE_RPC | L2 Rollup Node (op-node ). |
PRIVATE_KEY | Private key for the account that will be deploying the contract. |
ETHERSCAN_API_KEY | Etherscan API key for verifying the deployed contracts. |
There are additional optional parameters that you can set in the .env
file. See the Advanced Parameters section for more information.
2) Deploy the OPSuccinctL2OutputOracle
contract.
This contract is a modification of the L2OutputOracle
contract which verifies a proof along with the proposed state root.
Then, deploy the OPSuccinctL2OutputOracle
contract.
just deploy-oracle
If successful, you should see the following output:
% just deploy-oracle
warning: op-succinct-scripts@0.1.0: fault-proof built with release-client-lto profile
warning: op-succinct-scripts@0.1.0: range built with release-client-lto profile
warning: op-succinct-scripts@0.1.0: native_host_runner built with release profile
Finished `release` profile [optimized] target(s) in 9.00s
Running `target/release/fetch-rollup-config --env-file .env`
[⠊] Compiling...
[⠘] Compiling 2 files with Solc 0.8.15
[⠃] Solc 0.8.15 finished in 1.72s
Compiler run successful!
Script ran successfully.
== Return ==
0: address 0xde4656D4FbeaC0c0863Ab428727e3414Fa251A4C
## Setting up 1 EVM.
==========================
Chain 11155111
Estimated gas price: 1.57226658 gwei
Estimated total gas used for script: 2746913
Estimated amount required: 0.00431887950806754 ETH
==========================
In these deployment logs, 0xde4656D4FbeaC0c0863Ab428727e3414Fa251A4C
is the address of the proxy for the OPSuccinctL2OutputOracle
contract. This deployed proxy contract is used to track the verified state roots of the OP Stack chain on L1.
3) op-succinct
service environment variables
To start the op-succinct
service, add the following parameters to the .env
file in the root directory:
Parameter | Description |
---|---|
L2OO_ADDRESS | The address of the OPSuccinctL2OutputOracle contract from the previous step. |
SP1_PRIVATE_KEY | The private key for the account that will be submitting proofs to the L1. |
PROVER_NETWORK_RPC | The RPC endpoint for the Succinct Prover Network. The default endpoint (https://rpc.succinct.xyz ) is not suitable for use in OP Succinct. Reach out to the Succinct team to get access with OP Succinct. |
Now, you should have the following in your .env
file:
Parameter | Description |
---|---|
L1_RPC | L1 Archive Node. |
L1_BEACON_RPC | L1 Beacon Node. |
L2_RPC | L2 Execution Node (op-geth ). |
L2_NODE_RPC | L2 Rollup Node (op-node ). |
PRIVATE_KEY | Private key for the account that will be deploying the contract and relaying proofs on-chain. |
ETHERSCAN_API_KEY | Etherscan API key for verifying the deployed contracts. |
L2OO_ADDRESS | The address of the OPSuccinctL2OutputOracle contract from the previous step. |
SP1_PRIVATE_KEY | The private key for the account that will be submitting proofs to the L1. |
PROVER_NETWORK_RPC | Reach out to the Succinct team to get access here. The default endpoint (https://rpc.succinct.xyz ) is not suitable for use in OP Succinct. |
4) Start the op-succinct
service.
We provide a Docker Compose file for running the op-succinct
service.
Build the Docker Compose setup.
docker compose build
Run the Proposer
This command launches the op-succinct service in the background. It launches two containers: one container that manages proof generation and another container that is a small fork of the original op-proposer service.
After a few minutes, you should see the op-succinct-proposer service start to request proofs from the Succinct Prover Network. Once enough proofs have been generated, an aggregate proof will be requested and submitted to the L1.
docker compose up
To see the logs of the op-succinct
service, run:
docker compose logs -f
To stop the op-succinct
service, run:
docker compose stop
Migrate L2OutputOracle
to OPSuccinctL2OutputOracle
The last step is to update your OP Stack configuration to use the new OPSuccinctL2OutputOracle
contract managed by the op-succinct
service.
⚠️ Caution: When upgrading to the
OPSuccinctL2OutputOracle
contract, maintain the existingfinalizationPeriod
for a duration equal to at least onefinalizationPeriod
. Failure to do so will result in immediate finalization of all pending output roots upon upgrade, which is unsafe. Only after this waiting period has elapsed should you set thefinalizationPeriod
to your final desired value (e.g. 1 hour).
To upgrade an existing OP Stack deployment to use the OPSuccinctL2OutputOracle
contract, follow the instructions in the Upgrading OPSuccinctL2OutputOracle
section.
Advanced
This section contains advanced topics for OP Succinct.
Verify the OP Succinct binaries
When deploying OP Succinct in production, it's important to ensure that the SP1 programs used when generating proofs are reproducible.
Introduction
Recall there are two programs used in OP Succinct:
range
: Proves the correctness of an OP Stack derivation + STF for a range of blocks.aggregation
: Aggregates multiple range proofs into a single proof. This is the proof that lands on-chain. The aggregation proof ensures that allrange
proofs in a given block range are linked and use therangeVkeyCommitment
from theL2OutputOracleProxy
as the verification key.
Prerequisites
To reproduce the OP Succinct program binaries, you first need to install the cargo prove toolchain.
Ensure that you have the latest version of the toolchain by running:
sp1up
Confirm that you have the toolchain installed by running:
cargo prove --version
Verify the SP1 binaries
To build the SP1 binaries, first ensure that Docker is running.
docker ps
Then build the binaries:
cd programs/range
# Build the range-elf
cargo prove build --elf-name range-elf --docker --tag "v3.0.0"
cd programs/dummy-range
# Build the dummy-range-elf
cargo prove build --elf-name dummy-range-elf --docker --tag "v3.0.0"
cd ../aggregation
# Build the aggregation-elf
cargo prove build --elf-name aggregation-elf --docker --tag "v3.0.0"
Now, verify the binaries by confirming the output of vkey
matches the vkeys on the contract. The vkey
program outputs the verification keys
based on the ELFs in /elf
.
cargo run --bin vkey --release
L2 Node Setup
This guide will show you how to set up an L2 execution node (op-geth
) and a rollup node (op-node
) for your OP Stack chain.
Instructions
- Clone ops-anton and follow the instructions in the README to set up your rollup.
- Go to op-node.sh and set the
L2_RPC
to your rollup RPC. Modify thel1
andl1.beacon
to your L1 and L1 Beacon RPCs. Note: Your L1 node should be an archive node. - If you are starting a node for a different chain, you will need to modify
op-network
inop-geth.sh
here andnetwork
inop-node.sh
here. - In
/L2/op-mainnet
(or the directory you chose):- Generate a JWT secret
./generate_jwt.sh
docker network create anton-net
(Creates a Docker network for the nodes to communicate on).just up
(Starts all the services).
- Generate a JWT secret
Your op-geth
endpoint will be available at the RPC port chosen here, which in this case is 8547
(e.g. http://localhost:8547
).
Your op-node
endpoint (rollup node) will be available at the RPC port chosen here, which in this case is 5058
(e.g. http://localhost:5058
).
Check Sync Status
After a few hours, your node should be fully synced and you can use it to begin generating ZKPs.
To check your node's sync status, you can run the following commands:
op-geth:
curl -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0","method":"eth_syncing","params":[],"id":1}' http://localhost:8547
op-node:
curl -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0","method":"optimism_syncStatus","params":[],"id":1}' http://localhost:5058
Block Data
The block-data
script is a convenient CLI tool to fetch the block & fee data for a given range of blocks on a rollup.
Performs better with high RPS (requests per second) supported on the L2 RPC endpoint.
Overview
In the root directory, add the following RPC to your .env
file for your rollup:
Parameter | Description |
---|---|
L2_RPC | L2 Execution Node (op-geth ). |
To perform analysis on the fees collected on L2, you can use the block-data
script. This script will fetch the block & fee data for each block in the range from the L2 and output a CSV file with the columns: block_number
, transaction_count
, gas_used
, total_l1_fees
, total_tx_fees
.
Compared to the cost estimator, the block data script is much faster and requires less resources, so it's recommended to use this script if you only need the block data and want to calculate data quantities like average txns per block, avg gas per block, etc.
Once the script has finished execution, it will write the statistics for each block in the range to a CSV file at block-data/{chain_id}/{start_block}-{end_block}.csv
.
Run the Block Data Script
To run the block data script, use the following command:
RUST_LOG=info cargo run --bin block-data --release -- --start <start_l2_block> --end <end_l2_block>
Optional flags
Flag | Description |
---|---|
--env-file | The path to the environment file to use. (Ex. .env.opmainnet ) |
Useful Commands
cast block finalized -f number --rpc-url <L2_RPC>
: Get the latest finalized block number on the L2.cast bn --rpc-url <L2_RPC>
: Get the latest block number on the L2.
Sample Output
stdout
Fetching block data for blocks 5,484,100 to 5,484,200 on World Chain Mainnet:
Wrote block data to block-data/480/5484100-5484200-block-data.csv
Aggregate Block Data for blocks 5484100 to 5484200:
Total Blocks: 101
Total Transactions: 1977
Total Gas Used: 546370916
Total L1 Fees: 0.003644 ETH
Total TX Fees: 0.004038 ETH
Avg Txns/Block: 19.57
Avg Gas/Block: 5409613.03
Avg L1 Fees/Block: 0.000036 ETH
Avg TX Fees/Block: 0.000040 ETH
csv
block_number,transaction_count,gas_used,total_l1_fees,total_tx_fees
5710000,13,5920560,8004099318905,9272809586600
5710001,10,3000975,4810655220218,5353583855906
5710002,16,7269303,10842878782866,12174517937838
5710003,10,4521953,6142429255728,6967734553050
5710004,10,5558505,6534408691877,7550749486247
5710005,14,6670097,10210757953683,11431964042061
5710006,7,4725805,5863003171921,6725878188991
5710007,10,4798495,7011790976814,8252141668373
5710008,7,3805639,4428577556414,5121866899850
5710009,9,4348521,6732491769192,7697076627632
5710010,17,8728999,12317431205317,14022097163617
5710011,9,5882229,6229718004537,7411261930653
5710012,8,2053460,3062348125908,3938363190799
5710013,11,4829936,7756633163332,8721805365111
5710014,5,798837,1684650453190,2292476216082
5710015,10,4123290,7122749550608,7874581655693
5710016,8,1416529,3110958598569,3414612717107
...
Proposer
The op-succinct
service consists of two containers:
op-succinct-server
: Receives proof requests from theop-succinct-proposer
, generates the witness for the proof, and submits the proof to the Succinct Prover Network. Handles the communication with the Succinct's Prover Network to fetch the proof status and completed proof data.op-succinct-proposer
: Monitors L1 state to determine when to request a proof. Sends proof requests to theop-succinct-server
. Once proofs have been generated for a sufficiently large range, aggregates range proofs into an aggregation proof. Submits the aggregation proof to theOPSuccinctL2OutputOracle
contract which includes the L2 state outputs.
We've packaged the op-succinct
service in a docker compose file to make it easier to run.
Prerequisites
RPC Requirements
Confirm that your RPC's have all of the required endpoints. More details can be found in the prerequisites section.
Hardware Requirements
We recommend the following hardware configuration for the op-succinct
service containers:
Using the docker compose file:
- Full
op-succinct
service: 16 vCPUs, 64GB RAM. - Mock
op-succinct
service: 32 vCPUs, 128GB RAM. Increased memory because the machine is executing the proofs locally.
Running as separate containers:
op-succinct-server
- Full
op-succinct
service: 16 vCPUs, 64GB RAM. - Mock
op-succinct
service: 32 vCPUs, 128GB RAM. Increased memory because the machine is executing the proofs locally.
- Full
op-succinct-proposer
: 1 vCPU, 4GB RAM
For advanced configurations, depending on the number of concurrent requests you expect, you may need to increase the number of vCPUs and memory allocated to the op-succinct-server
container.
Environment Setup
Required Environment Variables
Before starting the proposer, the following environment variables should be in your .env
file. You should have already set up your environment when you deployed the L2 Output Oracle. If you have not done so, follow the steps in the Contract Configuration section.
Parameter | Description |
---|---|
L1_RPC | L1 Archive Node. |
L1_BEACON_RPC | L1 Consensus (Beacon) Node. |
L2_RPC | L2 Execution Node (op-geth ). |
L2_NODE_RPC | L2 Rollup Node (op-node ). |
PROVER_NETWORK_RPC | Default: rpc.succinct.xyz . |
SP1_PRIVATE_KEY | Key for the Succinct Prover Network. Get access here. |
SP1_PROVER | Default: network . Set to network to use the Succinct Prover Network. |
PRIVATE_KEY | Private key for the account that will be deploying the contract and posting output roots to L1. |
L2OO_ADDRESS | Address of the OPSuccinctL2OutputOracle contract. |
Advanced Environment Variables
The following environment variables are optional.
Parameter | Description |
---|---|
MAX_CONCURRENT_PROOF_REQUESTS | Default: 10 . The maximum number of concurrent proof requests to send to the op-succinct-server . |
MAX_BLOCK_RANGE_PER_SPAN_PROOF | Default: 300 . The maximum number of blocks to include in each span proof. For chains with high throughput, you need to decrease this value. |
OP_SUCCINCT_MOCK | Default: false . Set to true to run in mock proof mode. The OPSuccinctL2OutputOracle contract must be configured to use an SP1MockVerifier . |
OP_SUCCINCT_SERVER_URL | Default: http://op-succinct-server:3000 . The URL of the op-succinct-server service which the op-succinct-proposer will send proof requests to. |
METRICS_ENABLED | Default: true . Set to false to disable metrics collection. |
METRICS_PORT | Default: 7300 . The port to run the metrics server on. |
DB_PATH | Default: /usr/local/bin/dbdata . The path to the database directory within the container. |
POLL_INTERVAL | Default: 20s . The interval at which the op-succinct-proposer service runs. |
USE_CACHED_DB | Default: false . Set to true to use cached proofs from previous runs when restarting the service, avoiding regeneration of unused proofs. |
Build the Proposer Service
Build the docker images for the op-succinct-proposer
service.
docker compose build
Run the Proposer
This command launches the op-succinct-proposer
service in the background. It launches two containers: one container that manages proof generation and another container that is a small fork of the original op-proposer
service.
After a few minutes, you should see the op-succinct-proposer
service start to generate range proofs. Once enough range proofs have been generated, they will be verified in an aggregate proof and submitted to the L1.
docker compose up
To see the logs of the op-succinct-proposer
service, run:
docker compose logs -f
and to stop the op-succinct-proposer
service, run:
docker compose stop
Toggle Optimistic Mode
Optimistic mode is a feature that allows the L2OutputOracle to accept outputs without verification (mirroring the original L2OutputOracle
contract). This is useful for testing and development purposes, and as a fallback for when OPSuccinctL2OutputOracle
is unable to verify outputs.
When optimistic mode is enabled, the OPSuccinctL2OutputOracle
's proposeL2Output
function will match the interface of the original L2OutputOracle contract, with the modification that the proposer address must be in the approvedProposers
mapping, or permissionless proposing must be enabled.
Enable Optimistic Mode
To enable optimistic mode, call the enableOptimisticMode
function on the OPSuccinctL2OutputOracle
contract.
function enableOptimisticMode(uint256 _finalizationPeriodSeconds) external onlyOwner whenNotOptimistic {
finalizationPeriodSeconds = _finalizationPeriodSeconds;
optimisticMode = true;
emit OptimisticModeToggled(true, _finalizationPeriodSeconds);
}
Ensure that the finalizationPeriodSeconds
is set to a value that is appropriate for your use case. The standard setting is 1 week (604800 seconds).
The finalizationPeriodSeconds
should never be 0.
Disable Optimistic Mode
By default, optimistic mode is disabled. To switch back to validity mode, call the disableOptimisticMode
function on the OPSuccinctL2OutputOracle
contract.
function disableOptimisticMode(uint256 _finalizationPeriodSeconds) external onlyOwner whenOptimistic {
finalizationPeriodSeconds = _finalizationPeriodSeconds;
optimisticMode = false;
emit OptimisticModeToggled(false, _finalizationPeriodSeconds);
}
Set the finalizationPeriodSeconds
to a value that is appropriate for your use case. An example configuration is 1 hour (3600 seconds).
The finalizationPeriodSeconds
should never be 0.
Using Kurtosis to test op-succinct
What is Kurtosis?
Kurtosis is a development tool that allows you spin up local testnets for blockchain development and testing. The ethPandaOps team has created a package for spinning up OP Stack devnets using Kurtosis called optimism-package.
Install Kurtosis
First, install Kurtosis by following the instructions here: Kurtosis Installation Guide.
How to configure the OP Stack devnet
Configure the op-network.yaml
file to use the Kurtosis engine:
optimism_package:
chains:
- participants:
- el_type: op-geth
cl_type: op-node
network_params:
fjord_time_offset: 0
granite_time_offset: 0
holocene_time_offset: 0
additional_services:
- blockscout
ethereum_package:
participants:
- el_type: geth
- el_type: reth
network_params:
preset: minimal
additional_services:
- blockscout
How to run Kurtosis?
Run the testnet using the following command:
kurtosis run --enclave my-testnet github.com/ethpandaops/optimism-package --args-file op-network.yaml --image-download always
How to get the relevant RPC's from Kurtosis?
Once the Kurtosis service is running, you can get the relevant RPC endpoints (L1_RPC
, L2_RPC
, L1_BEACON_RPC
, L2_NODE_RPC
) from the logs:
========================================== User Services ==========================================
UUID Name Ports Status
f4d46dd9d329 cl-1-lighthouse-geth http: 4000/tcp -> http://127.0.0.1:32940 RUNNING
metrics: 5054/tcp -> http://127.0.0.1:32941
tcp-discovery: 9000/tcp -> 127.0.0.1:32942
udp-discovery: 9000/udp -> 127.0.0.1:32796
e42d898efb2e el-1-geth-lighthouse engine-rpc: 8551/tcp -> 127.0.0.1:32937 RUNNING
metrics: 9001/tcp -> http://127.0.0.1:32938
rpc: 8545/tcp -> 127.0.0.1:32935
tcp-discovery: 30303/tcp -> 127.0.0.1:32939
udp-discovery: 30303/udp -> 127.0.0.1:32795
ws: 8546/tcp -> 127.0.0.1:32936
37ed2311790f op-batcher-op-kurtosis http: 8548/tcp -> http://127.0.0.1:32951 RUNNING
d068303cf7af op-cl-1-op-node-op-geth-op-kurtosis http: 8547/tcp -> http://127.0.0.1:32949 RUNNING
tcp-discovery: 9003/tcp -> 127.0.0.1:32950
udp-discovery: 9003/udp -> 127.0.0.1:32798
d2a8cecbf572 op-el-1-op-geth-op-node-op-kurtosis engine-rpc: 8551/tcp -> 127.0.0.1:32946 RUNNING
metrics: 9001/tcp -> 127.0.0.1:32947
rpc: 8545/tcp -> http://127.0.0.1:32944
tcp-discovery: 30303/tcp -> 127.0.0.1:32948
udp-discovery: 30303/udp -> 127.0.0.1:32797
ws: 8546/tcp -> 127.0.0.1:32945
7a6d8bc60601 validator-key-generation-cl-validator-keystore <none> RUNNING
bc47bef086de vc-1-geth-lighthouse metrics: 8080/tcp -> http://127.0.0.1:32943 RUNNING
Relevant endpoints:
Endpoint | Service | URL |
---|---|---|
L1_RPC | rpc port of el-1-geth-lighthouse | http://127.0.0.1:32935 |
L2_RPC | rpc port of op-el-1-op-geth-op-node-op-kurtosis | http://127.0.0.1:32944 |
L1_BEACON_RPC | http port of cl-1-lighthouse-geth | http://127.0.0.1:32940 |
L2_NODE_RPC | http port of op-cl-1-op-node-op-geth-op-kurtosis | http://127.0.0.1:32949 |
Spin down the devnet
Remove the devnet with:
kurtosis clean -a
Upgrading to new op-succinct
version
Each new release of op-succinct
will specify if it includes:
- New verification keys
- Contract changes
- New
op-succinct
binary version
Based on what's included:
- Contract changes → Upgrade the
OPSuccinctL2OutputOracle
contract - New verification keys → Update
aggregationVkey
,rangeVkeyCommitment
androllupConfigHash
parameters - New binary → Upgrade Docker images
Upgrade Docker Containers
If you're using Docker, upgrade your containers to use the latest version of op-succinct
by checking out the latest release.
Docker images are not built for releases, but we support a docker compose
setup for the latest version of op-succinct
.
Upgrade Contract
- Check out the latest release of
op-succinct
from here. - Follow the instructions here to upgrade the
OPSuccinctL2OutputOracle
contract.
Note: As of release beta-v0.3.0
, the aggregationVkey
, rangeVkeyCommitment
and rollupConfigHash
are upgradeable without re-initializing the contract.
Update Contract Parameters
If you just need to update the aggregationVkey
, rangeVkeyCommitment
or rollupConfigHash
parameters and not upgrade the contract itself, follow these steps:
- Check out the latest release of
op-succinct
from here. - Follow the instructions here to update the parameters of the
OPSuccinctL2OutputOracle
contract.
Contracts
This section contains information about how to configure and deploy the OPSuccinctL2OutputOracle
contract.
Overview
The OPSuccinctL2OutputOracle
contract is a modification of the L2OutputOracle
contract that will verify SP1 proofs of the Optimism state transition function to get fully validity-proven state roots for the OP Stack rollup.
Configuration
When deploying or upgrading the OPSuccinctL2OutputOracle
contract, you will need to set the configuration parameters in your .env
file.
Required Parameters
When deploying or upgrading the OPSuccinctL2OutputOracle
contract, the following parameters are required to be set in your .env
file:
Parameter | Description |
---|---|
L1_RPC | L1 Archive Node. |
L1_BEACON_RPC | L1 Consensus (Beacon) Node. |
L2_RPC | L2 Execution Node (op-geth ). |
L2_NODE_RPC | L2 Rollup Node (op-node ). |
PRIVATE_KEY | Private key for the account that will be deploying the contract. |
ETHERSCAN_API_KEY | Etherscan API key used for verifying the contract (optional). |
Optional Advanced Parameters
You can configure additional parameters when deploying or upgrading the OPSuccinctL2OutputOracle
contract in your .env
file.
Parameter | Description |
---|---|
VERIFIER_ADDRESS | Default: Succinct's official Groth16 VerifierGateway. Address of the ISP1Verifier contract used to verify proofs. For mock proofs, this is the address of the SP1MockVerifier contract. |
STARTING_BLOCK_NUMBER | Default: The finalized block number on L2. The block number to initialize the contract from. OP Succinct will start proving state roots from this block number. |
SUBMISSION_INTERVAL | Default: 1000 . The minimum interval in L2 blocks at which checkpoints must be submitted. An aggregation proof can be posted for any range larger than this interval. |
FINALIZATION_PERIOD_SECS | Default: 3600 (1 hour). The time period (in seconds) after which a proposed output becomes finalized and withdrawals can be processed. |
PROPOSER | Default: The address of the account associated with PRIVATE_KEY . If PRIVATE_KEY is not set, address(0) . An Ethereum address authorized to submit proofs. Set to address(0) to allow permissionless submissions. Note: Use addProposer and removeProposer functions to update the list of approved proposers. |
CHALLENGER | Default: The address of the account associated with PRIVATE_KEY . If PRIVATE_KEY is not set, address(0) . Ethereum address authorized to dispute proofs. Set to address(0) for no challenging. |
OWNER | Default: The address of the account associated with PRIVATE_KEY . If PRIVATE_KEY is not set, address(0) . Ethereum address authorized to update the aggregationVkey , rangeVkeyCommitment , verifier , and rollupConfigHash parameters. Can also transfer ownership of the contract and update the approved proposers. In a production setting, set to the governance smart contract or multi-sig of the chain. |
Deploying OPSuccinctL2OutputOracle
Similar to the L2OutputOracle
contract, the OPSuccinctL2OutputOracle
is managed via an upgradeable proxy. Follow the instructions below to deploy the contract.
1. Pull the version of OPSuccinctL2OutputOracle
you want to deploy
Check out the latest release of op-succinct
from here.
2. Configure your environment
First, ensure that you have the correct environment variables set in your .env
file. See the Configuration section for more information.
3. Deploy OPSuccinctL2OutputOracle
To deploy the OPSuccinctL2OutputOracle
contract, run the following command in /contracts
.
just deploy-oracle
Optionally, you can pass the environment file you want to use to the command.
just deploy-oracle .env.example
This will deploy the OPSuccinctL2OutputOracle
contract using the parameters in the .env.example
file.
You will see the following output. The contract address that should be used is the proxy address. In the logs below, the proxy address is 0xa8A51b0a66FF2ee852a633cC2D59B6C1b47c7f00
.
% just deploy-oracle .env.example
warning: op-succinct-scripts@0.1.0: fault-proof built with release-client-lto profile at 2024-12-07 01:24:00
warning: op-succinct-scripts@0.1.0: range built with release-client-lto profile at 2024-12-07 01:24:00
warning: op-succinct-scripts@0.1.0: native_host_runner built with release profile at 2024-12-07 01:24:01
Finished `release` profile [optimized] target(s) in 0.40s
Running `target/release/fetch-rollup-config --env-file .env.example`
[⠊] Compiling...
No files changed, compilation skipped
Script ran successfully.
== Return ==
0: address 0xa8A51b0a66FF2ee852a633cC2D59B6C1b47c7f00
## Setting up 1 EVM.
==========================
Chain 11155111
Estimated gas price: 2.524425396 gwei
Estimated total gas used for script: 3225968
Estimated amount required: 0.008143715545883328 ETH
==========================
##### sepolia
✅ [Success]Hash: 0x0bdc8571277951abcc91759086d0b9e092354a14b4180b0182883a0ee2185833
Contract Address: 0xa8A51b0a66FF2ee852a633cC2D59B6C1b47c7f00
Block: 7246470
Paid: 0.0005939866343301 ETH (439035 gas * 1.35293686 gwei)
...
==========================
ONCHAIN EXECUTION COMPLETE & SUCCESSFUL.
##
Start verification for (2) contracts
Start verifying contract `0x476130149cD3828b8d8A9bb57eBf1B8A54592539` deployed on sepolia
...
Upgrading OPSuccinctL2OutputOracle
Similar to the L2OutputOracle
contract, the OPSuccinctL2OutputOracle
is managed via an upgradeable proxy. The upgrade process is the same as the L2OutputOracle
contract.
1. Decide on the target OPSuccinctL2OutputOracle
contract code
(Recommended) Using OPSuccinctL2OutputOracle
from a release
Check out the latest release of op-succinct
from here. You can always find the latest version of the OPSuccinctL2OutputOracle
on the latest release.
Manual Changes to OPSuccinctL2OutputOracle
If you want to manually upgrade the OPSuccinctL2OutputOracle
contract, follow these steps:
-
Make the relevant changes to the
OPSuccinctL2OutputOracle
contract. -
Then, manually bump the
initializerVersion
version in theOPSuccinctL2OutputOracle
contract. You will need to manually bump theinitializerVersion
version in theOPSuccinctL2OutputOracle
contract to keep track of the upgrade history.
// Original initializerVersion
uint256 public constant initializerVersion = 1;
// Increment the initializerVersion to 2.
uint256 public constant initializerVersion = 2;
2. Configure your environment
Ensure that you have the correct environment variables set in your environment file. See the Configuration section for more information.
3. Upgrade the OPSuccinctL2OutputOracle
contract
Get the address of the existing OPSuccinctL2OutputOracle
contract. If you are upgrading with an EOA ADMIN
key, you will execute the upgrade call with the ADMIN
key. If you do not have the ADMIN
key, the call below will output the raw calldata for the upgrade call, which can be executed by the "owner" in a separate context.
Upgrading with an EOA ADMIN
key
To update the L2OutputOracle
implementation with an EOA ADMIN
key, run the following command in /contracts
.
just upgrade-oracle
Upgrading with a non-EOA ADMIN
key
If the owner of the L2OutputOracle
is not an EOA (e.g. multisig, contract), set EXECUTE_UPGRADE_CALL
to false
in your .env
file. This will output the raw calldata for the upgrade call, which can be executed by the owner in a separate context.
Parameter | Description |
---|---|
EXECUTE_UPGRADE_CALL | Set to false to output the raw calldata for the upgrade call. |
Then, run the following command in /contracts
.
just upgrade-oracle
% just upgrade-oracle
warning: op-succinct-scripts@0.1.0: fault-proof built with release-client-lto profile
warning: op-succinct-scripts@0.1.0: range built with release-client-lto profile
warning: op-succinct-scripts@0.1.0: native_host_runner built with release profile
Finished `release` profile [optimized] target(s) in 0.35s
Running `target/release/fetch-rollup-config --env-file .env`
[⠊] Compiling...
Script ran successfully.
== Logs ==
The calldata for upgrading the contract with the new initialization parameters is:
0x4f1ef2860000000000000000000000007f5d6a5b55ee82090aedc859b40808103b30e46900000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000184c0e8e2a100000000000000000000000000000000000000000000000000000000000004b00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000135161100000000000000000000000000000000000000000000000000000000674107ce000000000000000000000000ded0000e32f8f40414d3ab3a830f735a3553e18e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001346d7ea10cc78c48e3da6f1890bb16cf27e962202f0f9b2c5c57f3cfb0c559ec1dca031e9fc246ec47246109ebb324a357302110de5d447af13a07f527620000000000000000000000004cb20fa9e6fdfe8fdb6ce0942c5f40d49c8986469ad6f24abc0df5e4cab37c1efae21643938ed5393389ce9e747524a59546a8785e32d5f9f902c6a46cb75cbdb083ea67b9475d7026542a009dc9d99072f4bdf100000000000000000000000000000000000000000000000000000000
## Setting up 1 EVM.
Updating OPSuccinctL2OutputOracle
Parameters
If you just need to update the aggregationVkey
, rangeVkeyCommitment
or rollupConfigHash
parameters and not upgrade the contract itself, you can use the just update-parameters
command.
The command will only update the parameters in the contract if they don't match the verification keys or the rollup config hash locally.
1. Configure your environment
First, ensure that you have the correct environment variables set in your .env
file. See the Configuration section for more information.
2. Update the parameters
If you are updating the parameters with an EOA ADMIN
key, you will execute the parameter update calls with the ADMIN
key. If you do not have the ADMIN
key, the call below will output the raw calldata for the parameter update calls, which can be executed by the "owner" in a separate context.
Updating Parameters with an EOA ADMIN
key
To update the parameters of the OPSuccinctL2OutputOracle
contract with an EOA ADMIN
key, run the following command in /contracts
.
just update-parameters
Updating Parameters with a non-EOA ADMIN
key
If the owner of the OPSuccinctL2OutputOracle
is not an EOA (e.g. multisig, contract), set EXECUTE_UPGRADE_CALL
to false
in your .env
file. This will output the raw calldata for the parameter update calls, which can be executed by the owner in a separate context.
Parameter | Description |
---|---|
EXECUTE_UPGRADE_CALL | Set to false to output the raw calldata for the parameter update calls. |
Then, run the following command in /contracts
.
just update-parameters
% just update-parameters
warning: op-succinct-scripts@0.1.0: fault-proof built with release-client-lto profile
warning: op-succinct-scripts@0.1.0: range built with release-client-lto profile
warning: op-succinct-scripts@0.1.0: native_host_runner built with release profile
Finished `release` profile [optimized] target(s) in 0.35s
Running `target/release/fetch-rollup-config --env-file .env`
[⠊] Compiling...
Script ran successfully.
== Logs ==
The calldata for upgrading the aggregationVkey is:
0xc4cb03ec005e5786785a9c61015fa1f0543831fb0e0602684473de8758496556010b1d08
The calldata for upgrading the rangeVkeyCommitment is:
0xbc91ce33472e8f9b2f650ae74c7997a3272ef5b50be834145b44cf7f1d52b58235bd6018
Modifications to Original L2OutputOracle
The original L2OutputOracle
contract can be found here.
The changes introduced in the OPSuccinctL2OutputOracle
contract are:
- The
submissionInterval
parameter is now the minimum interval in L2 blocks at which checkpoints must be submitted. An aggregation proof can be posted after this interval has passed. - The addition of the
aggregationVkey
,rangeVkeyCommitment
,verifier
,startingOutputRoot
, androllupConfigHash
parameters.startingOutputRoot
is used for initalizing the contract from an empty state, becauseop-succinct
requires a starting output root from which to prove the next state root. The other parameters are used for verifying the proofs posted to the contract. - The addition of
historicBlockHashes
to store the L1 block hashes which theop-succinct
proofs are anchored to. Whenever a proof is posted, the merkle proof verification will use these L1 block hashes to verify the state of the L2 which is posted as blobs or calldata to the L1. - The new
checkpointBlockHash
function which checkpoints the L1 block hash at a given L1 block number using theblockhash
function. - The
proposeL2Output
function now takes an additional_proof
parameter, which is the proof that is posted to the contract, and removes the unnecessary_l1BlockHash
parameter (which is redundant given thehistoricBlockHashes
mapping). This function also verifies the proof using theISP1VerifierGateway
contract. - Use an
initializerVersion
constant to track the "upgrade", rather than just the semantic version of theOPSuccinctL2OutputOracle
contract.
FAQ
How is data availability proven?
The range
program proves the correctness of an OP Stack derivation + STF for a range of blocks. The BlobProvider
verifies that the raw data (compressed L2 transaction calldata) matches the blob hash, and the ChainProvider
verifies that the blob hashes belong to a certain L1 block hash. At this point, we've verified that compressed L2 transaction calldata is available against a specific L1 block.
Because the range
program can include an arbitrary number of blocks with blobs, we supply an l1BlockHash
to the verifier. Within the range
program, we verify that the blocks from which the blobs are extracted chain up to the l1BlockHash
. This l1BlockHash
is made accessible when verifying a proof via the checkpointBlockHash
function.