feat: compress aggregate roots with SP1 - #602
Open
johnchandlerburnham wants to merge 2 commits into
Open
Conversation
johnchandlerburnham
force-pushed
the
jcb/sp1-compressor
branch
from
August 30, 2026 20:00
d04be4c to
b0b0172
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stack
This PR is stacked on
jcb/aggregate-firstand should target that branch:The base PR supplies the complete shard-to-root pipeline and persists one
uniform 18-word
ix_aggrouter claim. This PR adds only the terminalcompression layer: it verifies that one Aiur Multi-STARK root inside SP1 and
uses SP1's stock recursion tail to produce a final Groth16 or Plonk SNARK.
Reviewers do not need to re-review shard planning, structural joins, cache
resume, or the converged
ix_aggrcircuit in this PR. Conversely, this PRdoes not re-run the Lean kernel inside SP1 and does not feed individual shard
proofs to SP1.
Summary
The connector has three deliberately separate responsibilities:
a persisted
Ixon.Proof, rejecting anything that is not an eligibleCheckEnvroot.invokes the requested SP1 stage, verifies the resulting SP1 proof, and
independently checks its public values.
verification is the check attested by the terminal proof; the host
preflight is only an early error and cost guard.
Fixed public statement
The guest commits exactly 224 bytes:
IXROOT01protocol separatoru64valuesThe compact Multi-STARK proof is private witness data. Proof validity is
existentially attested for the exact verifying key, FRI parameters, and outer
claim bound into the public statement. Omitting the proof bytes from public
values avoids exposing or hashing a large, revision-sensitive encoding while
still pinning the statement it proves.
Both host and guest enforce:
verifying key; and
Integrated command
ix compress-root ROOT_ADDRESSreads one persisted aggregate wrapper fromthe Ix store, rebuilds the current recursion backend and allowed-system blob,
derives the uniform outer claim from the wrapper's
CheckEnv, and passes theresult to the SP1 connector.
Supported modes are
execute,core,compressed,groth16, andplonk;the CLI defaults to
groth16.--outputsaves the verified SP1 SDK proofcontainer. For Groth16 or Plonk,
--onchain-outputadditionally saves the rawproof bytes expected by an onchain verifier.
Final compression is intentionally a closure boundary:
CheckEnvroot;CheckEnvwrapper is rejected;--allow-open-rootexists only for--mode execute, allowing profiling ona retained-subtree fixture without permitting a misleading terminal proof.
Build and dependency isolation
SP1 remains opt-in so ordinary Ix builds do not compile or link the SDK:
IX_SP1=1enables the CPU connector;IX_SP1_CUDA=1enables it with the SDK's CUDA support;sp1-compressis a separate host workspace using the Succinct toolchain;and
sp1-compress/guestis a separate zkVM guest workspace with its own lockeddependency graph.
The root, host, and guest dependency graphs are synchronized at the protocol
boundary:
multi-starkis pinned to2892243e674f9a0b3aca9004a8d00c79a23beec1everywhere;261741a90e6e5e637a4dae7c00a501d63b90349c; andd36366f7badbff9be8e2522868dddd14561638f3.Aiur proof and verifying-key wire formats are revision-sensitive. These pins,
the host/guest codecs, and all three lockfiles must move together.
What lands
Guest and protocol boundary:
parameters, the exact 18-word outer claim, and one compact proof.
fixed-width public-value commit.
Rust and the zkVM guest.
boundary.
Host connector:
execute,core,compressed,groth16, andplonkexecution paths.raw onchain proof encoding.
execution, proof verification, and public-value agreement without needing
a large production aggregate fixture.
Ix integration:
ix compress-rootwith persisted-root loading, deterministic backendreconstruction, claim derivation, mode selection, and output flags.
open-root and wrong-claim cases.
builds unchanged.
verify a serialized proof outside the original in-process prover path.
Trust and safety properties
full Aiur verification and only then commits public values.
the expected 224 bytes, preventing accidental acceptance of a proof for a
differently encoded statement.
recursion verifier configuration.
closed
CheckEnvstatement established by the base PR.with another SP1 program or future statement format.
invalid proofs, open roots, and non-
CheckEnvwrappers fail closed.Current limitation
WITHOUT_VK_VERIFICATION=1is currently required for proof generation. TheSP1 fork used here adds Blake3 recursion shapes that are not yet represented
in its distributed recursion-verifying-key map. Execute mode does not require
the setting.
This escape hatch affects SP1's artifact-generation key-map check; it does
not bypass Aiur verification in either the native host or the SP1 guest, and
the host still verifies the final SP1 proof and its public values. It should
nonetheless be removed before treating the path as production-ready.
A real persisted production
ix_aggrroot has not yet been executed throughthe terminal, and GPU Groth16/Plonk generation has not yet been benchmarked.
The synthetic smoke below validates connector correctness and wire
compatibility only; it is not a cost estimate for the much larger production
recursion key and proof.
Validation
The rebased stack passes:
cargo check --release --locked --workspace --all-targetswith theproduction
parallel,net,test-ffifeatures.cargo clippy --release --locked --workspace --all-targetswith those samefeatures and
-D warnings.cargo check --release --locked --manifest-path sp1-compress/Cargo.toml --workspace --all-targets; this invokes the Succinct guest compiler ratherthan a stub guest.
SP1_SKIP_PROGRAM_BUILD=1 cargo clippy --release --locked --manifest-path sp1-compress/Cargo.toml --workspace --all-targets -- -D warnings.domain-separated public values, and strict claim shape/canonical encoding.
IX_SP1=1 lake build ix.lake exe IxTests ix-aggr, 99/99passed, including six terminal-compression policy cases.
lake build IxTests ix(1,093 jobs).lake exe ix codegen --check, includingthe 2,061,361-byte / 248-function converged
ix_aggrexecutor.cargo fmt --checkpasses.The end-to-end synthetic guest smoke also passed after rebasing to the current
Multi-STARK revision:
Review guide
The most useful review order is:
sp1-compress/guest/src/main.rs: the attested verification and publicstatement.
sp1-compress/host/src/lib.rs: preflight, SP1 modes, result verification,and artifact handling.
crates/aiur/src/vk_codec.rsandcrates/aiur/src/synthesis.rs: theserialized Aiur verification surface shared with the guest.
Ix/Cli/CompressRootCmd.lean: aggregate-root reconstruction and closureenforcement.
crates/ffi,lakefile.lean, andflake.nix: optional feature and buildisolation.
Out of scope