Miden prover
This crate proves post-execution witnesses produced by the
Miden processor using Plonky3. The
synchronous Prover does not execute programs: it consumes ExecutionWitness values and borrows
PrecompileWitness values.
Usage
Prover is synchronous and consumes post-execution witnesses:
Prover::prove(ExecutionWitness)proves the VM portion and returnsCompletewhen there is no deferred work, orDeferredcarrying a passiveDeferredStateWire.Prover::prove_full(ExecutionWitness)proves the VM and any precompile work locally.Prover::prove_precompile(&PrecompileWitness)proves one hydrated singleton or merged witness.
Use Prover::with_hash_fn to select the proof hash function.
Tracing must be selected before execution starts. Ordinary FastProcessor::execute* calls use a
no-op tracer and return ExecutionOutput, which cannot be promoted to ExecutionWitness after the
run because it contains no replay data. Call FastProcessor::execute_for_proving* when the result
will be passed to Prover.
Deferred precompile workflow
use ;
use Verifier;
use precompile_witness_from_wire;
// `witness` is an ExecutionWitness produced by FastProcessor.
let claim = witness.claim;
let prover = new;
let deferred = prover.prove?;
// Passively transport the proof, then decode it without a registry.
let bytes = deferred.to_bytes;
let transported = read_from_bytes?;
let Deferred = &transported else ;
// Hydration installs the bundled registry only when precompile proving begins.
let precompile_witness = precompile_witness_from_wire?;
let precompile_proof = prover.prove_precompile?;
let complete = transported.complete?;
let outcome = new.verify?;
assert!;
To share precompile proving across several deferred proofs, hydrate each transported wire, merge the
singleton witnesses with PrecompileWitness::merge, and call prove_precompile once. Attach the
resulting PrecompileProof to each deferred proof with complete, then verify each completed
proof.
complete performs only the deferred-to-complete lifecycle transition; it does not check artifact
compatibility.
Transport, hydration, structural validity, and fixed limits are specified in the deferred-proof semantics.
Synchronous execution and proving
The FastProcessor-backed prove_sync(&Prover, ...) function is the direct synchronous path for
executing and fully proving a program. When enabled in ExecutionOptions, it overlaps execution
with hasher trace construction when a Rayon worker is available. A caller with no separate Rayon
worker uses compact buffered replay. Proof generation remains configured on Prover.
STARK Backend
The prover uses Plonky3, a modular STARK proving framework.
STARK configurations are defined in the miden-air crate and shared between the prover and
verifier, ensuring consistency across the system.
Hash Function Selection
Different hash functions offer different tradeoffs:
BLAKE3 and Keccak provide faster proving, but they are not efficient for recursion. RPO256, Poseidon2, and RPX256 prove more slowly but support efficient recursive verification in Miden VM.
Crate features
Miden prover can be compiled with the following features:
The std feature is enabled by default and relies on the Rust standard library. The concurrent
feature implies std and also enables multi-threaded proof generation. A no_std build does not
rely on the Rust standard library and can compile to WebAssembly. Only the
wasm32-unknown-unknown and wasm32-wasip1 targets are officially supported.
To compile with no_std, disable default features via --no-default-features flag.
Concurrent proof generation
When compiled with the concurrent feature enabled, the prover generates STARK proofs using
multiple threads. For the benefits of concurrent proof generation, see these
benchmarks.
Internally, we use rayon for parallel computations. Use the
RAYON_NUM_THREADS environment variable to control the number of threads used to generate a STARK
proof.
License
This project is dual-licensed under the MIT and Apache 2.0 licenses.