Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/risc0/risc0/llms.txt

Use this file to discover all available pages before exploring further.

risc0-groth16

The risc0-groth16 crate implements a Groth16 SNARK verifier over the BN254 elliptic curve and provides functionality to convert RISC Zero STARK proofs into Groth16 SNARKs for efficient on-chain verification.

Installation

[dependencies]
risc0-groth16 = "1.3.0"

Overview

Groth16 proofs are much smaller and faster to verify than STARK proofs, making them ideal for blockchain applications. This crate allows you to:
  1. Verify existing Groth16 proofs
  2. Convert STARK proofs to Groth16 SNARKs (“shrink wrap”)
The prove feature requires an x86 architecture and Docker installation. See the installation guide for setup.

Feature Flags

prove
feature
Enables STARK-to-SNARK transformation.
  • Implies: std
  • Requirements: x86 architecture, Docker
cuda
feature
Enables CUDA GPU acceleration for proof generation.
  • Implies: prove
std
feature
Enables standard library support (enabled by default).

Types

Verifier

Verifier
struct
Groth16 proof verifier.
pub struct Verifier {
    // ...
}

impl Verifier {
    pub fn from_json(
        proof: ProofJson,
        public_inputs: PublicInputsJson,
        verifying_key: VerifyingKeyJson,
    ) -> Result<Self>;
    
    pub fn verify(&self) -> Result<()>;
}

ProofJson

ProofJson
struct
JSON representation of a Groth16 proof.
#[derive(Serialize, Deserialize)]
pub struct ProofJson {
    pub a: Vec<String>,
    pub b: Vec<Vec<String>>,
    pub c: Vec<String>,
}
Format: Ethereum-compatible JSON with hex-encoded field elements

VerifyingKeyJson

VerifyingKeyJson
struct
JSON representation of a Groth16 verifying key.
#[derive(Serialize, Deserialize)]
pub struct VerifyingKeyJson {
    pub alpha: Vec<String>,
    pub beta: Vec<Vec<String>>,
    pub gamma: Vec<Vec<String>>,
    pub delta: Vec<Vec<String>>,
    pub ic: Vec<Vec<String>>,
}

PublicInputsJson

PublicInputsJson
struct
JSON representation of public inputs.
#[derive(Serialize, Deserialize)]
pub struct PublicInputsJson {
    pub values: Vec<String>,
}

Seal

Seal
struct
Binary Groth16 seal for efficient verification.
pub struct Seal {
    pub a: G1Affine,
    pub b: G2Affine,
    pub c: G1Affine,
}

VerifyingKey

VerifyingKey
struct
Binary Groth16 verifying key.
pub struct VerifyingKey {
    pub alpha: G1Affine,
    pub beta: G2Affine,
    pub gamma: G2Affine,
    pub delta: G2Affine,
    pub ic: Vec<G1Affine>,
}

Verification Functions

verifying_key

verifying_key
function
Get the RISC Zero Groth16 verifying key.
pub fn verifying_key() -> &'static VerifyingKey
Returns: The global RISC Zero Groth16 verifying key

Proving Functions (with prove feature)

prove::shrink_wrap

shrink_wrap
function
Convert a STARK receipt to a Groth16 SNARK.
#[cfg(feature = "prove")]
pub fn shrink_wrap(
    receipt: &Receipt,
) -> Result<Groth16Receipt>
Parameters:
  • receipt: RISC Zero STARK receipt
Returns: Groth16 receipt with compressed proofRequirements:
  • Docker must be installed and running
  • x86_64 architecture
  • ~16GB RAM
  • Several minutes of proving time

Examples

Verifying a Groth16 Proof

use risc0_groth16::{ProofJson, PublicInputsJson, Verifier, VerifyingKeyJson};

fn verify_proof() -> Result<()> {
    // Load JSON data
    let vk_json: VerifyingKeyJson = serde_json::from_str(&vk_data)?;
    let proof_json: ProofJson = serde_json::from_str(&proof_data)?;
    let inputs_json = PublicInputsJson {
        values: serde_json::from_str(&inputs_data)?,
    };
    
    // Create verifier and verify
    let verifier = Verifier::from_json(
        proof_json,
        inputs_json,
        vk_json,
    )?;
    
    verifier.verify()?;
    println!("Proof verified successfully!");
    Ok(())
}

STARK to SNARK Conversion

use risc0_zkvm::{default_prover, ExecutorEnv, ProverOpts, ReceiptKind};
use risc0_groth16::prove::shrink_wrap;

fn prove_groth16() -> Result<()> {
    // Generate STARK receipt
    let env = ExecutorEnv::builder()
        .write(&input)?
        .build()?;
    
    let prover = default_prover();
    let stark_receipt = prover.prove(env, elf)?;
    
    // Convert to Groth16
    let groth16_receipt = shrink_wrap(&stark_receipt)?;
    
    // Much smaller proof!
    println!("STARK size: {} bytes", stark_receipt.journal.bytes.len());
    println!("Groth16 size: {} bytes", groth16_receipt.seal.len());
    
    Ok(())
}

Direct Groth16 Generation

use risc0_zkvm::{default_prover, ExecutorEnv, ProverOpts, ReceiptKind};

fn prove_groth16_directly() -> Result<()> {
    let env = ExecutorEnv::builder()
        .write(&input)?
        .build()?;
    
    // Specify Groth16 receipt kind
    let opts = ProverOpts::groth16();
    
    let prover = default_prover();
    let receipt = prover.prove_with_opts(env, elf, &opts)?;
    
    // Receipt is already Groth16
    println!("Generated Groth16 receipt");
    Ok(())
}

On-Chain Verification (Solidity)

// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.20;

import {Groth16Verifier} from "risc0-groth16-verifier.sol";

contract MyContract {
    Groth16Verifier public verifier;
    
    function verify(
        uint256[2] memory a,
        uint256[2][2] memory b,
        uint256[2] memory c,
        uint256[] memory publicInputs
    ) public view returns (bool) {
        return verifier.verify(a, b, c, publicInputs);
    }
}

Performance Comparison

Proof TypeSizeVerification TimeGeneration Time
STARK~200 KB~10-50 msSeconds
Groth16~1 KB~1-2 msMinutes
Groth16 takes longer to generate but is much smaller and faster to verify.

Elliptic Curve

The crate uses the BN254 (alt_bn128) elliptic curve:
  • Field: 254-bit prime field
  • Pairing-friendly: Supports efficient pairing operations
  • EVM-compatible: Native support in Ethereum via precompiles

JSON Format

The JSON formats are compatible with Ethereum:
{
  "proof": {
    "a": ["0x...", "0x..."],
    "b": [["0x...", "0x..."], ["0x...", "0x..."]],
    "c": ["0x...", "0x..."]
  },
  "publicInputs": {
    "values": ["0x...", "0x..."]
  }
}

Docker Requirements

For STARK-to-SNARK conversion, ensure Docker is configured:
# Check Docker installation
docker --version

# Pull the required image (done automatically)
# docker pull risc0/groth16-prover:latest

Installation for Proving

See the detailed installation guide for setting up the Groth16 prover.