Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions book/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@

- [Advanced](./advanced/intro.md)
- [Cost Estimator](./advanced/cost-estimator.md)
- [Prove Scripts](./advanced/prove-scripts.md)
- [Reproduce Binaries](./advanced/verify-binaries.md)
- [Node Setup](./advanced/node-setup.md)
- [Kurtosis](./advanced/kurtosis.md)
Expand Down
174 changes: 174 additions & 0 deletions book/advanced/prove-scripts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
# Prove Scripts

The prove scripts allow you to manually generate range and aggregation proofs for OP Succinct.

## Overview

OP Succinct uses a two-tier proving architecture:

1. **Range Proofs** (`multi.rs`): Generate compressed proofs for a range of L2 blocks. These proofs verify the state transition for a specific block range.

2. **Aggregation Proofs** (`agg.rs`): Combine multiple range proofs into a single aggregation proof. This reduces on-chain verification costs by verifying one proof instead of many.

Both binaries use the SP1 network prover by default.

### When to Use Aggregation

Aggregation is useful when you need to:
- Reduce on-chain verification costs by combining multiple range proofs into one proof
- Prove larger block ranges by aggregating individual range proofs from different time periods
- Combine proofs from different proving sessions into a single proof for batch submission

> **Note:** All range proofs must be generated in compressed mode for aggregation. The prove scripts handle this automatically.

## Setup

### Environment Configuration

Create a `.env` file in the project root directory:

```bash
# RPC Endpoints
L1_RPC=<YOUR_L1_RPC_ENDPOINT>
L1_BEACON_RPC=<YOUR_L1_BEACON_RPC_ENDPOINT>
L2_RPC=<YOUR_L2_RPC_ENDPOINT>
L2_NODE_RPC=<YOUR_L2_NODE_RPC_ENDPOINT>

# Network Prover Configuration
NETWORK_PRIVATE_KEY=<YOUR_NETWORK_PRIVATE_KEY>

# Proof Strategy Configuration
RANGE_PROOF_STRATEGY=reserved # Options: reserved, hosted, auction
AGG_PROOF_STRATEGY=reserved # Options: reserved, hosted, auction
AGG_PROOF_MODE=plonk # Options: plonk, groth16
```

### Environment Variables

#### Required

| Variable | Description |
|----------|-------------|
| `L1_RPC` | L1 Archive Node endpoint |
| `L1_BEACON_RPC` | L1 Consensus (Beacon) Node endpoint |
| `L2_RPC` | L2 Execution Node (`op-geth`) endpoint |
| `L2_NODE_RPC` | L2 Rollup Node (`op-node`) endpoint |
| `NETWORK_PRIVATE_KEY` | Private key for the Succinct Prover Network. See the [Succinct Prover Network Quickstart](https://docs.succinct.xyz/docs/sp1/prover-network/quickstart) for setup instructions. |

#### Optional

| Variable | Description | Default |
|----------|-------------|---------|
| `RANGE_PROOF_STRATEGY` | Proof fulfillment strategy for range proofs | `reserved` |
| `AGG_PROOF_STRATEGY` | Proof fulfillment strategy for aggregation proofs | `reserved` |
| `AGG_PROOF_MODE` | Proof mode for aggregation proofs (`plonk` or `groth16`) | `plonk` |

**Proof Strategies:**
- `reserved`: Uses reserved SP1 network capacity
- `hosted`: Uses hosted proof generation service
- `auction`: Uses auction-based proof fulfillment

**Proof Modes:**
- `plonk`: PLONK proof system (default)
- `groth16`: Groth16 proof system

### Getting Started with the Prover Network

1. Follow the [Succinct Prover Network Quickstart](https://docs.succinct.xyz/docs/sp1/prover-network/quickstart) to set up your account and obtain a private key.

2. Set the `NETWORK_PRIVATE_KEY` environment variable:
```.env
NETWORK_PRIVATE_KEY=0x...
```

3. Run the prove scripts. The binaries will automatically use the network prover with your configured key.

## Generating Range Proofs

The `multi.rs` binary generates compressed range proofs for a specified block range. These proofs verify the state transition function for the L2 blocks in the range.

### Usage

```bash
cargo run --bin multi --release -- \
--start <START_BLOCK> \
--end <END_BLOCK> \
--prove
```

### Example

```bash
# Generate a compressed range proof for blocks 1000-1300
cargo run --bin multi --release -- \
--start 1000 \
--end 1300 \
--prove
```

The proof will be generated in compressed mode, which is required for aggregation.

### Output

Range proofs are saved to `data/{chain_id}/proofs/{start_block}-{end_block}.bin`

## Generating Aggregation Proofs

The `agg.rs` binary aggregates multiple compressed range proofs into a single aggregation proof. This allows you to verify the state transition for a large block range with a single on-chain verification.

### How Aggregation Works

1. The binary loads the specified range proofs from `data/fetched_proofs/`
2. Each range proof is verified to ensure validity
3. The proofs are aggregated into a single proof that attests to the entire block range
4. The aggregation proof can be submitted on-chain for efficient verification

### Usage

```bash
cargo run --bin agg --release -- \
--proofs <PROOF_1>,<PROOF_2>,<PROOF_N> \
--prover <PROVER_ADDRESS> \
--prove
```

### Example

```bash
# Aggregate three consecutive range proofs covering blocks 1000-1900
cargo run --bin agg --release -- \
--proofs 1000-1300,1300-1600,1600-1900 \
--prover 0x1234567890abcdef1234567890abcdef12345678 \
--prove
```

This will generate a single aggregation proof that verifies the state transition from block 1000 to 1900.

### Parameters

| Parameter | Description | Required |
|-----------|-------------|----------|
| `--proofs` | Comma-separated list of proof names (without `.bin` extension) | Yes |
| `--prover` | Prover wallet address included in the aggregation proof | Yes |
| `--prove` | Generate proof (omit to only execute and verify inputs) | No |
| `--env-file` | Path to environment file (default: `.env`) | No |

### Requirements

- Proof files must exist in `data/fetched_proofs/` directory
- Proof names should match the range format: `{start_block}-{end_block}`
- Range proofs must be consecutive (e.g., 1000-1300, 1300-1600, 1600-1900)
- All range proofs are automatically verified before aggregation

## Local Development

For local development and testing, omit the `--prove` flag to execute the program without generating proofs. This allows you to verify correctness without incurring proving costs.

```bash
# Execute without proving
cargo run --bin multi --release -- \
--start 1000 \
--end 1300
```

This will run the full execution and report cycle counts without submitting proof requests to the network.
37 changes: 31 additions & 6 deletions scripts/prove/bin/agg.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
use std::{env, fs};

use alloy_primitives::{Address, B256};
use anyhow::Result;
use cargo_metadata::MetadataCommand;
use clap::Parser;
use op_succinct_client_utils::{boot::BootInfoStruct, types::u32_to_u8};
use op_succinct_elfs::AGGREGATION_ELF;
use op_succinct_host_utils::{fetcher::OPSuccinctDataFetcher, get_agg_proof_stdin};
use op_succinct_host_utils::{
fetcher::OPSuccinctDataFetcher, get_agg_proof_stdin, network::parse_fulfillment_strategy,
};
use op_succinct_proof_utils::get_range_elf_embedded;
use sp1_sdk::{
utils, HashableKey, Prover, ProverClient, SP1Proof, SP1ProofWithPublicValues, SP1VerifyingKey,
utils, HashableKey, Prover, ProverClient, SP1Proof, SP1ProofMode, SP1ProofWithPublicValues,
SP1VerifyingKey,
};
use std::fs;

#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
Expand Down Expand Up @@ -63,7 +67,14 @@ fn load_aggregation_proof_data(
(proofs, boot_infos)
}

// Execute the OP Succinct program for a single block.
/// Aggregates multiple range proofs into a single proof.
///
/// This binary takes multiple compressed range proofs and aggregates them into a single
/// aggregation proof. This is useful for:
/// - Reducing on-chain verification costs by combining multiple proofs into one
/// - Proving larger block ranges by aggregating individual range proofs
///
/// Note: All input range proofs must be in compressed format for aggregation to work.
#[tokio::main]
async fn main() -> Result<()> {
utils::setup_logger();
Expand All @@ -72,7 +83,7 @@ async fn main() -> Result<()> {

dotenv::from_filename(args.env_file).ok();

let prover = ProverClient::from_env();
let prover = ProverClient::builder().network().build();
let fetcher = OPSuccinctDataFetcher::new_with_rollup_config().await?;

let (_, vkey) = prover.setup(get_range_elf_embedded());
Expand All @@ -92,7 +103,21 @@ async fn main() -> Result<()> {
println!("Aggregate ELF Verification Key: {:?}", agg_vk.vk.bytes32());

if args.prove {
prover.prove(&agg_pk, &stdin).groth16().run().expect("proving failed");
let agg_proof_mode =
if env::var("AGG_PROOF_MODE").unwrap_or_else(|_| "plonk".to_string()).to_lowercase() ==
"groth16"
{
SP1ProofMode::Groth16
} else {
SP1ProofMode::Plonk
};

prover
.prove(&agg_pk, &stdin)
.mode(agg_proof_mode)
.strategy(parse_fulfillment_strategy(env::var("AGG_PROOF_STRATEGY")?))
.run()
.expect("proving failed");
} else {
let (_, report) = prover
.execute(AGGREGATION_ELF, &stdin)
Expand Down
31 changes: 23 additions & 8 deletions scripts/prove/bin/multi.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
use std::{env, fs, sync::Arc, time::Instant};

use anyhow::{Context, Result};
use clap::Parser;
use op_succinct_host_utils::{
block_range::get_validated_block_range, fetcher::OPSuccinctDataFetcher, host::OPSuccinctHost,
stats::ExecutionStats, witness_generation::WitnessGenerator,
network::parse_fulfillment_strategy, stats::ExecutionStats,
witness_generation::WitnessGenerator,
};
use op_succinct_proof_utils::{get_range_elf_embedded, initialize_host};
use op_succinct_prove::{execute_multi, DEFAULT_RANGE};
use op_succinct_scripts::HostExecutorArgs;
use sp1_sdk::{utils, ProverClient};
use std::{fs, sync::Arc, time::Instant};
use sp1_sdk::{utils, Prover, ProverClient};
use tracing::debug;

/// Execute the OP Succinct program for multiple blocks.
/// Generates a compressed range proof for a block range.
///
/// This binary generates a compressed SP1 proof that verifies the state transition
/// for a range of L2 blocks. The compressed proof format is required for aggregation.
///
/// The proof verifies that the rollup's state transition function was correctly executed
/// for all blocks in the specified range.
#[tokio::main]
async fn main() -> Result<()> {
let args = HostExecutorArgs::parse();
Expand Down Expand Up @@ -46,13 +54,20 @@ async fn main() -> Result<()> {
// Get the stdin for the block.
let sp1_stdin = host.witness_generator().get_sp1_stdin(witness_data)?;

let prover = ProverClient::from_env();

if args.prove {
// If the prove flag is set, generate a proof.
let prover = ProverClient::builder().network().build();

let (pk, _) = prover.setup(get_range_elf_embedded());
// Generate proofs in compressed mode for aggregation verification.
let proof = prover.prove(&pk, &sp1_stdin).compressed().run().unwrap();

// Generate a compressed range proof. Note that the compressed proof type is required
// for aggregation.
let proof = prover
.prove(&pk, &sp1_stdin)
.compressed()
.strategy(parse_fulfillment_strategy(env::var("RANGE_PROOF_STRATEGY")?))
.run()
.unwrap();

// Create a proof directory for the chain ID if it doesn't exist.
let proof_dir = format!("data/{}/proofs", data_fetcher.get_l2_chain_id().await.unwrap());
Expand Down
Loading