Integration Guide
This section explains how to connect a native Plonky3 prover to recursive verification.
Choose a native config
The 19 built-in FRI aliases
implement FriRecursionConfig, and the two built-in WHIR aliases
implement WhirRecursionConfig. Use a matching backend and parameters that
the recursive verifier accepts; native factory validation alone does not
establish recursive admissibility. The built-in FRI integration
and WHIR integration
show how each family prepares the circuit and restores opening witnesses.
For generic random-codeword and salted FRI configs, recursion and typed import
require R: CryptoRng + SeedableRng + Send + Sync + 'static; native factory
construction itself requires only CryptoRng + SeedableRng.
For a custom PCS setup outside those aliases, implement
FriRecursionConfig
or WhirRecursionConfig
on a StarkGenericConfig wrapper. The FRI contract supplies verifier target types, matching
FRI parameters, circuit preparation, and opening witness restoration. In particular,
set_fri_private_data receives the config and an OpeningTranscript; restore each query's
Merkle path from the proof's pruned multiproof before calling set_fri_mmcs_private_data.
The trait's rustdoc and the built-in implementation show the current signature and transcript
steps. Match the native prover parameters, including query count and MMCS permutation.
Verify your AIR
AIRs implementing Plonky3's Air trait get a blanket RecursiveAir implementation from
the symbolic constraint system. If your AIR needs a manual implementation, follow the
current RecursiveAir trait, including its trace-length
and lookup-aware quotient-degree calculation. For trusted prepared uni-STARK verification,
expected_public_input_count must identify the fixed public-input width.
Wrap a native proof in RecursionInput::UniStark for one-shot recursion, or construct
TrustedPreparedSource::UniStark with the trusted config, AIR, and preprocessing commitment
for repeated verification. See the compiled prelude example
and trusted layer tests for the prepared contract.
Use FriRecursionBackend::new(challenger_config).for_extension_degree::<D>() for a
matching binomial extension, FriRecursionBackend::new_d5 for a KoalaBear
quintic suite, or WhirRecursionBackend::new(...).for_extension_degree::<D>()
for WHIR, where D is 2 or 4 and matches the input's actual challenge dimension.
See backend selection.
Import portable artifacts into trusted recursion
Use TypedArtifactVerifier<SC> when a serialized verifier and proof must enter a
TrustedPreparedLayer or TrustedPreparedAggregation. Provision the expected
verifier bytes through an independent trusted channel, choose the matching
application-owned native SC configuration, and set ArtifactLimits. The
candidate verifier must match the pinned bytes exactly and its complete built-in
configuration descriptor must match the supplied configuration; matching only
the field or suite is insufficient. The sealed PortableArtifactImport trait
exposes this import for supported built-in configurations. The
typed importer
keeps that configuration and those limits for subsequent proof imports.
use p3_recursion::artifact::{
ArtifactLimits, CanonicalStatement, ExpectedVerifierArtifact,
PortableArtifactImport, TypedArtifactVerifier,
};
let authority = TypedArtifactVerifier::<Config>::decode_with_config(
app_config,
candidate_verifier_bytes,
ExpectedVerifierArtifact::from_trusted_bytes(pinned_verifier_bytes),
ArtifactLimits::default(),
)?;
let verified = authority.import_proof(
proof_bytes,
CanonicalStatement::new(expected_statement_bytes, statement_width),
)?;
Encode expected values as canonical base-field coefficients in schema order:
little-endian 4-byte words for BabyBear/KoalaBear or 8-byte words for
Goldilocks, with statement_width == authority.schema().base_len(). The
CanonicalStatement bytes have no length prefix.
The application supplies expected_statement_bytes independently of the proof
attachment. import_proof decodes under the retained limits and verifies the
native proof against that expected statement before returning a
VerifiedArtifactProof<SC>. Its statement() and trusted_identity_bytes()
accessors report the checked statement and pinned identity. as_source() supplies
the retained verifier authority and a representative proof when preparing a
trusted owner; as_input() supplies a proof and expected statement for a
compatible prepared owner's prove call. The destination owner still checks
its own retained relation and input contract. Imported proofs own their native
data and remain usable after the input byte buffers and importer are dropped.
The caller-supplied configuration matters for hiding suites: typed import
retains its application-controlled RNG setup. Salted FRI path restoration may
construct a private, fixed-seed MMCS helper for verification; it draws no
randomness and is not exposed as the proving configuration. PortableVerifier
can verify encoded proofs but does not expose a native configuration or proving
authority. Typed import supports the library's built-in artifact codecs; the
19 FRI and two WHIR aliases have
corresponding direct recursion integrations for admissible parameters. An output proving
configuration and backend are selected separately when constructing the trusted
prepared owner. See configuration support
and transition aggregation.
The portable aggregation example runs trusted setup, proof production, aggregation, and final verification in separate processes:
cargo run --locked --release -p p3-recursion --example portable_aggregation -- setup --trusted-dir ./demo-auth
cargo run --locked --release -p p3-recursion --example portable_aggregation -- produce --out-dir ./demo-children
cargo run --locked --release -p p3-recursion --example portable_aggregation -- aggregate --trusted-dir ./demo-auth --children-dir ./demo-children --out-dir ./demo-root
cargo run --locked --release -p p3-recursion --example portable_aggregation -- verify --trusted-dir ./demo-auth --root-dir ./demo-root --expected 10,20,20,40,10
Run with fresh output directories. Setup provisions demo-auth/leaf.verifier
and demo-auth/root.verifier from a separate valid fixture, before the producer
artifacts are consumed; it does not produce the root proof. The producer writes
demo-children/leaf.verifier and four leaf-0.proof through leaf-3.proof
payloads. Aggregation checks the child verifier against the trusted leaf pin,
imports all four proofs with independently specified statements, reuses one
prepared owner for both first-level pairs, and checks its emitted
demo-root/root.verifier against the trusted root pin. Verification reads
demo-root/root.proof and uses the --expected state and count supplied by
the caller. The producer's verifier and attached proof statements are payload
data; neither establishes the trusted identity or expected root. The example's
small FRI settings are for demonstration and testing. Production parameters
require separately provisioned trusted verifier artifacts.
Custom non-primitive chips
Custom non-primitive operations must be enabled on the CircuitBuilder before use. They
need matching trace generation, preprocessing, AIR builders, and table provers. The
PcsRecursionBackend interface supplies the
preprocessor, AIR-builder, and table-prover registration hooks. Prepared owners reuse that
backend through the prepared contract.
Integration checklist
- Choose a directly integrated built-in suite and matching backend, or implement the recursive PCS contract for a custom config.
- Supply an AIR with a
RecursiveAirimplementation and fixed public-input width when using a trusted owner. - Choose a backend with the matching field, permutation, and extension degree.
- Use a prepared owner for reuse; choose a trusted prepared owner when relation and statement authority must be fixed.
- Verify output against an independently retained
CircuitVerifierand caller-expected statement.