Deferral
The deferral extension enables guest programs to offload expensive computations to standalone circuits that are proven separately during the aggregation phase. Rather than executing the computation inside the VM, the guest issues a deferred call that records an input commitment and receives an output commitment back. The actual computation is proven outside the VM and linked back via cryptographic accumulators.
This is particularly useful for recursive STARK verification, where verifying a proof inside the VM would be prohibitively expensive. See the Verify STARK guest library for the primary use case.
For the full technical specification, see the Deferral Framework spec.
How It Works
- The guest program calls
deferred_compute, passing an input commitment (a 32-byte hash identifying the input). The VM records this commitment and returns an output key containing the output commitment and output length. - The guest allocates a buffer based on the output length from the output key, then calls
get_deferred_outputto have the VM write the raw output bytes into that buffer. - During aggregation, each deferred computation is independently proven by its corresponding deferral circuit, and the accumulators are reconciled with the VM's final memory state.
From the guest's perspective, the deferral acts like a black-box function call: given an input commitment, it produces a verified output. The guest never sees the proof or the raw input — only the commitments and the output.
Guest Library
The guest crate openvm-deferral-guest provides the following functions:
deferred_compute
pub fn deferred_compute<const DEFERRAL_IDX: u16>(input_commit: &Commit) -> OutputKeyIssues a deferred call at compile-time deferral index DEFERRAL_IDX. Returns an OutputKey containing the output commitment and length.
get_deferred_output
pub fn get_deferred_output<const DEFERRAL_IDX: u16>(output: &mut [u8], output_key: &OutputKey)Retrieves the raw output bytes for a previous deferred call. The caller must allocate a buffer of exactly output_key.output_len bytes.
Types
Commit = [u8; 32]— a 32-byte commitment used as input/output identifierOutputKey { output_commit: Commit, output_len: u64 }— returned bydeferred_compute, passed toget_deferred_output
DEFERRAL_IDX is a compile-time constant that identifies which deferral circuit to invoke. A VM configuration can support up to 1024 deferral circuits. Each index corresponds to a specific DeferralFn registered in the DeferralExtension.
Configuration
The deferral extension cannot be configured via openvm.toml alone — it requires programmatic setup through the SDK because each deferral circuit needs a DeferralFn (the function that computes outputs from inputs) and corresponding proving infrastructure.
To enable deferrals in your VM configuration:
- Build a
DeferralProverwith the appropriate single-circuit prover for your use case. - Create the extension with
DeferralProver::make_extension, passing the deferral function(s). - Set
SdkVmConfig.deferral = Some(deferral_ext). - Build the SDK with
Sdk::builder().deferral_prover(deferral_prover).
See the Verify STARK guest library for a complete example of wiring up the deferral extension with the STARK verification circuit.