Skip to main content
The #[jolt::advice] macro enables functions to compute values outside the zkVM and provide them as advice to the guest program. This allows expensive computations to run in native code while the guest only verifies the results.

Overview

Advice functions operate in two modes:
  1. Compute mode (compute_advice feature enabled): Executes the function body and writes the result to the advice tape
  2. Consume mode (default): Reads the pre-computed result from the advice tape
This dual compilation enables a two-pass proving strategy where expensive computations happen outside the proof.

Basic Usage

Requirements

required
Must be jolt::UntrustedAdvice<T> where T implements AdviceTapeIO.
required
Must be immutable. No mut bindings or &mut references allowed.
required
The function body computes the advice value. Should return UntrustedAdvice::new(value) or just value (automatic wrapping).

Supported Types

Types that implement AdviceTapeIO can be used as advice:

Built-in Types

  • Primitive integers: u8, u16, u32, u64, usize, i8, i16, i32, i64
  • Arrays: [T; N] where T: Pod
  • Tuples: (A, B), (A, B, C), … up to 7 elements (where each implements AdviceTapeIO)
  • Vectors: Vec<T> where T: Pod (requires std or guest-std feature)

Custom Types

Implement AdviceTapeIO manually:
Or use bytemuck for POD types:

Examples

Integer Factorization

Subset Index Finding

Custom Struct with Nested Types

How It Works

Two-Pass Compilation

The #[jolt::provable] macro compiles the guest program twice:
  1. First pass (compute_advice feature): Advice functions execute their bodies and populate the advice tape
  2. Second pass (normal): Advice functions read pre-computed values from the tape
This is handled automatically by the generated prove_* functions.

Macro Expansion

The #[jolt::advice] macro expands to:

Best Practices

Always Verify Advice

Advice is untrusted input from the prover. Always verify it satisfies the required constraints:

Use References for Large Inputs

Advice functions can take references to avoid copying:

Size Considerations

Set max_untrusted_advice_size in #[jolt::provable] large enough for all advice values:

Limitations

  • Parameters must be immutable (no mut or &mut)
  • Return type must be UntrustedAdvice<T> where T: AdviceTapeIO
  • The function body is only executed during the first pass (with compute_advice feature)
  • Reading beyond the advice tape length causes a runtime error during proof generation