Skip to content

feat(jolt-akita): share verifier state across setups and prepare it ahead of proofs - #2136

Open
mtbadakhshan wants to merge 2 commits into
a16z:mainfrom
LayerZero-Labs:taghi/akita-verifier-preprocessing
Open

mtbadakhshan wants to merge 2 commits into
a16z:mainfrom
LayerZero-Labs:taghi/akita-verifier-preprocessing

Conversation

@mtbadakhshan

@mtbadakhshan mtbadakhshan commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Summary

An AkitaVerifierSetup keeps its backend verifier in a serde-skipped cache. A deserialized setup, or one for a new shape, filled that cache on its first proof by running Akita's full prover setup (setup_prover + setup_verifier). The prover setup derives the matrix at prover capacity, computes every setup-prefix commitment, and keeps the whole matrix. Nothing was shared, so each shape paid this again and held its own copy.

This PR derives verifier state from the public seed at verifier size and shares it:

  • A deserialized setup attaches to a process-wide shared state on first use and grows it only on a miss.
  • A host can build that state before any proof arrives with AkitaVerifierResources::prepare.

It also adds a bound grouped catalog that classifies grouped requests (published / plannable / unsupported) and plans missing rows for many requests at once. A host uses it to prepare every shape it serves at startup.

Changes

  • AkitaScheme::verifier_setup_from_params: builds verifier metadata without a prover setup. AkitaScheme::setup builds its verifier half through it.
  • AkitaVerifierResources::prepare(setups): decodes and audits each distinct catalog, then sizes each catalog by its own largest setup. It derives one matrix from the seed, computes only the required prefix commitments, and builds one backend verifier per catalog. It fails on the first Err before generating anything. Holding the value keeps the state alive for setups that attach later.
  • dense_verifier / one_hot_verifier: on a cache miss, attach to the largest live shared state that covers the setup, instead of running setup_prover. On a miss they grow it: only missing prefix slots are computed, and the matrix stream is extended.
    • Lookups never wait for growth.
    • Concurrent misses build once.
    • Verifiers are reused only when their catalog's demand did not grow.
  • Decoded catalogs are shared too. A setup whose catalog bytes equal a prepared catalog's reuses its decoded, audited form, instead of decoding and auditing its own copy on first use.
  • schedule_registry::GroupedCatalog and GroupedAdmission: validate the dense and one-hot catalogs once, classify requests, and extend a catalog for many requests with shared lookup keys planned once.
  • AkitaVerifierSetup::schedule_artifacts is behind an Arc, so setups of one catalog share one copy.

Performance

Release build, Apple M-series. One-hot K16 setups with a 30-polynomial batch capacity, at 20–26 variables. Each setup is freshly deserialized, the way a long-running verifier receives a new shape; all are held alive, then each is verified twice.

Shape Before: first verify After prepare: first verify Unprepared (shared fallback) Repeat verify
20 vars 43.7 ms 2.9 ms 38.3 ms 2.5 ms
22 vars 40.6 ms 3.0 ms 4.6 ms 2.5–2.9 ms
24 vars 40.5 ms 3.5 ms 6.7 ms 3.4–3.5 ms
26 vars 59.9 ms 4.4 ms 33.4 ms 4.0–4.1 ms

prepare for all four shapes runs once, in 211 ms.

Memory (same run, all four setups held) Before After prepare Unprepared
Peak RSS of the verifying process 245 MB 221 MB 230 MB

At these sizes peak RSS is dominated by the loaded proofs. The savings grow with shape size, because each setup previously kept a prover-capacity matrix.

Testing

  • cargo nextest run -p jolt-akita (107 passed)
  • cargo clippy --all --features host and --features host,zk with -D warnings; cargo fmt --all --check
  • cargo nextest run -p jolt-prover --features akita,prover-fixtures -E 'binary(e2e_matrix)'
  • cargo nextest run -p jolt-verifier standard_muldiv --features prover-fixtures
  • New tests cover:
    • shared state across capacities in either order;
    • growth preserving prefix commitments and the matrix stream;
    • per-catalog sizing;
    • fail-fast preparation;
    • verification after the prepared value is dropped;
    • one-hot arities sharing one backend;
    • regressions for a hidden live state and for reused verifiers missing new prefixes;
    • grouped admission (covered, planned, unsupported) and multi-request extension.

Security Considerations

  • Verification checks are unchanged. Catalogs are still decoded and audited, and catalog_digest and the setup fields are still bound into the transcript.
  • The matrix and the setup-prefix commitments are derived from the public seed in-process. Nothing is loaded from a file or supplied by a caller. A substituted prefix commitment would let setup claims be checked against the wrong matrix, which is why no API accepts precomputed commitments.
  • Shared state is keyed by exact catalog bytes and per-catalog capacity. A setup attaches only to state built for an identical catalog with at least its capacity.

Breaking Changes

None to proof formats, transcripts or serialization.

  • AkitaScheme::setup now also rejects a group width of zero or above the batch capacity.
  • Unbound verifier setups in one process share state instead of each holding its own.

External contract: AkitaVerifierResources::prepare and GroupedCatalog are host APIs for long-running deployments that prepare verifier state before serving proofs. In-repo, the lazy path in adapters.rs uses the same machinery.

🤖 Generated with Claude Code

mtbadakhshan and others added 2 commits October 23, 2026 16:40
…head of proofs

A deserialized verifier setup filled its serde-skipped cache on first use by
running Akita's full prover setup, per setup value, with nothing shared.
Derive verifier state from the public seed at verifier size instead and share
it: unprepared setups attach to a process-wide state that grows on a miss, and
hosts can build it before any proof with AkitaVerifierResources::prepare.
GroupedCatalog classifies grouped requests and plans missing rows once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…resource tests

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant