Skip to content

perf(recursion): no-carry tensor contractions in the verifier guest (57,804,752 rows at inner 2^12) - #2154

Closed
Acentelles wants to merge 25 commits into
a16z:feat/fast-recursionfrom
Acentelles:recursion-guest-tensor-no-carry
Closed

Acentelles wants to merge 25 commits into
a16z:feat/fast-recursionfrom
Acentelles:recursion-guest-tensor-no-carry

Conversation

@Acentelles

@Acentelles Acentelles commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

This PR turns on the optional no-carry tensor contraction in the recursion verifier guest. It has three commits:

  1. Forward a new tensor-no-carry feature from the recursion example and its guest to jolt-akita, and on to akita-algebra.
  2. Turn it on by default in the recursion example. --no-default-features turns it off.
  3. Move the Akita pin on Acentelles/akita-lz from 9db4ee25 to a6a34dcf. The new pin is 9db4ee25 plus the Akita commit that adds the feature. Cargo.lock changes only the git source revisions.

The field values, proofs and transcripts are unchanged.

This PR stacks on #2153, which itself stacks on #2143. Please review only the last three commits. GitHub also shows the earlier commits until those PRs merge.

It is paired with the Akita PR that adds the feature: LayerZero-Labs/akita#272.

Measured effect

These are total trace rows (real plus virtual) of the recursion example's verifier guest. The pair below was measured on the equivalent build with a local Akita checkout, which runs a constant 14 rows above the public tree. Proofs are unchanged, and the Akita proof stays at 72,672 bytes ($2^{12}$) and 75,817 bytes ($2^{20}$).

Inner proof Without (#2153's settings) With this PR Difference Host
$2^{12}$ 57,813,926 57,804,752 -9,174 EPYC 9124
$2^{20}$ 147,659,422 147,597,159 -62,263 EPYC 9124
  • In that measurement, a tampered proof was rejected and a repeat gave the same rows.
  • With --no-default-features, the build reproduced the stock figure (62,367,771 rows).
  • Clippy passed in the default and no-default-features graphs.

Not measured:

  • the rows on this public tree with the new pin. This PR stays a draft until a fresh-clone build of this branch is measured.
  • the gain alone on earlier stacks; the paired Akita PR gives those figures (-23,538 / -138,253 and -23,482 / -138,188).

How to reproduce

git clone -b recursion-guest-tensor-no-carry https://github.com/Acentelles/jolt
cd jolt
cargo build --locked --profile ci -p recursion --features akita,field-inline,ntt-inline
target/ci/recursion generate --example fibonacci --workdir wd
RAYON_NUM_THREADS=1 target/ci/recursion trace --embed --expect accept --example fibonacci --workdir wd

The $2^{20}$ figure used the same host-only input override as #2143 (RECURSION_FIB_N=74858).

Acentelles and others added 25 commits October 20, 2026 20:14
l3-compression-weights on jolt-akita, the recursion host and the recursion
guest selects Akita's factored evaluation of the compression relation
weights (same field values). Feature-off guests compile byte for byte as
before: only Cargo feature tables and host-only code change.
The recursion example enables l3-compression-weights by default. The feature
forwards weakly (jolt-akita?/l3-compression-weights) and the host adds the
guest feature only together with akita, so Dory builds are unchanged.
--no-default-features turns it off. Host-side Cargo and cfg changes only.
Adds l2-terminal-quotient to jolt-akita (enabling akita-pcs's feature), the
recursion host and the verifier guest, the host's guest-feature line, and a
tamper-l2 tool for the rejection fixtures (quotient flip, noncanonical,
extra, short, response flip). Feature-off guest sources are untouched.
The recursion example enables l2-terminal-quotient by default next to
l3-compression-weights. The feature forwards weakly
(jolt-akita?/l2-terminal-quotient), and the host's guest-feature line, the
tamper-l2 command and its helpers are compiled only together with akita, so
Dory builds are unchanged and Akita builds prove and verify with the
quotient certificate. --no-default-features turns both off. Host-side Cargo
and cfg changes only.
Adds the word-decode and word-transcript features: Fp128 proof elements are
deserialized from fixed 16-byte tuples with register-sized accumulators, and
transcript scalars can be absorbed as whole words. Both are off by default.
The recursion example enables word-decode by default next to the factored
compression weights and the terminal quotient certificate. The feature
forwards weakly (jolt-akita?/word-decode) and the host forwards it to the
guest only together with akita, so Dory builds are unchanged.
--no-default-features turns all three off. Host-side Cargo and cfg changes
only.
The recursion example enables word-memory by default next to the factored
compression weights, the terminal quotient certificate and word decoding.
The host forwards it to the guest only together with akita, so Dory builds
are unchanged. --no-default-features turns all four off. Host-side Cargo and
cfg changes only.
The recursion example's default features use Akita changes that are not in
LayerZero-Labs/akita yet. Pin the Akita crates to the fork commit that carries
them so a fresh checkout builds the measured configuration.
…hold 1000 and one codegen unit by default

The recursion host now builds the verifier guest with
ZEROOS_GUEST_RUSTFLAGS=-Cllvm-args=-inline-threshold=1000 and
CARGO_PROFILE_RELEASE_CODEGEN_UNITS=1 (new default feature guest-codegen).
The settings apply to the verifier guest build only; the inner guests and
their proofs are unchanged. A value the caller already set for either
variable wins. RECURSION_GUEST_CODEGEN=off, or building without the
feature (--no-default-features), restores the stock guest build. Host-side
Cargo and source changes only.
…to 1750

The guest-codegen default for the recursion verifier guest build moves
from -Cllvm-args=-inline-threshold=1000 to -Cllvm-args=-inline-threshold=1750,
still with one codegen unit. Thresholds of 2000 and above fail to link the
guest. A caller value for ZEROOS_GUEST_RUSTFLAGS still wins, and
RECURSION_GUEST_CODEGEN=off restores the stock guest build. Host-side source
change only; the inner guests and their proofs are unchanged.
…cursion verifier guest build

The guest-codegen default for the recursion verifier guest build adds
-Cllvm-args=-enable-gvn-hoist and -Cllvm-args=-enable-dfa-jump-thread to
-Cllvm-args=-inline-threshold=1750, still with one codegen unit. A caller
value for ZEROOS_GUEST_RUSTFLAGS still wins, and RECURSION_GUEST_CODEGEN=off
restores the stock guest build. Host-side source change only; the inner
guests and their proofs are unchanged.
…he recursion verifier guest build

The guest-codegen default for the recursion verifier guest build adds
-Cllvm-args=-enable-ext-tsp-block-placement and
-Cllvm-args=-enable-tail-merge=false to the existing inline threshold,
GVN hoisting and DFA jump threading flags, still with one codegen unit.
A caller value for ZEROOS_GUEST_RUSTFLAGS still wins, and
RECURSION_GUEST_CODEGEN=off restores the stock guest build. Host-side
source change only; the inner guests and their proofs are unchanged.
The verifier_api test verifies Dory fixtures with VerifierPCS (Dory). With
jolt-sdk's akita feature, jolt_verifier::verify is the Akita path, whose
OneHotTrace metadata bounds Dory does not implement, so the test target
failed to compile (E0277) whenever akita was unified into jolt-sdk, for
example through the recursion example's akita feature. Gate the test to
builds without akita, like verifier_preprocessing_from_prover.
…erifier guest build

The guest-codegen default for the recursion verifier guest build adds
-Cllvm-args=-split-spill-mode=size to the existing inline threshold,
GVN hoisting, DFA jump threading, ExtTSP block placement and no tail
merging flags, still with one codegen unit. A caller value for
ZEROOS_GUEST_RUSTFLAGS still wins, and RECURSION_GUEST_CODEGEN=off
restores the stock guest build. Host-side source change only; the inner
guests and their proofs are unchanged.
…e recursion verifier guest build

The guest-codegen default for the recursion verifier guest build adds
-Cllvm-args=-riscv-disable-cost-per-use=true to the existing inline
threshold, GVN hoisting, DFA jump threading, ExtTSP block placement, no
tail merging and size-oriented spill splitting flags, still with one
codegen unit. A caller value for ZEROOS_GUEST_RUSTFLAGS still wins, and
RECURSION_GUEST_CODEGEN=off restores the stock guest build. Host-side
source change only; the inner guests and their proofs are unchanged.
The recursion host enables tensor-no-carry by default (weak dependency on
jolt-akita, as the other default verifier arms) and forwards it to the
verifier guest. The guest's Akita separates dense residual equality weights
into a high-part sum and a no-carry low span; the field values, proofs and
transcripts are unchanged. Turn it off with --no-default-features.
…tractions

Moves the Acentelles/akita-lz pin from 9db4ee25 to a6a34dcf, which is
9db4ee25 plus the optional no-carry tensor contraction (feature
tensor-no-carry). Cargo.lock changes only the git source revisions.
@Acentelles

Copy link
Copy Markdown
Collaborator Author

Folded into #2143.

@Acentelles Acentelles closed this Oct 26, 2026
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.

2 participants