From f18b84840eb8a54522cc5c1b3f338294a8d5d572 Mon Sep 17 00:00:00 2001 From: acentelles Date: Thu, 29 Oct 2026 23:08:01 +0000 Subject: [PATCH 01/17] build: pin Jolt to a16z/jolt main e1d8e02b5 Moves every a16z/jolt dependency (jolt-field and jolt-poly in the workspace and fuzz/, plus jolt-sdk and jolt-sdk-macros in profile/akita-recursion) from 1618f4b6d to Jolt main e1d8e02b5, whose jolt-field has the kernels the following verifier changes use (Field::signed_sum, Field::sum_of_products, Field::dot_product, ExtField::weighted_dot_base_rows, MulBaseUnreduced::dot_base). In profile/akita-recursion, Jolt main's jolt-sdk pulls in jolt-akita, which pins Akita by git revision; a patch table builds it against this checkout so the profile graph keeps one Akita and one jolt-field. Jolt main's provable verify function returns Result, so the host reports the verifier error instead of negating a bool. Manifests and that host call only; the lockfiles are regenerated in a following commit. --- crates/akita-algebra/Cargo.toml | 4 ++-- crates/akita-challenges/Cargo.toml | 2 +- crates/akita-config/Cargo.toml | 2 +- crates/akita-cpu-backend/Cargo.toml | 4 ++-- crates/akita-params/Cargo.toml | 2 +- crates/akita-pcs/Cargo.toml | 4 ++-- crates/akita-prover/Cargo.toml | 4 ++-- crates/akita-serialization/Cargo.toml | 4 ++-- crates/akita-setup/Cargo.toml | 2 +- crates/akita-sumcheck/Cargo.toml | 4 ++-- crates/akita-transcript/Cargo.toml | 2 +- crates/akita-types/Cargo.toml | 4 ++-- crates/akita-verifier/Cargo.toml | 4 ++-- fuzz/Cargo.toml | 4 ++-- profile/akita-recursion/Cargo.toml | 21 +++++++++++++++++++++ profile/akita-recursion/artifact/Cargo.toml | 2 +- profile/akita-recursion/glue/Cargo.toml | 2 +- profile/akita-recursion/guest/Cargo.toml | 4 ++-- profile/akita-recursion/host/Cargo.toml | 4 ++-- profile/akita-recursion/host/src/main.rs | 8 +++----- 20 files changed, 53 insertions(+), 34 deletions(-) diff --git a/crates/akita-algebra/Cargo.toml b/crates/akita-algebra/Cargo.toml index 66400473d..7c85cc94a 100644 --- a/crates/akita-algebra/Cargo.toml +++ b/crates/akita-algebra/Cargo.toml @@ -10,11 +10,11 @@ readme = "../../README.md" [dependencies] akita-error = { version = "0.1.0", path = "../akita-error" } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "1618f4b6dc97effcec3568ca7cf2b7420ac9e75f", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ "asm", "solinas", ] } -jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "1618f4b6dc97effcec3568ca7cf2b7420ac9e75f", default-features = false } +jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false } akita-serialization = { version = "0.1.0", path = "../akita-serialization" } rand_core = { version = "0.6", features = ["getrandom"] } rayon = { version = "1.10", optional = true } diff --git a/crates/akita-challenges/Cargo.toml b/crates/akita-challenges/Cargo.toml index 0773c9759..804722f74 100644 --- a/crates/akita-challenges/Cargo.toml +++ b/crates/akita-challenges/Cargo.toml @@ -11,7 +11,7 @@ readme = "../../README.md" [dependencies] akita-error = { version = "0.1.0", path = "../akita-error" } serde = { version = "1", features = ["derive"] } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "1618f4b6dc97effcec3568ca7cf2b7420ac9e75f", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ "asm", "solinas", ] } diff --git a/crates/akita-config/Cargo.toml b/crates/akita-config/Cargo.toml index a469737b9..2aa3f1c7e 100644 --- a/crates/akita-config/Cargo.toml +++ b/crates/akita-config/Cargo.toml @@ -30,7 +30,7 @@ test-support = [] [dependencies] akita-error = { version = "0.1.0", path = "../akita-error" } akita-challenges = { version = "0.1.0", path = "../akita-challenges", default-features = false } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "1618f4b6dc97effcec3568ca7cf2b7420ac9e75f", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ "asm", "solinas", ] } diff --git a/crates/akita-cpu-backend/Cargo.toml b/crates/akita-cpu-backend/Cargo.toml index 3e61aaa2b..a5885852b 100644 --- a/crates/akita-cpu-backend/Cargo.toml +++ b/crates/akita-cpu-backend/Cargo.toml @@ -14,11 +14,11 @@ akita-error = { version = "0.1.0", path = "../akita-error" } akita-algebra = { version = "0.1.0", path = "../akita-algebra" } akita-challenges = { version = "0.1.0", path = "../akita-challenges", default-features = false } akita-config = { version = "0.1.0", path = "../akita-config", default-features = false } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "1618f4b6dc97effcec3568ca7cf2b7420ac9e75f", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ "asm", "solinas", ] } -jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "1618f4b6dc97effcec3568ca7cf2b7420ac9e75f", default-features = false } +jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false } akita-serialization = { version = "0.1.0", path = "../akita-serialization" } akita-sumcheck = { version = "0.1.0", path = "../akita-sumcheck", default-features = false } akita-transcript = { version = "0.1.0", path = "../akita-transcript", default-features = false } diff --git a/crates/akita-params/Cargo.toml b/crates/akita-params/Cargo.toml index c5d1f66e0..4a1f64333 100644 --- a/crates/akita-params/Cargo.toml +++ b/crates/akita-params/Cargo.toml @@ -12,7 +12,7 @@ readme = "../../README.md" akita-error = { version = "0.1.0", path = "../akita-error" } akita-algebra = { version = "0.1.0", path = "../akita-algebra" } akita-challenges = { version = "0.1.0", path = "../akita-challenges", default-features = false } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "1618f4b6dc97effcec3568ca7cf2b7420ac9e75f", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ "asm", "solinas", ] } diff --git a/crates/akita-pcs/Cargo.toml b/crates/akita-pcs/Cargo.toml index 121b6ac3a..37f16be5f 100644 --- a/crates/akita-pcs/Cargo.toml +++ b/crates/akita-pcs/Cargo.toml @@ -102,7 +102,7 @@ akita-algebra = { version = "0.1.0", path = "../akita-algebra" } akita-challenges = { version = "0.1.0", path = "../akita-challenges", default-features = false } akita-config = { version = "0.1.0", path = "../akita-config", default-features = false } akita-cpu-backend = { version = "0.1.0", path = "../akita-cpu-backend", default-features = false } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "1618f4b6dc97effcec3568ca7cf2b7420ac9e75f", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ "asm", "solinas", ] } @@ -117,7 +117,7 @@ tracing = "0.1" rayon = { version = "1.10", optional = true } [dev-dependencies] -jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "1618f4b6dc97effcec3568ca7cf2b7420ac9e75f", default-features = false } +jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false } # Test-only: pull in `akita-config`'s workspace artifact loader and ring-plan # seed. Schedule rows remain checked-in external artifacts loaded at runtime. akita-config = { version = "0.1.0", path = "../akita-config", default-features = false, features = [ diff --git a/crates/akita-prover/Cargo.toml b/crates/akita-prover/Cargo.toml index ea05f3c44..ab66a0bf8 100644 --- a/crates/akita-prover/Cargo.toml +++ b/crates/akita-prover/Cargo.toml @@ -13,11 +13,11 @@ akita-error = { version = "0.1.0", path = "../akita-error" } akita-algebra = { version = "0.1.0", path = "../akita-algebra" } akita-challenges = { version = "0.1.0", path = "../akita-challenges", default-features = false } akita-config = { version = "0.1.0", path = "../akita-config", default-features = false } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "1618f4b6dc97effcec3568ca7cf2b7420ac9e75f", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ "asm", "solinas", ] } -jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "1618f4b6dc97effcec3568ca7cf2b7420ac9e75f", default-features = false } +jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false } akita-serialization = { version = "0.1.0", path = "../akita-serialization" } akita-sumcheck = { version = "0.1.0", path = "../akita-sumcheck", default-features = false } akita-transcript = { version = "0.1.0", path = "../akita-transcript", default-features = false } diff --git a/crates/akita-serialization/Cargo.toml b/crates/akita-serialization/Cargo.toml index 252c1ac40..64eab1d97 100644 --- a/crates/akita-serialization/Cargo.toml +++ b/crates/akita-serialization/Cargo.toml @@ -9,11 +9,11 @@ repository = "https://github.com/LayerZero-Labs/akita" readme = "../../README.md" [dependencies] -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "1618f4b6dc97effcec3568ca7cf2b7420ac9e75f", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ "asm", "solinas", ] } -jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "1618f4b6dc97effcec3568ca7cf2b7420ac9e75f", default-features = false } +jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false } thiserror = "2.0" [lints] diff --git a/crates/akita-setup/Cargo.toml b/crates/akita-setup/Cargo.toml index 52285eeab..03fe99be7 100644 --- a/crates/akita-setup/Cargo.toml +++ b/crates/akita-setup/Cargo.toml @@ -29,7 +29,7 @@ disk-persistence = ["akita-cpu-backend/disk-persistence"] akita-error = { version = "0.1.0", path = "../akita-error" } akita-config = { version = "0.1.0", path = "../akita-config", default-features = false } akita-cpu-backend = { version = "0.1.0", path = "../akita-cpu-backend", default-features = false } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "1618f4b6dc97effcec3568ca7cf2b7420ac9e75f", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ "asm", "solinas", ] } diff --git a/crates/akita-sumcheck/Cargo.toml b/crates/akita-sumcheck/Cargo.toml index 19182001a..3c4746187 100644 --- a/crates/akita-sumcheck/Cargo.toml +++ b/crates/akita-sumcheck/Cargo.toml @@ -11,11 +11,11 @@ readme = "../../README.md" [dependencies] akita-error = { version = "0.1.0", path = "../akita-error" } akita-algebra = { version = "0.1.0", path = "../akita-algebra" } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "1618f4b6dc97effcec3568ca7cf2b7420ac9e75f", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ "asm", "solinas", ] } -jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "1618f4b6dc97effcec3568ca7cf2b7420ac9e75f", default-features = false } +jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false } akita-serialization = { version = "0.1.0", path = "../akita-serialization" } akita-transcript = { version = "0.1.0", path = "../akita-transcript", default-features = false } diff --git a/crates/akita-transcript/Cargo.toml b/crates/akita-transcript/Cargo.toml index 949c4cbac..7caf60dda 100644 --- a/crates/akita-transcript/Cargo.toml +++ b/crates/akita-transcript/Cargo.toml @@ -10,7 +10,7 @@ readme = "../../README.md" [dependencies] akita-error = { version = "0.1.0", path = "../akita-error" } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "1618f4b6dc97effcec3568ca7cf2b7420ac9e75f", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ "asm", "solinas", ] } diff --git a/crates/akita-types/Cargo.toml b/crates/akita-types/Cargo.toml index b5aa0c706..80620379f 100644 --- a/crates/akita-types/Cargo.toml +++ b/crates/akita-types/Cargo.toml @@ -13,11 +13,11 @@ akita-params = { version = "0.1.0", path = "../akita-params", default-features = akita-error = { version = "0.1.0", path = "../akita-error" } akita-algebra = { version = "0.1.0", path = "../akita-algebra" } akita-challenges = { version = "0.1.0", path = "../akita-challenges", default-features = false } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "1618f4b6dc97effcec3568ca7cf2b7420ac9e75f", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ "asm", "solinas", ] } -jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "1618f4b6dc97effcec3568ca7cf2b7420ac9e75f", default-features = false } +jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false } akita-serialization = { version = "0.1.0", path = "../akita-serialization" } akita-sumcheck = { version = "0.1.0", path = "../akita-sumcheck", default-features = false } akita-transcript = { version = "0.1.0", path = "../akita-transcript", default-features = false } diff --git a/crates/akita-verifier/Cargo.toml b/crates/akita-verifier/Cargo.toml index 6b863326c..9b1d7d72f 100644 --- a/crates/akita-verifier/Cargo.toml +++ b/crates/akita-verifier/Cargo.toml @@ -18,11 +18,11 @@ akita-error = { version = "0.1.0", path = "../akita-error" } akita-algebra = { version = "0.1.0", path = "../akita-algebra" } akita-challenges = { version = "0.1.0", path = "../akita-challenges", default-features = false } akita-config = { version = "0.1.0", path = "../akita-config", default-features = false } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "1618f4b6dc97effcec3568ca7cf2b7420ac9e75f", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ "asm", "solinas", ] } -jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "1618f4b6dc97effcec3568ca7cf2b7420ac9e75f", default-features = false } +jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false } akita-serialization = { version = "0.1.0", path = "../akita-serialization" } akita-sumcheck = { version = "0.1.0", path = "../akita-sumcheck", default-features = false } akita-transcript = { version = "0.1.0", path = "../akita-transcript", default-features = false } diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index c0e3e5087..4b27b8e6a 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -73,11 +73,11 @@ akita-types = { path = "../crates/akita-types", default-features = false, featur akita-verifier = { path = "../crates/akita-verifier", default-features = false, features = [ "transcript-blake2b", ] } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "1618f4b6dc97effcec3568ca7cf2b7420ac9e75f", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ "asm", "solinas", ] } -jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "1618f4b6dc97effcec3568ca7cf2b7420ac9e75f", default-features = false } +jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false } libfuzzer-sys = "0.4.12" num-bigint = "0.4" rayon = "1.10" diff --git a/profile/akita-recursion/Cargo.toml b/profile/akita-recursion/Cargo.toml index 4573ea877..ee76a0adb 100644 --- a/profile/akita-recursion/Cargo.toml +++ b/profile/akita-recursion/Cargo.toml @@ -34,3 +34,24 @@ ark-bn254 = { git = "https://github.com/a16z/arkworks-algebra", branch = "dev/tw ark-ff = { git = "https://github.com/a16z/arkworks-algebra", branch = "dev/twist-shout" } ark-ec = { git = "https://github.com/a16z/arkworks-algebra", branch = "dev/twist-shout" } ark-serialize = { git = "https://github.com/a16z/arkworks-algebra", branch = "dev/twist-shout" } + +# Jolt's `jolt-akita`, pulled in by `jolt-sdk`, pins Akita by git revision. +# Build it against this checkout, so the profile graph has one Akita and one +# `jolt-field` identity. +[patch."https://github.com/LayerZero-Labs/akita.git"] +akita-algebra = { path = "../../crates/akita-algebra" } +akita-challenges = { path = "../../crates/akita-challenges" } +akita-config = { path = "../../crates/akita-config" } +akita-cpu-backend = { path = "../../crates/akita-cpu-backend" } +akita-error = { path = "../../crates/akita-error" } +akita-params = { path = "../../crates/akita-params" } +akita-pcs = { path = "../../crates/akita-pcs" } +akita-planner = { path = "../../crates/akita-planner" } +akita-prover = { path = "../../crates/akita-prover" } +akita-schedules = { path = "../../crates/akita-schedules" } +akita-serialization = { path = "../../crates/akita-serialization" } +akita-setup = { path = "../../crates/akita-setup" } +akita-sumcheck = { path = "../../crates/akita-sumcheck" } +akita-transcript = { path = "../../crates/akita-transcript" } +akita-types = { path = "../../crates/akita-types" } +akita-verifier = { path = "../../crates/akita-verifier" } diff --git a/profile/akita-recursion/artifact/Cargo.toml b/profile/akita-recursion/artifact/Cargo.toml index 5657bceb4..8dbb0fb1c 100644 --- a/profile/akita-recursion/artifact/Cargo.toml +++ b/profile/akita-recursion/artifact/Cargo.toml @@ -16,7 +16,7 @@ akita-recursion-glue = { path = "../glue" } akita-serialization = { path = "../../../crates/akita-serialization" } akita-config = { path = "../../../crates/akita-config", default-features = false, features = [ ] } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "1618f4b6dc97effcec3568ca7cf2b7420ac9e75f", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ "asm", "solinas", ] } diff --git a/profile/akita-recursion/glue/Cargo.toml b/profile/akita-recursion/glue/Cargo.toml index d33f3ffa7..d6f7a801a 100644 --- a/profile/akita-recursion/glue/Cargo.toml +++ b/profile/akita-recursion/glue/Cargo.toml @@ -27,7 +27,7 @@ trusted-benchmark-artifact = [] akita-error = { version = "0.1.0", path = "../../../crates/akita-error" } akita-algebra = { version = "0.1.0", path = "../../../crates/akita-algebra" } akita-config = { version = "0.1.0", path = "../../../crates/akita-config", default-features = false } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "1618f4b6dc97effcec3568ca7cf2b7420ac9e75f", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ "asm", "solinas", ] } diff --git a/profile/akita-recursion/guest/Cargo.toml b/profile/akita-recursion/guest/Cargo.toml index 1db110748..3ecd9ea77 100644 --- a/profile/akita-recursion/guest/Cargo.toml +++ b/profile/akita-recursion/guest/Cargo.toml @@ -34,11 +34,11 @@ trusted-benchmark-artifact = ["akita-recursion-glue/trusted-benchmark-artifact"] akita-error = { path = "../../../crates/akita-error" } # Aliased as `jolt` so `#[jolt::provable]` and `jolt::start_cycle_tracking` # resolve the same way as in the upstream Jolt examples. -jolt = { package = "jolt-sdk", git = "https://github.com/a16z/jolt", rev = "1618f4b6dc97effcec3568ca7cf2b7420ac9e75f", default-features = false } +jolt = { package = "jolt-sdk", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false } akita-recursion-glue = { path = "../glue" } akita-config = { path = "../../../crates/akita-config", default-features = false, features = [ ] } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "1618f4b6dc97effcec3568ca7cf2b7420ac9e75f", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ "asm", "solinas", ] } diff --git a/profile/akita-recursion/host/Cargo.toml b/profile/akita-recursion/host/Cargo.toml index c23af9259..99a2120a0 100644 --- a/profile/akita-recursion/host/Cargo.toml +++ b/profile/akita-recursion/host/Cargo.toml @@ -14,7 +14,7 @@ name = "akita-recursion-host" path = "src/main.rs" [dependencies] -jolt-sdk = { git = "https://github.com/a16z/jolt", rev = "1618f4b6dc97effcec3568ca7cf2b7420ac9e75f", default-features = false, features = [ +jolt-sdk = { git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ "host", ] } # We pin `jolt-sdk-macros` with `guest-std` directly so that the @@ -22,7 +22,7 @@ jolt-sdk = { git = "https://github.com/a16z/jolt", rev = "1618f4b6dc97effcec3568 # its own `cfg(feature = "guest-std")` at host compile time). Going through # `jolt-sdk/guest-std` would also pull `zeroos-runtime-musl` in for the # host build, which fails to link on macOS / non-musl platforms. -jolt-sdk-macros = { git = "https://github.com/a16z/jolt", rev = "1618f4b6dc97effcec3568ca7cf2b7420ac9e75f", features = [ +jolt-sdk-macros = { git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", features = [ "guest-std", ] } guest = { package = "akita-recursion-guest", path = "../guest", features = [ diff --git a/profile/akita-recursion/host/src/main.rs b/profile/akita-recursion/host/src/main.rs index 82be00a0d..1ecb39ecf 100644 --- a/profile/akita-recursion/host/src/main.rs +++ b/profile/akita-recursion/host/src/main.rs @@ -358,12 +358,10 @@ macro_rules! run_selected_guest { ); let now = Instant::now(); - let is_valid = verify($blob, output, program_io.panic, proof); + let verdict = verify($blob, output, program_io.panic, proof); let verifier_secs = now.elapsed().as_secs_f64(); - info!(verifier_secs, is_valid, "Jolt verifier finished"); - if !is_valid { - return Err("Jolt verifier rejected the proof".to_string()); - } + info!(verifier_secs, is_valid = verdict.is_ok(), "Jolt verifier finished"); + verdict.map_err(|err| format!("Jolt verifier rejected the proof: {err}"))?; if output != 0 { return Err(format!("guest reported Akita-verify failure: {output}")); } From fefb5d01ab55d1c802594f8d4ec6344e0fab8d03 Mon Sep 17 00:00:00 2001 From: acentelles Date: Sat, 24 Oct 2026 00:56:01 +0100 Subject: [PATCH 02/17] perf(challenges): use signed accumulation for sparse evaluation --- crates/akita-challenges/src/challenge.rs | 101 +++++++++++++++++++++-- 1 file changed, 93 insertions(+), 8 deletions(-) diff --git a/crates/akita-challenges/src/challenge.rs b/crates/akita-challenges/src/challenge.rs index b6edffbc4..5c1d0bd38 100644 --- a/crates/akita-challenges/src/challenge.rs +++ b/crates/akita-challenges/src/challenge.rs @@ -136,14 +136,14 @@ impl SparseChallenge { /// Evaluate this challenge against precomputed scalar powers. /// - /// The small integer coefficients are first embedded into the base field - /// `F`, then multiplied into `E` with a mixed base-field operation. The - /// ordinary base-field case is `E = F`. + /// Coefficients of magnitude one or two use signed addition in `E`. + /// Other coefficients are embedded into `F` and multiplied into `E` with + /// a mixed base-field operation. The ordinary base-field case is `E = F`. /// /// # Errors /// - /// Returns an error if `alpha_pows` does not have length `D`, or if a - /// term would index outside the supplied powers. This method assumes the + /// Returns an error for mismatched term counts, zero coefficients, or a + /// position outside the supplied powers. This method assumes the /// challenge came from the crate's fold-challenge sampler and therefore /// does not re-check uniqueness of positions on the hot path. pub fn eval_at_pows(&self, alpha_pows: &[E]) -> Result @@ -158,7 +158,7 @@ impl SparseChallenge { )); } - let mut acc = E::zero(); + let mut signed_terms = true; for (&pos, &coeff) in self.positions.iter().zip(self.coeffs.iter()) { let idx = pos as usize; if idx >= ring_d { @@ -171,7 +171,32 @@ impl SparseChallenge { "sparse challenge coefficients must be non-zero".to_string(), )); } - accumulate_small_signed::(&mut acc, alpha_pows[idx], i64::from(coeff)); + signed_terms &= matches!(coeff, -2 | -1 | 1 | 2); + } + if signed_terms { + // The checked positions borrow canonical powers. Repeating a term + // for magnitude two preserves the polynomial over every field; + // field-inline guests keep the sum in one accumulator. + return Ok(E::signed_sum( + self.positions + .iter() + .zip(&self.coeffs) + .flat_map(|(&position, &coefficient)| { + std::iter::repeat_n( + (&alpha_pows[position as usize], coefficient < 0), + usize::from(coefficient.unsigned_abs()), + ) + }), + )); + } + + let mut acc = E::zero(); + for (&position, &coefficient) in self.positions.iter().zip(&self.coeffs) { + accumulate_small_signed::( + &mut acc, + alpha_pows[position as usize], + i64::from(coefficient), + ); } Ok(acc) } @@ -180,7 +205,7 @@ impl SparseChallenge { #[cfg(test)] mod tests { use super::*; - use jolt_field::Prime128Offset275; + use jolt_field::{One, Prime128Offset275, Zero}; type F = Prime128Offset275; const D: usize = 4; @@ -247,6 +272,66 @@ mod tests { assert!(matches!(err, AkitaError::InvalidInput(msg) if msg.contains("length mismatch"))); } + #[test] + fn eval_at_pows_matches_dense_polynomial_at_boundary_points() { + let coefficients = [1, -2, 2, -1, 1, -1, 2, -2]; + let challenge = SparseChallenge { + positions: (0..coefficients.len() as u32).collect(), + coeffs: coefficients.into_iter().collect(), + }; + for alpha in [F::zero(), F::one(), -F::one(), F::from_u64(13)] { + let mut powers = Vec::new(); + let mut power = F::one(); + for _ in coefficients { + powers.push(power); + power *= alpha; + } + let expected = coefficients + .iter() + .rev() + .fold(F::zero(), |value, &coefficient| { + value * alpha + F::from_i64(i64::from(coefficient)) + }); + assert_eq!(challenge.eval_at_pows::(&powers).unwrap(), expected); + } + } + + #[test] + fn eval_at_pows_retains_general_coefficient_and_duplicate_semantics() { + let powers = [F::from_u64(7), -F::one()]; + for coefficients in [[i8::MIN, i8::MAX], [-2, 2], [-8, 3]] { + let challenge = SparseChallenge { + positions: vec![1, 1].into(), + coeffs: coefficients.into_iter().collect(), + }; + let sum = i64::from(coefficients[0]) + i64::from(coefficients[1]); + assert_eq!( + challenge.eval_at_pows::(&powers).unwrap(), + -F::from_i64(sum), + ); + assert!(challenge.validate_dyn(powers.len()).is_err()); + } + let empty = SparseChallenge { + positions: Default::default(), + coeffs: Default::default(), + }; + assert_eq!(empty.eval_at_pows::(&[]).unwrap(), F::zero()); + } + + #[test] + fn eval_at_pows_rejects_zero_after_valid_terms() { + for coefficients in [[1, 0], [3, 0]] { + let challenge = SparseChallenge { + positions: vec![0, 1].into(), + coeffs: coefficients.into_iter().collect(), + }; + assert!(matches!( + challenge.eval_at_pows::(&alpha_pows()), + Err(AkitaError::InvalidInput(message)) if message.contains("non-zero") + )); + } + } + #[test] fn validate_rejects_duplicate_positions() { let challenge = SparseChallenge { From af458fb7cd0a0da1c4666533c3c91edd18160a22 Mon Sep 17 00:00:00 2001 From: acentelles Date: Mon, 26 Oct 2026 18:09:35 +0000 Subject: [PATCH 03/17] feat(challenges): static operator-norm base tables behind ont-static-base Adds generated static base tables for the D64 selective-L2 operator-norm sampler, with the generator script. The tables are compiled in only with the ont-static-base feature, which is off by default; without it the sampler is unchanged. --- crates/akita-challenges/Cargo.toml | 3 + .../scripts/gen_op_norm_static_base.py | 204 +++++++++++++ .../akita-challenges/src/sampler/op_norm.rs | 79 ++++- .../src/sampler/op_norm/static_base.rs | 273 ++++++++++++++++++ 4 files changed, 558 insertions(+), 1 deletion(-) create mode 100644 crates/akita-challenges/scripts/gen_op_norm_static_base.py create mode 100644 crates/akita-challenges/src/sampler/op_norm/static_base.rs diff --git a/crates/akita-challenges/Cargo.toml b/crates/akita-challenges/Cargo.toml index 804722f74..45b174994 100644 --- a/crates/akita-challenges/Cargo.toml +++ b/crates/akita-challenges/Cargo.toml @@ -28,6 +28,9 @@ transcript-blake2b = ["akita-transcript/transcript-blake2b"] transcript-keccak = ["akita-transcript/transcript-keccak"] parallel = ["jolt-field/parallel"] logging-transcript = ["akita-transcript/logging-transcript"] +# Recursion option (default off): the D64 selective-L2 operator-norm +# table reads its base tables from generated static data (same entries). +ont-static-base = [] [lints] workspace = true diff --git a/crates/akita-challenges/scripts/gen_op_norm_static_base.py b/crates/akita-challenges/scripts/gen_op_norm_static_base.py new file mode 100644 index 000000000..6307a9f2c --- /dev/null +++ b/crates/akita-challenges/scripts/gen_op_norm_static_base.py @@ -0,0 +1,204 @@ +#!/usr/bin/env python3 +"""Generate src/sampler/op_norm/static_base.rs (feature `ont-static-base`). + +Exact-integer transcription of `op_norm.rs` `build_tables` (with `pi_enclosure`, +`arctan_inv`, `taylor_cos`, `taylor_sin`, `octant_reduce`, `apply_sign`, +`downscale_round`, `imul`, `iadd`, `isub`, `fdiv`, `cdiv`, `fshr`, `cshr`) for +the D64 selective-L2 operator-norm table: ring degree d = 64 at scale q = 48. +Python integers are unbounded, so every intermediate that Rust keeps in `i128` +is range-checked; a `checked_mul` overflow in Rust is a loop exit here as well. + +The output holds the 128-entry `base_cos` and `base_sin` tables as `i64` (the +production path downcasts them to `i64`; the generator asserts they fit) and +`eps_root`. The transcription is not trusted on its own: the +`static_base_equals_build_tables` unit test compares every entry and `eps_root` +with the Rust `build_tables` output. + +Usage: gen_op_norm_static_base.py [OUT] (default: ../src/sampler/op_norm/static_base.rs) +""" +import hashlib +import struct +import sys +from pathlib import Path + +I128_MIN, I128_MAX = -(1 << 127), (1 << 127) - 1 +TRIG_SCALE = 61 +TRIG_ONE = 1 << TRIG_SCALE +NTERMS = 12 +D, Q = 64, 48 + + +def chk(x): + assert I128_MIN <= x <= I128_MAX, "i128 overflow" + return x + + +def fdiv(a, b): + return chk(a // b) + + +def cdiv(a, b): + return chk(-((-a) // b)) + + +def fshr(x, sh): + return x >> sh + + +def cshr(x, sh): + return -((-x) >> sh) + + +def imul(a, b): + assert a[0] >= 0 and b[0] >= 0 + return (fshr(chk(a[0] * b[0]), TRIG_SCALE), cshr(chk(a[1] * b[1]), TRIG_SCALE)) + + +def iadd(a, b): + return (chk(a[0] + b[0]), chk(a[1] + b[1])) + + +def isub(a, b): + return (chk(a[0] - b[1]), chk(a[1] - b[0])) + + +def add_remainder(s, phi2, pw, fact, next_factor): + next_pow = imul(pw, phi2) + next_fact = chk(fact * next_factor * (next_factor + 1)) + rem = cdiv(next_pow[1], next_fact) + return (s[0] - rem, s[1] + rem) + + +def taylor_cos(phi): + phi2 = imul(phi, phi) + s, pw, fact = (TRIG_ONE, TRIG_ONE), (TRIG_ONE, TRIG_ONE), 1 + for n in range(1, NTERMS + 1): + pw = imul(pw, phi2) + tn = 2 * n + fact = chk(fact * (tn - 1) * tn) + term = (fdiv(pw[0], fact), cdiv(pw[1], fact)) + s = isub(s, term) if n % 2 == 1 else iadd(s, term) + return add_remainder(s, phi2, pw, fact, 2 * NTERMS + 1) + + +def taylor_sin(phi): + phi2 = imul(phi, phi) + s, pw, fact = phi, phi, 1 + for n in range(1, NTERMS + 1): + pw = imul(pw, phi2) + tn = 2 * n + fact = chk(fact * tn * (tn + 1)) + term = (fdiv(pw[0], fact), cdiv(pw[1], fact)) + s = isub(s, term) if n % 2 == 1 else iadd(s, term) + return add_remainder(s, phi2, pw, fact, 2 * NTERMS + 2) + + +def arctan_inv(x): + total, x_pow, x2, count, n = 0, x, x * x, 0, 0 + while True: + denom = (2 * n + 1) * x_pow # Rust: (2n+1).checked_mul(x_pow), None ends the loop + if not I128_MIN <= denom <= I128_MAX: + break + term = TRIG_ONE // denom # denom > 0: truncation equals floor + if term == 0: + break + total = total + term if n % 2 == 0 else total - term + count += 1 + n += 1 + nxt = x_pow * x2 # Rust: x_pow.checked_mul(x2), None ends the loop + if not I128_MIN <= nxt <= I128_MAX: + break + x_pow = nxt + slack = count + 1 + return (total - slack, total + slack) + + +def pi_enclosure(): + a5, a239 = arctan_inv(5), arctan_inv(239) + return (16 * a5[0] - 4 * a239[1], 16 * a5[1] - 4 * a239[0]) + + +def octant_reduce(t, d): + t %= 2 * d + cos_sign, sin_sign = 1, 1 + if t > d: + t = 2 * d - t + sin_sign = -1 + if t > d // 2: + t = d - t + cos_sign = -cos_sign + swap = t > d // 4 + if swap: + t = d // 2 - t + return t, swap, cos_sign, sin_sign + + +def apply_sign(v, sign): + return (-v[1], -v[0]) if sign < 0 else v + + +def downscale_round(v, shift): + lo, hi = fshr(v[0], shift), cshr(v[1], shift) + entry = fdiv(lo + hi, 2) + return entry, max(entry - lo, hi - entry) + + +def build_tables(d, q): + pi_lo, pi_hi = pi_enclosure() + shift = TRIG_SCALE - q + first_octant = [] + for r in range(d // 4 + 1): + phi = (fdiv(pi_lo * r, d), cdiv(pi_hi * r, d)) + first_octant.append((taylor_cos(phi), taylor_sin(phi))) + base_cos, base_sin, eps_root = [0] * (2 * d), [0] * (2 * d), 0 + for t in range(2 * d): + r, swap, cos_sign, sin_sign = octant_reduce(t, d) + cos_phi, sin_phi = first_octant[r] + cos_a, sin_a = (sin_phi, cos_phi) if swap else (cos_phi, sin_phi) + c_val, c_err = downscale_round(apply_sign(cos_a, cos_sign), shift) + s_val, s_err = downscale_round(apply_sign(sin_a, sin_sign), shift) + base_cos[t], base_sin[t] = c_val, s_val + eps_root = max(eps_root, c_err, s_err) + return base_cos, base_sin, eps_root + + +def render(base_cos, base_sin, eps_root, digest): + def table(name, values): + body = "".join(f" {v},\n" for v in values) + return f"pub(super) static {name}: [i64; {len(values)}] = [\n{body}];\n" + + return ( + "//! Generated by `scripts/gen_op_norm_static_base.py`; do not edit.\n" + "//!\n" + f"//! Certified `base_cos` / `base_sin` tables of the D64 selective-L2\n" + f"//! operator-norm predicate (`d = {D}`, `q = {Q}`), as `i64`, and their\n" + "//! sound error bound. `static_base_equals_build_tables` checks every entry\n" + "//! against `build_tables`.\n" + f"//! SHA-256 of the little-endian `i64` entries (cos then sin): {digest}\n" + "\n" + f"pub(super) const D: usize = {D};\n" + f"pub(super) const Q: u32 = {Q};\n" + f"pub(super) const EPS_ROOT: i128 = {eps_root};\n" + "\n" + + table("BASE_COS", base_cos) + + "\n" + + table("BASE_SIN", base_sin) + ) + + +def main(argv): + out = Path(argv[1]) if len(argv) > 1 else Path(__file__).resolve().parent.parent / "src/sampler/op_norm/static_base.rs" + base_cos, base_sin, eps_root = build_tables(D, Q) + assert all(-(1 << 63) <= v < (1 << 63) for v in base_cos + base_sin), "entry does not fit i64" + blob = b"".join(struct.pack(" (i128, i128) { (sum - slack, sum + slack) } +// Static operator-norm base tables (feature `ont-static-base`, default off). The +// base tables are a pure function of `(d, q)`; with the feature, the D64 +// selective-L2 table (`d = 64`, `q = 48`) reads them from generated static +// data instead of evaluating the interval Taylor series, and every other +// `(d, q)` still builds them. The transposed `freq_*_at` rows are still built +// at run time. Without the feature `base_tables` is `build_tables` itself. +#[cfg(not(feature = "ont-static-base"))] +use self::build_tables as base_tables; + +#[cfg(feature = "ont-static-base")] +mod static_base; + +#[cfg(feature = "ont-static-base")] +fn base_tables(d: usize, q: u32) -> (Vec, Vec, i128) { + if d == static_base::D && q == static_base::Q { + let widen = |table: &[i64]| -> Vec { table.iter().map(|&v| i128::from(v)).collect() }; + return ( + widen(static_base::BASE_COS.as_slice()), + widen(static_base::BASE_SIN.as_slice()), + static_base::EPS_ROOT, + ); + } + build_tables(d, q) +} + +#[cfg(all(test, feature = "ont-static-base"))] +mod static_base_tests { + use super::*; + + /// The generated tables equal `build_tables` entry for entry, and the + /// table built through them equals the one built from `build_tables`. + #[test] + fn static_base_equals_build_tables() { + let (cos, sin, eps_root) = build_tables(static_base::D, static_base::Q); + assert_eq!(eps_root, static_base::EPS_ROOT); + assert_eq!(cos.len(), static_base::BASE_COS.len()); + assert_eq!(sin.len(), static_base::BASE_SIN.len()); + for (built, embedded) in cos.iter().zip(static_base::BASE_COS.iter()) { + assert_eq!(*built, i128::from(*embedded)); + } + for (built, embedded) in sin.iter().zip(static_base::BASE_SIN.iter()) { + assert_eq!(*built, i128::from(*embedded)); + } + assert_eq!( + base_tables(static_base::D, static_base::Q), + (cos.clone(), sin.clone(), eps_root) + ); + + let narrow = |table: &[i128]| -> Vec { + table.iter().map(|&v| i64::try_from(v).unwrap()).collect() + }; + let (freq_cos, freq_sin) = + op_norm_accumulate::build_freq_at_tables(static_base::D, &narrow(&cos), &narrow(&sin)); + let table = OpNormTable::new(static_base::D, static_base::Q, 53, 18).unwrap(); + assert_eq!(table.freq_cos_at, freq_cos); + assert_eq!(table.freq_sin_at, freq_sin); + assert_eq!(table.eps_root, eps_root); + assert!(table.strict_threshold_contains_shrunken_subset(48, 4, 18, 600)); + } + + #[test] + fn static_base_still_validates_admitted_bounds() { + assert!(OpNormTable::new(64, 48, 53, 18).is_ok()); + assert!(OpNormTable::new(64, 48, u64::MAX, 18).is_err()); + assert!(OpNormTable::new(64, 48, 53, u64::MAX).is_err()); + assert!(OpNormTable::new(0, 48, 53, 18).is_err()); + assert!(OpNormTable::new(64, 0, 53, 18).is_err()); + } + + /// Every other `(d, q)` still builds its tables. + #[test] + fn static_base_falls_back_elsewhere() { + assert_eq!(base_tables(128, 48), build_tables(128, 48)); + assert_eq!(base_tables(64, 40), build_tables(64, 40)); + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/akita-challenges/src/sampler/op_norm/static_base.rs b/crates/akita-challenges/src/sampler/op_norm/static_base.rs new file mode 100644 index 000000000..637a94cf3 --- /dev/null +++ b/crates/akita-challenges/src/sampler/op_norm/static_base.rs @@ -0,0 +1,273 @@ +//! Generated by `scripts/gen_op_norm_static_base.py`; do not edit. +//! +//! Certified `base_cos` / `base_sin` tables of the D64 selective-L2 +//! operator-norm predicate (`d = 64`, `q = 48`), as `i64`, and their +//! sound error bound. `static_base_equals_build_tables` checks every entry +//! against `build_tables`. +//! SHA-256 of the little-endian `i64` entries (cos then sin): fd2c192c42aa43710ef7c9947d0d8626a5fc621b87912b28e19ccc52c45b826f + +pub(super) const D: usize = 64; +pub(super) const Q: u32 = 48; +pub(super) const EPS_ROOT: i128 = 1; + +pub(super) static BASE_COS: [i64; 128] = [ + 281474976710656, + 281135927774059, + 280119597762857, + 278428435105064, + 276066513959653, + 273039524401542, + 269354758713710, + 265021093819447, + 260048969897066, + 254450365228603, + 248238767343085, + 241429140523889, + 234037889758477, + 226082821217338, + 217583099357370, + 208559200753021, + 199032864766430, + 189027041175396, + 178565834885358, + 167674447858561, + 156379118400326, + 144707057948671, + 132686385519576, + 120346059965811, + 107715810212517, + 94826063637631, + 81707872769660, + 68392840479422, + 54913043845964, + 41300956880066, + 27589372291508, + 13811322488556, + 0, + -13811322488557, + -27589372291509, + -41300956880067, + -54913043845965, + -68392840479423, + -81707872769661, + -94826063637632, + -107715810212518, + -120346059965811, + -132686385519577, + -144707057948672, + -156379118400327, + -167674447858562, + -178565834885359, + -189027041175397, + -199032864766431, + -208559200753022, + -217583099357371, + -226082821217339, + -234037889758478, + -241429140523890, + -248238767343086, + -254450365228604, + -260048969897067, + -265021093819448, + -269354758713711, + -273039524401543, + -276066513959654, + -278428435105065, + -280119597762858, + -281135927774060, + -281474976710656, + -281135927774060, + -280119597762858, + -278428435105065, + -276066513959654, + -273039524401543, + -269354758713711, + -265021093819448, + -260048969897067, + -254450365228604, + -248238767343086, + -241429140523890, + -234037889758478, + -226082821217339, + -217583099357371, + -208559200753022, + -199032864766431, + -189027041175397, + -178565834885359, + -167674447858562, + -156379118400327, + -144707057948672, + -132686385519577, + -120346059965811, + -107715810212518, + -94826063637632, + -81707872769661, + -68392840479423, + -54913043845965, + -41300956880067, + -27589372291509, + -13811322488557, + 0, + 13811322488556, + 27589372291508, + 41300956880066, + 54913043845964, + 68392840479422, + 81707872769660, + 94826063637631, + 107715810212517, + 120346059965811, + 132686385519576, + 144707057948671, + 156379118400326, + 167674447858561, + 178565834885358, + 189027041175396, + 199032864766430, + 208559200753021, + 217583099357370, + 226082821217338, + 234037889758477, + 241429140523889, + 248238767343085, + 254450365228603, + 260048969897066, + 265021093819447, + 269354758713710, + 273039524401542, + 276066513959653, + 278428435105064, + 280119597762857, + 281135927774059, +]; + +pub(super) static BASE_SIN: [i64; 128] = [ + 0, + 13811322488556, + 27589372291508, + 41300956880066, + 54913043845964, + 68392840479422, + 81707872769660, + 94826063637631, + 107715810212517, + 120346059965811, + 132686385519576, + 144707057948671, + 156379118400326, + 167674447858561, + 178565834885358, + 189027041175396, + 199032864766430, + 208559200753021, + 217583099357370, + 226082821217338, + 234037889758477, + 241429140523889, + 248238767343085, + 254450365228603, + 260048969897066, + 265021093819447, + 269354758713710, + 273039524401542, + 276066513959653, + 278428435105064, + 280119597762857, + 281135927774059, + 281474976710656, + 281135927774059, + 280119597762857, + 278428435105064, + 276066513959653, + 273039524401542, + 269354758713710, + 265021093819447, + 260048969897066, + 254450365228603, + 248238767343085, + 241429140523889, + 234037889758477, + 226082821217338, + 217583099357370, + 208559200753021, + 199032864766430, + 189027041175396, + 178565834885358, + 167674447858561, + 156379118400326, + 144707057948671, + 132686385519576, + 120346059965811, + 107715810212517, + 94826063637631, + 81707872769660, + 68392840479422, + 54913043845964, + 41300956880066, + 27589372291508, + 13811322488556, + 0, + -13811322488557, + -27589372291509, + -41300956880067, + -54913043845965, + -68392840479423, + -81707872769661, + -94826063637632, + -107715810212518, + -120346059965811, + -132686385519577, + -144707057948672, + -156379118400327, + -167674447858562, + -178565834885359, + -189027041175397, + -199032864766431, + -208559200753022, + -217583099357371, + -226082821217339, + -234037889758478, + -241429140523890, + -248238767343086, + -254450365228604, + -260048969897067, + -265021093819448, + -269354758713711, + -273039524401543, + -276066513959654, + -278428435105065, + -280119597762858, + -281135927774060, + -281474976710656, + -281135927774060, + -280119597762858, + -278428435105065, + -276066513959654, + -273039524401543, + -269354758713711, + -265021093819448, + -260048969897067, + -254450365228604, + -248238767343086, + -241429140523890, + -234037889758478, + -226082821217339, + -217583099357371, + -208559200753022, + -199032864766431, + -189027041175397, + -178565834885359, + -167674447858562, + -156379118400327, + -144707057948672, + -132686385519577, + -120346059965811, + -107715810212518, + -94826063637632, + -81707872769661, + -68392840479423, + -54913043845965, + -41300956880067, + -27589372291509, + -13811322488557, +]; From bbedf3826362ce9ac5adf0aa78f0cb54adf7fc59 Mon Sep 17 00:00:00 2001 From: acentelles Date: Fri, 23 Oct 2026 15:29:09 +0100 Subject: [PATCH 04/17] perf(verifier): evaluate the compression relation weights by factor The compression relation table records one event per (gadget bit, source row, coefficient block) for every recomposition and one event per column for every compression row, and the verifier evaluated the table's multilinear extension event by event. Each of these families is an arithmetic progression of aligned events whose scalars are a row factor times a shared table: the lifted gadget powers, or one evaluated compression matrix's columns. The builder now records each such family as one group, and `CompressionRelationWeights::evaluate_at_point` evaluates a group's extension by factor: the shared alpha low factor, times dyadic blocks over the high index (a geometric table closes each block in a product of log factors, any other table caches the block's extension), or a loop over the per-event equality window when the stride is not a power of two. Every split is over disjoint digit positions of one index, so the value is the multilinear extension of the same dense table at every field point. A family that fails any precondition (alignment, domain, overflow, a zero gadget entry, a zero source ring dimension) is pushed event by event, so accepted inputs and errors are unchanged. Prover-side materialization (`into_sparse_entries`, dense accumulation) expands the groups back into their events, so prover output is unchanged. No proof byte, transcript or verifier decision changes. Unit tests compare the grouped path with the per-event path and with dense multilinear evaluation at random, zero, one and mixed points, including every evaluation tier, unaligned runs, clipped runs, interior and trailing zero columns and the error paths. The reduced-program test now counts and domain-checks grouped events as well. --- .../src/proof/compression_relation_weights.rs | 89 +- .../compression_relation_weights/factored.rs | 998 ++++++++++++++++++ .../compression_relation_weights/reduced.rs | 9 +- 3 files changed, 1066 insertions(+), 30 deletions(-) create mode 100644 crates/akita-types/src/proof/compression_relation_weights/factored.rs diff --git a/crates/akita-types/src/proof/compression_relation_weights.rs b/crates/akita-types/src/proof/compression_relation_weights.rs index 48bf13194..198bd738e 100644 --- a/crates/akita-types/src/proof/compression_relation_weights.rs +++ b/crates/akita-types/src/proof/compression_relation_weights.rs @@ -1,9 +1,12 @@ //! Shared compact F/H relation weights for prover materialization and verifier evaluation. +mod factored; mod reduced; pub use reduced::{build_reduced_compression_relation_weights, ReducedCompressionRelationWeights}; +use factored::push_recomposition; + use akita_algebra::eq_poly::EqPolynomial; use akita_algebra::offset_eq::{ eval_boolean_pair_tensor_families, EqPairTensorAxis, EqPairTensorFamily, OffsetEqWindow, @@ -39,12 +42,17 @@ struct EvaluatedCompressionMatrix { } /// Canonical additive relation table for every F/H compression layer. +/// +/// Events are stored individually or, for the recomposition and column +/// families, as `factored::Groups` of aligned progressions whose scalars +/// share one table; both forms describe the same additive table. #[derive(Clone, Debug)] pub struct CompressionRelationWeights { events: Vec>, alpha_powers: Vec, coefficient_block_len: usize, physical_field_len: usize, + groups: factored::Groups, } /// Checked sparse support for the negative-binary compression digits. @@ -190,7 +198,8 @@ impl CompressionRelationWeights { actual: weights.len(), }); } - for event in &self.events { + let expanded = self.expanded_group_events()?; + for event in self.events.iter().chain(&expanded) { let alpha = self .alpha_powers .get( @@ -229,6 +238,9 @@ impl CompressionRelationWeights { pub fn into_sparse_entries(mut self) -> Result, AkitaError> { /// Coefficients per parallel task, rounded up to whole clusters. const TASK_COEFFICIENTS: usize = 1 << 14; + let expanded = self.expanded_group_events()?; + self.events.extend(expanded); + self.groups = factored::Groups::default(); self.events .sort_unstable_by_key(|event| event.physical_start); // `push` bounds every event inside the physical domain, so these @@ -299,8 +311,18 @@ impl CompressionRelationWeights { } /// Evaluate the table's multilinear extension at one full witness point. + /// + /// Ungrouped events take the per-event path and groups are evaluated by + /// factor (see the `factored` module); the sum is the multilinear + /// extension of the dense table. #[tracing::instrument(skip_all, name = "compression_relation_mle")] pub fn evaluate_at_point(&self, point: &[E]) -> Result { + let events = self.evaluate_events_at_point(point)?; + Ok(events + self.evaluate_groups_at_point(point)?) + } + + /// The multilinear extension of the ungrouped events at `point`. + fn evaluate_events_at_point(&self, point: &[E]) -> Result { if checked::pow2(point.len()) != Some(self.physical_field_len) { return Err(AkitaError::InvalidSize { expected: self.physical_field_len.trailing_zeros() as usize, @@ -408,8 +430,10 @@ impl CompressionRelationWeights { } } +/// Push one recomposition as individual events (the fallback of +/// `factored::push_recomposition`). #[allow(clippy::too_many_arguments)] -fn push_recomposition( +fn push_recomposition_canonical( weights: &mut CompressionRelationWeights, span_start: usize, digit_ring_dim: usize, @@ -672,6 +696,7 @@ where alpha_powers: scalar_powers(alpha, maximum_dimension), coefficient_block_len, physical_field_len, + groups: factored::Groups::default(), }; let field_bits = usize::try_from(F::MODULUS_BITS) .map_err(|_| AkitaError::InvalidSetup("compression field width overflow".into()))?; @@ -736,20 +761,14 @@ where let evaluated = evaluated_matrices.get(matrix_index).ok_or_else(|| { AkitaError::Internal("evaluated compression matrix cache entry is missing".into()) })?; - for column in 0..map.input_width() { - let start = column * map.ring_dimension(); - weights.push( - span.range().start + start, - map.ring_dimension(), - 0, - row_weight - * evaluated.columns.get(column).copied().ok_or_else(|| { - AkitaError::Internal( - "compression column exceeds the evaluated column table".into(), - ) - })?, - )?; - } + weights.push_column_group( + span.range().start, + map.ring_dimension(), + map.input_width(), + row_weight, + matrix_index, + &evaluated.columns, + )?; if let Some(successor) = successor_compression_span(witness_layout, group_index, map_index)? { push_recomposition::( @@ -794,25 +813,36 @@ mod tests { #[test] fn sparse_evaluator_matches_dense_materialization() { - let mut weights = CompressionRelationWeights { - events: Vec::new(), - alpha_powers: (1..=16).map(F::from_u64).collect(), - coefficient_block_len: 2, - physical_field_len: 16, - }; - weights.push(0, 4, 0, F::from_u64(3)).unwrap(); - weights.push(6, 2, 4, F::from_u64(5)).unwrap(); - weights.push(8, 8, 0, F::from_u64(7)).unwrap(); let point = [ F::from_u64(11), F::from_u64(13), F::from_u64(17), F::from_u64(19), ]; - assert_eq!( - weights.evaluate_at_point(&point).unwrap(), - multilinear_eval(&weights.materialize_dense().unwrap(), &point).unwrap() - ); + for event_count in [0, 1, 3, 31, 32, 33, 64, 65] { + let mut weights = CompressionRelationWeights { + events: Vec::new(), + alpha_powers: (1..=16).map(F::from_u64).collect(), + coefficient_block_len: 2, + physical_field_len: 16, + groups: factored::Groups::default(), + }; + for (start, count, alpha_start, scalar) in + [(0, 4, 0, 3), (6, 2, 4, 5), (8, 8, 0, 7), (2, 4, 2, 11)] + .into_iter() + .cycle() + .take(event_count) + { + weights + .push(start, count, alpha_start, F::from_u64(scalar)) + .unwrap(); + } + assert_eq!( + weights.evaluate_at_point(&point).unwrap(), + multilinear_eval(&weights.materialize_dense().unwrap(), &point).unwrap(), + "event_count={event_count}", + ); + } } /// Unsorted, overlapping, cancelling, and task-spanning events give the @@ -825,6 +855,7 @@ mod tests { alpha_powers: (1..=4096).map(F::from_u64).collect(), coefficient_block_len: 8, physical_field_len, + groups: factored::Groups::default(), }; for index in 0..600usize { let coefficient_count = 8 << (index % 5); diff --git a/crates/akita-types/src/proof/compression_relation_weights/factored.rs b/crates/akita-types/src/proof/compression_relation_weights/factored.rs new file mode 100644 index 000000000..77db52473 --- /dev/null +++ b/crates/akita-types/src/proof/compression_relation_weights/factored.rs @@ -0,0 +1,998 @@ +//! Factorized evaluation of the recomposition and column compression events. +//! +//! The builder emits one event per (gadget bit, source row, coefficient block) +//! for every recomposition, and one event per column for every compression +//! row. Each such family is an arithmetic progression of aligned events whose +//! scalars are a common row factor times a shared table (the lifted gadget +//! powers, or one evaluated matrix's columns). This module records each family +//! as one [`CompressionEventGroup`] and evaluates the multilinear extension of +//! its events by factor: +//! +//! `sum_j sigma * y_j * L * eq(R, h0 + j T) = sigma * L * S`, +//! +//! where `sigma` is the row factor, `y_j` the table, `L` the shared alpha low +//! factor over the `log2(count)` low coordinates, `R` the remaining (high) +//! coordinates, `h0` the high index of the first event and `T` the high +//! stride. `S` is computed by dyadic blocks when `T` is a power of two (a +//! geometric table closes each block as a product of `log` factors, any other +//! table caches the block's multilinear extension) or otherwise by a loop over +//! the per-event equality window. +//! +//! Every factorization splits disjoint digit positions of one index, so the +//! value is exactly the multilinear extension of the dense table at arbitrary +//! field points; it never multiplies the extensions of two tables over the +//! same variables. A family that fails any precondition is pushed event by +//! event, so the accepted inputs and the errors are those of the per-event +//! path. Prover-side materialization expands the groups back into events. + +use super::*; + +/// Cached dyadic block extensions keyed by (table, offset, block bits, first +/// point coordinate). +type BlockCache = Vec<((usize, usize, usize, usize), E)>; + +/// Shared value table of one or more groups. +#[derive(Clone, Debug)] +pub(super) struct GroupTable { + values: Vec, + /// `beta^(2^i)` for `i <= floor(log2(len))` when the table is verified + /// geometric (`values[0] == 1`, `values[j] == values[j - 1] * beta`). + ratio_squares: Option>, + /// Every entry is nonzero. + all_nonzero: bool, +} + +impl GroupTable { + fn new(values: Vec, check_geometric: bool) -> Self { + let all_nonzero = values.iter().all(|value| !value.is_zero()); + let ratio_squares = if check_geometric { + Self::geometric_squares(&values) + } else { + None + }; + Self { + values, + ratio_squares, + all_nonzero, + } + } + + fn geometric_squares(values: &[E]) -> Option> { + let first = *values.first()?; + if first != E::one() { + return None; + } + let beta = values.get(1).copied().unwrap_or_else(E::one); + let mut previous = first; + for &value in values.iter().skip(1) { + if value != previous * beta { + return None; + } + previous = value; + } + let levels = usize::BITS as usize - values.len().leading_zeros() as usize; + let mut squares = Vec::with_capacity(levels.max(1)); + let mut square = beta; + for _ in 0..levels.max(1) { + squares.push(square); + let next = square * square; + square = next; + } + Some(squares) + } +} + +/// One arithmetic progression of aligned compression events: +/// `(physical_start + j * stride, coefficient_count, alpha_exponent_start, +/// scalar * table[j])` for `j < len`. +#[derive(Clone, Debug)] +pub(super) struct CompressionEventGroup { + physical_start: usize, + stride: usize, + len: usize, + coefficient_count: usize, + alpha_exponent_start: usize, + scalar: E, + table: usize, +} + +/// Group storage carried by [`CompressionRelationWeights`]. +#[derive(Clone, Debug)] +pub(super) struct Groups { + groups: Vec>, + tables: Vec>, + /// `(gadget levels, table index)`. + gadget_tables: Vec<(usize, usize)>, + /// `(evaluated matrix index, table index)`. + column_tables: Vec<(usize, usize)>, +} + +#[allow(clippy::derivable_impls)] +impl Default for Groups { + fn default() -> Self { + Self { + groups: Vec::new(), + tables: Vec::new(), + gadget_tables: Vec::new(), + column_tables: Vec::new(), + } + } +} + +/// Equality factor of `value` over `coordinates` (little-endian digits); zero +/// when `value` is outside the coordinates' domain, as `eq_eval_at_index`. +fn eq_bits(coordinates: &[E], value: usize) -> E { + if coordinates.len() < usize::BITS as usize && value >> coordinates.len() != 0 { + return E::zero(); + } + coordinates + .iter() + .enumerate() + .fold(E::one(), |acc, (bit, &coordinate)| { + if bit < usize::BITS as usize && (value >> bit) & 1 == 1 { + acc * coordinate + } else { + acc * (E::one() - coordinate) + } + }) +} + +impl CompressionRelationWeights { + /// Canonical admission test of one event (the checks of `push`), without + /// recording it. + fn admits_event( + &self, + physical_start: usize, + coefficient_count: usize, + alpha_exponent_start: usize, + ) -> bool { + let (Some(physical_end), Some(alpha_end)) = ( + physical_start.checked_add(coefficient_count), + alpha_exponent_start.checked_add(coefficient_count), + ) else { + return false; + }; + coefficient_count != 0 + && coefficient_count.is_power_of_two() + && physical_start.is_multiple_of(self.coefficient_block_len) + && coefficient_count.is_multiple_of(self.coefficient_block_len) + && alpha_exponent_start.is_multiple_of(self.coefficient_block_len) + && physical_end <= self.physical_field_len + && alpha_end <= self.alpha_powers.len() + } + + /// Whether every element `j < len` of a progression would be admitted by + /// `push` and takes the aligned evaluation path. The admission checks are + /// affine or monotone in `j`, so the first two and the last elements + /// decide them. + fn admits_progression( + &self, + physical_start: usize, + stride: usize, + len: usize, + coefficient_count: usize, + alpha_exponent_start: usize, + ) -> bool { + let Some(last_offset) = len.checked_sub(1).and_then(|last| last.checked_mul(stride)) else { + return len == 0; + }; + let Some(last_start) = physical_start.checked_add(last_offset) else { + return false; + }; + let second_ok = len < 2 + || physical_start.checked_add(stride).is_some_and(|second| { + self.admits_event(second, coefficient_count, alpha_exponent_start) + }); + coefficient_count.is_power_of_two() + && physical_start.is_multiple_of(coefficient_count) + && (len < 2 || stride.is_multiple_of(coefficient_count)) + && self.admits_event(physical_start, coefficient_count, alpha_exponent_start) + && second_ok + && self.admits_event(last_start, coefficient_count, alpha_exponent_start) + } + + fn gadget_table(&mut self, levels: usize) -> usize + where + F: Field + CanonicalEncoding, + E: ExtField, + { + if let Some(&(_, index)) = self + .groups + .gadget_tables + .iter() + .find(|(cached, _)| *cached == levels) + { + return index; + } + let values = gadget_row_scalars::(levels, 1) + .into_iter() + .map(>::lift_base) + .collect::>(); + self.groups.tables.push(GroupTable::new(values, true)); + let index = self.groups.tables.len() - 1; + self.groups.gadget_tables.push((levels, index)); + index + } + + /// Record the column events of one compression row: element `j` is + /// `(span_start + j * ring_dimension, ring_dimension, 0, row_weight * + /// columns[j])`. Falls back to the canonical loop when any precondition + /// fails. + pub(super) fn push_column_group( + &mut self, + span_start: usize, + ring_dimension: usize, + input_width: usize, + row_weight: E, + matrix_index: usize, + columns: &[E], + ) -> Result<(), AkitaError> { + let len = columns + .get(..input_width) + .and_then(|live| live.iter().rposition(|value| !value.is_zero())) + .map_or(0, |last| last + 1); + let grouped = columns.len() >= input_width + && (row_weight.is_zero() + || len == 0 + || self.admits_progression(span_start, ring_dimension, len, ring_dimension, 0)); + if !grouped { + return self.push_columns_canonical( + span_start, + ring_dimension, + input_width, + row_weight, + columns, + ); + } + if row_weight.is_zero() || len == 0 { + // Every canonical scalar is zero, so `push` records nothing. + return Ok(()); + } + let table = if let Some(&(_, index)) = self + .groups + .column_tables + .iter() + .find(|(cached, _)| *cached == matrix_index) + { + index + } else { + self.groups.tables.push(GroupTable::new( + columns.get(..input_width).unwrap_or(columns).to_vec(), + false, + )); + let index = self.groups.tables.len() - 1; + self.groups.column_tables.push((matrix_index, index)); + index + }; + self.groups.groups.push(CompressionEventGroup { + physical_start: span_start, + stride: ring_dimension, + len, + coefficient_count: ring_dimension, + alpha_exponent_start: 0, + scalar: row_weight, + table, + }); + Ok(()) + } + + /// The per-event column loop of `build_compression_relation_weights`: one + /// event per column. + fn push_columns_canonical( + &mut self, + span_start: usize, + ring_dimension: usize, + input_width: usize, + row_weight: E, + columns: &[E], + ) -> Result<(), AkitaError> { + for column in 0..input_width { + let start = column * ring_dimension; + self.push( + span_start + start, + ring_dimension, + 0, + row_weight + * columns.get(column).copied().ok_or_else(|| { + AkitaError::Internal( + "compression column exceeds the evaluated column table".into(), + ) + })?, + )?; + } + Ok(()) + } + + /// Canonical events of every group, zero scalars dropped as `push` does. + pub(super) fn expanded_group_events( + &self, + ) -> Result>, AkitaError> { + let mut events = Vec::new(); + for group in &self.groups.groups { + let table = + self.groups.tables.get(group.table).ok_or_else(|| { + AkitaError::Internal("compression group table is missing".into()) + })?; + let values = table.values.get(..group.len).ok_or_else(|| { + AkitaError::Internal("compression group exceeds its table".into()) + })?; + for (index, &value) in values.iter().enumerate() { + let scalar = group.scalar * value; + if scalar.is_zero() { + continue; + } + events.push(CompressionRelationEvent { + physical_start: group.physical_start + index * group.stride, + coefficient_count: group.coefficient_count, + alpha_exponent_start: group.alpha_exponent_start, + scalar, + }); + } + } + Ok(events) + } + + /// Sum of every group's events' extension at `point`, by factor. + pub(super) fn evaluate_groups_at_point(&self, point: &[E]) -> Result { + let mut low_factors = Vec::<((usize, usize), E)>::new(); + let mut windows = Vec::<(usize, OffsetEqWindow)>::new(); + let mut blocks = BlockCache::::new(); + let mut evaluation = E::zero(); + for group in &self.groups.groups { + let count = group.coefficient_count; + let low_bits = count.trailing_zeros() as usize; + let key = (group.alpha_exponent_start, count); + let low_factor = + if let Some((_, value)) = low_factors.iter().find(|(cached, _)| *cached == key) { + *value + } else { + let powers = group + .alpha_exponent_start + .checked_add(count) + .and_then(|end| self.alpha_powers.get(group.alpha_exponent_start..end)) + .ok_or_else(|| { + AkitaError::Internal( + "compression group exceeds the alpha power table".into(), + ) + })?; + let low_point = point.get(..low_bits).ok_or_else(|| { + AkitaError::Internal("compression group low point exceeds the point".into()) + })?; + let value = multilinear_eval(powers, low_point)?; + low_factors.push((key, value)); + value + }; + let high_point = point.get(low_bits..).ok_or_else(|| { + AkitaError::Internal("compression group high point exceeds the point".into()) + })?; + let table = + self.groups.tables.get(group.table).ok_or_else(|| { + AkitaError::Internal("compression group table is missing".into()) + })?; + let values = table.values.get(..group.len).ok_or_else(|| { + AkitaError::Internal("compression group exceeds its table".into()) + })?; + let first_high = group.physical_start >> low_bits; + let high_stride = group.stride >> low_bits; + let sum = if group.len == 1 || high_stride.is_power_of_two() { + let stride_bits = if group.len == 1 { + 0 + } else { + high_stride.trailing_zeros() as usize + }; + Self::dyadic_sum( + table, + values, + group.table, + high_point, + low_bits, + first_high, + stride_bits, + &mut blocks, + )? + } else { + let window_index = if let Some(index) = + windows.iter().position(|(cached, _)| *cached == low_bits) + { + index + } else { + let balanced_low_bits = high_point.len().div_ceil(2); + windows.push(( + low_bits, + OffsetEqWindow::with_low_bits(high_point, balanced_low_bits)?, + )); + windows.len() - 1 + }; + let window = &windows + .get(window_index) + .ok_or_else(|| { + AkitaError::Internal("compression group equality window is missing".into()) + })? + .1; + let mut sum = E::zero(); + let mut index = first_high; + for &value in values { + sum += value * window.eval(index); + index = index.wrapping_add(high_stride); + } + sum + }; + evaluation += group.scalar * low_factor * sum; + } + Ok(evaluation) + } + + /// `sum_j values[j] * eq(high_point, first_high + j * 2^stride_bits)` by + /// dyadic blocks. + /// + /// The low `stride_bits` digits of every index equal those of + /// `first_high`, so their equality factor is shared. The run + /// `(first_high >> stride_bits) + j` is split into maximal aligned blocks of + /// `2^b` indices; inside a block the low `b` digits range over all values + /// and the high digits are fixed, so the block contributes + /// `eq(rest, block index) * MLE(block values)(block point)`. For a + /// geometric table `values[j] = beta^j` the block extension is + /// `beta^offset * prod_i ((1 - r_i) + r_i * beta^(2^i))`. + #[allow(clippy::too_many_arguments)] + fn dyadic_sum( + table: &GroupTable, + values: &[E], + table_index: usize, + high_point: &[E], + low_bits: usize, + first_high: usize, + stride_bits: usize, + blocks: &mut BlockCache, + ) -> Result { + let (stride_point, run_point) = if stride_bits <= high_point.len() { + high_point.split_at(stride_bits) + } else { + return Err(AkitaError::Internal( + "compression group stride exceeds the point".into(), + )); + }; + let low_mask = (1usize << stride_bits) - 1; + let stride_factor = eq_bits(stride_point, first_high & low_mask); + let start = first_high >> stride_bits; + let end = start + .checked_add(values.len()) + .ok_or_else(|| AkitaError::Internal("compression group run overflow".into()))?; + let mut sum = E::zero(); + let mut position = start; + let mut ratio_power = E::one(); + while position < end { + let remaining = end - position; + let size_bits = (usize::BITS - 1 - remaining.leading_zeros()) as usize; + let block_bits = if position == 0 { + size_bits + } else { + size_bits.min(position.trailing_zeros() as usize) + }; + let block_len = 1usize << block_bits; + let offset = position - start; + let (block_point, rest_point) = if block_bits <= run_point.len() { + run_point.split_at(block_bits) + } else { + return Err(AkitaError::Internal( + "compression group block exceeds the point".into(), + )); + }; + let high_factor = eq_bits(rest_point, position >> block_bits); + let block = if let Some(squares) = &table.ratio_squares { + let product = block_point.iter().zip(squares).fold( + E::one(), + |acc, (&coordinate, &square)| { + acc * ((E::one() - coordinate) + coordinate * square) + }, + ); + ratio_power * product + } else { + let key = (table_index, offset, block_bits, low_bits + stride_bits); + if let Some((_, value)) = blocks.iter().find(|(cached, _)| *cached == key) { + *value + } else { + let slice = values.get(offset..offset + block_len).ok_or_else(|| { + AkitaError::Internal("compression group block exceeds its table".into()) + })?; + let value = multilinear_eval(slice, block_point)?; + blocks.push((key, value)); + value + } + }; + sum += high_factor * block; + if let Some(squares) = &table.ratio_squares { + // Advance beta^(position - start) by beta^(2^block_bits) when + // another block follows. + if position + block_len < end { + let square = squares.get(block_bits).ok_or_else(|| { + AkitaError::Internal("compression group ratio square is missing".into()) + })?; + ratio_power *= *square; + } + } + position += block_len; + } + Ok(stride_factor * sum) + } +} + +/// Recomposition events grouped by (source row, coefficient block) over the +/// gadget bits, or the canonical loop when any group fails a precondition. +#[allow(clippy::too_many_arguments)] +pub(super) fn push_recomposition( + weights: &mut CompressionRelationWeights, + span_start: usize, + digit_ring_dim: usize, + source_coefficients: usize, + source_ring_dim: usize, + source_row_start: usize, + source_row_count: usize, + field_bits: usize, + row_weights: &[E], +) -> Result<(), AkitaError> +where + F: Field + CanonicalEncoding, + E: FpExtEncoding + Ring + ExtField, +{ + let planned = plan_recomposition_groups::( + weights, + span_start, + digit_ring_dim, + source_coefficients, + source_ring_dim, + source_row_start, + source_row_count, + field_bits, + row_weights, + ); + match planned { + Some(groups) => { + weights.groups.groups.extend(groups); + Ok(()) + } + None => push_recomposition_canonical::( + weights, + span_start, + digit_ring_dim, + source_coefficients, + source_ring_dim, + source_row_start, + source_row_count, + field_bits, + row_weights, + ), + } +} + +/// Groups for one canonical `push_recomposition` call, or `None` when the +/// canonical loop must run (any error, overflow, misalignment, or a table +/// with a zero entry). +#[allow(clippy::too_many_arguments)] +fn plan_recomposition_groups( + weights: &mut CompressionRelationWeights, + span_start: usize, + digit_ring_dim: usize, + source_coefficients: usize, + source_ring_dim: usize, + source_row_start: usize, + source_row_count: usize, + field_bits: usize, + row_weights: &[E], +) -> Option>> +where + F: Field + CanonicalEncoding, + E: FpExtEncoding + Ring + ExtField, +{ + // A zero source ring dimension records no events, but the canonical loop + // still reads every row weight; it runs so a short table fails the same way. + if digit_ring_dim == 0 + || source_ring_dim == 0 + || !source_ring_dim.is_multiple_of(digit_ring_dim) + || source_row_count.checked_mul(source_ring_dim) != Some(source_coefficients) + { + return None; + } + let mut groups = Vec::new(); + if field_bits == 0 || source_row_count == 0 { + return Some(groups); + } + // The canonical loop computes every start with checked additions after an + // unchecked `bit * source_coefficients`; the largest one must not overflow. + let largest = (field_bits - 1) + .checked_mul(source_coefficients) + .and_then(|offset| span_start.checked_add(offset)) + .and_then(|start| start.checked_add((source_row_count - 1).checked_mul(source_ring_dim)?)) + .and_then(|start| start.checked_add(source_ring_dim - digit_ring_dim)); + largest?; + let table = weights.gadget_table::(field_bits); + if !weights.groups.tables.get(table)?.all_nonzero { + return None; + } + for source_row in 0..source_row_count { + let row_weight = *row_weights.get(source_row_start.checked_add(source_row)?)?; + if row_weight.is_zero() { + continue; + } + for coefficient_start in (0..source_ring_dim).step_by(digit_ring_dim) { + let physical_start = span_start + .checked_add(source_row * source_ring_dim)? + .checked_add(coefficient_start)?; + if !weights.admits_progression( + physical_start, + source_coefficients, + field_bits, + digit_ring_dim, + coefficient_start, + ) { + return None; + } + groups.push(CompressionEventGroup { + physical_start, + stride: source_coefficients, + len: field_bits, + coefficient_count: digit_ring_dim, + alpha_exponent_start: coefficient_start, + scalar: -row_weight, + table, + }); + } + } + Some(groups) +} + +#[cfg(test)] +mod tests { + use super::*; + use jolt_field::Prime128OffsetA7F7 as F; + use jolt_field::{One, Zero}; + + /// Deterministic full-width field elements (no external RNG). + struct Stream(u64); + + impl Stream { + fn next_u64(&mut self) -> u64 { + self.0 ^= self.0 << 13; + self.0 ^= self.0 >> 7; + self.0 ^= self.0 << 17; + self.0 + } + + fn field(&mut self) -> F { + let high = F::from_u64(self.next_u64()); + high * F::from_u64(self.next_u64()) + F::from_u64(self.next_u64()) + } + + fn point(&mut self, len: usize) -> Vec { + (0..len).map(|_| self.field()).collect() + } + } + + fn empty( + physical_field_len: usize, + alpha_len: usize, + block: usize, + stream: &mut Stream, + ) -> CompressionRelationWeights { + CompressionRelationWeights { + events: Vec::new(), + alpha_powers: (0..alpha_len).map(|_| stream.field()).collect(), + coefficient_block_len: block, + physical_field_len, + groups: Groups::default(), + } + } + + /// The same table built through the canonical loops only. + fn canonical_twin(weights: &CompressionRelationWeights) -> CompressionRelationWeights { + let mut twin = weights.clone(); + twin.events.extend(weights.expanded_group_events().unwrap()); + twin.groups = Groups::default(); + twin + } + + /// Points with random, zero and one coordinates. + fn points(n: usize, stream: &mut Stream) -> Vec> { + let mut out = vec![ + stream.point(n), + stream.point(n), + vec![F::zero(); n], + vec![F::one(); n], + ]; + let mut mixed = stream.point(n); + for (index, coordinate) in mixed.iter_mut().enumerate() { + if index % 3 == 0 { + *coordinate = F::zero(); + } else if index % 3 == 1 { + *coordinate = F::one(); + } + } + out.push(mixed); + out + } + + fn assert_all_agree(weights: &CompressionRelationWeights, stream: &mut Stream, label: &str) { + let n = weights.physical_field_len.trailing_zeros() as usize; + let dense = weights.materialize_dense().unwrap(); + let twin = canonical_twin(weights); + assert_eq!(twin.materialize_dense().unwrap(), dense, "{label}: dense"); + for point in points(n, stream) { + let expected = multilinear_eval(&dense, &point).unwrap(); + assert_eq!( + weights.evaluate_at_point(&point).unwrap(), + expected, + "{label}: factorized" + ); + assert_eq!( + twin.evaluate_events_at_point(&point).unwrap(), + expected, + "{label}: canonical" + ); + } + assert_eq!( + weights.clone().into_sparse_entries().unwrap(), + twin.into_sparse_entries().unwrap(), + "{label}: sparse entries" + ); + } + + /// Recomposition calls of many geometries agree with the canonical loop + /// and the dense extension at random, zero, one and mixed points. + #[test] + fn recomposition_groups_match_canonical() { + let mut stream = Stream(0x9e37_79b9_7f4a_7c15); + // (span_start, digit, source_coefficients, source_ring_dim, rows, field_bits, n) + let cases = [ + (0usize, 4usize, 16usize, 16usize, 1usize, 8usize, 9usize), // dyadic, aligned + (32, 4, 16, 16, 1, 8, 9), // unaligned run start + (0, 4, 48, 16, 3, 5, 10), // stride not a power of two + (64, 2, 8, 8, 1, 7, 9), // clipped run (7 bits) + (0, 1, 2, 2, 1, 128, 9), // count 1 (k = 0), 128 bits + (16, 8, 16, 8, 2, 3, 8), // two rows + (0, 4, 16, 16, 1, 1, 8), // a single bit + (0, 4, 16, 16, 1, 0, 8), // no bits at all + ]; + for (index, &(span, digit, source, ring, rows, bits, n)) in cases.iter().enumerate() { + let mut weights = empty(1 << n, 64, 1, &mut stream); + let mut canonical = weights.clone(); + let row_weights = stream.point(rows + 2); + push_recomposition::( + &mut weights, + span, + digit, + source, + ring, + 1, + rows, + bits, + &row_weights, + ) + .unwrap(); + push_recomposition_canonical::( + &mut canonical, + span, + digit, + source, + ring, + 1, + rows, + bits, + &row_weights, + ) + .unwrap(); + assert!( + weights.events.is_empty(), + "case {index}: every recomposition is grouped" + ); + // A raw canonical event in the same table. + let scalar = stream.field(); + weights.push(0, 2, 2, scalar).unwrap(); + canonical.push(0, 2, 2, scalar).unwrap(); + assert_eq!( + weights.materialize_dense().unwrap(), + canonical.materialize_dense().unwrap(), + "case {index}: grouped and canonical tables" + ); + assert_all_agree( + &weights, + &mut stream, + &format!("recomposition case {index}"), + ); + } + } + + /// Zero row weights record nothing, as the canonical loop. + #[test] + fn zero_row_weight_records_nothing() { + let mut stream = Stream(7); + let mut weights = empty(1 << 9, 64, 1, &mut stream); + push_recomposition::(&mut weights, 0, 4, 16, 16, 0, 1, 8, &[F::zero()]).unwrap(); + assert!(weights.groups.groups.is_empty() && weights.events.is_empty()); + weights + .push_column_group(0, 4, 8, F::zero(), 0, &stream.point(8)) + .unwrap(); + assert!(weights.groups.groups.is_empty() && weights.events.is_empty()); + } + + /// Column groups: shared tables, interior and trailing zeros, widths that + /// are not powers of two, unaligned spans, and the canonical fallback. + #[test] + fn column_groups_match_canonical() { + let mut stream = Stream(0x1234_5678_9abc_def1); + let n = 10; + let mut weights = empty(1 << n, 64, 2, &mut stream); + let mut columns = stream.point(12); + columns[3] = F::zero(); + columns[10] = F::zero(); + columns[11] = F::zero(); + let mut canonical = weights.clone(); + for span in [0usize, 64, 128, 256] { + let row_weight = stream.field(); + weights + .push_column_group(span, 4, 12, row_weight, 0, &columns) + .unwrap(); + canonical + .push_columns_canonical(span, 4, 12, row_weight, &columns) + .unwrap(); + } + let other = stream.point(5); + let row_weight = stream.field(); + weights + .push_column_group(512, 8, 5, row_weight, 1, &other) + .unwrap(); + canonical + .push_columns_canonical(512, 8, 5, row_weight, &other) + .unwrap(); + // Span not aligned to the ring dimension: canonical events, aligned + // to the block length so `push` admits them. + let misaligned = stream.point(3); + let row_weight = stream.field(); + weights + .push_column_group(2, 4, 3, row_weight, 2, &misaligned) + .unwrap(); + canonical + .push_columns_canonical(2, 4, 3, row_weight, &misaligned) + .unwrap(); + assert!( + !weights.events.is_empty(), + "the misaligned span takes the canonical path" + ); + assert!( + !weights.groups.groups.is_empty(), + "aligned spans are grouped" + ); + assert_eq!( + weights.materialize_dense().unwrap(), + canonical.materialize_dense().unwrap() + ); + assert_all_agree(&weights, &mut stream, "columns"); + } + + /// Errors are the canonical errors: a progression leaving the domain or a + /// misaligned block falls back to the canonical loop and fails the same way. + #[test] + fn errors_are_canonical() { + let mut stream = Stream(99); + let row_weights = stream.point(4); + for (span, block) in [(1usize << 9, 1usize), (2, 4)] { + let mut grouped = empty(1 << 9, 64, block, &mut stream); + let mut canonical = grouped.clone(); + let a = + push_recomposition::(&mut grouped, span, 4, 16, 16, 0, 1, 8, &row_weights); + let b = push_recomposition_canonical::( + &mut canonical, + span, + 4, + 16, + 16, + 0, + 1, + 8, + &row_weights, + ); + assert_eq!(format!("{a:?}"), format!("{b:?}")); + assert!(a.is_err()); + } + let mut grouped = empty(1 << 6, 64, 1, &mut stream); + let mut canonical = grouped.clone(); + let columns = stream.point(32); + let a = grouped.push_column_group(0, 4, 32, F::one(), 0, &columns); + let b = canonical.push_columns_canonical(0, 4, 32, F::one(), &columns); + assert_eq!(format!("{a:?}"), format!("{b:?}")); + assert!(a.is_err()); + let a = grouped.push_column_group(0, 4, 9, F::one(), 1, &columns[..8]); + let b = canonical.push_columns_canonical(0, 4, 9, F::one(), &columns[..8]); + assert_eq!(format!("{a:?}"), format!("{b:?}")); + } + + /// A zero source ring dimension records no events on either path, and a + /// row range past the row-weight table fails with the canonical error. + #[test] + fn zero_ring_dimension_errors_are_canonical() { + let mut stream = Stream(0x5eed); + let row_weights = stream.point(2); + for (row_start, row_count, fails) in [(0usize, 3usize, true), (1, 2, true), (0, 2, false)] { + let mut grouped = empty(1 << 6, 64, 1, &mut stream); + let mut canonical = grouped.clone(); + let a = push_recomposition::( + &mut grouped, + 0, + 4, + 0, + 0, + row_start, + row_count, + 8, + &row_weights, + ); + let b = push_recomposition_canonical::( + &mut canonical, + 0, + 4, + 0, + 0, + row_start, + row_count, + 8, + &row_weights, + ); + assert_eq!(format!("{a:?}"), format!("{b:?}")); + assert_eq!(a.is_err(), fails); + assert!(grouped.events.is_empty() && grouped.groups.groups.is_empty()); + assert!(canonical.events.is_empty()); + } + } + + /// Direct groups exercise tiers the producers do not reach: stride zero + /// (repeated starts), a non-geometric table under the dyadic tier, and a + /// geometric table with ratio one. + #[test] + fn direct_groups_cover_every_tier() { + let mut stream = Stream(0xdead_beef); + let n = 9; + let mut weights = empty(1 << n, 64, 1, &mut stream); + weights + .groups + .tables + .push(GroupTable::new(stream.point(16), true)); + weights + .groups + .tables + .push(GroupTable::new(vec![F::one(); 16], true)); + assert!(weights.groups.tables[0].ratio_squares.is_none()); + assert!(weights.groups.tables[1].ratio_squares.is_some()); + let scalar = stream.field(); + for (start, stride, len, count, table) in [ + (8usize, 0usize, 5usize, 4usize, 0usize), + (16, 4, 16, 4, 0), + (20, 8, 13, 4, 1), + (0, 12, 9, 4, 1), + (24, 8, 1, 8, 0), + ] { + weights.groups.groups.push(CompressionEventGroup { + physical_start: start, + stride, + len, + coefficient_count: count, + alpha_exponent_start: 4, + scalar, + table, + }); + } + assert_all_agree(&weights, &mut stream, "direct groups"); + } + + /// The product of two Boolean tables' extensions is not the extension of + /// their product (the pitfall the factorization avoids by splitting only + /// disjoint digit positions). + #[test] + fn same_variable_products_do_not_factor() { + let table = [F::one(), F::zero()]; + let point = [F::from_u64(5)]; + let product = + multilinear_eval(&table, &point).unwrap() * multilinear_eval(&table, &point).unwrap(); + let extension = multilinear_eval(&[F::one(), F::zero()], &point).unwrap(); + assert_ne!(product, extension); + let groups_value = eq_bits(&point[..], 0); + assert_eq!(groups_value, extension); + } +} diff --git a/crates/akita-types/src/proof/compression_relation_weights/reduced.rs b/crates/akita-types/src/proof/compression_relation_weights/reduced.rs index cd7c530b5..6c3168fe1 100644 --- a/crates/akita-types/src/proof/compression_relation_weights/reduced.rs +++ b/crates/akita-types/src/proof/compression_relation_weights/reduced.rs @@ -443,6 +443,7 @@ where alpha_powers: scalar_powers(alpha, maximum_dimension), coefficient_block_len, physical_field_len, + groups: super::factored::Groups::default(), }; let field_bits = usize::try_from(F::MODULUS_BITS) .map_err(|_| AkitaError::InvalidSetup("compression field width overflow".into()))?; @@ -624,11 +625,16 @@ mod tests { field_bits * (span.map().ring_dimension() / successor.map().ring_dimension()); } } - assert_eq!(program.linear.events.len(), expected_linear_events); + let grouped = program.linear.expanded_group_events().unwrap(); + assert_eq!( + program.linear.events.len() + grouped.len(), + expected_linear_events + ); assert!(program .linear .events .iter() + .chain(&grouped) .all(|event| { event.physical_start + event.coefficient_count <= physical_field_len })); let mut wrong_mode = params.clone(); @@ -703,6 +709,7 @@ mod tests { alpha_powers: Vec::new(), coefficient_block_len: 1, physical_field_len: 2048, + groups: super::factored::Groups::default(), }, maps: vec![ReducedCompressionMapEvent { span: span.clone(), From 0dabcd60038343613a6187eaa8e03c3d6b8b4b0d Mon Sep 17 00:00:00 2001 From: acentelles Date: Fri, 23 Oct 2026 20:55:45 +0100 Subject: [PATCH 05/17] test(verifier): cross-check factored compression weights against per-event evaluation Add the diagnostic feature `compression-weights-crosscheck` to `akita-types` (forwarded by `akita-pcs`). No default feature enables it, and without it the compiled code is unchanged: the only edits to existing code are a `cfg` attribute on `evaluate_at_point` and on the recomposition dispatcher, and a `cfg`-gated observation call at the start of `push_column_group`; every other existing line keeps its text and position. With the feature, `CompressionRelationWeights::evaluate_at_point` returns the same value and also: - evaluates the same table event by event (every group expanded into its events) at the requested point and at four seeded random points, and compares each value with the grouped evaluation; - counts the table's groups per evaluation tier (geometric dyadic blocks, cached dyadic blocks, per-event equality window) and its ungrouped events. Each recomposition call and compression row of the builders records whether the family was grouped or pushed event by event, with the reason for a fallback, and compares the grouped events with those of the canonical per-event loop on the same arguments. A difference is counted and returned as `AkitaError::Internal`, so verification fails closed. Counters are available from `crosscheck::report()`, and each evaluation emits one `tracing` event at INFO (target `akita_types::compression_weights_crosscheck`) whose message is a JSON object with that evaluation's tiers and its table's builder outcomes. Tests: with the feature, a table whose geometric closed form disagrees with its events is rejected; builder outcomes, fallback reasons and every tier are recorded; and `akita_fp128_e2e` runs dense, one-hot and precommitted fp128 roundtrips and checks that the cross-check ran with no difference. Every other roundtrip in that file is cross-checked too when the feature is on. --- book/src/usage/feature-flags.md | 9 + crates/akita-pcs/Cargo.toml | 1 + crates/akita-pcs/tests/akita_fp128_e2e.rs | 36 ++ crates/akita-types/Cargo.toml | 4 + .../src/proof/compression_relation_weights.rs | 7 +- .../crosscheck.rs | 398 ++++++++++++++++ .../compression_relation_weights/factored.rs | 426 +++++++++++++++++- 7 files changed, 873 insertions(+), 8 deletions(-) create mode 100644 crates/akita-types/src/proof/compression_relation_weights/crosscheck.rs diff --git a/book/src/usage/feature-flags.md b/book/src/usage/feature-flags.md index 03feed05b..19f2891d4 100644 --- a/book/src/usage/feature-flags.md +++ b/book/src/usage/feature-flags.md @@ -77,10 +77,19 @@ explains which family to choose. | --- | --- | | `logging-transcript` | Records transcript schedule events and checks that wire values are absorbed before challenges | | `response-model-diagnostics` | Measures complete source and response energies for planner model calibration | +| `compression-weights-crosscheck` | Checks every factored compression relation weight evaluation against the per-event evaluation and counts its evaluation tiers | `response-model-diagnostics` scans witness data that normal proving does not scan. Use it for model calibration runs, not for ordinary performance numbers. +`compression-weights-crosscheck` (on `akita-types`, forwarded by `akita-pcs`) +evaluates every compression relation weight table both by factor and event by +event, at the verifier's point and at seeded random points, and compares each +grouped builder family with the per-event builder. A difference fails +verification. Each evaluation emits one `tracing` event at `INFO` with its +evaluation tiers and builder outcomes. It is for native diagnostic runs; it +changes no proof, transcript or default build. + The `transcript_schedule` example uses `logging-transcript`: ```bash diff --git a/crates/akita-pcs/Cargo.toml b/crates/akita-pcs/Cargo.toml index 37f16be5f..ab9d3aa57 100644 --- a/crates/akita-pcs/Cargo.toml +++ b/crates/akita-pcs/Cargo.toml @@ -96,6 +96,7 @@ logging-transcript = [ "akita-cpu-backend/logging-transcript", ] response-model-diagnostics = ["akita-cpu-backend/response-model-diagnostics"] +compression-weights-crosscheck = ["akita-types/compression-weights-crosscheck"] [dependencies] akita-error = { version = "0.1.0", path = "../akita-error" } akita-algebra = { version = "0.1.0", path = "../akita-algebra" } diff --git a/crates/akita-pcs/tests/akita_fp128_e2e.rs b/crates/akita-pcs/tests/akita_fp128_e2e.rs index 0e50dad91..05e4611e3 100644 --- a/crates/akita-pcs/tests/akita_fp128_e2e.rs +++ b/crates/akita-pcs/tests/akita_fp128_e2e.rs @@ -673,3 +673,39 @@ fn fp128_dense_monomial_basis() { .expect("monomial verify"); }); } + +// ============================================================================ +// Compression relation weight cross-check (`compression-weights-crosscheck`) +// +// With the feature, every compression relation weight evaluation in this file +// is also evaluated event by event at its own point and at seeded random +// points, and every grouped builder family is compared with the canonical +// per-event loop; a difference fails verification. This test runs dense, +// one-hot and precommitted roundtrips and checks that the cross-check ran. +// ============================================================================ + +#[cfg(feature = "compression-weights-crosscheck")] +#[test] +fn fp128_compression_weights_crosscheck() { + use akita_types::proof::compression_relation_weights::crosscheck::{report, EXTRA_POINTS}; + init_rayon_pool(); + run_on_large_stack(|| { + let before = report(); + prove_verify_dense_roundtrip::(&[14, 16], b"crosscheck/fp128_dense"); + prove_verify_onehot_roundtrip::(&[12, 15], b"crosscheck/fp128_onehot"); + prove_verify_onehot_precommitted_roundtrip::( + &[16], + b"crosscheck/fp128_onehot_pre", + ); + let after = report(); + // Other tests may run concurrently, so these are lower bounds. + let evaluations = after.evaluations - before.evaluations; + assert!(evaluations > 0, "no compression relation weight evaluation"); + assert!(after.points - before.points >= evaluations * (1 + EXTRA_POINTS as u64)); + assert!(after.builders.recomposition_groups > before.builders.recomposition_groups); + assert!(after.builders.compared > before.builders.compared); + assert_eq!(after.mismatches, 0); + assert_eq!(after.builders.mismatches, 0); + eprintln!("compression weights cross-check report: {after:?}"); + }); +} diff --git a/crates/akita-types/Cargo.toml b/crates/akita-types/Cargo.toml index 80620379f..94763bc97 100644 --- a/crates/akita-types/Cargo.toml +++ b/crates/akita-types/Cargo.toml @@ -49,6 +49,10 @@ logging-transcript = [ "akita-params/logging-transcript", "akita-transcript/logging-transcript", ] +# Diagnostic: cross-checks every factored compression relation weight +# evaluation against the per-event evaluation and counts the evaluation tiers. +# Native diagnostic builds only; no default feature enables it. +compression-weights-crosscheck = [] [dev-dependencies] akita-params = { version = "0.1.0", path = "../akita-params", default-features = false, features = [ diff --git a/crates/akita-types/src/proof/compression_relation_weights.rs b/crates/akita-types/src/proof/compression_relation_weights.rs index 198bd738e..154551941 100644 --- a/crates/akita-types/src/proof/compression_relation_weights.rs +++ b/crates/akita-types/src/proof/compression_relation_weights.rs @@ -313,8 +313,8 @@ impl CompressionRelationWeights { /// Evaluate the table's multilinear extension at one full witness point. /// /// Ungrouped events take the per-event path and groups are evaluated by - /// factor (see the `factored` module); the sum is the multilinear - /// extension of the dense table. + /// factor (see the `factored` module); the sum is the dense table's extension. + #[cfg(not(feature = "compression-weights-crosscheck"))] #[tracing::instrument(skip_all, name = "compression_relation_mle")] pub fn evaluate_at_point(&self, point: &[E]) -> Result { let events = self.evaluate_events_at_point(point)?; @@ -805,6 +805,9 @@ where Ok(weights) } +#[cfg(feature = "compression-weights-crosscheck")] +pub mod crosscheck; + #[cfg(test)] mod tests { use super::*; diff --git a/crates/akita-types/src/proof/compression_relation_weights/crosscheck.rs b/crates/akita-types/src/proof/compression_relation_weights/crosscheck.rs new file mode 100644 index 000000000..45b662f45 --- /dev/null +++ b/crates/akita-types/src/proof/compression_relation_weights/crosscheck.rs @@ -0,0 +1,398 @@ +//! Diagnostic cross-check of the factored compression relation weights. +//! +//! Compiled only with the `compression-weights-crosscheck` feature, which no +//! default feature enables. With it, [`CompressionRelationWeights::evaluate_at_point`] +//! returns the value of the default build and also: +//! +//! - evaluates the same table event by event (every group expanded into its +//! events) at the requested point and at [`EXTRA_POINTS`] seeded random +//! points, and compares each value with the grouped evaluation; +//! - counts the table's groups and events per evaluation tier. +//! +//! Each recomposition call and each compression row of the builders records +//! whether its family was grouped or pushed event by event (with the reason), +//! and compares the grouped events with those of the canonical per-event loop +//! on the same arguments. +//! +//! A difference is counted and then returned as [`AkitaError::Internal`], so +//! the verifier rejects instead of accepting on an unchecked value. Counters +//! accumulate process-wide ([`report`]). Each evaluation also emits one +//! `tracing` event at `INFO` with target [`TRACING_TARGET`]; its message is a +//! JSON object for that evaluation, including the builder outcomes recorded +//! while the evaluated table was built. + +use super::*; +use rand_core::RngCore; +use std::cell::Cell; +use std::sync::atomic::{AtomicU64, Ordering}; +use std::sync::{Mutex, PoisonError}; + +/// Seeded random points checked per evaluation, besides its own point. +pub const EXTRA_POINTS: usize = 4; + +/// `tracing` target of the per-evaluation events. +pub const TRACING_TARGET: &str = "akita_types::compression_weights_crosscheck"; + +/// Evaluation `i` (process-wide count) draws its random points from `SEED + i`. +const SEED: u64 = 0x6372_6f73_7363_6865; + +/// Builder outcomes kept for attribution to a later evaluation; the oldest +/// half is dropped beyond this (outcomes of tables never evaluated, such as +/// the prover's). +const PENDING_CAP: usize = 1 << 20; + +/// Groups, and the table entries they cover, in one evaluation tier. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub struct TierCount { + /// Groups. + pub groups: u64, + /// Table entries covered by the groups, zero entries included. + pub entries: u64, +} + +impl TierCount { + fn add(&mut self, other: Self) { + self.groups += other.groups; + self.entries += other.entries; + } +} + +/// How the groups and ungrouped events of evaluated tables were evaluated. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub struct Tiers { + /// Dyadic blocks of a geometric table (the lifted gadget powers), each + /// closed as a product of logarithmically many factors. + pub geometric_dyadic: TierCount, + /// Dyadic blocks of any other table (evaluated compression columns), each + /// block's extension cached. + pub cached_dyadic: TierCount, + /// High strides that are not a power of two: a loop over the per-event + /// equality window. + pub window: TierCount, + /// Ungrouped events with an aligned span (per-event path). + pub ungrouped_aligned: u64, + /// Ungrouped events with an unaligned span (per-event fallback window). + pub ungrouped_unaligned: u64, +} + +impl Tiers { + fn add(&mut self, other: &Self) { + self.geometric_dyadic.add(other.geometric_dyadic); + self.cached_dyadic.add(other.cached_dyadic); + self.window.add(other.window); + self.ungrouped_aligned += other.ungrouped_aligned; + self.ungrouped_unaligned += other.ungrouped_unaligned; + } + + fn json(&self) -> String { + format!( + "{{\"geometric_dyadic\":[{},{}],\"cached_dyadic\":[{},{}],\"window\":[{},{}],\ + \"ungrouped_aligned\":{},\"ungrouped_unaligned\":{}}}", + self.geometric_dyadic.groups, + self.geometric_dyadic.entries, + self.cached_dyadic.groups, + self.cached_dyadic.entries, + self.window.groups, + self.window.entries, + self.ungrouped_aligned, + self.ungrouped_unaligned + ) + } +} + +/// Outcomes of the grouped builders. +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub struct BuilderCounts { + /// Recomposition calls recorded as groups. + pub recomposition_grouped: u64, + /// Groups recorded by those calls. + pub recomposition_groups: u64, + /// Recomposition calls pushed event by event. + pub recomposition_fallback: u64, + /// Compression rows whose columns were recorded as one group. + pub column_grouped: u64, + /// Compression rows with a zero row weight or only zero columns, which + /// record nothing. + pub column_zero: u64, + /// Compression rows pushed event by event. + pub column_fallback: u64, + /// Calls whose grouped events were compared with the canonical loop's. + pub compared: u64, + /// Compared calls whose events differ. + pub mismatches: u64, + /// Event-by-event calls by reason. + pub fallback_reasons: Vec<(&'static str, u64)>, +} + +impl BuilderCounts { + fn add(&mut self, outcome: BuilderOutcome, compared: Option) { + match outcome { + BuilderOutcome::RecompositionGrouped { groups } => { + self.recomposition_grouped += 1; + self.recomposition_groups += groups as u64; + } + BuilderOutcome::RecompositionFallback(reason) => { + self.recomposition_fallback += 1; + self.add_reason(reason); + } + BuilderOutcome::ColumnGrouped => self.column_grouped += 1, + BuilderOutcome::ColumnZero => self.column_zero += 1, + BuilderOutcome::ColumnFallback(reason) => { + self.column_fallback += 1; + self.add_reason(reason); + } + } + if let Some(equal) = compared { + self.compared += 1; + if !equal { + self.mismatches += 1; + } + } + } + + fn add_reason(&mut self, reason: &'static str) { + if let Some(entry) = self.fallback_reasons.iter_mut().find(|(r, _)| *r == reason) { + entry.1 += 1; + } else { + self.fallback_reasons.push((reason, 1)); + } + } + + fn json(&self) -> String { + let reasons = self + .fallback_reasons + .iter() + .map(|(reason, count)| format!("\"{reason}\":{count}")) + .collect::>() + .join(","); + format!( + "{{\"recomposition_grouped\":{},\"recomposition_groups\":{},\ + \"recomposition_fallback\":{},\"column_grouped\":{},\"column_zero\":{},\ + \"column_fallback\":{},\"compared\":{},\"mismatches\":{},\ + \"fallback_reasons\":{{{reasons}}}}}", + self.recomposition_grouped, + self.recomposition_groups, + self.recomposition_fallback, + self.column_grouped, + self.column_zero, + self.column_fallback, + self.compared, + self.mismatches + ) + } +} + +/// Process-wide cross-check counters. +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub struct CrossCheckReport { + /// `evaluate_at_point` calls. + pub evaluations: u64, + /// Points at which the grouped and per-event values were compared. + pub points: u64, + /// Compared points whose values differ. + pub mismatches: u64, + /// Evaluation tiers, summed over the evaluations. + pub tiers: Tiers, + /// Builder outcomes over every table built (prover and verifier). + pub builders: BuilderCounts, +} + +/// A snapshot of the process-wide counters. +pub fn report() -> CrossCheckReport { + with_state(|state| state.report.clone()) +} + +/// The outcome of one builder call. +#[derive(Clone, Copy, Debug)] +pub(super) enum BuilderOutcome { + RecompositionGrouped { groups: usize }, + RecompositionFallback(&'static str), + ColumnGrouped, + ColumnZero, + ColumnFallback(&'static str), +} + +struct Observation { + table: (usize, usize), + outcome: BuilderOutcome, + compared: Option, +} + +#[derive(Default)] +struct State { + report: CrossCheckReport, + pending: Vec, +} + +static STATE: Mutex> = Mutex::new(None); +static EVALUATIONS: AtomicU64 = AtomicU64::new(0); + +thread_local! { + static OBSERVING: Cell = const { Cell::new(false) }; +} + +fn with_state(f: impl FnOnce(&mut State) -> R) -> R { + let mut state = STATE.lock().unwrap_or_else(PoisonError::into_inner); + f(state.get_or_insert_with(State::default)) +} + +/// Marks a builder observation in progress on this thread, so the twin builds +/// it runs are not observed themselves. +pub(super) struct ObserverGuard; + +impl ObserverGuard { + pub(super) fn enter() -> Option { + OBSERVING.with(|observing| (!observing.replace(true)).then_some(Self)) + } +} + +impl Drop for ObserverGuard { + fn drop(&mut self) { + OBSERVING.with(|observing| observing.set(false)); + } +} + +/// Record one builder call's outcome for the table `table`; a failed +/// comparison is an error after it is counted. +pub(super) fn record_builder( + table: (usize, usize), + outcome: BuilderOutcome, + compared: Option, +) -> Result<(), AkitaError> { + with_state(|state| { + state.report.builders.add(outcome, compared); + if state.pending.len() >= PENDING_CAP { + state.pending = state.pending.split_off(PENDING_CAP / 2); + } + state.pending.push(Observation { + table, + outcome, + compared, + }); + }); + if compared == Some(false) { + return Err(AkitaError::Internal(format!( + "compression weights cross-check: grouped builder events differ from the canonical \ + loop ({outcome:?})" + ))); + } + Ok(()) +} + +/// Take the builder outcomes of the most recent build of `table`: the last +/// contiguous run of outcomes recorded for it. +fn claim(pending: &mut Vec, table: (usize, usize)) -> BuilderCounts { + let mut counts = BuilderCounts::default(); + let Some(last) = pending.iter().rposition(|entry| entry.table == table) else { + return counts; + }; + let first = pending + .get(..last) + .and_then(|before| before.iter().rposition(|entry| entry.table != table)) + .map_or(0, |index| index + 1); + for entry in pending.drain(first..=last) { + counts.add(entry.outcome, entry.compared); + } + counts +} + +/// SplitMix64, for the seeded random points. +struct SplitMix64(u64); + +impl RngCore for SplitMix64 { + fn next_u32(&mut self) -> u32 { + (self.next_u64() >> 32) as u32 + } + + fn next_u64(&mut self) -> u64 { + self.0 = self.0.wrapping_add(0x9e37_79b9_7f4a_7c15); + let mut z = self.0; + z = (z ^ (z >> 30)).wrapping_mul(0xbf58_476d_1ce4_e5b9); + z = (z ^ (z >> 27)).wrapping_mul(0x94d0_49bb_1331_11eb); + z ^ (z >> 31) + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + for chunk in dest.chunks_mut(8) { + let bytes = self.next_u64().to_le_bytes(); + chunk.copy_from_slice(bytes.get(..chunk.len()).unwrap_or(&bytes[..])); + } + } + + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> { + self.fill_bytes(dest); + Ok(()) + } +} + +impl CompressionRelationWeights { + /// Evaluate the table's multilinear extension at one full witness point. + /// + /// The value is the default build's. The evaluation is also compared with + /// the per-event evaluation of the same table at `point` and at + /// [`EXTRA_POINTS`] seeded random points; a difference is an error. + #[tracing::instrument(skip_all, name = "compression_relation_mle")] + pub fn evaluate_at_point(&self, point: &[E]) -> Result { + let events = self.evaluate_events_at_point(point)?; + let value = events + self.evaluate_groups_at_point(point)?; + self.cross_check_evaluation(point, value)?; + Ok(value) + } + + fn grouped_value(&self, point: &[E]) -> Option { + let events = self.evaluate_events_at_point(point).ok()?; + Some(events + self.evaluate_groups_at_point(point).ok()?) + } + + fn cross_check_evaluation(&self, point: &[E], value: E) -> Result<(), AkitaError> { + let index = EVALUATIONS.fetch_add(1, Ordering::Relaxed); + let per_event = self.crosscheck_expanded().ok(); + let per_event_value = |at: &[E]| { + per_event + .as_ref() + .and_then(|table| table.evaluate_events_at_point(at).ok()) + }; + // Point 0 is the evaluation's own point; points 1.. are random. + let mut differing = Vec::new(); + if per_event_value(point) != Some(value) { + differing.push(0); + } + let mut rng = SplitMix64(SEED.wrapping_add(index)); + for extra in 1..=EXTRA_POINTS { + let random = (0..point.len()) + .map(|_| E::random(&mut rng)) + .collect::>(); + let grouped = self.grouped_value(&random); + if grouped.is_none() || per_event_value(&random) != grouped { + differing.push(extra); + } + } + let tiers = self.crosscheck_tiers(); + let points = 1 + EXTRA_POINTS as u64; + let builder = with_state(|state| { + state.report.evaluations += 1; + state.report.points += points; + state.report.mismatches += differing.len() as u64; + state.report.tiers.add(&tiers); + claim(&mut state.pending, self.crosscheck_key()) + }); + tracing::info!( + target: TRACING_TARGET, + "{{\"evaluation\":{index},\"num_vars\":{},\"physical_field_len\":{},\ + \"points\":{points},\"mismatches\":{},\"tiers\":{},\"builder\":{}}}", + point.len(), + self.physical_field_len, + differing.len(), + tiers.json(), + builder.json() + ); + if differing.is_empty() { + Ok(()) + } else { + Err(AkitaError::Internal(format!( + "compression weights cross-check: grouped and per-event evaluations differ at \ + evaluation {index}, points {differing:?} (0 is the evaluation's own point)" + ))) + } + } +} diff --git a/crates/akita-types/src/proof/compression_relation_weights/factored.rs b/crates/akita-types/src/proof/compression_relation_weights/factored.rs index 77db52473..2c04f3fed 100644 --- a/crates/akita-types/src/proof/compression_relation_weights/factored.rs +++ b/crates/akita-types/src/proof/compression_relation_weights/factored.rs @@ -214,10 +214,8 @@ impl CompressionRelationWeights { index } - /// Record the column events of one compression row: element `j` is - /// `(span_start + j * ring_dimension, ring_dimension, 0, row_weight * - /// columns[j])`. Falls back to the canonical loop when any precondition - /// fails. + /// Record one compression row's column events (`row_weight * columns[j]` at + /// `span_start + j * ring_dimension`) as one group, or by the canonical loop. pub(super) fn push_column_group( &mut self, span_start: usize, @@ -227,6 +225,8 @@ impl CompressionRelationWeights { matrix_index: usize, columns: &[E], ) -> Result<(), AkitaError> { + #[cfg(feature = "compression-weights-crosscheck")] + self.crosscheck_columns(span_start, ring_dimension, input_width, row_weight, columns)?; let len = columns .get(..input_width) .and_then(|live| live.iter().rposition(|value| !value.is_zero())) @@ -516,8 +516,8 @@ impl CompressionRelationWeights { } } -/// Recomposition events grouped by (source row, coefficient block) over the -/// gadget bits, or the canonical loop when any group fails a precondition. +/// Recomposition events grouped over the gadget bits, or the canonical loop on any failure. +#[cfg(not(feature = "compression-weights-crosscheck"))] #[allow(clippy::too_many_arguments)] pub(super) fn push_recomposition( weights: &mut CompressionRelationWeights, @@ -640,6 +640,356 @@ where Some(groups) } +/// Recomposition events grouped over the gadget bits, or the canonical loop on +/// any failure, as without `compression-weights-crosscheck`. Each call also +/// records its outcome (with the reason for a fallback) and compares the +/// grouped events with the canonical loop's on the same arguments. +#[cfg(feature = "compression-weights-crosscheck")] +#[allow(clippy::too_many_arguments)] +pub(super) fn push_recomposition( + weights: &mut CompressionRelationWeights, + span_start: usize, + digit_ring_dim: usize, + source_coefficients: usize, + source_ring_dim: usize, + source_row_start: usize, + source_row_count: usize, + field_bits: usize, + row_weights: &[E], +) -> Result<(), AkitaError> +where + F: Field + CanonicalEncoding, + E: FpExtEncoding + Ring + ExtField, +{ + use super::crosscheck::BuilderOutcome; + let planned = plan_recomposition_groups::( + weights, + span_start, + digit_ring_dim, + source_coefficients, + source_ring_dim, + source_row_start, + source_row_count, + field_bits, + row_weights, + ); + let (outcome, compared) = match &planned { + Some(groups) => { + let mut grouped = weights.crosscheck_twin(true); + grouped.groups.groups.clone_from(groups); + let mut canonical = weights.crosscheck_twin(false); + let canonical_ok = push_recomposition_canonical::( + &mut canonical, + span_start, + digit_ring_dim, + source_coefficients, + source_ring_dim, + source_row_start, + source_row_count, + field_bits, + row_weights, + ) + .is_ok(); + ( + BuilderOutcome::RecompositionGrouped { + groups: groups.len(), + }, + Some(canonical_ok && grouped.crosscheck_same_events(&canonical)), + ) + } + None => ( + BuilderOutcome::RecompositionFallback(recomposition_fallback_reason::( + weights, + span_start, + digit_ring_dim, + source_coefficients, + source_ring_dim, + source_row_start, + source_row_count, + field_bits, + row_weights, + )), + None, + ), + }; + super::crosscheck::record_builder(weights.crosscheck_key(), outcome, compared)?; + match planned { + Some(groups) => { + weights.groups.groups.extend(groups); + Ok(()) + } + None => push_recomposition_canonical::( + weights, + span_start, + digit_ring_dim, + source_coefficients, + source_ring_dim, + source_row_start, + source_row_count, + field_bits, + row_weights, + ), + } +} + +/// Why `plan_recomposition_groups` declined a call: its preconditions, checked +/// in its order. +#[cfg(feature = "compression-weights-crosscheck")] +#[allow(clippy::too_many_arguments)] +fn recomposition_fallback_reason( + weights: &CompressionRelationWeights, + span_start: usize, + digit_ring_dim: usize, + source_coefficients: usize, + source_ring_dim: usize, + source_row_start: usize, + source_row_count: usize, + field_bits: usize, + row_weights: &[E], +) -> &'static str +where + F: Field + CanonicalEncoding, + E: FpExtEncoding + Ring + ExtField, +{ + if digit_ring_dim == 0 + || source_ring_dim == 0 + || !source_ring_dim.is_multiple_of(digit_ring_dim) + || source_row_count.checked_mul(source_ring_dim) != Some(source_coefficients) + { + return "recomposition_geometry_malformed"; + } + let largest = field_bits + .saturating_sub(1) + .checked_mul(source_coefficients) + .and_then(|offset| span_start.checked_add(offset)) + .and_then(|start| { + start.checked_add( + source_row_count + .saturating_sub(1) + .checked_mul(source_ring_dim)?, + ) + }) + .and_then(|start| start.checked_add(source_ring_dim - digit_ring_dim)); + if largest.is_none() { + return "recomposition_address_overflow"; + } + if gadget_row_scalars::(field_bits, 1) + .into_iter() + .any(|power| >::lift_base(power).is_zero()) + { + return "recomposition_zero_gadget_entry"; + } + for source_row in 0..source_row_count { + let Some(row_weight) = source_row_start + .checked_add(source_row) + .and_then(|index| row_weights.get(index)) + else { + return "recomposition_row_weight_missing"; + }; + if row_weight.is_zero() { + continue; + } + for coefficient_start in (0..source_ring_dim).step_by(digit_ring_dim) { + let physical_start = source_row + .checked_mul(source_ring_dim) + .and_then(|offset| span_start.checked_add(offset)) + .and_then(|start| start.checked_add(coefficient_start)); + let Some(physical_start) = physical_start else { + return "recomposition_address_overflow"; + }; + if !weights.admits_progression( + physical_start, + source_coefficients, + field_bits, + digit_ring_dim, + coefficient_start, + ) { + return "recomposition_progression_not_admitted"; + } + } + } + "recomposition_unclassified" +} + +#[cfg(feature = "compression-weights-crosscheck")] +impl CompressionRelationWeights { + /// The same geometry with no events and no groups; `with_tables` keeps the + /// group tables and their caches. + fn crosscheck_twin(&self, with_tables: bool) -> Self { + let groups = if with_tables { + Groups { + groups: Vec::new(), + tables: self.groups.tables.clone(), + gadget_tables: self.groups.gadget_tables.clone(), + column_tables: self.groups.column_tables.clone(), + } + } else { + Groups::default() + }; + Self { + events: Vec::new(), + alpha_powers: self.alpha_powers.clone(), + coefficient_block_len: self.coefficient_block_len, + physical_field_len: self.physical_field_len, + groups, + } + } + + /// Identity of this table while it lives: the address of its alpha power + /// table and its domain size. Builder outcomes are attributed by it. + pub(super) fn crosscheck_key(&self) -> (usize, usize) { + (self.alpha_powers.as_ptr().addr(), self.physical_field_len) + } + + /// The same table with every group expanded into its events. + pub(super) fn crosscheck_expanded(&self) -> Result { + let mut expanded = self.crosscheck_twin(false); + expanded.events.clone_from(&self.events); + expanded.events.extend(self.expanded_group_events()?); + Ok(expanded) + } + + /// Whether two tables hold the same events, groups expanded, compared as + /// the nonzero sums of scalars per (start, coefficient count, alpha start). + fn crosscheck_same_events(&self, other: &Self) -> bool { + match (self.crosscheck_event_sums(), other.crosscheck_event_sums()) { + (Ok(mine), Ok(theirs)) => mine == theirs, + _ => false, + } + } + + fn crosscheck_event_sums(&self) -> Result, AkitaError> { + let mut events = self + .events + .iter() + .cloned() + .chain(self.expanded_group_events()?) + .map(|event| { + ( + ( + event.physical_start, + event.coefficient_count, + event.alpha_exponent_start, + ), + event.scalar, + ) + }) + .collect::>(); + events.sort_unstable_by_key(|(key, _)| *key); + let mut sums = Vec::<((usize, usize, usize), E)>::with_capacity(events.len()); + for (key, scalar) in events { + if let Some((last, sum)) = sums.last_mut() { + if *last == key { + *sum += scalar; + continue; + } + } + sums.push((key, scalar)); + } + sums.retain(|(_, sum)| !sum.is_zero()); + Ok(sums) + } + + /// Groups and events per evaluation tier, selected as + /// `evaluate_groups_at_point` and `evaluate_events_at_point` select them. + pub(super) fn crosscheck_tiers(&self) -> super::crosscheck::Tiers { + let mut tiers = super::crosscheck::Tiers::default(); + for event in &self.events { + if event.physical_start & event.coefficient_count.wrapping_sub(1) == 0 { + tiers.ungrouped_aligned += 1; + } else { + tiers.ungrouped_unaligned += 1; + } + } + for group in &self.groups.groups { + let low_bits = group.coefficient_count.trailing_zeros(); + let high_stride = group.stride.checked_shr(low_bits).unwrap_or(0); + let tier = if group.len == 1 || high_stride.is_power_of_two() { + let geometric = self + .groups + .tables + .get(group.table) + .is_some_and(|table| table.ratio_squares.is_some()); + if geometric { + &mut tiers.geometric_dyadic + } else { + &mut tiers.cached_dyadic + } + } else { + &mut tiers.window + }; + tier.groups += 1; + tier.entries += group.len as u64; + } + tiers + } + + /// Record the outcome of one `push_column_group` call before it runs and, + /// unless it falls back, compare the grouped events with the canonical + /// loop's on the same arguments. + fn crosscheck_columns( + &self, + span_start: usize, + ring_dimension: usize, + input_width: usize, + row_weight: E, + columns: &[E], + ) -> Result<(), AkitaError> { + use super::crosscheck::{BuilderOutcome, ObserverGuard}; + let Some(_observing) = ObserverGuard::enter() else { + // The grouped twin below re-enters `push_column_group`. + return Ok(()); + }; + let len = columns + .get(..input_width) + .and_then(|live| live.iter().rposition(|value| !value.is_zero())) + .map_or(0, |last| last + 1); + let outcome = if columns.len() < input_width { + BuilderOutcome::ColumnFallback("column_table_shorter_than_width") + } else if row_weight.is_zero() || len == 0 { + BuilderOutcome::ColumnZero + } else if self.admits_progression(span_start, ring_dimension, len, ring_dimension, 0) { + BuilderOutcome::ColumnGrouped + } else { + BuilderOutcome::ColumnFallback("column_progression_not_admitted") + }; + let compared = if matches!(outcome, BuilderOutcome::ColumnFallback(_)) { + None + } else { + let mut grouped = self.crosscheck_twin(false); + let grouped_ok = grouped + .push_column_group( + span_start, + ring_dimension, + input_width, + row_weight, + 0, + columns, + ) + .is_ok(); + let mut canonical = self.crosscheck_twin(false); + let canonical_ok = canonical + .push_columns_canonical( + span_start, + ring_dimension, + input_width, + row_weight, + columns, + ) + .is_ok(); + let expected_groups = usize::from(matches!(outcome, BuilderOutcome::ColumnGrouped)); + Some( + grouped_ok + && canonical_ok + && grouped.events.is_empty() + && grouped.groups.groups.len() == expected_groups + && grouped.crosscheck_same_events(&canonical), + ) + }; + super::crosscheck::record_builder(self.crosscheck_key(), outcome, compared) + } +} + #[cfg(test)] mod tests { use super::*; @@ -995,4 +1345,68 @@ mod tests { let groups_value = eq_bits(&point[..], 0); assert_eq!(groups_value, extension); } + + /// The cross-check rejects an evaluation whose closed form disagrees with + /// the group's own events: a table marked geometric whose values are not. + #[cfg(feature = "compression-weights-crosscheck")] + #[test] + fn crosscheck_rejects_a_wrong_closed_form() { + let mut stream = Stream(0xc0ff_ee00); + let mut weights = empty(1 << 9, 64, 1, &mut stream); + let mut table = GroupTable::new(stream.point(16), false); + table.ratio_squares = Some((0..5).map(|i| F::from_u64(3 << i)).collect()); + weights.groups.tables.push(table); + weights.groups.groups.push(CompressionEventGroup { + physical_start: 0, + stride: 4, + len: 16, + coefficient_count: 4, + alpha_exponent_start: 0, + scalar: stream.field(), + table: 0, + }); + let error = weights.evaluate_at_point(&stream.point(9)).unwrap_err(); + assert!(format!("{error:?}").contains("compression weights cross-check")); + } + + /// The cross-check records the builder outcomes (grouped, fallback with + /// its reason) and the evaluation tiers of every group kind. + #[cfg(feature = "compression-weights-crosscheck")] + #[test] + fn crosscheck_records_outcomes_and_tiers() { + use crate::proof::compression_relation_weights::crosscheck::{report, CrossCheckReport}; + let mut stream = Stream(0x5eed_1234); + let mut weights = empty(1 << 10, 64, 1, &mut stream); + let row_weights = stream.point(3); + let before = report(); + // Geometric dyadic, window (stride 48), and a misaligned fallback. + push_recomposition::(&mut weights, 0, 4, 16, 16, 0, 1, 8, &row_weights).unwrap(); + push_recomposition::(&mut weights, 256, 4, 48, 16, 0, 3, 5, &row_weights).unwrap(); + push_recomposition::(&mut weights, 514, 4, 16, 16, 0, 1, 8, &row_weights).unwrap(); + // One grouped compression row (cached dyadic tier). + let columns = stream.point(6); + weights + .push_column_group(640, 4, 6, stream.field(), 0, &columns) + .unwrap(); + weights.evaluate_at_point(&stream.point(10)).unwrap(); + let after = report(); + let reason = |report: &CrossCheckReport| { + report + .builders + .fallback_reasons + .iter() + .find(|(reason, _)| *reason == "recomposition_progression_not_admitted") + .map_or(0, |(_, count)| *count) + }; + // Other tests may run concurrently, so every count is a lower bound. + assert!(after.evaluations > before.evaluations); + assert!(after.builders.recomposition_grouped >= before.builders.recomposition_grouped + 2); + assert!(after.builders.column_grouped > before.builders.column_grouped); + assert!(after.builders.compared >= before.builders.compared + 3); + assert!(reason(&after) > reason(&before)); + assert!(after.tiers.geometric_dyadic.groups > before.tiers.geometric_dyadic.groups); + assert!(after.tiers.window.groups > before.tiers.window.groups); + assert!(after.tiers.cached_dyadic.groups > before.tiers.cached_dyadic.groups); + assert!(after.tiers.ungrouped_unaligned > before.tiers.ungrouped_unaligned); + } } From dd987aad1aef10ee436425c8a5dd52d8fe89e7b0 Mon Sep 17 00:00:00 2001 From: acentelles Date: Fri, 23 Oct 2026 23:16:28 +0100 Subject: [PATCH 06/17] test(verifier): name the cross-check event-sum type The feature-gated event comparison returned Result, AkitaError>, which clippy::type_complexity rejects with compression-weights-crosscheck on. Name it EventSums. Feature-gated lines only; the default build is unchanged. --- .../src/proof/compression_relation_weights/factored.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/crates/akita-types/src/proof/compression_relation_weights/factored.rs b/crates/akita-types/src/proof/compression_relation_weights/factored.rs index 2c04f3fed..a50dab3bd 100644 --- a/crates/akita-types/src/proof/compression_relation_weights/factored.rs +++ b/crates/akita-types/src/proof/compression_relation_weights/factored.rs @@ -811,6 +811,10 @@ where "recomposition_unclassified" } +/// Nonzero scalar sums keyed by (start, coefficient count, alpha start). +#[cfg(feature = "compression-weights-crosscheck")] +type EventSums = Vec<((usize, usize, usize), E)>; + #[cfg(feature = "compression-weights-crosscheck")] impl CompressionRelationWeights { /// The same geometry with no events and no groups; `with_tables` keeps the @@ -858,7 +862,7 @@ impl CompressionRelationWeights { } } - fn crosscheck_event_sums(&self) -> Result, AkitaError> { + fn crosscheck_event_sums(&self) -> Result, AkitaError> { let mut events = self .events .iter() @@ -876,7 +880,7 @@ impl CompressionRelationWeights { }) .collect::>(); events.sort_unstable_by_key(|(key, _)| *key); - let mut sums = Vec::<((usize, usize, usize), E)>::with_capacity(events.len()); + let mut sums = EventSums::::with_capacity(events.len()); for (key, scalar) in events { if let Some((last, sum)) = sums.last_mut() { if *last == key { From 769356124899baf3a59aa8cb10838e06a9ef8123 Mon Sep 17 00:00:00 2001 From: acentelles Date: Sat, 24 Oct 2026 00:49:35 +0100 Subject: [PATCH 07/17] Batch reduced setup rows sharing one functional --- .../src/setup_contribution/scan/reduced.rs | 33 ++++- .../src/setup_contribution/tests.rs | 1 + .../setup_contribution/tests/fused_scan.rs | 2 +- .../tests/reduced_shared.rs | 139 ++++++++++++++++++ 4 files changed, 171 insertions(+), 4 deletions(-) create mode 100644 crates/akita-verifier/src/setup_contribution/tests/reduced_shared.rs diff --git a/crates/akita-verifier/src/setup_contribution/scan/reduced.rs b/crates/akita-verifier/src/setup_contribution/scan/reduced.rs index 6e2ea92a3..b2ffaabdb 100644 --- a/crates/akita-verifier/src/setup_contribution/scan/reduced.rs +++ b/crates/akita-verifier/src/setup_contribution/scan/reduced.rs @@ -196,6 +196,13 @@ where let setup_flat = setup_view.as_slice(); let job_rings = super::super::segments::SETUP_SCAN_JOB_RINGS; let num_jobs = required.div_ceil(job_rings); + // A single base-ring functional is independent of the physical ring index, + // so every row of a job goes through the field's weighted row kernel. Mixed + // dimensions or distinct functionals retain the general per-class path. + let shared_functional = match functional_classes { + [class] if class.ratio == 1 => Some(class.functional), + _ => None, + }; cfg_try_fold_reduce!( 0..num_jobs, E::zero, @@ -206,6 +213,16 @@ where .ok_or(AkitaError::InvalidProof)? .min(required); let setup = setup_flat.get(lo..hi).ok_or(AkitaError::InvalidProof)?; + let mut shared_rows = Vec::new(); + let mut shared_weights = Vec::new(); + if shared_functional.is_some() { + shared_rows.try_reserve_exact(setup.len()).map_err(|_| { + AkitaError::InvalidSetup("reduced scan row allocation failed".into()) + })?; + shared_weights.try_reserve_exact(setup.len()).map_err(|_| { + AkitaError::InvalidSetup("reduced scan weight allocation failed".into()) + })?; + } let mut segment_cursors = partitions .iter() .map(|partition| { @@ -241,12 +258,22 @@ where for (class, scalar) in functional_classes.iter().zip(&mut class_scalars) { let scalar = std::mem::replace(scalar, A::zero()).finish(); if !scalar.is_zero() { - let functional = class.chunk::(base_idx)?; - term.add_product(eval_ring_at_pows_fast(ring, functional), scalar); + if shared_functional.is_some() { + shared_rows.push(ring.coefficients().as_slice()); + shared_weights.push(scalar); + } else { + let functional = class.chunk::(base_idx)?; + term.add_product(eval_ring_at_pows_fast(ring, functional), scalar); + } } } } - Ok(acc + term.finish()) + let contribution = if let Some(functional) = shared_functional { + E::weighted_dot_base_rows(&shared_rows, &shared_weights, functional) + } else { + term.finish() + }; + Ok(acc + contribution) }, |lhs, rhs| Ok(lhs + rhs) ) diff --git a/crates/akita-verifier/src/setup_contribution/tests.rs b/crates/akita-verifier/src/setup_contribution/tests.rs index 6e13497dd..ff9f07dc2 100644 --- a/crates/akita-verifier/src/setup_contribution/tests.rs +++ b/crates/akita-verifier/src/setup_contribution/tests.rs @@ -20,6 +20,7 @@ mod direct_evaluation_regressions; mod fused_scan; mod packed_direct; mod prepare; +mod reduced_shared; mod span_evaluators; type F = Prime128OffsetA7F7; diff --git a/crates/akita-verifier/src/setup_contribution/tests/fused_scan.rs b/crates/akita-verifier/src/setup_contribution/tests/fused_scan.rs index 02761cbd3..88c89dbf4 100644 --- a/crates/akita-verifier/src/setup_contribution/tests/fused_scan.rs +++ b/crates/akita-verifier/src/setup_contribution/tests/fused_scan.rs @@ -89,7 +89,7 @@ fn naive_physical_b_weights( } #[allow(clippy::too_many_arguments)] -fn reduced_direct_literal_oracle( +pub(super) fn reduced_direct_literal_oracle( plan: &SetupContributionPlan, setup: &AkitaExpandedSetup, inputs: &TestSetupInputs, diff --git a/crates/akita-verifier/src/setup_contribution/tests/reduced_shared.rs b/crates/akita-verifier/src/setup_contribution/tests/reduced_shared.rs new file mode 100644 index 000000000..d80c1dcb1 --- /dev/null +++ b/crates/akita-verifier/src/setup_contribution/tests/reduced_shared.rs @@ -0,0 +1,139 @@ +use super::fused_scan::reduced_direct_literal_oracle; +use super::*; + +fn check_shared_reduced_scan(blocks: usize, scalar: impl Fn(u64) -> E, zero_rows: bool) +where + E: ExtField + MulBaseUnreduced, +{ + let role_dims = CommitmentRingDims { + inner: 64, + outer: 64, + opening: 64, + }; + let (inputs, groups, layout, base_plan, _, base_relation_point, fold_gadget) = + structured_weight_fixture_with_outgoing(blocks, &[blocks], role_dims, 64); + let geometry = base_plan.relation_address_geometry(); + let relation_point = base_relation_point + .iter() + .enumerate() + .map(|(index, _)| scalar(601 + index as u64)) + .collect::>(); + let coefficient_point = (0..geometry.relation_coefficient_variable_count()) + .map(|index| scalar(701 + index as u64)) + .collect::>(); + let row_weights = inputs + .eq_tau1 + .iter() + .copied() + .map(|weight| { + if zero_rows { + E::zero() + } else { + E::lift_base(weight) + } + }) + .collect::>(); + let alpha = scalar(809); + let plan = SetupContributionPlan::::prepare::( + &inputs.level_params, + &inputs.opening_batch, + 1, + row_weights.clone().into(), + &layout, + &groups, + PreparedRelationAddress::new(&relation_point).unwrap(), + Some(&fold_gadget), + geometry, + ) + .unwrap(); + let scan = DirectScan::new( + plan, + PreparedCoefficientFunctional::reduced_evaluation(alpha, &coefficient_point, geometry) + .unwrap(), + ) + .unwrap(); + let plan = scan.plan(); + // Check that the fixture exercises the single functional, ratio-one case. + let DirectScanMode::Reduced { groups: direct, .. } = &scan.mode else { + panic!("expected reduced fixture"); + }; + assert_eq!(plan.projection_geometry().base_ring_dim(), 64); + let first = &direct[0].roles[0].functional; + assert_eq!(first.len(), 64); + for group in direct { + for role in &group.roles { + assert_eq!(role.functional.as_ref(), first.as_ref()); + } + } + if blocks == 131 { + // Multiple 2048-ring jobs and a partial last job, without padding away + // the unequal ownership or physical-prefix boundaries. + assert!(plan.required() > super::super::segments::SETUP_SCAN_JOB_RINGS); + assert_ne!( + plan.required() % super::super::segments::SETUP_SCAN_JOB_RINGS, + 0 + ); + } + let setup_coefficients = plan.required() * 64; + let setup = AkitaExpandedSetup::from_trusted_seed_derived_parts_unchecked( + AkitaSetupDescriptor { + max_num_vars: 0, + max_num_batched_polys: 0, + num_field_elements: setup_coefficients, + setup_seed: [0u8; 32].into(), + }, + FlatMatrix::from_flat_data( + (0..setup_coefficients) + .map(|index| test_scalar(901 + index as u128)) + .collect(), + ), + ); + let expected = reduced_direct_literal_oracle( + plan, + &setup, + &inputs, + &groups, + &layout, + &fold_gadget, + &row_weights, + &coefficient_point, + alpha, + ); + assert_eq!(scan.evaluate_direct::(&setup).unwrap(), expected); + if zero_rows { + assert_eq!(expected, E::zero()); + } + + // A truncated public setup is still rejected at the existing boundary. + let truncated = AkitaExpandedSetup::from_trusted_seed_derived_parts_unchecked( + AkitaSetupDescriptor { + max_num_vars: 0, + max_num_batched_polys: 0, + num_field_elements: setup_coefficients - 64, + setup_seed: [0u8; 32].into(), + }, + FlatMatrix::from_flat_data(vec![F::zero(); setup_coefficients - 64]), + ); + assert!(scan.evaluate_direct::(&truncated).is_err()); +} + +#[test] +fn shared_reduced_scan_matches_literal_oracle_across_jobs() { + check_shared_reduced_scan(131, F::from_u64, false); +} + +#[test] +fn shared_reduced_scan_handles_zero_weights_and_boolean_points() { + check_shared_reduced_scan(5, |value| F::from_u64(value % 2), true); + check_shared_reduced_scan(5, |value| F::from_u64(value % 2), false); +} + +#[test] +fn shared_reduced_scan_matches_literal_oracle_over_extension_field() { + type X = jolt_field::Ext2; + check_shared_reduced_scan( + 5, + |value| X::from_base_slice(&[F::from_u64(value), F::from_u64(value + 10_000)]), + false, + ); +} From 3fe67f7fc76df62791b91989590574ebd57bdd00 Mon Sep 17 00:00:00 2001 From: acentelles Date: Sat, 24 Oct 2026 13:13:32 +0100 Subject: [PATCH 08/17] test(setup-contribution): import Ring for from_u64 in the reduced shared-scan tests --- .../src/setup_contribution/tests/reduced_shared.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/akita-verifier/src/setup_contribution/tests/reduced_shared.rs b/crates/akita-verifier/src/setup_contribution/tests/reduced_shared.rs index d80c1dcb1..eb5a4f8ba 100644 --- a/crates/akita-verifier/src/setup_contribution/tests/reduced_shared.rs +++ b/crates/akita-verifier/src/setup_contribution/tests/reduced_shared.rs @@ -1,5 +1,6 @@ use super::fused_scan::reduced_direct_literal_oracle; use super::*; +use jolt_field::Ring; fn check_shared_reduced_scan(blocks: usize, scalar: impl Fn(u64) -> E, zero_rows: bool) where From 36477849e3089ecea1b91725988a16a5e44591a2 Mon Sep 17 00:00:00 2001 From: acentelles Date: Mon, 26 Oct 2026 15:45:26 +0000 Subject: [PATCH 09/17] Add optional no-carry tensor contractions Port onto akita main (#188 ResidualTerms::{Table, Streamed}): the separated residual is prepared per view in DenseLeftOverlap::materialize (the plan no longer sees the equality window) and only from a tabulated residual; a streamed residual declines to the existing walk. The family scalar, which main now applies inside evaluate_residual, is applied to the separated value in the same way. --- crates/akita-algebra/Cargo.toml | 1 + .../src/offset_eq/tensor_pair/materialize.rs | 24 +++ .../tensor_pair/materialize/separate.rs | 182 ++++++++++++++++++ 3 files changed, 207 insertions(+) create mode 100644 crates/akita-algebra/src/offset_eq/tensor_pair/materialize/separate.rs diff --git a/crates/akita-algebra/Cargo.toml b/crates/akita-algebra/Cargo.toml index 7c85cc94a..cda9f6bfa 100644 --- a/crates/akita-algebra/Cargo.toml +++ b/crates/akita-algebra/Cargo.toml @@ -35,6 +35,7 @@ harness = false [features] default = [] parallel = ["dep:rayon", "jolt-field/parallel"] +tensor-no-carry = [] [lints] workspace = true diff --git a/crates/akita-algebra/src/offset_eq/tensor_pair/materialize.rs b/crates/akita-algebra/src/offset_eq/tensor_pair/materialize.rs index 97904ad21..1dd0464ea 100644 --- a/crates/akita-algebra/src/offset_eq/tensor_pair/materialize.rs +++ b/crates/akita-algebra/src/offset_eq/tensor_pair/materialize.rs @@ -182,6 +182,9 @@ pub(in crate::offset_eq) struct DenseLeftTensorView<'a, F: Field> { pub(in crate::offset_eq) residual: ResidualTerms, } +#[cfg(feature = "tensor-no-carry")] +mod separate; + impl DenseLeftTensorView<'_, F> { /// Number of nonzero-weight residual terms. Each axis count is at most /// its validated `len`, so this never exceeds the checked coordinate @@ -443,8 +446,18 @@ impl<'a, F: Field> DenseLeftOverlap<'a, F> { equality: &OffsetEqWindow, output_len: usize, ) -> Result, AkitaError> { + #[cfg(feature = "tensor-no-carry")] + let separated = self + .views + .iter() + .map(|view| separate::SeparatedResidual::prepare(view, equality)) + .collect::, AkitaError>>()?; let evaluate_coordinate = |(coordinate, destination): (usize, &mut F)| { + #[cfg(feature = "tensor-no-carry")] + let mut separated_views = separated.iter(); for view in &self.views { + #[cfg(feature = "tensor-no-carry")] + let prepared = separated_views.next().and_then(Option::as_ref); if view.family.scalar.is_zero() { continue; } @@ -457,6 +470,17 @@ impl<'a, F: Field> DenseLeftOverlap<'a, F> { coordinate, "right", )?; + #[cfg(feature = "tensor-no-carry")] + if let Some(prepared) = prepared { + let value = prepared.evaluate(equality, right_offset)?; + let scalar = view.family.scalar; + *destination += if scalar == F::one() { + value + } else { + scalar * value + }; + continue; + } *destination += view.evaluate_residual(equality, right_offset)?; } Ok::<_, AkitaError>(()) diff --git a/crates/akita-algebra/src/offset_eq/tensor_pair/materialize/separate.rs b/crates/akita-algebra/src/offset_eq/tensor_pair/materialize/separate.rs new file mode 100644 index 000000000..d832d07c6 --- /dev/null +++ b/crates/akita-algebra/src/offset_eq/tensor_pair/materialize/separate.rs @@ -0,0 +1,182 @@ +use super::{DenseLeftTensorView, ResidualTerms}; +use crate::offset_eq::{eq_eval_at_index, OffsetEqWindow}; +use crate::Field; +use akita_error::{checked, AkitaError}; + +pub(super) struct SeparatedResidual { + origin: usize, + low_origin: usize, + high_sum: F, +} + +impl SeparatedResidual { + /// A shared low residue and a no-carry span make the high weighted sum + /// independent of the destination coordinate. No field division is used. + pub(super) fn prepare( + view: &DenseLeftTensorView<'_, F>, + equality: &OffsetEqWindow, + ) -> Result, AkitaError> { + // Only a tabulated residual is separated; a streamed residual keeps + // the original walk. + let ResidualTerms::Table(residual) = &view.residual else { + return Ok(None); + }; + if residual.len() < 2 { + return Ok(None); + } + let axis = + view.family.axes.get(view.destination_axis).ok_or_else(|| { + AkitaError::Internal("tensor view destination axis is absent".into()) + })?; + let Some(last) = axis.len.checked_sub(1) else { + return Ok(None); + }; + let Some(span) = axis.right_stride.checked_mul(last) else { + return Ok(None); + }; + let Some(&(first_offset, _)) = residual.first() else { + return Ok(None); + }; + let origin = view.family.right_offset; + let Some(first_index) = origin.checked_add(first_offset) else { + return Ok(None); + }; + let low_origin = first_index & equality.low_mask; + if low_origin + .checked_add(span) + .is_none_or(|end| end > equality.low_mask) + { + return Ok(None); + } + // Validate every residual before doing field arithmetic. The original + // path remains responsible for errors when this optimization declines. + for &(offset, _) in residual { + let Some(index) = origin.checked_add(offset) else { + return Ok(None); + }; + if index & equality.low_mask != low_origin || index.checked_add(span).is_none() { + return Ok(None); + } + } + let mut high_sum = F::zero(); + for &(offset, weight) in residual { + // The validation above bounds the sum for every residual and coordinate. + let high = (origin + offset) >> equality.low_bits; + let factor = match &equality.eq_high { + Some(table) => table.get(high).copied().unwrap_or_else(F::zero), + None => eq_eval_at_index(&equality.high_challenges, high), + }; + high_sum += if weight == F::one() { + factor + } else { + weight * factor + }; + } + Ok(Some(Self { + origin, + low_origin, + high_sum, + })) + } + + pub(super) fn evaluate( + &self, + equality: &OffsetEqWindow, + base: usize, + ) -> Result { + let index = base + .checked_sub(self.origin) + .and_then(|delta| checked::sum([self.low_origin, delta])) + .ok_or_else(|| AkitaError::Internal("separated tensor low index overflow".into()))?; + let low = equality.eq_low.get(index).copied().ok_or_else(|| { + AkitaError::Internal("separated tensor low index is out of range".into()) + })?; + Ok(low * self.high_sum) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::offset_eq::{EqPairTensorAxis, EqPairTensorFamily}; + use jolt_field::{Fp64, One, Ring, Zero}; + + type F = Fp64<4294967197>; + + #[test] + fn separated_residual_matches_boolean_equality_with_zero_and_one_challenges() { + for challenges in [ + vec![F::from_u64(2); 6], + vec![ + F::zero(), + F::one(), + F::from_u64(3), + F::one(), + F::zero(), + F::from_u64(5), + ], + ] { + let equality = OffsetEqWindow::with_low_bits(&challenges, 3).unwrap(); + let family = + EqPairTensorFamily::new(0, 2, F::one(), vec![EqPairTensorAxis::unit(4, 1, 1)]) + .unwrap(); + let residual = vec![ + (0, F::one()), + (16, F::from_u64(3)), + (32, -F::one()), + (64, F::from_u64(7)), + ]; + let view = DenseLeftTensorView { + family: &family, + destination_axis: 0, + residual: ResidualTerms::Table(residual.clone()), + }; + let prepared = SeparatedResidual::prepare(&view, &equality) + .unwrap() + .unwrap(); + for coordinate in 0..4 { + let expected = residual + .iter() + .map(|&(offset, weight)| { + weight * eq_eval_at_index(&challenges, 2 + coordinate + offset) + }) + .sum::(); + assert_eq!( + prepared.evaluate(&equality, 2 + coordinate).unwrap(), + expected + ); + } + } + } + + #[test] + fn separated_residual_declines_carry_mixed_residue_and_overflow() { + let equality = OffsetEqWindow::with_low_bits(&[F::from_u64(2); 6], 3).unwrap(); + for (origin, len, offsets) in [ + (2, 8, [0, 16]), + (0, 4, [0, 17]), + (usize::MAX - 1, 4, [0, 16]), + ] { + let family = EqPairTensorFamily::new( + 0, + origin, + F::one(), + vec![EqPairTensorAxis::unit(len, 1, 1)], + ) + .unwrap(); + let view = DenseLeftTensorView { + family: &family, + destination_axis: 0, + residual: ResidualTerms::Table( + offsets + .into_iter() + .map(|offset| (offset, F::one())) + .collect(), + ), + }; + assert!(SeparatedResidual::prepare(&view, &equality) + .unwrap() + .is_none()); + } + } +} From 7721c4c9139b0f85423053e2375ed31d59cfe352 Mon Sep 17 00:00:00 2001 From: acentelles Date: Tue, 27 Oct 2026 00:00:47 +0000 Subject: [PATCH 10/17] Add optional tensor equality run accumulation Port onto akita main (#188 ResidualTerms::{Table, Streamed}): the run accumulator is called from DenseLeftOverlap::materialize on the same replaced comment line; it reads only a tabulated residual (a streamed residual declines) and, under tensor-no-carry, takes the per-view separated residuals prepared in materialize instead of a view field. The tests build tabulated views and no longer apply the family scalar on top of evaluate_residual, which includes it on main. --- crates/akita-algebra/Cargo.toml | 2 +- .../src/offset_eq/tensor_pair/materialize.rs | 5 +- .../offset_eq/tensor_pair/materialize/runs.rs | 115 ++++++++++++++++++ .../tensor_pair/materialize/runs/tests.rs | 100 +++++++++++++++ 4 files changed, 220 insertions(+), 2 deletions(-) create mode 100644 crates/akita-algebra/src/offset_eq/tensor_pair/materialize/runs.rs create mode 100644 crates/akita-algebra/src/offset_eq/tensor_pair/materialize/runs/tests.rs diff --git a/crates/akita-algebra/Cargo.toml b/crates/akita-algebra/Cargo.toml index cda9f6bfa..38e33523f 100644 --- a/crates/akita-algebra/Cargo.toml +++ b/crates/akita-algebra/Cargo.toml @@ -36,6 +36,6 @@ harness = false default = [] parallel = ["dep:rayon", "jolt-field/parallel"] tensor-no-carry = [] - +tensor-eq-runs = [] [lints] workspace = true diff --git a/crates/akita-algebra/src/offset_eq/tensor_pair/materialize.rs b/crates/akita-algebra/src/offset_eq/tensor_pair/materialize.rs index 1dd0464ea..457875727 100644 --- a/crates/akita-algebra/src/offset_eq/tensor_pair/materialize.rs +++ b/crates/akita-algebra/src/offset_eq/tensor_pair/materialize.rs @@ -489,7 +489,7 @@ impl<'a, F: Field> DenseLeftOverlap<'a, F> { let destination = output.get_mut(self.destination.clone()).ok_or_else(|| { AkitaError::Internal("validated tensor destination span exceeds the output".into()) })?; - // Tuned with `benches/offset_eq_window.rs::bench_materialize_disjoint_intervals` + #[cfg(feature = "tensor-eq-runs")] if runs::try_accumulate(equality, &self.views, #[cfg(feature = "tensor-no-carry")] &separated, destination)? { return Ok(output); } // on an Apple M4 Max (16 cores, 64 GiB). const PARALLEL_THRESHOLD: usize = 1 << 14; if self.work >= PARALLEL_THRESHOLD { @@ -566,3 +566,6 @@ fn visit_tensor_coordinates( } Ok(()) } + +#[cfg(feature = "tensor-eq-runs")] +mod runs; diff --git a/crates/akita-algebra/src/offset_eq/tensor_pair/materialize/runs.rs b/crates/akita-algebra/src/offset_eq/tensor_pair/materialize/runs.rs new file mode 100644 index 000000000..ede896f6d --- /dev/null +++ b/crates/akita-algebra/src/offset_eq/tensor_pair/materialize/runs.rs @@ -0,0 +1,115 @@ +use super::{DenseLeftTensorView, ResidualTerms}; +use crate::offset_eq::OffsetEqWindow; +use crate::Field; +use akita_error::AkitaError; + +/// Reorder the residual-by-coordinate sum into runs within one low table. +/// The high factor and residual coefficient are constant within each run. +/// Carries end a run; no inversion or nonzero challenge assumption is used. +pub(super) fn try_accumulate( + equality: &OffsetEqWindow, + views: &[DenseLeftTensorView<'_, F>], + #[cfg(feature = "tensor-no-carry")] separated: &[Option>], + destination: &mut [F], +) -> Result { + let Some(high_values) = &equality.eq_high else { + return Ok(false); + }; + if destination.len() < 16 { + return Ok(false); + } + // Finish admission before writing anything, so declining is transactional. + #[cfg(feature = "tensor-no-carry")] + if separated.iter().any(Option::is_some) { + return Ok(false); + } + for view in views { + // Runs need the tabulated residual; a streamed residual declines. + let ResidualTerms::Table(residual) = &view.residual else { + return Ok(false); + }; + let axis = view.family.axes.get(view.destination_axis).ok_or_else(|| { + AkitaError::Internal("tensor run destination axis is absent".into()) + })?; + if !axis.right_stride.is_power_of_two() + || axis.right_stride > equality.eq_low.len() / 8 + || axis.len != destination.len() + { + return Ok(false); + } + let span = axis.right_stride.checked_mul(axis.len - 1).ok_or_else(|| { + AkitaError::InvalidInput("tensor run right span overflow".into()) + })?; + let last = view.family.right_offset.checked_add(span).ok_or_else(|| { + AkitaError::InvalidInput("tensor run right offset overflow".into()) + })?; + if !view.family.scalar.is_zero() { + for &(offset, _) in residual { + last.checked_add(offset).ok_or_else(|| { + AkitaError::InvalidInput("tensor run residual offset overflow".into()) + })?; + } + } + } + for view in views { + if view.family.scalar.is_zero() { + continue; + } + let axis = view.family.axes.get(view.destination_axis).ok_or_else(|| { + AkitaError::Internal("validated tensor run destination axis is absent".into()) + })?; + let ResidualTerms::Table(residual) = &view.residual else { + return Err(AkitaError::Internal( + "validated tensor run residual is not tabulated".into(), + )); + }; + for &(offset, weight) in residual { + let coefficient = if view.family.scalar == F::one() { + weight + } else { + view.family.scalar * weight + }; + let mut index = view.family.right_offset.checked_add(offset).ok_or_else(|| { + AkitaError::Internal("validated tensor run offset overflow".into()) + })?; + let mut remaining = &mut destination[..]; + while !remaining.is_empty() { + let low = index & equality.low_mask; + let high = index >> equality.low_bits; + let Some(&high_value) = high_values.get(high) else { + // Monotone physical addresses cannot reenter the domain. + break; + }; + let available = (equality.low_mask - low) / axis.right_stride + 1; + let take = available.min(remaining.len()); + let (run, tail) = remaining.split_at_mut_checked(take).ok_or_else(|| { + AkitaError::Internal("validated tensor run split exceeds output".into()) + })?; + let scale = if coefficient == F::one() { + high_value + } else { + coefficient * high_value + }; + if !scale.is_zero() { + let low_values = equality.eq_low.get(low..).ok_or_else(|| { + AkitaError::Internal("tensor run low index exceeds table".into()) + })?; + for (value, &low_value) in run.iter_mut().zip(low_values.iter().step_by(axis.right_stride)) { + *value += low_value * scale; + } + } + if tail.is_empty() { + break; + } + index = axis.right_stride.checked_mul(take) + .and_then(|span| index.checked_add(span)) + .ok_or_else(|| AkitaError::Internal("validated tensor run advance overflow".into()))?; + remaining = tail; + } + } + } + Ok(true) +} + +#[cfg(test)] +mod tests; diff --git a/crates/akita-algebra/src/offset_eq/tensor_pair/materialize/runs/tests.rs b/crates/akita-algebra/src/offset_eq/tensor_pair/materialize/runs/tests.rs new file mode 100644 index 000000000..763ee782f --- /dev/null +++ b/crates/akita-algebra/src/offset_eq/tensor_pair/materialize/runs/tests.rs @@ -0,0 +1,100 @@ +use super::*; +use crate::offset_eq::{eq_eval_at_index, EqPairTensorAxis, EqPairTensorFamily}; +use jolt_field::{Fp64, One, Ring, Zero}; +use rand::{rngs::StdRng, Rng, SeedableRng}; + +type F = Fp64<4294967197>; + +#[test] +fn runs_match_scalar_equality_across_carries_and_domain_end() { + let mut rng = StdRng::seed_from_u64(0x5445); + for bits in [8, 10, 12] { + let random = (0..bits).map(|_| F::from_u64(rng.gen_range(0..10000))).collect::>(); + let boolean = (0..bits).map(|i| if i % 2 == 0 { F::zero() } else { F::one() }).collect::>(); + for point in [random, boolean, vec![F::zero(); bits], vec![F::one(); bits]] { + let eq = OffsetEqWindow::new(&point).unwrap(); + for stride in [1, 2] { + for len in [16, 17, 31, 32, 33, 64] { + for start in [0, 1, eq.low_mask, (1 << bits) - 3] { + let family = EqPairTensorFamily::new(0, start, F::from_u64(7), vec![EqPairTensorAxis::unit(len, 1, stride)]).unwrap(); + let residual = vec![(0, F::one()), (3, F::from_u64(9)), (eq.low_mask + 1, -F::one())]; + let view = DenseLeftTensorView { + family: &family, + destination_axis: 0, + residual: ResidualTerms::Table(residual.clone()), + }; + let expected = (0..len).map(|i| { + F::from_u64(11) + family.scalar * residual.iter().map(|&(offset, weight)| { + weight * eq_eval_at_index(&point, start + stride * i + offset) + }).sum::() + }).collect::>(); + let current = (0..len).map(|i| { + F::from_u64(11) + view.evaluate_residual(&eq, start + stride * i).unwrap() + }).collect::>(); + assert_eq!(current, expected); + let mut actual = vec![F::from_u64(11); len]; + assert!(try_accumulate(&eq, &[view], #[cfg(feature = "tensor-no-carry")] &[None], &mut actual).unwrap()); + assert_eq!(actual, expected); + } + } + } + } + } +} + +#[test] +fn multiple_families_accumulate_and_mixed_admission_leaves_output_untouched() { + let point = [F::from_u64(3); 12]; + let eq = OffsetEqWindow::new(&point).unwrap(); + let family = EqPairTensorFamily::new(0, 7, F::one(), vec![EqPairTensorAxis::unit(33, 1, 2)]).unwrap(); + let make_view = || DenseLeftTensorView { + family: &family, + destination_axis: 0, + residual: ResidualTerms::Table(vec![(0, F::from_u64(4)), (15, F::one())]), + }; + let first = make_view(); + let expected = (0..33).map(|i| F::from_u64(2) * first.evaluate_residual(&eq, 7 + 2 * i).unwrap()).collect::>(); + let mut output = vec![F::zero(); 33]; + assert!(try_accumulate(&eq, &[first, make_view()], #[cfg(feature = "tensor-no-carry")] &[None, None], &mut output).unwrap()); + assert_eq!(output, expected); + let invalid = EqPairTensorFamily::new(0, 7, F::one(), vec![EqPairTensorAxis::unit(33, 1, 3)]).unwrap(); + let mut second = make_view(); + second.family = &invalid; + let original = output.clone(); + assert!(!try_accumulate(&eq, &[make_view(), second], #[cfg(feature = "tensor-no-carry")] &[None, None], &mut output).unwrap()); + assert_eq!(output, original); +} + +#[cfg(feature = "tensor-no-carry")] +#[test] +fn banked_no_carry_specialization_keeps_its_dispatch() { + let eq = OffsetEqWindow::new(&[F::from_u64(3); 12]).unwrap(); + let family = EqPairTensorFamily::new(0, 0, F::one(), vec![EqPairTensorAxis::unit(16, 1, 1)]).unwrap(); + let view = DenseLeftTensorView { + family: &family, + destination_axis: 0, + residual: ResidualTerms::Table(vec![(0, F::one()), (64, F::from_u64(5))]), + }; + let separated = [super::super::separate::SeparatedResidual::prepare(&view, &eq).unwrap()]; + assert!(separated[0].is_some()); + let mut output = vec![F::zero(); 16]; + assert!(!try_accumulate(&eq, &[view], &separated, &mut output).unwrap()); + assert_eq!(output, vec![F::zero(); 16]); +} + +#[test] +fn declined_or_overflowing_runs_do_not_write_the_destination() { + let eq = OffsetEqWindow::new(&[F::from_u64(3); 10]).unwrap(); + for (start, stride, len, is_error) in [(0, 3, 32, false), (0, 1, 15, false), (usize::MAX - 2, 1, 32, true)] { + let family = EqPairTensorFamily::new(0, start, F::one(), vec![EqPairTensorAxis::unit(len, 1, stride)]).unwrap(); + let view = DenseLeftTensorView { + family: &family, + destination_axis: 0, + residual: ResidualTerms::Table(vec![(0, F::one())]), + }; + let mut output = vec![F::from_u64(17); len]; + let result = try_accumulate(&eq, &[view], #[cfg(feature = "tensor-no-carry")] &[None], &mut output); + if is_error { assert!(result.is_err()); } else { assert!(!result.unwrap()); } + assert_eq!(output, vec![F::from_u64(17); len]); + } +} From 1ad19b969864e6833d141c3bde0d6630c3659e1d Mon Sep 17 00:00:00 2001 From: acentelles Date: Tue, 27 Oct 2026 00:09:31 +0000 Subject: [PATCH 11/17] Use power-of-two run shifts and test Fp128 boundaries Port onto akita main (#188): keeps the earlier port (tabulated residuals only, scalar on main inside evaluate_residual). The run accumulator now takes a plain bool (some view took the no-carry separated path) instead of a cfg-gated slice argument, because rustfmt drops a cfg-gated call argument; the call site in DenseLeftOverlap::materialize is written in rustfmt form and the original comment line is restored (not line-preserving on this base). --- .../src/offset_eq/tensor_pair/materialize.rs | 10 +- .../offset_eq/tensor_pair/materialize/runs.rs | 53 +++++---- .../tensor_pair/materialize/runs/tests.rs | 106 +++++++++++++----- 3 files changed, 124 insertions(+), 45 deletions(-) diff --git a/crates/akita-algebra/src/offset_eq/tensor_pair/materialize.rs b/crates/akita-algebra/src/offset_eq/tensor_pair/materialize.rs index 457875727..2f961e637 100644 --- a/crates/akita-algebra/src/offset_eq/tensor_pair/materialize.rs +++ b/crates/akita-algebra/src/offset_eq/tensor_pair/materialize.rs @@ -489,7 +489,15 @@ impl<'a, F: Field> DenseLeftOverlap<'a, F> { let destination = output.get_mut(self.destination.clone()).ok_or_else(|| { AkitaError::Internal("validated tensor destination span exceeds the output".into()) })?; - #[cfg(feature = "tensor-eq-runs")] if runs::try_accumulate(equality, &self.views, #[cfg(feature = "tensor-no-carry")] &separated, destination)? { return Ok(output); } + #[cfg(all(feature = "tensor-eq-runs", feature = "tensor-no-carry"))] + let runs_declined = separated.iter().any(Option::is_some); + #[cfg(all(feature = "tensor-eq-runs", not(feature = "tensor-no-carry")))] + let runs_declined = false; + #[cfg(feature = "tensor-eq-runs")] + if runs::try_accumulate(equality, &self.views, runs_declined, destination)? { + return Ok(output); + } + // Tuned with `benches/offset_eq_window.rs::bench_materialize_disjoint_intervals` // on an Apple M4 Max (16 cores, 64 GiB). const PARALLEL_THRESHOLD: usize = 1 << 14; if self.work >= PARALLEL_THRESHOLD { diff --git a/crates/akita-algebra/src/offset_eq/tensor_pair/materialize/runs.rs b/crates/akita-algebra/src/offset_eq/tensor_pair/materialize/runs.rs index ede896f6d..5a3ee622b 100644 --- a/crates/akita-algebra/src/offset_eq/tensor_pair/materialize/runs.rs +++ b/crates/akita-algebra/src/offset_eq/tensor_pair/materialize/runs.rs @@ -9,7 +9,7 @@ use akita_error::AkitaError; pub(super) fn try_accumulate( equality: &OffsetEqWindow, views: &[DenseLeftTensorView<'_, F>], - #[cfg(feature = "tensor-no-carry")] separated: &[Option>], + separated: bool, destination: &mut [F], ) -> Result { let Some(high_values) = &equality.eq_high else { @@ -19,8 +19,8 @@ pub(super) fn try_accumulate( return Ok(false); } // Finish admission before writing anything, so declining is transactional. - #[cfg(feature = "tensor-no-carry")] - if separated.iter().any(Option::is_some) { + // A view that takes the no-carry separated path keeps that dispatch. + if separated { return Ok(false); } for view in views { @@ -28,21 +28,24 @@ pub(super) fn try_accumulate( let ResidualTerms::Table(residual) = &view.residual else { return Ok(false); }; - let axis = view.family.axes.get(view.destination_axis).ok_or_else(|| { - AkitaError::Internal("tensor run destination axis is absent".into()) - })?; + let axis = + view.family.axes.get(view.destination_axis).ok_or_else(|| { + AkitaError::Internal("tensor run destination axis is absent".into()) + })?; if !axis.right_stride.is_power_of_two() || axis.right_stride > equality.eq_low.len() / 8 || axis.len != destination.len() { return Ok(false); } - let span = axis.right_stride.checked_mul(axis.len - 1).ok_or_else(|| { - AkitaError::InvalidInput("tensor run right span overflow".into()) - })?; - let last = view.family.right_offset.checked_add(span).ok_or_else(|| { - AkitaError::InvalidInput("tensor run right offset overflow".into()) - })?; + let span = axis + .right_stride + .checked_mul(axis.len - 1) + .ok_or_else(|| AkitaError::InvalidInput("tensor run right span overflow".into()))?; + let last = + view.family.right_offset.checked_add(span).ok_or_else(|| { + AkitaError::InvalidInput("tensor run right offset overflow".into()) + })?; if !view.family.scalar.is_zero() { for &(offset, _) in residual { last.checked_add(offset).ok_or_else(|| { @@ -58,6 +61,7 @@ pub(super) fn try_accumulate( let axis = view.family.axes.get(view.destination_axis).ok_or_else(|| { AkitaError::Internal("validated tensor run destination axis is absent".into()) })?; + let stride_bits = axis.right_stride.trailing_zeros(); let ResidualTerms::Table(residual) = &view.residual else { return Err(AkitaError::Internal( "validated tensor run residual is not tabulated".into(), @@ -69,9 +73,13 @@ pub(super) fn try_accumulate( } else { view.family.scalar * weight }; - let mut index = view.family.right_offset.checked_add(offset).ok_or_else(|| { - AkitaError::Internal("validated tensor run offset overflow".into()) - })?; + let mut index = view + .family + .right_offset + .checked_add(offset) + .ok_or_else(|| { + AkitaError::Internal("validated tensor run offset overflow".into()) + })?; let mut remaining = &mut destination[..]; while !remaining.is_empty() { let low = index & equality.low_mask; @@ -80,7 +88,7 @@ pub(super) fn try_accumulate( // Monotone physical addresses cannot reenter the domain. break; }; - let available = (equality.low_mask - low) / axis.right_stride + 1; + let available = ((equality.low_mask - low) >> stride_bits) + 1; let take = available.min(remaining.len()); let (run, tail) = remaining.split_at_mut_checked(take).ok_or_else(|| { AkitaError::Internal("validated tensor run split exceeds output".into()) @@ -94,16 +102,23 @@ pub(super) fn try_accumulate( let low_values = equality.eq_low.get(low..).ok_or_else(|| { AkitaError::Internal("tensor run low index exceeds table".into()) })?; - for (value, &low_value) in run.iter_mut().zip(low_values.iter().step_by(axis.right_stride)) { + for (value, &low_value) in run + .iter_mut() + .zip(low_values.iter().step_by(axis.right_stride)) + { *value += low_value * scale; } } if tail.is_empty() { break; } - index = axis.right_stride.checked_mul(take) + index = axis + .right_stride + .checked_mul(take) .and_then(|span| index.checked_add(span)) - .ok_or_else(|| AkitaError::Internal("validated tensor run advance overflow".into()))?; + .ok_or_else(|| { + AkitaError::Internal("validated tensor run advance overflow".into()) + })?; remaining = tail; } } diff --git a/crates/akita-algebra/src/offset_eq/tensor_pair/materialize/runs/tests.rs b/crates/akita-algebra/src/offset_eq/tensor_pair/materialize/runs/tests.rs index 763ee782f..60e31e018 100644 --- a/crates/akita-algebra/src/offset_eq/tensor_pair/materialize/runs/tests.rs +++ b/crates/akita-algebra/src/offset_eq/tensor_pair/materialize/runs/tests.rs @@ -7,33 +7,70 @@ type F = Fp64<4294967197>; #[test] fn runs_match_scalar_equality_across_carries_and_domain_end() { + check_runs::(); +} + +#[test] +fn fp128_runs_match_scalar_equality_across_carries_and_domain_end() { + check_runs::(); +} + +fn check_runs() { let mut rng = StdRng::seed_from_u64(0x5445); - for bits in [8, 10, 12] { - let random = (0..bits).map(|_| F::from_u64(rng.gen_range(0..10000))).collect::>(); - let boolean = (0..bits).map(|i| if i % 2 == 0 { F::zero() } else { F::one() }).collect::>(); + for bits in [8, 10, 12, 20] { + let random = (0..bits) + .map(|_| F::from_u64(rng.gen_range(0..10000))) + .collect::>(); + let boolean = (0..bits) + .map(|i| if i % 2 == 0 { F::zero() } else { F::one() }) + .collect::>(); for point in [random, boolean, vec![F::zero(); bits], vec![F::one(); bits]] { let eq = OffsetEqWindow::new(&point).unwrap(); for stride in [1, 2] { for len in [16, 17, 31, 32, 33, 64] { for start in [0, 1, eq.low_mask, (1 << bits) - 3] { - let family = EqPairTensorFamily::new(0, start, F::from_u64(7), vec![EqPairTensorAxis::unit(len, 1, stride)]).unwrap(); - let residual = vec![(0, F::one()), (3, F::from_u64(9)), (eq.low_mask + 1, -F::one())]; + let family = EqPairTensorFamily::new( + 0, + start, + F::from_u64(7), + vec![EqPairTensorAxis::unit(len, 1, stride)], + ) + .unwrap(); + let residual = vec![ + (0, F::one()), + (3, F::from_u64(9)), + (eq.low_mask + 1, -F::one()), + ]; let view = DenseLeftTensorView { family: &family, destination_axis: 0, residual: ResidualTerms::Table(residual.clone()), }; - let expected = (0..len).map(|i| { - F::from_u64(11) + family.scalar * residual.iter().map(|&(offset, weight)| { - weight * eq_eval_at_index(&point, start + stride * i + offset) - }).sum::() - }).collect::>(); - let current = (0..len).map(|i| { - F::from_u64(11) + view.evaluate_residual(&eq, start + stride * i).unwrap() - }).collect::>(); + let expected = (0..len) + .map(|i| { + F::from_u64(11) + + family.scalar + * residual + .iter() + .map(|&(offset, weight)| { + weight + * eq_eval_at_index( + &point, + start + stride * i + offset, + ) + }) + .sum::() + }) + .collect::>(); + let current = (0..len) + .map(|i| { + F::from_u64(11) + + view.evaluate_residual(&eq, start + stride * i).unwrap() + }) + .collect::>(); assert_eq!(current, expected); let mut actual = vec![F::from_u64(11); len]; - assert!(try_accumulate(&eq, &[view], #[cfg(feature = "tensor-no-carry")] &[None], &mut actual).unwrap()); + assert!(try_accumulate(&eq, &[view], false, &mut actual).unwrap()); assert_eq!(actual, expected); } } @@ -46,22 +83,26 @@ fn runs_match_scalar_equality_across_carries_and_domain_end() { fn multiple_families_accumulate_and_mixed_admission_leaves_output_untouched() { let point = [F::from_u64(3); 12]; let eq = OffsetEqWindow::new(&point).unwrap(); - let family = EqPairTensorFamily::new(0, 7, F::one(), vec![EqPairTensorAxis::unit(33, 1, 2)]).unwrap(); + let family = + EqPairTensorFamily::new(0, 7, F::one(), vec![EqPairTensorAxis::unit(33, 1, 2)]).unwrap(); let make_view = || DenseLeftTensorView { family: &family, destination_axis: 0, residual: ResidualTerms::Table(vec![(0, F::from_u64(4)), (15, F::one())]), }; let first = make_view(); - let expected = (0..33).map(|i| F::from_u64(2) * first.evaluate_residual(&eq, 7 + 2 * i).unwrap()).collect::>(); + let expected = (0..33) + .map(|i| F::from_u64(2) * first.evaluate_residual(&eq, 7 + 2 * i).unwrap()) + .collect::>(); let mut output = vec![F::zero(); 33]; - assert!(try_accumulate(&eq, &[first, make_view()], #[cfg(feature = "tensor-no-carry")] &[None, None], &mut output).unwrap()); + assert!(try_accumulate(&eq, &[first, make_view()], false, &mut output).unwrap()); assert_eq!(output, expected); - let invalid = EqPairTensorFamily::new(0, 7, F::one(), vec![EqPairTensorAxis::unit(33, 1, 3)]).unwrap(); + let invalid = + EqPairTensorFamily::new(0, 7, F::one(), vec![EqPairTensorAxis::unit(33, 1, 3)]).unwrap(); let mut second = make_view(); second.family = &invalid; let original = output.clone(); - assert!(!try_accumulate(&eq, &[make_view(), second], #[cfg(feature = "tensor-no-carry")] &[None, None], &mut output).unwrap()); + assert!(!try_accumulate(&eq, &[make_view(), second], false, &mut output).unwrap()); assert_eq!(output, original); } @@ -69,7 +110,8 @@ fn multiple_families_accumulate_and_mixed_admission_leaves_output_untouched() { #[test] fn banked_no_carry_specialization_keeps_its_dispatch() { let eq = OffsetEqWindow::new(&[F::from_u64(3); 12]).unwrap(); - let family = EqPairTensorFamily::new(0, 0, F::one(), vec![EqPairTensorAxis::unit(16, 1, 1)]).unwrap(); + let family = + EqPairTensorFamily::new(0, 0, F::one(), vec![EqPairTensorAxis::unit(16, 1, 1)]).unwrap(); let view = DenseLeftTensorView { family: &family, destination_axis: 0, @@ -78,23 +120,37 @@ fn banked_no_carry_specialization_keeps_its_dispatch() { let separated = [super::super::separate::SeparatedResidual::prepare(&view, &eq).unwrap()]; assert!(separated[0].is_some()); let mut output = vec![F::zero(); 16]; - assert!(!try_accumulate(&eq, &[view], &separated, &mut output).unwrap()); + assert!(!try_accumulate(&eq, &[view], separated[0].is_some(), &mut output).unwrap()); assert_eq!(output, vec![F::zero(); 16]); } #[test] fn declined_or_overflowing_runs_do_not_write_the_destination() { let eq = OffsetEqWindow::new(&[F::from_u64(3); 10]).unwrap(); - for (start, stride, len, is_error) in [(0, 3, 32, false), (0, 1, 15, false), (usize::MAX - 2, 1, 32, true)] { - let family = EqPairTensorFamily::new(0, start, F::one(), vec![EqPairTensorAxis::unit(len, 1, stride)]).unwrap(); + for (start, stride, len, is_error) in [ + (0, 3, 32, false), + (0, 1, 15, false), + (usize::MAX - 2, 1, 32, true), + ] { + let family = EqPairTensorFamily::new( + 0, + start, + F::one(), + vec![EqPairTensorAxis::unit(len, 1, stride)], + ) + .unwrap(); let view = DenseLeftTensorView { family: &family, destination_axis: 0, residual: ResidualTerms::Table(vec![(0, F::one())]), }; let mut output = vec![F::from_u64(17); len]; - let result = try_accumulate(&eq, &[view], #[cfg(feature = "tensor-no-carry")] &[None], &mut output); - if is_error { assert!(result.is_err()); } else { assert!(!result.unwrap()); } + let result = try_accumulate(&eq, &[view], false, &mut output); + if is_error { + assert!(result.is_err()); + } else { + assert!(!result.unwrap()); + } assert_eq!(output, vec![F::from_u64(17); len]); } } From a2b83d94babf264530b2b17a0130d6f12d88a05a Mon Sep 17 00:00:00 2001 From: acentelles Date: Tue, 27 Oct 2026 04:01:25 +0000 Subject: [PATCH 12/17] Add optional line-preserving sums of products at the structured setup-scan sites Feature setup-sop-structured (default off; forwarded by akita-pcs) sums the cached structured E, T and Z contractions of the verifier setup scan through Field::dot_product and Field::sum_of_products. The scan-path kernels (the identity-path D/B/A weight loop and the B role terms) keep their current code. Field values are unchanged. Line-preserving: each structured call site selects through lb2_alt!, opened on the first and closed on the last line of the original statement (rustfmt::skip on the same line); every new item is appended after the last original line of its file, and the new module lb2.rs is declared at the end of mod.rs. Without the feature the expansion is the original tokens on their original lines. --- crates/akita-pcs/Cargo.toml | 3 + crates/akita-verifier/Cargo.toml | 5 + .../src/setup_contribution/lb2.rs | 147 ++++++++++++++++++ .../src/setup_contribution/mod.rs | 3 + .../src/setup_contribution/structured.rs | 41 ++++- 5 files changed, 193 insertions(+), 6 deletions(-) create mode 100644 crates/akita-verifier/src/setup_contribution/lb2.rs diff --git a/crates/akita-pcs/Cargo.toml b/crates/akita-pcs/Cargo.toml index ab9d3aa57..1d5af57ed 100644 --- a/crates/akita-pcs/Cargo.toml +++ b/crates/akita-pcs/Cargo.toml @@ -53,6 +53,9 @@ transcript-keccak = [ "akita-params/transcript-keccak", "akita-verifier/transcript-keccak", ] +# Optional (default off): sums of products at the structured +# sites of the verifier's setup scan (same field values). +setup-sop-structured = ["akita-verifier/setup-sop-structured"] parallel = [ "dep:rayon", "akita-algebra/parallel", diff --git a/crates/akita-verifier/Cargo.toml b/crates/akita-verifier/Cargo.toml index 9b1d7d72f..72cdf5bcc 100644 --- a/crates/akita-verifier/Cargo.toml +++ b/crates/akita-verifier/Cargo.toml @@ -50,6 +50,11 @@ transcript-keccak = [ "akita-params/transcript-keccak", ] benchmark-support = [] +# Optional (default off): the setup scan's cached structured +# E, T and Z contractions sum their two-factor products through +# `Field::sum_of_products` / `Field::dot_product` (same field values; one +# readout per sum on a field-inline guest). The scan-path kernels are unchanged. +setup-sop-structured = [] parallel = [ "dep:rayon", "akita-algebra/parallel", diff --git a/crates/akita-verifier/src/setup_contribution/lb2.rs b/crates/akita-verifier/src/setup_contribution/lb2.rs new file mode 100644 index 000000000..afbf26d82 --- /dev/null +++ b/crates/akita-verifier/src/setup_contribution/lb2.rs @@ -0,0 +1,147 @@ +//! Sums of two-factor products at the structured setup-scan sites (feature `setup-sop-structured`, default off). +//! +//! `lb2_alt!` selects, at each call site, between the original tokens (`off`, compiled without the feature, token for +//! token as before) and the summed path (`on`). The call sites keep their line numbers: the selector opens on the first +//! line and closes on the last line of the original statement, and every new item is appended after the last original +//! line of its file. Without the feature the expansion is exactly the original tokens, so the guest image is unchanged. +//! +//! [`PairSum`] buffers up to [`PAIR_CHUNK`] factor pairs on the stack and hands each full chunk to +//! [`Field::sum_of_products`]. On a field-inline guest that call keeps the running sum in the field register file and +//! reads out one value per chunk, where the plain `sum += a * b` loop reads out every product and adds it in software. +//! The result is the same field element on every path. A chunk holding a single pair takes the plain multiply, so a +//! one-product sum costs what it did before. + +/// Feature-off: the original tokens. +#[cfg(not(feature = "setup-sop-structured"))] +macro_rules! lb2_alt { + (off { $($off:tt)* } on { $($on:tt)* }) => { $($off)* }; +} +/// Feature-on: the sums-of-products path. +#[cfg(feature = "setup-sop-structured")] +macro_rules! lb2_alt { + (off { $($off:tt)* } on { $($on:tt)* }) => { $($on)* }; +} +pub(super) use lb2_alt; + +#[cfg(any(feature = "setup-sop-structured", test))] +use core::mem::MaybeUninit; +#[cfg(any(feature = "setup-sop-structured", test))] +use jolt_field::Field; + +/// Pairs per [`Field::sum_of_products`] call. +#[cfg(any(feature = "setup-sop-structured", test))] +pub(super) const PAIR_CHUNK: usize = 8; + +/// `Σ a_i · b_i` over the pushed pairs. +#[cfg(any(feature = "setup-sop-structured", test))] +pub(super) struct PairSum { + buf: [MaybeUninit<[E; 2]>; PAIR_CHUNK], + len: usize, + sum: Option, +} + +#[cfg(any(feature = "setup-sop-structured", test))] +impl PairSum { + #[inline(always)] + pub(super) fn new() -> Self { + Self { + buf: [const { MaybeUninit::uninit() }; PAIR_CHUNK], + len: 0, + sum: None, + } + } + + #[inline(always)] + pub(super) fn push(&mut self, a: E, b: E) { + if self.len == PAIR_CHUNK { + self.flush(); + } + self.buf[self.len].write([a, b]); + self.len += 1; + } + + #[inline(always)] + fn flush(&mut self) { + // SAFETY: `push` wrote the first `len` entries of `buf`, and + // `MaybeUninit<[E; 2]>` has the layout of `[E; 2]`. + let pairs: &[[E; 2]] = + unsafe { core::slice::from_raw_parts(self.buf.as_ptr().cast::<[E; 2]>(), self.len) }; + let chunk = match pairs { + [] => return, + [[a, b]] => *a * *b, + _ => E::sum_of_products(pairs), + }; + self.len = 0; + self.sum = Some(match self.sum { + Some(sum) => sum + chunk, + None => chunk, + }); + } + + /// The sum of every pushed product (zero when none was pushed). + #[inline(always)] + pub(super) fn finish(mut self) -> E { + self.flush(); + self.sum.unwrap_or_else(E::zero) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use jolt_field::{Prime128OffsetA7F7, Ring, Zero}; + + type F = Prime128OffsetA7F7; + + /// Deterministic full-width elements (a 64-bit LCG, two draws per element). + fn elements(seed: u64, n: usize) -> Vec { + let mut state = seed; + let mut next = || { + state = state + .wrapping_mul(6364136223846793005) + .wrapping_add(1442695040888963407); + state + }; + (0..n) + .map(|_| { + F::from_u64(next()) * F::from_u64(1 << 63) * F::from_u64(2) + F::from_u64(next()) + }) + .collect() + } + + fn plain(a: &[F], b: &[F]) -> F { + a.iter().zip(b).fold(F::zero(), |sum, (&x, &y)| sum + x * y) + } + + #[test] + fn pair_sum_matches_plain_fold_for_every_length() { + for len in 0..=3 * PAIR_CHUNK + 1 { + for seed in 0..4u64 { + let a = elements(2 * seed + 1, len); + let b = elements(2 * seed + 2 + 100 * len as u64, len); + let mut sum = PairSum::new(); + for (&x, &y) in a.iter().zip(&b) { + sum.push(x, y); + } + assert_eq!(sum.finish(), plain(&a, &b), "length {len}"); + } + } + } + + #[test] + fn pair_sum_matches_sum_of_products() { + let a = elements(7, 2 * PAIR_CHUNK + 3); + let b = elements(11, 2 * PAIR_CHUNK + 3); + let terms: Vec<[F; 2]> = a.iter().zip(&b).map(|(&x, &y)| [x, y]).collect(); + let mut sum = PairSum::new(); + for &[x, y] in &terms { + sum.push(x, y); + } + assert_eq!(sum.finish(), F::sum_of_products(&terms)); + } + + #[test] + fn pair_sum_of_nothing_is_zero() { + assert_eq!(PairSum::::new().finish(), F::zero()); + } +} diff --git a/crates/akita-verifier/src/setup_contribution/mod.rs b/crates/akita-verifier/src/setup_contribution/mod.rs index cc0ca778b..1f749d380 100644 --- a/crates/akita-verifier/src/setup_contribution/mod.rs +++ b/crates/akita-verifier/src/setup_contribution/mod.rs @@ -82,3 +82,6 @@ use reduced_role::{ materialize_reduced_role_tensor_weights, prepare_reduced_role_coefficient_state, }; use segments::scan_partition; + +// Appended after the last original line: the `lb2_alt!` selector and, with the feature, `PairSum`. +mod lb2; diff --git a/crates/akita-verifier/src/setup_contribution/structured.rs b/crates/akita-verifier/src/setup_contribution/structured.rs index e8e6aaa51..5d700f575 100644 --- a/crates/akita-verifier/src/setup_contribution/structured.rs +++ b/crates/akita-verifier/src/setup_contribution/structured.rs @@ -192,16 +192,16 @@ impl DirectScan { .checked_mul(e_stride) .ok_or(AkitaError::InvalidProof)?; let e_eq = checked_slice(&weights.e, e_start, e_stride, "structured direct E slice")?; - let e = e_eq + #[rustfmt::skip] let e = lb2_alt! { off { e_eq .iter() .zip(direct_opening_gadget) - .fold(E::zero(), |sum, (&eq, &gadget)| sum + eq * gadget); + .fold(E::zero(), |sum, (&eq, &gadget)| sum + eq * gadget) } on { lb2_dot(e_eq, direct_opening_gadget) } }; let t_start = block_claim .checked_mul(t_stride) .ok_or(AkitaError::InvalidProof)?; let t_eq = checked_slice(&weights.t, t_start, t_stride, "structured direct T slice")?; - let t = t_eq + #[rustfmt::skip] let t = lb2_alt! { off { t_eq .chunks_exact(t_row_stride) .zip(group.a_row_weights().iter()) .fold(E::zero(), |sum, (row, &row_weight)| { @@ -210,7 +210,7 @@ impl DirectScan { .iter() .zip(direct_commitment_gadget) .fold(E::zero(), |inner, (&eq, &gadget)| inner + eq * gadget) - }); + }) } on { lb2_t(t_eq, t_row_stride, group.a_row_weights(), direct_commitment_gadget) } }; let block_challenge = *block_challenges .get(block_claim) .ok_or(AkitaError::InvalidProof)?; @@ -247,10 +247,10 @@ impl DirectScan { group.depth_witness(), "structured direct Z slice", )?; - let inner = eq + #[rustfmt::skip] let inner = lb2_alt! { off { eq .iter() .zip(direct_witness_gadget) - .fold(E::zero(), |sum, (&eq, &gadget)| sum + eq * gadget); + .fold(E::zero(), |sum, (&eq, &gadget)| sum + eq * gadget) } on { lb2_dot(eq, direct_witness_gadget) } }; Ok(acc? + *opening_a_evals .get(position) @@ -581,3 +581,32 @@ where evaluation }) } + +// Feature `setup-sop-structured`, default off. Appended after the last original line so the +// feature-off source keeps every line number; the call sites above select these paths through `lb2_alt!`. +use super::lb2::lb2_alt; +#[cfg(feature = "setup-sop-structured")] +use super::lb2::PairSum; + +/// `Σ a[i]·b[i]` over the shorter slice, the same value as the plain zip-fold. Two or more products go through +/// `Field::dot_product` (one readout on a field-inline guest); a single product keeps the plain fold. +#[cfg(feature = "setup-sop-structured")] +#[inline(always)] +fn lb2_dot(a: &[E], b: &[E]) -> E { + if a.len().min(b.len()) >= 2 { + E::dot_product(a, b) + } else { + a.iter().zip(b).fold(E::zero(), |sum, (&x, &y)| sum + x * y) + } +} + +/// The structured T term, `Σ_row row_weight · dot(row, gadget)` with the outer sum through `PairSum`. +#[cfg(feature = "setup-sop-structured")] +#[inline(always)] +fn lb2_t(t_eq: &[E], t_row_stride: usize, row_weights: &[E], gadget: &[E]) -> E { + let mut sum = PairSum::new(); + for (row, &row_weight) in t_eq.chunks_exact(t_row_stride).zip(row_weights.iter()) { + sum.push(row_weight, lb2_dot(row, gadget)); + } + sum.finish() +} From eb2ab64668774e27786b7acaffd69df24c1b3022 Mon Sep 17 00:00:00 2001 From: acentelles Date: Wed, 28 Oct 2026 20:47:48 +0000 Subject: [PATCH 13/17] test(pcs): pass the witness chunking to the cross-check roundtrips --- crates/akita-pcs/tests/akita_fp128_e2e.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/crates/akita-pcs/tests/akita_fp128_e2e.rs b/crates/akita-pcs/tests/akita_fp128_e2e.rs index 05e4611e3..9000c69bd 100644 --- a/crates/akita-pcs/tests/akita_fp128_e2e.rs +++ b/crates/akita-pcs/tests/akita_fp128_e2e.rs @@ -691,9 +691,18 @@ fn fp128_compression_weights_crosscheck() { init_rayon_pool(); run_on_large_stack(|| { let before = report(); - prove_verify_dense_roundtrip::(&[14, 16], b"crosscheck/fp128_dense"); - prove_verify_onehot_roundtrip::(&[12, 15], b"crosscheck/fp128_onehot"); + prove_verify_dense_roundtrip::( + ChunkedWitnessCfg::default_non_chunked(), + &[14, 16], + b"crosscheck/fp128_dense", + ); + prove_verify_onehot_roundtrip::( + ChunkedWitnessCfg::default_non_chunked(), + &[12, 15], + b"crosscheck/fp128_onehot", + ); prove_verify_onehot_precommitted_roundtrip::( + ChunkedWitnessCfg::default_non_chunked(), &[16], b"crosscheck/fp128_onehot_pre", ); From 4f781ad03b7a3c5d585277b3d766472448c11b8d Mon Sep 17 00:00:00 2001 From: acentelles Date: Thu, 29 Oct 2026 23:30:00 +0000 Subject: [PATCH 14/17] build: regenerate the lockfiles for the Jolt pin Cargo.lock, fuzz/Cargo.lock and profile/akita-recursion/Cargo.lock resolved by cargo against the new a16z/jolt revision. --- Cargo.lock | 6 +- fuzz/Cargo.lock | 6 +- profile/akita-recursion/Cargo.lock | 594 ++++++++++------------------- 3 files changed, 198 insertions(+), 408 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b390df64c..cd5135b4f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -929,7 +929,7 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jolt-field" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ "cc", "num-traits", @@ -942,7 +942,7 @@ dependencies = [ [[package]] name = "jolt-poly" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ "jolt-field", "jolt-utils", @@ -956,7 +956,7 @@ dependencies = [ [[package]] name = "jolt-utils" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ "num-traits", ] diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index 1f991f592..5a3517b62 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -713,7 +713,7 @@ dependencies = [ [[package]] name = "jolt-field" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ "cc", "num-traits", @@ -726,7 +726,7 @@ dependencies = [ [[package]] name = "jolt-poly" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ "jolt-field", "jolt-utils", @@ -740,7 +740,7 @@ dependencies = [ [[package]] name = "jolt-utils" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ "num-traits", ] diff --git a/profile/akita-recursion/Cargo.lock b/profile/akita-recursion/Cargo.lock index fce4d72f9..2fb7be221 100644 --- a/profile/akita-recursion/Cargo.lock +++ b/profile/akita-recursion/Cargo.lock @@ -148,6 +148,17 @@ dependencies = [ "tracing", ] +[[package]] +name = "akita-planner" +version = "0.1.0" +dependencies = [ + "akita-challenges", + "akita-error", + "akita-params", + "akita-schedules", + "libm", +] + [[package]] name = "akita-prover" version = "0.1.0" @@ -412,9 +423,9 @@ version = "0.5.0" source = "git+https://github.com/a16z/arkworks-algebra?branch=dev%2Ftwist-shout#76bb3a4518928f1ff7f15875f940d614bb9845e6" dependencies = [ "ark-ec", - "ark-ff 0.5.0", - "ark-serialize 0.5.0", - "ark-std 0.5.0", + "ark-ff", + "ark-serialize", + "ark-std", ] [[package]] @@ -423,10 +434,10 @@ version = "0.5.0" source = "git+https://github.com/a16z/arkworks-algebra?branch=dev%2Ftwist-shout#76bb3a4518928f1ff7f15875f940d614bb9845e6" dependencies = [ "ahash", - "ark-ff 0.5.0", + "ark-ff", "ark-poly", - "ark-serialize 0.5.0", - "ark-std 0.5.0", + "ark-serialize", + "ark-std", "educe", "fnv", "hashbrown 0.15.5", @@ -444,10 +455,10 @@ version = "0.5.0" source = "git+https://github.com/a16z/arkworks-algebra?branch=dev%2Ftwist-shout#76bb3a4518928f1ff7f15875f940d614bb9845e6" dependencies = [ "allocative", - "ark-ff-asm 0.5.0", - "ark-ff-macros 0.5.0", - "ark-serialize 0.5.0", - "ark-std 0.5.0", + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", "arrayvec", "digest 0.10.7", "educe", @@ -459,23 +470,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "ark-ff" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7a806ac6c8307b929df4645776290a50ee2aac754ad09d8bdf73391309e43af" -dependencies = [ - "ark-ff-asm 0.6.0", - "ark-ff-macros 0.6.0", - "ark-serialize 0.6.0", - "ark-std 0.6.0", - "digest 0.10.7", - "educe", - "num-bigint 0.4.8", - "num-traits", - "zeroize", -] - [[package]] name = "ark-ff-asm" version = "0.5.0" @@ -485,16 +479,6 @@ dependencies = [ "syn 2.0.119", ] -[[package]] -name = "ark-ff-asm" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1479009684adc073dff49a1025d3a7065b317a9ead25aaaca38cdc70058ba8a2" -dependencies = [ - "quote", - "syn 2.0.119", -] - [[package]] name = "ark-ff-macros" version = "0.5.0" @@ -507,28 +491,15 @@ dependencies = [ "syn 2.0.119", ] -[[package]] -name = "ark-ff-macros" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a0691ed21ef00ef89c1e9bda832eba493dda3ec2f8d892fb25b705f73f06bb8" -dependencies = [ - "num-bigint 0.4.8", - "num-traits", - "proc-macro2", - "quote", - "syn 2.0.119", -] - [[package]] name = "ark-poly" version = "0.5.0" source = "git+https://github.com/a16z/arkworks-algebra?branch=dev%2Ftwist-shout#76bb3a4518928f1ff7f15875f940d614bb9845e6" dependencies = [ "ahash", - "ark-ff 0.5.0", - "ark-serialize 0.5.0", - "ark-std 0.5.0", + "ark-ff", + "ark-serialize", + "ark-std", "educe", "fnv", "hashbrown 0.15.5", @@ -539,26 +510,14 @@ name = "ark-serialize" version = "0.5.0" source = "git+https://github.com/a16z/arkworks-algebra?branch=dev%2Ftwist-shout#76bb3a4518928f1ff7f15875f940d614bb9845e6" dependencies = [ - "ark-serialize-derive 0.5.0", - "ark-std 0.5.0", + "ark-serialize-derive", + "ark-std", "arrayvec", "digest 0.10.7", "num-bigint 0.4.8", "rayon", ] -[[package]] -name = "ark-serialize" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a74dd304fd536fb95d0a328e72be759209cc496a9da094c5bc56e5fea4f9e86b" -dependencies = [ - "ark-serialize-derive 0.6.0", - "ark-std 0.6.0", - "digest 0.10.7", - "num-bigint 0.4.8", -] - [[package]] name = "ark-serialize-derive" version = "0.5.0" @@ -569,17 +528,6 @@ dependencies = [ "syn 2.0.119", ] -[[package]] -name = "ark-serialize-derive" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f153690697a2b91e5e1251ff98411ee5371500a111a0fd317a70e588eb300f9" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] - [[package]] name = "ark-std" version = "0.5.0" @@ -591,16 +539,6 @@ dependencies = [ "rayon", ] -[[package]] -name = "ark-std" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "367c9c827ed431bff6868b7aa926e05b16eb46603cc8b6e768e4a5553fa1d155" -dependencies = [ - "num-traits", - "rand 0.8.8", -] - [[package]] name = "arrayvec" version = "0.7.8" @@ -770,10 +708,10 @@ checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "common" version = "0.2.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ "allocative", - "ark-serialize 0.5.0", + "ark-serialize", "serde", "syn 3.0.5", ] @@ -952,9 +890,9 @@ checksum = "065945e9fff3c7dac5d6f72f8260eac82ad577e7c7009b6290847d1252d14d78" dependencies = [ "ark-bn254", "ark-ec", - "ark-ff 0.5.0", - "ark-serialize 0.5.0", - "ark-std 0.5.0", + "ark-ff", + "ark-serialize", + "ark-std", "bincode 1.3.3", "blake2 0.10.6", "digest 0.10.7", @@ -1119,11 +1057,24 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "r-efi", + "r-efi 5.3.0", "wasip2", "wasm-bindgen", ] +[[package]] +name = "getrandom" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi 6.0.0", + "wasm-bindgen", +] + [[package]] name = "gimli" version = "0.34.0" @@ -1200,15 +1151,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.15.0" @@ -1224,10 +1166,35 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" +[[package]] +name = "jolt-akita" +version = "0.1.0" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +dependencies = [ + "akita-algebra", + "akita-challenges", + "akita-config", + "akita-error", + "akita-params", + "akita-pcs", + "akita-planner", + "akita-schedules", + "akita-types", + "jolt-claims", + "jolt-crypto", + "jolt-field", + "jolt-openings", + "jolt-poly", + "jolt-transcript", + "rayon", + "serde", + "tracing", +] + [[package]] name = "jolt-blindfold" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ "jolt-claims", "jolt-crypto", @@ -1238,7 +1205,6 @@ dependencies = [ "jolt-transcript", "jolt-utils", "rand_core 0.6.4", - "rayon", "serde", "thiserror", ] @@ -1246,25 +1212,28 @@ dependencies = [ [[package]] name = "jolt-claims" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ - "blake2 0.11.0", "derive_more", "jolt-claims-derive", "jolt-field", "jolt-lookup-tables", "jolt-openings", "jolt-poly", + "jolt-r1cs", "jolt-riscv", + "jolt-transcript", "jolt-utils", + "rayon", "serde", + "sha3 0.12.0", "thiserror", ] [[package]] name = "jolt-claims-derive" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ "proc-macro2", "quote", @@ -1274,13 +1243,13 @@ dependencies = [ [[package]] name = "jolt-crypto" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ "ark-bn254", "ark-ec", - "ark-ff 0.5.0", - "ark-serialize 0.5.0", - "ark-std 0.5.0", + "ark-ff", + "ark-serialize", + "ark-std", "jolt-field", "jolt-poly", "jolt-transcript", @@ -1295,11 +1264,11 @@ dependencies = [ [[package]] name = "jolt-dory" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ "ark-bn254", "ark-ec", - "ark-serialize 0.5.0", + "ark-serialize", "dory-pcs", "jolt-crypto", "jolt-field", @@ -1315,28 +1284,32 @@ dependencies = [ [[package]] name = "jolt-field" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ "ark-bn254", - "ark-ff 0.5.0", - "ark-serialize 0.5.0", + "ark-ff", + "ark-serialize", "cc", "num-traits", "rand_core 0.6.4", "rayon", "serde", + "spongefish 0.8.0", "thiserror", ] [[package]] name = "jolt-host" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ "bincode 2.0.1", "common", + "jolt-field", + "jolt-platform", "jolt-program", "jolt-riscv", + "postcard", "serde", "tracer", "tracing", @@ -1345,7 +1318,7 @@ dependencies = [ [[package]] name = "jolt-kernels" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ "jolt-claims", "jolt-field", @@ -1369,7 +1342,7 @@ dependencies = [ [[package]] name = "jolt-kernels-derive" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ "proc-macro2", "quote", @@ -1379,7 +1352,7 @@ dependencies = [ [[package]] name = "jolt-lookup-tables" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ "jolt-field", "jolt-riscv", @@ -1390,7 +1363,7 @@ dependencies = [ [[package]] name = "jolt-openings" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ "jolt-crypto", "jolt-field", @@ -1408,9 +1381,9 @@ source = "git+https://github.com/a16z/arkworks-algebra?branch=dev%2Ftwist-shout# dependencies = [ "ark-bn254", "ark-ec", - "ark-ff 0.5.0", - "ark-serialize 0.5.0", - "ark-std 0.5.0", + "ark-ff", + "ark-serialize", + "ark-std", "arrayvec", "num-bigint 0.4.8", "num-integer", @@ -1422,7 +1395,7 @@ dependencies = [ [[package]] name = "jolt-platform" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ "getrandom 0.2.17", "getrandom 0.3.4", @@ -1432,7 +1405,7 @@ dependencies = [ [[package]] name = "jolt-poly" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ "jolt-field", "jolt-transcript", @@ -1448,12 +1421,13 @@ dependencies = [ [[package]] name = "jolt-program" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ - "ark-serialize 0.5.0", + "ark-serialize", "common", "jolt-riscv", "object", + "rayon", "serde", "thiserror", ] @@ -1461,13 +1435,15 @@ dependencies = [ [[package]] name = "jolt-prover" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ "common", + "jolt-akita", "jolt-claims", "jolt-crypto", "jolt-dory", "jolt-field", + "jolt-host", "jolt-kernels", "jolt-lookup-tables", "jolt-openings", @@ -1481,30 +1457,26 @@ dependencies = [ "rayon", "serde", "thiserror", + "tracer", "tracing", ] [[package]] name = "jolt-r1cs" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ - "jolt-claims", "jolt-field", - "jolt-poly", - "num-traits", - "rayon", "serde", "thiserror", - "tracing", ] [[package]] name = "jolt-riscv" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ - "ark-serialize 0.5.0", + "ark-serialize", "serde", "strum", "thiserror", @@ -1513,7 +1485,7 @@ dependencies = [ [[package]] name = "jolt-sdk" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ "bincode 2.0.1", "bytemuck", @@ -1541,7 +1513,7 @@ dependencies = [ [[package]] name = "jolt-sdk-macros" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ "common", "proc-macro2", @@ -1552,7 +1524,7 @@ dependencies = [ [[package]] name = "jolt-sumcheck" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ "jolt-crypto", "jolt-field", @@ -1568,21 +1540,21 @@ dependencies = [ [[package]] name = "jolt-transcript" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ "ark-bn254", - "ark-ff 0.5.0", - "blake2 0.11.0", - "digest 0.11.3", + "ark-ff", + "getrandom 0.4.3", "jolt-field", - "rand 0.8.8", - "spongefish 0.7.0", + "sha3 0.12.0", + "shake", + "spongefish 0.8.0", ] [[package]] name = "jolt-utils" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ "num-traits", "rayon", @@ -1591,11 +1563,10 @@ dependencies = [ [[package]] name = "jolt-verifier" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ - "ark-serialize 0.5.0", + "ark-serialize", "bincode 2.0.1", - "blake2 0.11.0", "common", "jolt-blindfold", "jolt-claims", @@ -1606,20 +1577,20 @@ dependencies = [ "jolt-openings", "jolt-poly", "jolt-program", - "jolt-r1cs", "jolt-riscv", "jolt-sumcheck", "jolt-transcript", "jolt-verifier-derive", "num-traits", "serde", + "sha3 0.12.0", "thiserror", ] [[package]] name = "jolt-verifier-derive" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ "proc-macro2", "quote", @@ -1629,7 +1600,7 @@ dependencies = [ [[package]] name = "jolt-witness" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ "common", "jolt-claims", @@ -1647,7 +1618,7 @@ dependencies = [ [[package]] name = "jolt-witness-derive" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ "proc-macro2", "quote", @@ -1696,6 +1667,12 @@ version = "0.2.189" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + [[package]] name = "link-section" version = "0.19.3" @@ -1858,46 +1835,17 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" -[[package]] -name = "p3-challenger" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dbe67345642fcf37c589a6d1af9372358481750553c1bfb48572abf0592aeb3" -dependencies = [ - "p3-field 0.5.4", - "p3-maybe-rayon 0.5.4", - "p3-monty-31 0.5.4", - "p3-symmetric 0.5.4", - "p3-util 0.5.4", - "tracing", -] - [[package]] name = "p3-challenger" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84d5d5e1ecf2c80b09b48ce870e8abd08b643454101c5dc9d0fd71bfbd78224d" dependencies = [ - "p3-field 0.6.3", - "p3-maybe-rayon 0.6.3", - "p3-monty-31 0.6.3", - "p3-symmetric 0.6.3", - "p3-util 0.6.3", - "tracing", -] - -[[package]] -name = "p3-dft" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83055e9db4ef464008ee8b0b9ef2b4b01a7aa1bdedf4d1c49c17e72ce247771b" -dependencies = [ - "itertools 0.14.0", - "p3-field 0.5.4", - "p3-matrix 0.5.4", - "p3-maybe-rayon 0.5.4", - "p3-util 0.5.4", - "spin 0.10.1", + "p3-field", + "p3-maybe-rayon", + "p3-monty-31", + "p3-symmetric", + "p3-util", "tracing", ] @@ -1908,30 +1856,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4321a952da2721ecd85ca593ea189798dfb4e439a2cc1378ce1442091880f173" dependencies = [ "itertools 0.15.0", - "p3-field 0.6.3", - "p3-matrix 0.6.3", - "p3-maybe-rayon 0.6.3", - "p3-util 0.6.3", + "p3-field", + "p3-matrix", + "p3-maybe-rayon", + "p3-util", "spin 0.12.3", "tracing", ] -[[package]] -name = "p3-field" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45391a9c842ff37f9a6164957c6b8ec40268ff10f9607b35e4d6192ed1ab4045" -dependencies = [ - "itertools 0.14.0", - "num-bigint 0.4.8", - "p3-maybe-rayon 0.5.4", - "p3-util 0.5.4", - "paste", - "rand 0.10.2", - "serde", - "tracing", -] - [[package]] name = "p3-field" version = "0.6.3" @@ -1940,61 +1872,30 @@ checksum = "53db75d38e04fc255826f388eca9d05976733dc9754aa3db411bc9ea1a37c1a0" dependencies = [ "itertools 0.15.0", "num-bigint 0.5.1", - "p3-maybe-rayon 0.6.3", - "p3-util 0.6.3", + "p3-maybe-rayon", + "p3-util", "paste", "rand 0.10.2", "serde", "tracing", ] -[[package]] -name = "p3-koala-bear" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46cc96aeb0acd85147e00ecb097a40ab050afb894b60808192ac000d7f09ce70" -dependencies = [ - "p3-challenger 0.5.4", - "p3-field 0.5.4", - "p3-mds 0.5.4", - "p3-monty-31 0.5.4", - "p3-poseidon1 0.5.4", - "p3-poseidon2 0.5.4", - "p3-symmetric 0.5.4", - "rand 0.10.2", -] - [[package]] name = "p3-koala-bear" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70cbc82137c157673e2d33d95f936a94ce237a790d46e0a2b3165dccfc385dd6" dependencies = [ - "p3-challenger 0.6.3", - "p3-field 0.6.3", - "p3-mds 0.6.3", - "p3-monty-31 0.6.3", - "p3-poseidon1 0.6.3", - "p3-poseidon2 0.6.3", - "p3-symmetric 0.6.3", + "p3-challenger", + "p3-field", + "p3-mds", + "p3-monty-31", + "p3-poseidon1", + "p3-poseidon2", + "p3-symmetric", "rand 0.10.2", ] -[[package]] -name = "p3-matrix" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64eb448f47bf7245ca281e3c42fb2e33d3fe5c86d283c0ef91e2fb8245b2d0e9" -dependencies = [ - "itertools 0.14.0", - "p3-field 0.5.4", - "p3-maybe-rayon 0.5.4", - "p3-util 0.5.4", - "rand 0.10.2", - "serde", - "tracing", -] - [[package]] name = "p3-matrix" version = "0.6.3" @@ -2002,74 +1903,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "473eb920c446a6f4536e0d3528fbdca2a23c0e24e1d0d7767452e6d385dd335c" dependencies = [ "itertools 0.15.0", - "p3-field 0.6.3", - "p3-maybe-rayon 0.6.3", - "p3-util 0.6.3", + "p3-field", + "p3-maybe-rayon", + "p3-util", "rand 0.10.2", "serde", "tracing", ] -[[package]] -name = "p3-maybe-rayon" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d1ffb2d24a932d4fa5258f3288130973175f1982c7606f9f7df5270c895531c" - [[package]] name = "p3-maybe-rayon" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6fddfd435f96394769414cf5590b77058aa506659bf20d6592e9d1989e04440" -[[package]] -name = "p3-mds" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4139bf9ccbc3e88119a2d2e9f698a735a3e33a69a6735c3edb2ce333de972e70" -dependencies = [ - "p3-dft 0.5.4", - "p3-field 0.5.4", - "p3-symmetric 0.5.4", - "p3-util 0.5.4", - "rand 0.10.2", -] - [[package]] name = "p3-mds" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "551ba0ab2cccd89f85a99450224898aff224e323bbf61f777ba6344f0896ef10" dependencies = [ - "p3-dft 0.6.3", - "p3-field 0.6.3", - "p3-symmetric 0.6.3", - "p3-util 0.6.3", - "rand 0.10.2", -] - -[[package]] -name = "p3-monty-31" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6d1aa65b2f49d58dd097a99dbd3ebcb0600bbac45d86339a382839933780689" -dependencies = [ - "itertools 0.14.0", - "num-bigint 0.4.8", - "p3-dft 0.5.4", - "p3-field 0.5.4", - "p3-matrix 0.5.4", - "p3-maybe-rayon 0.5.4", - "p3-mds 0.5.4", - "p3-poseidon1 0.5.4", - "p3-poseidon2 0.5.4", - "p3-symmetric 0.5.4", - "p3-util 0.5.4", - "paste", + "p3-dft", + "p3-field", + "p3-symmetric", + "p3-util", "rand 0.10.2", - "serde", - "spin 0.10.1", - "tracing", ] [[package]] @@ -2080,15 +1938,15 @@ checksum = "871f635f7340cd0868b17e43e0c98fefdafdaed90469d0725caf6d8372a2a47c" dependencies = [ "itertools 0.15.0", "num-bigint 0.5.1", - "p3-dft 0.6.3", - "p3-field 0.6.3", - "p3-matrix 0.6.3", - "p3-maybe-rayon 0.6.3", - "p3-mds 0.6.3", - "p3-poseidon1 0.6.3", - "p3-poseidon2 0.6.3", - "p3-symmetric 0.6.3", - "p3-util 0.6.3", + "p3-dft", + "p3-field", + "p3-matrix", + "p3-maybe-rayon", + "p3-mds", + "p3-poseidon1", + "p3-poseidon2", + "p3-symmetric", + "p3-util", "paste", "rand 0.10.2", "serde", @@ -2096,39 +1954,15 @@ dependencies = [ "tracing", ] -[[package]] -name = "p3-poseidon1" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c57b5971577e54cb6aa969d75a92c0b7f5d1417722562bf6ffe687f05a003ef4" -dependencies = [ - "p3-field 0.5.4", - "p3-symmetric 0.5.4", - "rand 0.10.2", -] - [[package]] name = "p3-poseidon1" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d0d304e9a1f29c0d66534aa84e69528e2118351fdce08dcf5898af4e0fecc32" dependencies = [ - "p3-field 0.6.3", - "p3-mds 0.6.3", - "p3-symmetric 0.6.3", - "rand 0.10.2", -] - -[[package]] -name = "p3-poseidon2" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c44d9bcb4972381b7ad44bb7f675233fce9ff072777dd3c027f912cf04bed8da" -dependencies = [ - "p3-field 0.5.4", - "p3-mds 0.5.4", - "p3-symmetric 0.5.4", - "p3-util 0.5.4", + "p3-field", + "p3-mds", + "p3-symmetric", "rand 0.10.2", ] @@ -2138,25 +1972,13 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43eb8a73a26d14becaed1c67c3e8a047e4311d7909b402383c82ca9643ba17c6" dependencies = [ - "p3-field 0.6.3", - "p3-mds 0.6.3", - "p3-symmetric 0.6.3", - "p3-util 0.6.3", + "p3-field", + "p3-mds", + "p3-symmetric", + "p3-util", "rand 0.10.2", ] -[[package]] -name = "p3-symmetric" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af42757f727b25aca1eac49f2562ad2131c99d259d7143e89075e7b7be6b7952" -dependencies = [ - "itertools 0.14.0", - "p3-field 0.5.4", - "p3-util 0.5.4", - "serde", -] - [[package]] name = "p3-symmetric" version = "0.6.3" @@ -2164,19 +1986,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2015ea80cad969b6aabf27a04884286fe1354393b166d968ee0d80a95126b2a4" dependencies = [ "itertools 0.15.0", - "p3-field 0.6.3", - "p3-util 0.6.3", - "serde", -] - -[[package]] -name = "p3-util" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d67ad92cd9397a7377acd7116d0920b603ba7bec9a3528ab56fe1224586f44c6" -dependencies = [ + "p3-field", + "p3-util", "serde", - "transpose", ] [[package]] @@ -2251,6 +2063,12 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + [[package]] name = "rand" version = "0.8.8" @@ -2538,15 +2356,6 @@ version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3763264f6b73151db08c50ff20d7d8a0b8796e021cdea7ceedad07b80155fa0e" -[[package]] -name = "spin" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "023a211cb3138dbc438680b32560ad89f699977624c9f8dbb95a47d5b4c07dd3" -dependencies = [ - "lock_api", -] - [[package]] name = "spin" version = "0.12.3" @@ -2573,14 +2382,13 @@ checksum = "3a0219bd7d979d58245a4f41f695e1ac9f8befdffadd7f61f1bae9e39abc6620" [[package]] name = "spongefish" -version = "0.7.0" -source = "git+https://github.com/arkworks-rs/spongefish?rev=d2d190b1329d35ac9577438d05aed4f17a57b9f9#d2d190b1329d35ac9577438d05aed4f17a57b9f9" +version = "0.7.4" +source = "git+https://github.com/arkworks-rs/spongefish?rev=ef9741346a150039427d9e0c02d6b2d73e93ec81#ef9741346a150039427d9e0c02d6b2d73e93ec81" dependencies = [ - "ark-ff 0.6.0", - "ark-serialize 0.6.0", "blake2 0.11.0", "digest 0.11.3", - "p3-koala-bear 0.5.4", + "keccak 0.2.2", + "p3-koala-bear", "rand 0.8.8", "sha2", "sha3 0.11.0", @@ -2588,16 +2396,14 @@ dependencies = [ [[package]] name = "spongefish" -version = "0.7.4" -source = "git+https://github.com/arkworks-rs/spongefish?rev=ef9741346a150039427d9e0c02d6b2d73e93ec81#ef9741346a150039427d9e0c02d6b2d73e93ec81" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62560b5029264a655fc461a0ecadc4d24862799190897d3225b3272b7a3f13b7" dependencies = [ - "blake2 0.11.0", "digest 0.11.3", + "getrandom 0.4.3", "keccak 0.2.2", - "p3-koala-bear 0.6.3", - "rand 0.8.8", - "sha2", - "sha3 0.11.0", + "zeroize", ] [[package]] @@ -2606,12 +2412,6 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" -[[package]] -name = "strength_reduce" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" - [[package]] name = "strsim" version = "0.11.1" @@ -2699,10 +2499,10 @@ dependencies = [ [[package]] name = "tracer" version = "0.2.0" -source = "git+https://github.com/a16z/jolt?rev=1618f4b6dc97effcec3568ca7cf2b7420ac9e75f#1618f4b6dc97effcec3568ca7cf2b7420ac9e75f" +source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" dependencies = [ "addr2line", - "ark-serialize 0.5.0", + "ark-serialize", "clap", "common", "derive_more", @@ -2787,16 +2587,6 @@ dependencies = [ "tracing-log", ] -[[package]] -name = "transpose" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad61aed86bc3faea4300c7aee358b4c6d0c8d6ccc36524c96e4c92ccf26e77e" -dependencies = [ - "num-integer", - "strength_reduce", -] - [[package]] name = "twox-hash" version = "2.1.4" From 6c25733560c72aca671a2a079991c8643310e807 Mon Sep 17 00:00:00 2001 From: acentelles Date: Fri, 30 Oct 2026 06:11:35 +0000 Subject: [PATCH 15/17] build: pin Jolt to a16z/jolt main 4e55c9a5 Update the manifest revisions and the three lockfile source IDs from e1d8e02b5 to 4e55c9a5. Dependency manifests and Jolt Cargo.lock are unchanged across this move; resolution and compilation are verified on the Linux gate host. --- Cargo.lock | 6 +-- crates/akita-algebra/Cargo.toml | 4 +- crates/akita-challenges/Cargo.toml | 2 +- crates/akita-config/Cargo.toml | 2 +- crates/akita-cpu-backend/Cargo.toml | 4 +- crates/akita-params/Cargo.toml | 2 +- crates/akita-pcs/Cargo.toml | 4 +- crates/akita-prover/Cargo.toml | 4 +- crates/akita-serialization/Cargo.toml | 4 +- crates/akita-setup/Cargo.toml | 2 +- crates/akita-sumcheck/Cargo.toml | 4 +- crates/akita-transcript/Cargo.toml | 2 +- crates/akita-types/Cargo.toml | 4 +- crates/akita-verifier/Cargo.toml | 4 +- fuzz/Cargo.lock | 6 +-- fuzz/Cargo.toml | 4 +- profile/akita-recursion/Cargo.lock | 58 ++++++++++----------- profile/akita-recursion/artifact/Cargo.toml | 2 +- profile/akita-recursion/glue/Cargo.toml | 2 +- profile/akita-recursion/guest/Cargo.toml | 4 +- profile/akita-recursion/host/Cargo.toml | 4 +- 21 files changed, 64 insertions(+), 64 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cd5135b4f..37190727e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -929,7 +929,7 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jolt-field" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "cc", "num-traits", @@ -942,7 +942,7 @@ dependencies = [ [[package]] name = "jolt-poly" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "jolt-field", "jolt-utils", @@ -956,7 +956,7 @@ dependencies = [ [[package]] name = "jolt-utils" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "num-traits", ] diff --git a/crates/akita-algebra/Cargo.toml b/crates/akita-algebra/Cargo.toml index 38e33523f..4b25d58a7 100644 --- a/crates/akita-algebra/Cargo.toml +++ b/crates/akita-algebra/Cargo.toml @@ -10,11 +10,11 @@ readme = "../../README.md" [dependencies] akita-error = { version = "0.1.0", path = "../akita-error" } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3", default-features = false, features = [ "asm", "solinas", ] } -jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false } +jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3", default-features = false } akita-serialization = { version = "0.1.0", path = "../akita-serialization" } rand_core = { version = "0.6", features = ["getrandom"] } rayon = { version = "1.10", optional = true } diff --git a/crates/akita-challenges/Cargo.toml b/crates/akita-challenges/Cargo.toml index 45b174994..a4d1676df 100644 --- a/crates/akita-challenges/Cargo.toml +++ b/crates/akita-challenges/Cargo.toml @@ -11,7 +11,7 @@ readme = "../../README.md" [dependencies] akita-error = { version = "0.1.0", path = "../akita-error" } serde = { version = "1", features = ["derive"] } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3", default-features = false, features = [ "asm", "solinas", ] } diff --git a/crates/akita-config/Cargo.toml b/crates/akita-config/Cargo.toml index 2aa3f1c7e..d8c9bf5db 100644 --- a/crates/akita-config/Cargo.toml +++ b/crates/akita-config/Cargo.toml @@ -30,7 +30,7 @@ test-support = [] [dependencies] akita-error = { version = "0.1.0", path = "../akita-error" } akita-challenges = { version = "0.1.0", path = "../akita-challenges", default-features = false } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3", default-features = false, features = [ "asm", "solinas", ] } diff --git a/crates/akita-cpu-backend/Cargo.toml b/crates/akita-cpu-backend/Cargo.toml index a5885852b..8a851d1ab 100644 --- a/crates/akita-cpu-backend/Cargo.toml +++ b/crates/akita-cpu-backend/Cargo.toml @@ -14,11 +14,11 @@ akita-error = { version = "0.1.0", path = "../akita-error" } akita-algebra = { version = "0.1.0", path = "../akita-algebra" } akita-challenges = { version = "0.1.0", path = "../akita-challenges", default-features = false } akita-config = { version = "0.1.0", path = "../akita-config", default-features = false } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3", default-features = false, features = [ "asm", "solinas", ] } -jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false } +jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3", default-features = false } akita-serialization = { version = "0.1.0", path = "../akita-serialization" } akita-sumcheck = { version = "0.1.0", path = "../akita-sumcheck", default-features = false } akita-transcript = { version = "0.1.0", path = "../akita-transcript", default-features = false } diff --git a/crates/akita-params/Cargo.toml b/crates/akita-params/Cargo.toml index 4a1f64333..27972b518 100644 --- a/crates/akita-params/Cargo.toml +++ b/crates/akita-params/Cargo.toml @@ -12,7 +12,7 @@ readme = "../../README.md" akita-error = { version = "0.1.0", path = "../akita-error" } akita-algebra = { version = "0.1.0", path = "../akita-algebra" } akita-challenges = { version = "0.1.0", path = "../akita-challenges", default-features = false } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3", default-features = false, features = [ "asm", "solinas", ] } diff --git a/crates/akita-pcs/Cargo.toml b/crates/akita-pcs/Cargo.toml index 1d5af57ed..47c05e682 100644 --- a/crates/akita-pcs/Cargo.toml +++ b/crates/akita-pcs/Cargo.toml @@ -106,7 +106,7 @@ akita-algebra = { version = "0.1.0", path = "../akita-algebra" } akita-challenges = { version = "0.1.0", path = "../akita-challenges", default-features = false } akita-config = { version = "0.1.0", path = "../akita-config", default-features = false } akita-cpu-backend = { version = "0.1.0", path = "../akita-cpu-backend", default-features = false } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3", default-features = false, features = [ "asm", "solinas", ] } @@ -121,7 +121,7 @@ tracing = "0.1" rayon = { version = "1.10", optional = true } [dev-dependencies] -jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false } +jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3", default-features = false } # Test-only: pull in `akita-config`'s workspace artifact loader and ring-plan # seed. Schedule rows remain checked-in external artifacts loaded at runtime. akita-config = { version = "0.1.0", path = "../akita-config", default-features = false, features = [ diff --git a/crates/akita-prover/Cargo.toml b/crates/akita-prover/Cargo.toml index ab66a0bf8..1c1df5ec2 100644 --- a/crates/akita-prover/Cargo.toml +++ b/crates/akita-prover/Cargo.toml @@ -13,11 +13,11 @@ akita-error = { version = "0.1.0", path = "../akita-error" } akita-algebra = { version = "0.1.0", path = "../akita-algebra" } akita-challenges = { version = "0.1.0", path = "../akita-challenges", default-features = false } akita-config = { version = "0.1.0", path = "../akita-config", default-features = false } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3", default-features = false, features = [ "asm", "solinas", ] } -jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false } +jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3", default-features = false } akita-serialization = { version = "0.1.0", path = "../akita-serialization" } akita-sumcheck = { version = "0.1.0", path = "../akita-sumcheck", default-features = false } akita-transcript = { version = "0.1.0", path = "../akita-transcript", default-features = false } diff --git a/crates/akita-serialization/Cargo.toml b/crates/akita-serialization/Cargo.toml index 64eab1d97..9f5d8c4bf 100644 --- a/crates/akita-serialization/Cargo.toml +++ b/crates/akita-serialization/Cargo.toml @@ -9,11 +9,11 @@ repository = "https://github.com/LayerZero-Labs/akita" readme = "../../README.md" [dependencies] -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3", default-features = false, features = [ "asm", "solinas", ] } -jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false } +jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3", default-features = false } thiserror = "2.0" [lints] diff --git a/crates/akita-setup/Cargo.toml b/crates/akita-setup/Cargo.toml index 03fe99be7..22c78a17b 100644 --- a/crates/akita-setup/Cargo.toml +++ b/crates/akita-setup/Cargo.toml @@ -29,7 +29,7 @@ disk-persistence = ["akita-cpu-backend/disk-persistence"] akita-error = { version = "0.1.0", path = "../akita-error" } akita-config = { version = "0.1.0", path = "../akita-config", default-features = false } akita-cpu-backend = { version = "0.1.0", path = "../akita-cpu-backend", default-features = false } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3", default-features = false, features = [ "asm", "solinas", ] } diff --git a/crates/akita-sumcheck/Cargo.toml b/crates/akita-sumcheck/Cargo.toml index 3c4746187..687a7a63c 100644 --- a/crates/akita-sumcheck/Cargo.toml +++ b/crates/akita-sumcheck/Cargo.toml @@ -11,11 +11,11 @@ readme = "../../README.md" [dependencies] akita-error = { version = "0.1.0", path = "../akita-error" } akita-algebra = { version = "0.1.0", path = "../akita-algebra" } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3", default-features = false, features = [ "asm", "solinas", ] } -jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false } +jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3", default-features = false } akita-serialization = { version = "0.1.0", path = "../akita-serialization" } akita-transcript = { version = "0.1.0", path = "../akita-transcript", default-features = false } diff --git a/crates/akita-transcript/Cargo.toml b/crates/akita-transcript/Cargo.toml index 7caf60dda..62140c6ef 100644 --- a/crates/akita-transcript/Cargo.toml +++ b/crates/akita-transcript/Cargo.toml @@ -10,7 +10,7 @@ readme = "../../README.md" [dependencies] akita-error = { version = "0.1.0", path = "../akita-error" } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3", default-features = false, features = [ "asm", "solinas", ] } diff --git a/crates/akita-types/Cargo.toml b/crates/akita-types/Cargo.toml index 94763bc97..55945079f 100644 --- a/crates/akita-types/Cargo.toml +++ b/crates/akita-types/Cargo.toml @@ -13,11 +13,11 @@ akita-params = { version = "0.1.0", path = "../akita-params", default-features = akita-error = { version = "0.1.0", path = "../akita-error" } akita-algebra = { version = "0.1.0", path = "../akita-algebra" } akita-challenges = { version = "0.1.0", path = "../akita-challenges", default-features = false } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3", default-features = false, features = [ "asm", "solinas", ] } -jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false } +jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3", default-features = false } akita-serialization = { version = "0.1.0", path = "../akita-serialization" } akita-sumcheck = { version = "0.1.0", path = "../akita-sumcheck", default-features = false } akita-transcript = { version = "0.1.0", path = "../akita-transcript", default-features = false } diff --git a/crates/akita-verifier/Cargo.toml b/crates/akita-verifier/Cargo.toml index 72cdf5bcc..d7bcf4e09 100644 --- a/crates/akita-verifier/Cargo.toml +++ b/crates/akita-verifier/Cargo.toml @@ -18,11 +18,11 @@ akita-error = { version = "0.1.0", path = "../akita-error" } akita-algebra = { version = "0.1.0", path = "../akita-algebra" } akita-challenges = { version = "0.1.0", path = "../akita-challenges", default-features = false } akita-config = { version = "0.1.0", path = "../akita-config", default-features = false } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3", default-features = false, features = [ "asm", "solinas", ] } -jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false } +jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3", default-features = false } akita-serialization = { version = "0.1.0", path = "../akita-serialization" } akita-sumcheck = { version = "0.1.0", path = "../akita-sumcheck", default-features = false } akita-transcript = { version = "0.1.0", path = "../akita-transcript", default-features = false } diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index 5a3517b62..e62bc4d39 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -713,7 +713,7 @@ dependencies = [ [[package]] name = "jolt-field" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "cc", "num-traits", @@ -726,7 +726,7 @@ dependencies = [ [[package]] name = "jolt-poly" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "jolt-field", "jolt-utils", @@ -740,7 +740,7 @@ dependencies = [ [[package]] name = "jolt-utils" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "num-traits", ] diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 4b27b8e6a..c9b74fef8 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -73,11 +73,11 @@ akita-types = { path = "../crates/akita-types", default-features = false, featur akita-verifier = { path = "../crates/akita-verifier", default-features = false, features = [ "transcript-blake2b", ] } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3", default-features = false, features = [ "asm", "solinas", ] } -jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false } +jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3", default-features = false } libfuzzer-sys = "0.4.12" num-bigint = "0.4" rayon = "1.10" diff --git a/profile/akita-recursion/Cargo.lock b/profile/akita-recursion/Cargo.lock index 2fb7be221..93b772317 100644 --- a/profile/akita-recursion/Cargo.lock +++ b/profile/akita-recursion/Cargo.lock @@ -708,7 +708,7 @@ checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "common" version = "0.2.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "allocative", "ark-serialize", @@ -1169,7 +1169,7 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jolt-akita" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "akita-algebra", "akita-challenges", @@ -1194,7 +1194,7 @@ dependencies = [ [[package]] name = "jolt-blindfold" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "jolt-claims", "jolt-crypto", @@ -1212,7 +1212,7 @@ dependencies = [ [[package]] name = "jolt-claims" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "derive_more", "jolt-claims-derive", @@ -1233,7 +1233,7 @@ dependencies = [ [[package]] name = "jolt-claims-derive" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "proc-macro2", "quote", @@ -1243,7 +1243,7 @@ dependencies = [ [[package]] name = "jolt-crypto" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "ark-bn254", "ark-ec", @@ -1264,7 +1264,7 @@ dependencies = [ [[package]] name = "jolt-dory" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "ark-bn254", "ark-ec", @@ -1284,7 +1284,7 @@ dependencies = [ [[package]] name = "jolt-field" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "ark-bn254", "ark-ff", @@ -1301,7 +1301,7 @@ dependencies = [ [[package]] name = "jolt-host" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "bincode 2.0.1", "common", @@ -1318,7 +1318,7 @@ dependencies = [ [[package]] name = "jolt-kernels" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "jolt-claims", "jolt-field", @@ -1342,7 +1342,7 @@ dependencies = [ [[package]] name = "jolt-kernels-derive" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "proc-macro2", "quote", @@ -1352,7 +1352,7 @@ dependencies = [ [[package]] name = "jolt-lookup-tables" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "jolt-field", "jolt-riscv", @@ -1363,7 +1363,7 @@ dependencies = [ [[package]] name = "jolt-openings" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "jolt-crypto", "jolt-field", @@ -1395,7 +1395,7 @@ dependencies = [ [[package]] name = "jolt-platform" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "getrandom 0.2.17", "getrandom 0.3.4", @@ -1405,7 +1405,7 @@ dependencies = [ [[package]] name = "jolt-poly" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "jolt-field", "jolt-transcript", @@ -1421,7 +1421,7 @@ dependencies = [ [[package]] name = "jolt-program" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "ark-serialize", "common", @@ -1435,7 +1435,7 @@ dependencies = [ [[package]] name = "jolt-prover" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "common", "jolt-akita", @@ -1464,7 +1464,7 @@ dependencies = [ [[package]] name = "jolt-r1cs" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "jolt-field", "serde", @@ -1474,7 +1474,7 @@ dependencies = [ [[package]] name = "jolt-riscv" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "ark-serialize", "serde", @@ -1485,7 +1485,7 @@ dependencies = [ [[package]] name = "jolt-sdk" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "bincode 2.0.1", "bytemuck", @@ -1513,7 +1513,7 @@ dependencies = [ [[package]] name = "jolt-sdk-macros" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "common", "proc-macro2", @@ -1524,7 +1524,7 @@ dependencies = [ [[package]] name = "jolt-sumcheck" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "jolt-crypto", "jolt-field", @@ -1540,7 +1540,7 @@ dependencies = [ [[package]] name = "jolt-transcript" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "ark-bn254", "ark-ff", @@ -1554,7 +1554,7 @@ dependencies = [ [[package]] name = "jolt-utils" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "num-traits", "rayon", @@ -1563,7 +1563,7 @@ dependencies = [ [[package]] name = "jolt-verifier" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "ark-serialize", "bincode 2.0.1", @@ -1590,7 +1590,7 @@ dependencies = [ [[package]] name = "jolt-verifier-derive" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "proc-macro2", "quote", @@ -1600,7 +1600,7 @@ dependencies = [ [[package]] name = "jolt-witness" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "common", "jolt-claims", @@ -1618,7 +1618,7 @@ dependencies = [ [[package]] name = "jolt-witness-derive" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "proc-macro2", "quote", @@ -2499,7 +2499,7 @@ dependencies = [ [[package]] name = "tracer" version = "0.2.0" -source = "git+https://github.com/a16z/jolt?rev=e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401#e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401" +source = "git+https://github.com/a16z/jolt?rev=4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3#4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3" dependencies = [ "addr2line", "ark-serialize", diff --git a/profile/akita-recursion/artifact/Cargo.toml b/profile/akita-recursion/artifact/Cargo.toml index 8dbb0fb1c..8bc1a31f0 100644 --- a/profile/akita-recursion/artifact/Cargo.toml +++ b/profile/akita-recursion/artifact/Cargo.toml @@ -16,7 +16,7 @@ akita-recursion-glue = { path = "../glue" } akita-serialization = { path = "../../../crates/akita-serialization" } akita-config = { path = "../../../crates/akita-config", default-features = false, features = [ ] } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3", default-features = false, features = [ "asm", "solinas", ] } diff --git a/profile/akita-recursion/glue/Cargo.toml b/profile/akita-recursion/glue/Cargo.toml index d6f7a801a..70d0f280c 100644 --- a/profile/akita-recursion/glue/Cargo.toml +++ b/profile/akita-recursion/glue/Cargo.toml @@ -27,7 +27,7 @@ trusted-benchmark-artifact = [] akita-error = { version = "0.1.0", path = "../../../crates/akita-error" } akita-algebra = { version = "0.1.0", path = "../../../crates/akita-algebra" } akita-config = { version = "0.1.0", path = "../../../crates/akita-config", default-features = false } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3", default-features = false, features = [ "asm", "solinas", ] } diff --git a/profile/akita-recursion/guest/Cargo.toml b/profile/akita-recursion/guest/Cargo.toml index 3ecd9ea77..f732f29e7 100644 --- a/profile/akita-recursion/guest/Cargo.toml +++ b/profile/akita-recursion/guest/Cargo.toml @@ -34,11 +34,11 @@ trusted-benchmark-artifact = ["akita-recursion-glue/trusted-benchmark-artifact"] akita-error = { path = "../../../crates/akita-error" } # Aliased as `jolt` so `#[jolt::provable]` and `jolt::start_cycle_tracking` # resolve the same way as in the upstream Jolt examples. -jolt = { package = "jolt-sdk", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false } +jolt = { package = "jolt-sdk", git = "https://github.com/a16z/jolt", rev = "4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3", default-features = false } akita-recursion-glue = { path = "../glue" } akita-config = { path = "../../../crates/akita-config", default-features = false, features = [ ] } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3", default-features = false, features = [ "asm", "solinas", ] } diff --git a/profile/akita-recursion/host/Cargo.toml b/profile/akita-recursion/host/Cargo.toml index 99a2120a0..be049f301 100644 --- a/profile/akita-recursion/host/Cargo.toml +++ b/profile/akita-recursion/host/Cargo.toml @@ -14,7 +14,7 @@ name = "akita-recursion-host" path = "src/main.rs" [dependencies] -jolt-sdk = { git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", default-features = false, features = [ +jolt-sdk = { git = "https://github.com/a16z/jolt", rev = "4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3", default-features = false, features = [ "host", ] } # We pin `jolt-sdk-macros` with `guest-std` directly so that the @@ -22,7 +22,7 @@ jolt-sdk = { git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf9 # its own `cfg(feature = "guest-std")` at host compile time). Going through # `jolt-sdk/guest-std` would also pull `zeroos-runtime-musl` in for the # host build, which fails to link on macOS / non-musl platforms. -jolt-sdk-macros = { git = "https://github.com/a16z/jolt", rev = "e1d8e02b502e0f3462adf93e5ecc1f7c52b3f401", features = [ +jolt-sdk-macros = { git = "https://github.com/a16z/jolt", rev = "4e55c9a5f7033d1b88254df051e0bd8c4a4b0ec3", features = [ "guest-std", ] } guest = { package = "akita-recursion-guest", path = "../guest", features = [ From abd713126af0df3d6ac0bc43ae2967ada1e4c34c Mon Sep 17 00:00:00 2001 From: acentelles Date: Fri, 30 Oct 2026 21:40:30 +0000 Subject: [PATCH 16/17] Pin Jolt to main --- crates/akita-algebra/Cargo.toml | 6 +++--- crates/akita-challenges/Cargo.toml | 4 ++-- crates/akita-config/Cargo.toml | 2 +- crates/akita-cpu-backend/Cargo.toml | 4 ++-- crates/akita-params/Cargo.toml | 4 ++-- crates/akita-pcs/Cargo.toml | 4 ++-- crates/akita-prover/Cargo.toml | 4 ++-- crates/akita-serialization/Cargo.toml | 4 ++-- crates/akita-setup/Cargo.toml | 2 +- crates/akita-sumcheck/Cargo.toml | 4 ++-- crates/akita-transcript/Cargo.toml | 4 ++-- crates/akita-types/Cargo.toml | 4 ++-- crates/akita-verifier/Cargo.toml | 4 ++-- fuzz/Cargo.toml | 4 ++-- profile/akita-recursion/artifact/Cargo.toml | 2 +- profile/akita-recursion/glue/Cargo.toml | 2 +- profile/akita-recursion/guest/Cargo.toml | 4 ++-- profile/akita-recursion/host/Cargo.toml | 4 ++-- .../akita-recursion/inline-parity/guest/Cargo.toml | 4 ++-- .../akita-recursion/inline-parity/host/Cargo.toml | 12 ++++++------ 20 files changed, 41 insertions(+), 41 deletions(-) diff --git a/crates/akita-algebra/Cargo.toml b/crates/akita-algebra/Cargo.toml index 9be452f38..bcf8d0eb9 100644 --- a/crates/akita-algebra/Cargo.toml +++ b/crates/akita-algebra/Cargo.toml @@ -9,13 +9,13 @@ repository = "https://github.com/LayerZero-Labs/akita" readme = "../../README.md" [dependencies] -jolt-inlines-ntt = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false, optional = true } +jolt-inlines-ntt = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false, optional = true } akita-error = { version = "0.1.0", path = "../akita-error" } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false, features = [ "asm", "solinas", ] } -jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false } +jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false } akita-serialization = { version = "0.1.0", path = "../akita-serialization" } rand_core = { version = "0.6", features = ["getrandom"] } rayon = { version = "1.10", optional = true } diff --git a/crates/akita-challenges/Cargo.toml b/crates/akita-challenges/Cargo.toml index 17ae912d1..d5b9a4ed4 100644 --- a/crates/akita-challenges/Cargo.toml +++ b/crates/akita-challenges/Cargo.toml @@ -11,13 +11,13 @@ readme = "../../README.md" [dependencies] akita-error = { version = "0.1.0", path = "../akita-error" } serde = { version = "1", features = ["derive"] } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false, features = [ "asm", "solinas", ] } akita-transcript = { version = "0.1.0", path = "../akita-transcript", default-features = false } keccak = { version = "0.1.6", features = ["asm"] } -jolt-inlines-keccak256 = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false, optional = true } +jolt-inlines-keccak256 = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false, optional = true } smallvec = { version = "1.15.2", features = ["const_generics"] } [dev-dependencies] diff --git a/crates/akita-config/Cargo.toml b/crates/akita-config/Cargo.toml index d8bdd524c..519eb397c 100644 --- a/crates/akita-config/Cargo.toml +++ b/crates/akita-config/Cargo.toml @@ -30,7 +30,7 @@ test-support = [] [dependencies] akita-error = { version = "0.1.0", path = "../akita-error" } akita-challenges = { version = "0.1.0", path = "../akita-challenges", default-features = false } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false, features = [ "asm", "solinas", ] } diff --git a/crates/akita-cpu-backend/Cargo.toml b/crates/akita-cpu-backend/Cargo.toml index 76c73b0d4..68f6eff70 100644 --- a/crates/akita-cpu-backend/Cargo.toml +++ b/crates/akita-cpu-backend/Cargo.toml @@ -14,11 +14,11 @@ akita-error = { version = "0.1.0", path = "../akita-error" } akita-algebra = { version = "0.1.0", path = "../akita-algebra" } akita-challenges = { version = "0.1.0", path = "../akita-challenges", default-features = false } akita-config = { version = "0.1.0", path = "../akita-config", default-features = false } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false, features = [ "asm", "solinas", ] } -jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false } +jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false } akita-serialization = { version = "0.1.0", path = "../akita-serialization" } akita-sumcheck = { version = "0.1.0", path = "../akita-sumcheck", default-features = false } akita-transcript = { version = "0.1.0", path = "../akita-transcript", default-features = false } diff --git a/crates/akita-params/Cargo.toml b/crates/akita-params/Cargo.toml index f72bacfef..ccdd5ea06 100644 --- a/crates/akita-params/Cargo.toml +++ b/crates/akita-params/Cargo.toml @@ -12,11 +12,11 @@ readme = "../../README.md" akita-error = { version = "0.1.0", path = "../akita-error" } akita-algebra = { version = "0.1.0", path = "../akita-algebra" } akita-challenges = { version = "0.1.0", path = "../akita-challenges", default-features = false } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false, features = [ "asm", "solinas", ] } -jolt-inlines-blake2 = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false, optional = true } +jolt-inlines-blake2 = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false, optional = true } akita-serialization = { version = "0.1.0", path = "../akita-serialization" } akita-sumcheck = { version = "0.1.0", path = "../akita-sumcheck", default-features = false } akita-transcript = { version = "0.1.0", path = "../akita-transcript", default-features = false } diff --git a/crates/akita-pcs/Cargo.toml b/crates/akita-pcs/Cargo.toml index ed2555ec6..2158a3c18 100644 --- a/crates/akita-pcs/Cargo.toml +++ b/crates/akita-pcs/Cargo.toml @@ -114,7 +114,7 @@ akita-algebra = { version = "0.1.0", path = "../akita-algebra" } akita-challenges = { version = "0.1.0", path = "../akita-challenges", default-features = false } akita-config = { version = "0.1.0", path = "../akita-config", default-features = false } akita-cpu-backend = { version = "0.1.0", path = "../akita-cpu-backend", default-features = false } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false, features = [ "asm", "solinas", ] } @@ -129,7 +129,7 @@ tracing = "0.1" rayon = { version = "1.10", optional = true } [dev-dependencies] -jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false } +jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false } # Test-only: pull in `akita-config`'s workspace artifact loader and ring-plan # seed. Schedule rows remain checked-in external artifacts loaded at runtime. akita-config = { version = "0.1.0", path = "../akita-config", default-features = false, features = [ diff --git a/crates/akita-prover/Cargo.toml b/crates/akita-prover/Cargo.toml index 42df7dcee..5f67f3a05 100644 --- a/crates/akita-prover/Cargo.toml +++ b/crates/akita-prover/Cargo.toml @@ -13,11 +13,11 @@ akita-error = { version = "0.1.0", path = "../akita-error" } akita-algebra = { version = "0.1.0", path = "../akita-algebra" } akita-challenges = { version = "0.1.0", path = "../akita-challenges", default-features = false } akita-config = { version = "0.1.0", path = "../akita-config", default-features = false } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false, features = [ "asm", "solinas", ] } -jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false } +jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false } akita-serialization = { version = "0.1.0", path = "../akita-serialization" } akita-sumcheck = { version = "0.1.0", path = "../akita-sumcheck", default-features = false } akita-transcript = { version = "0.1.0", path = "../akita-transcript", default-features = false } diff --git a/crates/akita-serialization/Cargo.toml b/crates/akita-serialization/Cargo.toml index 8002759ff..88aac1264 100644 --- a/crates/akita-serialization/Cargo.toml +++ b/crates/akita-serialization/Cargo.toml @@ -9,11 +9,11 @@ repository = "https://github.com/LayerZero-Labs/akita" readme = "../../README.md" [dependencies] -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false, features = [ "asm", "solinas", ] } -jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false } +jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false } thiserror = "2.0" [lints] diff --git a/crates/akita-setup/Cargo.toml b/crates/akita-setup/Cargo.toml index 3fececa4e..cfa6f83e3 100644 --- a/crates/akita-setup/Cargo.toml +++ b/crates/akita-setup/Cargo.toml @@ -29,7 +29,7 @@ disk-persistence = ["akita-cpu-backend/disk-persistence"] akita-error = { version = "0.1.0", path = "../akita-error" } akita-config = { version = "0.1.0", path = "../akita-config", default-features = false } akita-cpu-backend = { version = "0.1.0", path = "../akita-cpu-backend", default-features = false } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false, features = [ "asm", "solinas", ] } diff --git a/crates/akita-sumcheck/Cargo.toml b/crates/akita-sumcheck/Cargo.toml index 42047e81f..9ba3ea146 100644 --- a/crates/akita-sumcheck/Cargo.toml +++ b/crates/akita-sumcheck/Cargo.toml @@ -11,11 +11,11 @@ readme = "../../README.md" [dependencies] akita-error = { version = "0.1.0", path = "../akita-error" } akita-algebra = { version = "0.1.0", path = "../akita-algebra" } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false, features = [ "asm", "solinas", ] } -jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false } +jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false } akita-serialization = { version = "0.1.0", path = "../akita-serialization" } akita-transcript = { version = "0.1.0", path = "../akita-transcript", default-features = false } diff --git a/crates/akita-transcript/Cargo.toml b/crates/akita-transcript/Cargo.toml index 1583e180d..4c6aef3cc 100644 --- a/crates/akita-transcript/Cargo.toml +++ b/crates/akita-transcript/Cargo.toml @@ -10,8 +10,8 @@ readme = "../../README.md" [dependencies] akita-error = { version = "0.1.0", path = "../akita-error" } -jolt-inlines-blake2 = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false, optional = true } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false, features = [ +jolt-inlines-blake2 = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false, optional = true } +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false, features = [ "asm", "solinas", ] } diff --git a/crates/akita-types/Cargo.toml b/crates/akita-types/Cargo.toml index 47e20538f..7aed86e31 100644 --- a/crates/akita-types/Cargo.toml +++ b/crates/akita-types/Cargo.toml @@ -13,11 +13,11 @@ akita-params = { version = "0.1.0", path = "../akita-params", default-features = akita-error = { version = "0.1.0", path = "../akita-error" } akita-algebra = { version = "0.1.0", path = "../akita-algebra" } akita-challenges = { version = "0.1.0", path = "../akita-challenges", default-features = false } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false, features = [ "asm", "solinas", ] } -jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false } +jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false } akita-serialization = { version = "0.1.0", path = "../akita-serialization" } akita-sumcheck = { version = "0.1.0", path = "../akita-sumcheck", default-features = false } akita-transcript = { version = "0.1.0", path = "../akita-transcript", default-features = false } diff --git a/crates/akita-verifier/Cargo.toml b/crates/akita-verifier/Cargo.toml index 1baca1d28..781014164 100644 --- a/crates/akita-verifier/Cargo.toml +++ b/crates/akita-verifier/Cargo.toml @@ -18,11 +18,11 @@ akita-error = { version = "0.1.0", path = "../akita-error" } akita-algebra = { version = "0.1.0", path = "../akita-algebra" } akita-challenges = { version = "0.1.0", path = "../akita-challenges", default-features = false } akita-config = { version = "0.1.0", path = "../akita-config", default-features = false } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false, features = [ "asm", "solinas", ] } -jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false } +jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false } akita-serialization = { version = "0.1.0", path = "../akita-serialization" } akita-sumcheck = { version = "0.1.0", path = "../akita-sumcheck", default-features = false } akita-transcript = { version = "0.1.0", path = "../akita-transcript", default-features = false } diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 0a87f84f4..71d96524f 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -73,11 +73,11 @@ akita-types = { path = "../crates/akita-types", default-features = false, featur akita-verifier = { path = "../crates/akita-verifier", default-features = false, features = [ "transcript-blake2b", ] } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false, features = [ "asm", "solinas", ] } -jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false } +jolt-poly = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false } libfuzzer-sys = "0.4.12" num-bigint = "0.4" rayon = "1.10" diff --git a/profile/akita-recursion/artifact/Cargo.toml b/profile/akita-recursion/artifact/Cargo.toml index 97e2680ff..e0c949e40 100644 --- a/profile/akita-recursion/artifact/Cargo.toml +++ b/profile/akita-recursion/artifact/Cargo.toml @@ -16,7 +16,7 @@ akita-recursion-glue = { path = "../glue" } akita-serialization = { path = "../../../crates/akita-serialization" } akita-config = { path = "../../../crates/akita-config", default-features = false, features = [ ] } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false, features = [ "asm", "solinas", ] } diff --git a/profile/akita-recursion/glue/Cargo.toml b/profile/akita-recursion/glue/Cargo.toml index 1e0fb658a..af8ed1ef1 100644 --- a/profile/akita-recursion/glue/Cargo.toml +++ b/profile/akita-recursion/glue/Cargo.toml @@ -27,7 +27,7 @@ trusted-benchmark-artifact = [] akita-error = { version = "0.1.0", path = "../../../crates/akita-error" } akita-algebra = { version = "0.1.0", path = "../../../crates/akita-algebra" } akita-config = { version = "0.1.0", path = "../../../crates/akita-config", default-features = false } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false, features = [ "asm", "solinas", ] } diff --git a/profile/akita-recursion/guest/Cargo.toml b/profile/akita-recursion/guest/Cargo.toml index 682a0ed32..d7e029645 100644 --- a/profile/akita-recursion/guest/Cargo.toml +++ b/profile/akita-recursion/guest/Cargo.toml @@ -34,11 +34,11 @@ trusted-benchmark-artifact = ["akita-recursion-glue/trusted-benchmark-artifact"] akita-error = { path = "../../../crates/akita-error" } # Aliased as `jolt` so `#[jolt::provable]` and `jolt::start_cycle_tracking` # resolve the same way as in the upstream Jolt examples. -jolt = { package = "jolt-sdk", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false } +jolt = { package = "jolt-sdk", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false } akita-recursion-glue = { path = "../glue" } akita-config = { path = "../../../crates/akita-config", default-features = false, features = [ ] } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false, features = [ +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false, features = [ "asm", "solinas", ] } diff --git a/profile/akita-recursion/host/Cargo.toml b/profile/akita-recursion/host/Cargo.toml index 5b4c59078..149017fbe 100644 --- a/profile/akita-recursion/host/Cargo.toml +++ b/profile/akita-recursion/host/Cargo.toml @@ -14,7 +14,7 @@ name = "akita-recursion-host" path = "src/main.rs" [dependencies] -jolt-sdk = { git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false, features = [ +jolt-sdk = { git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false, features = [ "host", ] } # We pin `jolt-sdk-macros` with `guest-std` directly so that the @@ -22,7 +22,7 @@ jolt-sdk = { git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068d # its own `cfg(feature = "guest-std")` at host compile time). Going through # `jolt-sdk/guest-std` would also pull `zeroos-runtime-musl` in for the # host build, which fails to link on macOS / non-musl platforms. -jolt-sdk-macros = { git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", features = [ +jolt-sdk-macros = { git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", features = [ "guest-std", ] } guest = { package = "akita-recursion-guest", path = "../guest", features = [ diff --git a/profile/akita-recursion/inline-parity/guest/Cargo.toml b/profile/akita-recursion/inline-parity/guest/Cargo.toml index 8439f4e87..2ad27b749 100644 --- a/profile/akita-recursion/inline-parity/guest/Cargo.toml +++ b/profile/akita-recursion/inline-parity/guest/Cargo.toml @@ -29,8 +29,8 @@ akita-transcript = { path = "../../../../crates/akita-transcript", default-featu "blake2-inline", ] } # Aliased as `jolt` so `#[jolt::provable]` resolves as in the Jolt examples. -jolt = { package = "jolt-sdk", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false } -jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false, features = [ +jolt = { package = "jolt-sdk", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false } +jolt-field = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false, features = [ "asm", "solinas", ] } diff --git a/profile/akita-recursion/inline-parity/host/Cargo.toml b/profile/akita-recursion/inline-parity/host/Cargo.toml index 39d8e20d1..a341a1cee 100644 --- a/profile/akita-recursion/inline-parity/host/Cargo.toml +++ b/profile/akita-recursion/inline-parity/host/Cargo.toml @@ -21,26 +21,26 @@ path = "src/main.rs" [dependencies] guest = { package = "akita-inline-parity-guest", path = "../guest" } -jolt-sdk = { git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", default-features = false, features = [ +jolt-sdk = { git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", default-features = false, features = [ "host", ] } # Pinned with `guest-std` so `#[jolt::provable]` builds the guest in std mode # without pulling ZeroOS musl into the host build (see `../../host/Cargo.toml`). -jolt-sdk-macros = { git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", features = [ +jolt-sdk-macros = { git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", features = [ "guest-std", ] } # Linked for their `inventory` registrations: Jolt expands an inline # instruction only when its crate's `host` feature is in the host binary. -jolt-inlines-blake2 = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", features = [ +jolt-inlines-blake2 = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", features = [ "host", ] } -jolt-inlines-keccak256 = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", features = [ +jolt-inlines-keccak256 = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", features = [ "host", ] } -jolt-inlines-ntt = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", features = [ +jolt-inlines-ntt = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", features = [ "host", ] } -jolt-program = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "83fcab4937c492615b068dc852ad848c3b20cde0", features = [ +jolt-program = { version = "=0.1.0", git = "https://github.com/a16z/jolt", rev = "718921695296180005c2bf028451f730886561bb", features = [ "image", ] } akita-algebra = { path = "../../../../crates/akita-algebra" } From a3aceff392c03c093476515a3844bc5c99c97bab Mon Sep 17 00:00:00 2001 From: acentelles Date: Fri, 30 Oct 2026 20:58:12 +0000 Subject: [PATCH 17/17] build: resolve lockfiles after merging main Cargo.lock, fuzz/Cargo.lock and profile/akita-recursion/Cargo.lock resolved by cargo against the new a16z/jolt revision. --- Cargo.lock | 12 ++-- fuzz/Cargo.lock | 6 +- profile/akita-recursion/Cargo.lock | 91 +++++++++++++----------------- 3 files changed, 49 insertions(+), 60 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 391dab224..4134c6036 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -933,7 +933,7 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jolt-field" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "cc", "num-traits", @@ -946,7 +946,7 @@ dependencies = [ [[package]] name = "jolt-inlines-blake2" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "digest 0.11.3", ] @@ -954,17 +954,17 @@ dependencies = [ [[package]] name = "jolt-inlines-keccak256" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" [[package]] name = "jolt-inlines-ntt" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" [[package]] name = "jolt-poly" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "jolt-field", "jolt-utils", @@ -978,7 +978,7 @@ dependencies = [ [[package]] name = "jolt-utils" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "num-traits", ] diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index 3db9277f0..425173a6c 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -713,7 +713,7 @@ dependencies = [ [[package]] name = "jolt-field" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "cc", "num-traits", @@ -726,7 +726,7 @@ dependencies = [ [[package]] name = "jolt-poly" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "jolt-field", "jolt-utils", @@ -740,7 +740,7 @@ dependencies = [ [[package]] name = "jolt-utils" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "num-traits", ] diff --git a/profile/akita-recursion/Cargo.lock b/profile/akita-recursion/Cargo.lock index edc7c9250..8329d6f0d 100644 --- a/profile/akita-recursion/Cargo.lock +++ b/profile/akita-recursion/Cargo.lock @@ -739,7 +739,7 @@ checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "common" version = "0.2.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "allocative", "ark-serialize", @@ -1200,7 +1200,7 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jolt-akita" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "akita-algebra", "akita-challenges", @@ -1225,7 +1225,7 @@ dependencies = [ [[package]] name = "jolt-blindfold" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "jolt-claims", "jolt-crypto", @@ -1236,7 +1236,6 @@ dependencies = [ "jolt-transcript", "jolt-utils", "rand_core 0.6.4", - "rayon", "serde", "thiserror", ] @@ -1244,9 +1243,8 @@ dependencies = [ [[package]] name = "jolt-claims" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ - "blake2 0.11.0", "derive_more", "jolt-claims-derive", "jolt-field", @@ -1255,16 +1253,18 @@ dependencies = [ "jolt-poly", "jolt-r1cs", "jolt-riscv", + "jolt-transcript", "jolt-utils", "rayon", "serde", + "sha3 0.12.0", "thiserror", ] [[package]] name = "jolt-claims-derive" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "proc-macro2", "quote", @@ -1274,7 +1274,7 @@ dependencies = [ [[package]] name = "jolt-crypto" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "ark-bn254", "ark-ec", @@ -1295,7 +1295,7 @@ dependencies = [ [[package]] name = "jolt-dory" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "ark-bn254", "ark-ec", @@ -1315,7 +1315,7 @@ dependencies = [ [[package]] name = "jolt-field" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "ark-bn254", "ark-ff", @@ -1325,13 +1325,14 @@ dependencies = [ "rand_core 0.6.4", "rayon", "serde", + "spongefish 0.8.0", "thiserror", ] [[package]] name = "jolt-host" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "bincode 2.0.1", "common", @@ -1348,7 +1349,7 @@ dependencies = [ [[package]] name = "jolt-inlines-blake2" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "digest 0.11.3", "jolt-inlines-sdk", @@ -1357,7 +1358,7 @@ dependencies = [ [[package]] name = "jolt-inlines-keccak256" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "jolt-inlines-sdk", ] @@ -1365,7 +1366,7 @@ dependencies = [ [[package]] name = "jolt-inlines-ntt" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "jolt-inlines-sdk", ] @@ -1373,7 +1374,7 @@ dependencies = [ [[package]] name = "jolt-inlines-sdk" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "inventory", "jolt-platform", @@ -1386,7 +1387,7 @@ dependencies = [ [[package]] name = "jolt-kernels" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "jolt-claims", "jolt-field", @@ -1410,7 +1411,7 @@ dependencies = [ [[package]] name = "jolt-kernels-derive" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "proc-macro2", "quote", @@ -1420,7 +1421,7 @@ dependencies = [ [[package]] name = "jolt-lookup-tables" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "jolt-field", "jolt-riscv", @@ -1431,7 +1432,7 @@ dependencies = [ [[package]] name = "jolt-openings" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "jolt-crypto", "jolt-field", @@ -1463,7 +1464,7 @@ dependencies = [ [[package]] name = "jolt-platform" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "getrandom 0.2.17", "getrandom 0.3.4", @@ -1473,7 +1474,7 @@ dependencies = [ [[package]] name = "jolt-poly" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "jolt-field", "jolt-transcript", @@ -1489,7 +1490,7 @@ dependencies = [ [[package]] name = "jolt-program" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "ark-serialize", "common", @@ -1503,7 +1504,7 @@ dependencies = [ [[package]] name = "jolt-prover" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "common", "jolt-akita", @@ -1532,7 +1533,7 @@ dependencies = [ [[package]] name = "jolt-r1cs" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "jolt-field", "serde", @@ -1542,7 +1543,7 @@ dependencies = [ [[package]] name = "jolt-riscv" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "ark-serialize", "serde", @@ -1553,7 +1554,7 @@ dependencies = [ [[package]] name = "jolt-sdk" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "bincode 2.0.1", "bytemuck", @@ -1581,7 +1582,7 @@ dependencies = [ [[package]] name = "jolt-sdk-macros" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "common", "proc-macro2", @@ -1592,7 +1593,7 @@ dependencies = [ [[package]] name = "jolt-sumcheck" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "jolt-crypto", "jolt-field", @@ -1608,21 +1609,21 @@ dependencies = [ [[package]] name = "jolt-transcript" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "ark-bn254", "ark-ff", - "blake2 0.11.0", - "digest 0.11.3", "getrandom 0.4.3", "jolt-field", + "sha3 0.12.0", + "shake", "spongefish 0.8.0", ] [[package]] name = "jolt-utils" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "num-traits", "rayon", @@ -1631,11 +1632,10 @@ dependencies = [ [[package]] name = "jolt-verifier" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "ark-serialize", "bincode 2.0.1", - "blake2 0.11.0", "common", "jolt-blindfold", "jolt-claims", @@ -1652,13 +1652,14 @@ dependencies = [ "jolt-verifier-derive", "num-traits", "serde", + "sha3 0.12.0", "thiserror", ] [[package]] name = "jolt-verifier-derive" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "proc-macro2", "quote", @@ -1668,7 +1669,7 @@ dependencies = [ [[package]] name = "jolt-witness" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "common", "jolt-claims", @@ -1686,7 +1687,7 @@ dependencies = [ [[package]] name = "jolt-witness-derive" version = "0.1.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "proc-macro2", "quote", @@ -2470,8 +2471,7 @@ checksum = "62560b5029264a655fc461a0ecadc4d24862799190897d3225b3272b7a3f13b7" dependencies = [ "digest 0.11.3", "getrandom 0.4.3", - "shake", - "turboshake", + "keccak 0.2.2", "zeroize", ] @@ -2568,7 +2568,7 @@ dependencies = [ [[package]] name = "tracer" version = "0.2.0" -source = "git+https://github.com/a16z/jolt?rev=83fcab4937c492615b068dc852ad848c3b20cde0#83fcab4937c492615b068dc852ad848c3b20cde0" +source = "git+https://github.com/a16z/jolt?rev=718921695296180005c2bf028451f730886561bb#718921695296180005c2bf028451f730886561bb" dependencies = [ "addr2line", "ark-serialize", @@ -2656,17 +2656,6 @@ dependencies = [ "tracing-log", ] -[[package]] -name = "turboshake" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f892c6904b0bd5a9241eac848347abcbbbd2b9f3892bad23ac3e6efab8d6f06a" -dependencies = [ - "digest 0.11.3", - "keccak 0.2.2", - "sponge-cursor", -] - [[package]] name = "twox-hash" version = "2.1.4"