Skip to main content

Overview

Preprocessing functions generate reusable data structures required for efficient proving and verification. The #[jolt::provable] macro generates several preprocessing functions that must be called before proving or verifying.

Preprocessing Pipeline

The preprocessing pipeline has three stages:
  1. Shared preprocessing - Common data used by both prover and verifier
  2. Prover preprocessing - Prover-specific data derived from shared preprocessing
  3. Verifier preprocessing - Verifier-specific data derived from shared preprocessing

Function Signatures

preprocess_shared

Generates shared preprocessing data from the compiled program. Parameters:
  • program - Mutable reference to the compiled guest program
Returns:
  • Shared preprocessing data containing:
    • Decoded bytecode
    • Memory layout
    • Memory initialization
    • Maximum trace length configuration

preprocess_prover

Generates prover-specific preprocessing from shared data. Parameters:
  • shared_preprocessing - The shared preprocessing output
Returns:
  • Prover preprocessing including commitment scheme generators and prover-specific state

preprocess_verifier

Generates verifier-specific preprocessing from shared data. Parameters:
  • shared_preprocessing - The shared preprocessing output
  • generators - Verifier setup for the commitment scheme (obtained from prover preprocessing)
Returns:
  • Verifier preprocessing containing all data needed for verification

verifier_preprocessing_from_prover

Convenience function to derive verifier preprocessing from prover preprocessing. Parameters:
  • prover_preprocessing - Reference to prover preprocessing
Returns:
  • Verifier preprocessing

Usage Examples

Standard Preprocessing Flow

Alternative: Deriving Verifier from Prover

Serializing Preprocessing

Preprocessing data can be serialized and saved to disk for reuse:

Memory Configuration

The preprocessing uses memory configuration attributes from the #[jolt::provable] macro:
These attributes configure the memory layout embedded in the preprocessing:
  • max_input_size - Maximum size of serialized public inputs
  • max_output_size - Maximum size of serialized outputs
  • max_trusted_advice_size - Maximum size of trusted advice
  • max_untrusted_advice_size - Maximum size of untrusted advice
  • stack_size - Guest program stack size
  • heap_size - Guest program heap size
  • max_trace_length - Maximum execution trace length

Performance Considerations

One-Time Cost

Preprocessing is a one-time cost for a given program. Once computed, the preprocessing can be reused for any number of proofs with different inputs.

Computation Time

Preprocessing time depends on:
  • Program size (bytecode length)
  • max_trace_length parameter
  • Memory configuration sizes
Typically takes seconds to minutes for moderate-sized programs.

Storage Size

Verifier preprocessing is typically much smaller than prover preprocessing, making it suitable for:
  • Embedding in verifier applications
  • Distribution to multiple verifiers
  • Long-term storage

Generated From

For a function annotated with #[jolt::provable]:
The macro generates:
  • preprocess_shared_fib
  • preprocess_prover_fib
  • preprocess_verifier_fib
  • verifier_preprocessing_from_prover_fib
  • compile - Compiles the guest program required for preprocessing
  • prove - Uses prover preprocessing to generate proofs
  • verify - Uses verifier preprocessing to verify proofs
  • memory_config - Returns the memory configuration