refactor: complete the Akita shared-field cutover - #1
Closed
Acentelles wants to merge 6 commits into
Closed
Conversation
…ield serde bounds The temporary bootstrap adapter for the pre-cutover akita-field type (src/akita.rs, the `akita` feature, and the optional akita-config/ akita-field dependencies) existed only so the pre-cutover Akita field could satisfy JoltField before Akita a16z#307 rebound Akita onto the shared jolt-field landed by Jolt a16z#1684. With Akita a16z#307 the Akita field type IS jolt_field::Fp128 at Akita's modulus, so the edge is dead: delete it and restore the serde bounds (Serialize + DeserializeOwned) on the JoltField trait and its blanket impl, per the promise recorded in the trait doc and in specs/jolt-field-rebuild.md deviation 1. Downstream manifests drop their references to the deleted feature; the legacy prover's own akita-config/akita-field dependency edges die with the adapter rebind in the next commit.
Re-point the akita-* git pins from the pre-cutover revision to the Akita a16z#307 head and adapt jolt-akita and the legacy packed prover path: the post-cutover Akita field type IS jolt_field::Fp128, so the legacy AkitaFp128 adapter surface shrinks accordingly, and schedule resolution is catalog-only (the planner DP became offline-only, and upstream's own generated tables are gitignored bootstrap artifacts that a Git-dependency checkout does not contain). Consequences carried here: - Jolt-owned schedule catalogs regenerated via gen_jolt_schedules over the production grids plus an explicit test-support grid (vars 12..=16, 1..=4 polys) covering the shapes jolt-akita's own harnesses exercise, mirroring the test-scale rows upstream ships in its local catalogs. - One production boundary shape, the widest K=16 group at the minimum padded trace (16 vars, 81 polys), is unschedulable by the post-cutover planner although the pre-cutover runtime planner scheduled it; the catalog coverage test pins this as an explicit known exception that fails the moment the planner covers it, and the question is raised on the Akita a16z#307 review thread. - Test fixtures moved off shapes that are no longer schedulable (13-var 2-poly dense groups); purely-dense fixtures use dense-only setups and the grouped one-hot test a one-hot-only setup, so neither builds the other flavor's setup at unsupported shapes. jolt-akita suite: 38 passed, 0 failed, 3 skipped. WARNING: the akita pins reference the stacked-review head on the contributor fork; re-point to the LayerZero-Labs/akita merge revision of a16z#307 before landing.
The structural cargo-metadata check now rejects every akita-field identity (the crate no longer exists; any occurrence means a stale pre-cutover Akita pin in the graph) and requires exactly one jolt-field identity, the workspace path unified with Akita's Git pin via the root [patch] table. Workflow lane renamed to match.
…rebuild Deviation 1 (JoltField serde bounds) and the akita cutover item move from open to discharged-by-this-branch; the remaining-work list keeps x86 validation, bench re-runs, and the CI SIMD lane.
…eature
The akita feature now enables dep:jolt-field directly (previously only
the prover feature did, so -p jolt-verifier --features akita had no
jolt-field to link for the rewritten adapter), and the packed test
modules qualify Ring::from_u64 at the call sites.
Known-failing on this branch, documented in the draft description:
zkvm::packed::tests::{muldiv_e2e_akita, muldiv_e2e_akita_forced_k256}
fail verification with StageClaimOutputMismatch at stage 1 — the
legacy packed stage-claim plumbing predates the post-cutover Akita
claim layout (per-group opening points, chunk-major witnesses); the
adaptation is an open item pending Akita-maintainer input. 443/445
legacy akita tests pass.
…e packed pipeline Root cause of the packed muldiv e2e failures (StageClaimOutputMismatch at stage 1): the legacy transcripts hardcode the scalar-challenge convention as digest-bytes-reversed (big-endian) before field decode — correct for BN254 — while the modular verifier decodes with the field's own from_scalar_challenge_bytes, which for the shared Solinas Fp128 is unreversed little-endian. Pre-cutover the akita bootstrap adapter carried the reversed convention, so both sides agreed; the cutover made AkitaField the shared Fp128 and silently flipped the verifier side. Both decodes consume the same 16 bytes, so the transcript stream stayed synchronized while every challenge_scalar VALUE diverged, surfacing as a claim/reduction mismatch at the first batched check of the packed pipeline only. Fix: the legacy JoltField gains from_scalar_challenge_bytes with the reversed convention as its default (BN254/Dory byte-identical by construction); blake2b, keccak, and the prover-native verifier transcripts delegate to it; AkitaFp128 overrides it to the shared unreversed convention, matching the modular verifier. Also: the K=256 catalog gains the forced-K256 e2e band (20 vars at production widths) — the forced test deliberately runs the K=256 regime below its production window, which the offline-only planner must cover explicitly. Battery: fmt, clippy (host, host+zk, akita x2, -Dwarnings), identity gate, muldiv 3/3 host and 3/3 zk, jolt-prover-legacy --features akita 445/445, jolt-akita 38/38.
Owner
Author
|
Superseded: re-opened against a16z/jolt as the stacked draft. |
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.
Summary
DRAFT, stacked on a16z#1684 and on Akita a16z#307; cannot land before both merge. Every stacked pin carries a
WARNINGcomment and must be re-pointed to the LayerZero-Labs/akita merge revision of a16z#307 before landing.This PR discharges every "removed in the final migration PR" promise left in the tree by a16z#1684 (the shared-field landing) and Akita a16z#307 (the Akita-side cutover). Post-cutover, Akita's field type IS
jolt_field::Fp128, so the bootstrap machinery is not replaced — it is deleted as meaningless.Changes
jolt-field:src/akita.rs, theakitafeature, and the optionalakita-config/akita-fielddependencies.JoltField's serde bounds (Field + CanonicalEncoding + WithAccumulator + Serialize + DeserializeOwned), reverting the recorded deviation that existed only because the orphan rule barred serde impls for the foreign bootstrap type.jolt-akitaplus the legacy packed prover path;akita-fielddisappears from the dependency graph entirely.[patch]table redirects Akita'sjolt-fieldgit dependency onto the workspace member, so exactly onejolt-fieldpackage identity resolves; the shared-field identity gate flips to reject everyakita-fieldidentity (structuralcargo metadatacheck, color-independent).from_scalar_challenge_bytes, unreversed little-endian for the shared SolinasFp128. Pre-cutover the bootstrap adapter carried the reversal, so both sides agreed; the cutover silently flipped the verifier side. Both decodes consume the same 16 bytes, so the transcript stream stayed synchronized while everychallenge_scalarvalue diverged — surfacing as a deterministicStageClaimOutputMismatchat the first batched-claim check, packed pipeline only. Fixed by giving the legacyJoltFieldafrom_scalar_challenge_byteswhose default preserves the reversed convention (BN254/Dory byte-identical by construction), delegating the blake2b/keccak/prover-native transcripts to it, and overriding it onAkitaFp128to the shared unreversed convention.jolt-prover-legacy'sakitafeature now enablesdep:jolt-fielddirectly, so-p jolt-verifier --features akitabuilds standalone.Testing
jolt-prover-legacy --features akita445/445 (including all three packed muldiv e2e variants);jolt-akita38 passed, 3 skipped;muldive2e 3/3 underhostand 3/3 underhost,zk(the BN254 proving path is untouched).cargo clippyandcargo fmtpass: fmt--checkclean; clippy--all-targets -- -D warningsunderhost,host,zk,-p jolt-verifier --features akita, and-p jolt-prover-legacy --features akita, all withRUSTFLAGS=-Dwarnings.jolt-fieldidentity, zeroakita-field.Security Considerations
AkitaFp128scalar challenges now decode unreversed little-endian, aligning the legacy prover with the modular verifier and with Akita Refactoring get_polys_r1cs to use references instead of cloning a16z/jolt#307's own transcript convention. BN254 challenge derivation is byte-identical by construction (the default preserves the reversed convention), witnessed by the Dorymuldive2e passing in both modes. Packed proofs are not byte-frozen across the cutover.jolt-fieldpackage identity and zeroakita-field, closing the dual-identity hazard the[patch]wiring exists to prevent.Breaking Changes
jolt-fieldloses itsakitafeature and optional akita dependencies;JoltFieldregainsSerialize + DeserializeOwnedsupertraits (types implementing the component traits without serde no longer satisfy it).AkitaFp128scalar-challenge decoding switches to the shared unreversed convention, so packed proofs produced before this PR do not verify after it (and vice versa). BN254/Dory proof formats are unchanged.jolt-prover-legacy'sakitafeature now enablesdep:jolt-field.