Documentation Index
Fetch the complete documentation index at: https://mintlify.com/a16z/jolt/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The verification functions allow you to verify that a zero-knowledge proof is valid. The #[jolt::provable] macro generates two verification-related functions:
build_verifier_<function_name> - Creates a reusable verifier closure (recommended)
- Internal verification logic used by the verifier closure
Function Signature
build_verifier
pub fn build_verifier_<function_name>(
preprocessing: jolt::JoltVerifierPreprocessing<jolt::F, jolt::PCS>,
) -> impl Fn(
// ... public inputs
output: ReturnType,
panic: bool,
// Optional: trusted_advice_commitment (if function has trusted advice)
proof: jolt::RV64IMACProof,
) -> bool + Sync + Send
Parameters
Preprocessing:
preprocessing - Verifier preprocessing data (obtained from preprocess_verifier_<function_name>)
Verifier Closure Parameters:
- Public inputs - The same public inputs provided to the prover
output - The claimed output value
panic - Whether the program panicked during execution
trusted_advice_commitment (optional) - Commitment to trusted advice, if present
proof - The zero-knowledge proof to verify
Return Value
Returns true if the proof is valid, false otherwise.
Verification Process
The verifier:
- Reconstructs the expected I/O device state from public inputs and claimed outputs
- Verifies the proof against the preprocessing data
- Checks that all constraints are satisfied
- Returns a boolean indicating validity
Usage Examples
Basic Verification
use std::time::Instant;
// Setup: compile and preprocess (typically done once)
let target_dir = "/tmp/jolt-guest-targets";
let mut program = guest::compile_fib(target_dir);
let shared_preprocessing = guest::preprocess_shared_fib(&mut program);
let prover_preprocessing = guest::preprocess_prover_fib(shared_preprocessing.clone());
let verifier_setup = prover_preprocessing.generators.to_verifier_setup();
let verifier_preprocessing = guest::preprocess_verifier_fib(
shared_preprocessing,
verifier_setup,
);
// Build verifier and prover
let prove_fib = guest::build_prover_fib(program, prover_preprocessing);
let verify_fib = guest::build_verifier_fib(verifier_preprocessing);
// Prove
let input = 50;
let (output, proof, io_device) = prove_fib(input);
// Verify
let is_valid = verify_fib(input, output, io_device.panic, proof);
println!("Proof is valid: {}", is_valid);
assert!(is_valid);
let a = vec![1usize, 2, 3, 4, 5];
let b = vec![0usize, 1, 2, 3, 4, 5, 6, 7, 8, 9];
let n = 221u8;
// Generate proof
let (output, proof, io_device) = prove_advice_demo(n, a.clone(), b.clone());
// Verify with the same inputs
let is_valid = verify_advice_demo(
n,
a,
b,
output,
io_device.panic,
proof,
);
assert!(is_valid);
With Trusted Advice
let public_input = 42;
let trusted_data = vec![1, 2, 3, 4, 5];
// Prover commits to trusted advice
let (commitment, hint) = guest::commit_trusted_advice_my_function(
trusted_data.clone(),
&prover_preprocessing,
);
// Generate proof
let (output, proof, io_device) = prove_my_function(
program,
prover_preprocessing,
public_input,
trusted_data,
commitment,
hint,
);
// Verifier only needs the commitment (not the trusted data)
let is_valid = verify_my_function(
public_input,
output,
io_device.panic,
commitment,
proof,
);
assert!(is_valid);
Preprocessing Conversion
You can obtain verifier preprocessing from prover preprocessing:
// From prover preprocessing
let verifier_preprocessing = guest::verifier_preprocessing_from_prover_fib(
&prover_preprocessing
);
// Or from shared preprocessing + verifier setup
let verifier_setup = prover_preprocessing.generators.to_verifier_setup();
let verifier_preprocessing = guest::preprocess_verifier_fib(
shared_preprocessing,
verifier_setup,
);
Generated From
For a function annotated with #[jolt::provable]:
#[jolt::provable]
fn fib(n: u32) -> u32 {
// implementation
}
The macro generates build_verifier_fib that creates verification closures.
Important Notes
- The verifier is deterministic - the same inputs and proof always produce the same result
- The verifier is thread-safe (
Sync + Send) and can be used concurrently
- Verification is typically much faster than proof generation
- The verifier does not need access to trusted advice data, only its commitment
- The
panic flag from io_device.panic must be passed to the verifier
prove - Generates proofs that can be verified
preprocess - Generates preprocessing data for verification
analyze - Analyzes execution without generating a proof