Skip to main content
The #[jolt::provable] macro is the primary way to create provable functions in Jolt. It transforms a regular Rust function into a full zkVM program with generated host-side proving and verification infrastructure.

Basic Usage

This generates several host-side functions:
  • compile_fibonacci(target_dir) - Compiles guest to RISC-V
  • preprocess_shared_fibonacci(program) - Shared preprocessing
  • preprocess_prover_fibonacci(shared) - Prover-specific preprocessing
  • preprocess_verifier_fibonacci(shared, generators) - Verifier-specific preprocessing
  • build_prover_fibonacci(program, preprocessing) - Returns proving closure
  • build_verifier_fibonacci(preprocessing) - Returns verification closure
  • prove_fibonacci(...) - Direct proof generation
  • analyze_fibonacci(...) - Program analysis without proving

Parameters

The macro accepts configuration parameters:

Memory Configuration

Memory sizes must be powers of 2 or the linker will fail. These values determine the guest’s memory layout.

Trace Configuration

The trace length affects:
  • Maximum program complexity
  • Preprocessing time
  • Proof generation time

Development Features

Backtraces and debug profiles increase guest binary size and execution time. Use only during development.

Function Signatures

Public Inputs

Regular parameters become public inputs to the proof:
Both data and expected_hash are public inputs that must be provided by both prover and verifier.

Trusted Advice

Wrap parameters in TrustedAdvice<T> to mark them as committed advice:
The prover commits to trusted advice before seeing the challenge. The verifier receives only the commitment.

Untrusted Advice

Wrap parameters in UntrustedAdvice<T> for witness data:
Untrusted advice is provided by the prover but must be verified by the guest.
See Runtime Advice for the difference between trusted and untrusted advice.

Return Values

Return values become public outputs:
Both prover and verifier know the output value. For private outputs, write to trusted advice instead.

Generated Functions

The macro generates a complete proving/verification workflow:

Compilation

Compiles the guest function to RISC-V ELF binary. The binary is cached in the target directory.

Preprocessing

Preprocessing happens in phases:
See Preprocessing for details.

Building Closures

Create reusable proving/verification closures:

Direct Proving

For one-off proofs:

Analysis

Analyze program execution without generating a proof:

Complete Example

Guest (guest/src/lib.rs):
Host (src/main.rs):

Best Practices

Overallocation wastes proving time. Measure actual usage with analyze_* before finalizing limits.
Large public inputs increase verification time. Use advice for large witness data.
Don’t pass secrets as public inputs. Use TrustedAdvice<T> instead.
Preprocessing is expensive. Reuse the same preprocessing for multiple proofs of the same program.

Limitations

  • Function must have a determinate signature (no generics in macro itself)
  • All types must implement Serialize + Deserialize (via postcard)
  • Advice types must implement AdviceTapeIO
  • Function cannot be async or have special ABIs