From 2bfb3d9cb546011f4b2ddda6f6edbd8f4d272244 Mon Sep 17 00:00:00 2001 From: markosg04 Date: Mon, 20 Apr 2026 14:10:21 -0400 Subject: [PATCH 01/14] feat(jolt-hyperkzg): add HyperKZG multilinear commitment scheme Introduces jolt-hyperkzg, a pairing-based multilinear polynomial commitment scheme implementing the jolt-openings trait surface. Generic over `P: PairingGroup`; BN254 is the production instantiation. Contents: - scheme.rs: HyperKZGScheme implementing CommitmentScheme and AdditivelyHomomorphic; prove/verify built on KZG univariate openings - kzg.rs: univariate KZG primitives (commit, evaluate, witness polynomial division) used internally by the multilinear protocol - types.rs: HyperKZGCommitment, HyperKZGProof, HyperKZGProverSetup, HyperKZGVerifierSetup - error.rs: HyperKzgError enum --- Cargo.lock | 20 + Cargo.toml | 1 + crates/jolt-hyperkzg/Cargo.toml | 35 + crates/jolt-hyperkzg/README.md | 49 ++ crates/jolt-hyperkzg/benches/hyperkzg.rs | 182 ++++++ crates/jolt-hyperkzg/fuzz/Cargo.toml | 36 ++ .../fuzz/fuzz_targets/commit_open_verify.rs | 45 ++ .../fuzz/fuzz_targets/tampered_proof.rs | 65 ++ .../fuzz/fuzz_targets/wrong_eval.rs | 59 ++ crates/jolt-hyperkzg/src/error.rs | 14 + crates/jolt-hyperkzg/src/kzg.rs | 263 ++++++++ crates/jolt-hyperkzg/src/lib.rs | 28 + crates/jolt-hyperkzg/src/scheme.rs | 605 ++++++++++++++++++ crates/jolt-hyperkzg/src/types.rs | 118 ++++ .../jolt-hyperkzg/tests/commit_open_verify.rs | 224 +++++++ 15 files changed, 1744 insertions(+) create mode 100644 crates/jolt-hyperkzg/Cargo.toml create mode 100644 crates/jolt-hyperkzg/README.md create mode 100644 crates/jolt-hyperkzg/benches/hyperkzg.rs create mode 100644 crates/jolt-hyperkzg/fuzz/Cargo.toml create mode 100644 crates/jolt-hyperkzg/fuzz/fuzz_targets/commit_open_verify.rs create mode 100644 crates/jolt-hyperkzg/fuzz/fuzz_targets/tampered_proof.rs create mode 100644 crates/jolt-hyperkzg/fuzz/fuzz_targets/wrong_eval.rs create mode 100644 crates/jolt-hyperkzg/src/error.rs create mode 100644 crates/jolt-hyperkzg/src/kzg.rs create mode 100644 crates/jolt-hyperkzg/src/lib.rs create mode 100644 crates/jolt-hyperkzg/src/scheme.rs create mode 100644 crates/jolt-hyperkzg/src/types.rs create mode 100644 crates/jolt-hyperkzg/tests/commit_open_verify.rs diff --git a/Cargo.lock b/Cargo.lock index ddc3063d30..42fc519ebb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2846,6 +2846,26 @@ dependencies = [ "serde", ] +[[package]] +name = "jolt-hyperkzg" +version = "0.1.0" +dependencies = [ + "criterion", + "jolt-crypto", + "jolt-field", + "jolt-openings", + "jolt-poly", + "jolt-transcript", + "num-traits", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rand_core 0.6.4", + "rayon", + "serde", + "thiserror 2.0.18", + "tracing", +] + [[package]] name = "jolt-inlines-bigint" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 42bec6295e..602909b5ae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ members = [ "crates/jolt-sumcheck", "crates/jolt-openings", "crates/jolt-dory", + "crates/jolt-hyperkzg", "crates/jolt-riscv", "crates/jolt-transcript", "crates/jolt-profiling", diff --git a/crates/jolt-hyperkzg/Cargo.toml b/crates/jolt-hyperkzg/Cargo.toml new file mode 100644 index 0000000000..2e88a335f9 --- /dev/null +++ b/crates/jolt-hyperkzg/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "jolt-hyperkzg" +version = "0.1.0" +edition = "2021" +license = "MIT" +description = "HyperKZG multilinear polynomial commitment scheme for the Jolt zkVM" + +[lints] +workspace = true + +[dependencies] +jolt-crypto = { path = "../jolt-crypto" } +jolt-field = { path = "../jolt-field" } +jolt-poly = { path = "../jolt-poly" } +jolt-transcript = { path = "../jolt-transcript" } +jolt-openings = { path = "../jolt-openings" } +serde = { workspace = true, features = ["derive"] } +tracing.workspace = true +num-traits = { workspace = true } +rayon = { workspace = true } +thiserror = { workspace = true } +rand_core = { workspace = true } +rand_chacha = { workspace = true } + +[dev-dependencies] +jolt-field = { path = "../jolt-field", features = ["bn254"] } +criterion = { workspace = true } +rand = { workspace = true } + +[[bench]] +name = "hyperkzg" +harness = false + +[package.metadata.cargo-machete] +ignored = ["rand_core", "rand_chacha", "rand"] diff --git a/crates/jolt-hyperkzg/README.md b/crates/jolt-hyperkzg/README.md new file mode 100644 index 0000000000..a71a555d61 --- /dev/null +++ b/crates/jolt-hyperkzg/README.md @@ -0,0 +1,49 @@ +# jolt-hyperkzg + +HyperKZG multilinear polynomial commitment scheme for the Jolt zkVM. + +Part of the [Jolt](https://github.com/a16z/jolt) zkVM. + +## Overview + +HyperKZG reduces multilinear polynomial commitments to univariate KZG using the Gemini transformation ([section 2.4.2](https://eprint.iacr.org/2022/420.pdf)), operating directly on evaluation-form polynomials (no FFT/interpolation). + +This crate is generic over `PairingGroup` from `jolt-crypto` and implements `CommitmentScheme` and `AdditivelyHomomorphic` from `jolt-openings`. + +### Protocol + +1. **Commit** — MSM of evaluations against SRS G1 powers. +2. **Open** (Gemini reduction) — fold the multilinear polynomial `ℓ-1` times producing intermediate commitments, derive challenge `r`, batch KZG open at `[r, -r, r²]`. +3. **Verify** — evaluation consistency check, then batch KZG pairing check. + +## Public API + +- **`HyperKZGScheme

`** — Main entry point. Implements `CommitmentScheme` and `AdditivelyHomomorphic`. +- **`HyperKZGCommitment

`** — A commitment (G1 point). +- **`HyperKZGProof

`** — Opening proof containing intermediate commitments and evaluations. +- **`HyperKZGProverSetup

`** / **`HyperKZGVerifierSetup

`** — Structured reference strings. + +### Submodules + +- **`kzg`** — Univariate KZG primitives (commit, open, batch verify). +- **`error`** — Error types. + +## Dependency Position + +``` +jolt-field ─┐ +jolt-crypto ─┤ +jolt-poly ─┼─► jolt-hyperkzg +jolt-transcript ─┤ +jolt-openings ─┘ +``` + +Used by `jolt-zkvm`. + +## Feature Flags + +This crate has no feature flags. + +## License + +MIT diff --git a/crates/jolt-hyperkzg/benches/hyperkzg.rs b/crates/jolt-hyperkzg/benches/hyperkzg.rs new file mode 100644 index 0000000000..82883916b1 --- /dev/null +++ b/crates/jolt-hyperkzg/benches/hyperkzg.rs @@ -0,0 +1,182 @@ +#![allow(unused_results)] + +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; + +use jolt_crypto::Bn254; +use jolt_field::{Field, Fr}; +use jolt_hyperkzg::{HyperKZGProverSetup, HyperKZGScheme, HyperKZGVerifierSetup}; +use jolt_openings::{AdditivelyHomomorphic, CommitmentScheme}; +use jolt_poly::Polynomial; +use jolt_transcript::Transcript; +use rand_chacha::ChaCha20Rng; +use rand_core::SeedableRng; + +type TestScheme = HyperKZGScheme; + +fn make_setup(max_degree: usize) -> (HyperKZGProverSetup, HyperKZGVerifierSetup) { + let mut rng = ChaCha20Rng::seed_from_u64(0xbe0c); + let g1 = Bn254::g1_generator(); + let g2 = Bn254::g2_generator(); + let pk = TestScheme::setup(&mut rng, max_degree, g1, g2); + let vk = TestScheme::verifier_setup(&pk); + (pk, vk) +} + +fn bench_commit(c: &mut Criterion) { + let mut group = c.benchmark_group("hyperkzg_commit"); + for num_vars in [8, 10, 12, 14] { + let n = 1 << num_vars; + let (pk, _) = make_setup(n); + group.bench_with_input( + BenchmarkId::from_parameter(num_vars), + &num_vars, + |b, &nv| { + b.iter_batched( + || { + let mut rng = ChaCha20Rng::seed_from_u64(0); + Polynomial::::random(nv, &mut rng) + }, + |poly| TestScheme::commit(poly.evaluations(), &pk), + criterion::BatchSize::SmallInput, + ); + }, + ); + } + group.finish(); +} + +fn bench_open(c: &mut Criterion) { + let mut group = c.benchmark_group("hyperkzg_open"); + for num_vars in [8, 10, 12, 14] { + let n = 1 << num_vars; + let (pk, _) = make_setup(n); + group.bench_with_input( + BenchmarkId::from_parameter(num_vars), + &num_vars, + |b, &nv| { + b.iter_batched( + || { + let mut rng = ChaCha20Rng::seed_from_u64(0); + let poly = Polynomial::::random(nv, &mut rng); + let point: Vec = + (0..nv).map(|_| ::random(&mut rng)).collect(); + let eval = poly.evaluate(&point); + (poly, point, eval) + }, + |(poly, point, eval)| { + let mut transcript = jolt_transcript::Blake2bTranscript::new(b"bench-open"); + ::open( + &poly, + &point, + eval, + &pk, + None, + &mut transcript, + ) + }, + criterion::BatchSize::SmallInput, + ); + }, + ); + } + group.finish(); +} + +fn bench_verify(c: &mut Criterion) { + let mut group = c.benchmark_group("hyperkzg_verify"); + for num_vars in [8, 10, 12, 14] { + let n = 1 << num_vars; + let (pk, vk) = make_setup(n); + group.bench_with_input( + BenchmarkId::from_parameter(num_vars), + &num_vars, + |b, &nv| { + b.iter_batched( + || { + let mut rng = ChaCha20Rng::seed_from_u64(0); + let poly = Polynomial::::random(nv, &mut rng); + let point: Vec = + (0..nv).map(|_| ::random(&mut rng)).collect(); + let eval = poly.evaluate(&point); + let (commitment, ()) = TestScheme::commit(poly.evaluations(), &pk); + let mut transcript = + jolt_transcript::Blake2bTranscript::new(b"bench-verify"); + let proof = ::open( + &poly, + &point, + eval, + &pk, + None, + &mut transcript, + ); + (commitment, point, eval, proof) + }, + |(commitment, point, eval, proof)| { + let mut transcript = + jolt_transcript::Blake2bTranscript::new(b"bench-verify"); + ::verify( + &commitment, + &point, + eval, + &proof, + &vk, + &mut transcript, + ) + }, + criterion::BatchSize::SmallInput, + ); + }, + ); + } + group.finish(); +} + +fn bench_combine(c: &mut Criterion) { + let mut group = c.benchmark_group("hyperkzg_combine"); + for count in [2, 4, 8, 16] { + let num_vars = 10; + let n = 1 << num_vars; + let (pk, _) = make_setup(n); + let mut rng = ChaCha20Rng::seed_from_u64(0); + + let commitments: Vec<_> = (0..count) + .map(|_| { + let poly = Polynomial::::random(num_vars, &mut rng); + let (c, ()) = TestScheme::commit(poly.evaluations(), &pk); + c + }) + .collect(); + let scalars: Vec = (0..count).map(|_| Fr::random(&mut rng)).collect(); + + group.bench_with_input(BenchmarkId::from_parameter(count), &count, |b, _| { + b.iter(|| TestScheme::combine(&commitments, &scalars)); + }); + } + group.finish(); +} + +fn bench_setup(c: &mut Criterion) { + let mut group = c.benchmark_group("hyperkzg_setup"); + for num_vars in [8, 10, 12] { + let n = 1 << num_vars; + group.bench_with_input(BenchmarkId::from_parameter(num_vars), &num_vars, |b, _| { + b.iter(|| { + let mut rng = ChaCha20Rng::seed_from_u64(0xbe0c); + let g1 = Bn254::g1_generator(); + let g2 = Bn254::g2_generator(); + TestScheme::setup(&mut rng, n, g1, g2) + }); + }); + } + group.finish(); +} + +criterion_group!( + benches, + bench_setup, + bench_commit, + bench_open, + bench_verify, + bench_combine, +); +criterion_main!(benches); diff --git a/crates/jolt-hyperkzg/fuzz/Cargo.toml b/crates/jolt-hyperkzg/fuzz/Cargo.toml new file mode 100644 index 0000000000..dc2b94ca42 --- /dev/null +++ b/crates/jolt-hyperkzg/fuzz/Cargo.toml @@ -0,0 +1,36 @@ +[workspace] + +[package] +name = "jolt-hyperkzg-fuzz" +version = "0.0.0" +publish = false +edition = "2021" + +[package.metadata] +cargo-fuzz = true + +[dependencies] +libfuzzer-sys = "0.4" +jolt-hyperkzg = { path = ".." } +jolt-crypto = { path = "../../jolt-crypto" } +jolt-field = { path = "../../jolt-field", features = ["bn254"] } +jolt-openings = { path = "../../jolt-openings" } +jolt-poly = { path = "../../jolt-poly" } +jolt-transcript = { path = "../../jolt-transcript" } +rand_chacha = "0.3" +rand_core = "0.6" + +[[bin]] +name = "commit_open_verify" +path = "fuzz_targets/commit_open_verify.rs" +doc = false + +[[bin]] +name = "tampered_proof" +path = "fuzz_targets/tampered_proof.rs" +doc = false + +[[bin]] +name = "wrong_eval" +path = "fuzz_targets/wrong_eval.rs" +doc = false diff --git a/crates/jolt-hyperkzg/fuzz/fuzz_targets/commit_open_verify.rs b/crates/jolt-hyperkzg/fuzz/fuzz_targets/commit_open_verify.rs new file mode 100644 index 0000000000..51c8079b54 --- /dev/null +++ b/crates/jolt-hyperkzg/fuzz/fuzz_targets/commit_open_verify.rs @@ -0,0 +1,45 @@ +#![no_main] + +//! Fuzz: random polynomial + random point must always commit-open-verify successfully. + +use jolt_crypto::Bn254; +use jolt_field::{Field, Fr}; +use jolt_hyperkzg::HyperKZGScheme; +use jolt_openings::CommitmentScheme; +use jolt_poly::Polynomial; +use jolt_transcript::{Blake2bTranscript, Transcript}; +use libfuzzer_sys::fuzz_target; +use rand_chacha::ChaCha20Rng; +use rand_core::SeedableRng; + +type TestScheme = HyperKZGScheme; + +fuzz_target!(|data: &[u8]| { + if data.len() < 8 { + return; + } + + let seed = u64::from_le_bytes(data[..8].try_into().unwrap()); + let num_vars = (data.len() % 4) + 1; // 1..=4 variables + let n = 1usize << num_vars; + + let mut rng = ChaCha20Rng::seed_from_u64(seed); + let g1 = Bn254::g1_generator(); + let g2 = Bn254::g2_generator(); + let pk = TestScheme::setup(&mut rng, n, g1, g2); + let vk = TestScheme::verifier_setup(&pk); + + let poly = Polynomial::::random(num_vars, &mut rng); + let point: Vec = (0..num_vars).map(|_| Fr::random(&mut rng)).collect(); + let eval = poly.evaluate(&point); + + let (commitment, ()) = TestScheme::commit(poly.evaluations(), &pk); + + let mut pt = Blake2bTranscript::new(b"fuzz"); + let proof = + ::open(&poly, &point, eval, &pk, None, &mut pt); + + let mut vt = Blake2bTranscript::new(b"fuzz"); + ::verify(&commitment, &point, eval, &proof, &vk, &mut vt) + .expect("valid proof must verify"); +}); diff --git a/crates/jolt-hyperkzg/fuzz/fuzz_targets/tampered_proof.rs b/crates/jolt-hyperkzg/fuzz/fuzz_targets/tampered_proof.rs new file mode 100644 index 0000000000..12dc6cf59c --- /dev/null +++ b/crates/jolt-hyperkzg/fuzz/fuzz_targets/tampered_proof.rs @@ -0,0 +1,65 @@ +#![no_main] + +//! Fuzz: tamper with proof evaluation bytes and verify that verification rejects. +//! +//! We generate a valid proof, then corrupt an evaluation entry using fuzzer-chosen bytes. + +use jolt_crypto::Bn254; +use jolt_field::{Field, Fr}; +use jolt_hyperkzg::HyperKZGScheme; +use jolt_openings::CommitmentScheme; +use jolt_poly::Polynomial; +use jolt_transcript::{Blake2bTranscript, Transcript}; +use libfuzzer_sys::fuzz_target; +use rand_chacha::ChaCha20Rng; +use rand_core::SeedableRng; + +type TestScheme = HyperKZGScheme; + +fuzz_target!(|data: &[u8]| { + if data.len() < 10 { + return; + } + + let num_vars = 3; + let n = 1usize << num_vars; + + let mut rng = ChaCha20Rng::seed_from_u64(0xfade); + let g1 = Bn254::g1_generator(); + let g2 = Bn254::g2_generator(); + let pk = TestScheme::setup(&mut rng, n, g1, g2); + let vk = TestScheme::verifier_setup(&pk); + + let poly = Polynomial::::random(num_vars, &mut rng); + let point: Vec = (0..num_vars).map(|_| Fr::random(&mut rng)).collect(); + let eval = poly.evaluate(&point); + + let (commitment, ()) = TestScheme::commit(poly.evaluations(), &pk); + + let mut pt = Blake2bTranscript::new(b"fuzz-tamper"); + let proof = + ::open(&poly, &point, eval, &pk, None, &mut pt); + + let tamper_row = (data[0] as usize) % proof.v.len(); + let tamper_col = (data[1] as usize) % proof.v[tamper_row].len(); + let tamper_val = Fr::from_bytes(&data[2..]); + + // Skip if the corruption is a no-op + if tamper_val == proof.v[tamper_row][tamper_col] { + return; + } + + let mut tampered = proof.clone(); + tampered.v[tamper_row][tamper_col] = tamper_val; + + let mut vt = Blake2bTranscript::new(b"fuzz-tamper"); + let result = ::verify( + &commitment, + &point, + eval, + &tampered, + &vk, + &mut vt, + ); + assert!(result.is_err(), "tampered proof must be rejected"); +}); diff --git a/crates/jolt-hyperkzg/fuzz/fuzz_targets/wrong_eval.rs b/crates/jolt-hyperkzg/fuzz/fuzz_targets/wrong_eval.rs new file mode 100644 index 0000000000..4c15d1af2f --- /dev/null +++ b/crates/jolt-hyperkzg/fuzz/fuzz_targets/wrong_eval.rs @@ -0,0 +1,59 @@ +#![no_main] + +//! Fuzz: claim a wrong evaluation and verify that verification rejects. +//! +//! The prover generates a valid proof for the correct evaluation. The +//! verifier checks against a fuzzer-derived wrong evaluation. Must reject. + +use jolt_crypto::Bn254; +use jolt_field::{Field, Fr}; +use jolt_hyperkzg::HyperKZGScheme; +use jolt_openings::CommitmentScheme; +use jolt_poly::Polynomial; +use jolt_transcript::{Blake2bTranscript, Transcript}; +use libfuzzer_sys::fuzz_target; +use rand_chacha::ChaCha20Rng; +use rand_core::SeedableRng; + +type TestScheme = HyperKZGScheme; + +fuzz_target!(|data: &[u8]| { + if data.len() < 32 { + return; + } + + let num_vars = 3; + let n = 1usize << num_vars; + + let mut rng = ChaCha20Rng::seed_from_u64(0xface); + let g1 = Bn254::g1_generator(); + let g2 = Bn254::g2_generator(); + let pk = TestScheme::setup(&mut rng, n, g1, g2); + let vk = TestScheme::verifier_setup(&pk); + + let poly = Polynomial::::random(num_vars, &mut rng); + let point: Vec = (0..num_vars).map(|_| Fr::random(&mut rng)).collect(); + let eval = poly.evaluate(&point); + + let wrong_eval = Fr::from_bytes(data); + if wrong_eval == eval { + return; + } + + let (commitment, ()) = TestScheme::commit(poly.evaluations(), &pk); + + let mut pt = Blake2bTranscript::new(b"fuzz-wrong-eval"); + let proof = + ::open(&poly, &point, eval, &pk, None, &mut pt); + + let mut vt = Blake2bTranscript::new(b"fuzz-wrong-eval"); + let result = ::verify( + &commitment, + &point, + wrong_eval, + &proof, + &vk, + &mut vt, + ); + assert!(result.is_err(), "wrong evaluation must be rejected"); +}); diff --git a/crates/jolt-hyperkzg/src/error.rs b/crates/jolt-hyperkzg/src/error.rs new file mode 100644 index 0000000000..9a22a896b4 --- /dev/null +++ b/crates/jolt-hyperkzg/src/error.rs @@ -0,0 +1,14 @@ +//! Error types for HyperKZG operations. + +/// Errors produced by the HyperKZG commitment scheme. +#[derive(Debug, thiserror::Error)] +pub enum HyperKZGError { + #[error("SRS too small: have {have} powers, need {need}")] + SrsTooSmall { have: usize, need: usize }, + + #[error("proof verification failed")] + VerificationFailed, + + #[error("invalid proof structure: {0}")] + InvalidProof(&'static str), +} diff --git a/crates/jolt-hyperkzg/src/kzg.rs b/crates/jolt-hyperkzg/src/kzg.rs new file mode 100644 index 0000000000..c59e8cc480 --- /dev/null +++ b/crates/jolt-hyperkzg/src/kzg.rs @@ -0,0 +1,263 @@ +//! Univariate KZG primitives: commit, witness polynomial, batch open/verify. +//! +//! These are the building blocks consumed by the HyperKZG protocol. +//! All operations are generic over `P: PairingGroup`. + +#![allow(non_snake_case)] + +use jolt_crypto::{JoltGroup, PairingGroup}; +use jolt_field::Field; +use jolt_transcript::{AppendToTranscript, Transcript}; +use num_traits::{One, Zero}; +use rayon::prelude::*; + +use crate::error::HyperKZGError; +use crate::types::{HyperKZGProverSetup, HyperKZGVerifierSetup}; + +/// Commits to a polynomial (given as evaluation/coefficient vector) using MSM against SRS G1 powers. +pub(crate) fn kzg_commit( + coeffs: &[P::ScalarField], + setup: &HyperKZGProverSetup

, +) -> Result { + if setup.g1_powers.len() < coeffs.len() { + return Err(HyperKZGError::SrsTooSmall { + have: setup.g1_powers.len(), + need: coeffs.len(), + }); + } + Ok(P::G1::msm(&setup.g1_powers[..coeffs.len()], coeffs)) +} + +/// Computes the KZG witness polynomial `h(x) = f(x) / (x - u)`. +/// +/// Uses Horner's method in reverse: `h[i-1] = f[i] + h[i] * u`. +/// The remainder is `f(u)`, but we don't need it since the verifier +/// can derive it from the evaluation vectors. +pub(crate) fn compute_witness_polynomial(f: &[F], u: F) -> Vec { + let d = f.len(); + let mut h = vec![F::zero(); d]; + for i in (1..d).rev() { + h[i - 1] = f[i] + h[i] * u; + } + h +} + +/// Evaluates a polynomial (in evaluation/coefficient form) at a point. +/// +/// Standard Horner evaluation: `f(u) = f[0] + f[1]*u + f[2]*u^2 + ...` +pub(crate) fn eval_univariate(coeffs: &[F], u: F) -> F { + let mut result = F::zero(); + let mut power = F::one(); + for &c in coeffs { + result += c * power; + power *= u; + } + result +} + +/// Batch KZG opening: commits to witness polynomials for each evaluation point. +/// +/// Given polynomials `f[0..k]` and evaluation points `u[0..t]`, computes: +/// - `v[i][j]` = f_j(u_i) for all i, j +/// - Linear combination `B = sum_j q^j * f_j` using Fiat-Shamir challenge +/// - Witness commitments `w[i]` = commit(B(x) / (x - u_i)) +/// +/// Returns `(w, v)`. +pub(crate) fn kzg_open_batch( + f: &[Vec], + u: &[P::ScalarField], + setup: &HyperKZGProverSetup

, + transcript: &mut T, +) -> (Vec, Vec>) +where + P: PairingGroup, + T: Transcript, + P::ScalarField: AppendToTranscript, + P::G1: AppendToTranscript, +{ + let k = f.len(); + + // Compute evaluations v[i][j] = f_j(u_i) + let v: Vec> = u + .par_iter() + .map(|ui| f.iter().map(|fj| eval_univariate(fj, *ui)).collect()) + .collect(); + + // Absorb all evaluations into transcript + for row in &v { + for val in row { + transcript.append(val); + } + } + + // Derive batching challenge and compute powers q, q^2, ..., q^{k-1} + let q: P::ScalarField = transcript.challenge(); + let q_powers = challenge_powers(q, k); + + // B(x) = sum_j q^j * f_j(x) + let poly_len = f[0].len(); + let mut b_poly = vec![P::ScalarField::zero(); poly_len]; + for (fj, &qj) in f.iter().zip(q_powers.iter()) { + for (b, &c) in b_poly.iter_mut().zip(fj.iter()) { + *b += qj * c; + } + } + + // Compute witness polynomials and commit + let w: Vec = u + .par_iter() + .map(|ui| { + let h = compute_witness_polynomial::(&b_poly, *ui); + P::G1::msm(&setup.g1_powers[..h.len()], &h) + }) + .collect(); + + // Absorb witness commitments and derive one more challenge to keep + // prover/verifier transcripts in sync + for wi in &w { + transcript.append(wi); + } + let _: P::ScalarField = transcript.challenge(); + + (w, v) +} + +/// Batch KZG verification: checks that commitments open correctly at all points. +/// +/// Optimized for the t=3 case used by HyperKZG. The pairing check verifies: +/// `e(L, g2) == e(R, beta_g2)` +pub(crate) fn kzg_verify_batch( + vk: &HyperKZGVerifierSetup

, + com: &[P::G1], + wit: &[P::G1], + u: &[P::ScalarField], + v: &[Vec], + transcript: &mut T, +) -> bool +where + P: PairingGroup, + T: Transcript, + P::ScalarField: AppendToTranscript, + P::G1: AppendToTranscript, +{ + let k = com.len(); + + // Absorb evaluations + for row in v { + for val in row { + transcript.append(val); + } + } + + let q: P::ScalarField = transcript.challenge(); + let q_powers = challenge_powers(q, k); + + // Absorb witness commitments + for wi in wit { + transcript.append(wi); + } + let d_0: P::ScalarField = transcript.challenge(); + let d_1 = d_0 * d_0; + + assert_eq!( + wit.len(), + 3, + "HyperKZG requires exactly 3 evaluation points" + ); + + // q_power_multiplier = 1 + d_0 + d_1 + let q_power_multiplier = P::ScalarField::one() + d_0 + d_1; + let q_powers_multiplied: Vec = + q_powers.iter().map(|qp| *qp * q_power_multiplier).collect(); + + // B(u_i) = sum_j q^j * v[i][j] + let b_u: Vec = v + .iter() + .map(|v_i| { + v_i.iter() + .zip(q_powers.iter()) + .map(|(&a, &b)| a * b) + .fold(P::ScalarField::zero(), |acc, x| acc + x) + }) + .collect(); + + // L = MSM over [C_0..C_{k-1}, W_0, W_1, W_2, g1] with scalars + // [q_powers_multiplied, u_0, u_1*d_0, u_2*d_1, -(b_u[0] + d_0*b_u[1] + d_1*b_u[2])] + let mut bases = Vec::with_capacity(k + 4); + bases.extend_from_slice(&com[..k]); + bases.push(wit[0]); + bases.push(wit[1]); + bases.push(wit[2]); + bases.push(vk.g1); + + let mut scalars = Vec::with_capacity(k + 4); + scalars.extend_from_slice(&q_powers_multiplied[..k]); + scalars.push(u[0]); + scalars.push(u[1] * d_0); + scalars.push(u[2] * d_1); + scalars.push(-(b_u[0] + d_0 * b_u[1] + d_1 * b_u[2])); + + let lhs = P::G1::msm(&bases, &scalars); + + // R = W[0] + d_0*W[1] + d_1*W[2] + let rhs = wit[0] + wit[1].scalar_mul(&d_0) + wit[2].scalar_mul(&d_1); + + // e(L, g2) * e(-R, beta_g2) == identity + let result = P::multi_pairing(&[lhs, -rhs], &[vk.g2, vk.beta_g2]); + result.is_identity() +} + +/// Computes `[1, c, c^2, ..., c^{n-1}]`. +pub(crate) fn challenge_powers(c: F, n: usize) -> Vec { + let mut powers = Vec::with_capacity(n); + let mut cur = F::one(); + for _ in 0..n { + powers.push(cur); + cur *= c; + } + powers +} + +#[cfg(test)] +mod tests { + use super::*; + use jolt_field::Fr; + use num_traits::Zero; + + #[test] + fn witness_polynomial_division() { + // f(x) = 1 + 2x + 3x^2 + 4x^3 + // f(2) = 1 + 4 + 12 + 32 = 49 + // h(x) = f(x)/(x-2), so f(x) = (x-2)*h(x) + f(2) + let f = vec![ + Fr::from_u64(1), + Fr::from_u64(2), + Fr::from_u64(3), + Fr::from_u64(4), + ]; + let u = Fr::from_u64(2); + let h = compute_witness_polynomial::(&f, u); + + // Verify: (x-u)*h(x) + f(u) should reconstruct f(x) + for x_val in [0u64, 1, 3, 5, 100] { + let x = Fr::from_u64(x_val); + let fx = eval_univariate(&f, x); + let hx = eval_univariate(&h, x); + let fu = eval_univariate(&f, u); + assert_eq!(fx, (x - u) * hx + fu); + } + } + + #[test] + fn eval_univariate_at_zero() { + let f = vec![Fr::from_u64(42), Fr::from_u64(7), Fr::from_u64(3)]; + assert_eq!(eval_univariate(&f, Fr::zero()), Fr::from_u64(42)); + } + + #[test] + fn eval_univariate_linear() { + // f(x) = 3 + 5x, f(2) = 13 + let f = vec![Fr::from_u64(3), Fr::from_u64(5)]; + assert_eq!(eval_univariate(&f, Fr::from_u64(2)), Fr::from_u64(13)); + } +} diff --git a/crates/jolt-hyperkzg/src/lib.rs b/crates/jolt-hyperkzg/src/lib.rs new file mode 100644 index 0000000000..532f02d01e --- /dev/null +++ b/crates/jolt-hyperkzg/src/lib.rs @@ -0,0 +1,28 @@ +//! HyperKZG multilinear polynomial commitment scheme. +//! +//! HyperKZG reduces multilinear polynomial commitments to univariate KZG using +//! the Gemini transformation (section 2.4.2 of ), +//! operating directly on evaluation-form polynomials (no FFT/interpolation). +//! +//! This crate is generic over `PairingGroup` from `jolt-crypto` and implements +//! the `CommitmentScheme` and `AdditivelyHomomorphic` traits from `jolt-openings`. +//! +//! # Protocol overview +//! +//! 1. **Commit**: MSM of evaluations against SRS G1 powers (treating the +//! multilinear evaluation table as univariate coefficients). +//! 2. **Open** (Gemini reduction): +//! - Phase 1: Fold the multilinear polynomial `ell - 1` times, producing +//! intermediate polynomial commitments. +//! - Phase 2: Derive challenge `r` and evaluation points `[r, -r, r^2]`. +//! - Phase 3: Batch KZG opening of all intermediate polynomials at three points. +//! 3. **Verify**: Check evaluation consistency across the three evaluation vectors, +//! then batch KZG pairing check. + +pub mod error; +pub mod kzg; +pub mod scheme; +pub mod types; + +pub use scheme::HyperKZGScheme; +pub use types::{HyperKZGCommitment, HyperKZGProof, HyperKZGProverSetup, HyperKZGVerifierSetup}; diff --git a/crates/jolt-hyperkzg/src/scheme.rs b/crates/jolt-hyperkzg/src/scheme.rs new file mode 100644 index 0000000000..de5666563d --- /dev/null +++ b/crates/jolt-hyperkzg/src/scheme.rs @@ -0,0 +1,605 @@ +//! HyperKZG commitment scheme implementing `jolt-openings` traits. +//! +//! [`HyperKZGScheme`] is generic over `P: PairingGroup` — instantiate with +//! `Bn254` for the concrete BN254 curve. + +#![expect( + clippy::expect_used, + reason = "KZG operations return Result for API symmetry; with a correctly-sized SRS and well-formed inputs these errors are unreachable" +)] + +use std::marker::PhantomData; + +use jolt_crypto::{Commitment, DeriveSetup, JoltGroup, PairingGroup, PedersenSetup}; +use jolt_field::Field; +use jolt_openings::{AdditivelyHomomorphic, CommitmentScheme, OpeningsError}; +use jolt_poly::Polynomial; +use jolt_transcript::{AppendToTranscript, Label, LabelWithCount, Transcript}; +use num_traits::{One, Zero}; +use rayon::prelude::*; + +use crate::error::HyperKZGError; +use crate::kzg::{self, kzg_open_batch, kzg_verify_batch}; +use crate::types::{HyperKZGCommitment, HyperKZGProof, HyperKZGProverSetup, HyperKZGVerifierSetup}; + +/// HyperKZG multilinear polynomial commitment scheme. +/// +/// Generic over `P: PairingGroup`. Implements [`CommitmentScheme`] and +/// [`AdditivelyHomomorphic`] from `jolt-openings`. +#[derive(Clone)] +pub struct HyperKZGScheme { + _phantom: PhantomData

, +} + +impl HyperKZGScheme

+where + P::ScalarField: AppendToTranscript, + P::G1: AppendToTranscript, +{ + /// Generates an SRS from a random generator and secret scalar. + /// + /// `max_degree` is the maximum polynomial length (number of evaluations). + /// The SRS will contain `max_degree + 1` G1 powers and 2 G2 powers. + pub fn setup( + rng: &mut R, + max_degree: usize, + g1: P::G1, + g2: P::G2, + ) -> HyperKZGProverSetup

{ + let beta = P::ScalarField::random(rng); + Self::setup_from_secret(beta, max_degree, g1, g2) + } + + /// Generates SRS from a known secret (for deterministic testing). + pub fn setup_from_secret( + beta: P::ScalarField, + max_degree: usize, + g1: P::G1, + g2: P::G2, + ) -> HyperKZGProverSetup

{ + let mut g1_powers = Vec::with_capacity(max_degree + 1); + let mut cur = g1; + for _ in 0..=max_degree { + g1_powers.push(cur); + cur = cur.scalar_mul(&beta); + } + + let g2_powers = vec![g2, g2.scalar_mul(&beta)]; + + HyperKZGProverSetup { + g1_powers, + g2_powers, + } + } + + /// Phase 1 of the HyperKZG protocol: fold the multilinear polynomial. + /// + /// Given polynomial $P$ with $2^\ell$ evaluations and opening point + /// $x = (x_1, \ldots, x_\ell)$, produces $\ell$ polynomials + /// $P_0 = P, P_1, \ldots, P_{\ell-1}$ where each $P_i$ has half + /// the length of $P_{i-1}$. + /// + /// The folding relation is: + /// $P_i[j] = (1 - x_{\ell-i}) \cdot P_{i-1}[2j] + x_{\ell-i} \cdot P_{i-1}[2j+1]$ + fn fold_polynomials( + evals: &[P::ScalarField], + point: &[P::ScalarField], + ) -> Vec> { + let ell = point.len(); + let mut polys = Vec::with_capacity(ell); + polys.push(evals.to_vec()); + + for i in 0..ell - 1 { + let prev = &polys[i]; + let half = prev.len() / 2; + let xi = point[ell - i - 1]; + let mut pi = vec![P::ScalarField::zero(); half]; + pi.par_iter_mut().enumerate().for_each(|(j, pj)| { + *pj = prev[2 * j] + xi * (prev[2 * j + 1] - prev[2 * j]); + }); + polys.push(pi); + } + + polys + } + + /// Full HyperKZG opening proof. + #[tracing::instrument(skip_all, name = "HyperKZG::open")] + pub fn open>( + setup: &HyperKZGProverSetup

, + evals: &[P::ScalarField], + point: &[P::ScalarField], + transcript: &mut T, + ) -> Result, HyperKZGError> { + let ell = point.len(); + let n = evals.len(); + assert_eq!(n, 1 << ell, "evaluation count must be 2^ell"); + + // Phase 1: fold + let polys = Self::fold_polynomials(evals, point); + assert_eq!(polys.len(), ell); + assert_eq!(polys[ell - 1].len(), 2); + + // Commit to intermediate polynomials (skip polys[0] — already committed) + let com: Vec = polys[1..] + .par_iter() + .map(|p| kzg::kzg_commit::

(p, setup).expect("SRS large enough for intermediate")) + .collect(); + + // Phase 2: derive challenge r + for c in &com { + transcript.append(c); + } + let r: P::ScalarField = transcript.challenge(); + let u = vec![r, -r, r * r]; + + // Phase 3: batch open all polynomials at the three points + let (w, v) = kzg_open_batch::(&polys, &u, setup, transcript); + + Ok(HyperKZGProof { com, w, v }) + } + + /// HyperKZG verification. + #[tracing::instrument(skip_all, name = "HyperKZG::verify")] + pub fn verify>( + vk: &HyperKZGVerifierSetup

, + commitment: &HyperKZGCommitment

, + point: &[P::ScalarField], + claimed_eval: &P::ScalarField, + proof: &HyperKZGProof

, + transcript: &mut T, + ) -> Result<(), HyperKZGError> { + let ell = point.len(); + + let mut com = proof.com.clone(); + + // Absorb intermediate commitments + for c in &com { + transcript.append(c); + } + let r: P::ScalarField = transcript.challenge(); + + if r.is_zero() { + return Err(HyperKZGError::VerificationFailed); + } + + // Prepend the original commitment as C_0 + com.insert(0, commitment.point); + + let u = vec![r, -r, r * r]; + + // Validate proof dimensions + let v = &proof.v; + if v.len() != 3 { + return Err(HyperKZGError::InvalidProof("v must have 3 evaluation rows")); + } + if v[0].len() != ell || v[1].len() != ell || v[2].len() != ell { + return Err(HyperKZGError::InvalidProof( + "each v row must have ell entries", + )); + } + + let ypos = &v[0]; // evaluations at r + let yneg = &v[1]; // evaluations at -r + let mut y_sq = v[2].clone(); // evaluations at r^2 + y_sq.push(*claimed_eval); + + // Consistency check: the folding relation must hold across evaluations + // + // For each level i, the polynomial P_i is defined by: + // P_i(x) = (1 - x_{ell-i}) * P_{i-1,even}(x) + x_{ell-i} * P_{i-1,odd}(x) + // + // This implies: + // 2*r * P_{i+1}(r^2) = r * (1 - x_{ell-i-1}) * (P_i(r) + P_i(-r)) + // + x_{ell-i-1} * (P_i(r) - P_i(-r)) + let two = P::ScalarField::from_u64(2); + for i in 0..ell { + let lhs = two * r * y_sq[i + 1]; + let rhs = r * (P::ScalarField::one() - point[ell - i - 1]) * (ypos[i] + yneg[i]) + + point[ell - i - 1] * (ypos[i] - yneg[i]); + if lhs != rhs { + return Err(HyperKZGError::VerificationFailed); + } + } + + // Batch KZG pairing check + if !kzg_verify_batch::(vk, &com, &proof.w, &u, &proof.v, transcript) { + return Err(HyperKZGError::VerificationFailed); + } + + Ok(()) + } +} + +impl DeriveSetup> for PedersenSetup { + fn derive(source: &HyperKZGProverSetup

, capacity: usize) -> Self { + assert!( + source.g1_powers.len() > capacity, + "SRS has {} G1 powers, need at least {} (capacity + 1 for blinding)", + source.g1_powers.len(), + capacity + 1, + ); + let message_generators = source.g1_powers[..capacity].to_vec(); + let blinding_generator = source.g1_powers[capacity]; + PedersenSetup::new(message_generators, blinding_generator) + } +} + +impl Commitment for HyperKZGScheme

{ + type Output = HyperKZGCommitment

; +} + +impl CommitmentScheme for HyperKZGScheme

+where + P::ScalarField: AppendToTranscript, + P::G1: AppendToTranscript, +{ + type Field = P::ScalarField; + type Proof = HyperKZGProof

; + type ProverSetup = HyperKZGProverSetup

; + type VerifierSetup = HyperKZGVerifierSetup

; + type Polynomial = Polynomial; + type OpeningHint = (); + type SetupParams = (usize, P::G1, P::G2); + + fn setup( + (max_num_vars, g1, g2): Self::SetupParams, + ) -> (Self::ProverSetup, Self::VerifierSetup) { + use rand_chacha::{rand_core::SeedableRng, ChaCha20Rng}; + let mut rng = ChaCha20Rng::seed_from_u64(0); + let max_degree = 1usize << max_num_vars; + let prover = + HyperKZGScheme::setup_from_secret(P::ScalarField::random(&mut rng), max_degree, g1, g2); + let verifier = Self::verifier_setup(&prover); + (prover, verifier) + } + + fn verifier_setup(prover_setup: &Self::ProverSetup) -> Self::VerifierSetup { + HyperKZGVerifierSetup::from(prover_setup) + } + + fn commit + ?Sized>( + poly: &S, + setup: &Self::ProverSetup, + ) -> (Self::Output, Self::OpeningHint) { + // HyperKZG always works on dense evaluations. + let mut evaluations = Vec::with_capacity(1 << poly.num_vars()); + poly.for_each_row(poly.num_vars(), &mut |_, row| { + evaluations.extend_from_slice(row); + }); + let point = kzg::kzg_commit::

(&evaluations, setup) + .expect("SRS must be large enough for the polynomial"); + (HyperKZGCommitment { point }, ()) + } + + fn open( + poly: &Self::Polynomial, + point: &[Self::Field], + _eval: Self::Field, + setup: &Self::ProverSetup, + _hint: Option, + transcript: &mut impl Transcript, + ) -> Self::Proof { + Self::open(setup, poly.evaluations(), point, transcript) + .expect("HyperKZG open should not fail with valid inputs") + } + + fn verify( + commitment: &Self::Output, + point: &[Self::Field], + eval: Self::Field, + proof: &Self::Proof, + setup: &Self::VerifierSetup, + transcript: &mut impl Transcript, + ) -> Result<(), OpeningsError> { + Self::verify(setup, commitment, point, &eval, proof, transcript) + .map_err(|_| OpeningsError::VerificationFailed) + } + + fn bind_opening_inputs( + transcript: &mut impl Transcript, + point: &[Self::Field], + eval: &Self::Field, + ) { + transcript.append(&LabelWithCount( + b"hyperkzg_opening_point", + point.len() as u64, + )); + for p in point { + p.append_to_transcript(transcript); + } + transcript.append(&Label(b"hyperkzg_opening_eval")); + eval.append_to_transcript(transcript); + } +} + +impl AdditivelyHomomorphic for HyperKZGScheme

+where + P::ScalarField: AppendToTranscript, + P::G1: AppendToTranscript, +{ + fn combine(commitments: &[Self::Output], scalars: &[Self::Field]) -> Self::Output { + assert_eq!(commitments.len(), scalars.len()); + let combined = commitments + .iter() + .zip(scalars.iter()) + .map(|(c, s)| c.point.scalar_mul(s)) + .fold(P::G1::identity(), |acc, x| acc + x); + HyperKZGCommitment { point: combined } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use jolt_crypto::Bn254; + use jolt_field::Fr; + use jolt_poly::Polynomial; + use jolt_transcript::Blake2bTranscript; + use rand_chacha::ChaCha20Rng; + use rand_core::SeedableRng; + + type TestScheme = HyperKZGScheme; + + fn test_setup(max_degree: usize) -> (HyperKZGProverSetup, HyperKZGVerifierSetup) { + let mut rng = ChaCha20Rng::seed_from_u64(0xdead_beef); + let g1 = Bn254::g1_generator(); + let g2 = Bn254::g2_generator(); + let prover = TestScheme::setup(&mut rng, max_degree, g1, g2); + let verifier = TestScheme::verifier_setup(&prover); + (prover, verifier) + } + + #[test] + fn commit_open_verify_roundtrip() { + for ell in [2, 3, 4, 6, 8] { + let n = 1 << ell; + let mut rng = ChaCha20Rng::seed_from_u64(ell as u64); + let (pk, vk) = test_setup(n); + + let poly = Polynomial::::random(ell, &mut rng); + let point: Vec = (0..ell).map(|_| Fr::random(&mut rng)).collect(); + let eval = poly.evaluate(&point); + + let (commitment, ()) = TestScheme::commit(poly.evaluations(), &pk); + + let mut prover_transcript = Blake2bTranscript::new(b"test"); + let proof = ::open( + &poly, + &point, + eval, + &pk, + None, + &mut prover_transcript, + ); + + let mut verifier_transcript = Blake2bTranscript::new(b"test"); + let result = ::verify( + &commitment, + &point, + eval, + &proof, + &vk, + &mut verifier_transcript, + ); + assert!(result.is_ok(), "ell={ell}: verification failed: {result:?}"); + } + } + + #[test] + fn wrong_eval_rejects() { + let ell = 4; + let n = 1 << ell; + let mut rng = ChaCha20Rng::seed_from_u64(42); + let (pk, vk) = test_setup(n); + + let poly = Polynomial::::random(ell, &mut rng); + let point: Vec = (0..ell).map(|_| Fr::random(&mut rng)).collect(); + let eval = poly.evaluate(&point); + let wrong_eval = eval + Fr::from_u64(1); + + let (commitment, ()) = TestScheme::commit(poly.evaluations(), &pk); + + let mut prover_transcript = Blake2bTranscript::new(b"test-bad"); + let proof = ::open( + &poly, + &point, + eval, + &pk, + None, + &mut prover_transcript, + ); + + let mut verifier_transcript = Blake2bTranscript::new(b"test-bad"); + let result = ::verify( + &commitment, + &point, + wrong_eval, + &proof, + &vk, + &mut verifier_transcript, + ); + assert!(result.is_err(), "wrong evaluation should be rejected"); + } + + #[test] + fn tampered_proof_rejects() { + let ell = 4; + let n = 1 << ell; + let mut rng = ChaCha20Rng::seed_from_u64(99); + let (pk, vk) = test_setup(n); + + let poly = Polynomial::::random(ell, &mut rng); + let point: Vec = (0..ell).map(|_| Fr::random(&mut rng)).collect(); + let eval = poly.evaluate(&point); + + let (commitment, ()) = TestScheme::commit(poly.evaluations(), &pk); + + let mut prover_transcript = Blake2bTranscript::new(b"test-tamper"); + let mut proof = ::open( + &poly, + &point, + eval, + &pk, + None, + &mut prover_transcript, + ); + + // Tamper with proof: swap v[0] and v[1] + let v1 = proof.v[1].clone(); + proof.v[0].clone_from(&v1); + + let mut verifier_transcript = Blake2bTranscript::new(b"test-tamper"); + let result = ::verify( + &commitment, + &point, + eval, + &proof, + &vk, + &mut verifier_transcript, + ); + assert!(result.is_err(), "tampered proof should be rejected"); + } + + #[test] + fn combine_is_homomorphic() { + let ell = 3; + let n = 1 << ell; + let mut rng = ChaCha20Rng::seed_from_u64(300); + let (pk, _vk) = test_setup(n); + + let poly_a = Polynomial::::random(ell, &mut rng); + let poly_b = Polynomial::::random(ell, &mut rng); + + let (ca, ()) = TestScheme::commit(poly_a.evaluations(), &pk); + let (cb, ()) = TestScheme::commit(poly_b.evaluations(), &pk); + + let sum_evals: Vec = poly_a + .evaluations() + .iter() + .zip(poly_b.evaluations().iter()) + .map(|(a, b)| *a + *b) + .collect(); + let (c_sum_direct, ()) = TestScheme::commit(&sum_evals, &pk); + + let c_sum_combined = TestScheme::combine(&[ca, cb], &[Fr::from_u64(1), Fr::from_u64(1)]); + + assert_eq!( + c_sum_direct, c_sum_combined, + "combine([1,1]) must match commitment to sum" + ); + } + + #[test] + fn combine_with_scalars() { + let ell = 3; + let n = 1 << ell; + let mut rng = ChaCha20Rng::seed_from_u64(400); + let (pk, _vk) = test_setup(n); + + let poly_a = Polynomial::::random(ell, &mut rng); + let poly_b = Polynomial::::random(ell, &mut rng); + let s_a = Fr::random(&mut rng); + let s_b = Fr::random(&mut rng); + + let (ca, ()) = TestScheme::commit(poly_a.evaluations(), &pk); + let (cb, ()) = TestScheme::commit(poly_b.evaluations(), &pk); + + let combined_evals: Vec = poly_a + .evaluations() + .iter() + .zip(poly_b.evaluations().iter()) + .map(|(a, b)| s_a * *a + s_b * *b) + .collect(); + let (c_direct, ()) = TestScheme::commit(&combined_evals, &pk); + + let c_combined = TestScheme::combine(&[ca, cb], &[s_a, s_b]); + + assert_eq!(c_direct, c_combined); + } + + #[test] + fn open_verify_with_random_points() { + let mut rng = ChaCha20Rng::seed_from_u64(0xcafe); + + for _ in 0..5 { + let ell = 4; + let n = 1 << ell; + let (pk, vk) = test_setup(n); + + let poly = Polynomial::::random(ell, &mut rng); + let point: Vec = (0..ell).map(|_| Fr::random(&mut rng)).collect(); + let eval = poly.evaluate(&point); + + let (commitment, ()) = TestScheme::commit(poly.evaluations(), &pk); + + let mut pt = Blake2bTranscript::new(b"rand-test"); + let proof = + ::open(&poly, &point, eval, &pk, None, &mut pt); + + let mut vt = Blake2bTranscript::new(b"rand-test"); + ::verify( + &commitment, + &point, + eval, + &proof, + &vk, + &mut vt, + ) + .expect("random instance should verify"); + } + } + + #[test] + fn extract_vc_setup_produces_valid_pedersen() { + use jolt_crypto::{Pedersen, VectorCommitment}; + + let n = 1 << 4; + let (pk, _vk) = test_setup(n); + + let capacity = 5; + let vc_setup = PedersenSetup::::derive(&pk, capacity); + + assert_eq!( + as VectorCommitment>::capacity(&vc_setup), + capacity, + ); + + // Commit and verify a small vector. + let values = vec![Fr::one(), Fr::from_u64(2), Fr::from_u64(3)]; + let blinding = Fr::from_u64(42); + let commitment = as VectorCommitment>::commit( + &vc_setup, &values, &blinding, + ); + assert!( + as VectorCommitment>::verify( + &vc_setup, + &commitment, + &values, + &blinding, + ) + ); + } + + #[test] + fn trivial_polynomial() { + // 1-variable polynomial: [a, b] + let ell = 1; + let n = 1 << ell; + let mut rng = ChaCha20Rng::seed_from_u64(777); + let (pk, vk) = test_setup(n); + + let poly = Polynomial::::random(ell, &mut rng); + let point: Vec = (0..ell).map(|_| Fr::random(&mut rng)).collect(); + let eval = poly.evaluate(&point); + + let (commitment, ()) = TestScheme::commit(poly.evaluations(), &pk); + + let mut pt = Blake2bTranscript::new(b"trivial"); + let proof = ::open(&poly, &point, eval, &pk, None, &mut pt); + + let mut vt = Blake2bTranscript::new(b"trivial"); + ::verify(&commitment, &point, eval, &proof, &vk, &mut vt) + .expect("trivial polynomial should verify"); + } +} diff --git a/crates/jolt-hyperkzg/src/types.rs b/crates/jolt-hyperkzg/src/types.rs new file mode 100644 index 0000000000..f482172ff0 --- /dev/null +++ b/crates/jolt-hyperkzg/src/types.rs @@ -0,0 +1,118 @@ +//! Commitment, proof, and setup types for HyperKZG. +//! +//! All types are generic over `P: PairingGroup` — no arkworks leakage. + +use jolt_crypto::{HomomorphicCommitment, JoltGroup, PairingGroup}; +use serde::{Deserialize, Serialize}; + +/// Commitment to a multilinear polynomial: a single G1 element. +#[derive(Serialize, Deserialize)] +#[serde(bound( + serialize = "P::G1: Serialize", + deserialize = "P::G1: for<'a> Deserialize<'a>" +))] +pub struct HyperKZGCommitment { + pub(crate) point: P::G1, +} + +impl Copy for HyperKZGCommitment

{} + +#[expect( + clippy::expl_impl_clone_on_copy, + reason = "explicit impl is required because PairingGroup is not bounded by Clone" +)] +impl Clone for HyperKZGCommitment

{ + fn clone(&self) -> Self { + *self + } +} + +impl std::fmt::Debug for HyperKZGCommitment

{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("HyperKZGCommitment") + .field("point", &self.point) + .finish() + } +} + +impl PartialEq for HyperKZGCommitment

{ + fn eq(&self, other: &Self) -> bool { + self.point == other.point + } +} + +impl Eq for HyperKZGCommitment

{} + +impl HomomorphicCommitment for HyperKZGCommitment

{ + #[inline] + fn linear_combine(c1: &Self, c2: &Self, scalar: &F) -> Self { + Self { + point: HomomorphicCommitment::linear_combine(&c1.point, &c2.point, scalar), + } + } +} + +impl Default for HyperKZGCommitment

{ + fn default() -> Self { + Self { + point: P::G1::identity(), + } + } +} + +/// Opening proof for the HyperKZG protocol. +/// +/// - `com`: intermediate polynomial commitments from the Gemini folding (ell - 1 elements) +/// - `w`: KZG witness commitments for the three evaluation points `[r, -r, r^2]` +/// - `v`: evaluations of all intermediate polynomials at the three points +/// (`v[t][k]` = polynomial k evaluated at point t) +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(bound( + serialize = "P::G1: Serialize, P::ScalarField: Serialize", + deserialize = "P::G1: for<'a> Deserialize<'a>, P::ScalarField: for<'a> Deserialize<'a>" +))] +pub struct HyperKZGProof { + pub com: Vec, + pub w: Vec, + pub v: Vec>, +} + +/// Prover setup: SRS G1 and G2 powers. +/// +/// G1 powers: `[g1, beta * g1, beta^2 * g1, ..., beta^n * g1]` +/// G2 powers: `[g2, beta * g2]` (only two needed for KZG verification). +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(bound( + serialize = "P::G1: Serialize, P::G2: Serialize", + deserialize = "P::G1: for<'a> Deserialize<'a>, P::G2: for<'a> Deserialize<'a>" +))] +pub struct HyperKZGProverSetup { + pub(crate) g1_powers: Vec, + pub(crate) g2_powers: Vec, +} + +/// Verifier setup: the four G1/G2 elements needed for pairing checks. +/// +/// - `g1`: generator $g$ +/// - `g2`: generator $h$ +/// - `beta_g2`: $\beta \cdot h$ (for KZG pairing check) +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +#[serde(bound( + serialize = "P::G1: Serialize, P::G2: Serialize", + deserialize = "P::G1: for<'a> Deserialize<'a>, P::G2: for<'a> Deserialize<'a>" +))] +pub struct HyperKZGVerifierSetup { + pub(crate) g1: P::G1, + pub(crate) g2: P::G2, + pub(crate) beta_g2: P::G2, +} + +impl From<&HyperKZGProverSetup

> for HyperKZGVerifierSetup

{ + fn from(prover: &HyperKZGProverSetup

) -> Self { + Self { + g1: prover.g1_powers[0], + g2: prover.g2_powers[0], + beta_g2: prover.g2_powers[1], + } + } +} diff --git a/crates/jolt-hyperkzg/tests/commit_open_verify.rs b/crates/jolt-hyperkzg/tests/commit_open_verify.rs new file mode 100644 index 0000000000..9ee2e6eba2 --- /dev/null +++ b/crates/jolt-hyperkzg/tests/commit_open_verify.rs @@ -0,0 +1,224 @@ +//! Integration tests for HyperKZG commit → open → verify pipeline with BN254. + +#![expect(clippy::expect_used, reason = "tests may panic on assertion failures")] + +use jolt_crypto::Bn254; +use jolt_field::{Field, Fr}; +use jolt_hyperkzg::{HyperKZGProverSetup, HyperKZGScheme, HyperKZGVerifierSetup}; +use jolt_openings::{AdditivelyHomomorphic, CommitmentScheme}; +use jolt_poly::Polynomial; +use jolt_transcript::{Blake2bTranscript, Transcript}; +use rand_chacha::ChaCha20Rng; +use rand_core::SeedableRng; + +type KzgPCS = HyperKZGScheme; + +fn make_setup(max_degree: usize) -> (HyperKZGProverSetup, HyperKZGVerifierSetup) { + let mut rng = ChaCha20Rng::seed_from_u64(0xdead_beef); + let g1 = Bn254::g1_generator(); + let g2 = Bn254::g2_generator(); + let pk = KzgPCS::setup(&mut rng, max_degree, g1, g2); + let vk = KzgPCS::verifier_setup(&pk); + (pk, vk) +} + +fn commit_open_verify( + poly: &Polynomial, + point: &[Fr], + pk: &HyperKZGProverSetup, + vk: &HyperKZGVerifierSetup, + label: &'static [u8], +) { + let eval = poly.evaluate(point); + let (commitment, ()) = ::commit(poly.evaluations(), pk); + + let mut t_p = Blake2bTranscript::new(label); + let proof = ::open(poly, point, eval, pk, None, &mut t_p); + + let mut t_v = Blake2bTranscript::new(label); + ::verify(&commitment, point, eval, &proof, vk, &mut t_v) + .expect("verification should succeed"); +} + +// Basic roundtrip for various polynomial sizes + +#[test] +fn roundtrip_num_vars_1_to_8() { + let mut rng = ChaCha20Rng::seed_from_u64(1000); + for nv in 1..=8 { + let (pk, vk) = make_setup(1 << nv); + let poly = Polynomial::::random(nv, &mut rng); + let point: Vec = (0..nv).map(|_| Fr::random(&mut rng)).collect(); + commit_open_verify(&poly, &point, &pk, &vk, b"kzg-sizes"); + } +} + +// Edge cases + +/// All-zero polynomial commits to identity point and still verifies. +#[test] +fn zero_polynomial_roundtrip() { + let nv = 3; + let (pk, vk) = make_setup(1 << nv); + let poly = Polynomial::::zeros(nv); + let point = vec![Fr::from_u64(42); nv]; + commit_open_verify(&poly, &point, &pk, &vk, b"kzg-zero"); +} + +/// Single-variable polynomial (2 evaluations). +#[test] +fn single_variable_polynomial() { + let mut rng = ChaCha20Rng::seed_from_u64(2000); + let (pk, vk) = make_setup(2); + let poly = Polynomial::::random(1, &mut rng); + let point = vec![Fr::random(&mut rng)]; + commit_open_verify(&poly, &point, &pk, &vk, b"kzg-single-var"); +} + +/// Constant polynomial (all evaluations are the same value). +#[test] +fn constant_polynomial() { + let nv = 3; + let (pk, vk) = make_setup(1 << nv); + let val = Fr::from_u64(42); + let poly = Polynomial::new(vec![val; 1 << nv]); + let mut rng = ChaCha20Rng::seed_from_u64(2001); + let point: Vec = (0..nv).map(|_| Fr::random(&mut rng)).collect(); + commit_open_verify(&poly, &point, &pk, &vk, b"kzg-constant"); +} + +// Wrong evaluation rejection + +#[test] +fn wrong_eval_rejected() { + let mut rng = ChaCha20Rng::seed_from_u64(3000); + let nv = 4; + let (pk, vk) = make_setup(1 << nv); + let poly = Polynomial::::random(nv, &mut rng); + let point: Vec = (0..nv).map(|_| Fr::random(&mut rng)).collect(); + + let correct_eval = poly.evaluate(&point); + let wrong_eval = correct_eval + Fr::from_u64(1); + let (commitment, ()) = ::commit(poly.evaluations(), &pk); + + // Prover opens with correct eval + let mut t_p = Blake2bTranscript::new(b"kzg-wrong"); + let proof = + ::open(&poly, &point, correct_eval, &pk, None, &mut t_p); + + // Verifier checks with wrong eval + let mut t_v = Blake2bTranscript::new(b"kzg-wrong"); + let result = ::verify( + &commitment, + &point, + wrong_eval, + &proof, + &vk, + &mut t_v, + ); + assert!(result.is_err(), "wrong evaluation must be rejected"); +} + +// Homomorphic properties + +/// combine([C_a, C_b], [1, 1]) == commit(a + b). +#[test] +fn homomorphic_sum() { + let mut rng = ChaCha20Rng::seed_from_u64(4000); + let nv = 4; + let (pk, vk) = make_setup(1 << nv); + let a = Polynomial::::random(nv, &mut rng); + let b = Polynomial::::random(nv, &mut rng); + + let (com_a, ()) = ::commit(a.evaluations(), &pk); + let (com_b, ()) = ::commit(b.evaluations(), &pk); + let combined_com = ::combine( + &[com_a, com_b], + &[Fr::from_u64(1), Fr::from_u64(1)], + ); + + let sum_poly = a + b; + let point: Vec = (0..nv).map(|_| Fr::random(&mut rng)).collect(); + let eval = sum_poly.evaluate(&point); + + let mut t_p = Blake2bTranscript::new(b"kzg-homo"); + let proof = ::open(&sum_poly, &point, eval, &pk, None, &mut t_p); + + let mut t_v = Blake2bTranscript::new(b"kzg-homo"); + ::verify(&combined_com, &point, eval, &proof, &vk, &mut t_v) + .expect("homomorphic sum must verify"); +} + +/// combine with arbitrary scalars: s_a·C_a + s_b·C_b == commit(s_a·a + s_b·b). +#[test] +fn homomorphic_weighted_combination() { + let mut rng = ChaCha20Rng::seed_from_u64(4001); + let nv = 3; + let (pk, vk) = make_setup(1 << nv); + let a = Polynomial::::random(nv, &mut rng); + let b = Polynomial::::random(nv, &mut rng); + let s_a = Fr::random(&mut rng); + let s_b = Fr::random(&mut rng); + + let (com_a, ()) = ::commit(a.evaluations(), &pk); + let (com_b, ()) = ::commit(b.evaluations(), &pk); + let combined_com = ::combine(&[com_a, com_b], &[s_a, s_b]); + + let weighted_poly = a * s_a + b * s_b; + let point: Vec = (0..nv).map(|_| Fr::random(&mut rng)).collect(); + let eval = weighted_poly.evaluate(&point); + + let mut t_p = Blake2bTranscript::new(b"kzg-weighted"); + let proof = + ::open(&weighted_poly, &point, eval, &pk, None, &mut t_p); + + let mut t_v = Blake2bTranscript::new(b"kzg-weighted"); + ::verify(&combined_com, &point, eval, &proof, &vk, &mut t_v) + .expect("weighted combination must verify"); +} + +// Deterministic setup + +#[test] +fn deterministic_setup_from_secret() { + let g1 = Bn254::g1_generator(); + let g2 = Bn254::g2_generator(); + let beta = Fr::from_u64(12345); + + let pk1 = KzgPCS::setup_from_secret(beta, 16, g1, g2); + let pk2 = KzgPCS::setup_from_secret(beta, 16, g1, g2); + let _vk1 = KzgPCS::verifier_setup(&pk1); + let vk2 = KzgPCS::verifier_setup(&pk2); + + // Same setup yields same commitments + let poly = Polynomial::new(vec![Fr::from_u64(1), Fr::from_u64(2)]); + let (com1, ()) = ::commit(poly.evaluations(), &pk1); + let (com2, ()) = ::commit(poly.evaluations(), &pk2); + assert_eq!( + com1, com2, + "deterministic setups must produce same commitments" + ); + + // Verify with either setup + let point = vec![Fr::from_u64(7)]; + let eval = poly.evaluate(&point); + let mut t = Blake2bTranscript::new(b"det-setup"); + let proof = ::open(&poly, &point, eval, &pk1, None, &mut t); + let mut t = Blake2bTranscript::new(b"det-setup"); + ::verify(&com1, &point, eval, &proof, &vk2, &mut t) + .expect("cross-setup verification must work"); +} + +// Property test: random polynomials always verify + +#[test] +fn property_random_polynomials_always_verify() { + for seed in 5000..5010 { + let mut rng = ChaCha20Rng::seed_from_u64(seed); + let nv = 2 + (seed as usize % 5); // 2..6 + let (pk, vk) = make_setup(1 << nv); + let poly = Polynomial::::random(nv, &mut rng); + let point: Vec = (0..nv).map(|_| Fr::random(&mut rng)).collect(); + commit_open_verify(&poly, &point, &pk, &vk, b"kzg-property"); + } +} From 65f757058d61520f8573271a2a12d79c2d9650cb Mon Sep 17 00:00:00 2001 From: Andrew Tretyakov <42178850+0xAndoroid@users.noreply.github.com> Date: Thu, 7 May 2026 10:27:16 -0400 Subject: [PATCH 02/14] fix(hyperkzg): harden verifier proof validation --- crates/jolt-hyperkzg/Cargo.toml | 2 +- crates/jolt-hyperkzg/benches/hyperkzg.rs | 20 ++- crates/jolt-hyperkzg/src/kzg.rs | 14 +- crates/jolt-hyperkzg/src/scheme.rs | 136 +++++++++++++++--- .../jolt-hyperkzg/tests/commit_open_verify.rs | 2 +- 5 files changed, 131 insertions(+), 43 deletions(-) diff --git a/crates/jolt-hyperkzg/Cargo.toml b/crates/jolt-hyperkzg/Cargo.toml index 2e88a335f9..9986c5f33f 100644 --- a/crates/jolt-hyperkzg/Cargo.toml +++ b/crates/jolt-hyperkzg/Cargo.toml @@ -19,7 +19,7 @@ tracing.workspace = true num-traits = { workspace = true } rayon = { workspace = true } thiserror = { workspace = true } -rand_core = { workspace = true } +rand_core = { workspace = true, features = ["getrandom"] } rand_chacha = { workspace = true } [dev-dependencies] diff --git a/crates/jolt-hyperkzg/benches/hyperkzg.rs b/crates/jolt-hyperkzg/benches/hyperkzg.rs index 82883916b1..27c587e741 100644 --- a/crates/jolt-hyperkzg/benches/hyperkzg.rs +++ b/crates/jolt-hyperkzg/benches/hyperkzg.rs @@ -1,9 +1,7 @@ -#![allow(unused_results)] - use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; use jolt_crypto::Bn254; -use jolt_field::{Field, Fr}; +use jolt_field::{Fr, RandomSampling}; use jolt_hyperkzg::{HyperKZGProverSetup, HyperKZGScheme, HyperKZGVerifierSetup}; use jolt_openings::{AdditivelyHomomorphic, CommitmentScheme}; use jolt_poly::Polynomial; @@ -27,7 +25,7 @@ fn bench_commit(c: &mut Criterion) { for num_vars in [8, 10, 12, 14] { let n = 1 << num_vars; let (pk, _) = make_setup(n); - group.bench_with_input( + let _ = group.bench_with_input( BenchmarkId::from_parameter(num_vars), &num_vars, |b, &nv| { @@ -50,7 +48,7 @@ fn bench_open(c: &mut Criterion) { for num_vars in [8, 10, 12, 14] { let n = 1 << num_vars; let (pk, _) = make_setup(n); - group.bench_with_input( + let _ = group.bench_with_input( BenchmarkId::from_parameter(num_vars), &num_vars, |b, &nv| { @@ -58,8 +56,7 @@ fn bench_open(c: &mut Criterion) { || { let mut rng = ChaCha20Rng::seed_from_u64(0); let poly = Polynomial::::random(nv, &mut rng); - let point: Vec = - (0..nv).map(|_| ::random(&mut rng)).collect(); + let point: Vec = (0..nv).map(|_| Fr::random(&mut rng)).collect(); let eval = poly.evaluate(&point); (poly, point, eval) }, @@ -87,7 +84,7 @@ fn bench_verify(c: &mut Criterion) { for num_vars in [8, 10, 12, 14] { let n = 1 << num_vars; let (pk, vk) = make_setup(n); - group.bench_with_input( + let _ = group.bench_with_input( BenchmarkId::from_parameter(num_vars), &num_vars, |b, &nv| { @@ -95,8 +92,7 @@ fn bench_verify(c: &mut Criterion) { || { let mut rng = ChaCha20Rng::seed_from_u64(0); let poly = Polynomial::::random(nv, &mut rng); - let point: Vec = - (0..nv).map(|_| ::random(&mut rng)).collect(); + let point: Vec = (0..nv).map(|_| Fr::random(&mut rng)).collect(); let eval = poly.evaluate(&point); let (commitment, ()) = TestScheme::commit(poly.evaluations(), &pk); let mut transcript = @@ -148,7 +144,7 @@ fn bench_combine(c: &mut Criterion) { .collect(); let scalars: Vec = (0..count).map(|_| Fr::random(&mut rng)).collect(); - group.bench_with_input(BenchmarkId::from_parameter(count), &count, |b, _| { + let _ = group.bench_with_input(BenchmarkId::from_parameter(count), &count, |b, _| { b.iter(|| TestScheme::combine(&commitments, &scalars)); }); } @@ -159,7 +155,7 @@ fn bench_setup(c: &mut Criterion) { let mut group = c.benchmark_group("hyperkzg_setup"); for num_vars in [8, 10, 12] { let n = 1 << num_vars; - group.bench_with_input(BenchmarkId::from_parameter(num_vars), &num_vars, |b, _| { + let _ = group.bench_with_input(BenchmarkId::from_parameter(num_vars), &num_vars, |b, _| { b.iter(|| { let mut rng = ChaCha20Rng::seed_from_u64(0xbe0c); let g1 = Bn254::g1_generator(); diff --git a/crates/jolt-hyperkzg/src/kzg.rs b/crates/jolt-hyperkzg/src/kzg.rs index c59e8cc480..ef6694df65 100644 --- a/crates/jolt-hyperkzg/src/kzg.rs +++ b/crates/jolt-hyperkzg/src/kzg.rs @@ -3,8 +3,6 @@ //! These are the building blocks consumed by the HyperKZG protocol. //! All operations are generic over `P: PairingGroup`. -#![allow(non_snake_case)] - use jolt_crypto::{JoltGroup, PairingGroup}; use jolt_field::Field; use jolt_transcript::{AppendToTranscript, Transcript}; @@ -142,6 +140,10 @@ where { let k = com.len(); + if wit.len() != 3 || u.len() != 3 || v.len() != 3 || v.iter().any(|row| row.len() != k) { + return false; + } + // Absorb evaluations for row in v { for val in row { @@ -159,12 +161,6 @@ where let d_0: P::ScalarField = transcript.challenge(); let d_1 = d_0 * d_0; - assert_eq!( - wit.len(), - 3, - "HyperKZG requires exactly 3 evaluation points" - ); - // q_power_multiplier = 1 + d_0 + d_1 let q_power_multiplier = P::ScalarField::one() + d_0 + d_1; let q_powers_multiplied: Vec = @@ -221,7 +217,7 @@ pub(crate) fn challenge_powers(c: F, n: usize) -> Vec { #[cfg(test)] mod tests { use super::*; - use jolt_field::Fr; + use jolt_field::{Fr, FromPrimitiveInt}; use num_traits::Zero; #[test] diff --git a/crates/jolt-hyperkzg/src/scheme.rs b/crates/jolt-hyperkzg/src/scheme.rs index de5666563d..05b46f6f92 100644 --- a/crates/jolt-hyperkzg/src/scheme.rs +++ b/crates/jolt-hyperkzg/src/scheme.rs @@ -11,7 +11,7 @@ use std::marker::PhantomData; use jolt_crypto::{Commitment, DeriveSetup, JoltGroup, PairingGroup, PedersenSetup}; -use jolt_field::Field; +use jolt_field::{FromPrimitiveInt, RandomSampling}; use jolt_openings::{AdditivelyHomomorphic, CommitmentScheme, OpeningsError}; use jolt_poly::Polynomial; use jolt_transcript::{AppendToTranscript, Label, LabelWithCount, Transcript}; @@ -50,7 +50,11 @@ where Self::setup_from_secret(beta, max_degree, g1, g2) } - /// Generates SRS from a known secret (for deterministic testing). + /// Generates SRS from a known secret. + /// + /// WARNING: this is only appropriate for deterministic tests or trusted + /// setup tooling that destroys `beta`; anyone who knows `beta` can break + /// KZG binding. pub fn setup_from_secret( beta: P::ScalarField, max_degree: usize, @@ -151,10 +155,30 @@ where ) -> Result<(), HyperKZGError> { let ell = point.len(); - let mut com = proof.com.clone(); + if proof.com.len() + 1 != ell { + return Err(HyperKZGError::InvalidProof( + "com must contain ell - 1 intermediate commitments", + )); + } + + // Validate proof dimensions before mutating the transcript. + let v = &proof.v; + if v.len() != 3 { + return Err(HyperKZGError::InvalidProof("v must have 3 evaluation rows")); + } + if v[0].len() != ell || v[1].len() != ell || v[2].len() != ell { + return Err(HyperKZGError::InvalidProof( + "each v row must have ell entries", + )); + } + if proof.w.len() != 3 { + return Err(HyperKZGError::InvalidProof( + "w must have 3 witness commitments", + )); + } // Absorb intermediate commitments - for c in &com { + for c in &proof.com { transcript.append(c); } let r: P::ScalarField = transcript.challenge(); @@ -164,21 +188,12 @@ where } // Prepend the original commitment as C_0 - com.insert(0, commitment.point); + let mut com = Vec::with_capacity(ell); + com.push(commitment.point); + com.extend_from_slice(&proof.com); let u = vec![r, -r, r * r]; - // Validate proof dimensions - let v = &proof.v; - if v.len() != 3 { - return Err(HyperKZGError::InvalidProof("v must have 3 evaluation rows")); - } - if v[0].len() != ell || v[1].len() != ell || v[2].len() != ell { - return Err(HyperKZGError::InvalidProof( - "each v row must have ell entries", - )); - } - let ypos = &v[0]; // evaluations at r let yneg = &v[1]; // evaluations at -r let mut y_sq = v[2].clone(); // evaluations at r^2 @@ -245,11 +260,9 @@ where fn setup( (max_num_vars, g1, g2): Self::SetupParams, ) -> (Self::ProverSetup, Self::VerifierSetup) { - use rand_chacha::{rand_core::SeedableRng, ChaCha20Rng}; - let mut rng = ChaCha20Rng::seed_from_u64(0); + let mut rng = rand_core::OsRng; let max_degree = 1usize << max_num_vars; - let prover = - HyperKZGScheme::setup_from_secret(P::ScalarField::random(&mut rng), max_degree, g1, g2); + let prover = HyperKZGScheme::setup(&mut rng, max_degree, g1, g2); let verifier = Self::verifier_setup(&prover); (prover, verifier) } @@ -422,6 +435,89 @@ mod tests { assert!(result.is_err(), "wrong evaluation should be rejected"); } + #[test] + fn missing_intermediate_commitment_rejects() { + let ell = 4; + let n = 1 << ell; + let mut rng = ChaCha20Rng::seed_from_u64(43); + let (pk, vk) = test_setup(n); + + let poly = Polynomial::::random(ell, &mut rng); + let point: Vec = (0..ell).map(|_| Fr::random(&mut rng)).collect(); + let eval = poly.evaluate(&point); + + let (commitment, ()) = TestScheme::commit(poly.evaluations(), &pk); + + let mut prover_transcript = Blake2bTranscript::new(b"test-missing-com"); + let mut proof = ::open( + &poly, + &point, + eval, + &pk, + None, + &mut prover_transcript, + ); + let _ = proof.com.pop(); + + let mut verifier_transcript = Blake2bTranscript::new(b"test-missing-com"); + let result = TestScheme::verify( + &vk, + &commitment, + &point, + &eval, + &proof, + &mut verifier_transcript, + ); + assert!(matches!(result, Err(HyperKZGError::InvalidProof(_)))); + } + + #[test] + fn malformed_witness_commitments_reject_without_panic() { + let ell = 4; + let n = 1 << ell; + let mut rng = ChaCha20Rng::seed_from_u64(44); + let (pk, vk) = test_setup(n); + + let poly = Polynomial::::random(ell, &mut rng); + let point: Vec = (0..ell).map(|_| Fr::random(&mut rng)).collect(); + let eval = poly.evaluate(&point); + + let (commitment, ()) = TestScheme::commit(poly.evaluations(), &pk); + + let mut prover_transcript = Blake2bTranscript::new(b"test-short-w"); + let mut proof = ::open( + &poly, + &point, + eval, + &pk, + None, + &mut prover_transcript, + ); + let _ = proof.w.pop(); + + let mut verifier_transcript = Blake2bTranscript::new(b"test-short-w"); + let result = TestScheme::verify( + &vk, + &commitment, + &point, + &eval, + &proof, + &mut verifier_transcript, + ); + assert!(matches!(result, Err(HyperKZGError::InvalidProof(_)))); + } + + #[test] + fn trait_setup_uses_fresh_randomness() { + let g1 = Bn254::g1_generator(); + let g2 = Bn254::g2_generator(); + + let (_pk1, vk1) = ::setup((4, g1, g2)); + let (_pk2, vk2) = ::setup((4, g1, g2)); + + assert_ne!(vk1.beta_g2, vk2.beta_g2); + } + #[test] fn tampered_proof_rejects() { let ell = 4; diff --git a/crates/jolt-hyperkzg/tests/commit_open_verify.rs b/crates/jolt-hyperkzg/tests/commit_open_verify.rs index 9ee2e6eba2..52a8376880 100644 --- a/crates/jolt-hyperkzg/tests/commit_open_verify.rs +++ b/crates/jolt-hyperkzg/tests/commit_open_verify.rs @@ -3,7 +3,7 @@ #![expect(clippy::expect_used, reason = "tests may panic on assertion failures")] use jolt_crypto::Bn254; -use jolt_field::{Field, Fr}; +use jolt_field::{Fr, FromPrimitiveInt, RandomSampling}; use jolt_hyperkzg::{HyperKZGProverSetup, HyperKZGScheme, HyperKZGVerifierSetup}; use jolt_openings::{AdditivelyHomomorphic, CommitmentScheme}; use jolt_poly::Polynomial; From 01d21ccbe6ebcb5f5e667f2855436adb7fbb4970 Mon Sep 17 00:00:00 2001 From: Markos Georghiades <53157953+Markos-The-G@users.noreply.github.com> Date: Fri, 8 May 2026 00:01:23 -0400 Subject: [PATCH 03/14] feat(jolt-witness): add witness crate and modular helpers Adds the jolt-witness crate and the supporting modular crate APIs needed before landing the Bolt and generated-code stack. The new witness crate centralizes Bolt-facing witness/oracle helpers for commitment trace inputs, one-hot chunk materialization, sparse stage 4/5 trace data, stage 6 bytecode/read-RAF/booleanity inputs, and small deterministic oracle helpers used by generated tests. This also moves the primitive modular crates onto the semantic surface expected by Bolt-generated code: a simplified jolt-field trait bundle, transcript byte-length accounting and MockTranscript, reusable polynomial/source helpers, R1CS row-dot helpers, trace extraction over CycleRow, canonical lookup-table ordering/names, and sumcheck verifier helper modules. This intentionally does not include the PCS prover/verifier split, Bolt itself, generated prover/verifier/kernel crates, or jolt-equivalence/CI wiring. Validation: - cargo clippy -p jolt-witness -p jolt-poly -p jolt-r1cs -p jolt-trace -p jolt-transcript -p jolt-lookup-tables -p jolt-riscv -p jolt-crypto -p jolt-sumcheck -p jolt-openings -p jolt-dory -p jolt-hyperkzg -q --all-targets -- -D warnings - cargo nextest run -p jolt-witness -p jolt-poly -p jolt-r1cs -p jolt-trace -p jolt-transcript -p jolt-lookup-tables -p jolt-riscv -p jolt-crypto -p jolt-sumcheck -p jolt-openings -p jolt-dory -p jolt-hyperkzg --cargo-quiet --- Cargo.lock | 13 +- Cargo.toml | 3 + crates/jolt-crypto/benches/crypto.rs | 2 +- .../fuzz/fuzz_targets/group_arith.rs | 6 +- .../fuzz/fuzz_targets/pedersen_commit.rs | 6 +- crates/jolt-crypto/src/ec/bn254/gt.rs | 5 + crates/jolt-crypto/src/ec/bn254/mod.rs | 8 +- crates/jolt-crypto/tests/coverage.rs | 2 +- crates/jolt-crypto/tests/group_laws.rs | 2 +- crates/jolt-crypto/tests/pairing.rs | 2 +- crates/jolt-crypto/tests/pedersen.rs | 2 +- crates/jolt-crypto/tests/serialization.rs | 2 +- crates/jolt-dory/benches/dory.rs | 24 +- crates/jolt-dory/src/scheme.rs | 76 +- crates/jolt-dory/src/streaming.rs | 123 +- crates/jolt-dory/src/types.rs | 18 +- crates/jolt-dory/tests/commit_open_verify.rs | 42 +- crates/jolt-field/benches/field_arith.rs | 22 +- .../fuzz/fuzz_targets/field_arith.rs | 6 +- .../fuzz/fuzz_targets/from_bytes.rs | 10 +- .../fuzz_targets/wide_accumulator_fmadd.rs | 7 +- .../fuzz_targets/wide_accumulator_merge.rs | 7 +- crates/jolt-field/src/accumulator.rs | 147 ++- crates/jolt-field/src/additive_group.rs | 20 - crates/jolt-field/src/arkworks/bn254.rs | 116 +- crates/jolt-field/src/arkworks/bn254_ops.rs | 13 + crates/jolt-field/src/arkworks/mod.rs | 1 + .../src/arkworks/scalar_accumulator.rs | 78 ++ .../src/arkworks/wide_accumulator.rs | 27 +- crates/jolt-field/src/canonical_bit_length.rs | 7 - crates/jolt-field/src/canonical_bytes.rs | 13 - crates/jolt-field/src/canonical_u64.rs | 5 - crates/jolt-field/src/field.rs | 133 +- crates/jolt-field/src/field_core.rs | 4 - crates/jolt-field/src/fixed_byte_size.rs | 5 - crates/jolt-field/src/fixed_bytes.rs | 19 - crates/jolt-field/src/from_primitive_int.rs | 46 - crates/jolt-field/src/invertible.rs | 13 - crates/jolt-field/src/lib.rs | 60 +- crates/jolt-field/src/mul_pow_2.rs | 17 - crates/jolt-field/src/mul_primitive_int.rs | 28 - crates/jolt-field/src/random_sampling.rs | 7 - crates/jolt-field/src/reducing_bytes.rs | 5 - crates/jolt-field/src/ring_core.rs | 33 - crates/jolt-field/src/transcript_challenge.rs | 7 - crates/jolt-field/src/with_accumulator.rs | 7 - crates/jolt-field/tests/coverage.rs | 95 +- crates/jolt-field/tests/field_operations.rs | 124 +- crates/jolt-hyperkzg/benches/hyperkzg.rs | 2 +- crates/jolt-hyperkzg/src/kzg.rs | 2 +- crates/jolt-hyperkzg/src/scheme.rs | 2 +- .../jolt-hyperkzg/tests/commit_open_verify.rs | 2 +- .../src/instructions/virt/assert_lte.rs | 2 +- .../src/instructions/virt/movsign.rs | 2 +- crates/jolt-lookup-tables/src/tables/mod.rs | 132 +- .../src/tables/prefixes/mod.rs | 6 + .../src/tables/suffixes/rev8w.rs | 4 +- .../src/tables/virtual_rev8w.rs | 5 +- crates/jolt-openings/benches/rlc.rs | 16 +- crates/jolt-openings/fuzz/fuzz_targets/rlc.rs | 6 +- crates/jolt-openings/src/mock.rs | 20 +- crates/jolt-openings/src/reduction.rs | 2 +- crates/jolt-openings/tests/reduction.rs | 2 +- crates/jolt-poly/benches/poly_ops.rs | 2 +- .../fuzz/fuzz_targets/dense_poly_ops.rs | 10 +- crates/jolt-poly/src/compressed_univariate.rs | 2 +- crates/jolt-poly/src/dense.rs | 66 +- crates/jolt-poly/src/eq.rs | 2 +- crates/jolt-poly/src/eq_plus_one.rs | 2 +- crates/jolt-poly/src/expanding_table.rs | 212 ++++ crates/jolt-poly/src/identity.rs | 2 +- crates/jolt-poly/src/lagrange.rs | 27 +- crates/jolt-poly/src/lib.rs | 6 +- crates/jolt-poly/src/lt.rs | 2 +- crates/jolt-poly/src/multilinear.rs | 23 +- crates/jolt-poly/src/one_hot.rs | 2 +- crates/jolt-poly/src/polynomial.rs | 1015 +++++++++++++++ crates/jolt-poly/src/source.rs | 553 ++++++++ crates/jolt-poly/src/split_eq.rs | 438 +++++++ crates/jolt-poly/src/univariate.rs | 64 +- crates/jolt-poly/tests/integration.rs | 2 +- crates/jolt-r1cs/src/constraint.rs | 2 +- crates/jolt-r1cs/src/constraints/rv64.rs | 2 +- crates/jolt-r1cs/src/key.rs | 2 +- crates/jolt-r1cs/src/lib.rs | 2 + crates/jolt-r1cs/src/provider.rs | 2 +- crates/jolt-r1cs/src/row_dots.rs | 118 ++ crates/jolt-riscv/src/lib.rs | 26 +- crates/jolt-sumcheck/Cargo.toml | 4 - crates/jolt-sumcheck/src/batched.rs | 81 ++ crates/jolt-sumcheck/src/batched_verifier.rs | 4 +- crates/jolt-sumcheck/src/claim.rs | 9 +- crates/jolt-sumcheck/src/clear.rs | 118 ++ crates/jolt-sumcheck/src/error.rs | 4 +- crates/jolt-sumcheck/src/lib.rs | 8 +- crates/jolt-sumcheck/src/proof.rs | 3 +- crates/jolt-sumcheck/src/round.rs | 143 +++ crates/jolt-sumcheck/src/round_proof.rs | 3 +- crates/jolt-sumcheck/src/scalar.rs | 47 - crates/jolt-sumcheck/src/tests.rs | 2 +- crates/jolt-sumcheck/src/verifier.rs | 4 +- .../jolt-sumcheck/tests/mersenne61_compat.rs | 377 ------ crates/jolt-sumcheck/tests/roundtrip.rs | 2 +- crates/jolt-sumcheck/tests/soundness.rs | 2 +- crates/jolt-trace/Cargo.toml | 3 + crates/jolt-trace/src/bytecode.rs | 12 +- crates/jolt-trace/src/cycle_row.rs | 77 ++ crates/jolt-trace/src/extract.rs | 118 ++ crates/jolt-trace/src/lib.rs | 8 + crates/jolt-trace/src/r1cs_witness.rs | 172 +++ crates/jolt-trace/src/ram.rs | 2 +- crates/jolt-trace/src/tracer_cycle.rs | 547 ++++++++ .../jolt-transcript/benches/transcript_ops.rs | 6 +- crates/jolt-transcript/fuzz/Cargo.toml | 2 +- crates/jolt-transcript/src/blake2b.rs | 5 - crates/jolt-transcript/src/blanket.rs | 11 +- crates/jolt-transcript/src/digest.rs | 54 +- crates/jolt-transcript/src/domain.rs | 12 + crates/jolt-transcript/src/impl_transcript.rs | 166 +++ crates/jolt-transcript/src/keccak.rs | 5 - crates/jolt-transcript/src/lib.rs | 18 +- crates/jolt-transcript/src/mock.rs | 109 ++ crates/jolt-transcript/src/poseidon.rs | 9 +- crates/jolt-transcript/src/transcript.rs | 4 + crates/jolt-transcript/tests/blake2b_tests.rs | 4 +- crates/jolt-transcript/tests/keccak_tests.rs | 1 - .../jolt-transcript/tests/poseidon_tests.rs | 1 + crates/jolt-witness/Cargo.toml | 13 + crates/jolt-witness/src/lib.rs | 1119 +++++++++++++++++ 129 files changed, 6110 insertions(+), 1386 deletions(-) delete mode 100644 crates/jolt-field/src/additive_group.rs create mode 100644 crates/jolt-field/src/arkworks/scalar_accumulator.rs delete mode 100644 crates/jolt-field/src/canonical_bit_length.rs delete mode 100644 crates/jolt-field/src/canonical_bytes.rs delete mode 100644 crates/jolt-field/src/canonical_u64.rs delete mode 100644 crates/jolt-field/src/field_core.rs delete mode 100644 crates/jolt-field/src/fixed_byte_size.rs delete mode 100644 crates/jolt-field/src/fixed_bytes.rs delete mode 100644 crates/jolt-field/src/from_primitive_int.rs delete mode 100644 crates/jolt-field/src/invertible.rs delete mode 100644 crates/jolt-field/src/mul_pow_2.rs delete mode 100644 crates/jolt-field/src/mul_primitive_int.rs delete mode 100644 crates/jolt-field/src/random_sampling.rs delete mode 100644 crates/jolt-field/src/reducing_bytes.rs delete mode 100644 crates/jolt-field/src/ring_core.rs delete mode 100644 crates/jolt-field/src/transcript_challenge.rs delete mode 100644 crates/jolt-field/src/with_accumulator.rs create mode 100644 crates/jolt-poly/src/expanding_table.rs create mode 100644 crates/jolt-poly/src/polynomial.rs create mode 100644 crates/jolt-poly/src/source.rs create mode 100644 crates/jolt-poly/src/split_eq.rs create mode 100644 crates/jolt-r1cs/src/row_dots.rs create mode 100644 crates/jolt-sumcheck/src/batched.rs create mode 100644 crates/jolt-sumcheck/src/clear.rs create mode 100644 crates/jolt-sumcheck/src/round.rs delete mode 100644 crates/jolt-sumcheck/src/scalar.rs delete mode 100644 crates/jolt-sumcheck/tests/mersenne61_compat.rs create mode 100644 crates/jolt-trace/src/cycle_row.rs create mode 100644 crates/jolt-trace/src/extract.rs create mode 100644 crates/jolt-trace/src/r1cs_witness.rs create mode 100644 crates/jolt-trace/src/tracer_cycle.rs create mode 100644 crates/jolt-transcript/src/impl_transcript.rs create mode 100644 crates/jolt-transcript/src/mock.rs create mode 100644 crates/jolt-witness/Cargo.toml create mode 100644 crates/jolt-witness/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 42fc519ebb..be1f53eb9a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3110,8 +3110,6 @@ dependencies = [ "jolt-field", "jolt-poly", "jolt-transcript", - "num-traits", - "rand_core 0.6.4", "serde", "thiserror 2.0.18", "tracing", @@ -3123,7 +3121,10 @@ version = "0.1.0" dependencies = [ "bincode 2.0.1", "common", + "jolt-field", + "jolt-r1cs", "jolt-riscv", + "jolt-witness", "rand 0.8.5", "serde", "tracer", @@ -3146,6 +3147,14 @@ dependencies = [ "sha3 0.11.0", ] +[[package]] +name = "jolt-witness" +version = "0.1.0" +dependencies = [ + "jolt-field", + "jolt-poly", +] + [[package]] name = "js-sys" version = "0.3.91" diff --git a/Cargo.toml b/Cargo.toml index 602909b5ae..4f1428d30b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,6 +35,7 @@ members = [ "crates/jolt-hyperkzg", "crates/jolt-riscv", "crates/jolt-transcript", + "crates/jolt-witness", "crates/jolt-profiling", "crates/jolt-field", "jolt-core", @@ -382,6 +383,8 @@ jolt-openings = { path = "./crates/jolt-openings" } jolt-poly = { path = "./crates/jolt-poly" } jolt-transcript = { path = "./crates/jolt-transcript" } jolt-sumcheck = { path = "./crates/jolt-sumcheck" } +jolt-r1cs = { path = "./crates/jolt-r1cs" } +jolt-witness = { path = "./crates/jolt-witness" } jolt-riscv = { path = "./crates/jolt-riscv" } jolt-trace = { path = "./crates/jolt-trace" } jolt-lookup-tables = { path = "./crates/jolt-lookup-tables" } diff --git a/crates/jolt-crypto/benches/crypto.rs b/crates/jolt-crypto/benches/crypto.rs index d41511ccb3..42d5d6fd4e 100644 --- a/crates/jolt-crypto/benches/crypto.rs +++ b/crates/jolt-crypto/benches/crypto.rs @@ -5,7 +5,7 @@ use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; use jolt_crypto::{ Bn254, Bn254G1, Bn254G2, JoltGroup, PairingGroup, Pedersen, PedersenSetup, VectorCommitment, }; -use jolt_field::{Fr, FromPrimitiveInt, RandomSampling}; +use jolt_field::{Field, Fr}; use rand_chacha::ChaCha20Rng; use rand_core::SeedableRng; diff --git a/crates/jolt-crypto/fuzz/fuzz_targets/group_arith.rs b/crates/jolt-crypto/fuzz/fuzz_targets/group_arith.rs index cfe9b9062a..16318d8985 100644 --- a/crates/jolt-crypto/fuzz/fuzz_targets/group_arith.rs +++ b/crates/jolt-crypto/fuzz/fuzz_targets/group_arith.rs @@ -1,14 +1,14 @@ #![no_main] use jolt_crypto::{Bn254, Bn254G1, JoltGroup}; -use jolt_field::{Fr, ReducingBytes}; +use jolt_field::{Field, Fr}; use libfuzzer_sys::fuzz_target; fn parse_input(data: &[u8]) -> Option<(Fr, Fr, Bn254G1)> { if data.len() < 64 { return None; } - let s1 = ::from_le_bytes_mod_order(&data[..32]); - let s2 = ::from_le_bytes_mod_order(&data[32..64]); + let s1 = Fr::from_bytes(&data[..32]); + let s2 = Fr::from_bytes(&data[32..64]); let g = Bn254::g1_generator(); let p = g.scalar_mul(&s1); Some((s1, s2, p)) diff --git a/crates/jolt-crypto/fuzz/fuzz_targets/pedersen_commit.rs b/crates/jolt-crypto/fuzz/fuzz_targets/pedersen_commit.rs index aaa1d14a62..d6e6719857 100644 --- a/crates/jolt-crypto/fuzz/fuzz_targets/pedersen_commit.rs +++ b/crates/jolt-crypto/fuzz/fuzz_targets/pedersen_commit.rs @@ -1,6 +1,6 @@ #![no_main] use jolt_crypto::{Bn254, Bn254G1, VectorCommitment, JoltGroup, Pedersen, PedersenSetup}; -use jolt_field::{Fr, FromPrimitiveInt, ReducingBytes}; +use jolt_field::{Field, Fr}; use libfuzzer_sys::fuzz_target; /// Fixed small setup (4 generators) — deterministic so we don't waste fuzzer @@ -23,9 +23,9 @@ fuzz_target!(|data: &[u8]| { let setup = fixed_setup(); let values: Vec = (0..4) - .map(|i| ::from_le_bytes_mod_order(&data[i * 32..(i + 1) * 32])) + .map(|i| Fr::from_bytes(&data[i * 32..(i + 1) * 32])) .collect(); - let blinding = ::from_le_bytes_mod_order(&data[128..160]); + let blinding = Fr::from_bytes(&data[128..160]); // Commit-verify round-trip let c = Pedersen::::commit(&setup, &values, &blinding); diff --git a/crates/jolt-crypto/src/ec/bn254/gt.rs b/crates/jolt-crypto/src/ec/bn254/gt.rs index befa42df4c..4237a4d113 100644 --- a/crates/jolt-crypto/src/ec/bn254/gt.rs +++ b/crates/jolt-crypto/src/ec/bn254/gt.rs @@ -139,6 +139,11 @@ impl AppendToTranscript for Bn254GT { buf.reverse(); transcript.append_bytes(&buf); } + + fn serialized_len(&self) -> u64 { + use ark_serialize::CanonicalSerialize; + self.0.uncompressed_size() as u64 + } } impl JoltGroup for Bn254GT { diff --git a/crates/jolt-crypto/src/ec/bn254/mod.rs b/crates/jolt-crypto/src/ec/bn254/mod.rs index 29ccc507ab..cba4b71d8a 100644 --- a/crates/jolt-crypto/src/ec/bn254/mod.rs +++ b/crates/jolt-crypto/src/ec/bn254/mod.rs @@ -139,6 +139,11 @@ macro_rules! impl_jolt_group_wrapper { buf.reverse(); transcript.append_bytes(&buf); } + + fn serialized_len(&self) -> u64 { + use ::ark_serialize::CanonicalSerialize; + self.0.uncompressed_size() as u64 + } } impl $crate::JoltGroup for $wrapper { @@ -259,8 +264,7 @@ impl PairingGroup for Bn254 { /// catches silent modular reduction when `F` has a larger modulus than BN254 Fr. #[inline] pub(crate) fn field_to_fr(f: &F) -> ark_bn254::Fr { - let mut bytes = vec![0u8; F::NUM_BYTES]; - f.to_bytes_le(&mut bytes); + let bytes = f.to_bytes(); #[cfg(debug_assertions)] { use ark_ff::{BigInteger, PrimeField as _}; diff --git a/crates/jolt-crypto/tests/coverage.rs b/crates/jolt-crypto/tests/coverage.rs index 3dca4b1230..ab34960ffc 100644 --- a/crates/jolt-crypto/tests/coverage.rs +++ b/crates/jolt-crypto/tests/coverage.rs @@ -7,7 +7,7 @@ use jolt_crypto::ec::bn254::glv; use jolt_crypto::{ Bn254, Bn254G1, Bn254G2, Bn254GT, HomomorphicCommitment, JoltGroup, PairingGroup, }; -use jolt_field::{Fr, FromPrimitiveInt, RandomSampling}; +use jolt_field::{Field, Fr}; use rand_chacha::ChaCha20Rng; use rand_core::SeedableRng; diff --git a/crates/jolt-crypto/tests/group_laws.rs b/crates/jolt-crypto/tests/group_laws.rs index 4477227487..740dd4cbdc 100644 --- a/crates/jolt-crypto/tests/group_laws.rs +++ b/crates/jolt-crypto/tests/group_laws.rs @@ -1,7 +1,7 @@ //! Algebraic group law tests for BN254 G1 and G2. use jolt_crypto::{Bn254, Bn254G1, Bn254G2, JoltGroup}; -use jolt_field::{Fr, FromPrimitiveInt, RandomSampling}; +use jolt_field::{Field, Fr}; use rand_chacha::ChaCha20Rng; use rand_core::SeedableRng; diff --git a/crates/jolt-crypto/tests/pairing.rs b/crates/jolt-crypto/tests/pairing.rs index a50c75dd4d..1daefca73c 100644 --- a/crates/jolt-crypto/tests/pairing.rs +++ b/crates/jolt-crypto/tests/pairing.rs @@ -1,7 +1,7 @@ //! Pairing bilinearity and consistency tests for BN254. use jolt_crypto::{Bn254, Bn254G2, Bn254GT, JoltGroup, PairingGroup}; -use jolt_field::{Fr, FromPrimitiveInt, RandomSampling}; +use jolt_field::{Field, Fr}; use rand_chacha::ChaCha20Rng; use rand_core::SeedableRng; diff --git a/crates/jolt-crypto/tests/pedersen.rs b/crates/jolt-crypto/tests/pedersen.rs index b1d3201b43..a640c4ed55 100644 --- a/crates/jolt-crypto/tests/pedersen.rs +++ b/crates/jolt-crypto/tests/pedersen.rs @@ -1,7 +1,7 @@ //! Pedersen commitment scheme tests over BN254 G1. use jolt_crypto::{Bn254, Bn254G1, JoltGroup, Pedersen, PedersenSetup, VectorCommitment}; -use jolt_field::{Fr, FromPrimitiveInt, RandomSampling}; +use jolt_field::{Field, Fr}; use rand_chacha::ChaCha20Rng; use rand_core::SeedableRng; diff --git a/crates/jolt-crypto/tests/serialization.rs b/crates/jolt-crypto/tests/serialization.rs index d543789d24..216193e51b 100644 --- a/crates/jolt-crypto/tests/serialization.rs +++ b/crates/jolt-crypto/tests/serialization.rs @@ -2,7 +2,7 @@ //! Serialization round-trip tests for all BN254 types. use jolt_crypto::{Bn254, Bn254G1, Bn254G2, Bn254GT, JoltGroup, PairingGroup, PedersenSetup}; -use jolt_field::{Fr, FromPrimitiveInt}; +use jolt_field::{Field, Fr}; use rand_chacha::ChaCha20Rng; use rand_core::SeedableRng; diff --git a/crates/jolt-dory/benches/dory.rs b/crates/jolt-dory/benches/dory.rs index 76b8a6efda..3d220bc5fd 100644 --- a/crates/jolt-dory/benches/dory.rs +++ b/crates/jolt-dory/benches/dory.rs @@ -3,7 +3,7 @@ use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; use jolt_dory::{DoryScheme, DoryVerifierSetup}; -use jolt_field::{Fr, RandomSampling}; +use jolt_field::{Field, Fr}; use jolt_openings::{CommitmentScheme, StreamingCommitment, ZkOpeningScheme}; use jolt_poly::{OneHotPolynomial, Polynomial}; use jolt_transcript::Transcript; @@ -58,9 +58,7 @@ fn bench_open(c: &mut Criterion) { || { let mut rng = ChaCha20Rng::seed_from_u64(0); let poly = Polynomial::::random(nv, &mut rng); - let point: Vec = (0..nv) - .map(|_| ::random(&mut rng)) - .collect(); + let point: Vec = (0..nv).map(|_| Fr::random(&mut rng)).collect(); let eval = poly.evaluate(&point); (poly, point, eval) }, @@ -89,9 +87,7 @@ fn bench_verify(c: &mut Criterion) { || { let mut rng = ChaCha20Rng::seed_from_u64(0); let poly = Polynomial::::random(nv, &mut rng); - let point: Vec = (0..nv) - .map(|_| ::random(&mut rng)) - .collect(); + let point: Vec = (0..nv).map(|_| Fr::random(&mut rng)).collect(); let eval = poly.evaluate(&point); let (commitment, _) = DoryScheme::commit(poly.evaluations(), &setup); let mut transcript = @@ -160,8 +156,8 @@ fn bench_combine(c: &mut Criterion) { let poly_b = Polynomial::::random(num_vars, &mut rng); let (commit_a, _) = DoryScheme::commit(poly_a.evaluations(), &setup); let (commit_b, _) = DoryScheme::commit(poly_b.evaluations(), &setup); - let s_a = ::random(&mut rng); - let s_b = ::random(&mut rng); + let s_a = Fr::random(&mut rng); + let s_b = Fr::random(&mut rng); group.bench_with_input(BenchmarkId::from_parameter(num_vars), &num_vars, |b, _| { b.iter(|| { @@ -186,7 +182,7 @@ fn bench_combine_hints(c: &mut Criterion) { .map(|_| { let poly = Polynomial::::random(num_vars, &mut rng); let (_, hint) = DoryScheme::commit(poly.evaluations(), &setup); - (hint, ::random(&mut rng)) + (hint, Fr::random(&mut rng)) }) .collect(); let hints: Vec<_> = hints_and_scalars.iter().map(|(h, _)| h.clone()).collect(); @@ -223,9 +219,7 @@ fn bench_open_zk(c: &mut Criterion) { || { let mut rng = ChaCha20Rng::seed_from_u64(0); let poly = Polynomial::::random(nv, &mut rng); - let point: Vec = (0..nv) - .map(|_| ::random(&mut rng)) - .collect(); + let point: Vec = (0..nv).map(|_| Fr::random(&mut rng)).collect(); let eval = poly.evaluate(&point); (poly, point, eval) }, @@ -255,9 +249,7 @@ fn bench_verify_zk(c: &mut Criterion) { || { let mut rng = ChaCha20Rng::seed_from_u64(0); let poly = Polynomial::::random(nv, &mut rng); - let point: Vec = (0..nv) - .map(|_| ::random(&mut rng)) - .collect(); + let point: Vec = (0..nv).map(|_| Fr::random(&mut rng)).collect(); let eval = poly.evaluate(&point); let (commitment, _) = DoryScheme::commit(poly.evaluations(), &setup); let mut transcript = diff --git a/crates/jolt-dory/src/scheme.rs b/crates/jolt-dory/src/scheme.rs index 9b40b34891..86c16a1013 100644 --- a/crates/jolt-dory/src/scheme.rs +++ b/crates/jolt-dory/src/scheme.rs @@ -14,7 +14,7 @@ use dory::primitives::arithmetic::{ }; use dory::primitives::poly::{MultilinearLagrange, Polynomial as DoryPolynomial}; use jolt_crypto::{Bn254G1, Bn254GT, Commitment, DeriveSetup, JoltGroup, PedersenSetup}; -use jolt_field::Fr; +use jolt_field::{Field, Fr}; use jolt_openings::{AdditivelyHomomorphic, CommitmentScheme, OpeningsError, ZkOpeningScheme}; use jolt_poly::MultilinearPoly; use jolt_transcript::{AppendToTranscript, Label, LabelWithCount, Transcript}; @@ -65,6 +65,12 @@ pub(crate) fn jolt_g1_vec_to_ark(v: Vec) -> Vec { unsafe { std::mem::transmute(v) } } +#[inline] +pub(crate) fn jolt_g1_to_ark(jolt: Bn254G1) -> ArkG1 { + // SAFETY: same layout as jolt_g1_vec_to_ark. + unsafe { std::mem::transmute_copy(&jolt) } +} + #[inline] pub(crate) fn ark_to_jolt_g1_vec(v: Vec) -> Vec { // SAFETY: same layout as jolt_g1_vec_to_ark. @@ -141,8 +147,8 @@ impl CommitmentScheme for DoryScheme { let num_cols = 1usize << sigma; let num_rows = 1usize << (num_vars - sigma); - let row_commitments = if poly.is_one_hot() { - commit_rows_one_hot(poly, num_rows, num_cols, &setup.0) + let row_commitments = if poly.is_sparse() { + commit_rows_sparse(poly, num_rows, num_cols, &setup.0) } else { commit_rows_dense(poly, sigma, &setup.0) }; @@ -174,7 +180,7 @@ impl CommitmentScheme for DoryScheme { let row_commitments = match hint { Some(h) => jolt_g1_vec_to_ark(h.0), - None if poly.is_one_hot() => commit_rows_one_hot(poly, num_rows, num_cols, &setup.0), + None if poly.is_sparse() => commit_rows_sparse(poly, num_rows, num_cols, &setup.0), None => commit_rows_dense(poly, sigma, &setup.0), }; @@ -298,7 +304,7 @@ impl ZkOpeningScheme for DoryScheme { let row_commitments = match hint { Some(h) => jolt_g1_vec_to_ark(h.0), - None if poly.is_one_hot() => commit_rows_one_hot(poly, num_rows, num_cols, &setup.0), + None if poly.is_sparse() => commit_rows_sparse(poly, num_rows, num_cols, &setup.0), None => commit_rows_dense(poly, sigma, &setup.0), }; @@ -371,8 +377,9 @@ fn commit_rows_dense + ?Sized>( .collect() } -/// One-hot commit: O(T) group additions for unit-valued one-hot polynomials. -fn commit_rows_one_hot + ?Sized>( +/// Sparse commit: O(nnz) group operations, with the one-hot case kept as pure +/// group addition. +fn commit_rows_sparse + ?Sized>( poly: &P, num_rows: usize, num_cols: usize, @@ -380,24 +387,32 @@ fn commit_rows_one_hot + ?Sized>( ) -> Vec { let g1_bases = &setup.g1_vec[..num_cols]; - let mut cols_per_row: Vec> = vec![Vec::new(); num_rows]; - poly.for_each_one(&mut |flat_idx| { + let mut entries_per_row: Vec> = vec![Vec::new(); num_rows]; + poly.for_each_nonzero(&mut |flat_idx, value| { let row = flat_idx / num_cols; let col = flat_idx % num_cols; debug_assert!( row < num_rows && col < num_cols, - "for_each_one out-of-bounds flat_idx: row={row} num_rows={num_rows} col={col} num_cols={num_cols}", + "for_each_nonzero out-of-bounds flat_idx: row={row} num_rows={num_rows} col={col} num_cols={num_cols}", ); - cols_per_row[row].push(col); + entries_per_row[row].push((col, value)); }); - cols_per_row + entries_per_row .par_iter() - .map(|cols| { - cols.iter() - .fold(::G1::identity(), |acc, &col| { - ::G1::add(&acc, &g1_bases[col]) - }) + .map(|entries| { + entries.iter().fold( + ::G1::identity(), + |acc, &(col, value)| { + let term = if value == Fr::from_u64(1) { + g1_bases[col] + } else { + let base = ark_to_jolt_g1(g1_bases[col]); + jolt_g1_to_ark(base.scalar_mul(&value)) + }; + ::G1::add(&acc, &term) + }, + ) }) .collect() } @@ -455,7 +470,7 @@ impl> MultilinearLagrange for DorySourceAdapter<'_ mod tests { use super::*; use jolt_crypto::{Pedersen, VectorCommitment}; - use jolt_field::{FromPrimitiveInt, RandomSampling}; + use jolt_field::Field; use jolt_poly::Polynomial; use rand_chacha::ChaCha20Rng; use rand_core::SeedableRng; @@ -469,9 +484,7 @@ mod tests { let verifier_setup = DoryVerifierSetup(prover_setup.0.to_verifier_setup()); let poly = Polynomial::::random(num_vars, &mut rng); - let point: Vec = (0..num_vars) - .map(|_| ::random(&mut rng)) - .collect(); + let point: Vec = (0..num_vars).map(|_| Fr::random(&mut rng)).collect(); let eval = poly.evaluate(&point); let (commitment, hint) = DoryScheme::commit(poly.evaluations(), &prover_setup); @@ -519,13 +532,8 @@ mod tests { .collect(); let (commit_sum_direct, _) = DoryScheme::commit(&sum_evals, &prover_setup); - let combined = DoryScheme::combine( - &[commit_a, commit_b], - &[ - ::from_u64(1), - ::from_u64(1), - ], - ); + let combined = + DoryScheme::combine(&[commit_a, commit_b], &[Fr::from_u64(1), Fr::from_u64(1)]); assert_eq!( commit_sum_direct, combined, @@ -542,9 +550,7 @@ mod tests { let verifier_setup = DoryVerifierSetup(prover_setup.0.to_verifier_setup()); let poly = Polynomial::::random(num_vars, &mut rng); - let point: Vec = (0..num_vars) - .map(|_| ::random(&mut rng)) - .collect(); + let point: Vec = (0..num_vars).map(|_| Fr::random(&mut rng)).collect(); let eval = poly.evaluate(&point); let (commitment, hint) = DoryScheme::commit(poly.evaluations(), &prover_setup); @@ -583,12 +589,8 @@ mod tests { capacity, ); - let values = vec![ - ::from_u64(1), - ::from_u64(2), - ::from_u64(3), - ]; - let blinding = ::from_u64(42); + let values = vec![Fr::from_u64(1), Fr::from_u64(2), Fr::from_u64(3)]; + let blinding = Fr::from_u64(42); let commitment = as VectorCommitment>::commit(&vc_setup, &values, &blinding); assert!( as VectorCommitment>::verify( diff --git a/crates/jolt-dory/src/streaming.rs b/crates/jolt-dory/src/streaming.rs index 9645312143..a8770cbd40 100644 --- a/crates/jolt-dory/src/streaming.rs +++ b/crates/jolt-dory/src/streaming.rs @@ -4,12 +4,42 @@ use dory::backends::arkworks::G1Routines; use dory::primitives::arithmetic::{DoryRoutines, PairingCurve}; use jolt_field::Fr; use jolt_openings::StreamingCommitment; +use rayon::prelude::*; -use crate::scheme::{ark_to_jolt_g1, ark_to_jolt_gt, jolt_fr_to_ark, jolt_g1_vec_to_ark, ArkFr}; -use crate::types::{DoryCommitment, DoryPartialCommitment}; +use crate::scheme::{ + ark_to_jolt_g1, ark_to_jolt_g1_vec, ark_to_jolt_gt, jolt_fr_to_ark, jolt_g1_vec_to_ark, ArkFr, +}; +use crate::types::{DoryCommitment, DoryHint, DoryPartialCommitment, DoryProverSetup}; type InnerBN254 = dory::backends::arkworks::BN254; +impl crate::DoryScheme { + #[tracing::instrument(skip_all, name = "DoryScheme::commit_evaluations_with_row_len")] + pub fn commit_evaluations_with_row_len( + data: &[Fr], + row_len: usize, + setup: &DoryProverSetup, + ) -> (DoryCommitment, DoryHint) { + assert!(row_len > 0, "Dory row length must be nonzero"); + + let g1_bases = &setup.0.g1_vec[..row_len]; + let row_commitments: Vec<_> = data + .par_chunks(row_len) + .map(|chunk| { + let scalars: Vec = chunk.iter().map(jolt_fr_to_ark).collect(); + G1Routines::msm(&g1_bases[..chunk.len()], &scalars) + }) + .collect(); + + let g2_bases = &setup.0.g2_vec[..row_commitments.len()]; + let tier_2 = ::multi_pair_g2_setup(&row_commitments, g2_bases); + ( + DoryCommitment(ark_to_jolt_gt(&tier_2)), + DoryHint(ark_to_jolt_g1_vec(row_commitments)), + ) + } +} + impl StreamingCommitment for crate::DoryScheme { type PartialCommitment = DoryPartialCommitment; @@ -19,49 +49,18 @@ impl StreamingCommitment for crate::DoryScheme { } } - /// Commits one full row of the polynomial as `MSM(g1_bases[..chunk.len()], chunk)`, - /// matching the per-row work in [`DoryScheme::commit`](crate::DoryScheme::commit)'s - /// dense path. Caller must feed every row at the same chunk width. #[tracing::instrument(skip_all, name = "DoryScheme::stream_feed")] fn feed(partial: &mut Self::PartialCommitment, chunk: &[Fr], setup: &Self::ProverSetup) { - assert!( - chunk.len().is_power_of_two(), - "streaming: chunk length ({}) must be a power of two", - chunk.len(), - ); - assert!( - chunk.len() <= setup.0.g1_vec.len(), - "streaming: chunk length ({}) exceeds Dory SRS size ({})", - chunk.len(), - setup.0.g1_vec.len(), - ); - let g1_bases = &setup.0.g1_vec[..chunk.len()]; let scalars: Vec = chunk.iter().map(jolt_fr_to_ark).collect(); let row_commitment = G1Routines::msm(g1_bases, &scalars); partial.row_commitments.push(ark_to_jolt_g1(row_commitment)); } - /// Aggregates row commitments into the final tier-2 commitment, matching - /// [`DoryScheme::commit`](crate::DoryScheme::commit). Asserts that the - /// streamed row count is a power of two (the layout `DoryScheme::commit` - /// produces). #[tracing::instrument(skip_all, name = "DoryScheme::stream_finish")] fn finish(partial: Self::PartialCommitment, setup: &Self::ProverSetup) -> Self::Output { - let num_rows = partial.row_commitments.len(); - assert!( - num_rows.is_power_of_two(), - "streaming: row count ({num_rows}) must be a power of two", - ); - assert!( - num_rows <= setup.0.g2_vec.len(), - "streaming: row count ({}) exceeds Dory SRS size ({})", - num_rows, - setup.0.g2_vec.len(), - ); - let ark_rows = jolt_g1_vec_to_ark(partial.row_commitments); - let g2_bases = &setup.0.g2_vec[..num_rows]; + let g2_bases = &setup.0.g2_vec[..ark_rows.len()]; let tier_2 = ::multi_pair_g2_setup(&ark_rows, g2_bases); DoryCommitment(ark_to_jolt_gt(&tier_2)) } @@ -69,7 +68,7 @@ impl StreamingCommitment for crate::DoryScheme { #[cfg(test)] mod tests { - use jolt_field::RandomSampling; + use jolt_field::Field; use jolt_openings::{CommitmentScheme, StreamingCommitment}; use rand_chacha::ChaCha20Rng; use rand_core::SeedableRng; @@ -88,7 +87,7 @@ mod tests { let prover_setup = DoryScheme::setup_prover(num_vars); let evals: Vec = (0..num_rows * num_cols) - .map(|_| ::random(&mut rng)) + .map(|_| ::random(&mut rng)) .collect(); let poly = jolt_poly::Polynomial::new(evals.clone()); @@ -105,4 +104,56 @@ mod tests { "streaming and direct commitments must match" ); } + + #[test] + fn batched_rows_match_streaming_and_direct() { + let num_vars: usize = 6; + let row_len = 1usize << num_vars.div_ceil(2); + let mut rng = ChaCha20Rng::seed_from_u64(101); + + let prover_setup = DoryScheme::setup_prover(num_vars); + let evals: Vec = (0..(1usize << num_vars)) + .map(|_| ::random(&mut rng)) + .collect(); + let poly = jolt_poly::Polynomial::new(evals.clone()); + + let (direct, direct_hint) = DoryScheme::commit(poly.evaluations(), &prover_setup); + let (batched, batched_hint) = + DoryScheme::commit_evaluations_with_row_len(&evals, row_len, &prover_setup); + + let mut partial = DoryScheme::begin(&prover_setup); + for row in evals.chunks(row_len) { + DoryScheme::feed(&mut partial, row, &prover_setup); + } + let streamed = DoryScheme::finish(partial, &prover_setup); + + assert_eq!(batched, direct); + assert_eq!(batched, streamed); + assert_eq!(batched_hint.0, direct_hint.0); + } + + #[test] + fn batched_rows_allow_short_final_row() { + let num_vars: usize = 5; + let row_len = 1usize << num_vars.div_ceil(2); + let short_len = (1usize << num_vars) - 1; + let mut rng = ChaCha20Rng::seed_from_u64(102); + + let prover_setup = DoryScheme::setup_prover(num_vars); + let evals: Vec = (0..short_len) + .map(|_| ::random(&mut rng)) + .collect(); + + let (batched, batched_hint) = + DoryScheme::commit_evaluations_with_row_len(&evals, row_len, &prover_setup); + let mut partial = DoryScheme::begin(&prover_setup); + for row in evals.chunks(row_len) { + DoryScheme::feed(&mut partial, row, &prover_setup); + } + let streaming_hint = partial.row_commitments.clone(); + let streamed = DoryScheme::finish(partial, &prover_setup); + + assert_eq!(batched, streamed); + assert_eq!(batched_hint.0, streaming_hint); + } } diff --git a/crates/jolt-dory/src/types.rs b/crates/jolt-dory/src/types.rs index 97c5f8fd4f..76d05a92e9 100644 --- a/crates/jolt-dory/src/types.rs +++ b/crates/jolt-dory/src/types.rs @@ -38,6 +38,10 @@ impl AppendToTranscript for DoryCommitment { fn append_to_transcript(&self, transcript: &mut T) { self.0.append_to_transcript(transcript); } + + fn serialized_len(&self) -> u64 { + self.0.serialized_len() + } } impl HomomorphicCommitment for DoryCommitment { @@ -135,7 +139,7 @@ fn validate_proof_round_count(buf: &[u8]) -> Result<(), String> { #[expect(clippy::expect_used, reason = "tests may panic on assertion failures")] mod tests { use super::*; - use jolt_field::RandomSampling; + use jolt_field::Field; use jolt_openings::CommitmentScheme; use jolt_poly::Polynomial; use jolt_transcript::Transcript; @@ -173,9 +177,7 @@ mod tests { let prover_setup = crate::DoryScheme::setup_prover(num_vars); let poly = Polynomial::::random(num_vars, &mut rng); - let point: Vec = (0..num_vars) - .map(|_| ::random(&mut rng)) - .collect(); + let point: Vec = (0..num_vars).map(|_| Fr::random(&mut rng)).collect(); let eval = poly.evaluate(&point); let (commitment, hint) = crate::DoryScheme::commit(poly.evaluations(), &prover_setup); @@ -212,9 +214,7 @@ mod tests { let prover_setup = crate::DoryScheme::setup_prover(num_vars); let poly = Polynomial::::random(num_vars, &mut rng); - let point: Vec = (0..num_vars) - .map(|_| ::random(&mut rng)) - .collect(); + let point: Vec = (0..num_vars).map(|_| Fr::random(&mut rng)).collect(); let eval = poly.evaluate(&point); let mut transcript = jolt_transcript::Blake2bTranscript::new(b"serde-bp"); @@ -247,9 +247,7 @@ mod tests { let prover_setup = crate::DoryScheme::setup_prover(num_vars); let poly = Polynomial::::random(num_vars, &mut rng); - let point: Vec = (0..num_vars) - .map(|_| ::random(&mut rng)) - .collect(); + let point: Vec = (0..num_vars).map(|_| Fr::random(&mut rng)).collect(); let eval = poly.evaluate(&point); let mut transcript = jolt_transcript::Blake2bTranscript::new(b"serde-oversized"); diff --git a/crates/jolt-dory/tests/commit_open_verify.rs b/crates/jolt-dory/tests/commit_open_verify.rs index 378ac74436..a373bbbd9a 100644 --- a/crates/jolt-dory/tests/commit_open_verify.rs +++ b/crates/jolt-dory/tests/commit_open_verify.rs @@ -7,7 +7,7 @@ use dory::backends::arkworks::ArkG1; use jolt_dory::DoryScheme; -use jolt_field::{Fr, FromPrimitiveInt, RandomSampling}; +use jolt_field::{Field, Fr}; use jolt_openings::{ AdditivelyHomomorphic, CommitmentScheme, StreamingCommitment, ZkOpeningScheme, }; @@ -21,9 +21,7 @@ fn round_trip>(num_vars: usize, seed: u64, label: let prover_setup = DoryScheme::setup_prover(num_vars); let verifier_setup = DoryScheme::setup_verifier(num_vars); let poly = Polynomial::::random(num_vars, &mut rng); - let point: Vec = (0..num_vars) - .map(|_| ::random(&mut rng)) - .collect(); + let point: Vec = (0..num_vars).map(|_| Fr::random(&mut rng)).collect(); let eval = poly.evaluate(&point); let (commitment, hint) = DoryScheme::commit(poly.evaluations(), &prover_setup); @@ -123,9 +121,7 @@ fn wrong_eval_rejected() { let prover_setup = DoryScheme::setup_prover(num_vars); let verifier_setup = DoryScheme::setup_verifier(num_vars); let poly = Polynomial::::random(num_vars, &mut rng); - let point: Vec = (0..num_vars) - .map(|_| ::random(&mut rng)) - .collect(); + let point: Vec = (0..num_vars).map(|_| Fr::random(&mut rng)).collect(); let eval = poly.evaluate(&point); let (commitment, hint) = DoryScheme::commit(poly.evaluations(), &prover_setup); @@ -153,9 +149,7 @@ fn wrong_point_rejected() { let prover_setup = DoryScheme::setup_prover(num_vars); let verifier_setup = DoryScheme::setup_verifier(num_vars); let poly = Polynomial::::random(num_vars, &mut rng); - let point: Vec = (0..num_vars) - .map(|_| ::random(&mut rng)) - .collect(); + let point: Vec = (0..num_vars).map(|_| Fr::random(&mut rng)).collect(); let eval = poly.evaluate(&point); let (commitment, hint) = DoryScheme::commit(poly.evaluations(), &prover_setup); @@ -189,8 +183,8 @@ fn combine_linear_combination() { let (commit_a, _) = DoryScheme::commit(poly_a.evaluations(), &prover_setup); let (commit_b, _) = DoryScheme::commit(poly_b.evaluations(), &prover_setup); - let c1 = ::random(&mut rng); - let c2 = ::random(&mut rng); + let c1 = Fr::random(&mut rng); + let c2 = Fr::random(&mut rng); let combined = DoryScheme::combine(&[commit_a, commit_b], &[c1, c2]); @@ -231,9 +225,7 @@ fn wrong_commitment_rejected() { let verifier_setup = DoryScheme::setup_verifier(num_vars); let poly = Polynomial::::random(num_vars, &mut rng); - let point: Vec = (0..num_vars) - .map(|_| ::random(&mut rng)) - .collect(); + let point: Vec = (0..num_vars).map(|_| Fr::random(&mut rng)).collect(); let eval = poly.evaluate(&point); let (commitment, hint) = DoryScheme::commit(poly.evaluations(), &prover_setup); @@ -265,9 +257,7 @@ fn wrong_transcript_domain_rejected() { let prover_setup = DoryScheme::setup_prover(num_vars); let verifier_setup = DoryScheme::setup_verifier(num_vars); let poly = Polynomial::::random(num_vars, &mut rng); - let point: Vec = (0..num_vars) - .map(|_| ::random(&mut rng)) - .collect(); + let point: Vec = (0..num_vars).map(|_| Fr::random(&mut rng)).collect(); let eval = poly.evaluate(&point); let (commitment, hint) = DoryScheme::commit(poly.evaluations(), &prover_setup); @@ -292,9 +282,7 @@ fn zk_round_trip>(num_vars: usize, seed: u64, labe let prover_setup = DoryScheme::setup_prover(num_vars); let verifier_setup = DoryScheme::setup_verifier(num_vars); let poly = Polynomial::::random(num_vars, &mut rng); - let point: Vec = (0..num_vars) - .map(|_| ::random(&mut rng)) - .collect(); + let point: Vec = (0..num_vars).map(|_| Fr::random(&mut rng)).collect(); let eval = poly.evaluate(&point); let (commitment, hint) = DoryScheme::commit(poly.evaluations(), &prover_setup); @@ -330,9 +318,7 @@ fn zk_wrong_commitment_rejected() { let verifier_setup = DoryScheme::setup_verifier(num_vars); let poly = Polynomial::::random(num_vars, &mut rng); - let point: Vec = (0..num_vars) - .map(|_| ::random(&mut rng)) - .collect(); + let point: Vec = (0..num_vars).map(|_| Fr::random(&mut rng)).collect(); let eval = poly.evaluate(&point); let (commitment, hint) = DoryScheme::commit(poly.evaluations(), &prover_setup); @@ -357,9 +343,7 @@ fn wrong_eval_commitment_rejected_zk() { let prover_setup = DoryScheme::setup_prover(num_vars); let verifier_setup = DoryScheme::setup_verifier(num_vars); let poly = Polynomial::::random(num_vars, &mut rng); - let point: Vec = (0..num_vars) - .map(|_| ::random(&mut rng)) - .collect(); + let point: Vec = (0..num_vars).map(|_| Fr::random(&mut rng)).collect(); let eval = poly.evaluate(&point); let (commitment, hint) = DoryScheme::commit(poly.evaluations(), &prover_setup); @@ -385,9 +369,7 @@ fn zk_wrong_transcript_domain_rejected() { let prover_setup = DoryScheme::setup_prover(num_vars); let verifier_setup = DoryScheme::setup_verifier(num_vars); let poly = Polynomial::::random(num_vars, &mut rng); - let point: Vec = (0..num_vars) - .map(|_| ::random(&mut rng)) - .collect(); + let point: Vec = (0..num_vars).map(|_| Fr::random(&mut rng)).collect(); let eval = poly.evaluate(&point); let (commitment, hint) = DoryScheme::commit(poly.evaluations(), &prover_setup); diff --git a/crates/jolt-field/benches/field_arith.rs b/crates/jolt-field/benches/field_arith.rs index cfe784f76c..2125b1035a 100644 --- a/crates/jolt-field/benches/field_arith.rs +++ b/crates/jolt-field/benches/field_arith.rs @@ -3,14 +3,14 @@ use std::hint::black_box; use criterion::{criterion_group, criterion_main, Criterion}; -use jolt_field::{FixedBytes, Fr, MulPrimitiveInt, RandomSampling}; +use jolt_field::{Field, Fr}; use rand_chacha::ChaCha20Rng; use rand_core::SeedableRng; fn bench_field_mul(c: &mut Criterion) { let mut rng = ChaCha20Rng::seed_from_u64(0); - let a: Fr = ::random(&mut rng); - let b: Fr = ::random(&mut rng); + let a: Fr = Field::random(&mut rng); + let b: Fr = Field::random(&mut rng); c.bench_function("Fr * Fr", |bench| { bench.iter(|| black_box(a) * black_box(b)); @@ -19,35 +19,35 @@ fn bench_field_mul(c: &mut Criterion) { fn bench_mul_u64(c: &mut Criterion) { let mut rng = ChaCha20Rng::seed_from_u64(1); - let a: Fr = ::random(&mut rng); + let a: Fr = Field::random(&mut rng); let n = 0xDEAD_BEEF_CAFE_BABEu64; c.bench_function("Fr::mul_u64", |bench| { - bench.iter(|| ::mul_u64(black_box(&a), black_box(n))); + bench.iter(|| ::mul_u64(black_box(&a), black_box(n))); }); } fn bench_mul_u128(c: &mut Criterion) { let mut rng = ChaCha20Rng::seed_from_u64(2); - let a: Fr = ::random(&mut rng); + let a: Fr = Field::random(&mut rng); let n = 0xDEAD_BEEF_CAFE_BABE_1234_5678_9ABC_DEF0u128; c.bench_function("Fr::mul_u128", |bench| { - bench.iter(|| ::mul_u128(black_box(&a), black_box(n))); + bench.iter(|| ::mul_u128(black_box(&a), black_box(n))); }); } fn bench_to_from_bytes(c: &mut Criterion) { let mut rng = ChaCha20Rng::seed_from_u64(4); - let a: Fr = ::random(&mut rng); - let bytes = a.to_bytes_array(); + let a: Fr = Field::random(&mut rng); + let bytes = a.to_bytes(); c.bench_function("Fr::to_bytes", |bench| { - bench.iter(|| black_box(a).to_bytes_array()); + bench.iter(|| black_box(a).to_bytes()); }); c.bench_function("Fr::from_bytes", |bench| { - bench.iter(|| Fr::from_bytes_array(black_box(&bytes))); + bench.iter(|| ::from_bytes(black_box(&bytes))); }); } diff --git a/crates/jolt-field/fuzz/fuzz_targets/field_arith.rs b/crates/jolt-field/fuzz/fuzz_targets/field_arith.rs index 4e71b313d7..e8dd4901e5 100644 --- a/crates/jolt-field/fuzz/fuzz_targets/field_arith.rs +++ b/crates/jolt-field/fuzz/fuzz_targets/field_arith.rs @@ -1,5 +1,5 @@ #![no_main] -use jolt_field::{Fr, FromPrimitiveInt, Invertible, ReducingBytes}; +use jolt_field::{Field, Fr}; use libfuzzer_sys::fuzz_target; use num_traits::Zero; @@ -7,8 +7,8 @@ fuzz_target!(|data: &[u8]| { if data.len() < 64 { return; } - let a = ::from_le_bytes_mod_order(&data[..32]); - let b = ::from_le_bytes_mod_order(&data[32..64]); + let a = ::from_bytes(&data[..32]); + let b = ::from_bytes(&data[32..64]); // Arithmetic operations must not panic let sum = a + b; diff --git a/crates/jolt-field/fuzz/fuzz_targets/from_bytes.rs b/crates/jolt-field/fuzz/fuzz_targets/from_bytes.rs index d8fcbf633d..6cafc11ef2 100644 --- a/crates/jolt-field/fuzz/fuzz_targets/from_bytes.rs +++ b/crates/jolt-field/fuzz/fuzz_targets/from_bytes.rs @@ -1,14 +1,14 @@ #![no_main] -use jolt_field::{FixedBytes, Fr, ReducingBytes}; +use jolt_field::{Field, Fr}; use libfuzzer_sys::fuzz_target; fuzz_target!(|data: &[u8]| { // from_bytes should never panic on arbitrary input - let a = ::from_le_bytes_mod_order(data); + let a = ::from_bytes(data); // Round-trip: from_bytes → to_bytes → from_bytes must be stable - let bytes = a.to_bytes_array(); - let b = ::from_le_bytes_mod_order(&bytes); - let bytes2 = b.to_bytes_array(); + let bytes = a.to_bytes(); + let b = ::from_bytes(&bytes); + let bytes2 = b.to_bytes(); assert_eq!(bytes, bytes2, "from_bytes round-trip is not stable"); }); diff --git a/crates/jolt-field/fuzz/fuzz_targets/wide_accumulator_fmadd.rs b/crates/jolt-field/fuzz/fuzz_targets/wide_accumulator_fmadd.rs index 84c149a022..58ca65edc8 100644 --- a/crates/jolt-field/fuzz/fuzz_targets/wide_accumulator_fmadd.rs +++ b/crates/jolt-field/fuzz/fuzz_targets/wide_accumulator_fmadd.rs @@ -1,5 +1,5 @@ #![no_main] -use jolt_field::{AdditiveAccumulator, Fr, ReducingBytes, RingAccumulator, WideAccumulator}; +use jolt_field::{Field, FieldAccumulator, Fr, WideAccumulator}; use libfuzzer_sys::fuzz_target; use num_traits::Zero; @@ -16,9 +16,8 @@ fuzz_target!(|data: &[u8]| { let pairs = data.len() / 64; for i in 0..pairs { let offset = i * 64; - let a = ::from_le_bytes_mod_order(&data[offset..offset + 32]); - let b = - ::from_le_bytes_mod_order(&data[offset + 32..offset + 64]); + let a = ::from_bytes(&data[offset..offset + 32]); + let b = ::from_bytes(&data[offset + 32..offset + 64]); acc.fmadd(a, b); naive_sum += a * b; diff --git a/crates/jolt-field/fuzz/fuzz_targets/wide_accumulator_merge.rs b/crates/jolt-field/fuzz/fuzz_targets/wide_accumulator_merge.rs index d82049deea..e43b3a1233 100644 --- a/crates/jolt-field/fuzz/fuzz_targets/wide_accumulator_merge.rs +++ b/crates/jolt-field/fuzz/fuzz_targets/wide_accumulator_merge.rs @@ -1,5 +1,5 @@ #![no_main] -use jolt_field::{AdditiveAccumulator, Fr, ReducingBytes, RingAccumulator, WideAccumulator}; +use jolt_field::{Field, FieldAccumulator, Fr, WideAccumulator}; use libfuzzer_sys::fuzz_target; fuzz_target!(|data: &[u8]| { @@ -17,9 +17,8 @@ fuzz_target!(|data: &[u8]| { for i in 0..pairs { let offset = i * 64; - let a = ::from_le_bytes_mod_order(&data[offset..offset + 32]); - let b = - ::from_le_bytes_mod_order(&data[offset + 32..offset + 64]); + let a = ::from_bytes(&data[offset..offset + 32]); + let b = ::from_bytes(&data[offset + 32..offset + 64]); if i < split { acc1.fmadd(a, b); diff --git a/crates/jolt-field/src/accumulator.rs b/crates/jolt-field/src/accumulator.rs index 74143bdb55..b2adc8edef 100644 --- a/crates/jolt-field/src/accumulator.rs +++ b/crates/jolt-field/src/accumulator.rs @@ -1,7 +1,7 @@ -//! Deferred-reduction accumulators. +//! Deferred-reduction accumulator for fused multiply-add. //! //! In sumcheck inner loops, many products are summed before the final result -//! is needed. [`RingAccumulator`] lets implementations defer modular reduction +//! is needed. [`FieldAccumulator`] lets implementations defer modular reduction //! by accumulating in wider integer types, reducing once at the end. This //! amortizes the expensive reduction across hundreds of multiply-add steps. //! @@ -9,31 +9,16 @@ //! - `WideAccumulator` (BN254, in `arkworks/`) — 9-limb wide integer accumulator //! that defers Montgomery reduction. -use crate::{AdditiveGroup, FromPrimitiveInt, RingCore}; +use crate::Field; use num_traits::One; -/// Accumulates additive values with potentially deferred reduction. -pub trait AdditiveAccumulator: Default + Copy + Send + Sync { - /// The element type this accumulator reduces to. - type Element: AdditiveGroup; - - /// Adds one element into the accumulator. - fn add(&mut self, value: Self::Element); - - /// Merge another accumulator's partial sum into this one. - fn merge(&mut self, other: Self); - - /// Finalize: reduce the accumulated value to an element. - fn reduce(self) -> Self::Element; -} - /// Accumulates products with potentially deferred modular reduction. /// /// The hot loop pattern `acc += a * b` repeated hundreds of times per output /// slot dominates the CPU prover. Standard field arithmetic reduces mod p /// after every multiply and every add. Implementations for specific fields /// (e.g., BN254 Fr) can instead accumulate unreduced wide products and -/// reduce once at the end via [`AdditiveAccumulator::reduce`]. +/// reduce once at the end via [`reduce`](Self::reduce). /// /// # Invariants /// @@ -42,63 +27,104 @@ pub trait AdditiveAccumulator: Default + Copy + Send + Sync { /// partial result (used for parallel reduction). /// - [`reduce`](Self::reduce) must return the field element equal to the /// accumulated sum of products. -pub trait RingAccumulator: AdditiveAccumulator -where - Self::Element: RingCore + FromPrimitiveInt, -{ +pub trait FieldAccumulator: Default + Copy + Send + Sync { + /// The field type this accumulator operates over. + type Field: crate::Field; + /// Fused multiply-add: `self += a * b` without intermediate reduction. - fn fmadd(&mut self, a: Self::Element, b: Self::Element); + fn fmadd(&mut self, a: Self::Field, b: Self::Field); /// Fused multiply-add with a `u8` scalar: `self += a * F::from(b)`. /// /// Implementations may override for optimized small-scalar multiplication /// (e.g., 4×1 limb schoolbook instead of 4×4). #[inline] - fn fmadd_u8(&mut self, a: Self::Element, b: u8) { - self.fmadd(a, Self::Element::from_u8(b)); + fn fmadd_u8(&mut self, a: Self::Field, b: u8) { + self.fmadd(a, Self::Field::from_u8(b)); } /// Fused multiply-add with a `u64` scalar: `self += a * F::from(b)`. #[inline] - fn fmadd_u64(&mut self, a: Self::Element, b: u64) { - self.fmadd(a, Self::Element::from_u64(b)); + fn fmadd_u64(&mut self, a: Self::Field, b: u64) { + self.fmadd(a, Self::Field::from_u64(b)); } /// Fused multiply-add with an `i64` scalar: `self += a * F::from(b)`. #[inline] - fn fmadd_i64(&mut self, a: Self::Element, b: i64) { - self.fmadd(a, Self::Element::from_i64(b)); + fn fmadd_i64(&mut self, a: Self::Field, b: i64) { + self.fmadd(a, Self::Field::from_i64(b)); } /// Fused multiply-add with a `bool` scalar: `self += a` when `b` is true. #[inline] - fn fmadd_bool(&mut self, a: Self::Element, b: bool) { + fn fmadd_bool(&mut self, a: Self::Field, b: bool) { if b { - self.fmadd(a, ::one()); + self.fmadd(a, ::one()); } } + + /// Accumulate a field element with unit weight: `self += val`. + #[inline] + fn acc_add(&mut self, val: Self::Field) { + self.fmadd(::one(), val); + } + + /// Merge another accumulator's partial sum into this one. + /// + /// Used in parallel reduction (e.g., Rayon fold+reduce) where each thread + /// accumulates independently, then results are combined. + fn merge(&mut self, other: Self); + + /// Finalize: reduce the accumulated value to a field element. + fn reduce(self) -> Self::Field; +} + +/// Accumulates products of field elements with small integer scalars. +/// +/// This is the raw-scalar analogue of [`FieldAccumulator`]. It is useful when a +/// hot loop repeatedly adds terms of the form `a * n`, where `n` is a `u64` or +/// `u128` known outside the field. Implementations may defer the modular +/// reduction across many bucketed additions. +pub trait FieldScalarAccumulator: Default + Copy + Send + Sync { + /// The field type this accumulator operates over. + type Field: crate::Field; + + /// Accumulate a field element with unit scalar. + fn add(&mut self, value: Self::Field); + + /// Fused multiply-add with a `u64` scalar: `self += value * scalar`. + fn add_mul_u64(&mut self, value: Self::Field, scalar: u64); + + /// Fused multiply-add with a `u128` scalar: `self += value * scalar`. + fn add_mul_u128(&mut self, value: Self::Field, scalar: u128); + + /// Merge another accumulator's partial sum into this one. + fn merge(&mut self, other: Self); + + /// Finalize to a field element. + fn reduce(self) -> Self::Field; } /// Naive accumulator using standard field arithmetic. /// -/// Every [`fmadd`](RingAccumulator::fmadd) performs a full modular multiply +/// Every [`fmadd`](FieldAccumulator::fmadd) performs a full modular multiply /// and add. Used as a fallback for fields without wide-integer optimization. #[derive(Clone, Copy)] -pub struct NaiveAccumulator(R); +pub struct NaiveAccumulator(F); -impl Default for NaiveAccumulator { +impl Default for NaiveAccumulator { #[inline] fn default() -> Self { - Self(R::zero()) + Self(F::zero()) } } -impl AdditiveAccumulator for NaiveAccumulator { - type Element = R; +impl FieldAccumulator for NaiveAccumulator { + type Field = F; #[inline] - fn add(&mut self, value: R) { - self.0 += value; + fn fmadd(&mut self, a: F, b: F) { + self.0 += a * b; } #[inline] @@ -107,14 +133,47 @@ impl AdditiveAccumulator for NaiveAccumulator } #[inline] - fn reduce(self) -> R { + fn reduce(self) -> F { self.0 } } -impl RingAccumulator for NaiveAccumulator { +/// Naive raw-scalar accumulator using ordinary field arithmetic. +#[derive(Clone, Copy)] +pub struct NaiveScalarAccumulator(F); + +impl Default for NaiveScalarAccumulator { #[inline] - fn fmadd(&mut self, a: R, b: R) { - self.0 += a * b; + fn default() -> Self { + Self(F::zero()) + } +} + +impl FieldScalarAccumulator for NaiveScalarAccumulator { + type Field = F; + + #[inline] + fn add(&mut self, value: F) { + self.0 += value; + } + + #[inline] + fn add_mul_u64(&mut self, value: F, scalar: u64) { + self.0 += value.mul_u64(scalar); + } + + #[inline] + fn add_mul_u128(&mut self, value: F, scalar: u128) { + self.0 += value.mul_u128(scalar); + } + + #[inline] + fn merge(&mut self, other: Self) { + self.0 += other.0; + } + + #[inline] + fn reduce(self) -> F { + self.0 } } diff --git a/crates/jolt-field/src/additive_group.rs b/crates/jolt-field/src/additive_group.rs deleted file mode 100644 index cd7146d885..0000000000 --- a/crates/jolt-field/src/additive_group.rs +++ /dev/null @@ -1,20 +0,0 @@ -use num_traits::Zero; -use std::ops::{Add, AddAssign, Neg, Sub, SubAssign}; - -/// Minimal additive group operations shared by fields, rings, and accumulators. -pub trait AdditiveGroup: - Sized - + Clone - + Copy - + Send - + Sync - + Zero - + Add - + for<'a> Add<&'a Self, Output = Self> - + AddAssign - + Sub - + for<'a> Sub<&'a Self, Output = Self> - + SubAssign - + Neg -{ -} diff --git a/crates/jolt-field/src/arkworks/bn254.rs b/crates/jolt-field/src/arkworks/bn254.rs index df579d70ad..2c4161429a 100644 --- a/crates/jolt-field/src/arkworks/bn254.rs +++ b/crates/jolt-field/src/arkworks/bn254.rs @@ -2,11 +2,7 @@ //! //! [`Fr`] is `#[repr(transparent)]` over the inner arkworks scalar field element, //! so it has identical layout and can be transmuted where needed. -use crate::{ - AdditiveGroup, CanonicalBitLength, CanonicalBytes, CanonicalU64, Field, FieldCore, - FixedByteSize, FixedBytes, FromPrimitiveInt, Invertible, Limbs, MulPrimitiveInt, - RandomSampling, ReducingBytes, RingCore, TranscriptChallenge, WithAccumulator, -}; +use crate::{Field, Limbs}; use ark_ff::{prelude::*, PrimeField, UniformRand}; use rand_core::RngCore; @@ -38,56 +34,56 @@ impl From for ark_bn254::Fr { impl From for Fr { #[inline(always)] fn from(v: bool) -> Self { - ::from_bool(v) + ::from_bool(v) } } impl From for Fr { #[inline(always)] fn from(v: u8) -> Self { - ::from_u64(v as u64) + ::from_u64(v as u64) } } impl From for Fr { #[inline(always)] fn from(v: u16) -> Self { - ::from_u64(v as u64) + ::from_u64(v as u64) } } impl From for Fr { #[inline(always)] fn from(v: u32) -> Self { - ::from_u64(v as u64) + ::from_u64(v as u64) } } impl From for Fr { #[inline(always)] fn from(v: u64) -> Self { - ::from_u64(v) + ::from_u64(v) } } impl From for Fr { #[inline(always)] fn from(v: i64) -> Self { - ::from_i64(v) + ::from_i64(v) } } impl From for Fr { #[inline(always)] fn from(v: i128) -> Self { - ::from_i128(v) + ::from_i128(v) } } impl From for Fr { #[inline(always)] fn from(v: u128) -> Self { - ::from_u128(v) + ::from_u128(v) } } @@ -298,6 +294,12 @@ impl Fr { Fr(bn254_ops::from_bigint_unchecked(limbs.into())) } + /// Barrett-reduces an unreduced internal-representation integer. + #[inline(always)] + pub fn from_barrett_reduced_limbs(limbs: Limbs) -> Self { + Fr(bn254_ops::from_barrett_reduce(limbs.into())) + } + /// Access the internal Montgomery-form limbs. /// /// Used by [`WideAccumulator`](super::wide_accumulator::WideAccumulator) @@ -314,86 +316,54 @@ impl Fr { } } -impl AdditiveGroup for Fr {} - -impl RingCore for Fr { - #[inline] - fn square(&self) -> Self { - Fr(::square(&self.0)) - } -} - -impl Invertible for Fr { - #[inline] - fn inverse(&self) -> Option { - ::inverse(&self.0).map(Fr) - } -} - -impl FieldCore for Fr {} +impl Field for Fr { + type Accumulator = super::wide_accumulator::WideAccumulator; + type ScalarAccumulator = super::scalar_accumulator::ScalarAccumulator; -impl FixedByteSize for Fr { const NUM_BYTES: usize = 32; -} -impl CanonicalBytes for Fr { #[expect(clippy::expect_used)] - #[inline] - fn to_bytes_le(&self, out: &mut [u8]) { - assert_eq!(out.len(), ::NUM_BYTES); + fn to_bytes(&self) -> [u8; 32] { use ark_serialize::CanonicalSerialize; + let mut buf = [0u8; 32]; self.0 - .serialize_compressed(out) + .serialize_compressed(&mut buf[..]) .expect("BN254 Fr always serializes to 32 bytes"); + buf } -} -impl ReducingBytes for Fr { - #[inline] - fn from_le_bytes_mod_order(bytes: &[u8]) -> Self { - Fr::from_le_bytes_mod_order(bytes) + fn random(rng: &mut R) -> Self { + Fr(::rand(rng)) } -} -impl TranscriptChallenge for Fr { - #[inline] - fn from_challenge_bytes(bytes: &[u8]) -> Self { + fn from_bytes(bytes: &[u8]) -> Self { Fr::from_le_bytes_mod_order(bytes) } -} -impl FixedBytes<32> for Fr {} - -impl CanonicalU64 for Fr { - #[inline] - fn to_canonical_u64_checked(&self) -> Option { + fn to_u64(&self) -> Option { let bigint = ::into_bigint(self.0); let limbs: &[u64] = bigint.as_ref(); let result = limbs[0]; - if ::from_u64(result) != *self { + if ::from_u64(result) != *self { None } else { Some(result) } } -} -impl CanonicalBitLength for Fr { - #[inline] fn num_bits(&self) -> u32 { ::into_bigint(self.0).num_bits() } -} -impl RandomSampling for Fr { - #[inline] - fn random(rng: &mut R) -> Self { - Fr(::rand(rng)) + fn square(&self) -> Self { + Fr(::square(&self.0)) + } + + fn inverse(&self) -> Option { + ::inverse(&self.0).map(Fr) } -} -impl FromPrimitiveInt for Fr { #[inline] fn from_u64(n: u64) -> Self { Fr(bn254_ops::from_u64(n)) @@ -421,15 +391,7 @@ impl FromPrimitiveInt for Fr { fn from_u128(val: u128) -> Self { Fr(bn254_ops::from_u128(val)) } -} - -impl WithAccumulator for Fr { - type Accumulator = super::wide_accumulator::WideAccumulator; -} - -impl crate::MulPow2 for Fr {} -impl MulPrimitiveInt for Fr { #[inline] fn mul_u64(&self, n: u64) -> Self { Fr(bn254_ops::mul_u64(self.0, n)) @@ -451,13 +413,11 @@ impl MulPrimitiveInt for Fr { } } -impl Field for Fr {} - #[cfg(test)] #[expect(clippy::unwrap_used)] mod tests { use super::*; - use crate::{CanonicalU64, FixedBytes}; + use crate::Field; #[test] fn field_arithmetic_basic() { @@ -482,8 +442,8 @@ mod tests { #[test] fn serialization_roundtrip() { let val = Fr::from_u64(123_456_789); - let bytes = val.to_bytes_array(); - let recovered = Fr::from_bytes_array(&bytes); + let bytes = val.to_bytes(); + let recovered = Fr::from_bytes(&bytes); assert_eq!(val, recovered); } @@ -499,10 +459,10 @@ mod tests { #[test] fn to_u64_roundtrip() { - assert_eq!(Fr::from_u64(999).to_canonical_u64_checked(), Some(999)); + assert_eq!(Fr::from_u64(999).to_u64(), Some(999)); // Large field element should not fit in u64 let big = Fr::from_u128(u128::MAX / 2); - assert_eq!(big.to_canonical_u64_checked(), None); + assert_eq!(big.to_u64(), None); } #[test] diff --git a/crates/jolt-field/src/arkworks/bn254_ops.rs b/crates/jolt-field/src/arkworks/bn254_ops.rs index 3a1d061791..a1026c8202 100644 --- a/crates/jolt-field/src/arkworks/bn254_ops.rs +++ b/crates/jolt-field/src/arkworks/bn254_ops.rs @@ -385,6 +385,19 @@ fn from_unchecked_nplus2(element: BigInt<6>) -> Fr { Fp::new_unchecked(r2) } +/// Barrett-reduce an arbitrary little-endian limb integer into a field element. +#[inline(always)] +pub(crate) fn from_barrett_reduce(element: BigInt) -> Fr { + let mut acc = BigInt::([0u64; N]); + let mut i = L; + while i > 0 { + i -= 1; + let chunk = nplus1_from_low_and_high(element.0[i], acc.0); + acc = barrett_reduce_5_to_4(chunk); + } + Fp::new_unchecked(acc) +} + /// Multiply a field element by u64. #[inline(always)] pub(crate) fn mul_u64(a: Fr, b: u64) -> Fr { diff --git a/crates/jolt-field/src/arkworks/mod.rs b/crates/jolt-field/src/arkworks/mod.rs index 841398bb79..b5778f5394 100644 --- a/crates/jolt-field/src/arkworks/mod.rs +++ b/crates/jolt-field/src/arkworks/mod.rs @@ -9,6 +9,7 @@ use ark_ff::BigInt; pub mod bn254; pub(crate) mod bn254_ops; pub mod montgomery_impl; +pub mod scalar_accumulator; pub mod wide_accumulator; impl From> for BigInt { diff --git a/crates/jolt-field/src/arkworks/scalar_accumulator.rs b/crates/jolt-field/src/arkworks/scalar_accumulator.rs new file mode 100644 index 0000000000..ff2d94a407 --- /dev/null +++ b/crates/jolt-field/src/arkworks/scalar_accumulator.rs @@ -0,0 +1,78 @@ +//! Deferred-reduction accumulator for BN254 Fr times raw integer scalars. + +use crate::accumulator::FieldScalarAccumulator; +use crate::arkworks::bn254::Fr; +use crate::Limbs; + +/// Accumulates sums of `Fr * u64/u128` in Montgomery form. +#[derive(Clone, Copy)] +pub struct ScalarAccumulator { + /// A field element has 4 limbs; multiplying by a u128 gives 6 limbs, and + /// the extra limb provides carry headroom for many bucket additions. + limbs: Limbs<7>, +} + +impl Default for ScalarAccumulator { + #[inline] + fn default() -> Self { + Self { + limbs: Limbs::zero(), + } + } +} + +impl FieldScalarAccumulator for ScalarAccumulator { + type Field = Fr; + + #[inline(always)] + fn add(&mut self, value: Fr) { + self.add_mul_u64(value, 1); + } + + #[inline(always)] + fn add_mul_u64(&mut self, value: Fr, scalar: u64) { + if scalar != 0 { + self.limbs + .fmadd::<4, 1>(&value.inner_limbs(), &Limbs::<1>::from_u64(scalar)); + } + } + + #[inline(always)] + fn add_mul_u128(&mut self, value: Fr, scalar: u128) { + if scalar >> 64 == 0 { + self.add_mul_u64(value, scalar as u64); + } else { + let scalar_limbs = Limbs::<2>::new([scalar as u64, (scalar >> 64) as u64]); + self.limbs + .fmadd::<4, 2>(&value.inner_limbs(), &scalar_limbs); + } + } + + #[inline(always)] + fn merge(&mut self, other: Self) { + self.limbs.add_assign_trunc::<7>(&other.limbs); + } + + #[inline(always)] + fn reduce(self) -> Fr { + Fr::from_barrett_reduced_limbs(self.limbs) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::Field; + + #[test] + fn accumulates_raw_scalars() { + let mut acc = ScalarAccumulator::default(); + acc.add(Fr::from_u64(3)); + acc.add_mul_u64(Fr::from_u64(5), 7); + acc.add_mul_u128(Fr::from_u64(11), 1u128 << 80); + + let expected = + Fr::from_u64(3) + Fr::from_u64(5).mul_u64(7) + Fr::from_u64(11).mul_u128(1u128 << 80); + assert_eq!(acc.reduce(), expected); + } +} diff --git a/crates/jolt-field/src/arkworks/wide_accumulator.rs b/crates/jolt-field/src/arkworks/wide_accumulator.rs index ab76c66ab4..b08420c86c 100644 --- a/crates/jolt-field/src/arkworks/wide_accumulator.rs +++ b/crates/jolt-field/src/arkworks/wide_accumulator.rs @@ -9,7 +9,7 @@ //! elements is 8 limbs (512 bits). A 9-limb accumulator (576 bits) can //! hold up to 2^64 such products without overflow. -use crate::accumulator::{AdditiveAccumulator, RingAccumulator}; +use crate::accumulator::FieldAccumulator; use crate::arkworks::bn254::Fr; use crate::Limbs; @@ -19,7 +19,7 @@ use super::bn254_ops; /// /// Stores the running sum of Montgomery-form products as a 576-bit integer. /// Converting to a field element requires a single Montgomery reduction -/// via [`AdditiveAccumulator::reduce`]. +/// via [`reduce`](FieldAccumulator::reduce). #[derive(Clone, Copy)] pub struct WideAccumulator { /// 9 limbs = 2×4 (product width) + 1 (addition headroom). @@ -35,12 +35,12 @@ impl Default for WideAccumulator { } } -impl AdditiveAccumulator for WideAccumulator { - type Element = Fr; +impl FieldAccumulator for WideAccumulator { + type Field = Fr; #[inline(always)] - fn add(&mut self, value: Fr) { - self.fmadd(value, ::one()); + fn fmadd(&mut self, a: Fr, b: Fr) { + self.limbs.fmadd::<4, 4>(&a.inner_limbs(), &b.inner_limbs()); } #[inline(always)] @@ -49,25 +49,18 @@ impl AdditiveAccumulator for WideAccumulator { } fn reduce(self) -> Fr { - // The accumulator holds Montgomery-form products and/or elements. - // Montgomery reduction divides product terms by R; raw element additions - // are already in Montgomery form and live in the low limbs. + // The accumulator holds sum_i (a_i_mont × b_i_mont). + // Montgomery reduction divides by R, yielding the Montgomery form + // of sum_i (a_i × b_i). let bigint = self.limbs.into(); Fr::from_inner(bn254_ops::from_montgomery_reduce(bigint)) } } -impl RingAccumulator for WideAccumulator { - #[inline(always)] - fn fmadd(&mut self, a: Fr, b: Fr) { - self.limbs.fmadd::<4, 4>(&a.inner_limbs(), &b.inner_limbs()); - } -} - #[cfg(test)] mod tests { use super::*; - use crate::{AdditiveAccumulator, FromPrimitiveInt}; + use crate::Field; #[test] fn single_fmadd() { diff --git a/crates/jolt-field/src/canonical_bit_length.rs b/crates/jolt-field/src/canonical_bit_length.rs deleted file mode 100644 index 89664ed862..0000000000 --- a/crates/jolt-field/src/canonical_bit_length.rs +++ /dev/null @@ -1,7 +0,0 @@ -/// Significant-bit introspection for canonical representatives. -pub trait CanonicalBitLength { - /// Number of significant bits in this element's canonical representative. - /// - /// Zero is considered to have zero significant bits. - fn num_bits(&self) -> u32; -} diff --git a/crates/jolt-field/src/canonical_bytes.rs b/crates/jolt-field/src/canonical_bytes.rs deleted file mode 100644 index 6b0363f65c..0000000000 --- a/crates/jolt-field/src/canonical_bytes.rs +++ /dev/null @@ -1,13 +0,0 @@ -/// Canonical little-endian byte encoding. -pub trait CanonicalBytes: Sized + crate::FixedByteSize { - /// Writes the canonical little-endian encoding into `out`. - fn to_bytes_le(&self, out: &mut [u8]); - - /// Returns the canonical little-endian encoding as a vector. - #[inline] - fn to_bytes_le_vec(&self) -> Vec { - let mut out = vec![0u8; Self::NUM_BYTES]; - self.to_bytes_le(&mut out); - out - } -} diff --git a/crates/jolt-field/src/canonical_u64.rs b/crates/jolt-field/src/canonical_u64.rs deleted file mode 100644 index 9d2b8f1cab..0000000000 --- a/crates/jolt-field/src/canonical_u64.rs +++ /dev/null @@ -1,5 +0,0 @@ -/// Checked extraction of canonical representatives that fit in `u64`. -pub trait CanonicalU64 { - /// Returns the canonical representative as `u64` if it fits. - fn to_canonical_u64_checked(&self) -> Option; -} diff --git a/crates/jolt-field/src/field.rs b/crates/jolt-field/src/field.rs index 80c1da6778..0ea3c23409 100644 --- a/crates/jolt-field/src/field.rs +++ b/crates/jolt-field/src/field.rs @@ -1,15 +1,11 @@ #[cfg(feature = "allocative")] use allocative::Allocative; -use serde::{de::DeserializeOwned, Serialize}; +use num_traits::{One, Zero}; +use rand_core::RngCore; +use serde::{Deserialize, Serialize}; use std::fmt::{Debug, Display}; use std::hash::Hash; -use std::ops::Mul; - -use crate::{ - CanonicalBitLength, CanonicalBytes, CanonicalU64, FieldCore, FixedByteSize, FixedBytes, - FromPrimitiveInt, MulPow2, MulPrimitiveInt, RandomSampling, ReducingBytes, RingCore, - TranscriptChallenge, WithAccumulator, -}; +use std::ops::{Add, AddAssign, Div, Mul, MulAssign, Neg, Sub, SubAssign}; /// Prime field element abstraction used throughout Jolt. /// @@ -22,31 +18,116 @@ use crate::{ pub trait Field: 'static + Sized + + Zero + + One + + Neg + + Add + + for<'a> Add<&'a Self, Output = Self> + + Sub + + for<'a> Sub<&'a Self, Output = Self> + + Mul + + for<'a> Mul<&'a Self, Output = Self> + + Div + + for<'a> Div<&'a Self, Output = Self> + + AddAssign + + SubAssign + + MulAssign + + core::iter::Sum + + for<'a> core::iter::Sum<&'a Self> + + core::iter::Product + + for<'a> core::iter::Product<&'a Self> + + Eq + Copy + Sync + Send - + Default - + Eq - + Hash + Display + Debug - + FieldCore - + FromPrimitiveInt - + CanonicalBytes - + ReducingBytes - + TranscriptChallenge - + FixedBytes<32> - + FixedByteSize - + CanonicalBitLength - + CanonicalU64 - + RandomSampling - + WithAccumulator - + MulPow2 - + MulPrimitiveInt + + Default + + Hash + Serialize - + DeserializeOwned + + for<'de> Deserialize<'de> + MaybeAllocative { + /// Accumulator for deferred-reduction fused multiply-add. + /// + /// For BN254 Fr, this is a wide 9-limb integer that defers Montgomery + /// reduction. For other fields, use [`NaiveAccumulator`](crate::NaiveAccumulator). + type Accumulator: crate::FieldAccumulator; + + /// Accumulator for deferred-reduction field × raw-integer additions. + type ScalarAccumulator: crate::FieldScalarAccumulator; + + /// Byte length of a canonical (compressed) serialized element. + const NUM_BYTES: usize; + + /// Serializes to compressed canonical form (little-endian, 32 bytes). + fn to_bytes(&self) -> [u8; 32]; + + /// Samples a uniformly random field element. + fn random(rng: &mut R) -> Self; + /// Deserializes from little-endian bytes, reducing modulo the field prime. + fn from_bytes(bytes: &[u8]) -> Self; + /// Returns the value as `u64` if it fits, or `None` if >= 2^64. + fn to_u64(&self) -> Option; + /// Number of significant bits in the canonical representation. + fn num_bits(&self) -> u32; + /// Returns `self * self`. + fn square(&self) -> Self; + /// Multiplicative inverse, or `None` for the zero element. + fn inverse(&self) -> Option; + + fn from_bool(val: bool) -> Self { + if val { + Self::one() + } else { + Self::zero() + } + } + fn from_u8(n: u8) -> Self { + Self::from_u64(n as u64) + } + fn from_u16(n: u16) -> Self { + Self::from_u64(n as u64) + } + fn from_u32(n: u32) -> Self { + Self::from_u64(n as u64) + } + fn from_u64(n: u64) -> Self; + /// Maps a signed integer to its canonical field representative: negative + /// values become `p - |val|`. + fn from_i64(val: i64) -> Self; + /// Maps a signed integer to its canonical field representative: negative + /// values become `p - |val|`. + fn from_i128(val: i128) -> Self; + fn from_u128(val: u128) -> Self; + + fn mul_u64(&self, n: u64) -> Self { + *self * Self::from_u64(n) + } + + fn mul_i64(&self, n: i64) -> Self { + *self * Self::from_i64(n) + } + + fn mul_u128(&self, n: u128) -> Self { + *self * Self::from_u128(n) + } + + fn mul_i128(&self, n: i128) -> Self { + *self * Self::from_i128(n) + } + + /// Multiplication of a field element and a power of 2. + /// Split into chunks of 63 bits, then multiply and accumulate. + fn mul_pow_2(&self, mut pow: usize) -> Self { + assert!(pow <= 255, "pow > 255"); + let mut res = *self; + while pow >= 64 { + res = res.mul_u64(1 << 63); + pow -= 63; + } + res.mul_u64(1 << pow) + } } #[cfg(feature = "allocative")] @@ -73,7 +154,7 @@ pub trait OptimizedMul: Sized + Mul { impl OptimizedMul for F where - F: RingCore, + F: Field, { #[inline(always)] fn mul_0_optimized(self, other: F) -> F { diff --git a/crates/jolt-field/src/field_core.rs b/crates/jolt-field/src/field_core.rs deleted file mode 100644 index d9a6f5eee7..0000000000 --- a/crates/jolt-field/src/field_core.rs +++ /dev/null @@ -1,4 +0,0 @@ -use crate::{Invertible, RingCore}; - -/// Algebraic field marker: ring arithmetic plus explicit inversion. -pub trait FieldCore: RingCore + Invertible {} diff --git a/crates/jolt-field/src/fixed_byte_size.rs b/crates/jolt-field/src/fixed_byte_size.rs deleted file mode 100644 index 09e1ac47a4..0000000000 --- a/crates/jolt-field/src/fixed_byte_size.rs +++ /dev/null @@ -1,5 +0,0 @@ -/// Fixed byte-size metadata for canonical encodings. -pub trait FixedByteSize { - /// Byte length of the fixed-size encoding. - const NUM_BYTES: usize; -} diff --git a/crates/jolt-field/src/fixed_bytes.rs b/crates/jolt-field/src/fixed_bytes.rs deleted file mode 100644 index 6f465be63b..0000000000 --- a/crates/jolt-field/src/fixed_bytes.rs +++ /dev/null @@ -1,19 +0,0 @@ -use crate::{CanonicalBytes, FixedByteSize, ReducingBytes}; - -/// Fixed-array convenience API for canonical field/value encodings. -pub trait FixedBytes: CanonicalBytes + ReducingBytes + FixedByteSize { - /// Returns the canonical fixed-size byte encoding. - #[inline] - fn to_bytes_array(&self) -> [u8; N] { - debug_assert_eq!(Self::NUM_BYTES, N); - let mut out = [0u8; N]; - self.to_bytes_le(&mut out); - out - } - - /// Reducing constructor from a fixed-size byte array. - #[inline] - fn from_bytes_array(bytes: &[u8; N]) -> Self { - Self::from_le_bytes_mod_order(bytes) - } -} diff --git a/crates/jolt-field/src/from_primitive_int.rs b/crates/jolt-field/src/from_primitive_int.rs deleted file mode 100644 index 31cf1aef12..0000000000 --- a/crates/jolt-field/src/from_primitive_int.rs +++ /dev/null @@ -1,46 +0,0 @@ -/// Embed primitive integer values into a scalar object. -pub trait FromPrimitiveInt: Sized { - #[inline] - fn from_bool(v: bool) -> Self { - if v { - Self::from_u64(1) - } else { - Self::from_u64(0) - } - } - - #[inline] - fn from_u8(v: u8) -> Self { - Self::from_u64(v as u64) - } - - #[inline] - fn from_i8(v: i8) -> Self { - Self::from_i64(v as i64) - } - - #[inline] - fn from_u16(v: u16) -> Self { - Self::from_u64(v as u64) - } - - #[inline] - fn from_i16(v: i16) -> Self { - Self::from_i64(v as i64) - } - - #[inline] - fn from_u32(v: u32) -> Self { - Self::from_u64(v as u64) - } - - #[inline] - fn from_i32(v: i32) -> Self { - Self::from_i64(v as i64) - } - - fn from_u64(v: u64) -> Self; - fn from_i64(v: i64) -> Self; - fn from_u128(v: u128) -> Self; - fn from_i128(v: i128) -> Self; -} diff --git a/crates/jolt-field/src/invertible.rs b/crates/jolt-field/src/invertible.rs deleted file mode 100644 index 5e15491d5a..0000000000 --- a/crates/jolt-field/src/invertible.rs +++ /dev/null @@ -1,13 +0,0 @@ -use crate::RingCore; - -/// Ring-level inversion capability with explicit zero handling. -pub trait Invertible: RingCore { - /// Multiplicative inverse, or `None` for the zero element. - fn inverse(&self) -> Option; - - /// Multiplicative inverse with zero mapped to zero. - #[inline] - fn inv_or_zero(self) -> Self { - self.inverse().unwrap_or_else(Self::zero) - } -} diff --git a/crates/jolt-field/src/lib.rs b/crates/jolt-field/src/lib.rs index 143c649521..0f514c4269 100644 --- a/crates/jolt-field/src/lib.rs +++ b/crates/jolt-field/src/lib.rs @@ -1,21 +1,12 @@ -//! Field and ring abstractions for the Jolt zkVM. +//! Field abstractions for the Jolt zkVM. //! -//! This crate exposes a slim algebraic hierarchy under Jolt's compatibility -//! [`Field`] bundle: -//! -//! ```text -//! AdditiveGroup -> RingCore -> FieldCore -//! \-> Invertible -//! ``` -//! -//! Serialization, sampling, transcript challenges, primitive-integer embedding, -//! and accumulator support are separate capabilities so non-BN254 fields can -//! opt into only the surface they actually provide. +//! Backend-agnostic interface over prime-order scalar fields, currently +//! implemented for BN254 Fr. Leaf crate with no internal Jolt dependencies. //! //! # Core traits //! -//! - [`Field`] — Jolt compatibility umbrella -//! - [`RingAccumulator`] — deferred-reduction fused multiply-add +//! - [`Field`] — prime field element (`Copy`, thread-safe, serializable) +//! - [`FieldAccumulator`] — deferred-reduction fused multiply-add //! - [`OptimizedMul`] — fast-path short-circuits for zero/one //! - [`MontgomeryConstants`] — Montgomery form constants for GPU backends //! @@ -29,45 +20,14 @@ //! - [`Limbs`] — fixed-width limb array for unreduced arithmetic //! - [`signed`] module — `S64`, `S128`, `S192`, `S256` and half-limb variants -mod accumulator; -mod additive_group; -mod canonical_bit_length; -mod canonical_bytes; -mod canonical_u64; mod field; -mod field_core; -mod fixed_byte_size; -mod fixed_bytes; -mod from_primitive_int; -mod invertible; -mod montgomery_constants; -mod mul_pow_2; -mod mul_primitive_int; -mod random_sampling; -mod reducing_bytes; -mod ring_core; -mod transcript_challenge; -mod with_accumulator; - -pub use accumulator::{AdditiveAccumulator, NaiveAccumulator, RingAccumulator}; -pub use additive_group::AdditiveGroup; -pub use canonical_bit_length::CanonicalBitLength; -pub use canonical_bytes::CanonicalBytes; -pub use canonical_u64::CanonicalU64; pub use field::{Field, MaybeAllocative, OptimizedMul}; -pub use field_core::FieldCore; -pub use fixed_byte_size::FixedByteSize; -pub use fixed_bytes::FixedBytes; -pub use from_primitive_int::FromPrimitiveInt; -pub use invertible::Invertible; +mod accumulator; +pub use accumulator::{ + FieldAccumulator, FieldScalarAccumulator, NaiveAccumulator, NaiveScalarAccumulator, +}; +mod montgomery_constants; pub use montgomery_constants::MontgomeryConstants; -pub use mul_pow_2::MulPow2; -pub use mul_primitive_int::MulPrimitiveInt; -pub use random_sampling::RandomSampling; -pub use reducing_bytes::ReducingBytes; -pub use ring_core::RingCore; -pub use transcript_challenge::TranscriptChallenge; -pub use with_accumulator::WithAccumulator; pub mod limbs; pub use limbs::Limbs; diff --git a/crates/jolt-field/src/mul_pow_2.rs b/crates/jolt-field/src/mul_pow_2.rs deleted file mode 100644 index dbc30ee975..0000000000 --- a/crates/jolt-field/src/mul_pow_2.rs +++ /dev/null @@ -1,17 +0,0 @@ -use crate::{FromPrimitiveInt, RingCore}; - -/// Multiplication by powers of two. -pub trait MulPow2: RingCore + FromPrimitiveInt { - /// Multiplies this ring element by the integer `2^pow`. - #[inline] - fn mul_pow_2(&self, pow: usize) -> Self { - assert!(pow <= 255, "pow > 255"); - let mut res = *self; - let mut p = pow; - while p >= 64 { - res *= Self::from_u64(1 << 63); - p -= 63; - } - res * Self::from_u64(1 << p) - } -} diff --git a/crates/jolt-field/src/mul_primitive_int.rs b/crates/jolt-field/src/mul_primitive_int.rs deleted file mode 100644 index 4980596de0..0000000000 --- a/crates/jolt-field/src/mul_primitive_int.rs +++ /dev/null @@ -1,28 +0,0 @@ -use crate::{FromPrimitiveInt, RingCore}; - -/// Multiplication by primitive integer scalars. -pub trait MulPrimitiveInt: RingCore + FromPrimitiveInt { - /// Multiplies by a `u64`. - #[inline(always)] - fn mul_u64(&self, n: u64) -> Self { - *self * Self::from_u64(n) - } - - /// Multiplies by an `i64`. - #[inline(always)] - fn mul_i64(&self, n: i64) -> Self { - *self * Self::from_i64(n) - } - - /// Multiplies by a `u128`. - #[inline(always)] - fn mul_u128(&self, n: u128) -> Self { - *self * Self::from_u128(n) - } - - /// Multiplies by an `i128`. - #[inline(always)] - fn mul_i128(&self, n: i128) -> Self { - *self * Self::from_i128(n) - } -} diff --git a/crates/jolt-field/src/random_sampling.rs b/crates/jolt-field/src/random_sampling.rs deleted file mode 100644 index ea56da35fb..0000000000 --- a/crates/jolt-field/src/random_sampling.rs +++ /dev/null @@ -1,7 +0,0 @@ -use rand_core::RngCore; - -/// RNG-backed sampling for tests and witnesses. -pub trait RandomSampling { - /// Samples a random element. - fn random(rng: &mut R) -> Self; -} diff --git a/crates/jolt-field/src/reducing_bytes.rs b/crates/jolt-field/src/reducing_bytes.rs deleted file mode 100644 index 89d4302105..0000000000 --- a/crates/jolt-field/src/reducing_bytes.rs +++ /dev/null @@ -1,5 +0,0 @@ -/// Reducing little-endian byte constructor. -pub trait ReducingBytes: Sized { - /// Deserializes little-endian bytes by reducing into this type. - fn from_le_bytes_mod_order(bytes: &[u8]) -> Self; -} diff --git a/crates/jolt-field/src/ring_core.rs b/crates/jolt-field/src/ring_core.rs deleted file mode 100644 index 5c28b820d5..0000000000 --- a/crates/jolt-field/src/ring_core.rs +++ /dev/null @@ -1,33 +0,0 @@ -use crate::AdditiveGroup; -use num_traits::One; -use std::{ - fmt::{Debug, Display}, - hash::Hash, - iter::{Product, Sum}, - ops::{Mul, MulAssign}, -}; - -/// Core ring arithmetic: additive group plus multiplication and one. -pub trait RingCore: - AdditiveGroup - + One - + PartialEq - + Eq - + Default - + Debug - + Display - + Hash - + Mul - + for<'a> Mul<&'a Self, Output = Self> - + MulAssign - + Sum - + for<'a> Sum<&'a Self> - + Product - + for<'a> Product<&'a Self> -{ - /// Returns `self * self`. - #[inline] - fn square(&self) -> Self { - *self * *self - } -} diff --git a/crates/jolt-field/src/transcript_challenge.rs b/crates/jolt-field/src/transcript_challenge.rs deleted file mode 100644 index 9fd5a4d2e8..0000000000 --- a/crates/jolt-field/src/transcript_challenge.rs +++ /dev/null @@ -1,7 +0,0 @@ -/// Fiat-Shamir challenge decoding from squeezed transcript bytes. -pub trait TranscriptChallenge: - Sized + Copy + Default + PartialEq + Eq + std::fmt::Debug + std::hash::Hash + Sync + Send + 'static -{ - /// Constructs a challenge from transcript bytes. - fn from_challenge_bytes(bytes: &[u8]) -> Self; -} diff --git a/crates/jolt-field/src/with_accumulator.rs b/crates/jolt-field/src/with_accumulator.rs deleted file mode 100644 index 65c50cc90d..0000000000 --- a/crates/jolt-field/src/with_accumulator.rs +++ /dev/null @@ -1,7 +0,0 @@ -use crate::{AdditiveAccumulator, AdditiveGroup}; - -/// Associates an additive redundant accumulator with an element type. -pub trait WithAccumulator: AdditiveGroup { - /// Accumulator type. - type Accumulator: AdditiveAccumulator; -} diff --git a/crates/jolt-field/tests/coverage.rs b/crates/jolt-field/tests/coverage.rs index e083e2696b..d59d073440 100644 --- a/crates/jolt-field/tests/coverage.rs +++ b/crates/jolt-field/tests/coverage.rs @@ -7,43 +7,34 @@ use ark_std::test_rng; use jolt_field::signed::*; -use jolt_field::{ - AdditiveAccumulator, FixedBytes, Fr, FromPrimitiveInt, Limbs, MulPow2, NaiveAccumulator, - OptimizedMul, RandomSampling, RingAccumulator, -}; +use jolt_field::{Field, FieldAccumulator, Fr, Limbs, NaiveAccumulator, OptimizedMul}; use num_traits::{One, Zero}; #[test] fn naive_accumulator_fmadd() { - let a = ::from_u64(7); - let b = ::from_u64(11); - let c = ::from_u64(3); - let d = ::from_u64(5); + let a = ::from_u64(7); + let b = ::from_u64(11); + let c = ::from_u64(3); + let d = ::from_u64(5); let mut acc = NaiveAccumulator::::default(); acc.fmadd(a, b); acc.fmadd(c, d); // 7*11 + 3*5 = 77 + 15 = 92 - assert_eq!(acc.reduce(), ::from_u64(92)); + assert_eq!(acc.reduce(), ::from_u64(92)); } #[test] fn naive_accumulator_merge() { let mut acc1 = NaiveAccumulator::::default(); - acc1.fmadd( - ::from_u64(2), - ::from_u64(3), - ); + acc1.fmadd(::from_u64(2), ::from_u64(3)); let mut acc2 = NaiveAccumulator::::default(); - acc2.fmadd( - ::from_u64(4), - ::from_u64(5), - ); + acc2.fmadd(::from_u64(4), ::from_u64(5)); acc1.merge(acc2); // 2*3 + 4*5 = 6 + 20 = 26 - assert_eq!(acc1.reduce(), ::from_u64(26)); + assert_eq!(acc1.reduce(), ::from_u64(26)); } #[test] @@ -56,12 +47,12 @@ fn naive_accumulator_reduce_empty() { fn wide_accumulator_fmadd() { use jolt_field::WideAccumulator; - let a = ::from_u64(13); - let b = ::from_u64(17); + let a = ::from_u64(13); + let b = ::from_u64(17); let mut acc = WideAccumulator::default(); acc.fmadd(a, b); - assert_eq!(acc.reduce(), ::from_u64(13 * 17)); + assert_eq!(acc.reduce(), ::from_u64(13 * 17)); } #[test] @@ -69,20 +60,14 @@ fn wide_accumulator_merge() { use jolt_field::WideAccumulator; let mut acc1 = WideAccumulator::default(); - acc1.fmadd( - ::from_u64(10), - ::from_u64(20), - ); + acc1.fmadd(::from_u64(10), ::from_u64(20)); let mut acc2 = WideAccumulator::default(); - acc2.fmadd( - ::from_u64(30), - ::from_u64(40), - ); + acc2.fmadd(::from_u64(30), ::from_u64(40)); acc1.merge(acc2); // 10*20 + 30*40 = 200 + 1200 = 1400 - assert_eq!(acc1.reduce(), ::from_u64(1400)); + assert_eq!(acc1.reduce(), ::from_u64(1400)); } #[test] @@ -101,8 +86,8 @@ fn wide_accumulator_many_fmadds() { let mut expected = Fr::zero(); let mut rng = test_rng(); for _ in 0..500 { - let a: Fr = ::random(&mut rng); - let b: Fr = ::random(&mut rng); + let a: Fr = Field::random(&mut rng); + let b: Fr = Field::random(&mut rng); acc.fmadd(a, b); expected += a * b; } @@ -112,8 +97,8 @@ fn wide_accumulator_many_fmadds() { #[test] fn optimized_mul_blanket_impl() { let mut rng = test_rng(); - let a: Fr = ::random(&mut rng); - let b: Fr = ::random(&mut rng); + let a: Fr = Field::random(&mut rng); + let b: Fr = Field::random(&mut rng); // mul_0_optimized: both nonzero assert_eq!(a.mul_0_optimized(b), a * b); @@ -147,41 +132,35 @@ fn optimized_mul_blanket_impl() { #[test] fn field_from_bool_edge() { - assert_eq!(::from_bool(true), Fr::one()); - assert_eq!(::from_bool(false), Fr::zero()); + assert_eq!(::from_bool(true), Fr::one()); + assert_eq!(::from_bool(false), Fr::zero()); } #[test] fn field_from_small_types_boundary() { - assert_eq!(::from_u8(0), Fr::zero()); + assert_eq!(::from_u8(0), Fr::zero()); + assert_eq!(::from_u8(255), ::from_u64(255)); + assert_eq!(::from_u16(0), Fr::zero()); assert_eq!( - ::from_u8(255), - ::from_u64(255) + ::from_u16(65535), + ::from_u64(65535) ); - assert_eq!(::from_u16(0), Fr::zero()); + assert_eq!(::from_u32(0), Fr::zero()); assert_eq!( - ::from_u16(65535), - ::from_u64(65535) - ); - assert_eq!(::from_u32(0), Fr::zero()); - assert_eq!( - ::from_u32(u32::MAX), - ::from_u64(u32::MAX as u64) + ::from_u32(u32::MAX), + ::from_u64(u32::MAX as u64) ); } #[test] fn field_mul_pow_2_boundary() { - let f = ::from_u64(1); + let f = ::from_u64(1); // pow=0 -> f * 1 = f - assert_eq!(::mul_pow_2(&f, 0), f); + assert_eq!(::mul_pow_2(&f, 0), f); // pow=1 -> f * 2 - assert_eq!( - ::mul_pow_2(&f, 1), - ::from_u64(2) - ); + assert_eq!(::mul_pow_2(&f, 1), ::from_u64(2)); // pow=64 -> goes through while loop at least once - let result = ::mul_pow_2(&f, 64); + let result = ::mul_pow_2(&f, 64); let mut expected = f; for _ in 0..64 { expected = expected + expected; @@ -192,8 +171,8 @@ fn field_mul_pow_2_boundary() { #[test] #[should_panic(expected = "pow > 255")] fn field_mul_pow_2_overflow() { - let f = ::from_u64(1); - let _ = ::mul_pow_2(&f, 256); + let f = ::from_u64(1); + let _ = ::mul_pow_2(&f, 256); } #[test] @@ -957,8 +936,8 @@ fn fr_neg() { fn fr_inner_roundtrip() { // Test Fr(ark_bn254::Fr) -> ark_bn254::Fr conversion (inner type) let a = Fr::from_u64(12345); - let bytes = a.to_bytes_array(); - let b = Fr::from_bytes_array(&bytes); + let bytes = a.to_bytes(); + let b = Fr::from_bytes(&bytes); assert_eq!(a, b); } diff --git a/crates/jolt-field/tests/field_operations.rs b/crates/jolt-field/tests/field_operations.rs index 2f56bd304c..b648dd6932 100644 --- a/crates/jolt-field/tests/field_operations.rs +++ b/crates/jolt-field/tests/field_operations.rs @@ -2,9 +2,8 @@ use ark_std::rand::Rng; use ark_std::{test_rng, One, Zero}; -use jolt_field::{ - CanonicalU64, Fr, FromPrimitiveInt, MulPow2, MulPrimitiveInt, RandomSampling, ReducingBytes, -}; +use jolt_field::Field; +use jolt_field::Fr; use rand_chacha::rand_core::RngCore; #[test] @@ -14,17 +13,17 @@ fn implicit_montgomery_conversion() { for _ in 0..256 { let x = rng.next_u64(); assert_eq!( - ::from_u64(x), - Fr::one() * ::from_u64(x) + ::from_u64(x), + Fr::one() * ::from_u64(x) ); } for _ in 0..256 { let x = rng.next_u64(); - let y: Fr = ::random(&mut rng); + let y: Fr = Field::random(&mut rng); assert_eq!( - y * ::from_u64(x), - y * ::from_u64(x) + y * ::from_u64(x), + y * ::from_u64(x) ); } } @@ -33,8 +32,8 @@ fn implicit_montgomery_conversion() { fn field_arithmetic() { let mut rng = test_rng(); - let x = ::from_u64(rng.next_u64()); - let y = ::from_u64(rng.next_u64()); + let x = ::from_u64(rng.next_u64()); + let y = ::from_u64(rng.next_u64()); let sum = x + y; assert_eq!(sum, y + x); @@ -55,30 +54,30 @@ fn field_arithmetic() { fn field_conversions() { let mut rng = test_rng(); - assert_eq!(::from_bool(true), Fr::one()); - assert_eq!(::from_bool(false), Fr::zero()); + assert_eq!(::from_bool(true), Fr::one()); + assert_eq!(::from_bool(false), Fr::zero()); for _ in 0..100 { let val = rng.gen::(); - let field_elem = ::from_u8(val); - assert_eq!(field_elem, ::from_u64(val as u64)); + let field_elem = ::from_u8(val); + assert_eq!(field_elem, ::from_u64(val as u64)); } for _ in 0..100 { let val = rng.gen::(); - let field_elem = ::from_u16(val); - assert_eq!(field_elem, ::from_u64(val as u64)); + let field_elem = ::from_u16(val); + assert_eq!(field_elem, ::from_u64(val as u64)); } for _ in 0..100 { let val = rng.gen::(); - let field_elem = ::from_u32(val); - assert_eq!(field_elem, ::from_u64(val as u64)); + let field_elem = ::from_u32(val); + assert_eq!(field_elem, ::from_u64(val as u64)); } for _ in 0..100 { let val = rng.gen::(); - let field_elem = ::from_u128(val); + let field_elem = ::from_u128(val); assert!(!field_elem.is_zero() || val == 0); } } @@ -90,7 +89,7 @@ fn bytes_conversion() { for &len in &[1, 8, 16, 32, 48, 64] { let mut bytes = vec![0u8; len]; rng.fill_bytes(&mut bytes); - let _field_elem = ::from_le_bytes_mod_order(&bytes); + let _field_elem = ::from_bytes(&bytes); } } @@ -100,29 +99,23 @@ fn signed_conversions() { for _ in 0..100 { let val = rng.gen::(); - let field_elem = ::from_i64(val); + let field_elem = ::from_i64(val); if val >= 0 { - assert_eq!(field_elem, ::from_u64(val as u64)); + assert_eq!(field_elem, ::from_u64(val as u64)); } else { - assert_eq!( - field_elem, - -::from_u64(val.unsigned_abs()) - ); + assert_eq!(field_elem, -::from_u64(val.unsigned_abs())); } } for _ in 0..100 { let val = rng.gen::(); - let field_elem = ::from_i128(val); + let field_elem = ::from_i128(val); if val >= 0 { - assert_eq!(field_elem, ::from_u128(val as u128)); + assert_eq!(field_elem, ::from_u128(val as u128)); } else { - assert_eq!( - field_elem, - -::from_u128(val.unsigned_abs()) - ); + assert_eq!(field_elem, -::from_u128(val.unsigned_abs())); } } } @@ -132,12 +125,12 @@ fn mul_u64_method() { let mut rng = test_rng(); for _ in 0..100 { - let field_elem: Fr = ::random(&mut rng); + let field_elem: Fr = Field::random(&mut rng); let n = rng.next_u64(); // Use UFCS to call trait method (arkworks has inherent mul_u64 with different signature) - let result = ::mul_u64(&field_elem, n); - let expected = field_elem * ::from_u64(n); + let result = ::mul_u64(&field_elem, n); + let expected = field_elem * ::from_u64(n); assert_eq!(result, expected); } } @@ -147,11 +140,11 @@ fn mul_i64_method() { let mut rng = test_rng(); for _ in 0..100 { - let field_elem: Fr = ::random(&mut rng); + let field_elem: Fr = Field::random(&mut rng); let n = rng.gen::(); - let result = ::mul_i64(&field_elem, n); - let expected = field_elem * ::from_i64(n); + let result = ::mul_i64(&field_elem, n); + let expected = field_elem * ::from_i64(n); assert_eq!(result, expected); } } @@ -161,11 +154,11 @@ fn mul_u128_method() { let mut rng = test_rng(); for _ in 0..100 { - let field_elem: Fr = ::random(&mut rng); + let field_elem: Fr = Field::random(&mut rng); let n = rng.gen::(); - let result = ::mul_u128(&field_elem, n); - let expected = field_elem * ::from_u128(n); + let result = ::mul_u128(&field_elem, n); + let expected = field_elem * ::from_u128(n); assert_eq!(result, expected); } } @@ -175,11 +168,11 @@ fn mul_i128_method() { let mut rng = test_rng(); for _ in 0..100 { - let field_elem: Fr = ::random(&mut rng); + let field_elem: Fr = Field::random(&mut rng); let n = rng.gen::(); - let result = ::mul_i128(&field_elem, n); - let expected = field_elem * ::from_i128(n); + let result = ::mul_i128(&field_elem, n); + let expected = field_elem * ::from_i128(n); assert_eq!(result, expected); } } @@ -189,10 +182,10 @@ fn mul_pow_2_method() { let mut rng = test_rng(); for _ in 0..10 { - let field_elem: Fr = ::random(&mut rng); + let field_elem: Fr = Field::random(&mut rng); for pow in [0, 1, 2, 7, 16, 32, 63, 64, 127, 128, 255] { - let result = ::mul_pow_2(&field_elem, pow); + let result = ::mul_pow_2(&field_elem, pow); let mut expected = field_elem; for _ in 0..pow { expected = expected + expected; @@ -207,10 +200,10 @@ fn mul_by_small_values() { let mut rng = test_rng(); for _ in 0..100 { - let field_elem: Fr = ::random(&mut rng); + let field_elem: Fr = Field::random(&mut rng); let small_val = rng.gen_range(0u64..1000); - let result1 = field_elem * ::from_u64(small_val); + let result1 = field_elem * ::from_u64(small_val); let mut result2 = Fr::zero(); for _ in 0..small_val { @@ -224,34 +217,25 @@ fn mul_by_small_values() { #[test] fn special_values() { let mut rng = test_rng(); - let field_elem: Fr = ::random(&mut rng); - - assert_eq!( - field_elem * ::from_u64(0), - Fr::zero() - ); - assert_eq!( - field_elem * ::from_u64(1), - field_elem - ); - assert!((Fr::zero() * ::from_u64(rng.next_u64())).is_zero()); - - assert_eq!(::mul_u64(&field_elem, 0), Fr::zero()); - assert_eq!(::mul_u64(&field_elem, 1), field_elem); - assert_eq!( - ::mul_u64(&Fr::zero(), 42), - Fr::zero() - ); + let field_elem: Fr = Field::random(&mut rng); + + assert_eq!(field_elem * ::from_u64(0), Fr::zero()); + assert_eq!(field_elem * ::from_u64(1), field_elem); + assert!((Fr::zero() * ::from_u64(rng.next_u64())).is_zero()); + + assert_eq!(::mul_u64(&field_elem, 0), Fr::zero()); + assert_eq!(::mul_u64(&field_elem, 1), field_elem); + assert_eq!(::mul_u64(&Fr::zero(), 42), Fr::zero()); } #[test] fn to_u64_conversion() { for i in 0..1000u64 { - let field_elem = ::from_u64(i); - assert_eq!(field_elem.to_canonical_u64_checked(), Some(i)); + let field_elem = ::from_u64(i); + assert_eq!(field_elem.to_u64(), Some(i)); } let mut rng = test_rng(); - let large_field: Fr = ::random(&mut rng); - let _ = large_field.to_canonical_u64_checked(); + let large_field: Fr = Field::random(&mut rng); + let _ = large_field.to_u64(); } diff --git a/crates/jolt-hyperkzg/benches/hyperkzg.rs b/crates/jolt-hyperkzg/benches/hyperkzg.rs index 27c587e741..56e4796198 100644 --- a/crates/jolt-hyperkzg/benches/hyperkzg.rs +++ b/crates/jolt-hyperkzg/benches/hyperkzg.rs @@ -1,7 +1,7 @@ use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; use jolt_crypto::Bn254; -use jolt_field::{Fr, RandomSampling}; +use jolt_field::{Field, Fr}; use jolt_hyperkzg::{HyperKZGProverSetup, HyperKZGScheme, HyperKZGVerifierSetup}; use jolt_openings::{AdditivelyHomomorphic, CommitmentScheme}; use jolt_poly::Polynomial; diff --git a/crates/jolt-hyperkzg/src/kzg.rs b/crates/jolt-hyperkzg/src/kzg.rs index ef6694df65..ae3dcdce20 100644 --- a/crates/jolt-hyperkzg/src/kzg.rs +++ b/crates/jolt-hyperkzg/src/kzg.rs @@ -217,7 +217,7 @@ pub(crate) fn challenge_powers(c: F, n: usize) -> Vec { #[cfg(test)] mod tests { use super::*; - use jolt_field::{Fr, FromPrimitiveInt}; + use jolt_field::{Field, Fr}; use num_traits::Zero; #[test] diff --git a/crates/jolt-hyperkzg/src/scheme.rs b/crates/jolt-hyperkzg/src/scheme.rs index 05b46f6f92..4e6bbe2b7e 100644 --- a/crates/jolt-hyperkzg/src/scheme.rs +++ b/crates/jolt-hyperkzg/src/scheme.rs @@ -11,7 +11,7 @@ use std::marker::PhantomData; use jolt_crypto::{Commitment, DeriveSetup, JoltGroup, PairingGroup, PedersenSetup}; -use jolt_field::{FromPrimitiveInt, RandomSampling}; +use jolt_field::Field; use jolt_openings::{AdditivelyHomomorphic, CommitmentScheme, OpeningsError}; use jolt_poly::Polynomial; use jolt_transcript::{AppendToTranscript, Label, LabelWithCount, Transcript}; diff --git a/crates/jolt-hyperkzg/tests/commit_open_verify.rs b/crates/jolt-hyperkzg/tests/commit_open_verify.rs index 52a8376880..9ee2e6eba2 100644 --- a/crates/jolt-hyperkzg/tests/commit_open_verify.rs +++ b/crates/jolt-hyperkzg/tests/commit_open_verify.rs @@ -3,7 +3,7 @@ #![expect(clippy::expect_used, reason = "tests may panic on assertion failures")] use jolt_crypto::Bn254; -use jolt_field::{Fr, FromPrimitiveInt, RandomSampling}; +use jolt_field::{Field, Fr}; use jolt_hyperkzg::{HyperKZGProverSetup, HyperKZGScheme, HyperKZGVerifierSetup}; use jolt_openings::{AdditivelyHomomorphic, CommitmentScheme}; use jolt_poly::Polynomial; diff --git a/crates/jolt-lookup-tables/src/instructions/virt/assert_lte.rs b/crates/jolt-lookup-tables/src/instructions/virt/assert_lte.rs index 93bfc17dae..61ed9974d9 100644 --- a/crates/jolt-lookup-tables/src/instructions/virt/assert_lte.rs +++ b/crates/jolt-lookup-tables/src/instructions/virt/assert_lte.rs @@ -3,7 +3,7 @@ use crate::traits::LookupQuery; use jolt_trace::instructions::AssertLte; use jolt_trace::JoltCycle; -impl_lookup_table!(AssertLte, Some(UnsignedLessThanEqual)); +impl_lookup_table!(AssertLte, Some(LessThanEqual)); impl LookupQuery for AssertLte { fn to_instruction_inputs(&self) -> (u64, i128) { diff --git a/crates/jolt-lookup-tables/src/instructions/virt/movsign.rs b/crates/jolt-lookup-tables/src/instructions/virt/movsign.rs index bdc615365f..c4e3962476 100644 --- a/crates/jolt-lookup-tables/src/instructions/virt/movsign.rs +++ b/crates/jolt-lookup-tables/src/instructions/virt/movsign.rs @@ -3,7 +3,7 @@ use crate::traits::LookupQuery; use jolt_trace::instructions::MovSign; use jolt_trace::{JoltCycle, JoltInstruction}; -impl_lookup_table!(MovSign, Some(SignMask)); +impl_lookup_table!(MovSign, Some(Movsign)); impl LookupQuery for MovSign { fn to_instruction_inputs(&self) -> (u64, i128) { diff --git a/crates/jolt-lookup-tables/src/tables/mod.rs b/crates/jolt-lookup-tables/src/tables/mod.rs index d6b629cac9..43487daf2e 100644 --- a/crates/jolt-lookup-tables/src/tables/mod.rs +++ b/crates/jolt-lookup-tables/src/tables/mod.rs @@ -70,7 +70,7 @@ use range_check::RangeCheckTable; use range_check_aligned::RangeCheckAlignedTable; use shift_right_bitmask::ShiftRightBitmaskTable; use sign_extend_half_word::SignExtendHalfWordTable; -use sign_mask::SignMaskTable; +use sign_mask::SignMaskTable as MovsignTable; use signed_greater_than_equal::SignedGreaterThanEqualTable; use signed_less_than::SignedLessThanTable; use unsigned_greater_than_equal::UnsignedGreaterThanEqualTable; @@ -78,7 +78,6 @@ use unsigned_less_than::UnsignedLessThanTable; use unsigned_less_than_equal::UnsignedLessThanEqualTable; use upper_word::UpperWordTable; use valid_div0::ValidDiv0Table; -use valid_signed_remainder::ValidSignedRemainderTable; use valid_unsigned_remainder::ValidUnsignedRemainderTable; use virtual_change_divisor::VirtualChangeDivisorTable; use virtual_change_divisor_w::VirtualChangeDivisorWTable; @@ -108,32 +107,31 @@ pub enum LookupTableKind { Or(OrTable), Xor(XorTable), Equal(EqualTable), + SignedGreaterThanEqual(SignedGreaterThanEqualTable), + UnsignedGreaterThanEqual(UnsignedGreaterThanEqualTable), NotEqual(NotEqualTable), SignedLessThan(SignedLessThanTable), UnsignedLessThan(UnsignedLessThanTable), - SignedGreaterThanEqual(SignedGreaterThanEqualTable), - UnsignedGreaterThanEqual(UnsignedGreaterThanEqualTable), - UnsignedLessThanEqual(UnsignedLessThanEqualTable), + Movsign(MovsignTable), UpperWord(UpperWordTable), + LessThanEqual(UnsignedLessThanEqualTable), + ValidUnsignedRemainder(ValidUnsignedRemainderTable), + ValidDiv0(ValidDiv0Table), + HalfwordAlignment(HalfwordAlignmentTable), + WordAlignment(WordAlignmentTable), LowerHalfWord(LowerHalfWordTable), SignExtendHalfWord(SignExtendHalfWordTable), - SignMask(SignMaskTable), Pow2(Pow2Table), Pow2W(Pow2WTable), ShiftRightBitmask(ShiftRightBitmaskTable), + VirtualRev8W(VirtualRev8WTable), VirtualSRL(VirtualSRLTable), VirtualSRA(VirtualSRATable), VirtualROTR(VirtualROTRTable), VirtualROTRW(VirtualROTRWTable), - ValidDiv0(ValidDiv0Table), - ValidUnsignedRemainder(ValidUnsignedRemainderTable), - ValidSignedRemainder(ValidSignedRemainderTable), VirtualChangeDivisor(VirtualChangeDivisorTable), VirtualChangeDivisorW(VirtualChangeDivisorWTable), - HalfwordAlignment(HalfwordAlignmentTable), - WordAlignment(WordAlignmentTable), MulUNoOverflow(MulUNoOverflowTable), - VirtualRev8W(VirtualRev8WTable), VirtualXORROT32(VirtualXORROTTable), VirtualXORROT24(VirtualXORROTTable), VirtualXORROT16(VirtualXORROTTable), @@ -158,32 +156,31 @@ macro_rules! dispatch { Self::Or($t) => $expr, Self::Xor($t) => $expr, Self::Equal($t) => $expr, + Self::SignedGreaterThanEqual($t) => $expr, + Self::UnsignedGreaterThanEqual($t) => $expr, Self::NotEqual($t) => $expr, Self::SignedLessThan($t) => $expr, Self::UnsignedLessThan($t) => $expr, - Self::SignedGreaterThanEqual($t) => $expr, - Self::UnsignedGreaterThanEqual($t) => $expr, - Self::UnsignedLessThanEqual($t) => $expr, + Self::Movsign($t) => $expr, Self::UpperWord($t) => $expr, + Self::LessThanEqual($t) => $expr, + Self::ValidUnsignedRemainder($t) => $expr, + Self::ValidDiv0($t) => $expr, + Self::HalfwordAlignment($t) => $expr, + Self::WordAlignment($t) => $expr, Self::LowerHalfWord($t) => $expr, Self::SignExtendHalfWord($t) => $expr, - Self::SignMask($t) => $expr, Self::Pow2($t) => $expr, Self::Pow2W($t) => $expr, Self::ShiftRightBitmask($t) => $expr, + Self::VirtualRev8W($t) => $expr, Self::VirtualSRL($t) => $expr, Self::VirtualSRA($t) => $expr, Self::VirtualROTR($t) => $expr, Self::VirtualROTRW($t) => $expr, - Self::ValidDiv0($t) => $expr, - Self::ValidUnsignedRemainder($t) => $expr, - Self::ValidSignedRemainder($t) => $expr, Self::VirtualChangeDivisor($t) => $expr, Self::VirtualChangeDivisorW($t) => $expr, - Self::HalfwordAlignment($t) => $expr, - Self::WordAlignment($t) => $expr, Self::MulUNoOverflow($t) => $expr, - Self::VirtualRev8W($t) => $expr, Self::VirtualXORROT32($t) => $expr, Self::VirtualXORROT24($t) => $expr, Self::VirtualXORROT16($t) => $expr, @@ -197,6 +194,97 @@ macro_rules! dispatch { } impl LookupTableKind { + /// Returns the canonical Jolt lookup table list in `jolt-core` order. + pub fn all() -> [Self; 40] { + [ + Self::RangeCheck(Default::default()), + Self::RangeCheckAligned(Default::default()), + Self::And(Default::default()), + Self::Andn(Default::default()), + Self::Or(Default::default()), + Self::Xor(Default::default()), + Self::Equal(Default::default()), + Self::SignedGreaterThanEqual(Default::default()), + Self::UnsignedGreaterThanEqual(Default::default()), + Self::NotEqual(Default::default()), + Self::SignedLessThan(Default::default()), + Self::UnsignedLessThan(Default::default()), + Self::Movsign(Default::default()), + Self::UpperWord(Default::default()), + Self::LessThanEqual(Default::default()), + Self::ValidUnsignedRemainder(Default::default()), + Self::ValidDiv0(Default::default()), + Self::HalfwordAlignment(Default::default()), + Self::WordAlignment(Default::default()), + Self::LowerHalfWord(Default::default()), + Self::SignExtendHalfWord(Default::default()), + Self::Pow2(Default::default()), + Self::Pow2W(Default::default()), + Self::ShiftRightBitmask(Default::default()), + Self::VirtualRev8W(Default::default()), + Self::VirtualSRL(Default::default()), + Self::VirtualSRA(Default::default()), + Self::VirtualROTR(Default::default()), + Self::VirtualROTRW(Default::default()), + Self::VirtualChangeDivisor(Default::default()), + Self::VirtualChangeDivisorW(Default::default()), + Self::MulUNoOverflow(Default::default()), + Self::VirtualXORROT32(Default::default()), + Self::VirtualXORROT24(Default::default()), + Self::VirtualXORROT16(Default::default()), + Self::VirtualXORROT63(Default::default()), + Self::VirtualXORROTW16(Default::default()), + Self::VirtualXORROTW12(Default::default()), + Self::VirtualXORROTW8(Default::default()), + Self::VirtualXORROTW7(Default::default()), + ] + } + + pub fn name(&self) -> &'static str { + match self { + Self::RangeCheck(_) => "RangeCheck", + Self::RangeCheckAligned(_) => "RangeCheckAligned", + Self::And(_) => "And", + Self::Andn(_) => "Andn", + Self::Or(_) => "Or", + Self::Xor(_) => "Xor", + Self::Equal(_) => "Equal", + Self::SignedGreaterThanEqual(_) => "SignedGreaterThanEqual", + Self::UnsignedGreaterThanEqual(_) => "UnsignedGreaterThanEqual", + Self::NotEqual(_) => "NotEqual", + Self::SignedLessThan(_) => "SignedLessThan", + Self::UnsignedLessThan(_) => "UnsignedLessThan", + Self::Movsign(_) => "Movsign", + Self::UpperWord(_) => "UpperWord", + Self::LessThanEqual(_) => "LessThanEqual", + Self::ValidUnsignedRemainder(_) => "ValidUnsignedRemainder", + Self::ValidDiv0(_) => "ValidDiv0", + Self::HalfwordAlignment(_) => "HalfwordAlignment", + Self::WordAlignment(_) => "WordAlignment", + Self::LowerHalfWord(_) => "LowerHalfWord", + Self::SignExtendHalfWord(_) => "SignExtendHalfWord", + Self::Pow2(_) => "Pow2", + Self::Pow2W(_) => "Pow2W", + Self::ShiftRightBitmask(_) => "ShiftRightBitmask", + Self::VirtualRev8W(_) => "VirtualRev8W", + Self::VirtualSRL(_) => "VirtualSRL", + Self::VirtualSRA(_) => "VirtualSRA", + Self::VirtualROTR(_) => "VirtualROTR", + Self::VirtualROTRW(_) => "VirtualROTRW", + Self::VirtualChangeDivisor(_) => "VirtualChangeDivisor", + Self::VirtualChangeDivisorW(_) => "VirtualChangeDivisorW", + Self::MulUNoOverflow(_) => "MulUNoOverflow", + Self::VirtualXORROT32(_) => "VirtualXORROT32", + Self::VirtualXORROT24(_) => "VirtualXORROT24", + Self::VirtualXORROT16(_) => "VirtualXORROT16", + Self::VirtualXORROT63(_) => "VirtualXORROT63", + Self::VirtualXORROTW16(_) => "VirtualXORROTW16", + Self::VirtualXORROTW12(_) => "VirtualXORROTW12", + Self::VirtualXORROTW8(_) => "VirtualXORROTW8", + Self::VirtualXORROTW7(_) => "VirtualXORROTW7", + } + } + /// Returns the discriminant as a `usize`, suitable for array indexing. #[inline] pub fn index(&self) -> usize { diff --git a/crates/jolt-lookup-tables/src/tables/prefixes/mod.rs b/crates/jolt-lookup-tables/src/tables/prefixes/mod.rs index d3943afb9c..302ea13677 100644 --- a/crates/jolt-lookup-tables/src/tables/prefixes/mod.rs +++ b/crates/jolt-lookup-tables/src/tables/prefixes/mod.rs @@ -88,6 +88,12 @@ impl From for PrefixEval { } } +impl PrefixEval { + pub fn into_inner(self) -> F { + self.0 + } +} + impl Index for &[PrefixEval] { type Output = F; diff --git a/crates/jolt-lookup-tables/src/tables/suffixes/rev8w.rs b/crates/jolt-lookup-tables/src/tables/suffixes/rev8w.rs index b935b93b7e..92a8c87d53 100644 --- a/crates/jolt-lookup-tables/src/tables/suffixes/rev8w.rs +++ b/crates/jolt-lookup-tables/src/tables/suffixes/rev8w.rs @@ -5,7 +5,7 @@ pub enum Rev8WSuffix {} impl SparseDenseSuffix for Rev8WSuffix { fn suffix_mle(b: LookupBits) -> u64 { - let val = u128::from(b) as u32; - val.swap_bytes() as u64 + let val = u128::from(b) as u64; + crate::tables::virtual_rev8w::rev8w(val) } } diff --git a/crates/jolt-lookup-tables/src/tables/virtual_rev8w.rs b/crates/jolt-lookup-tables/src/tables/virtual_rev8w.rs index 2e33cfeaef..743a20cec0 100644 --- a/crates/jolt-lookup-tables/src/tables/virtual_rev8w.rs +++ b/crates/jolt-lookup-tables/src/tables/virtual_rev8w.rs @@ -62,12 +62,9 @@ impl PrefixSuffixDecomposition for VirtualRev8WTable= 64 bits, and Rev8WSuffix only - // handles the lower 32 bits. The decomposition is therefore only valid for - // lookup indices whose value fits in 32 bits (upper word = 0). #[cfg(test)] fn random_lookup_index(rng: &mut rand::rngs::StdRng) -> u128 { - rand::RngCore::next_u32(rng) as u128 + rand::RngCore::next_u64(rng) as u128 } } diff --git a/crates/jolt-openings/benches/rlc.rs b/crates/jolt-openings/benches/rlc.rs index 8cb7314e36..457050298f 100644 --- a/crates/jolt-openings/benches/rlc.rs +++ b/crates/jolt-openings/benches/rlc.rs @@ -3,7 +3,7 @@ use std::hint::black_box; use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; -use jolt_field::{Fr, RandomSampling}; +use jolt_field::{Field, Fr}; use rand_chacha::ChaCha20Rng; use rand_core::SeedableRng; @@ -12,16 +12,12 @@ use jolt_openings::{rlc_combine, rlc_combine_scalars}; fn bench_rlc_combine(c: &mut Criterion) { let mut group = c.benchmark_group("rlc_combine"); let mut rng = ChaCha20Rng::seed_from_u64(0); - let rho: Fr = ::random(&mut rng); + let rho: Fr = Field::random(&mut rng); for (n_polys, num_vars) in [(8, 18), (32, 14)] { let len = 1 << num_vars; let tables: Vec> = (0..n_polys) - .map(|_| { - (0..len) - .map(|_| ::random(&mut rng)) - .collect() - }) + .map(|_| (0..len).map(|_| Fr::random(&mut rng)).collect()) .collect(); let refs: Vec<&[Fr]> = tables.iter().map(|t| t.as_slice()).collect(); @@ -39,12 +35,10 @@ fn bench_rlc_combine(c: &mut Criterion) { fn bench_rlc_combine_scalars(c: &mut Criterion) { let mut group = c.benchmark_group("rlc_combine_scalars"); let mut rng = ChaCha20Rng::seed_from_u64(1); - let rho: Fr = ::random(&mut rng); + let rho: Fr = Field::random(&mut rng); for n in [8, 32] { - let evals: Vec = (0..n) - .map(|_| ::random(&mut rng)) - .collect(); + let evals: Vec = (0..n).map(|_| Fr::random(&mut rng)).collect(); group.bench_with_input(BenchmarkId::from_parameter(n), &n, |bench, _| { bench.iter(|| rlc_combine_scalars(black_box(&evals), black_box(rho))); diff --git a/crates/jolt-openings/fuzz/fuzz_targets/rlc.rs b/crates/jolt-openings/fuzz/fuzz_targets/rlc.rs index 535cf55f8b..2cc915fa5a 100644 --- a/crates/jolt-openings/fuzz/fuzz_targets/rlc.rs +++ b/crates/jolt-openings/fuzz/fuzz_targets/rlc.rs @@ -1,5 +1,5 @@ #![no_main] -use jolt_field::{Fr, FromPrimitiveInt, RandomSampling, ReducingBytes}; +use jolt_field::{Field, Fr}; use jolt_openings::{rlc_combine, rlc_combine_scalars}; use libfuzzer_sys::fuzz_target; @@ -9,7 +9,7 @@ fuzz_target!(|data: &[u8]| { return; } - let rho = ::from_le_bytes_mod_order(&data[..32]); + let rho = ::from_bytes(&data[..32]); let remaining = &data[32..]; // Build 1-4 polynomials of length 1-8 from remaining bytes @@ -25,7 +25,7 @@ fuzz_target!(|data: &[u8]| { if end - start < 32 { Fr::from_u64(remaining[start] as u64) } else { - ::from_le_bytes_mod_order(&remaining[start..end]) + ::from_bytes(&remaining[start..end]) } }) .collect(); diff --git a/crates/jolt-openings/src/mock.rs b/crates/jolt-openings/src/mock.rs index 39d0150f8c..ec7aa70f0d 100644 --- a/crates/jolt-openings/src/mock.rs +++ b/crates/jolt-openings/src/mock.rs @@ -31,15 +31,19 @@ pub struct MockProof { impl AppendToTranscript for MockCommitment { fn append_to_transcript(&self, transcript: &mut T) { - let mut buf = Vec::with_capacity(self.evaluations.len() * F::NUM_BYTES); + let mut buf = Vec::with_capacity(self.evaluations.len() * 32); for e in &self.evaluations { - let start = buf.len(); - buf.resize(start + F::NUM_BYTES, 0); - e.to_bytes_le(&mut buf[start..]); + buf.extend_from_slice(&e.to_bytes()); } buf.reverse(); transcript.append_bytes(&buf); } + + fn serialized_len(&self) -> u64 { + u64::try_from(self.evaluations.len()) + .unwrap_or(u64::MAX / 32) + .saturating_mul(32) + } } impl Commitment for MockCommitmentScheme { @@ -160,6 +164,10 @@ impl AppendToTranscript for MockHidingCommitment { fn append_to_transcript(&self, transcript: &mut T) { self.eval.append_to_transcript(transcript); } + + fn serialized_len(&self) -> u64 { + self.eval.serialized_len() + } } impl ZkOpeningScheme for MockCommitmentScheme { @@ -194,6 +202,7 @@ impl ZkOpeningScheme for MockCommitmentScheme { actual: format!("len={}", proof.evaluations.len()), }); } + Ok(()) } } @@ -203,7 +212,8 @@ impl ZkOpeningScheme for MockCommitmentScheme { mod tests { use super::*; use crate::{reduce_prover, reduce_verifier, ProverClaim, VerifierClaim}; - use jolt_field::{Fr, FromPrimitiveInt, RandomSampling}; + use jolt_field::Field; + use jolt_field::Fr; use jolt_poly::Polynomial; use jolt_transcript::Blake2bTranscript; use rand_chacha::rand_core::SeedableRng; diff --git a/crates/jolt-openings/src/reduction.rs b/crates/jolt-openings/src/reduction.rs index 9cd5402312..d985505625 100644 --- a/crates/jolt-openings/src/reduction.rs +++ b/crates/jolt-openings/src/reduction.rs @@ -168,7 +168,7 @@ fn group_verifier_claims_by_point( #[cfg(test)] mod tests { use super::*; - use jolt_field::{Fr, FromPrimitiveInt, RandomSampling}; + use jolt_field::Fr; use jolt_poly::Polynomial; #[test] diff --git a/crates/jolt-openings/tests/reduction.rs b/crates/jolt-openings/tests/reduction.rs index 38f5e5ff09..14ec309efd 100644 --- a/crates/jolt-openings/tests/reduction.rs +++ b/crates/jolt-openings/tests/reduction.rs @@ -13,7 +13,7 @@ reason = "tests may panic on assertion failures" )] -use jolt_field::{Fr, FromPrimitiveInt, RandomSampling, ReducingBytes}; +use jolt_field::{Field, Fr}; use jolt_openings::mock::MockCommitmentScheme; use jolt_openings::{reduce_prover, reduce_verifier, CommitmentScheme, ProverClaim, VerifierClaim}; use jolt_poly::Polynomial; diff --git a/crates/jolt-poly/benches/poly_ops.rs b/crates/jolt-poly/benches/poly_ops.rs index 51ace32b25..a6b61660d3 100644 --- a/crates/jolt-poly/benches/poly_ops.rs +++ b/crates/jolt-poly/benches/poly_ops.rs @@ -1,7 +1,7 @@ #![expect(unused_results)] use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; -use jolt_field::{Fr, RandomSampling}; +use jolt_field::{Field, Fr}; use jolt_poly::{EqPolynomial, Polynomial}; use rand_chacha::ChaCha20Rng; use rand_core::SeedableRng; diff --git a/crates/jolt-poly/fuzz/fuzz_targets/dense_poly_ops.rs b/crates/jolt-poly/fuzz/fuzz_targets/dense_poly_ops.rs index 3ffb0d46d3..662c72c761 100644 --- a/crates/jolt-poly/fuzz/fuzz_targets/dense_poly_ops.rs +++ b/crates/jolt-poly/fuzz/fuzz_targets/dense_poly_ops.rs @@ -1,5 +1,5 @@ #![no_main] -use jolt_field::{Fr, ReducingBytes}; +use jolt_field::{Field, Fr}; use jolt_poly::Polynomial; use libfuzzer_sys::fuzz_target; @@ -20,18 +20,14 @@ fuzz_target!(|data: &[u8]| { // Build evaluation vector from fuzzer data let evals: Vec = (0..n) - .map(|i| ::from_le_bytes_mod_order(&data[i * 32..(i + 1) * 32])) + .map(|i| ::from_bytes(&data[i * 32..(i + 1) * 32])) .collect(); let poly = Polynomial::new(evals); // Build evaluation point from fuzzer data let point_start = n * 32; let point: Vec = (0..num_vars) - .map(|i| { - ::from_le_bytes_mod_order( - &data[point_start + i * 32..point_start + (i + 1) * 32], - ) - }) + .map(|i| ::from_bytes(&data[point_start + i * 32..point_start + (i + 1) * 32])) .collect(); // evaluate and evaluate_and_consume must agree and not panic diff --git a/crates/jolt-poly/src/compressed_univariate.rs b/crates/jolt-poly/src/compressed_univariate.rs index e013789f29..ff0c4e5b83 100644 --- a/crates/jolt-poly/src/compressed_univariate.rs +++ b/crates/jolt-poly/src/compressed_univariate.rs @@ -95,7 +95,7 @@ impl CompressedPoly { #[expect(clippy::unwrap_used)] mod tests { use super::*; - use jolt_field::{Fr, FromPrimitiveInt}; + use jolt_field::Fr; use num_traits::{One, Zero}; /// Helper: build a standard polynomial p(x) = c0 + c1*x + c2*x^2 + ... diff --git a/crates/jolt-poly/src/dense.rs b/crates/jolt-poly/src/dense.rs index 46293f2bbb..2f6b38647c 100644 --- a/crates/jolt-poly/src/dense.rs +++ b/crates/jolt-poly/src/dense.rs @@ -360,6 +360,70 @@ impl crate::MultilinearBinding for Polynomial { } } +/// Fixes the first (MSB) variable in a dense evaluation vector. +#[inline] +pub fn bind_high_to_low(evals: &mut Vec, scalar: F) { + let half = evals.len() / 2; + + #[cfg(feature = "parallel")] + { + if half >= PAR_THRESHOLD { + use rayon::prelude::*; + let (lo, hi) = evals.split_at_mut(half); + lo.par_iter_mut().zip(hi.par_iter()).for_each(|(a, b)| { + *a = *a + scalar * (*b - *a); + }); + } else { + for i in 0..half { + let lo = evals[i]; + let hi = evals[i + half]; + evals[i] = lo + scalar * (hi - lo); + } + } + } + + #[cfg(not(feature = "parallel"))] + { + for i in 0..half { + let lo = evals[i]; + let hi = evals[i + half]; + evals[i] = lo + scalar * (hi - lo); + } + } + + evals.truncate(half); +} + +/// Fixes the last (LSB) variable in a dense evaluation vector. +#[inline] +pub fn bind_low_to_high(evals: &mut Vec, scalar: F) { + let half = evals.len() / 2; + + #[cfg(feature = "parallel")] + { + if half >= PAR_THRESHOLD { + use rayon::prelude::*; + let coeffs = &*evals; + *evals = (0..half) + .into_par_iter() + .map(|i| { + let lo = coeffs[2 * i]; + let hi = coeffs[2 * i + 1]; + lo + scalar * (hi - lo) + }) + .collect(); + return; + } + } + + for i in 0..half { + let lo = evals[2 * i]; + let hi = evals[2 * i + 1]; + evals[i] = lo + scalar * (hi - lo); + } + evals.truncate(half); +} + #[inline] fn assert_matching_dims(a: &Polynomial, b: &Polynomial) -> (usize, usize) { assert_eq!( @@ -518,8 +582,8 @@ impl Neg for Polynomial { #[expect(clippy::unwrap_used)] mod tests { use super::*; + use jolt_field::Field; use jolt_field::Fr; - use jolt_field::{FromPrimitiveInt, RandomSampling}; use num_traits::{One, Zero}; use rand_chacha::ChaCha20Rng; use rand_core::SeedableRng; diff --git a/crates/jolt-poly/src/eq.rs b/crates/jolt-poly/src/eq.rs index 94dfcf44b3..9760e430b2 100644 --- a/crates/jolt-poly/src/eq.rs +++ b/crates/jolt-poly/src/eq.rs @@ -347,8 +347,8 @@ impl crate::MultilinearEvaluation for EqPolynomial { #[cfg(test)] mod tests { use super::*; + use jolt_field::Field; use jolt_field::Fr; - use jolt_field::{FromPrimitiveInt, RandomSampling}; use num_traits::{One, Zero}; use rand_chacha::ChaCha20Rng; use rand_core::SeedableRng; diff --git a/crates/jolt-poly/src/eq_plus_one.rs b/crates/jolt-poly/src/eq_plus_one.rs index e05cb69ded..d3eab42c5a 100644 --- a/crates/jolt-poly/src/eq_plus_one.rs +++ b/crates/jolt-poly/src/eq_plus_one.rs @@ -170,7 +170,7 @@ impl EqPlusOnePrefixSuffix { #[cfg(test)] mod tests { use super::*; - use jolt_field::{Fr, FromPrimitiveInt, RandomSampling}; + use jolt_field::{Field, Fr}; use num_traits::{One, Zero}; use rand_chacha::ChaCha20Rng; use rand_core::SeedableRng; diff --git a/crates/jolt-poly/src/expanding_table.rs b/crates/jolt-poly/src/expanding_table.rs new file mode 100644 index 0000000000..b1d32d2e49 --- /dev/null +++ b/crates/jolt-poly/src/expanding_table.rs @@ -0,0 +1,212 @@ +//! Incrementally materialized equality tables. + +use std::ops::Index; + +use jolt_field::Field; + +use crate::{thread::unsafe_allocate_zero_vec, BindingOrder}; + +#[cfg(feature = "parallel")] +use rayon::prelude::*; + +/// Table containing the evaluations of `eq(x, r)` as challenges are streamed in. +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub struct ExpandingTable { + binding_order: BindingOrder, + len: usize, + values: Vec, + scratch_space: Vec, +} + +impl ExpandingTable { + #[tracing::instrument(skip_all, name = "ExpandingTable::new")] + pub fn new(capacity: usize, binding_order: BindingOrder) -> Self { + assert!(capacity > 0, "expanding table capacity must be positive"); + let (values, scratch_space) = join_or_serial( + || unsafe_allocate_zero_vec(capacity), + || match binding_order { + BindingOrder::LowToHigh => Vec::new(), + BindingOrder::HighToLow => unsafe_allocate_zero_vec(capacity), + }, + ); + Self { + binding_order, + len: 0, + values, + scratch_space, + } + } + + #[inline] + pub fn len(&self) -> usize { + self.len + } + + #[inline] + pub fn is_empty(&self) -> bool { + self.len == 0 + } + + #[inline] + pub fn order(&self) -> BindingOrder { + self.binding_order + } + + #[inline] + pub fn values(&self) -> &[F] { + &self.values[..self.len] + } + + pub fn reset(&mut self, value: F) { + assert!(!self.values.is_empty(), "expanding table has zero capacity"); + self.values[0] = value; + self.len = 1; + } + + pub fn clone_values(&self) -> Vec { + self.values().to_vec() + } + + #[tracing::instrument(skip_all, name = "ExpandingTable::update")] + pub fn update(&mut self, challenge: F) { + assert!(self.len > 0, "expanding table must be reset before update"); + assert!( + self.len * 2 <= self.values.len(), + "expanding table capacity exceeded" + ); + match self.binding_order { + BindingOrder::LowToHigh => self.update_low_to_high(challenge), + BindingOrder::HighToLow => self.update_high_to_low(challenge), + } + self.len *= 2; + } + + fn update_low_to_high(&mut self, challenge: F) { + #[cfg(feature = "parallel")] + { + let (left, right) = self.values.split_at_mut(self.len); + left.par_iter_mut() + .zip(right.par_iter_mut()) + .for_each(|(left, right)| { + *right = *left * challenge; + *left -= *right; + }); + } + + #[cfg(not(feature = "parallel"))] + { + let (left, right) = self.values.split_at_mut(self.len); + for (left, right) in left.iter_mut().zip(right.iter_mut()) { + *right = *left * challenge; + *left -= *right; + } + } + } + + fn update_high_to_low(&mut self, challenge: F) { + #[cfg(feature = "parallel")] + { + self.values[..self.len] + .par_iter() + .zip(self.scratch_space.par_chunks_mut(2)) + .for_each(|(&value, dest)| { + let eval_1 = value * challenge; + dest[0] = value - eval_1; + dest[1] = eval_1; + }); + std::mem::swap(&mut self.values, &mut self.scratch_space); + } + + #[cfg(not(feature = "parallel"))] + { + for (index, &value) in self.values[..self.len].iter().enumerate() { + let eval_1 = value * challenge; + self.scratch_space[2 * index] = value - eval_1; + self.scratch_space[2 * index + 1] = eval_1; + } + std::mem::swap(&mut self.values, &mut self.scratch_space); + } + } +} + +impl Index for ExpandingTable { + type Output = F; + + fn index(&self, index: usize) -> &Self::Output { + assert!( + index < self.len, + "expanding table index {index} out of bounds for len {}", + self.len + ); + &self.values[index] + } +} + +#[cfg(feature = "parallel")] +fn join_or_serial( + left: impl FnOnce() -> A + Send, + right: impl FnOnce() -> B + Send, +) -> (A, B) { + rayon::join(left, right) +} + +#[cfg(not(feature = "parallel"))] +fn join_or_serial(left: impl FnOnce() -> A, right: impl FnOnce() -> B) -> (A, B) { + (left(), right()) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::EqPolynomial; + use jolt_field::{Field, Fr}; + use num_traits::One; + use rand_chacha::ChaCha20Rng; + use rand_core::SeedableRng; + + #[test] + fn high_to_low_matches_eq_table_prefixes() { + let mut rng = ChaCha20Rng::seed_from_u64(710); + let point: Vec = (0..8).map(|_| Fr::random(&mut rng)).collect(); + let mut table = ExpandingTable::new(1 << point.len(), BindingOrder::HighToLow); + table.reset(Fr::one()); + + for prefix_len in 0..=point.len() { + let expected = EqPolynomial::::evals(&point[..prefix_len], None); + assert_eq!(table.values(), expected); + if prefix_len < point.len() { + table.update(point[prefix_len]); + } + } + } + + #[test] + fn low_to_high_matches_reversed_eq_prefixes() { + let mut rng = ChaCha20Rng::seed_from_u64(711); + let point: Vec = (0..8).map(|_| Fr::random(&mut rng)).collect(); + let mut reversed_prefix = Vec::new(); + let mut table = ExpandingTable::new(1 << point.len(), BindingOrder::LowToHigh); + table.reset(Fr::one()); + + for (prefix_len, &challenge) in point.iter().enumerate() { + let expected = EqPolynomial::::evals(&reversed_prefix, None); + assert_eq!(table.values(), expected, "prefix_len={prefix_len}"); + reversed_prefix.insert(0, challenge); + table.update(challenge); + } + let expected = EqPolynomial::::evals(&reversed_prefix, None); + assert_eq!(table.values(), expected); + } + + #[test] + fn clone_and_index_expose_active_prefix_only() { + let mut table = ExpandingTable::new(8, BindingOrder::HighToLow); + table.reset(Fr::from_u64(3)); + table.update(Fr::from_u64(5)); + + assert_eq!(table.len(), 2); + assert_eq!(table[0], Fr::from_u64(3) - Fr::from_u64(15)); + assert_eq!(table[1], Fr::from_u64(15)); + assert_eq!(table.clone_values(), table.values()); + } +} diff --git a/crates/jolt-poly/src/identity.rs b/crates/jolt-poly/src/identity.rs index 2cc61284b5..f050fccec7 100644 --- a/crates/jolt-poly/src/identity.rs +++ b/crates/jolt-poly/src/identity.rs @@ -59,8 +59,8 @@ impl crate::MultilinearEvaluation for IdentityPolynomial { #[cfg(test)] mod tests { use super::*; + use jolt_field::Field; use jolt_field::Fr; - use jolt_field::FromPrimitiveInt; use num_traits::{One, Zero}; #[test] diff --git a/crates/jolt-poly/src/lagrange.rs b/crates/jolt-poly/src/lagrange.rs index 485e0742f8..c28005ea0a 100644 --- a/crates/jolt-poly/src/lagrange.rs +++ b/crates/jolt-poly/src/lagrange.rs @@ -154,10 +154,35 @@ pub fn interpolate_to_coeffs(domain_start: i64, values: &[F]) -> Vec(domain_start: i64, domain_size: usize, k: usize, r: F) -> F { + let mut numer = F::one(); + let mut denom = F::one(); + for j in 0..domain_size { + if j == k { + continue; + } + numer *= r - F::from_i64(domain_start + j as i64); + denom *= F::from_i128(k as i128 - j as i128); + } + numer / denom +} + +/// Evaluates `sum_k L_k(tau) * L_k(r)` over a consecutive integer domain. +pub fn lagrange_kernel_eval(domain_start: i64, domain_size: usize, tau: F, r: F) -> F { + let tau_evals = lagrange_evals(domain_start, domain_size, tau); + let r_evals = lagrange_evals(domain_start, domain_size, r); + tau_evals + .iter() + .zip(r_evals.iter()) + .map(|(&a, &b)| a * b) + .fold(F::zero(), |acc, value| acc + value) +} + #[cfg(test)] mod tests { use super::*; - use jolt_field::{Fr, FromPrimitiveInt}; + use jolt_field::Fr; use num_traits::{One, Zero}; #[test] diff --git a/crates/jolt-poly/src/lib.rs b/crates/jolt-poly/src/lib.rs index 88c2d27055..a67085c12e 100644 --- a/crates/jolt-poly/src/lib.rs +++ b/crates/jolt-poly/src/lib.rs @@ -48,22 +48,26 @@ mod compressed_univariate; mod dense; mod eq; mod eq_plus_one; +mod expanding_table; mod identity; pub mod lagrange; mod lt; pub mod math; mod multilinear; mod one_hot; +mod split_eq; pub mod thread; mod univariate; pub use binding::BindingOrder; pub use compressed_univariate::CompressedPoly; -pub use dense::Polynomial; +pub use dense::{bind_high_to_low, bind_low_to_high, Polynomial}; pub use eq::EqPolynomial; pub use eq_plus_one::{EqPlusOnePolynomial, EqPlusOnePrefixSuffix}; +pub use expanding_table::ExpandingTable; pub use identity::IdentityPolynomial; pub use lt::LtPolynomial; pub use multilinear::{MultilinearBinding, MultilinearEvaluation, MultilinearPoly, RlcSource}; pub use one_hot::OneHotPolynomial; +pub use split_eq::GruenSplitEqPolynomial; pub use univariate::{UnivariatePoly, UnivariatePolynomial}; diff --git a/crates/jolt-poly/src/lt.rs b/crates/jolt-poly/src/lt.rs index 1b50547463..ea473618cf 100644 --- a/crates/jolt-poly/src/lt.rs +++ b/crates/jolt-poly/src/lt.rs @@ -169,7 +169,7 @@ fn bind_in_place(v: &mut Vec, challenge: F) { #[cfg(test)] mod tests { use super::*; - use jolt_field::{Fr, FromPrimitiveInt, RandomSampling}; + use jolt_field::{Field, Fr}; use num_traits::{One, Zero}; use rand_chacha::ChaCha20Rng; use rand_core::SeedableRng; diff --git a/crates/jolt-poly/src/multilinear.rs b/crates/jolt-poly/src/multilinear.rs index b2b49906eb..e3e740034c 100644 --- a/crates/jolt-poly/src/multilinear.rs +++ b/crates/jolt-poly/src/multilinear.rs @@ -69,6 +69,8 @@ pub trait MultilinearBinding: Send + Sync { /// - [`fold_rows`](Self::fold_rows): matrix-vector product $v \cdot M$ (opening protocols) /// - [`is_one_hot`](Self::is_one_hot) / [`for_each_one`](Self::for_each_one): unit-entry /// one-hot hints for PCS commit optimization (e.g., batch addition instead of MSM) +/// - [`is_sparse`](Self::is_sparse) / [`for_each_nonzero`](Self::for_each_nonzero): +/// weighted sparse-entry hints for PCS commit optimization pub trait MultilinearPoly: Send + Sync { /// Number of variables $n$. The polynomial has $2^n$ evaluations. fn num_vars(&self) -> usize; @@ -130,6 +132,25 @@ pub trait MultilinearPoly: Send + Sync { /// should override this method. The default is a no-op for non-one-hot /// polynomials. fn for_each_one(&self, _f: &mut dyn FnMut(usize)) {} + + /// Whether this polynomial exposes sparse nonzero entries. + /// + /// This is a more general contract than [`is_one_hot`](Self::is_one_hot): + /// entries may carry arbitrary field weights. One-hot implementors get a + /// default sparse view through [`for_each_one`](Self::for_each_one). + fn is_sparse(&self) -> bool { + self.is_one_hot() + } + + /// Iterates over `(position, value)` pairs for nonzero entries. + /// + /// Implementations that return true from [`is_sparse`](Self::is_sparse) + /// should override this when entries are not unit-valued. + fn for_each_nonzero(&self, f: &mut dyn FnMut(usize, F)) { + if self.is_one_hot() { + self.for_each_one(&mut |idx| f(idx, F::one())); + } + } } // --------------------------------------------------------------------------- @@ -355,7 +376,7 @@ impl> MultilinearPoly for RlcSource { #[cfg(test)] mod tests { use super::*; - use jolt_field::{Fr, RandomSampling}; + use jolt_field::Fr; use num_traits::Zero; use rand_chacha::ChaCha20Rng; use rand_core::SeedableRng; diff --git a/crates/jolt-poly/src/one_hot.rs b/crates/jolt-poly/src/one_hot.rs index da9f097a34..fa0d96fdcc 100644 --- a/crates/jolt-poly/src/one_hot.rs +++ b/crates/jolt-poly/src/one_hot.rs @@ -150,7 +150,7 @@ impl MultilinearPoly for OneHotPolynomial { mod tests { use super::*; use crate::Polynomial; - use jolt_field::{Fr, RandomSampling}; + use jolt_field::Fr; use num_traits::Zero; use rand_chacha::ChaCha20Rng; use rand_core::{RngCore, SeedableRng}; diff --git a/crates/jolt-poly/src/polynomial.rs b/crates/jolt-poly/src/polynomial.rs new file mode 100644 index 0000000000..548ea2bd04 --- /dev/null +++ b/crates/jolt-poly/src/polynomial.rs @@ -0,0 +1,1015 @@ +//! Polynomial stored as evaluations over the Boolean hypercube. + +use std::ops::{Add, AddAssign, Mul, Neg, Sub, SubAssign}; + +use jolt_field::Field; +use rand_core::RngCore; +use serde::{Deserialize, Serialize}; + +use crate::eq::EqPolynomial; + +/// Minimum number of evaluations before parallelizing bind/evaluate. +/// +/// Below this threshold the overhead of Rayon work-stealing exceeds the +/// benefit. 1024 field elements is roughly one L1 cache line's worth of +/// useful work per core, keeping synchronization cost negligible. +pub(crate) const PAR_THRESHOLD: usize = 1024; + +/// Multilinear polynomial stored as evaluations over the Boolean hypercube $\{0,1\}^n$. +/// +/// Generic over the scalar type `T`: +/// - When `T` is a [`Field`] type: full polynomial with in-place [`bind`](Polynomial::bind), +/// [`evaluate`](Polynomial::evaluate), and arithmetic operators. +/// - When `T` is a small type (`u8`, `bool`, `i64`, etc.): compact storage with +/// [`bind_to_field`](Polynomial::bind_to_field) for on-demand field promotion. +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(bound(serialize = "T: Serialize", deserialize = "T: for<'a> Deserialize<'a>",))] +pub struct Polynomial { + evals: Vec, + num_vars: usize, +} + +impl Polynomial { + /// Creates a polynomial from its evaluations over the Boolean hypercube. + /// + /// # Panics + /// Panics if `evals.len()` is not a power of two (or zero). + pub fn new(evals: Vec) -> Self { + let len = evals.len(); + if len == 0 { + return Self { evals, num_vars: 0 }; + } + assert!( + len.is_power_of_two(), + "evaluation count must be a power of two, got {len}" + ); + let num_vars = len.trailing_zeros() as usize; + Self { evals, num_vars } + } + + /// Number of variables `n`. The polynomial has `2^n` evaluations. + #[inline] + pub fn num_vars(&self) -> usize { + self.num_vars + } + + #[inline] + pub fn len(&self) -> usize { + self.evals.len() + } + + #[inline] + pub fn is_empty(&self) -> bool { + self.evals.is_empty() + } + + /// The raw evaluation table over the Boolean hypercube. + #[inline] + pub fn evals(&self) -> &[T] { + &self.evals + } +} + +impl Polynomial { + /// Fixes the first variable to `scalar`, promoting all evaluations to field elements. + /// + /// Produces a `Polynomial` with `n - 1` variables: + /// $$g(x_2, \ldots, x_n) = (1 - s) \cdot f(0, x_2, \ldots) + s \cdot f(1, x_2, \ldots)$$ + /// + /// When `T = F`, the `From` conversion is the identity and the compiler + /// eliminates it, making this equivalent to an allocating bind. + pub fn bind_to_field>(&self, scalar: F) -> Polynomial { + let half = self.evals.len() / 2; + let mut result = Vec::with_capacity(half); + for i in 0..half { + let lo: F = self.evals[i].into(); + let hi: F = self.evals[i + half].into(); + result.push(lo + scalar * (hi - lo)); + } + Polynomial { + evals: result, + num_vars: self.num_vars - 1, + } + } +} + +impl Polynomial { + /// Creates the zero polynomial with $2^n$ evaluations all equal to zero. + pub fn zeros(num_vars: usize) -> Self { + Self { + evals: vec![F::zero(); 1 << num_vars], + num_vars, + } + } + + /// Creates a polynomial with random evaluations. + pub fn random(num_vars: usize, rng: &mut impl RngCore) -> Self { + let evals = (0..(1 << num_vars)).map(|_| F::random(rng)).collect(); + Self { evals, num_vars } + } + + /// Fixes the first (MSB) variable to `scalar` in place, halving the evaluations. + /// + /// The evaluations table is laid out so that the first variable controls the + /// upper/lower half split: indices `0..half` have $x_1 = 0$ and indices + /// `half..2*half` have $x_1 = 1$. The result is: + /// $$g(x_2, \ldots, x_n) = f(0, x_2, \ldots) + s \cdot (f(1, x_2, \ldots) - f(0, x_2, \ldots))$$ + /// + /// Equivalent to `bind_with_order(scalar, BindingOrder::HighToLow)`. + #[inline] + pub fn bind(&mut self, scalar: F) { + self.bind_high_to_low(scalar); + } + + /// Binds with the specified variable ordering. + /// + /// - `BindingOrder::HighToLow`: binds the MSB (first variable, index `0`). + /// Pairs `evals[i]` with `evals[i + half]`. + /// - `BindingOrder::LowToHigh`: binds the LSB (last variable, index `n-1`). + /// Pairs `evals[2*i]` with `evals[2*i + 1]`. + #[inline] + pub fn bind_with_order(&mut self, scalar: F, order: crate::BindingOrder) { + match order { + crate::BindingOrder::HighToLow => self.bind_high_to_low(scalar), + crate::BindingOrder::LowToHigh => self.bind_low_to_high(scalar), + } + } + + #[inline] + fn bind_high_to_low(&mut self, scalar: F) { + bind_high_to_low(&mut self.evals, scalar); + self.num_vars -= 1; + } + + #[inline] + fn bind_low_to_high(&mut self, scalar: F) { + bind_low_to_high(&mut self.evals, scalar); + self.num_vars -= 1; + } + + /// Returns the `(lo, hi)` pair for the given index and binding order. + /// + /// For sumcheck round polynomial evaluation at index `j`: + /// - `HighToLow`: `lo = evals[j]`, `hi = evals[j + half]` + /// - `LowToHigh`: `lo = evals[2*j]`, `hi = evals[2*j + 1]` + #[inline] + pub fn sumcheck_eval_pair(&self, index: usize, order: crate::BindingOrder) -> (F, F) { + match order { + crate::BindingOrder::HighToLow => { + let half = self.evals.len() / 2; + (self.evals[index], self.evals[index + half]) + } + crate::BindingOrder::LowToHigh => (self.evals[2 * index], self.evals[2 * index + 1]), + } + } + + /// Evaluates the polynomial at `point` using the multilinear extension formula: + /// $$f(r) = \sum_{x \in \{0,1\}^n} f(x) \cdot \widetilde{eq}(x, r)$$ + pub fn evaluate(&self, point: &[F]) -> F { + assert_eq!( + point.len(), + self.num_vars, + "point dimension must match num_vars" + ); + let eq_evals = EqPolynomial::new(point.to_vec()).evaluations(); + + #[cfg(feature = "parallel")] + { + if self.evals.len() >= PAR_THRESHOLD { + use rayon::prelude::*; + return self + .evals + .par_iter() + .zip(eq_evals.par_iter()) + .map(|(&f, &e)| f * e) + .sum(); + } + } + + self.evals + .iter() + .zip(eq_evals.iter()) + .map(|(&f, &e)| f * e) + .sum() + } + + /// Evaluates by sequentially binding each variable, consuming `self`. + /// + /// More memory-efficient than `evaluate` when the polynomial is no longer needed, + /// as it avoids materializing the full eq table. + pub fn evaluate_and_consume(mut self, point: &[F]) -> F { + assert_eq!( + point.len(), + self.num_vars, + "point dimension must match num_vars" + ); + for &r in point { + self.bind(r); + } + debug_assert_eq!(self.evals.len(), 1); + self.evals[0] + } + + #[inline] + pub fn evaluations(&self) -> &[F] { + &self.evals + } + + #[inline] + pub fn evaluations_mut(&mut self) -> &mut [F] { + &mut self.evals + } +} + +impl From> for Polynomial { + fn from(evaluations: Vec) -> Self { + Self::new(evaluations) + } +} + +impl crate::MultilinearEvaluation for Polynomial { + #[inline] + fn num_vars(&self) -> usize { + self.num_vars + } + + #[inline] + fn len(&self) -> usize { + self.evals.len() + } + + fn evaluate(&self, point: &[F]) -> F { + Polynomial::evaluate(self, point) + } +} + +impl crate::MultilinearBinding for Polynomial { + fn bind(&mut self, scalar: F) { + Polynomial::bind(self, scalar); + } +} + +#[inline] +fn assert_matching_dims(a: &Polynomial, b: &Polynomial) -> (usize, usize) { + assert_eq!( + a.num_vars, b.num_vars, + "num_vars mismatch: {} vs {}", + a.num_vars, b.num_vars + ); + (a.num_vars, a.evals.len()) +} + +impl Add for Polynomial { + type Output = Self; + + fn add(mut self, rhs: Self) -> Self { + self += &rhs; + self + } +} + +impl Add<&Self> for Polynomial { + type Output = Self; + + fn add(mut self, rhs: &Self) -> Self { + self += rhs; + self + } +} + +impl AddAssign for Polynomial { + fn add_assign(&mut self, rhs: Self) { + *self += &rhs; + } +} + +impl AddAssign<&Self> for Polynomial { + fn add_assign(&mut self, rhs: &Self) { + let (_nv, len) = assert_matching_dims(self, rhs); + + #[cfg(feature = "parallel")] + { + if len >= PAR_THRESHOLD { + use rayon::prelude::*; + self.evals + .par_iter_mut() + .zip(rhs.evals.par_iter()) + .for_each(|(a, b)| *a += *b); + return; + } + } + + for i in 0..len { + self.evals[i] += rhs.evals[i]; + } + } +} + +impl Sub for Polynomial { + type Output = Self; + + fn sub(mut self, rhs: Self) -> Self { + self -= &rhs; + self + } +} + +impl Sub<&Self> for Polynomial { + type Output = Self; + + fn sub(mut self, rhs: &Self) -> Self { + self -= rhs; + self + } +} + +impl SubAssign for Polynomial { + fn sub_assign(&mut self, rhs: Self) { + *self -= &rhs; + } +} + +impl SubAssign<&Self> for Polynomial { + fn sub_assign(&mut self, rhs: &Self) { + let (_nv, len) = assert_matching_dims(self, rhs); + + #[cfg(feature = "parallel")] + { + if len >= PAR_THRESHOLD { + use rayon::prelude::*; + self.evals + .par_iter_mut() + .zip(rhs.evals.par_iter()) + .for_each(|(a, b)| *a -= *b); + return; + } + } + + for i in 0..len { + self.evals[i] -= rhs.evals[i]; + } + } +} + +impl Mul for Polynomial { + type Output = Self; + + fn mul(mut self, rhs: F) -> Self { + let len = self.evals.len(); + + #[cfg(feature = "parallel")] + { + if len >= PAR_THRESHOLD { + use rayon::prelude::*; + self.evals.par_iter_mut().for_each(|a| *a *= rhs); + return self; + } + } + + for i in 0..len { + self.evals[i] *= rhs; + } + self + } +} + +impl Mul for &Polynomial { + type Output = Polynomial; + + fn mul(self, rhs: F) -> Polynomial { + self.clone() * rhs + } +} + +impl Neg for Polynomial { + type Output = Self; + + fn neg(mut self) -> Self { + let len = self.evals.len(); + + #[cfg(feature = "parallel")] + { + if len >= PAR_THRESHOLD { + use rayon::prelude::*; + self.evals.par_iter_mut().for_each(|a| *a = -*a); + return self; + } + } + + for i in 0..len { + self.evals[i] = -self.evals[i]; + } + self + } +} + +/// Fixes the MSB variable of an evaluation table to `scalar`, halving the buffer. +/// +/// Pairs `evals[i]` with `evals[i + half]`: +/// $$g(x_2, \ldots) = f(0, x_2, \ldots) + s \cdot (f(1, x_2, \ldots) - f(0, x_2, \ldots))$$ +/// +/// Operates directly on a `Vec` without tracking `num_vars`. Used by +/// [`Polynomial::bind`] internally and by compute backends that manage +/// raw buffers. +#[inline] +pub fn bind_high_to_low(evals: &mut Vec, scalar: F) { + let half = evals.len() / 2; + + #[cfg(feature = "parallel")] + { + if half >= PAR_THRESHOLD { + use rayon::prelude::*; + let (lo, hi) = evals.split_at_mut(half); + lo.par_iter_mut().zip(hi.par_iter()).for_each(|(a, b)| { + *a = *a + scalar * (*b - *a); + }); + evals.truncate(half); + return; + } + } + + for i in 0..half { + let lo = evals[i]; + let hi = evals[i + half]; + evals[i] = lo + scalar * (hi - lo); + } + evals.truncate(half); +} + +/// Fixes the LSB variable of an evaluation table to `scalar`, halving the buffer. +/// +/// Pairs `evals[2*i]` with `evals[2*i + 1]`: +/// $$g(\ldots, x_{n-1}) = f(\ldots, 0) + s \cdot (f(\ldots, 1) - f(\ldots, 0))$$ +/// +/// Operates directly on a `Vec` without tracking `num_vars`. Used by +/// [`Polynomial::bind_with_order`] internally and by compute backends that +/// manage raw buffers. +#[inline] +pub fn bind_low_to_high(evals: &mut Vec, scalar: F) { + let half = evals.len() / 2; + + #[cfg(feature = "parallel")] + { + if half >= PAR_THRESHOLD { + use rayon::prelude::*; + // Interleaved read pattern (2i, 2i+1) → write (i) aliases across + // iterations: iteration j reads evals[2j] which iteration i=2j + // writes. A separate output buffer avoids the data race. + let src: &[F] = evals; + let result: Vec = (0..half) + .into_par_iter() + .map(|i| { + let lo = src[2 * i]; + let hi = src[2 * i + 1]; + lo + scalar * (hi - lo) + }) + .collect(); + *evals = result; + return; + } + } + + for i in 0..half { + let lo = evals[2 * i]; + let hi = evals[2 * i + 1]; + evals[i] = lo + scalar * (hi - lo); + } + evals.truncate(half); +} + +#[cfg(test)] +mod tests { + use super::*; + use jolt_field::Field; + use jolt_field::Fr; + use num_traits::Zero; + use rand_chacha::ChaCha20Rng; + use rand_core::SeedableRng; + + #[test] + fn bind_to_field_then_evaluate_equals_direct_evaluate() { + let mut rng = ChaCha20Rng::seed_from_u64(1); + let n = 5; + let poly = Polynomial::::random(n, &mut rng); + let point: Vec = (0..n).map(|_| Fr::random(&mut rng)).collect(); + + let direct = poly.evaluate(&point); + + let bound = poly.bind_to_field(point[0]); + let via_bind = bound.evaluate(&point[1..]); + + assert_eq!(direct, via_bind); + } + + #[test] + fn zeros_evaluates_to_zero() { + let mut rng = ChaCha20Rng::seed_from_u64(2); + let n = 4; + let poly = Polynomial::::zeros(n); + let point: Vec = (0..n).map(|_| Fr::random(&mut rng)).collect(); + assert!(poly.evaluate(&point).is_zero()); + } + + #[test] + fn bind_matches_bind_to_field() { + let mut rng = ChaCha20Rng::seed_from_u64(3); + let n = 6; + let poly = Polynomial::::random(n, &mut rng); + let scalar = Fr::random(&mut rng); + + let bound = poly.bind_to_field(scalar); + + let mut poly_mut = poly; + poly_mut.bind(scalar); + + assert_eq!(bound.evaluations(), poly_mut.evaluations()); + } + + #[test] + fn evaluate_and_consume_matches_evaluate() { + let mut rng = ChaCha20Rng::seed_from_u64(4); + let n = 4; + let poly = Polynomial::::random(n, &mut rng); + let point: Vec = (0..n).map(|_| Fr::random(&mut rng)).collect(); + + let expected = poly.evaluate(&point); + let consumed = poly.clone().evaluate_and_consume(&point); + assert_eq!(expected, consumed); + } + + #[test] + fn empty_polynomial() { + let poly = Polynomial::::new(vec![]); + assert_eq!(poly.num_vars(), 0); + assert!(poly.is_empty()); + } + + #[test] + fn single_evaluation() { + let val = Fr::from_u64(42); + let poly = Polynomial::new(vec![val]); + assert_eq!(poly.num_vars(), 0); + assert_eq!(poly.evaluate(&[]), val); + } + + #[test] + fn sequential_bind_equals_full_evaluate() { + let mut rng = ChaCha20Rng::seed_from_u64(5); + let n = 4; + let poly = Polynomial::::random(n, &mut rng); + let point: Vec = (0..n).map(|_| Fr::random(&mut rng)).collect(); + + let mut p = poly.clone(); + for &r in &point { + p.bind(r); + } + assert_eq!(p.evals.len(), 1); + assert_eq!(p.evals[0], poly.evaluate(&point)); + } + + #[test] + fn serde_round_trip() { + let mut rng = ChaCha20Rng::seed_from_u64(100); + let poly = Polynomial::::random(4, &mut rng); + let bytes = bincode::serde::encode_to_vec(&poly, bincode::config::standard()).unwrap(); + let recovered: Polynomial = + bincode::serde::decode_from_slice(&bytes, bincode::config::standard()) + .unwrap() + .0; + assert_eq!(poly, recovered); + } + + #[test] + fn serde_round_trip_empty() { + let poly = Polynomial::::new(vec![]); + let bytes = bincode::serde::encode_to_vec(&poly, bincode::config::standard()).unwrap(); + let recovered: Polynomial = + bincode::serde::decode_from_slice(&bytes, bincode::config::standard()) + .unwrap() + .0; + assert_eq!(poly, recovered); + } + + #[test] + fn serde_round_trip_single() { + let poly = Polynomial::new(vec![Fr::from_u64(99)]); + let bytes = bincode::serde::encode_to_vec(&poly, bincode::config::standard()).unwrap(); + let recovered: Polynomial = + bincode::serde::decode_from_slice(&bytes, bincode::config::standard()) + .unwrap() + .0; + assert_eq!(poly, recovered); + } + + #[test] + fn parallel_bind_matches_bind_to_field() { + // n=11 -> 2048 evaluations, above PAR_THRESHOLD=1024 + let mut rng = ChaCha20Rng::seed_from_u64(201); + let n = 11; + let poly = Polynomial::::random(n, &mut rng); + let scalar = Fr::random(&mut rng); + + let bound = poly.bind_to_field(scalar); + + let mut poly_mut = poly; + poly_mut.bind(scalar); + + assert_eq!(bound.evaluations(), poly_mut.evaluations()); + } + + #[test] + fn parallel_bind_equals_evaluate_and_consume() { + let mut rng = ChaCha20Rng::seed_from_u64(202); + let n = 11; + let poly = Polynomial::::random(n, &mut rng); + let point: Vec = (0..n).map(|_| Fr::random(&mut rng)).collect(); + + let consumed = poly.clone().evaluate_and_consume(&point); + + let mut p = poly; + for &r in &point { + p.bind(r); + } + assert_eq!(p.evals.len(), 1); + assert_eq!(p.evals[0], consumed); + } + + #[test] + fn parallel_bind_then_evaluate_and_consume() { + let mut rng = ChaCha20Rng::seed_from_u64(203); + let n = 11; + let poly = Polynomial::::random(n, &mut rng); + let point: Vec = (0..n).map(|_| Fr::random(&mut rng)).collect(); + + let expected = poly.clone().evaluate_and_consume(&point); + + let bound = poly.bind_to_field(point[0]); + let via_bind = bound.evaluate_and_consume(&point[1..]); + assert_eq!(expected, via_bind); + } + + #[test] + fn add_element_wise() { + let mut rng = ChaCha20Rng::seed_from_u64(500); + let n = 4; + let a = Polynomial::::random(n, &mut rng); + let b = Polynomial::::random(n, &mut rng); + + let sum = a.clone() + &b; + for i in 0..sum.evaluations().len() { + assert_eq!( + sum.evaluations()[i], + a.evaluations()[i] + b.evaluations()[i] + ); + } + } + + #[test] + fn sub_element_wise() { + let mut rng = ChaCha20Rng::seed_from_u64(501); + let n = 4; + let a = Polynomial::::random(n, &mut rng); + let b = Polynomial::::random(n, &mut rng); + + let diff = a.clone() - &b; + for i in 0..diff.evaluations().len() { + assert_eq!( + diff.evaluations()[i], + a.evaluations()[i] - b.evaluations()[i] + ); + } + } + + #[test] + fn scalar_mul() { + let mut rng = ChaCha20Rng::seed_from_u64(502); + let n = 4; + let poly = Polynomial::::random(n, &mut rng); + let s = Fr::random(&mut rng); + + let scaled = poly.clone() * s; + for i in 0..scaled.evaluations().len() { + assert_eq!(scaled.evaluations()[i], poly.evaluations()[i] * s); + } + } + + #[test] + fn negation() { + let mut rng = ChaCha20Rng::seed_from_u64(503); + let n = 4; + let poly = Polynomial::::random(n, &mut rng); + + let neg = -poly.clone(); + for i in 0..neg.evaluations().len() { + assert_eq!(neg.evaluations()[i], -poly.evaluations()[i]); + } + } + + #[test] + fn add_preserves_evaluation() { + let mut rng = ChaCha20Rng::seed_from_u64(504); + let n = 5; + let a = Polynomial::::random(n, &mut rng); + let b = Polynomial::::random(n, &mut rng); + let point: Vec = (0..n).map(|_| Fr::random(&mut rng)).collect(); + + let sum = a.clone() + &b; + assert_eq!( + sum.evaluate(&point), + a.evaluate(&point) + b.evaluate(&point) + ); + } + + #[test] + fn sub_preserves_evaluation() { + let mut rng = ChaCha20Rng::seed_from_u64(505); + let n = 5; + let a = Polynomial::::random(n, &mut rng); + let b = Polynomial::::random(n, &mut rng); + let point: Vec = (0..n).map(|_| Fr::random(&mut rng)).collect(); + + let diff = a.clone() - &b; + assert_eq!( + diff.evaluate(&point), + a.evaluate(&point) - b.evaluate(&point) + ); + } + + #[test] + fn scalar_mul_preserves_evaluation() { + let mut rng = ChaCha20Rng::seed_from_u64(506); + let n = 5; + let poly = Polynomial::::random(n, &mut rng); + let s = Fr::random(&mut rng); + let point: Vec = (0..n).map(|_| Fr::random(&mut rng)).collect(); + + let scaled = poly.clone() * s; + assert_eq!(scaled.evaluate(&point), poly.evaluate(&point) * s); + } + + #[test] + #[should_panic(expected = "num_vars mismatch")] + fn add_mismatched_num_vars_panics() { + let mut rng = ChaCha20Rng::seed_from_u64(510); + let a = Polynomial::::random(3, &mut rng); + let b = Polynomial::::random(4, &mut rng); + let _ = a + b; + } + + #[test] + fn add_assign_accumulation() { + let mut rng = ChaCha20Rng::seed_from_u64(511); + let n = 4; + let a = Polynomial::::random(n, &mut rng); + let b = Polynomial::::random(n, &mut rng); + let c = Polynomial::::random(n, &mut rng); + + let mut acc = a.clone(); + acc += &b; + acc += &c; + + let expected = a.clone() + &b + &c; + assert_eq!(acc, expected); + } + + #[test] + fn neg_double_is_identity() { + let mut rng = ChaCha20Rng::seed_from_u64(512); + let poly = Polynomial::::random(4, &mut rng); + assert_eq!(-(-poly.clone()), poly); + } + + #[test] + fn add_sub_inverse() { + let mut rng = ChaCha20Rng::seed_from_u64(513); + let n = 4; + let a = Polynomial::::random(n, &mut rng); + let b = Polynomial::::random(n, &mut rng); + + let result = (a.clone() + &b) - &b; + assert_eq!(result, a); + } + + #[test] + fn ref_scalar_mul() { + let mut rng = ChaCha20Rng::seed_from_u64(514); + let n = 4; + let poly = Polynomial::::random(n, &mut rng); + let s = Fr::random(&mut rng); + + let owned_result = poly.clone() * s; + let ref_result = &poly * s; + assert_eq!(owned_result, ref_result); + } + + #[test] + fn compact_u8_bind_to_field_matches_dense() { + let scalars: Vec = vec![0, 1, 2, 3, 4, 5, 6, 7]; + let compact = Polynomial::new(scalars.clone()); + let dense_evals: Vec = scalars.iter().map(|&s| Fr::from(s)).collect(); + let dense = Polynomial::new(dense_evals); + + let mut rng = ChaCha20Rng::seed_from_u64(10); + let scalar = Fr::random(&mut rng); + + assert_eq!( + compact.bind_to_field::(scalar), + dense.bind_to_field(scalar) + ); + } + + #[test] + fn compact_u8_sequential_bind_matches_evaluate() { + let scalars: Vec = vec![0, 1, 2, 3, 4, 5, 6, 7]; + let compact = Polynomial::new(scalars.clone()); + let dense_evals: Vec = scalars.iter().map(|&s| Fr::from(s)).collect(); + let dense = Polynomial::new(dense_evals); + + let mut rng = ChaCha20Rng::seed_from_u64(10); + let point: Vec = (0..3).map(|_| Fr::random(&mut rng)).collect(); + + let mut bound = compact.bind_to_field::(point[0]); + for &r in &point[1..] { + bound.bind(r); + } + assert_eq!(bound.evals[0], dense.evaluate(&point)); + } + + #[test] + fn compact_bool_bind_to_field_matches_dense() { + let scalars: Vec = vec![true, false, false, true]; + let compact = Polynomial::new(scalars.clone()); + let dense_evals: Vec = scalars.iter().map(|&s| Fr::from(s)).collect(); + let dense = Polynomial::new(dense_evals); + + let mut rng = ChaCha20Rng::seed_from_u64(20); + let scalar = Fr::random(&mut rng); + + assert_eq!( + compact.bind_to_field::(scalar), + dense.bind_to_field(scalar) + ); + } + + #[test] + fn compact_u16_bind_to_field_matches_dense() { + let scalars: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8]; + let compact = Polynomial::new(scalars.clone()); + let dense_evals: Vec = scalars.iter().map(|&s| Fr::from(s)).collect(); + let dense = Polynomial::new(dense_evals); + + let mut rng = ChaCha20Rng::seed_from_u64(30); + let scalar = Fr::random(&mut rng); + + assert_eq!( + compact.bind_to_field::(scalar), + dense.bind_to_field(scalar) + ); + } + + #[test] + fn compact_i64_bind_to_field_matches_dense() { + let scalars: Vec = vec![-1, 0, 1, -100, i64::MIN, i64::MAX, -42, 42]; + let compact = Polynomial::new(scalars.clone()); + let dense_evals: Vec = scalars.iter().map(|&s| Fr::from(s)).collect(); + let dense = Polynomial::new(dense_evals); + + let mut rng = ChaCha20Rng::seed_from_u64(50); + let scalar = Fr::random(&mut rng); + + assert_eq!( + compact.bind_to_field::(scalar), + dense.bind_to_field(scalar) + ); + } + + #[test] + fn compact_i128_bind_to_field_matches_dense() { + let scalars: Vec = vec![-1, 0, 1, -999, i128::MIN, i128::MAX, -7, 7]; + let compact = Polynomial::new(scalars.clone()); + let dense_evals: Vec = scalars.iter().map(|&s| Fr::from(s)).collect(); + let dense = Polynomial::new(dense_evals); + + let mut rng = ChaCha20Rng::seed_from_u64(60); + let scalar = Fr::random(&mut rng); + + assert_eq!( + compact.bind_to_field::(scalar), + dense.bind_to_field(scalar) + ); + } + + #[test] + fn compact_u128_bind_to_field_matches_dense() { + let scalars: Vec = vec![u128::MAX, u128::MAX - 1, 0, 1]; + let compact = Polynomial::new(scalars.clone()); + let dense_evals: Vec = scalars.iter().map(|&s| Fr::from(s)).collect(); + let dense = Polynomial::new(dense_evals); + + let mut rng = ChaCha20Rng::seed_from_u64(70); + let scalar = Fr::random(&mut rng); + + assert_eq!( + compact.bind_to_field::(scalar), + dense.bind_to_field(scalar) + ); + } + + #[test] + fn compact_bind_chain_consistency() { + let scalars: Vec = vec![10, 20, 30, 40, 50, 60, 70, 80]; + let compact = Polynomial::new(scalars.clone()); + let dense_evals: Vec = scalars.iter().map(|&s| Fr::from(s)).collect(); + let dense = Polynomial::new(dense_evals); + + let mut rng = ChaCha20Rng::seed_from_u64(80); + let r1 = Fr::random(&mut rng); + let r2 = Fr::random(&mut rng); + let remaining: Vec = (0..1).map(|_| Fr::random(&mut rng)).collect(); + + // bind_to_field(r1) then bind(r2) should match dense evaluate + let mut bound = compact.bind_to_field::(r1); + bound.bind(r2); + let result = bound.evaluate(&remaining); + + let mut full_point = vec![r1, r2]; + full_point.extend_from_slice(&remaining); + assert_eq!(result, dense.evaluate(&full_point)); + } + + #[test] + fn compact_empty() { + let compact = Polynomial::::new(vec![]); + assert_eq!(compact.num_vars(), 0); + assert!(compact.is_empty()); + } + + #[test] + fn compact_single_element() { + let compact = Polynomial::::new(vec![42]); + assert_eq!(compact.num_vars(), 0); + assert_eq!(compact.evals(), &[42u64]); + } + + #[test] + fn serde_round_trip_compact_u8() { + let scalars: Vec = vec![0, 1, 2, 3, 4, 5, 6, 7]; + let compact = Polynomial::new(scalars); + let bytes = bincode::serde::encode_to_vec(&compact, bincode::config::standard()).unwrap(); + let recovered: Polynomial = + bincode::serde::decode_from_slice(&bytes, bincode::config::standard()) + .unwrap() + .0; + + let mut rng = ChaCha20Rng::seed_from_u64(40); + let scalar = Fr::random(&mut rng); + assert_eq!( + compact.bind_to_field::(scalar), + recovered.bind_to_field::(scalar) + ); + } + + #[test] + fn serde_round_trip_compact_bool() { + let scalars: Vec = vec![true, false, true, false]; + let compact = Polynomial::new(scalars); + let bytes = bincode::serde::encode_to_vec(&compact, bincode::config::standard()).unwrap(); + let recovered: Polynomial = + bincode::serde::decode_from_slice(&bytes, bincode::config::standard()) + .unwrap() + .0; + + let mut rng = ChaCha20Rng::seed_from_u64(41); + let scalar = Fr::random(&mut rng); + assert_eq!( + compact.bind_to_field::(scalar), + recovered.bind_to_field::(scalar) + ); + } + + #[test] + fn low_to_high_binding_produces_correct_evaluation() { + let mut rng = ChaCha20Rng::seed_from_u64(900); + let n = 5; + let poly = Polynomial::::random(n, &mut rng); + let point: Vec = (0..n).map(|_| Fr::random(&mut rng)).collect(); + + // HighToLow binds point[0] first (MSB), so binding sequentially + // with point[0], point[1], ... should yield evaluate(point). + let mut hi_to_lo = poly.clone(); + for &r in &point { + hi_to_lo.bind_with_order(r, crate::BindingOrder::HighToLow); + } + assert_eq!(hi_to_lo.len(), 1); + assert_eq!(hi_to_lo.evaluations()[0], poly.evaluate(&point)); + + // LowToHigh binds point[n-1] first (LSB), so to get the same + // evaluation we must reverse the order of challenges. + let mut lo_to_hi = poly.clone(); + for &r in point.iter().rev() { + lo_to_hi.bind_with_order(r, crate::BindingOrder::LowToHigh); + } + assert_eq!(lo_to_hi.len(), 1); + assert_eq!(lo_to_hi.evaluations()[0], poly.evaluate(&point)); + } +} diff --git a/crates/jolt-poly/src/source.rs b/crates/jolt-poly/src/source.rs new file mode 100644 index 0000000000..2556f7f92b --- /dev/null +++ b/crates/jolt-poly/src/source.rs @@ -0,0 +1,553 @@ +//! Abstract multilinear polynomial trait and compositions. +//! +//! [`MultilinearPoly`] is the core abstraction over multilinear polynomials +//! in evaluation form. Implementations range from dense evaluation tables +//! ([`Polynomial`](crate::Polynomial)) to structured sparse representations +//! ([`OneHotPolynomial`](crate::OneHotPolynomial)) to lazy compositions ([`RlcSource`]). The trait +//! decouples polynomial *access* from *storage*, enabling streaming opening +//! proofs where the full $2^n$ table never resides in memory simultaneously. +//! +//! [`RlcSource`] composes multiple polynomials via random linear combination +//! without materializing the combined table. Its [`fold_rows`](MultilinearPoly::fold_rows) +//! distributes across constituents, avoiding allocation of the combined table. + +use jolt_field::Field; + +use crate::Polynomial; + +/// A multilinear polynomial $f : \{0,1\}^n \to \mathbb{F}$ in evaluation form. +/// +/// The evaluation table can be viewed as a $(2^\nu \times 2^\sigma)$ matrix +/// where $\nu + \sigma = n$. Implementations range from dense evaluation +/// tables ([`Polynomial`](crate::Polynomial)) to structured sparse forms +/// ([`OneHotPolynomial`](crate::OneHotPolynomial)) to lazy compositions ([`RlcSource`]). +/// +/// Core operations: +/// - [`num_vars`](Self::num_vars) / [`evaluate`](Self::evaluate): metadata and point evaluation +/// - [`for_each_row`](Self::for_each_row): row-wise iteration (streaming commit, row-based MSM) +/// - [`fold_rows`](Self::fold_rows): matrix-vector product $v \cdot M$ (opening protocols) +/// - [`is_sparse`](Self::is_sparse) / [`for_each_nonzero`](Self::for_each_nonzero): sparsity +/// hints for PCS commit optimization (e.g., batch addition instead of MSM) +pub trait MultilinearPoly: Send + Sync { + /// Number of variables $n$. The polynomial has $2^n$ evaluations. + fn num_vars(&self) -> usize; + + /// Evaluates $f(r)$ at an arbitrary point $r \in \mathbb{F}^n$. + fn evaluate(&self, point: &[F]) -> F; + + /// Iterates over the evaluation table in row-major order. + /// + /// The table is interpreted as a $(2^\nu \times 2^\sigma)$ matrix where + /// $\sigma$ is the number of column variables and $\nu = n - \sigma$. + /// The closure receives `(row_index, row_data)` pairs in order. + /// + /// For in-memory polynomials, rows are borrowed slices (zero-copy). + /// For lazy sources, each row may be computed on-the-fly. + fn for_each_row(&self, sigma: usize, f: &mut dyn FnMut(usize, &[F])); + + /// Folds a left vector against the $(2^\nu \times 2^\sigma)$ matrix form. + /// + /// Computes: + /// $$\text{result}\[c\] = \sum_{r=0}^{2^\nu - 1} \text{left}\[r\] \cdot M\[r\]\[c\]$$ + /// + /// where $M\[r\]\[c\] = f(\text{bits}(r \cdot 2^\sigma + c))$ and + /// $\nu = n - \sigma$. + /// + /// The default implementation iterates rows via [`for_each_row`](Self::for_each_row). + /// Implementations with distributable structure (e.g., [`RlcSource`]) or + /// sparse representations (e.g., one-hot polynomials) should override + /// for better performance. + /// + /// # Panics + /// + /// Panics if `left.len() != 2^(num_vars - sigma)`. + fn fold_rows(&self, left: &[F], sigma: usize) -> Vec { + let num_cols = 1usize << sigma; + let mut result = vec![F::zero(); num_cols]; + self.for_each_row(sigma, &mut |row_idx, row| { + let l = left[row_idx]; + for (r, &val) in result.iter_mut().zip(row.iter()) { + *r += l * val; + } + }); + result + } + + /// Whether this polynomial has sparse structure that allows more efficient + /// commitment (e.g., batch affine addition instead of full MSM). + /// + /// When true, PCS backends should use [`for_each_nonzero`](Self::for_each_nonzero) + /// to access only the nonzero entries. + fn is_sparse(&self) -> bool { + false + } + + /// Iterates over nonzero entries as `(flat_index, value)` pairs. + /// + /// For dense polynomials, the default scans the full table. Structured + /// sparse types (e.g., [`OneHotPolynomial`](crate::OneHotPolynomial)) yield only O(T) entries. + fn for_each_nonzero(&self, f: &mut dyn FnMut(usize, F)) { + let n = self.num_vars(); + let total = 1usize << n; + self.for_each_row(n, &mut |_, row| { + for (i, &val) in row.iter().take(total).enumerate() { + if !val.is_zero() { + f(i, val); + } + } + }); + } +} + +impl MultilinearPoly for Polynomial { + #[inline] + fn num_vars(&self) -> usize { + Polynomial::num_vars(self) + } + + fn evaluate(&self, point: &[F]) -> F { + Polynomial::evaluate(self, point) + } + + fn for_each_row(&self, sigma: usize, f: &mut dyn FnMut(usize, &[F])) { + let num_cols = 1usize << sigma; + for (i, row) in self.evaluations().chunks(num_cols).enumerate() { + f(i, row); + } + } + + fn fold_rows(&self, left: &[F], sigma: usize) -> Vec { + let num_cols = 1usize << sigma; + let evals = self.evaluations(); + debug_assert_eq!( + left.len(), + evals.len() / num_cols, + "left vector length must equal number of rows" + ); + + let mut result = vec![F::zero(); num_cols]; + for (row_idx, row) in evals.chunks(num_cols).enumerate() { + let l = left[row_idx]; + for (r, &val) in result.iter_mut().zip(row.iter()) { + *r += l * val; + } + } + result + } +} + +impl MultilinearPoly for [F] { + #[inline] + fn num_vars(&self) -> usize { + if self.is_empty() { + return 0; + } + assert!( + self.len().is_power_of_two(), + "slice length must be a power of two, got {}", + self.len() + ); + self.len().trailing_zeros() as usize + } + + fn evaluate(&self, point: &[F]) -> F { + let eq_evals = crate::EqPolynomial::new(point.to_vec()).evaluations(); + self.iter().zip(eq_evals.iter()).map(|(&f, &e)| f * e).sum() + } + + fn for_each_row(&self, sigma: usize, f: &mut dyn FnMut(usize, &[F])) { + let num_cols = 1usize << sigma; + for (i, row) in self.chunks(num_cols).enumerate() { + f(i, row); + } + } + + fn fold_rows(&self, left: &[F], sigma: usize) -> Vec { + let num_cols = 1usize << sigma; + let mut result = vec![F::zero(); num_cols]; + for (row_idx, row) in self.chunks(num_cols).enumerate() { + let l = left[row_idx]; + for (r, &val) in result.iter_mut().zip(row.iter()) { + *r += l * val; + } + } + result + } +} + +impl MultilinearPoly for Vec { + #[inline] + fn num_vars(&self) -> usize { + self.as_slice().num_vars() + } + + fn evaluate(&self, point: &[F]) -> F { + self.as_slice().evaluate(point) + } + + fn for_each_row(&self, sigma: usize, f: &mut dyn FnMut(usize, &[F])) { + self.as_slice().for_each_row(sigma, f); + } + + fn fold_rows(&self, left: &[F], sigma: usize) -> Vec { + self.as_slice().fold_rows(left, sigma) + } +} + +/// Lazy RLC composition of multilinear polynomials. +/// +/// Represents $f(x) = \sum_{i=0}^{k-1} s_i \cdot f_i(x)$ without +/// materializing the combined evaluation table. Operations distribute +/// over the constituents: +/// +/// - [`evaluate`](MultilinearPoly::evaluate): $\sum_i s_i \cdot f_i(r)$ +/// - [`fold_rows`](MultilinearPoly::fold_rows): $\sum_i s_i \cdot (v \cdot M_i)$ — +/// each polynomial computes its own fold, results are combined with scalars. +/// No evaluation table is ever materialized. +pub struct RlcSource> { + sources: Vec, + scalars: Vec, + num_vars: usize, +} + +impl> RlcSource { + /// Creates a lazy RLC composition. + /// + /// # Panics + /// + /// Panics if `sources` and `scalars` have different lengths, or if + /// sources have inconsistent `num_vars`. + pub fn new(sources: Vec, scalars: Vec) -> Self { + assert_eq!(sources.len(), scalars.len()); + let num_vars = sources.first().map_or(0, |s| s.num_vars()); + debug_assert!( + sources.iter().all(|s| s.num_vars() == num_vars), + "all sources must have the same num_vars" + ); + Self { + sources, + scalars, + num_vars, + } + } + + pub fn sources(&self) -> &[S] { + &self.sources + } + + pub fn scalars(&self) -> &[F] { + &self.scalars + } +} + +impl> MultilinearPoly for RlcSource { + fn num_vars(&self) -> usize { + self.num_vars + } + + fn evaluate(&self, point: &[F]) -> F { + self.sources + .iter() + .zip(&self.scalars) + .map(|(source, &scalar)| scalar * source.evaluate(point)) + .fold(F::zero(), |acc, x| acc + x) + } + + /// Iterates over combined rows by collecting each source's rows and combining. + /// + /// Memory: O(k × 2^σ) where k = number of sources. + /// For streaming-critical paths, prefer [`fold_rows`](Self::fold_rows) which + /// distributes without materializing any rows. + fn for_each_row(&self, sigma: usize, f: &mut dyn FnMut(usize, &[F])) { + if self.sources.is_empty() { + return; + } + + let num_cols = 1usize << sigma; + let nu = self.num_vars.saturating_sub(sigma); + let num_rows = 1usize << nu; + + // Collect all rows from all sources. + // Each inner vec has num_rows entries, each of length num_cols. + let all_rows: Vec>> = self + .sources + .iter() + .map(|source| { + let mut rows = Vec::with_capacity(num_rows); + source.for_each_row(sigma, &mut |_idx, row| { + rows.push(row.to_vec()); + }); + rows + }) + .collect(); + + let mut combined = vec![F::zero(); num_cols]; + for row_idx in 0..num_rows { + combined.fill(F::zero()); + for (source_rows, &scalar) in all_rows.iter().zip(&self.scalars) { + for (dst, &val) in combined.iter_mut().zip(source_rows[row_idx].iter()) { + *dst += scalar * val; + } + } + f(row_idx, &combined); + } + } + + /// Distributes fold_rows across constituent sources. + /// + /// Computes $\sum_i s_i \cdot (v \cdot M_i)$ by having each source + /// independently compute its own fold. No evaluation table is + /// ever materialized — this is the key streaming win. + fn fold_rows(&self, left: &[F], sigma: usize) -> Vec { + let num_cols = 1usize << sigma; + let mut result = vec![F::zero(); num_cols]; + for (source, &scalar) in self.sources.iter().zip(&self.scalars) { + let contribution = source.fold_rows(left, sigma); + for (r, &c) in result.iter_mut().zip(contribution.iter()) { + *r += scalar * c; + } + } + result + } +} + +#[cfg(test)] +mod tests { + use super::*; + use jolt_field::Fr; + use num_traits::Zero; + use rand_chacha::ChaCha20Rng; + use rand_core::SeedableRng; + + #[test] + fn polynomial_for_each_row_matches_chunks() { + let mut rng = ChaCha20Rng::seed_from_u64(1); + let poly = Polynomial::::random(4, &mut rng); + let sigma = 2; + let num_cols = 1usize << sigma; + + let mut rows = Vec::new(); + poly.for_each_row(sigma, &mut |_idx, row| { + rows.push(row.to_vec()); + }); + + assert_eq!(rows.len(), poly.len() / num_cols); + for (i, row) in rows.iter().enumerate() { + let start = i * num_cols; + assert_eq!(row.as_slice(), &poly.evaluations()[start..start + num_cols]); + } + } + + #[test] + fn polynomial_fold_rows_matches_manual_vmp() { + let mut rng = ChaCha20Rng::seed_from_u64(2); + let num_vars = 4; + let sigma = 2; + let nu = num_vars - sigma; + let num_cols = 1usize << sigma; + let num_rows = 1usize << nu; + + let poly = Polynomial::::random(num_vars, &mut rng); + let left: Vec = (0..num_rows).map(|_| Fr::random(&mut rng)).collect(); + + let result = poly.fold_rows(&left, sigma); + + // Manual VMP + let mut expected = vec![Fr::zero(); num_cols]; + for (row, &l) in left.iter().enumerate() { + for (col, dest) in expected.iter_mut().enumerate() { + *dest += l * poly.evaluations()[row * num_cols + col]; + } + } + + assert_eq!(result, expected); + } + + #[test] + fn rlc_source_evaluate_matches_manual() { + let mut rng = ChaCha20Rng::seed_from_u64(10); + let num_vars = 3; + + let p1 = Polynomial::::random(num_vars, &mut rng); + let p2 = Polynomial::::random(num_vars, &mut rng); + let s1 = Fr::random(&mut rng); + let s2 = Fr::random(&mut rng); + + let point: Vec = (0..num_vars).map(|_| Fr::random(&mut rng)).collect(); + + let rlc = RlcSource::new(vec![p1.clone(), p2.clone()], vec![s1, s2]); + let result = rlc.evaluate(&point); + let expected = s1 * p1.evaluate(&point) + s2 * p2.evaluate(&point); + + assert_eq!(result, expected); + } + + #[test] + fn rlc_source_fold_rows_matches_materialized() { + let mut rng = ChaCha20Rng::seed_from_u64(20); + let num_vars = 4; + let sigma = 2; + let nu = num_vars - sigma; + let num_rows = 1usize << nu; + + let p1 = Polynomial::::random(num_vars, &mut rng); + let p2 = Polynomial::::random(num_vars, &mut rng); + let s1 = Fr::random(&mut rng); + let s2 = Fr::random(&mut rng); + let left: Vec = (0..num_rows).map(|_| Fr::random(&mut rng)).collect(); + + // Lazy fold + let rlc = RlcSource::new(vec![p1.clone(), p2.clone()], vec![s1, s2]); + let lazy_result = rlc.fold_rows(&left, sigma); + + // Materialized fold + let combined_evals: Vec = p1 + .evaluations() + .iter() + .zip(p2.evaluations().iter()) + .map(|(&a, &b)| s1 * a + s2 * b) + .collect(); + let combined = Polynomial::new(combined_evals); + let materialized_result = combined.fold_rows(&left, sigma); + + assert_eq!(lazy_result, materialized_result); + } + + #[test] + fn rlc_source_for_each_row_matches_materialized() { + let mut rng = ChaCha20Rng::seed_from_u64(30); + let num_vars = 3; + let sigma = 1; + + let p1 = Polynomial::::random(num_vars, &mut rng); + let p2 = Polynomial::::random(num_vars, &mut rng); + let s1 = Fr::random(&mut rng); + let s2 = Fr::random(&mut rng); + + let rlc = RlcSource::new(vec![p1.clone(), p2.clone()], vec![s1, s2]); + + let mut lazy_rows = Vec::new(); + rlc.for_each_row(sigma, &mut |_idx, row| { + lazy_rows.push(row.to_vec()); + }); + + let combined_evals: Vec = p1 + .evaluations() + .iter() + .zip(p2.evaluations().iter()) + .map(|(&a, &b)| s1 * a + s2 * b) + .collect(); + let combined = Polynomial::new(combined_evals); + let mut materialized_rows = Vec::new(); + combined.for_each_row(sigma, &mut |_idx, row| { + materialized_rows.push(row.to_vec()); + }); + + assert_eq!(lazy_rows, materialized_rows); + } + + #[test] + fn rlc_source_fold_equals_evaluate_at_point() { + use crate::eq::EqPolynomial; + + let mut rng = ChaCha20Rng::seed_from_u64(40); + let num_vars = 4; + let sigma = 2; + let nu = num_vars - sigma; + + let p1 = Polynomial::::random(num_vars, &mut rng); + let p2 = Polynomial::::random(num_vars, &mut rng); + let p3 = Polynomial::::random(num_vars, &mut rng); + let s1 = Fr::random(&mut rng); + let s2 = Fr::random(&mut rng); + let s3 = Fr::random(&mut rng); + + let point: Vec = (0..num_vars).map(|_| Fr::random(&mut rng)).collect(); + + // Split point into row-point (first nu vars) and col-point (last sigma vars) + let row_point = &point[..nu]; + let col_point = &point[nu..]; + + let rlc = RlcSource::new(vec![p1.clone(), p2.clone(), p3.clone()], vec![s1, s2, s3]); + + // fold_rows with eq(row_point) as left vector, then dot with eq(col_point) + let eq_rows = EqPolynomial::new(row_point.to_vec()).evaluations(); + let folded = rlc.fold_rows(&eq_rows, sigma); + let eq_cols = EqPolynomial::new(col_point.to_vec()).evaluations(); + let via_fold: Fr = folded + .iter() + .zip(eq_cols.iter()) + .map(|(&a, &b)| a * b) + .sum(); + + // Direct evaluation + let via_eval = rlc.evaluate(&point); + + assert_eq!(via_fold, via_eval); + } + + #[test] + fn default_fold_rows_matches_override() { + let mut rng = ChaCha20Rng::seed_from_u64(50); + let num_vars = 4; + let sigma = 2; + let nu = num_vars - sigma; + let num_rows = 1usize << nu; + + let poly = Polynomial::::random(num_vars, &mut rng); + let left: Vec = (0..num_rows).map(|_| Fr::random(&mut rng)).collect(); + + // Use the default impl (via for_each_row) + let default_result = default_fold_rows(&poly, &left, sigma); + + // Use the overridden impl + let override_result = poly.fold_rows(&left, sigma); + + assert_eq!(default_result, override_result); + } + + /// Calls the default `fold_rows` implementation (via `for_each_row`). + fn default_fold_rows( + source: &impl MultilinearPoly, + left: &[F], + sigma: usize, + ) -> Vec { + let num_cols = 1usize << sigma; + let mut result = vec![F::zero(); num_cols]; + source.for_each_row(sigma, &mut |row_idx, row| { + let l = left[row_idx]; + for (r, &val) in result.iter_mut().zip(row.iter()) { + *r += l * val; + } + }); + result + } + + #[test] + fn empty_rlc_source() { + let rlc: RlcSource> = RlcSource::new(vec![], vec![]); + assert_eq!(rlc.num_vars(), 0); + } + + #[test] + fn single_source_rlc_is_scaled_original() { + let mut rng = ChaCha20Rng::seed_from_u64(60); + let num_vars = 3; + let sigma = 1; + let nu = num_vars - sigma; + let num_rows = 1usize << nu; + + let poly = Polynomial::::random(num_vars, &mut rng); + let scalar = Fr::random(&mut rng); + let left: Vec = (0..num_rows).map(|_| Fr::random(&mut rng)).collect(); + + let rlc = RlcSource::new(vec![poly.clone()], vec![scalar]); + let rlc_result = rlc.fold_rows(&left, sigma); + + // Manually scale the polynomial fold + let direct_result = poly.fold_rows(&left, sigma); + let scaled: Vec = direct_result.iter().map(|&v| scalar * v).collect(); + + assert_eq!(rlc_result, scaled); + } +} diff --git a/crates/jolt-poly/src/split_eq.rs b/crates/jolt-poly/src/split_eq.rs new file mode 100644 index 0000000000..501cb537c9 --- /dev/null +++ b/crates/jolt-poly/src/split_eq.rs @@ -0,0 +1,438 @@ +//! Split equality polynomial used by sumcheck provers. +//! +//! This implements the Dao-Thaler/Gruen factorization used by Jolt's larger +//! sumchecks. It stores prefix tables for two halves of the remaining equality +//! polynomial and tracks already-bound variables in a scalar. + +use jolt_field::Field; + +use crate::{BindingOrder, EqPolynomial, Polynomial, UnivariatePoly}; + +#[cfg(feature = "parallel")] +use rayon::prelude::*; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct GruenSplitEqPolynomial { + current_index: usize, + current_scalar: F, + w: Vec, + e_in_vec: Vec>, + e_out_vec: Vec>, + binding_order: BindingOrder, +} + +impl GruenSplitEqPolynomial { + #[tracing::instrument(skip_all, name = "GruenSplitEqPolynomial::new_with_scaling")] + pub fn new_with_scaling( + w: &[F], + binding_order: BindingOrder, + scaling_factor: Option, + ) -> Self { + assert!(!w.is_empty(), "split eq requires at least one variable"); + match binding_order { + BindingOrder::LowToHigh => { + let split = w.len() / 2; + let w_prime = &w[..w.len() - 1]; + let (w_out, w_in) = w_prime.split_at(split); + let (e_out_vec, e_in_vec) = join_or_serial( + || EqPolynomial::evals_cached(w_out, None), + || EqPolynomial::evals_cached(w_in, None), + ); + Self { + current_index: w.len(), + current_scalar: scaling_factor.unwrap_or_else(F::one), + w: w.to_vec(), + e_in_vec, + e_out_vec, + binding_order, + } + } + BindingOrder::HighToLow => { + let w_prime = &w[1..]; + let split = w.len() / 2; + let (w_in, w_out) = w_prime.split_at(split); + let (e_in_vec, e_out_vec) = join_or_serial( + || EqPolynomial::evals_cached_rev(w_in, None), + || EqPolynomial::evals_cached_rev(w_out, None), + ); + Self { + current_index: 0, + current_scalar: scaling_factor.unwrap_or_else(F::one), + w: w.to_vec(), + e_in_vec, + e_out_vec, + binding_order, + } + } + } + } + + #[tracing::instrument(skip_all, name = "GruenSplitEqPolynomial::new")] + pub fn new(w: &[F], binding_order: BindingOrder) -> Self { + Self::new_with_scaling(w, binding_order, None) + } + + #[inline] + pub fn num_vars(&self) -> usize { + self.w.len() + } + + #[inline] + pub fn len(&self) -> usize { + match self.binding_order { + BindingOrder::LowToHigh => 1 << self.current_index, + BindingOrder::HighToLow => 1 << (self.w.len() - self.current_index), + } + } + + #[inline] + pub fn is_empty(&self) -> bool { + false + } + + #[inline] + pub fn num_bound_vars(&self) -> usize { + match self.binding_order { + BindingOrder::LowToHigh => self.w.len() - self.current_index, + BindingOrder::HighToLow => self.current_index, + } + } + + #[inline] + pub fn e_in_current_len(&self) -> usize { + self.e_in_current().len() + } + + #[inline] + pub fn e_out_current_len(&self) -> usize { + self.e_out_current().len() + } + + #[inline] + pub fn e_in_current(&self) -> &[F] { + &self.e_in_vec[self.e_in_vec.len() - 1] + } + + #[inline] + pub fn e_out_current(&self) -> &[F] { + &self.e_out_vec[self.e_out_vec.len() - 1] + } + + pub fn e_out_in_for_window(&self, window_size: usize) -> (&[F], &[F]) { + assert_eq!( + self.binding_order, + BindingOrder::LowToHigh, + "streaming windows are not defined for high-to-low split eq" + ); + let num_unbound = self.current_index; + let window_size = window_size.min(num_unbound); + let head_len = num_unbound.saturating_sub(window_size); + let split = self.w.len() / 2; + let head_out_bits = head_len.min(split); + let head_in_bits = head_len.saturating_sub(head_out_bits); + (&self.e_out_vec[head_out_bits], &self.e_in_vec[head_in_bits]) + } + + pub fn e_active_for_window(&self, window_size: usize) -> Vec { + if window_size <= 1 { + return vec![F::one()]; + } + assert_eq!( + self.binding_order, + BindingOrder::LowToHigh, + "streaming windows are not defined for high-to-low split eq" + ); + let num_unbound = self.current_index; + if window_size > num_unbound { + return vec![F::one()]; + } + let remaining_w = &self.w[..num_unbound]; + let window_start = remaining_w.len() - window_size; + let (_head, w_window) = remaining_w.split_at(window_start); + let (w_active, _w_current) = w_window.split_at(window_size - 1); + EqPolynomial::::evals(w_active, None) + } + + #[tracing::instrument(skip_all, name = "GruenSplitEqPolynomial::bind")] + pub fn bind(&mut self, r: F) { + match self.binding_order { + BindingOrder::LowToHigh => { + let w = self.w[self.current_index - 1]; + let prod = w * r; + self.current_scalar *= F::one() - w - r + prod + prod; + self.current_index -= 1; + if self.w.len() / 2 < self.current_index && self.e_in_vec.len() > 1 { + let _ = self.e_in_vec.pop(); + } else if 0 < self.current_index && self.e_out_vec.len() > 1 { + let _ = self.e_out_vec.pop(); + } + } + BindingOrder::HighToLow => { + let w = self.w[self.current_index]; + let prod = w * r; + self.current_scalar *= F::one() - w - r + prod + prod; + self.current_index += 1; + if self.current_index <= self.w.len() / 2 && self.e_in_vec.len() > 1 { + let _ = self.e_in_vec.pop(); + } else if self.current_index <= self.w.len() && self.e_out_vec.len() > 1 { + let _ = self.e_out_vec.pop(); + } + } + } + } + + pub fn gruen_poly_deg_3( + &self, + q_constant: F, + q_quadratic_coeff: F, + s_0_plus_s_1: F, + ) -> UnivariatePoly { + let eq_eval_1 = self.current_scalar * self.current_w(); + let eq_eval_0 = self.current_scalar - eq_eval_1; + let eq_slope = eq_eval_1 - eq_eval_0; + let eq_eval_2 = eq_eval_1 + eq_slope; + let eq_eval_3 = eq_eval_2 + eq_slope; + + let quadratic_eval_0 = q_constant; + let cubic_eval_0 = eq_eval_0 * quadratic_eval_0; + let cubic_eval_1 = s_0_plus_s_1 - cubic_eval_0; + let quadratic_eval_1 = cubic_eval_1 / eq_eval_1; + let e_times_2 = q_quadratic_coeff + q_quadratic_coeff; + let quadratic_eval_2 = quadratic_eval_1 + quadratic_eval_1 - quadratic_eval_0 + e_times_2; + let quadratic_eval_3 = + quadratic_eval_2 + quadratic_eval_1 - quadratic_eval_0 + e_times_2 + e_times_2; + + UnivariatePoly::from_evals(&[ + cubic_eval_0, + cubic_eval_1, + eq_eval_2 * quadratic_eval_2, + eq_eval_3 * quadratic_eval_3, + ]) + } + + pub fn gruen_poly_deg_2(&self, q_0: F, previous_claim: F) -> UnivariatePoly { + let eq_eval_1 = self.current_scalar * self.current_w(); + let eq_eval_0 = self.current_scalar - eq_eval_1; + let eq_slope = eq_eval_1 - eq_eval_0; + let eq_eval_2 = eq_eval_1 + eq_slope; + + let quadratic_eval_0 = eq_eval_0 * q_0; + let quadratic_eval_1 = previous_claim - quadratic_eval_0; + let linear_eval_1 = quadratic_eval_1 / eq_eval_1; + let linear_eval_2 = linear_eval_1 + linear_eval_1 - q_0; + + UnivariatePoly::from_evals(&[ + quadratic_eval_0, + quadratic_eval_1, + eq_eval_2 * linear_eval_2, + ]) + } + + pub fn gruen_poly_from_evals(&self, q_evals: &[F], s_0_plus_s_1: F) -> UnivariatePoly { + assert!(!q_evals.is_empty(), "q_evals must be non-empty"); + let r_round = self.current_w(); + let l_at_0 = self.current_scalar * EqPolynomial::::mle(&[F::zero()], &[r_round]); + let l_at_1 = self.current_scalar * EqPolynomial::::mle(&[F::one()], &[r_round]); + let q_at_0 = (s_0_plus_s_1 - l_at_1 * q_evals[0]) / l_at_0; + + let mut full_q_evals = Vec::with_capacity(q_evals.len() + 1); + full_q_evals.push(q_at_0); + full_q_evals.extend_from_slice(q_evals); + let q = UnivariatePoly::from_evals_toom(&full_q_evals); + + let l_c0 = l_at_0; + let l_c1 = l_at_1 - l_at_0; + let q_coeffs = q.into_coefficients(); + let mut s_coeffs = vec![F::zero(); q_coeffs.len() + 1]; + for (index, q_coeff) in q_coeffs.into_iter().enumerate() { + s_coeffs[index] += q_coeff * l_c0; + s_coeffs[index + 1] += q_coeff * l_c1; + } + UnivariatePoly::new(s_coeffs) + } + + pub fn merge(&self) -> Polynomial { + let evals = match self.binding_order { + BindingOrder::LowToHigh => { + EqPolynomial::evals(&self.w[..self.current_index], Some(self.current_scalar)) + } + BindingOrder::HighToLow => { + EqPolynomial::evals(&self.w[self.current_index..], Some(self.current_scalar)) + } + }; + Polynomial::new(evals) + } + + #[inline] + pub fn current_scalar(&self) -> F { + self.current_scalar + } + + #[inline] + pub fn current_w(&self) -> F { + match self.binding_order { + BindingOrder::LowToHigh => self.w[self.current_index - 1], + BindingOrder::HighToLow => self.w[self.current_index], + } + } + + #[inline] + pub fn group_index(&self, x_out: usize, x_in: usize) -> usize { + let num_x_in_bits = self.e_in_current_len().trailing_zeros() as usize; + (x_out << num_x_in_bits) | x_in + } + + pub fn fold_out_in< + OuterAcc: Send, + InnerAcc: Send, + MakeInner: Fn() -> InnerAcc + Sync + Send, + InnerStep: Fn(&mut InnerAcc, usize, usize, F) + Sync + Send, + OuterStep: Fn(usize, F, InnerAcc) -> OuterAcc + Sync + Send, + Merge: Fn(OuterAcc, OuterAcc) -> OuterAcc + Sync + Send, + >( + &self, + make_inner: MakeInner, + inner_step: InnerStep, + outer_step: OuterStep, + merge: Merge, + ) -> OuterAcc { + let e_out = self.e_out_current(); + let e_in = self.e_in_current(); + + #[cfg(feature = "parallel")] + { + let result = (0..e_out.len()) + .into_par_iter() + .map(|x_out| { + let mut inner_acc = make_inner(); + for (x_in, &e_in) in e_in.iter().enumerate() { + let group = self.group_index(x_out, x_in); + inner_step(&mut inner_acc, group, x_in, e_in); + } + outer_step(x_out, e_out[x_out], inner_acc) + }) + .reduce_with(merge); + if let Some(result) = result { + result + } else { + assert!(!e_out.is_empty(), "split eq e_out invariant"); + std::process::abort(); + } + } + + #[cfg(not(feature = "parallel"))] + { + let mut iter = (0..e_out.len()).map(|x_out| { + let mut inner_acc = make_inner(); + for (x_in, &e_in) in e_in.iter().enumerate() { + let group = self.group_index(x_out, x_in); + inner_step(&mut inner_acc, group, x_in, e_in); + } + outer_step(x_out, e_out[x_out], inner_acc) + }); + let first = iter.next().expect("split eq e_out invariant"); + iter.fold(first, merge) + } + } +} + +#[cfg(feature = "parallel")] +fn join_or_serial( + left: impl FnOnce() -> A + Send, + right: impl FnOnce() -> B + Send, +) -> (A, B) { + rayon::join(left, right) +} + +#[cfg(not(feature = "parallel"))] +fn join_or_serial(left: impl FnOnce() -> A, right: impl FnOnce() -> B) -> (A, B) { + (left(), right()) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::math::Math; + use jolt_field::{Field, Fr}; + use num_traits::{One, Zero}; + use rand_chacha::ChaCha20Rng; + use rand_core::SeedableRng; + + #[test] + fn bind_low_to_high_matches_dense_eq() { + let mut rng = ChaCha20Rng::seed_from_u64(700); + let point: Vec = (0..10).map(|_| Fr::random(&mut rng)).collect(); + let mut dense = Polynomial::new(EqPolynomial::::evals(&point, None)); + let mut split = GruenSplitEqPolynomial::new(&point, BindingOrder::LowToHigh); + assert_eq!(dense, split.merge()); + + for _ in 0..point.len() { + let r = Fr::random(&mut rng); + dense.bind_with_order(r, BindingOrder::LowToHigh); + split.bind(r); + assert_eq!(dense, split.merge()); + } + } + + #[test] + fn bind_high_to_low_matches_dense_eq() { + let mut rng = ChaCha20Rng::seed_from_u64(701); + let point: Vec = (0..10).map(|_| Fr::random(&mut rng)).collect(); + let mut dense = Polynomial::new(EqPolynomial::::evals(&point, None)); + let mut split = GruenSplitEqPolynomial::new(&point, BindingOrder::HighToLow); + assert_eq!(dense, split.merge()); + + for _ in 0..point.len() { + let r = Fr::random(&mut rng); + dense.bind_with_order(r, BindingOrder::HighToLow); + split.bind(r); + assert_eq!(dense, split.merge()); + } + } + + #[test] + fn window_size_one_factors_current_head() { + let mut rng = ChaCha20Rng::seed_from_u64(702); + let point: Vec = (0..10).map(|_| Fr::random(&mut rng)).collect(); + let mut split = GruenSplitEqPolynomial::new(&point, BindingOrder::LowToHigh); + + for _round in 0..point.len() { + let num_unbound = split.current_index; + if num_unbound <= 1 { + break; + } + let (e_out, e_in) = split.e_out_in_for_window(1); + let head = EqPolynomial::::evals(&split.w[..num_unbound - 1], None); + assert_eq!(e_out.len() * e_in.len(), head.len()); + + let x_in_bits = e_in.len().log_2(); + for (x_out, &e_out) in e_out.iter().enumerate() { + for (x_in, &e_in) in e_in.iter().enumerate() { + let index = (x_out << x_in_bits) | x_in; + assert_eq!(e_out * e_in, head[index]); + } + } + + split.bind(Fr::random(&mut rng)); + } + } + + #[test] + fn gruen_degree_two_matches_direct_interpolation() { + let mut rng = ChaCha20Rng::seed_from_u64(703); + let point: Vec = (0..5).map(|_| Fr::random(&mut rng)).collect(); + let split = GruenSplitEqPolynomial::new(&point, BindingOrder::LowToHigh); + let q0 = Fr::from_u64(11); + let q1 = Fr::from_u64(29); + let l1 = split.current_scalar() * split.current_w(); + let l0 = split.current_scalar() - l1; + let previous_claim = l0 * q0 + l1 * q1; + + let poly = split.gruen_poly_deg_2(q0, previous_claim); + let q2 = q1 + q1 - q0; + let l2 = l1 + (l1 - l0); + assert_eq!(poly.evaluate(Fr::zero()), l0 * q0); + assert_eq!(poly.evaluate(Fr::one()), l1 * q1); + assert_eq!(poly.evaluate(Fr::from_u64(2)), l2 * q2); + } +} diff --git a/crates/jolt-poly/src/univariate.rs b/crates/jolt-poly/src/univariate.rs index 47cc890e80..ffccf355b5 100644 --- a/crates/jolt-poly/src/univariate.rs +++ b/crates/jolt-poly/src/univariate.rs @@ -195,8 +195,12 @@ impl UnivariatePoly { /// on the Vandermonde system. Equivalent to `interpolate_over_integers` but uses a /// direct matrix solve instead of the Lagrange formula. pub fn from_evals(evals: &[F]) -> Self { - Self { - coefficients: gaussian_elimination_vandermonde(evals), + match evals { + [e0, e1, e2] => Self::from_evals_degree2(*e0, *e1, *e2), + [e0, e1, e2, e3] => Self::from_evals_degree3(*e0, *e1, *e2, *e3), + _ => Self { + coefficients: gaussian_elimination_vandermonde(evals), + }, } } @@ -204,10 +208,16 @@ impl UnivariatePoly { /// /// Recovers `p(1) = hint - p(0)` and then interpolates over the full set `{0, 1, ..., n-1}`. pub fn from_evals_and_hint(hint: F, evals: &[F]) -> Self { - let mut full = evals.to_vec(); - let eval_at_1 = hint - full[0]; - full.insert(1, eval_at_1); - Self::from_evals(&full) + match evals { + [e0, e2] => Self::from_evals_degree2(*e0, hint - *e0, *e2), + [e0, e2, e3] => Self::from_evals_degree3(*e0, hint - *e0, *e2, *e3), + _ => { + let mut full = evals.to_vec(); + let eval_at_1 = hint - full[0]; + full.insert(1, eval_at_1); + Self::from_evals(&full) + } + } } /// Interpolates from evaluations at `[0, 1, ..., degree-1, ∞]`. @@ -252,7 +262,6 @@ impl UnivariatePoly { /// - `hint = s(0) + s(1)` /// /// Used by the split-eq evaluator to construct round polynomials. - #[expect(clippy::expect_used)] pub fn from_linear_times_quadratic_with_hint( linear_coeffs: [F; 2], quadratic_coeff_0: F, @@ -270,11 +279,8 @@ impl UnivariatePoly { !linear_eval_one.is_zero(), "linear polynomial vanishes at x=1" ); - let linear_eval_one_inv = linear_eval_one - .inverse() - .expect("nonzero linear_eval_one has an inverse"); let quadratic_coeff_1 = - (hint - cubic_coeff_0) * linear_eval_one_inv - quadratic_coeff_0 - quadratic_coeff_2; + (hint - cubic_coeff_0) / linear_eval_one - quadratic_coeff_0 - quadratic_coeff_2; // s(X) = (a + bX)(c + dX + eX^2) = ac + (ad+bc)X + (ae+bd)X^2 + beX^3 let coefficients = vec![ @@ -286,6 +292,25 @@ impl UnivariatePoly { Self { coefficients } } + fn from_evals_degree2(e0: F, e1: F, e2: F) -> Self { + let c0 = e0; + let c2 = (e0 - e1 - e1 + e2) / F::from_u64(2); + let c1 = e1 - e0 - c2; + Self { + coefficients: vec![c0, c1, c2], + } + } + + fn from_evals_degree3(e0: F, e1: F, e2: F, e3: F) -> Self { + let c0 = e0; + let c3 = (e3 - e0 + (e1 - e2) * F::from_u64(3)) / F::from_u64(6); + let c2 = (e0 - e1 - e1 + e2) / F::from_u64(2) - c3 - c3 - c3; + let c1 = e1 - e0 - c2 - c3; + Self { + coefficients: vec![c0, c1, c2, c3], + } + } + /// Returns `true` if all coefficients are zero (or the vector is empty). pub fn is_zero(&self) -> bool { self.coefficients.is_empty() || self.coefficients.iter().all(|c| *c == F::zero()) @@ -499,10 +524,7 @@ fn gaussian_elimination_augmented(matrix: &mut [Vec]) -> Vec { } for j in (i + 1)..size { - let pivot_inv = matrix[i][i] - .inverse() - .expect("nonzero pivot has an inverse"); - let factor = matrix[j][i] * pivot_inv; + let factor = matrix[j][i] / matrix[i][i]; #[expect(clippy::needless_range_loop)] for k in i..=size { let tmp = matrix[i][k]; @@ -518,10 +540,7 @@ fn gaussian_elimination_augmented(matrix: &mut [Vec]) -> Vec { "singular matrix in gaussian_elimination_augmented" ); for j in (0..i).rev() { - let pivot_inv = matrix[i][i] - .inverse() - .expect("nonzero pivot has an inverse"); - let factor = matrix[j][i] * pivot_inv; + let factor = matrix[j][i] / matrix[i][i]; for k in (0..=size).rev() { let tmp = matrix[i][k]; matrix[j][k] -= factor * tmp; @@ -531,10 +550,7 @@ fn gaussian_elimination_augmented(matrix: &mut [Vec]) -> Vec { let mut result = vec![F::zero(); size]; for i in 0..size { - let pivot_inv = matrix[i][i] - .inverse() - .expect("nonzero pivot has an inverse"); - result[i] = matrix[i][size] * pivot_inv; + result[i] = matrix[i][size] / matrix[i][i]; } result } @@ -543,8 +559,8 @@ fn gaussian_elimination_augmented(matrix: &mut [Vec]) -> Vec { #[expect(clippy::unwrap_used)] mod tests { use super::*; + use jolt_field::Field; use jolt_field::Fr; - use jolt_field::FromPrimitiveInt; use num_traits::{One, Zero}; #[test] diff --git a/crates/jolt-poly/tests/integration.rs b/crates/jolt-poly/tests/integration.rs index 5ffa348a39..bdad95ff50 100644 --- a/crates/jolt-poly/tests/integration.rs +++ b/crates/jolt-poly/tests/integration.rs @@ -5,7 +5,7 @@ //! (Polynomial, EqPolynomial, UnivariatePoly, IdentityPolynomial, RlcSource) //! that are used throughout the proving system. -use jolt_field::{Fr, FromPrimitiveInt, RandomSampling}; +use jolt_field::{Field, Fr}; use jolt_poly::{ EqPolynomial, IdentityPolynomial, MultilinearPoly, Polynomial, RlcSource, UnivariatePoly, }; diff --git a/crates/jolt-r1cs/src/constraint.rs b/crates/jolt-r1cs/src/constraint.rs index 7222b4c352..296261f035 100644 --- a/crates/jolt-r1cs/src/constraint.rs +++ b/crates/jolt-r1cs/src/constraint.rs @@ -149,7 +149,7 @@ fn dot(row: &[(usize, F)], witness: &[F]) -> F { #[cfg(test)] mod tests { use super::*; - use jolt_field::{Fr, FromPrimitiveInt}; + use jolt_field::Fr; #[test] fn satisfied_constraint() { diff --git a/crates/jolt-r1cs/src/constraints/rv64.rs b/crates/jolt-r1cs/src/constraints/rv64.rs index 33d24178c1..0bd95331ce 100644 --- a/crates/jolt-r1cs/src/constraints/rv64.rs +++ b/crates/jolt-r1cs/src/constraints/rv64.rs @@ -388,7 +388,7 @@ pub fn rv64_constraints() -> crate::ConstraintMatrices { #[expect(clippy::expect_used, reason = "tests may unwind via panic")] mod tests { use super::*; - use jolt_field::{Fr, FromPrimitiveInt}; + use jolt_field::Fr; use num_traits::Zero; /// A no-op cycle: const=1, all else zero. All eq-conditional guards diff --git a/crates/jolt-r1cs/src/key.rs b/crates/jolt-r1cs/src/key.rs index 767199a9ef..b25625c2ba 100644 --- a/crates/jolt-r1cs/src/key.rs +++ b/crates/jolt-r1cs/src/key.rs @@ -280,7 +280,7 @@ impl R1csKey { mod tests { use super::*; use crate::constraint::ConstraintMatrices; - use jolt_field::{Fr, FromPrimitiveInt, RandomSampling}; + use jolt_field::{Field, Fr}; use num_traits::{One, Zero}; /// x * x = y, y * x = z — 2 constraints, 4 vars [1, x, y, z] diff --git a/crates/jolt-r1cs/src/lib.rs b/crates/jolt-r1cs/src/lib.rs index 62f0f4176d..64131de158 100644 --- a/crates/jolt-r1cs/src/lib.rs +++ b/crates/jolt-r1cs/src/lib.rs @@ -13,8 +13,10 @@ pub mod constraint; pub mod constraints; pub mod key; pub mod provider; +pub mod row_dots; pub use column::R1csColumn; pub use constraint::ConstraintMatrices; pub use key::R1csKey; pub use provider::{R1csSource, SpartanChallenges}; +pub use row_dots::{R1csRowDotSlice, R1csRowDotTable}; diff --git a/crates/jolt-r1cs/src/provider.rs b/crates/jolt-r1cs/src/provider.rs index 79f52c9509..1fa2ea7910 100644 --- a/crates/jolt-r1cs/src/provider.rs +++ b/crates/jolt-r1cs/src/provider.rs @@ -147,7 +147,7 @@ impl<'a, F: Field> R1csSource<'a, F> { mod tests { use super::*; use crate::constraint::ConstraintMatrices; - use jolt_field::{Fr, FromPrimitiveInt}; + use jolt_field::{Field, Fr}; use num_traits::{One, Zero}; #[test] diff --git a/crates/jolt-r1cs/src/row_dots.rs b/crates/jolt-r1cs/src/row_dots.rs new file mode 100644 index 0000000000..11a040a10b --- /dev/null +++ b/crates/jolt-r1cs/src/row_dots.rs @@ -0,0 +1,118 @@ +use jolt_field::Field; + +use crate::R1csKey; + +#[cfg(feature = "parallel")] +use rayon::prelude::*; + +#[derive(Clone, Debug)] +pub struct R1csRowDotTable { + row_count: usize, + cycle_count: usize, + a: Vec, + b: Vec, +} + +#[derive(Clone, Copy, Debug)] +pub struct R1csRowDotSlice<'a, F: Field> { + pub a: &'a [F], + pub b: &'a [F], +} + +impl R1csRowDotTable { + #[tracing::instrument(skip_all, name = "R1csRowDotTable::compute_ab_prefix")] + pub fn compute_ab_prefix(key: &R1csKey, witness: &[F], row_count: usize) -> Self { + assert!( + row_count <= key.matrices.num_constraints, + "row_count exceeds R1CS constraint count" + ); + let expected = key.num_cycles * key.num_vars_padded; + assert_eq!( + witness.len(), + expected, + "R1CS witness length does not match key shape" + ); + + let total = key.num_cycles * row_count; + let mut a = vec![F::zero(); total]; + let mut b = vec![F::zero(); total]; + compute_row_dots(key, witness, row_count, &mut a, &mut b); + + Self { + row_count, + cycle_count: key.num_cycles, + a, + b, + } + } + + #[inline] + pub fn row_count(&self) -> usize { + self.row_count + } + + #[inline] + pub fn cycle_count(&self) -> usize { + self.cycle_count + } + + #[inline] + pub fn cycle(&self, cycle: usize) -> R1csRowDotSlice<'_, F> { + assert!(cycle < self.cycle_count, "cycle index out of bounds"); + let start = cycle * self.row_count; + let end = start + self.row_count; + R1csRowDotSlice { + a: &self.a[start..end], + b: &self.b[start..end], + } + } +} + +#[cfg(feature = "parallel")] +fn compute_row_dots( + key: &R1csKey, + witness: &[F], + row_count: usize, + a: &mut [F], + b: &mut [F], +) { + a.par_chunks_mut(row_count) + .zip(b.par_chunks_mut(row_count)) + .enumerate() + .for_each(|(cycle, (a_chunk, b_chunk))| { + let start = cycle * key.num_vars_padded; + let witness_row = &witness[start..start + key.matrices.num_vars]; + for row in 0..row_count { + a_chunk[row] = row_dot(&key.matrices.a[row], witness_row); + b_chunk[row] = row_dot(&key.matrices.b[row], witness_row); + } + }); +} + +#[cfg(not(feature = "parallel"))] +fn compute_row_dots( + key: &R1csKey, + witness: &[F], + row_count: usize, + a: &mut [F], + b: &mut [F], +) { + for cycle in 0..key.num_cycles { + let witness_start = cycle * key.num_vars_padded; + let row_start = cycle * row_count; + let witness_row = &witness[witness_start..witness_start + key.matrices.num_vars]; + for row in 0..row_count { + a[row_start + row] = row_dot(&key.matrices.a[row], witness_row); + b[row_start + row] = row_dot(&key.matrices.b[row], witness_row); + } + } +} + +#[inline] +fn row_dot(row: &[(usize, F)], witness: &[F]) -> F { + let mut acc = F::zero(); + for &(variable, coefficient) in row { + acc += coefficient * witness[variable]; + } + acc +} diff --git a/crates/jolt-riscv/src/lib.rs b/crates/jolt-riscv/src/lib.rs index 5ee9a433d0..988cf8f7aa 100644 --- a/crates/jolt-riscv/src/lib.rs +++ b/crates/jolt-riscv/src/lib.rs @@ -51,13 +51,12 @@ macro_rules! jolt_instruction { fn circuit_flags(&self) -> $crate::CircuitFlagSet { let mut flags = $crate::CircuitFlagSet::default() $(.set($crate::CircuitFlags::$circuit))*; - if let Some(virtual_sequence_remaining) = self.0.virtual_sequence_remaining() { + let virtual_sequence_remaining = self.0.virtual_sequence_remaining(); + if virtual_sequence_remaining.is_some() { flags = flags.set($crate::CircuitFlags::VirtualInstruction); - if virtual_sequence_remaining == 0 { - flags = flags.set($crate::CircuitFlags::IsLastInSequence); - } + $crate::jolt_instruction!(@set_is_last_in_sequence flags, $name, virtual_sequence_remaining); } - if self.0.virtual_sequence_remaining().unwrap_or(0) != 0 { + if virtual_sequence_remaining.unwrap_or(0) != 0 { flags = flags.set($crate::CircuitFlags::DoNotUpdateUnexpandedPC); } if self.0.is_compressed() { @@ -89,13 +88,12 @@ macro_rules! jolt_instruction { #[inline] fn circuit_flags(&self) -> $crate::CircuitFlagSet { let mut flags = $crate::CircuitFlagSet::default(); - if let Some(virtual_sequence_remaining) = self.0.virtual_sequence_remaining() { + let virtual_sequence_remaining = self.0.virtual_sequence_remaining(); + if virtual_sequence_remaining.is_some() { flags = flags.set($crate::CircuitFlags::VirtualInstruction); - if virtual_sequence_remaining == 0 { - flags = flags.set($crate::CircuitFlags::IsLastInSequence); - } + $crate::jolt_instruction!(@set_is_last_in_sequence flags, $name, virtual_sequence_remaining); } - if self.0.virtual_sequence_remaining().unwrap_or(0) != 0 { + if virtual_sequence_remaining.unwrap_or(0) != 0 { flags = flags.set($crate::CircuitFlags::DoNotUpdateUnexpandedPC); } if self.0.is_compressed() { @@ -133,6 +131,14 @@ macro_rules! jolt_instruction { pub struct $name(pub T); }; + (@set_is_last_in_sequence $flags:ident, Jalr, $virtual_sequence_remaining:expr) => { + if $virtual_sequence_remaining == Some(0) { + $flags = $flags.set($crate::CircuitFlags::IsLastInSequence); + } + }; + + (@set_is_last_in_sequence $flags:ident, $name:ident, $virtual_sequence_remaining:expr) => {}; + // Internal: emit `JoltInstruction` for `$name` whenever `T` is itself a // `RISCVInstruction`. Lets call sites treat the wrapper newtype as a Jolt // instruction directly without unwrapping `self.0`. diff --git a/crates/jolt-sumcheck/Cargo.toml b/crates/jolt-sumcheck/Cargo.toml index ff40a99d36..f790381acd 100644 --- a/crates/jolt-sumcheck/Cargo.toml +++ b/crates/jolt-sumcheck/Cargo.toml @@ -15,7 +15,3 @@ jolt-transcript.workspace = true serde = { workspace = true, features = ["derive"] } tracing.workspace = true thiserror.workspace = true - -[dev-dependencies] -num-traits = { workspace = true } -rand_core = { workspace = true } diff --git a/crates/jolt-sumcheck/src/batched.rs b/crates/jolt-sumcheck/src/batched.rs new file mode 100644 index 0000000000..f37b5d9397 --- /dev/null +++ b/crates/jolt-sumcheck/src/batched.rs @@ -0,0 +1,81 @@ +//! Batched sumcheck verification: reduces multiple claims into one via random +//! linear combination. +//! +//! Supports claims with **different** `num_vars` and `degree` bounds via +//! front-loaded batching: shorter instances are active only in the last +//! `num_vars` rounds and are padded with constant dummy polynomials in +//! earlier rounds. Each claim is scaled by $2^{N - n_i}$ where $N$ is the +//! maximum `num_vars` across all claims. + +use jolt_field::Field; +use jolt_transcript::{AppendToTranscript, Transcript}; + +use crate::claim::SumcheckClaim; +use crate::error::SumcheckError; +use crate::round::RoundVerifier; + +/// Batched sumcheck verifier. +/// +/// Recomputes the combined claim with the same scaling and batching +/// coefficients as the prover, then delegates to the single-instance +/// verifier. +pub struct BatchedSumcheckVerifier; + +impl BatchedSumcheckVerifier { + /// Verifies a batched sumcheck proof with a pluggable round verifier. + /// + /// Returns `(v, r)` on success, where `v` is the combined final + /// evaluation and `r` is the full challenge vector of length + /// `max(num_vars)`. + /// + /// # Errors + /// + /// Returns [`SumcheckError`] if verification fails. + #[tracing::instrument(skip_all, name = "BatchedSumcheckVerifier::verify")] + pub fn verify( + claims: &[SumcheckClaim], + round_proofs: &[V::RoundProof], + transcript: &mut T, + verifier: &V, + ) -> Result<(F, Vec), SumcheckError> + where + F: Field, + T: Transcript, + V: RoundVerifier, + { + if claims.is_empty() { + return Err(SumcheckError::EmptyClaims); + } + + let max_num_vars = claims.iter().map(|c| c.num_vars).max().unwrap(); + let max_degree = claims.iter().map(|c| c.degree).max().unwrap(); + + // Fiat-Shamir: absorb claimed sums (must match prover). + for claim in claims { + claim.claimed_sum.append_to_transcript(transcript); + } + + let alpha: F = transcript.challenge(); + + let combined_sum: F = claims + .iter() + .enumerate() + .fold(F::zero(), |acc, (j, claim)| { + let scaled = claim.claimed_sum.mul_pow_2(max_num_vars - claim.num_vars); + acc + alpha.pow(j) * scaled + }); + + let combined_claim = SumcheckClaim { + num_vars: max_num_vars, + degree: max_degree, + claimed_sum: combined_sum, + }; + + crate::verifier::SumcheckVerifier::verify( + &combined_claim, + round_proofs, + transcript, + verifier, + ) + } +} diff --git a/crates/jolt-sumcheck/src/batched_verifier.rs b/crates/jolt-sumcheck/src/batched_verifier.rs index 984c9afdb2..9f6f0b043b 100644 --- a/crates/jolt-sumcheck/src/batched_verifier.rs +++ b/crates/jolt-sumcheck/src/batched_verifier.rs @@ -7,12 +7,12 @@ //! earlier rounds. Each claim is scaled by $2^{N - n_i}$ where $N$ is the //! maximum `num_vars` across all claims. +use jolt_field::Field; use jolt_transcript::{AppendToTranscript, Transcript}; use crate::claim::{EvaluationClaim, SumcheckClaim}; use crate::error::SumcheckError; use crate::round_proof::RoundProof; -use crate::scalar::SumcheckScalar; /// Batched sumcheck verifier. /// @@ -38,7 +38,7 @@ impl BatchedSumcheckVerifier { transcript: &mut T, ) -> Result, SumcheckError> where - F: SumcheckScalar, + F: Field, T: Transcript, P: RoundProof, { diff --git a/crates/jolt-sumcheck/src/claim.rs b/crates/jolt-sumcheck/src/claim.rs index 64d910f70a..83ea885de3 100644 --- a/crates/jolt-sumcheck/src/claim.rs +++ b/crates/jolt-sumcheck/src/claim.rs @@ -1,7 +1,6 @@ //! Sumcheck claim: the public statement that the protocol proves. -use jolt_field::FieldCore; - +use jolt_field::Field; /// A sumcheck claim asserting that /// $\sum_{x \in \{0,1\}^n} g(x) = C$ /// where $g$ is a polynomial of individual degree at most `degree` in each variable. @@ -13,7 +12,7 @@ use jolt_field::FieldCore; /// For a product of $k$ multilinear polynomials, `degree = k`. /// * `claimed_sum` -- the value $C$ that the prover claims the sum equals. #[derive(Clone, Debug)] -pub struct SumcheckClaim { +pub struct SumcheckClaim { /// Number of Boolean variables in the summation. pub num_vars: usize, /// Maximum degree of each round polynomial. @@ -22,7 +21,7 @@ pub struct SumcheckClaim { pub claimed_sum: F, } -impl SumcheckClaim { +impl SumcheckClaim { /// Construct a sumcheck claim. /// /// # Panics @@ -50,7 +49,7 @@ impl SumcheckClaim { /// BlindFold, etc.) to retain soundness — sumcheck alone does not /// verify `v` against any commitment. #[derive(Clone, Debug, PartialEq, Eq)] -pub struct EvaluationClaim { +pub struct EvaluationClaim { /// Challenge point `r = (r_1, ..., r_n)`. pub point: Vec, /// Claimed evaluation `g(r) = v`. diff --git a/crates/jolt-sumcheck/src/clear.rs b/crates/jolt-sumcheck/src/clear.rs new file mode 100644 index 0000000000..6bc19e9b30 --- /dev/null +++ b/crates/jolt-sumcheck/src/clear.rs @@ -0,0 +1,118 @@ +//! Helpers for cleartext sumcheck verifier calls. + +use jolt_field::Field; +use jolt_transcript::Transcript; + +use crate::{ClearRoundVerifier, SumcheckClaim, SumcheckError, SumcheckProof, SumcheckVerifier}; + +/// Wire encoding used for cleartext round polynomial transcript absorption. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum ClearRoundEncoding { + /// Absorb every round-polynomial coefficient. + Full, + /// Absorb every coefficient except the recoverable linear term. + Compressed, +} + +/// Static verifier plan for one cleartext sumcheck instance. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct ClearSumcheckPlan { + /// Number of Boolean variables in the sumcheck claim. + pub num_vars: usize, + /// Maximum allowed degree for each round polynomial. + pub degree: usize, + /// Domain-separation label absorbed before each round polynomial. + pub round_label: &'static [u8], + /// Transcript wire encoding for each round polynomial. + pub round_encoding: ClearRoundEncoding, +} + +/// Successful cleartext sumcheck verification output. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct ClearSumcheckOutput { + /// Final reduced evaluation claim. + pub final_eval: F, + /// Fiat-Shamir challenge point produced by verification. + pub point: Vec, +} + +impl ClearSumcheckPlan { + /// Verifies a cleartext sumcheck proof and returns its reduced evaluation claim. + pub fn verify( + &self, + claimed_sum: F, + proof: &SumcheckProof, + transcript: &mut T, + ) -> Result, SumcheckError> + where + F: Field, + T: Transcript, + { + let claim = SumcheckClaim { + num_vars: self.num_vars, + degree: self.degree, + claimed_sum, + }; + let verifier = match self.round_encoding { + ClearRoundEncoding::Full => ClearRoundVerifier::with_label(self.round_label), + ClearRoundEncoding::Compressed => { + ClearRoundVerifier::with_label_compressed(self.round_label) + } + }; + let (final_eval, point) = + SumcheckVerifier::verify(&claim, &proof.round_polynomials, transcript, &verifier)?; + Ok(ClearSumcheckOutput { final_eval, point }) + } +} + +#[cfg(test)] +mod tests { + use jolt_field::{Field, Fr}; + use jolt_poly::UnivariatePoly; + use jolt_transcript::Blake2bTranscript; + + use super::*; + + #[test] + fn verifies_labeled_full_rounds() { + let proof = SumcheckProof { + round_polynomials: vec![UnivariatePoly::new(vec![Fr::from_u64(1), Fr::from_u64(1)])], + }; + let plan = ClearSumcheckPlan { + num_vars: 1, + degree: 1, + round_label: b"round", + round_encoding: ClearRoundEncoding::Full, + }; + let mut transcript = Blake2bTranscript::::new(b"test"); + + let output = plan + .verify(Fr::from_u64(3), &proof, &mut transcript) + .expect("valid proof"); + + assert_eq!(output.point.len(), 1); + assert_eq!( + output.final_eval, + proof.round_polynomials[0].evaluate(output.point[0]) + ); + } + + #[test] + fn verifies_labeled_compressed_rounds() { + let proof = SumcheckProof { + round_polynomials: vec![UnivariatePoly::new(vec![Fr::from_u64(1), Fr::from_u64(1)])], + }; + let plan = ClearSumcheckPlan { + num_vars: 1, + degree: 1, + round_label: b"round", + round_encoding: ClearRoundEncoding::Compressed, + }; + let mut transcript = Blake2bTranscript::::new(b"test"); + + let output = plan + .verify(Fr::from_u64(3), &proof, &mut transcript) + .expect("valid compressed proof"); + assert_eq!(output.point.len(), 1); + } +} diff --git a/crates/jolt-sumcheck/src/error.rs b/crates/jolt-sumcheck/src/error.rs index 6a17f358bf..2cad6982c0 100644 --- a/crates/jolt-sumcheck/src/error.rs +++ b/crates/jolt-sumcheck/src/error.rs @@ -1,6 +1,6 @@ //! Error types for sumcheck protocol verification failures. -use jolt_field::FieldCore; +use jolt_field::Field; /// Errors that can occur during sumcheck verification. /// @@ -9,7 +9,7 @@ use jolt_field::FieldCore; /// diverged. #[derive(Debug, thiserror::Error)] #[non_exhaustive] -pub enum SumcheckError { +pub enum SumcheckError { /// Round check failed: the sum $s_i(0) + s_i(1)$ did not match the /// expected value carried forward from the previous round. #[error("round {round}: expected sum {expected}, got {actual}")] diff --git a/crates/jolt-sumcheck/src/lib.rs b/crates/jolt-sumcheck/src/lib.rs index a37124ee2f..b71fd2d471 100644 --- a/crates/jolt-sumcheck/src/lib.rs +++ b/crates/jolt-sumcheck/src/lib.rs @@ -1,9 +1,9 @@ //! Sumcheck protocol: claims, proofs, and verification. //! //! Verifier-side types and logic for the sumcheck protocol, used by the Jolt -//! zkVM. This crate is **verifier-only** and **backend-agnostic**: any field and -//! transcript can be plugged in. Proving is handled by `jolt-zkvm`'s runtime, -//! which drives sumcheck rounds via `ComputeBackend` primitives. +//! zkVM. This crate is **verifier-side** and **backend-agnostic**: any field and +//! transcript can be plugged in. Prover-side code drives sumcheck rounds and +//! emits proof data that these verifier primitives check. //! //! # Protocol overview //! @@ -65,7 +65,6 @@ pub mod claim; pub mod error; pub mod proof; pub mod round_proof; -pub mod scalar; pub mod verifier; #[cfg(test)] @@ -76,5 +75,4 @@ pub use claim::{EvaluationClaim, SumcheckClaim}; pub use error::SumcheckError; pub use proof::SumcheckProof; pub use round_proof::{CompressedLabeledRoundPoly, LabeledRoundPoly, RoundProof}; -pub use scalar::SumcheckScalar; pub use verifier::SumcheckVerifier; diff --git a/crates/jolt-sumcheck/src/proof.rs b/crates/jolt-sumcheck/src/proof.rs index bff701c267..ff0b91724d 100644 --- a/crates/jolt-sumcheck/src/proof.rs +++ b/crates/jolt-sumcheck/src/proof.rs @@ -1,5 +1,6 @@ //! Proof structures for single and batched sumcheck protocols. +use jolt_field::Field; use jolt_poly::UnivariatePoly; use serde::{Deserialize, Serialize}; @@ -15,7 +16,7 @@ use serde::{Deserialize, Serialize}; /// $(r_1, \ldots, r_n)$. #[derive(Clone, Debug, Default, Serialize, Deserialize)] #[serde(bound = "")] -pub struct SumcheckProof { +pub struct SumcheckProof { /// Round polynomials $s_1, \ldots, s_n$ in the order they were generated. pub round_polynomials: Vec>, } diff --git a/crates/jolt-sumcheck/src/round.rs b/crates/jolt-sumcheck/src/round.rs new file mode 100644 index 0000000000..666c05bd9b --- /dev/null +++ b/crates/jolt-sumcheck/src/round.rs @@ -0,0 +1,143 @@ +//! Strategy trait for sumcheck round polynomial verification. +//! +//! [`RoundVerifier`] defines how round polynomials are verified against the +//! Fiat-Shamir transcript: +//! +//! - **Clear mode** ([`ClearRoundVerifier`]): polynomial coefficients are +//! checked directly — `poly(0) + poly(1) == running_sum`. +//! - **Committed mode** (future, in `jolt-blindfold`): polynomial commitments +//! are absorbed into the transcript; consistency is verified via BlindFold. + +use jolt_field::Field; +use jolt_poly::{UnivariatePoly, UnivariatePolynomial}; +use jolt_transcript::{AppendToTranscript, LabelWithCount, Transcript}; + +use crate::error::SumcheckError; + +/// Strategy for how the verifier processes per-round proof data. +/// +/// Verification proceeds in two phases per round: +/// 1. [`absorb_and_check`](Self::absorb_and_check) — absorb round data into +/// the transcript, optionally verify consistency (clear mode checks +/// `poly(0) + poly(1) == running_sum`; committed mode skips this). +/// 2. [`next_running_sum`](Self::next_running_sum) — compute the next running +/// sum using the derived challenge (clear mode evaluates the polynomial; +/// committed mode returns zero since BlindFold verifies later). +pub trait RoundVerifier { + /// Per-round proof data (`UnivariatePoly` for clear, commitment for ZK). + type RoundProof; + + /// Absorb round data into the transcript and verify consistency. + /// + /// Called BEFORE challenge derivation. The implementation must append + /// the same bytes to the transcript as the prover appended, to maintain + /// Fiat-Shamir synchronization. + fn absorb_and_check( + &self, + proof: &Self::RoundProof, + running_sum: F, + degree_bound: usize, + round: usize, + transcript: &mut impl Transcript, + ) -> Result<(), SumcheckError>; + + /// Compute the next running sum given the Fiat-Shamir challenge. + /// + /// Called AFTER challenge derivation. + fn next_running_sum(&self, proof: &Self::RoundProof, challenge: F) -> F; +} + +/// Cleartext verifier: checks polynomial consistency and evaluates. +/// +/// When `label` is `Some`, a [`LabelWithCount`] word is absorbed before +/// each round's coefficients. +/// +/// When `compressed` is `true`, the linear term `c1` is omitted from +/// transcript absorption (matching the prover's compressed wire format: +/// `c1` is recoverable from `running_sum - c0`). The label count then +/// uses `coeffs.len() - 1`. +#[derive(Default)] +pub struct ClearRoundVerifier { + label: Option<&'static [u8]>, + compressed: bool, +} + +impl ClearRoundVerifier { + /// Verifier with no domain-separation labels (raw coefficient absorption). + pub fn new() -> Self { + Self::default() + } + + /// Verifier that prepends a `LabelWithCount` word before each round's coefficients. + pub fn with_label(label: &'static [u8]) -> Self { + Self { + label: Some(label), + compressed: false, + } + } + + /// Verifier that absorbs the compressed form (omits linear term `c1`). + /// Matches the prover's `RoundPolyEncoding::Compressed` wire format. + pub fn with_label_compressed(label: &'static [u8]) -> Self { + Self { + label: Some(label), + compressed: true, + } + } +} + +impl RoundVerifier for ClearRoundVerifier { + type RoundProof = UnivariatePoly; + + fn absorb_and_check( + &self, + proof: &UnivariatePoly, + running_sum: F, + degree_bound: usize, + round: usize, + transcript: &mut impl Transcript, + ) -> Result<(), SumcheckError> { + if proof.degree() > degree_bound { + return Err(SumcheckError::DegreeBoundExceeded { + got: proof.degree(), + max: degree_bound, + }); + } + + let sum = proof.evaluate(F::zero()) + proof.evaluate(F::one()); + if sum != running_sum { + return Err(SumcheckError::RoundCheckFailed { + round, + expected: format!("{running_sum}"), + actual: format!("{sum}"), + }); + } + + let coeffs = proof.coefficients(); + if self.compressed { + let compressed_len = coeffs.len().saturating_sub(1); + if let Some(label) = self.label { + transcript.append(&LabelWithCount(label, compressed_len as u64)); + } + if let Some(c0) = coeffs.first() { + c0.append_to_transcript(transcript); + } + for c in coeffs.iter().skip(2) { + c.append_to_transcript(transcript); + } + } else { + if let Some(label) = self.label { + transcript.append(&LabelWithCount(label, coeffs.len() as u64)); + } + for coeff in coeffs { + coeff.append_to_transcript(transcript); + } + } + + Ok(()) + } + + fn next_running_sum(&self, proof: &UnivariatePoly, challenge: F) -> F { + proof.evaluate(challenge) + } +} diff --git a/crates/jolt-sumcheck/src/round_proof.rs b/crates/jolt-sumcheck/src/round_proof.rs index 54c592119a..013839a57f 100644 --- a/crates/jolt-sumcheck/src/round_proof.rs +++ b/crates/jolt-sumcheck/src/round_proof.rs @@ -11,7 +11,6 @@ use jolt_poly::{UnivariatePoly, UnivariatePolynomial}; use jolt_transcript::{AppendToTranscript, LabelWithCount, Transcript}; use crate::error::SumcheckError; -use crate::scalar::SumcheckScalar; /// Per-round proof operations used by the sumcheck verifier. /// @@ -20,7 +19,7 @@ use crate::scalar::SumcheckScalar; /// transcript labelling and compression choices. The single verifier loop /// in [`crate::SumcheckVerifier::verify`] drives any impl uniformly; future /// ZK support is a new impl, not a new strategy trait. -pub trait RoundProof { +pub trait RoundProof { /// Degree of this round polynomial (for the degree-bound check). fn degree(&self) -> usize; diff --git a/crates/jolt-sumcheck/src/scalar.rs b/crates/jolt-sumcheck/src/scalar.rs deleted file mode 100644 index 761a833ffe..0000000000 --- a/crates/jolt-sumcheck/src/scalar.rs +++ /dev/null @@ -1,47 +0,0 @@ -use std::{ - fmt::{Debug, Display}, - hash::Hash, -}; - -use jolt_field::{ - CanonicalBytes, FieldCore, FixedByteSize, FromPrimitiveInt, MulPow2, TranscriptChallenge, -}; - -/// Scalar capabilities used by the verifier-side sumcheck crate. -pub trait SumcheckScalar: - FieldCore - + FromPrimitiveInt - + MulPow2 - + CanonicalBytes - + FixedByteSize - + TranscriptChallenge - + Copy - + Default - + Eq - + Debug - + Display - + Hash - + Send - + Sync - + 'static -{ -} - -impl SumcheckScalar for F where - F: FieldCore - + FromPrimitiveInt - + MulPow2 - + CanonicalBytes - + FixedByteSize - + TranscriptChallenge - + Copy - + Default - + Eq - + Debug - + Display - + Hash - + Send - + Sync - + 'static -{ -} diff --git a/crates/jolt-sumcheck/src/tests.rs b/crates/jolt-sumcheck/src/tests.rs index b3cce06f73..1666917ab2 100644 --- a/crates/jolt-sumcheck/src/tests.rs +++ b/crates/jolt-sumcheck/src/tests.rs @@ -6,7 +6,7 @@ reason = "tests may panic on assertion failures" )] -use jolt_field::{Fr, FromPrimitiveInt}; +use jolt_field::{Field, Fr}; use jolt_poly::UnivariatePoly; use jolt_transcript::{AppendToTranscript, Blake2bTranscript, LabelWithCount, Transcript}; diff --git a/crates/jolt-sumcheck/src/verifier.rs b/crates/jolt-sumcheck/src/verifier.rs index ae5a1bb3d5..3ab12e01be 100644 --- a/crates/jolt-sumcheck/src/verifier.rs +++ b/crates/jolt-sumcheck/src/verifier.rs @@ -1,11 +1,11 @@ //! Sumcheck verifier: checks round polynomials against the claimed sum. +use jolt_field::Field; use jolt_transcript::Transcript; use crate::claim::{EvaluationClaim, SumcheckClaim}; use crate::error::SumcheckError; use crate::round_proof::RoundProof; -use crate::scalar::SumcheckScalar; /// Stateless sumcheck verifier engine. /// @@ -50,7 +50,7 @@ impl SumcheckVerifier { transcript: &mut T, ) -> Result, SumcheckError> where - F: SumcheckScalar, + F: Field, T: Transcript, P: RoundProof, { diff --git a/crates/jolt-sumcheck/tests/mersenne61_compat.rs b/crates/jolt-sumcheck/tests/mersenne61_compat.rs deleted file mode 100644 index 4a3142f934..0000000000 --- a/crates/jolt-sumcheck/tests/mersenne61_compat.rs +++ /dev/null @@ -1,377 +0,0 @@ -#![expect(clippy::unwrap_used, reason = "tests may panic on assertion failures")] - -//! Compatibility test for non-BN254 sumcheck verifier plumbing. -//! -//! `Mersenne61` is intentionally small and exists here only to prove that the -//! transcript and verifier APIs no longer depend on BN254-specific helper -//! surface. It is not a production proving field. Real sumcheck soundness with -//! this base field would require an adequately large extension field. - -use std::{ - fmt::{Debug, Display}, - hash::Hash, - iter::{Product, Sum}, - ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}, -}; - -use jolt_field::{ - AdditiveGroup, CanonicalBitLength, CanonicalBytes, CanonicalU64, FieldCore, FixedByteSize, - FixedBytes, FromPrimitiveInt, Invertible, MulPow2, MulPrimitiveInt, NaiveAccumulator, - RandomSampling, ReducingBytes, RingCore, TranscriptChallenge, WithAccumulator, -}; -use jolt_sumcheck::{EvaluationClaim, RoundProof, SumcheckClaim, SumcheckError, SumcheckVerifier}; -use jolt_transcript::{AppendToTranscript, Blake2bTranscript, KeccakTranscript, Transcript}; -use num_traits::{One, Zero}; - -const MODULUS: u64 = (1u64 << 61) - 1; - -#[derive(Clone, Copy, Default, PartialEq, Eq, Hash)] -struct Mersenne61(u64); - -impl Mersenne61 { - fn reduce_u128(x: u128) -> Self { - let p = MODULUS as u128; - let mut y = (x & p) + (x >> 61); - y = (y & p) + (y >> 61); - if y >= p { - y -= p; - } - Self(y as u64) - } - - fn pow(self, mut exp: u64) -> Self { - let mut base = self; - let mut acc = Self::one(); - while exp > 0 { - if exp & 1 == 1 { - acc *= base; - } - base *= base; - exp >>= 1; - } - acc - } -} - -impl Debug for Mersenne61 { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - Debug::fmt(&self.0, f) - } -} - -impl Display for Mersenne61 { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - Display::fmt(&self.0, f) - } -} - -impl Zero for Mersenne61 { - fn zero() -> Self { - Self(0) - } - - fn is_zero(&self) -> bool { - self.0 == 0 - } -} - -impl One for Mersenne61 { - fn one() -> Self { - Self(1) - } - - fn is_one(&self) -> bool { - self.0 == 1 - } -} - -impl Add for Mersenne61 { - type Output = Self; - - fn add(self, rhs: Self) -> Self::Output { - let mut sum = self.0 + rhs.0; - if sum >= MODULUS { - sum -= MODULUS; - } - Self(sum) - } -} - -impl Add<&Self> for Mersenne61 { - type Output = Self; - - fn add(self, rhs: &Self) -> Self::Output { - self + *rhs - } -} - -impl AddAssign for Mersenne61 { - fn add_assign(&mut self, rhs: Self) { - *self = *self + rhs; - } -} - -impl Sub for Mersenne61 { - type Output = Self; - - fn sub(self, rhs: Self) -> Self::Output { - if self.0 >= rhs.0 { - Self(self.0 - rhs.0) - } else { - Self(MODULUS - (rhs.0 - self.0)) - } - } -} - -impl Sub<&Self> for Mersenne61 { - type Output = Self; - - fn sub(self, rhs: &Self) -> Self::Output { - self - *rhs - } -} - -impl SubAssign for Mersenne61 { - fn sub_assign(&mut self, rhs: Self) { - *self = *self - rhs; - } -} - -impl Neg for Mersenne61 { - type Output = Self; - - fn neg(self) -> Self::Output { - if self.is_zero() { - self - } else { - Self(MODULUS - self.0) - } - } -} - -impl Mul for Mersenne61 { - type Output = Self; - - fn mul(self, rhs: Self) -> Self::Output { - Self::reduce_u128(self.0 as u128 * rhs.0 as u128) - } -} - -impl Mul<&Self> for Mersenne61 { - type Output = Self; - - fn mul(self, rhs: &Self) -> Self::Output { - self * *rhs - } -} - -impl MulAssign for Mersenne61 { - fn mul_assign(&mut self, rhs: Self) { - *self = *self * rhs; - } -} - -impl Sum for Mersenne61 { - fn sum>(iter: I) -> Self { - iter.fold(Self::zero(), |acc, x| acc + x) - } -} - -impl<'a> Sum<&'a Mersenne61> for Mersenne61 { - fn sum>(iter: I) -> Self { - iter.copied().sum() - } -} - -impl Product for Mersenne61 { - fn product>(iter: I) -> Self { - iter.fold(Self::one(), |acc, x| acc * x) - } -} - -impl<'a> Product<&'a Mersenne61> for Mersenne61 { - fn product>(iter: I) -> Self { - iter.copied().product() - } -} - -impl AdditiveGroup for Mersenne61 {} -impl RingCore for Mersenne61 {} - -impl Invertible for Mersenne61 { - fn inverse(&self) -> Option { - if self.is_zero() { - None - } else { - Some(self.pow(MODULUS - 2)) - } - } -} - -impl FieldCore for Mersenne61 {} - -impl FromPrimitiveInt for Mersenne61 { - fn from_u64(v: u64) -> Self { - Self::reduce_u128(v as u128) - } - - fn from_i64(v: i64) -> Self { - if v >= 0 { - Self::from_u64(v as u64) - } else { - -Self::from_u64(v.unsigned_abs()) - } - } - - fn from_u128(v: u128) -> Self { - Self::reduce_u128(v) - } - - fn from_i128(v: i128) -> Self { - if v >= 0 { - Self::from_u128(v as u128) - } else { - -Self::from_u128(v.unsigned_abs()) - } - } -} - -impl RandomSampling for Mersenne61 { - fn random(rng: &mut R) -> Self { - Self::from_u64(rng.next_u64()) - } -} - -impl CanonicalBytes for Mersenne61 { - fn to_bytes_le(&self, out: &mut [u8]) { - assert_eq!(out.len(), 8); - out.copy_from_slice(&self.0.to_le_bytes()); - } -} - -impl ReducingBytes for Mersenne61 { - fn from_le_bytes_mod_order(bytes: &[u8]) -> Self { - let mut buf = [0u8; 16]; - let len = bytes.len().min(16); - buf[..len].copy_from_slice(&bytes[..len]); - Self::from_u128(u128::from_le_bytes(buf)) - } -} - -impl TranscriptChallenge for Mersenne61 { - fn from_challenge_bytes(bytes: &[u8]) -> Self { - Self::from_le_bytes_mod_order(bytes) - } -} - -impl FixedByteSize for Mersenne61 { - const NUM_BYTES: usize = 8; -} - -impl FixedBytes<8> for Mersenne61 {} - -impl CanonicalBitLength for Mersenne61 { - fn num_bits(&self) -> u32 { - u64::BITS - self.0.leading_zeros() - } -} - -impl CanonicalU64 for Mersenne61 { - fn to_canonical_u64_checked(&self) -> Option { - Some(self.0) - } -} - -impl WithAccumulator for Mersenne61 { - type Accumulator = NaiveAccumulator; -} - -impl MulPow2 for Mersenne61 {} -impl MulPrimitiveInt for Mersenne61 {} - -#[derive(Clone, Debug)] -struct LinearRound { - coeffs: [Mersenne61; 2], -} - -impl RoundProof for LinearRound { - fn degree(&self) -> usize { - 1 - } - - fn check_sum( - &self, - running_sum: Mersenne61, - round: usize, - ) -> Result<(), SumcheckError> { - let actual = self.evaluate(Mersenne61::zero()) + self.evaluate(Mersenne61::one()); - if actual == running_sum { - Ok(()) - } else { - Err(SumcheckError::RoundCheckFailed { - round, - expected: running_sum, - actual, - }) - } - } - - fn evaluate(&self, challenge: Mersenne61) -> Mersenne61 { - self.coeffs[0] + self.coeffs[1] * challenge - } - - fn append_to_transcript(&self, transcript: &mut impl Transcript) { - self.coeffs[0].append_to_transcript(transcript); - self.coeffs[1].append_to_transcript(transcript); - } -} - -fn build_rounds() -> ( - SumcheckClaim, - Vec, - EvaluationClaim, -) { - let mut transcript = Blake2bTranscript::::new(b"mersenne61"); - let mut running_sum = Mersenne61::from_u64(10); - let mut point = Vec::new(); - let mut rounds = Vec::new(); - - for _ in 0..4 { - let c0 = running_sum * Mersenne61::from_u64(3); - let c1 = running_sum - c0 - c0; - let round = LinearRound { coeffs: [c0, c1] }; - round.append_to_transcript(&mut transcript); - let r = transcript.challenge(); - running_sum = round.evaluate(r); - point.push(r); - rounds.push(round); - } - - ( - SumcheckClaim::new(4, 1, Mersenne61::from_u64(10)), - rounds, - EvaluationClaim { - point, - value: running_sum, - }, - ) -} - -#[test] -fn hash_transcripts_accept_mersenne61_without_bn254_field_surface() { - let mut blake = Blake2bTranscript::::new(b"compat"); - let mut keccak = KeccakTranscript::::new(b"compat"); - Mersenne61::from_u64(42).append_to_transcript(&mut blake); - Mersenne61::from_u64(42).append_to_transcript(&mut keccak); - - let _: Mersenne61 = blake.challenge(); - let _: Mersenne61 = keccak.challenge(); -} - -#[test] -fn sumcheck_verifier_accepts_mersenne61_round_proof() { - let (claim, rounds, expected) = build_rounds(); - let mut verifier_transcript = Blake2bTranscript::::new(b"mersenne61"); - let actual = SumcheckVerifier::verify(&claim, &rounds, &mut verifier_transcript).unwrap(); - assert_eq!(actual, expected); -} diff --git a/crates/jolt-sumcheck/tests/roundtrip.rs b/crates/jolt-sumcheck/tests/roundtrip.rs index 06199c9b4b..7c6e301d70 100644 --- a/crates/jolt-sumcheck/tests/roundtrip.rs +++ b/crates/jolt-sumcheck/tests/roundtrip.rs @@ -6,7 +6,7 @@ #![expect(clippy::unwrap_used, reason = "tests may panic on assertion failures")] -use jolt_field::{Fr, FromPrimitiveInt, MulPow2}; +use jolt_field::{Field, Fr}; use jolt_poly::{Polynomial, UnivariatePoly}; use jolt_sumcheck::claim::{EvaluationClaim, SumcheckClaim}; use jolt_sumcheck::proof::SumcheckProof; diff --git a/crates/jolt-sumcheck/tests/soundness.rs b/crates/jolt-sumcheck/tests/soundness.rs index b4a78fb8ce..997c49495b 100644 --- a/crates/jolt-sumcheck/tests/soundness.rs +++ b/crates/jolt-sumcheck/tests/soundness.rs @@ -6,7 +6,7 @@ #![expect(clippy::unwrap_used, reason = "tests may panic on assertion failures")] -use jolt_field::{Fr, FromPrimitiveInt}; +use jolt_field::{Field, Fr}; use jolt_poly::{Polynomial, UnivariatePoly}; use jolt_sumcheck::claim::{EvaluationClaim, SumcheckClaim}; use jolt_sumcheck::error::SumcheckError; diff --git a/crates/jolt-trace/Cargo.toml b/crates/jolt-trace/Cargo.toml index 15689376a3..388fd655b7 100644 --- a/crates/jolt-trace/Cargo.toml +++ b/crates/jolt-trace/Cargo.toml @@ -17,7 +17,10 @@ test-utils = [] [dependencies] bincode.workspace = true common = { workspace = true } +jolt-field = { workspace = true } +jolt-r1cs = { workspace = true } jolt-riscv = { workspace = true } +jolt-witness = { workspace = true } rand = { workspace = true } serde.workspace = true tracer = { workspace = true, features = ["std", "test-utils"] } diff --git a/crates/jolt-trace/src/bytecode.rs b/crates/jolt-trace/src/bytecode.rs index 461f45d8d1..ec38c36666 100644 --- a/crates/jolt-trace/src/bytecode.rs +++ b/crates/jolt-trace/src/bytecode.rs @@ -8,7 +8,7 @@ //! - [`BytecodePCMapper::get_pc`] — resolves `(address, virtual_sequence_remaining)` //! to a dense bytecode table index, accounting for virtual instruction expansion. -use crate::JoltInstruction; +use crate::{CycleRow, JoltInstruction}; use common::constants::{ALIGNMENT_FACTOR_BYTECODE, RAM_START_ADDRESS}; use serde::{Deserialize, Serialize}; use tracer::instruction::Instruction; @@ -64,6 +64,16 @@ impl BytecodePreprocessing { cycle.virtual_sequence_remaining().unwrap_or(0), ) } + + pub fn get_cycle_pc(&self, cycle: &impl CycleRow) -> usize { + if cycle.is_noop() { + return 0; + } + self.pc_map.get_pc( + cycle.unexpanded_pc() as usize, + cycle.virtual_sequence_remaining().unwrap_or(0), + ) + } } /// Maps physical instruction addresses to dense bytecode table indices. diff --git a/crates/jolt-trace/src/cycle_row.rs b/crates/jolt-trace/src/cycle_row.rs new file mode 100644 index 0000000000..e7722c3845 --- /dev/null +++ b/crates/jolt-trace/src/cycle_row.rs @@ -0,0 +1,77 @@ +//! Abstract cycle interface for the proving pipeline. +//! +//! [`CycleRow`] is the boundary between the tracer (which produces concrete +//! `Cycle` values) and the proving system (which consumes per-cycle data to +//! build witnesses). All ISA-specific logic (instruction dispatch, flag +//! computation, operand routing) is pushed into the `CycleRow` implementation, +//! so the prover sees only scalars and static flag sets. + +use jolt_riscv::{CircuitFlagSet, InstructionFlagSet}; + +/// Abstract interface for one execution cycle of a RISC-V trace. +/// +/// Bolt's witness layer is generic over `CycleRow`. The concrete implementation +/// for `tracer::Cycle` lives in this crate. +pub trait CycleRow: Copy { + /// A no-op (padding) cycle. + fn noop() -> Self; + + /// True if this cycle is a no-op (padding). + fn is_noop(&self) -> bool; + + /// The unexpanded (pre-virtual-expansion) program counter. + fn unexpanded_pc(&self) -> u64; + + /// Remaining steps in a virtual instruction sequence, or `None` if + /// this is a real (non-virtual) instruction. + fn virtual_sequence_remaining(&self) -> Option; + + /// True if this is the first instruction in a virtual sequence. + fn is_first_in_sequence(&self) -> bool; + + /// True if this is a virtual (expanded) instruction. + fn is_virtual(&self) -> bool; + + /// RS1 register read: `(register_index, value)`, or `None` if unused. + fn rs1_read(&self) -> Option<(u8, u64)>; + + /// RS2 register read: `(register_index, value)`, or `None` if unused. + fn rs2_read(&self) -> Option<(u8, u64)>; + + /// RD register write: `(register_index, pre_value, post_value)`, or `None`. + fn rd_write(&self) -> Option<(u8, u64, u64)>; + + /// The static `rd` operand from the instruction encoding. + fn rd_operand(&self) -> Option; + + /// RAM access address, or `None` if no RAM access this cycle. + fn ram_access_address(&self) -> Option; + + /// RAM read value (pre-access value). `None` if no RAM access. + fn ram_read_value(&self) -> Option; + + /// RAM write value (post-access value). `None` if no RAM access. + fn ram_write_value(&self) -> Option; + + /// The immediate operand, sign-extended. + fn imm(&self) -> i128; + + /// R1CS circuit flags. + fn circuit_flags(&self) -> CircuitFlagSet; + + /// Non-R1CS instruction flags. + fn instruction_flags(&self) -> InstructionFlagSet; + + /// Combined lookup index for RA polynomial construction (128-bit). + fn lookup_index(&self) -> u128; + + /// Lookup table evaluation result. + /// + /// For arithmetic: the computation result (e.g., rs1 + rs2 for ADD). + /// For branches: the comparison result (0 or 1). + /// For stores: zero. + /// For no-ops: zero. + /// + /// This is the value of V_LOOKUP_OUTPUT in the R1CS witness. + fn lookup_output(&self) -> u64; +} diff --git a/crates/jolt-trace/src/extract.rs b/crates/jolt-trace/src/extract.rs new file mode 100644 index 0000000000..852c447751 --- /dev/null +++ b/crates/jolt-trace/src/extract.rs @@ -0,0 +1,118 @@ +//! Single-pass trace extraction: witness inputs + R1CS + instruction flags. +//! +//! [`extract_trace`] iterates the trace once, producing all three artifacts +//! the prover needs. R1CS witness construction delegates to +//! [`r1cs_cycle_witness`](crate::r1cs_witness::r1cs_cycle_witness). + +use common::jolt_device::MemoryLayout; +use jolt_field::Field; +use jolt_r1cs::constraints::rv64::*; +use jolt_riscv::{InstructionFlagSet, InstructionFlags}; +use jolt_witness::CycleInput; + +use crate::bytecode::BytecodePreprocessing; +use crate::r1cs_witness::r1cs_cycle_witness; +use crate::CycleRow; + +/// Per-cycle instruction flag polynomials for sumcheck instances. +pub struct InstructionFlagData { + pub is_noop: Vec, + pub left_is_rs1: Vec, + pub left_is_pc: Vec, + pub right_is_rs2: Vec, + pub right_is_imm: Vec, +} + +/// Extract witness inputs, R1CS witness, and instruction flags in one pass. +/// +/// Produces `size`-length outputs, padding beyond `trace.len()` with defaults. +pub fn extract_trace( + trace: &[C], + size: usize, + bytecode: &BytecodePreprocessing, + memory_layout: &MemoryLayout, + num_vars_padded: usize, +) -> (Vec, Vec, InstructionFlagData) { + let mut inputs = Vec::with_capacity(size); + let mut r1cs = vec![F::from_u64(0); size * num_vars_padded]; + let mut flags = InstructionFlagData::new(size); + + for t in 0..size { + let offset = t * num_vars_padded; + + if t < trace.len() { + let cycle = &trace[t]; + + if cycle.is_noop() { + inputs.push(CycleInput::PADDING); + } else { + inputs.push(cycle_input(cycle, bytecode, memory_layout)); + } + + let row = r1cs_cycle_witness::(trace, t, bytecode); + r1cs[offset..offset + NUM_VARS_PER_CYCLE].copy_from_slice(&row); + + flags.set(t, cycle.instruction_flags()); + } else { + inputs.push(CycleInput::PADDING); + flags.is_noop[t] = F::from_u64(1); + r1cs[offset + V_CONST] = F::from_u64(1); + r1cs[offset + V_FLAG_DO_NOT_UPDATE_UNEXPANDED_PC] = F::from_u64(1); + r1cs[offset + V_NEXT_IS_NOOP] = F::from_u64(1); + } + } + + (inputs, r1cs, flags) +} + +fn cycle_input( + cycle: &impl CycleRow, + bytecode: &BytecodePreprocessing, + memory_layout: &MemoryLayout, +) -> CycleInput { + let rd_inc = match cycle.rd_write() { + Some((_, pre, post)) => post as i128 - pre as i128, + None => 0, + }; + let ram_inc = match (cycle.ram_read_value(), cycle.ram_write_value()) { + (Some(pre), Some(post)) => post as i128 - pre as i128, + _ => 0, + }; + let lowest = memory_layout.get_lowest_address(); + let ram_address = cycle.ram_access_address().map(|addr| { + debug_assert!( + addr >= lowest, + "RAM address {addr:#x} below lowest {lowest:#x}" + ); + ((addr - lowest) / 8) as u128 + }); + + CycleInput { + dense: [rd_inc, ram_inc], + one_hot: [ + Some(cycle.lookup_index()), + Some(bytecode.get_cycle_pc(cycle) as u128), + ram_address, + ], + } +} + +impl InstructionFlagData { + fn new(size: usize) -> Self { + Self { + is_noop: vec![F::from_u64(0); size], + left_is_rs1: vec![F::from_u64(0); size], + left_is_pc: vec![F::from_u64(0); size], + right_is_rs2: vec![F::from_u64(0); size], + right_is_imm: vec![F::from_u64(0); size], + } + } + + fn set(&mut self, t: usize, iflags: InstructionFlagSet) { + self.is_noop[t] = F::from_u64(iflags[InstructionFlags::IsNoop] as u64); + self.left_is_rs1[t] = F::from_u64(iflags[InstructionFlags::LeftOperandIsRs1Value] as u64); + self.left_is_pc[t] = F::from_u64(iflags[InstructionFlags::LeftOperandIsPC] as u64); + self.right_is_rs2[t] = F::from_u64(iflags[InstructionFlags::RightOperandIsRs2Value] as u64); + self.right_is_imm[t] = F::from_u64(iflags[InstructionFlags::RightOperandIsImm] as u64); + } +} diff --git a/crates/jolt-trace/src/lib.rs b/crates/jolt-trace/src/lib.rs index d48b3a5edb..101293688b 100644 --- a/crates/jolt-trace/src/lib.rs +++ b/crates/jolt-trace/src/lib.rs @@ -6,11 +6,17 @@ mod analyze; pub mod bytecode; +mod cycle_row; +mod extract; mod jolt_cycle; mod program; +pub mod r1cs_witness; pub mod ram; +mod tracer_cycle; pub use bytecode::BytecodePreprocessing; +pub use cycle_row::CycleRow; +pub use extract::{extract_trace, InstructionFlagData}; pub use jolt_cycle::JoltCycle; pub use jolt_riscv::instructions; pub use jolt_riscv::{ @@ -18,6 +24,8 @@ pub use jolt_riscv::{ InterleavedBitsMarker, JoltInstruction, JoltInstructions, NUM_CIRCUIT_FLAGS, NUM_INSTRUCTION_FLAGS, }; +pub use r1cs_witness::{build_r1cs_witness, r1cs_cycle_witness}; +pub use tracer_cycle::{instruction_circuit_flags, instruction_instruction_flags}; use std::path::{Path, PathBuf}; diff --git a/crates/jolt-trace/src/r1cs_witness.rs b/crates/jolt-trace/src/r1cs_witness.rs new file mode 100644 index 0000000000..c879be10fd --- /dev/null +++ b/crates/jolt-trace/src/r1cs_witness.rs @@ -0,0 +1,172 @@ +//! Per-cycle R1CS witness extraction from [`CycleRow`] data. +//! +//! Produces the witness vector for one cycle, matching the variable +//! layout in [`jolt_r1cs::constraints::rv64`]. + +use jolt_field::Field; +use jolt_r1cs::constraints::rv64::*; +use jolt_riscv::{CircuitFlagSet, CircuitFlags, InstructionFlags}; + +use crate::bytecode::BytecodePreprocessing; +use crate::CycleRow; + +/// Per-cycle R1CS witness matching `jolt_r1cs::constraints::rv64` layout. +pub fn r1cs_cycle_witness( + trace: &[C], + t: usize, + bytecode: &BytecodePreprocessing, +) -> [F; NUM_VARS_PER_CYCLE] { + let cycle = &trace[t]; + let next = trace.get(t + 1); + + let mut w = [F::from_u64(0); NUM_VARS_PER_CYCLE]; + w[V_CONST] = F::from_u64(1); + + if cycle.is_noop() { + w[V_FLAG_DO_NOT_UPDATE_UNEXPANDED_PC] = F::from_u64(1); + w[V_NEXT_IS_NOOP] = F::from_u64(next.is_none_or(|c| c.is_noop()) as u64); + fill_next_fields(&mut w, next, bytecode); + return w; + } + + let cflags = cycle.circuit_flags(); + let iflags = cycle.instruction_flags(); + + // Instruction inputs + let left_input = if iflags[InstructionFlags::LeftOperandIsPC] { + cycle.unexpanded_pc() + } else if iflags[InstructionFlags::LeftOperandIsRs1Value] { + cycle.rs1_read().map_or(0, |(_, v)| v) + } else { + 0 + }; + + let right_input: i128 = if iflags[InstructionFlags::RightOperandIsImm] { + cycle.imm() + } else if iflags[InstructionFlags::RightOperandIsRs2Value] { + cycle.rs2_read().map_or(0, |(_, v)| v as i128) + } else { + 0 + }; + + w[V_LEFT_INSTRUCTION_INPUT] = F::from_u64(left_input); + w[V_RIGHT_INSTRUCTION_INPUT] = F::from_i128(right_input); + w[V_PRODUCT] = w[V_LEFT_INSTRUCTION_INPUT] * w[V_RIGHT_INSTRUCTION_INPUT]; + + // Lookup output + let lookup_output = cycle.lookup_output(); + w[V_LOOKUP_OUTPUT] = F::from_u64(lookup_output); + + // Lookup operands — must match R1CS constraints + let (left_lookup, right_lookup) = + lookup_operands(left_input, right_input, w[V_PRODUCT], cflags, lookup_output); + w[V_LEFT_LOOKUP_OPERAND] = left_lookup; + w[V_RIGHT_LOOKUP_OPERAND] = right_lookup; + + // Registers + w[V_RS1_VALUE] = F::from_u64(cycle.rs1_read().map_or(0, |(_, v)| v)); + w[V_RS2_VALUE] = F::from_u64(cycle.rs2_read().map_or(0, |(_, v)| v)); + w[V_RD_WRITE_VALUE] = F::from_u64(cycle.rd_write().map_or(0, |(_, _, post)| post)); + + // RAM + w[V_RAM_ADDRESS] = F::from_u64(cycle.ram_access_address().unwrap_or(0)); + w[V_RAM_READ_VALUE] = F::from_u64(cycle.ram_read_value().unwrap_or(0)); + w[V_RAM_WRITE_VALUE] = F::from_u64(cycle.ram_write_value().unwrap_or(0)); + + // PCs + w[V_PC] = F::from_u64(bytecode.get_cycle_pc(cycle) as u64); + w[V_UNEXPANDED_PC] = F::from_u64(cycle.unexpanded_pc()); + w[V_IMM] = F::from_i128(cycle.imm()); + + // Circuit flags + w[V_FLAG_ADD_OPERANDS] = F::from_u64(cflags[CircuitFlags::AddOperands] as u64); + w[V_FLAG_SUBTRACT_OPERANDS] = F::from_u64(cflags[CircuitFlags::SubtractOperands] as u64); + w[V_FLAG_MULTIPLY_OPERANDS] = F::from_u64(cflags[CircuitFlags::MultiplyOperands] as u64); + w[V_FLAG_LOAD] = F::from_u64(cflags[CircuitFlags::Load] as u64); + w[V_FLAG_STORE] = F::from_u64(cflags[CircuitFlags::Store] as u64); + w[V_FLAG_JUMP] = F::from_u64(cflags[CircuitFlags::Jump] as u64); + w[V_FLAG_WRITE_LOOKUP_OUTPUT_TO_RD] = + F::from_u64(cflags[CircuitFlags::WriteLookupOutputToRD] as u64); + w[V_FLAG_VIRTUAL_INSTRUCTION] = F::from_u64(cflags[CircuitFlags::VirtualInstruction] as u64); + w[V_FLAG_ASSERT] = F::from_u64(cflags[CircuitFlags::Assert] as u64); + w[V_FLAG_DO_NOT_UPDATE_UNEXPANDED_PC] = + F::from_u64(cflags[CircuitFlags::DoNotUpdateUnexpandedPC] as u64); + w[V_FLAG_ADVICE] = F::from_u64(cflags[CircuitFlags::Advice] as u64); + w[V_FLAG_IS_COMPRESSED] = F::from_u64(cflags[CircuitFlags::IsCompressed] as u64); + w[V_FLAG_IS_FIRST_IN_SEQUENCE] = F::from_u64(cflags[CircuitFlags::IsFirstInSequence] as u64); + w[V_FLAG_IS_LAST_IN_SEQUENCE] = F::from_u64(cflags[CircuitFlags::IsLastInSequence] as u64); + + // Product factors + w[V_BRANCH] = F::from_u64(iflags[InstructionFlags::Branch] as u64); + w[V_SHOULD_BRANCH] = w[V_LOOKUP_OUTPUT] * w[V_BRANCH]; + + // Next-cycle fields + fill_next_fields(&mut w, next, bytecode); + let next_is_noop = next.is_none_or(|c| c.is_noop()); + w[V_NEXT_IS_NOOP] = F::from_u64(next_is_noop as u64); + w[V_SHOULD_JUMP] = w[V_FLAG_JUMP] * (F::from_u64(1) - w[V_NEXT_IS_NOOP]); + + w +} + +fn fill_next_fields( + w: &mut [F; NUM_VARS_PER_CYCLE], + next: Option<&C>, + bytecode: &BytecodePreprocessing, +) { + if let Some(nc) = next { + w[V_NEXT_PC] = F::from_u64(bytecode.get_cycle_pc(nc) as u64); + w[V_NEXT_UNEXPANDED_PC] = F::from_u64(nc.unexpanded_pc()); + let nc_flags = nc.circuit_flags(); + w[V_NEXT_IS_VIRTUAL] = F::from_u64(nc_flags[CircuitFlags::VirtualInstruction] as u64); + w[V_NEXT_IS_FIRST_IN_SEQUENCE] = + F::from_u64(nc_flags[CircuitFlags::IsFirstInSequence] as u64); + } +} + +/// Lookup operands matching the R1CS constraints: +/// - Add: `(0, left + right)` +/// - Sub: `(0, left - right + 2^64)` +/// - Mul: `(0, product)` +/// - Advice: `(0, lookup_output)` +/// - Default: `(left, right)` +fn lookup_operands( + left: u64, + right: i128, + product: F, + cflags: CircuitFlagSet, + lookup_output: u64, +) -> (F, F) { + if cflags[CircuitFlags::AddOperands] { + (F::from_u64(0), F::from_i128(left as i128 + right)) + } else if cflags[CircuitFlags::SubtractOperands] { + ( + F::from_u64(0), + F::from_i128(left as i128 - right + (1i128 << 64)), + ) + } else if cflags[CircuitFlags::MultiplyOperands] { + (F::from_u64(0), product) + } else if cflags[CircuitFlags::Advice] { + (F::from_u64(0), F::from_u64(lookup_output)) + } else { + (F::from_u64(left), F::from_i128(right)) + } +} + +/// Flat R1CS witness for the entire trace. +/// +/// Returns `Vec` of length `trace.len() * num_vars_padded`. +pub fn build_r1cs_witness( + trace: &[C], + bytecode: &BytecodePreprocessing, + num_vars_padded: usize, +) -> Vec { + let n = trace.len(); + let mut witness = vec![F::from_u64(0); n * num_vars_padded]; + for t in 0..n { + let row = r1cs_cycle_witness::(trace, t, bytecode); + witness[t * num_vars_padded..t * num_vars_padded + NUM_VARS_PER_CYCLE] + .copy_from_slice(&row); + } + witness +} diff --git a/crates/jolt-trace/src/ram.rs b/crates/jolt-trace/src/ram.rs index 982879b159..3c6c1ecf7d 100644 --- a/crates/jolt-trace/src/ram.rs +++ b/crates/jolt-trace/src/ram.rs @@ -5,7 +5,7 @@ //! - `Memory`: final tracer memory state //! - `JoltDevice`: I/O data (inputs, outputs, advice, panic/termination) //! -//! Mirrors jolt-core's `gen_ram_memory_states` but uses jolt-host types. +//! Mirrors jolt-core's `gen_ram_memory_states` but uses jolt-trace types. use common::constants::RAM_START_ADDRESS; use common::jolt_device::JoltDevice; diff --git a/crates/jolt-trace/src/tracer_cycle.rs b/crates/jolt-trace/src/tracer_cycle.rs new file mode 100644 index 0000000000..8b7287084e --- /dev/null +++ b/crates/jolt-trace/src/tracer_cycle.rs @@ -0,0 +1,547 @@ +//! `CycleRow` implementation for `tracer::Cycle`. +//! +//! Maps `Instruction` variants to ISA structs via [`with_isa_struct!`], then +//! derives circuit flags and instruction flags. + +use jolt_riscv::{CircuitFlagSet, CircuitFlags, Flags, InstructionFlagSet, InstructionFlags}; +use tracer::instruction::{Cycle, Instruction, RAMAccess}; + +use crate::CycleRow; + +/// Map an `Instruction` variant to its ISA struct, bind it to `$i`, evaluate `$body`. +/// The `noop =>` arm handles `Instruction::NoOp` separately. +macro_rules! with_isa_struct { + ($instr:expr, |$i:ident| $body:expr, noop => $noop:expr) => {{ + use jolt_riscv::instructions::*; + match $instr { + Instruction::ADD(value) => { + let $i = Add(*value); + $body + } + Instruction::ADDI(value) => { + let $i = Addi(*value); + $body + } + Instruction::SUB(value) => { + let $i = Sub(*value); + $body + } + Instruction::LUI(value) => { + let $i = Lui(*value); + $body + } + Instruction::AUIPC(value) => { + let $i = Auipc(*value); + $body + } + Instruction::MUL(value) => { + let $i = Mul(*value); + $body + } + Instruction::MULHU(value) => { + let $i = MulHU(*value); + $body + } + Instruction::AND(value) => { + let $i = And(*value); + $body + } + Instruction::ANDI(value) => { + let $i = AndI(*value); + $body + } + Instruction::ANDN(value) => { + let $i = Andn(*value); + $body + } + Instruction::OR(value) => { + let $i = Or(*value); + $body + } + Instruction::ORI(value) => { + let $i = OrI(*value); + $body + } + Instruction::XOR(value) => { + let $i = Xor(*value); + $body + } + Instruction::XORI(value) => { + let $i = XorI(*value); + $body + } + Instruction::SLT(value) => { + let $i = Slt(*value); + $body + } + Instruction::SLTI(value) => { + let $i = SltI(*value); + $body + } + Instruction::SLTIU(value) => { + let $i = SltIU(*value); + $body + } + Instruction::SLTU(value) => { + let $i = SltU(*value); + $body + } + Instruction::BEQ(value) => { + let $i = Beq(*value); + $body + } + Instruction::BGE(value) => { + let $i = Bge(*value); + $body + } + Instruction::BGEU(value) => { + let $i = BgeU(*value); + $body + } + Instruction::BLT(value) => { + let $i = Blt(*value); + $body + } + Instruction::BLTU(value) => { + let $i = BltU(*value); + $body + } + Instruction::BNE(value) => { + let $i = Bne(*value); + $body + } + Instruction::JAL(value) => { + let $i = Jal(*value); + $body + } + Instruction::JALR(value) => { + let $i = Jalr(*value); + $body + } + Instruction::LD(value) => { + let $i = Ld(*value); + $body + } + Instruction::SD(value) => { + let $i = Sd(*value); + $body + } + Instruction::EBREAK(value) => { + let $i = Ebreak(*value); + $body + } + Instruction::ECALL(value) => { + let $i = Ecall(*value); + $body + } + Instruction::FENCE(value) => { + let $i = Fence(*value); + $body + } + Instruction::VirtualAdvice(value) => { + let $i = VirtualAdvice(*value); + $body + } + Instruction::VirtualAdviceLen(value) => { + let $i = VirtualAdviceLen(*value); + $body + } + Instruction::VirtualAdviceLoad(value) => { + let $i = VirtualAdviceLoad(*value); + $body + } + Instruction::VirtualHostIO(value) => { + let $i = VirtualHostIO(*value); + $body + } + Instruction::VirtualMULI(value) => { + let $i = MulI(*value); + $body + } + Instruction::VirtualPow2(value) => { + let $i = Pow2(*value); + $body + } + Instruction::VirtualPow2I(value) => { + let $i = Pow2I(*value); + $body + } + Instruction::VirtualPow2W(value) => { + let $i = Pow2W(*value); + $body + } + Instruction::VirtualPow2IW(value) => { + let $i = Pow2IW(*value); + $body + } + Instruction::VirtualAssertEQ(value) => { + let $i = AssertEq(*value); + $body + } + Instruction::VirtualAssertLTE(value) => { + let $i = AssertLte(*value); + $body + } + Instruction::VirtualAssertValidDiv0(value) => { + let $i = AssertValidDiv0(*value); + $body + } + Instruction::VirtualAssertValidUnsignedRemainder(value) => { + let $i = AssertValidUnsignedRemainder(*value); + $body + } + Instruction::VirtualAssertMulUNoOverflow(value) => { + let $i = AssertMulUNoOverflow(*value); + $body + } + Instruction::VirtualAssertWordAlignment(value) => { + let $i = AssertWordAlignment(*value); + $body + } + Instruction::VirtualAssertHalfwordAlignment(value) => { + let $i = AssertHalfwordAlignment(*value); + $body + } + Instruction::VirtualMovsign(value) => { + let $i = MovSign(*value); + $body + } + Instruction::VirtualRev8W(value) => { + let $i = VirtualRev8W(*value); + $body + } + Instruction::VirtualChangeDivisor(value) => { + let $i = VirtualChangeDivisor(*value); + $body + } + Instruction::VirtualChangeDivisorW(value) => { + let $i = VirtualChangeDivisorW(*value); + $body + } + Instruction::VirtualZeroExtendWord(value) => { + let $i = VirtualZeroExtendWord(*value); + $body + } + Instruction::VirtualSignExtendWord(value) => { + let $i = VirtualSignExtendWord(*value); + $body + } + Instruction::VirtualSRL(value) => { + let $i = VirtualSrl(*value); + $body + } + Instruction::VirtualSRLI(value) => { + let $i = VirtualSrli(*value); + $body + } + Instruction::VirtualSRA(value) => { + let $i = VirtualSra(*value); + $body + } + Instruction::VirtualSRAI(value) => { + let $i = VirtualSrai(*value); + $body + } + Instruction::VirtualShiftRightBitmask(value) => { + let $i = VirtualShiftRightBitmask(*value); + $body + } + Instruction::VirtualShiftRightBitmaskI(value) => { + let $i = VirtualShiftRightBitmaski(*value); + $body + } + Instruction::VirtualROTRI(value) => { + let $i = VirtualRotri(*value); + $body + } + Instruction::VirtualROTRIW(value) => { + let $i = VirtualRotriw(*value); + $body + } + Instruction::VirtualXORROT32(value) => { + let $i = VirtualXorRot32(*value); + $body + } + Instruction::VirtualXORROT24(value) => { + let $i = VirtualXorRot24(*value); + $body + } + Instruction::VirtualXORROT16(value) => { + let $i = VirtualXorRot16(*value); + $body + } + Instruction::VirtualXORROT63(value) => { + let $i = VirtualXorRot63(*value); + $body + } + Instruction::VirtualXORROTW16(value) => { + let $i = VirtualXorRotW16(*value); + $body + } + Instruction::VirtualXORROTW12(value) => { + let $i = VirtualXorRotW12(*value); + $body + } + Instruction::VirtualXORROTW8(value) => { + let $i = VirtualXorRotW8(*value); + $body + } + Instruction::VirtualXORROTW7(value) => { + let $i = VirtualXorRotW7(*value); + $body + } + Instruction::NoOp => $noop, + Instruction::INLINE(x) => panic!( + "INLINE reached CycleRow: opcode={}, funct3={}, funct7={}", + x.opcode, x.funct3, x.funct7 + ), + _ => panic!("unsupported instruction: {:?}", $instr), + } + }}; +} + +impl CycleRow for Cycle { + fn noop() -> Self { + Cycle::NoOp + } + + fn is_noop(&self) -> bool { + matches!(self, Cycle::NoOp) + } + + fn unexpanded_pc(&self) -> u64 { + match self { + Cycle::NoOp => 0, + _ => self.instruction().normalize().address as u64, + } + } + + fn virtual_sequence_remaining(&self) -> Option { + match self { + Cycle::NoOp => None, + _ => self.instruction().normalize().virtual_sequence_remaining, + } + } + + fn is_first_in_sequence(&self) -> bool { + match self { + Cycle::NoOp => false, + _ => self.instruction().normalize().is_first_in_sequence, + } + } + + fn is_virtual(&self) -> bool { + self.virtual_sequence_remaining().is_some() + } + + fn rs1_read(&self) -> Option<(u8, u64)> { + self.rs1_read() + } + + fn rs2_read(&self) -> Option<(u8, u64)> { + self.rs2_read() + } + + fn rd_write(&self) -> Option<(u8, u64, u64)> { + self.rd_write() + } + + fn rd_operand(&self) -> Option { + match self { + Cycle::NoOp => None, + _ => self.instruction().normalize().operands.rd, + } + } + + fn ram_access_address(&self) -> Option { + match self.ram_access() { + RAMAccess::Read(r) => Some(r.address), + RAMAccess::Write(w) => Some(w.address), + RAMAccess::NoOp => None, + } + } + + fn ram_read_value(&self) -> Option { + match self.ram_access() { + RAMAccess::Read(r) => Some(r.value), + RAMAccess::Write(w) => Some(w.pre_value), + RAMAccess::NoOp => None, + } + } + + fn ram_write_value(&self) -> Option { + match self.ram_access() { + RAMAccess::Read(r) => Some(r.value), + RAMAccess::Write(w) => Some(w.post_value), + RAMAccess::NoOp => None, + } + } + + fn imm(&self) -> i128 { + match self { + Cycle::NoOp => 0, + _ => self.instruction().normalize().operands.imm, + } + } + + fn circuit_flags(&self) -> CircuitFlagSet { + static_circuit_flags(&self.instruction()) + } + + fn instruction_flags(&self) -> InstructionFlagSet { + static_instruction_flags(&self.instruction()) + } + + fn lookup_index(&self) -> u128 { + let cflags = self.circuit_flags(); + let iflags = self.instruction_flags(); + let (left, right) = instruction_inputs(self, iflags); + + if cflags[CircuitFlags::AddOperands] { + (left as u128).wrapping_add(right) + } else if cflags[CircuitFlags::SubtractOperands] { + (1u128 << 64).wrapping_sub(right).wrapping_add(left as u128) + } else if cflags[CircuitFlags::MultiplyOperands] { + (left as u128).wrapping_mul(right) + } else if cflags[CircuitFlags::Advice] { + self.rd_write().map_or(0, |(_, _, post)| post as u128) + } else if self.is_noop() { + 0 + } else { + interleave_bits(left, right as u64) + } + } + + fn lookup_output(&self) -> u64 { + if self.is_noop() { + return 0; + } + let cflags = self.circuit_flags(); + let iflags = self.instruction_flags(); + + if cflags[CircuitFlags::Jump] { + // JAL/JALR: lookup output = jump target, not return address. + let left = if iflags[InstructionFlags::LeftOperandIsPC] { + self.unexpanded_pc() + } else { + self.rs1_read().map_or(0, |(_, v)| v) + }; + let target = (left as i64).wrapping_add(self.imm() as i64) as u64; + if iflags[InstructionFlags::LeftOperandIsRs1Value] { + target & !1 // JALR aligns to 2-byte boundary + } else { + target + } + } else if cflags[CircuitFlags::Assert] { + 1 + } else if iflags[InstructionFlags::Branch] { + let rs1 = self.rs1_read().map_or(0, |(_, v)| v); + let rs2 = self.rs2_read().map_or(0, |(_, v)| v); + branch_result(self.instruction(), rs1, rs2) + } else if cflags[CircuitFlags::WriteLookupOutputToRD] { + self.rd_write().map_or(0, |(_, _, post)| post) + } else { + 0 + } + } +} + +fn instruction_inputs(cycle: &impl CycleRow, iflags: InstructionFlagSet) -> (u64, u128) { + let left = if iflags[InstructionFlags::LeftOperandIsPC] { + cycle.unexpanded_pc() + } else if iflags[InstructionFlags::LeftOperandIsRs1Value] { + cycle.rs1_read().map_or(0, |(_, v)| v) + } else { + 0 + }; + + let right: i128 = if iflags[InstructionFlags::RightOperandIsImm] { + cycle.imm() + } else if iflags[InstructionFlags::RightOperandIsRs2Value] { + cycle.rs2_read().map_or(0, |(_, v)| v as i128) + } else { + 0 + }; + + (left, right as u64 as u128) +} + +pub fn instruction_circuit_flags(instr: &Instruction) -> CircuitFlagSet { + with_isa_struct!(instr, |i| Flags::circuit_flags(&i), noop => { + CircuitFlagSet::default().set(CircuitFlags::DoNotUpdateUnexpandedPC) + }) +} + +pub fn instruction_instruction_flags(instr: &Instruction) -> InstructionFlagSet { + with_isa_struct!(instr, |i| Flags::instruction_flags(&i), noop => { + InstructionFlagSet::default().set(InstructionFlags::IsNoop) + }) +} + +fn static_circuit_flags(instr: &Instruction) -> CircuitFlagSet { + instruction_circuit_flags(instr) +} + +fn static_instruction_flags(instr: &Instruction) -> InstructionFlagSet { + instruction_instruction_flags(instr) +} + +#[inline] +fn interleave_bits(x: u64, y: u64) -> u128 { + let mut x_bits = x as u128; + x_bits = (x_bits | (x_bits << 32)) & 0x0000_0000_FFFF_FFFF_0000_0000_FFFF_FFFF; + x_bits = (x_bits | (x_bits << 16)) & 0x0000_FFFF_0000_FFFF_0000_FFFF_0000_FFFF; + x_bits = (x_bits | (x_bits << 8)) & 0x00FF_00FF_00FF_00FF_00FF_00FF_00FF_00FF; + x_bits = (x_bits | (x_bits << 4)) & 0x0F0F_0F0F_0F0F_0F0F_0F0F_0F0F_0F0F_0F0F; + x_bits = (x_bits | (x_bits << 2)) & 0x3333_3333_3333_3333_3333_3333_3333_3333; + x_bits = (x_bits | (x_bits << 1)) & 0x5555_5555_5555_5555_5555_5555_5555_5555; + + let mut y_bits = y as u128; + y_bits = (y_bits | (y_bits << 32)) & 0x0000_0000_FFFF_FFFF_0000_0000_FFFF_FFFF; + y_bits = (y_bits | (y_bits << 16)) & 0x0000_FFFF_0000_FFFF_0000_FFFF_0000_FFFF; + y_bits = (y_bits | (y_bits << 8)) & 0x00FF_00FF_00FF_00FF_00FF_00FF_00FF_00FF; + y_bits = (y_bits | (y_bits << 4)) & 0x0F0F_0F0F_0F0F_0F0F_0F0F_0F0F_0F0F_0F0F; + y_bits = (y_bits | (y_bits << 2)) & 0x3333_3333_3333_3333_3333_3333_3333_3333; + y_bits = (y_bits | (y_bits << 1)) & 0x5555_5555_5555_5555_5555_5555_5555_5555; + + (x_bits << 1) | y_bits +} + +fn branch_result(instr: Instruction, rs1: u64, rs2: u64) -> u64 { + let taken = match instr { + Instruction::BEQ(_) => rs1 == rs2, + Instruction::BNE(_) => rs1 != rs2, + Instruction::BLT(_) => (rs1 as i64) < (rs2 as i64), + Instruction::BGE(_) => (rs1 as i64) >= (rs2 as i64), + Instruction::BLTU(_) => rs1 < rs2, + Instruction::BGEU(_) => rs1 >= rs2, + _ => false, + }; + taken as u64 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn noop_trait_methods() { + let noop = Cycle::noop(); + assert!(noop.is_noop()); + assert_eq!(noop.unexpanded_pc(), 0); + assert!(noop.ram_access_address().is_none()); + assert!(noop.rs1_read().is_none()); + assert!(noop.rd_write().is_none()); + + let cflags = CycleRow::circuit_flags(&noop); + assert!(cflags[CircuitFlags::DoNotUpdateUnexpandedPC]); + + let iflags = CycleRow::instruction_flags(&noop); + assert!(iflags[InstructionFlags::IsNoop]); + } + + #[test] + fn noop_lookup_index_is_zero() { + assert_eq!(Cycle::noop().lookup_index(), 0); + } +} diff --git a/crates/jolt-transcript/benches/transcript_ops.rs b/crates/jolt-transcript/benches/transcript_ops.rs index 2cc82cbd65..0f2a682be1 100644 --- a/crates/jolt-transcript/benches/transcript_ops.rs +++ b/crates/jolt-transcript/benches/transcript_ops.rs @@ -4,7 +4,9 @@ use std::hint::black_box; use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; use jolt_field::Fr; -use jolt_transcript::{Blake2bTranscript, KeccakTranscript, PoseidonTranscript, Transcript}; +#[cfg(feature = "poseidon")] +use jolt_transcript::PoseidonTranscript; +use jolt_transcript::{Blake2bTranscript, KeccakTranscript, Transcript}; fn bench_append_bytes(c: &mut Criterion) { let mut group = c.benchmark_group("append_bytes"); @@ -32,6 +34,7 @@ fn bench_append_bytes(c: &mut Criterion) { criterion::BatchSize::SmallInput, ); }); + #[cfg(feature = "poseidon")] group.bench_with_input(BenchmarkId::new("Poseidon", label), data, |bench, data| { bench.iter_batched( || PoseidonTranscript::::new(b"bench"), @@ -73,6 +76,7 @@ fn bench_challenge(c: &mut Criterion) { ); }); + #[cfg(feature = "poseidon")] group.bench_function("Poseidon", |bench| { bench.iter_batched( || { diff --git a/crates/jolt-transcript/fuzz/Cargo.toml b/crates/jolt-transcript/fuzz/Cargo.toml index 4c5897b2f1..40c4bb8798 100644 --- a/crates/jolt-transcript/fuzz/Cargo.toml +++ b/crates/jolt-transcript/fuzz/Cargo.toml @@ -21,7 +21,7 @@ cargo-fuzz = true [dependencies] libfuzzer-sys = "0.4" -jolt-transcript = { path = ".." } +jolt-transcript = { path = "..", features = ["poseidon"] } [[bin]] name = "transcript_no_panic" diff --git a/crates/jolt-transcript/src/blake2b.rs b/crates/jolt-transcript/src/blake2b.rs index ac5abf8d25..4b47d4a28b 100644 --- a/crates/jolt-transcript/src/blake2b.rs +++ b/crates/jolt-transcript/src/blake2b.rs @@ -5,9 +5,4 @@ use blake2::{digest::consts::U32, Blake2b}; use crate::digest::DigestTranscript; /// Fiat-Shamir transcript backed by Blake2b-256. -#[cfg(feature = "poseidon")] pub type Blake2bTranscript = DigestTranscript, F>; - -/// Fiat-Shamir transcript backed by Blake2b-256. -#[cfg(not(feature = "poseidon"))] -pub type Blake2bTranscript = DigestTranscript, F>; diff --git a/crates/jolt-transcript/src/blanket.rs b/crates/jolt-transcript/src/blanket.rs index d080b2f5c4..0cc1342ac9 100644 --- a/crates/jolt-transcript/src/blanket.rs +++ b/crates/jolt-transcript/src/blanket.rs @@ -1,16 +1,19 @@ //! Blanket implementation of [`AppendToTranscript`] for field elements. -use jolt_field::CanonicalBytes; +use jolt_field::Field; use crate::transcript::{AppendToTranscript, Transcript}; /// Absorbs any field element as big-endian bytes (reversed from the canonical /// LE layout) for EVM compatibility. -impl AppendToTranscript for F { +impl AppendToTranscript for F { fn append_to_transcript(&self, transcript: &mut T) { - let mut buf = vec![0u8; F::NUM_BYTES]; - self.to_bytes_le(&mut buf); + let mut buf = self.to_bytes(); buf.reverse(); transcript.append_bytes(&buf); } + + fn serialized_len(&self) -> u64 { + 32 + } } diff --git a/crates/jolt-transcript/src/digest.rs b/crates/jolt-transcript/src/digest.rs index 67e9fef4c2..410919d2cc 100644 --- a/crates/jolt-transcript/src/digest.rs +++ b/crates/jolt-transcript/src/digest.rs @@ -18,8 +18,11 @@ struct TestState { /// Fiat-Shamir transcript backed by a 256-bit digest. /// /// Generic over the hash function `D` and field type `F`. Challenges are -/// produced as field elements through `F::from_challenge_bytes`. -pub struct DigestTranscript + 'static, F> { +/// produced as full-width field elements via `F::from_bytes()`. +pub struct DigestTranscript< + D: Digest + 'static, + F: jolt_field::Field = jolt_field::Fr, +> { state: [u8; 32], n_rounds: u32, #[cfg(test)] @@ -27,11 +30,7 @@ pub struct DigestTranscript + 'static, F> { _marker: std::marker::PhantomData<(fn() -> D, F)>, } -impl Clone for DigestTranscript -where - D: Digest, - F: jolt_field::TranscriptChallenge, -{ +impl, F: jolt_field::Field> Clone for DigestTranscript { fn clone(&self) -> Self { Self { state: self.state, @@ -43,21 +42,13 @@ where } } -impl Default for DigestTranscript -where - D: Digest, - F: jolt_field::TranscriptChallenge, -{ +impl, F: jolt_field::Field> Default for DigestTranscript { fn default() -> Self { Self::new(b"") } } -impl std::fmt::Debug for DigestTranscript -where - D: Digest, - F: jolt_field::TranscriptChallenge, -{ +impl, F: jolt_field::Field> std::fmt::Debug for DigestTranscript { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("DigestTranscript") .field("state", &format_args!("{:02x?}", self.state)) @@ -66,11 +57,7 @@ where } } -impl DigestTranscript -where - D: Digest, - F: jolt_field::TranscriptChallenge, -{ +impl, F: jolt_field::Field> DigestTranscript { #[inline] fn hasher(&self) -> D { let mut round_bytes = [0u8; 32]; @@ -97,11 +84,7 @@ where #[inline] fn challenge_bytes32(&mut self, out: &mut [u8; 32]) { - let hash: [u8; 32] = self - .hasher() - .chain_update([0x01]) // squeeze domain tag - .finalize() - .into(); + let hash: [u8; 32] = self.hasher().finalize().into(); out.copy_from_slice(&hash); self.update_state(hash); } @@ -124,11 +107,7 @@ where } } -impl Transcript for DigestTranscript -where - D: Digest, - F: jolt_field::TranscriptChallenge, -{ +impl, F: jolt_field::Field> Transcript for DigestTranscript { type Challenge = F; fn new(label: &'static [u8]) -> Self { @@ -155,19 +134,14 @@ where } fn append_bytes(&mut self, bytes: &[u8]) { - let hash: [u8; 32] = self - .hasher() - .chain_update([0x00]) // absorb domain tag - .chain_update(bytes) - .finalize() - .into(); + let hash: [u8; 32] = self.hasher().chain_update(bytes).finalize().into(); self.update_state(hash); } fn challenge(&mut self) -> F { - let mut buf = [0u8; 16]; + let mut buf = vec![0u8; F::NUM_BYTES]; self.challenge_bytes(&mut buf); - F::from_challenge_bytes(&buf) + F::from_bytes(&buf) } #[inline] diff --git a/crates/jolt-transcript/src/domain.rs b/crates/jolt-transcript/src/domain.rs index 5be57e8800..00cab90ccc 100644 --- a/crates/jolt-transcript/src/domain.rs +++ b/crates/jolt-transcript/src/domain.rs @@ -31,6 +31,10 @@ impl AppendToTranscript for Label { padded[..self.0.len()].copy_from_slice(self.0); transcript.append_bytes(&padded); } + + fn serialized_len(&self) -> u64 { + 32 + } } /// Packed label (24 bytes) + count (8 bytes BE) in one 32-byte word. @@ -56,6 +60,10 @@ impl AppendToTranscript for LabelWithCount { packed[24..32].copy_from_slice(&self.1.to_be_bytes()); transcript.append_bytes(&packed); } + + fn serialized_len(&self) -> u64 { + 32 + } } /// EVM-compatible left-padded u64: 24 zero bytes + 8-byte BE value. @@ -69,6 +77,10 @@ impl AppendToTranscript for U64Word { packed[24..].copy_from_slice(&self.0.to_be_bytes()); transcript.append_bytes(&packed); } + + fn serialized_len(&self) -> u64 { + 32 + } } #[cfg(test)] diff --git a/crates/jolt-transcript/src/impl_transcript.rs b/crates/jolt-transcript/src/impl_transcript.rs new file mode 100644 index 0000000000..e8461e8279 --- /dev/null +++ b/crates/jolt-transcript/src/impl_transcript.rs @@ -0,0 +1,166 @@ +//! Macro for implementing the Transcript trait with different hash functions. + +/// Implements the `Transcript` trait for a hash-based transcript. +/// +/// The generated struct is generic over `F: Field`, producing full-width +/// field-element challenges directly via `F::from_bytes()`. +macro_rules! impl_transcript { + ($name:ident, $hasher:ty, $new_hasher:expr) => { + use $crate::transcript::Transcript; + + /// Internal state for test-time transcript comparison. + #[cfg(test)] + #[derive(Clone, Default)] + struct TestState { + state_history: Vec<[u8; 32]>, + expected_state_history: Option>, + } + + #[doc = concat!("Fiat-Shamir transcript backed by ", stringify!($hasher), ".")] + /// + /// Generic over the field type `F`. Challenges are produced as + /// full-width field elements directly via `F::from_bytes()`. + #[derive(Clone)] + pub struct $name { + /// 256-bit running state. + state: [u8; 32], + /// Round counter for domain separation. + n_rounds: u32, + /// Test-only state for transcript comparison. + #[cfg(test)] + test_state: TestState, + _field: std::marker::PhantomData, + } + + impl Default for $name { + fn default() -> Self { + Self { + state: [0u8; 32], + n_rounds: 0, + #[cfg(test)] + test_state: TestState::default(), + _field: std::marker::PhantomData, + } + } + } + + impl std::fmt::Debug for $name { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct(stringify!($name)) + .field("state", &format_args!("{:02x?}", self.state)) + .field("n_rounds", &self.n_rounds) + .finish() + } + } + + impl $name { + /// Returns a hasher seeded with `state || round_counter` for domain separation. + #[inline] + fn hasher(&self) -> $hasher { + let mut round_bytes = [0u8; 32]; + round_bytes[28..].copy_from_slice(&self.n_rounds.to_be_bytes()); + <$hasher as Digest>::new() + .chain_update(self.state) + .chain_update(round_bytes) + } + + /// Fills `out` with challenge bytes, using `ceil(len / 32)` hash invocations. + fn challenge_bytes(&mut self, out: &mut [u8]) { + let mut remaining = out.len(); + let mut offset = 0; + + while remaining > 32 { + let mut chunk = [0u8; 32]; + self.challenge_bytes32(&mut chunk); + out[offset..offset + 32].copy_from_slice(&chunk); + offset += 32; + remaining -= 32; + } + + let mut final_chunk = [0u8; 32]; + self.challenge_bytes32(&mut final_chunk); + out[offset..offset + remaining].copy_from_slice(&final_chunk[..remaining]); + } + + /// Squeezes exactly 32 bytes from the transcript state. + #[inline] + fn challenge_bytes32(&mut self, out: &mut [u8; 32]) { + let hash: [u8; 32] = self.hasher().finalize().into(); + out.copy_from_slice(&hash); + self.update_state(hash); + } + + fn update_state(&mut self, new_state: [u8; 32]) { + self.state = new_state; + self.n_rounds += 1; + + #[cfg(test)] + { + if let Some(ref expected) = self.test_state.expected_state_history { + assert_eq!( + new_state, expected[self.n_rounds as usize], + "Fiat-Shamir transcript mismatch at round {}", + self.n_rounds + ); + } + self.test_state.state_history.push(new_state); + } + } + } + + impl Transcript for $name { + type Challenge = F; + + fn new(label: &'static [u8]) -> Self { + assert!( + label.len() <= $crate::transcript::MAX_LABEL_LEN, + "label must be at most {} bytes", + $crate::transcript::MAX_LABEL_LEN, + ); + + let mut padded = [0u8; $crate::transcript::MAX_LABEL_LEN]; + padded[..label.len()].copy_from_slice(label); + + let hash: [u8; 32] = <$hasher as Digest>::new() + .chain_update(padded) + .finalize() + .into(); + + Self { + state: hash, + n_rounds: 0, + #[cfg(test)] + test_state: TestState { + state_history: vec![hash], + expected_state_history: None, + }, + _field: std::marker::PhantomData, + } + } + + fn append_bytes(&mut self, bytes: &[u8]) { + let hash: [u8; 32] = self.hasher().chain_update(bytes).finalize().into(); + self.update_state(hash); + } + + fn challenge(&mut self) -> F { + let mut buf = vec![0u8; F::NUM_BYTES]; + self.challenge_bytes(&mut buf); + F::from_bytes(&buf) + } + + #[inline] + fn state(&self) -> &[u8; 32] { + &self.state + } + + #[cfg(test)] + fn compare_to(&mut self, other: &Self) { + self.test_state.expected_state_history = + Some(other.test_state.state_history.clone()); + } + } + }; +} + +pub(crate) use impl_transcript; diff --git a/crates/jolt-transcript/src/keccak.rs b/crates/jolt-transcript/src/keccak.rs index bd4bae354b..9449baedc2 100644 --- a/crates/jolt-transcript/src/keccak.rs +++ b/crates/jolt-transcript/src/keccak.rs @@ -5,9 +5,4 @@ use sha3::Keccak256; use crate::digest::DigestTranscript; /// Fiat-Shamir transcript backed by Keccak-256. -#[cfg(feature = "poseidon")] pub type KeccakTranscript = DigestTranscript; - -/// Fiat-Shamir transcript backed by Keccak-256. -#[cfg(not(feature = "poseidon"))] -pub type KeccakTranscript = DigestTranscript; diff --git a/crates/jolt-transcript/src/lib.rs b/crates/jolt-transcript/src/lib.rs index 9fcc5f4fee..a529f1e505 100644 --- a/crates/jolt-transcript/src/lib.rs +++ b/crates/jolt-transcript/src/lib.rs @@ -13,23 +13,25 @@ //! //! # Implementations //! -//! Hash backends use a `state || round_counter` domain separation scheme and -//! delegate field-family challenge decoding to `TranscriptChallenge`. +//! Hash backends produce full-width field challenges and use a +//! `state || round_counter` domain separation scheme. //! //! - [`Blake2bTranscript`]: Uses Blake2b-256. Default choice for Jolt proofs. //! - [`KeccakTranscript`]: Uses Keccak-256. EVM-compatible for on-chain verification. -//! - [`PoseidonTranscript`]: Uses Poseidon over BN254 when the `poseidon` feature is enabled. +//! - `PoseidonTranscript`: Uses Poseidon over BN254 when the `poseidon` feature is enabled. //! //! # Dependency position //! -//! Depends on `jolt-field` for field challenge decoding and transcript -//! absorption. The `poseidon` feature enables BN254/Poseidon dependencies. +//! Depends on `jolt-field` (for the blanket [`AppendToTranscript`] impl on +//! [`Field`](jolt_field::Field) types). Used by `jolt-crypto`, `jolt-sumcheck`, +//! `jolt-openings`, `jolt-dory`, `jolt-blindfold`, and generated Jolt protocol +//! crates. //! //! # Example //! -//! ```ignore +//! ``` //! use jolt_transcript::{Transcript, Blake2bTranscript}; -//! use jolt_field::{FromPrimitiveInt, Fr}; +//! use jolt_field::{Field, Fr}; //! //! let mut transcript = Blake2bTranscript::::new(b"my_protocol"); //! @@ -51,6 +53,7 @@ mod blanket; mod digest; pub mod domain; mod keccak; +mod mock; #[cfg(feature = "poseidon")] mod poseidon; mod transcript; @@ -59,6 +62,7 @@ pub use blake2b::Blake2bTranscript; pub use digest::DigestTranscript; pub use domain::{Label, LabelWithCount, U64Word}; pub use keccak::KeccakTranscript; +pub use mock::MockTranscript; #[cfg(feature = "poseidon")] pub use poseidon::PoseidonTranscript; pub use transcript::{AppendToTranscript, Transcript}; diff --git a/crates/jolt-transcript/src/mock.rs b/crates/jolt-transcript/src/mock.rs new file mode 100644 index 0000000000..66df0d9521 --- /dev/null +++ b/crates/jolt-transcript/src/mock.rs @@ -0,0 +1,109 @@ +//! Deterministic mock transcript for testing. +//! +//! All absorb operations are no-ops. Challenges come from a seeded Blake2b +//! counter, producing the same sequence regardless of what is absorbed. +//! Use the same seed in both jolt-core's and jolt-transcript's mock +//! transcripts to get identical challenges for cross-system comparison. + +use crate::transcript::{AppendToTranscript, Transcript}; +use blake2::digest::consts::U32; +use blake2::{Blake2b, Digest}; +use jolt_field::Field; +use std::marker::PhantomData; + +type Blake2b256 = Blake2b; + +/// Mock transcript that ignores absorbs and produces deterministic challenges. +/// +/// Challenges are derived from `H(seed || counter)` where counter increments +/// on each squeeze. Two mock transcripts with the same seed always produce +/// identical challenge sequences. +#[derive(Clone)] +pub struct MockTranscript { + seed: [u8; 32], + counter: u64, + _field: PhantomData, +} + +impl Default for MockTranscript { + fn default() -> Self { + Self { + seed: [0u8; 32], + counter: 0, + _field: PhantomData, + } + } +} + +impl MockTranscript { + /// Creates a mock transcript with the given seed bytes. + #[must_use] + pub fn with_seed(seed: &[u8]) -> Self { + let hash: [u8; 32] = Blake2b256::new().chain_update(seed).finalize().into(); + Self { + seed: hash, + counter: 0, + _field: PhantomData, + } + } + + fn next_bytes32(&mut self) -> [u8; 32] { + let hash: [u8; 32] = Blake2b256::new() + .chain_update(self.seed) + .chain_update(self.counter.to_le_bytes()) + .finalize() + .into(); + self.counter += 1; + hash + } +} + +impl Transcript for MockTranscript { + type Challenge = F; + + fn new(_label: &'static [u8]) -> Self { + Self::with_seed(b"mock_transcript_default_seed") + } + + fn append_bytes(&mut self, _bytes: &[u8]) {} + + fn append(&mut self, _value: &A) {} + + fn challenge(&mut self) -> F { + F::from_bytes(&self.next_bytes32()) + } + + fn state(&self) -> &[u8; 32] { + &self.seed + } + + #[cfg(test)] + fn compare_to(&mut self, _other: &Self) {} +} + +#[cfg(test)] +mod tests { + use super::*; + use jolt_field::Fr; + + #[test] + fn same_seed_same_challenges() { + let mut t1 = MockTranscript::::with_seed(b"test"); + let mut t2 = MockTranscript::::with_seed(b"test"); + + // Absorb different things — shouldn't matter + t1.append_bytes(b"hello"); + t2.append_bytes(b"world"); + + for _ in 0..100 { + assert_eq!(t1.challenge(), t2.challenge()); + } + } + + #[test] + fn different_seed_different_challenges() { + let mut t1 = MockTranscript::::with_seed(b"seed_a"); + let mut t2 = MockTranscript::::with_seed(b"seed_b"); + assert_ne!(t1.challenge(), t2.challenge()); + } +} diff --git a/crates/jolt-transcript/src/poseidon.rs b/crates/jolt-transcript/src/poseidon.rs index 1a008839f0..4cd923d0f8 100644 --- a/crates/jolt-transcript/src/poseidon.rs +++ b/crates/jolt-transcript/src/poseidon.rs @@ -1,5 +1,4 @@ //! Poseidon-based Fiat-Shamir transcript for SNARK-friendly verification. -#![cfg(feature = "poseidon")] //! //! Uses 3-input Poseidon (width-4 permutation: 3 inputs + 1 capacity element) //! over BN254 Fr with circom-compatible parameters via [`light_poseidon`]. @@ -43,8 +42,8 @@ const BYTES_PER_CHUNK: usize = 32; /// Fiat-Shamir transcript using Poseidon hash over BN254. /// -/// Generic over the field type `F`. Challenges are produced as field -/// elements directly via `TranscriptChallenge`. +/// Generic over the field type `F`. Challenges are produced as full-width +/// field elements directly via `F::from_bytes()`. pub struct PoseidonTranscript { /// 256-bit running state (canonical LE serialization of Fr). state: [u8; 32], @@ -233,9 +232,9 @@ impl Transcript for PoseidonTranscript { } fn challenge(&mut self) -> F { - let mut buf = [0u8; 16]; + let mut buf = vec![0u8; F::NUM_BYTES]; self.challenge_bytes(&mut buf); - ::from_challenge_bytes(&buf) + F::from_bytes(&buf) } #[inline] diff --git a/crates/jolt-transcript/src/transcript.rs b/crates/jolt-transcript/src/transcript.rs index cc4d9580cd..9b0053efcf 100644 --- a/crates/jolt-transcript/src/transcript.rs +++ b/crates/jolt-transcript/src/transcript.rs @@ -78,4 +78,8 @@ pub const MAX_LABEL_LEN: usize = 32; pub trait AppendToTranscript { /// Absorbs this value into the transcript. fn append_to_transcript(&self, transcript: &mut T); + + /// Number of raw bytes that [`append_to_transcript`](Self::append_to_transcript) + /// feeds to [`Transcript::append_bytes`]. + fn serialized_len(&self) -> u64; } diff --git a/crates/jolt-transcript/tests/blake2b_tests.rs b/crates/jolt-transcript/tests/blake2b_tests.rs index f2af8920a0..3dba55874c 100644 --- a/crates/jolt-transcript/tests/blake2b_tests.rs +++ b/crates/jolt-transcript/tests/blake2b_tests.rs @@ -1,9 +1,8 @@ //! Tests for Blake2bTranscript implementation. -#![cfg(feature = "poseidon")] mod common; -use jolt_field::{Fr, FromPrimitiveInt}; +use jolt_field::Fr; use jolt_transcript::Blake2bTranscript; use num_traits::Zero; @@ -61,6 +60,7 @@ fn test_field_zero_one_distinct_states() { #[test] fn test_field_element_ordering_sensitivity() { + use jolt_field::{Field, Fr}; use jolt_transcript::{AppendToTranscript, Transcript}; let a = Fr::from_u64(42); diff --git a/crates/jolt-transcript/tests/keccak_tests.rs b/crates/jolt-transcript/tests/keccak_tests.rs index 8ba613d52b..9058f8da61 100644 --- a/crates/jolt-transcript/tests/keccak_tests.rs +++ b/crates/jolt-transcript/tests/keccak_tests.rs @@ -1,5 +1,4 @@ //! Tests for KeccakTranscript implementation. -#![cfg(feature = "poseidon")] mod common; diff --git a/crates/jolt-transcript/tests/poseidon_tests.rs b/crates/jolt-transcript/tests/poseidon_tests.rs index 64a9e7557e..0d1e47a125 100644 --- a/crates/jolt-transcript/tests/poseidon_tests.rs +++ b/crates/jolt-transcript/tests/poseidon_tests.rs @@ -1,4 +1,5 @@ //! Tests for PoseidonTranscript implementation. + #![cfg(feature = "poseidon")] mod common; diff --git a/crates/jolt-witness/Cargo.toml b/crates/jolt-witness/Cargo.toml new file mode 100644 index 0000000000..2ec9481490 --- /dev/null +++ b/crates/jolt-witness/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "jolt-witness" +version = "0.1.0" +edition = "2021" +license = "MIT OR Apache-2.0" +description = "Primitive oracle construction kernels for Bolt-generated Jolt code" + +[lints] +workspace = true + +[dependencies] +jolt-field = { path = "../jolt-field" } +jolt-poly = { path = "../jolt-poly" } diff --git a/crates/jolt-witness/src/lib.rs b/crates/jolt-witness/src/lib.rs new file mode 100644 index 0000000000..4f95953936 --- /dev/null +++ b/crates/jolt-witness/src/lib.rs @@ -0,0 +1,1119 @@ +//! Primitive oracle construction kernels for Bolt-generated Jolt code. +//! +//! This crate is intentionally not a runtime/provider abstraction. Generated +//! code calls these kernels after the Bolt lowering pipeline has made oracle +//! generation explicit in IR. + +use jolt_field::Field; +use jolt_poly::EqPolynomial; + +pub const NUM_DENSE_TRACE_COLUMNS: usize = 2; +pub const NUM_ONE_HOT_TRACE_SOURCES: usize = 3; + +/// Per-cycle primitive inputs consumed by Bolt oracle generation. +#[derive(Clone, Copy, Debug)] +pub struct CycleInput { + pub dense: [i128; NUM_DENSE_TRACE_COLUMNS], + pub one_hot: [Option; NUM_ONE_HOT_TRACE_SOURCES], +} + +impl CycleInput { + pub const PADDING: Self = Self { + dense: [0; NUM_DENSE_TRACE_COLUMNS], + one_hot: [Some(0), Some(0), None], + }; +} + +impl Default for CycleInput { + fn default() -> Self { + Self::PADDING + } +} + +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub struct CommitmentTraceSources { + pub rd_inc: Vec, + pub ram_inc: Vec, + pub instruction_keys: Vec>, + pub ram_addresses: Vec>, + pub bytecode_indices: Vec>, +} + +impl CommitmentTraceSources { + pub fn from_cycle_inputs(cycle_inputs: &[CycleInput]) -> Self { + Self { + rd_inc: cycle_inputs.iter().map(|cycle| cycle.dense[0]).collect(), + ram_inc: cycle_inputs.iter().map(|cycle| cycle.dense[1]).collect(), + instruction_keys: one_hot_cycle_column(cycle_inputs, 0), + ram_addresses: one_hot_cycle_column(cycle_inputs, 2), + bytecode_indices: one_hot_cycle_column(cycle_inputs, 1), + } + } +} + +pub fn commitment_trace_sources(cycle_inputs: &[CycleInput]) -> CommitmentTraceSources { + CommitmentTraceSources::from_cycle_inputs(cycle_inputs) +} + +/// Returns a dense trace source by its generated oracle source name. +pub fn dense_cycle_source(cycle_inputs: &[CycleInput], source: &str) -> Vec { + let slot = match source { + "trace.rd_inc" => 0, + "trace.ram_inc" => 1, + _ => unreachable!("unsupported dense source `{source}`"), + }; + cycle_inputs.iter().map(|cycle| cycle.dense[slot]).collect() +} + +/// Returns a one-hot trace source by its generated oracle source name. +pub fn one_hot_cycle_source(cycle_inputs: &[CycleInput], source: &str) -> Vec> { + let slot = match source { + "trace.instruction_keys" => 0, + "trace.bytecode_indices" => 1, + "trace.ram_addresses" => 2, + _ => unreachable!("unsupported one-hot source `{source}`"), + }; + one_hot_cycle_column(cycle_inputs, slot) +} + +/// Maps generated one-hot padding policy names to the corresponding value. +pub fn one_hot_padding_value(padding: &str) -> Option { + match padding { + "zero" => Some(0), + "none" => None, + _ => unreachable!("unsupported padding `{padding}`"), + } +} + +/// Converts an i128 trace column to field elements and pads it to `target_len`. +/// +/// The input is normally trace-length data; commitment domains can be larger +/// than the trace domain, so generated code asks for the final committed length. +pub fn dense_i128_column_to_field(values: &[i128], target_len: usize) -> Vec { + assert!( + values.len() <= target_len, + "dense trace column has {} values, target length is {target_len}", + values.len() + ); + let mut output: Vec = values.iter().map(|&value| F::from_i128(value)).collect(); + output.resize(target_len, F::zero()); + output +} + +/// Pads an optional field-valued oracle to `target_len`. +/// +/// `None` stays `None`; zero-skipping policy is deliberately left to the +/// generated commitment code because skip semantics are protocol metadata. +pub fn optional_field_oracle(values: Option<&[F]>, target_len: usize) -> Option> { + values.map(|values| pad_field_oracle(values, target_len)) +} + +/// Pads a field-valued oracle to `target_len`. +pub fn pad_field_oracle(values: &[F], target_len: usize) -> Vec { + assert!( + values.len() <= target_len, + "field oracle has {} values, target length is {target_len}", + values.len() + ); + let mut output = values.to_vec(); + output.resize(target_len, F::zero()); + output +} + +/// Deterministic placeholder data for optional advice oracles in synthetic tests. +pub fn deterministic_oracle_data(oracle: &str, num_vars: usize) -> Vec { + let seed = oracle.bytes().fold(17u64, |state, byte| { + state.wrapping_mul(131).wrapping_add(byte as u64) + }); + (0..(1usize << num_vars)) + .map(|index| F::from_u64(seed.wrapping_add(index as u64 + 1))) + .collect() +} + +/// Returns synthetic data for non-advice oracles and `None` for optional advice. +pub fn optional_oracle_data(oracle: &str, num_vars: usize) -> Option> { + match oracle { + "UntrustedAdvice" | "TrustedAdvice" => None, + _ => Some(deterministic_oracle_data(oracle, num_vars)), + } +} + +/// Builds sparse per-cycle one-hot chunk indices. +/// +/// The returned vector has one entry per trace cycle. `None` means no one-hot +/// entry is active for that cycle. Chunk `0` is the most significant chunk, +/// matching jolt-core's committed RA decomposition. +pub fn one_hot_chunk_indices( + values: &[Option], + chunk: usize, + num_chunks: usize, + chunk_bits: usize, + trace_len: usize, + padding_value: Option, +) -> Vec> { + assert!( + values.len() <= trace_len, + "one-hot source has {} values, trace length is {trace_len}", + values.len() + ); + assert!( + chunk < num_chunks, + "chunk index {chunk} out of bounds for {num_chunks} chunks" + ); + assert!( + chunk_bits <= u8::BITS as usize, + "chunk_bits must fit in one byte" + ); + assert!( + chunk_bits * num_chunks <= u128::BITS as usize, + "one-hot chunks must fit in u128 source values" + ); + + let chunk_domain = 1usize << chunk_bits; + let shift = chunk_bits * (num_chunks - 1 - chunk); + let mask = (chunk_domain - 1) as u128; + let mut output = Vec::with_capacity(trace_len); + + for cycle in 0..trace_len { + let value = values.get(cycle).copied().flatten().or(padding_value); + output.push(value.map(|value| ((value >> shift) & mask) as u8)); + } + + output +} + +/// Builds one address-major one-hot chunk polynomial. +/// +/// Layout is `output[chunk_value * trace_len + cycle]`. Chunk `0` is the most +/// significant chunk, matching jolt-core's committed RA decomposition. +pub fn one_hot_chunk_address_major( + values: &[Option], + chunk: usize, + num_chunks: usize, + chunk_bits: usize, + trace_len: usize, + padding_value: Option, +) -> Vec { + let indices = one_hot_chunk_indices( + values, + chunk, + num_chunks, + chunk_bits, + trace_len, + padding_value, + ); + one_hot_address_major_from_indices(&indices, chunk_bits) +} + +/// Builds one address-major one-hot chunk polynomial from sparse per-cycle indices. +/// +/// Layout is `output[chunk_value * trace_len + cycle]`. +pub fn one_hot_address_major_from_indices( + indices: &[Option], + chunk_bits: usize, +) -> Vec { + assert!( + chunk_bits < usize::BITS as usize, + "chunk_bits must fit in usize" + ); + + let chunk_domain = 1usize << chunk_bits; + let mut output = vec![F::zero(); chunk_domain * indices.len()]; + + for (cycle, index) in indices.iter().enumerate() { + if let Some(index) = index { + let index = usize::from(*index); + assert!( + index < chunk_domain, + "one-hot index {index} exceeds chunk domain {chunk_domain}" + ); + output[index * indices.len() + cycle] = F::one(); + } + } + + output +} + +/// Builds one cycle-major one-hot chunk polynomial from sparse per-cycle indices. +/// +/// Layout is `output[cycle * chunk_domain + chunk_value]`. +pub fn one_hot_cycle_major_from_indices( + indices: &[Option], + chunk_bits: usize, +) -> Vec { + assert!( + chunk_bits < usize::BITS as usize, + "chunk_bits must fit in usize" + ); + + let chunk_domain = 1usize << chunk_bits; + let mut output = vec![F::zero(); chunk_domain * indices.len()]; + + for (cycle, index) in indices.iter().enumerate() { + if let Some(index) = index { + let index = usize::from(*index); + assert!( + index < chunk_domain, + "one-hot index {index} exceeds chunk domain {chunk_domain}" + ); + output[cycle * chunk_domain + index] = F::one(); + } + } + + output +} + +/// Evaluates one-hot per-cycle indices at an address-chunk point. +/// +/// The returned vector has one field element per cycle. Skipped entries +/// evaluate to zero. +pub fn one_hot_evals_at_chunk_point(indices: &[Option], point: &[F]) -> Vec { + let eq_table = EqPolynomial::::evals(point, None); + indices + .iter() + .map(|index| { + index.map_or(F::zero(), |index| { + let index = usize::from(index); + assert!( + index < eq_table.len(), + "one-hot index {index} exceeds chunk point domain {}", + eq_table.len() + ); + eq_table[index] + }) + }) + .collect() +} + +/// Returns most-significant-first chunk widths for a bitstring split by `chunk_bits`. +/// +/// If the high chunk is partial, it appears first. The result is padded with +/// full-width chunks until it reaches `chunk_count`. +pub fn msb_chunk_bit_widths( + total_bits: usize, + chunk_bits: usize, + chunk_count: usize, +) -> Vec { + assert!(chunk_bits > 0, "chunk_bits must be nonzero"); + let first_chunk_bits = total_bits % chunk_bits; + let mut widths = Vec::with_capacity(chunk_count); + if first_chunk_bits != 0 { + widths.push(first_chunk_bits); + } + while widths.len() < chunk_count { + widths.push(chunk_bits); + } + widths +} + +/// Splits a most-significant-first point into fixed-width chunks. +/// +/// The high chunk is left-padded with zero challenges if the point length is +/// not a multiple of `chunk_bits`. +pub fn msb_point_chunks(point: &[F], chunk_bits: usize) -> Vec> { + assert!(chunk_bits > 0, "chunk_bits must be nonzero"); + let mut padded = Vec::new(); + let remainder = point.len() % chunk_bits; + if remainder != 0 { + padded.resize(chunk_bits - remainder, F::zero()); + } + padded.extend_from_slice(point); + padded + .chunks(chunk_bits) + .map(|chunk| chunk.to_vec()) + .collect() +} + +/// Computes `post - pre` in the field for a `u64` value transition. +pub fn u64_increment(pre: u64, post: u64) -> F { + if post >= pre { + F::from_u64(post - pre) + } else { + -F::from_u64(pre - post) + } +} + +/// Computes a field increment column from `(pre, post)` `u64` transitions. +pub fn u64_increment_column(transitions: impl IntoIterator) -> Vec { + transitions + .into_iter() + .map(|(pre, post)| u64_increment(pre, post)) + .collect() +} + +/// Computes a field increment column where a missing write contributes zero. +pub fn optional_u64_increment_column( + transitions: impl IntoIterator>, +) -> Vec { + transitions + .into_iter() + .map(|transition| transition.map_or_else(F::zero, |(pre, post)| u64_increment(pre, post))) + .collect() +} + +/// Materializes an optional `usize` source column. +pub fn optional_usize_column( + values: impl IntoIterator>, +) -> Vec> { + values.into_iter().collect() +} + +#[derive(Clone, Debug)] +pub struct Stage45SparseTraceWitness { + pub rd_inc: Vec, + pub ram_addresses: Vec>, + pub ram_inc: Vec, + pub rd_write_addresses: Vec>, +} + +pub fn stage4_5_sparse_trace_witness( + register_writes: impl IntoIterator>, + ram_accesses: impl IntoIterator, u64, u64)>, +) -> Stage45SparseTraceWitness { + let mut rd_inc = Vec::new(); + let mut rd_write_addresses = Vec::new(); + for write in register_writes { + if let Some((address, pre_value, post_value)) = write { + rd_inc.push(u64_increment(pre_value, post_value)); + rd_write_addresses.push(Some(address)); + } else { + rd_inc.push(F::zero()); + rd_write_addresses.push(None); + } + } + + let mut ram_addresses = Vec::new(); + let mut ram_inc = Vec::new(); + for (address, read_value, write_value) in ram_accesses { + ram_addresses.push(address); + ram_inc.push(u64_increment(read_value, write_value)); + } + + Stage45SparseTraceWitness { + rd_inc, + ram_addresses, + ram_inc, + rd_write_addresses, + } +} + +/// Evaluates a `u64`-valued multilinear extension at `point`. +pub fn mle_eval_u64(values: &[u64], point: &[F]) -> F { + EqPolynomial::::evals(point, None) + .iter() + .zip(values) + .map(|(&weight, &value)| weight * F::from_u64(value)) + .sum() +} + +/// Builds the Stage 4 `RamValInit` opening from the initial RAM image. +/// +/// Stage 4 consumes this at the same address point as `RamValFinal`. +pub fn stage4_ram_val_init_opening( + initial_ram_state: &[u64], + ram_val_final_point: &[F], +) -> (Vec, F) { + ( + ram_val_final_point.to_vec(), + mle_eval_u64(initial_ram_state, ram_val_final_point), + ) +} + +/// Reverses a challenge point. +pub fn reverse_point(point: &[F]) -> Vec { + point.iter().rev().copied().collect() +} + +/// Returns the last `len` point coordinates in reverse order. +pub fn reversed_suffix(point: &[F], len: usize) -> Vec { + let Some(start) = point.len().checked_sub(len) else { + unreachable!("point is shorter than suffix length {len}"); + }; + point[start..].iter().rev().copied().collect() +} + +/// Normalizes Stage 4 register read/write points to address-major order. +pub fn normalized_stage4_registers_rw_point( + log_t: usize, + register_log_k: usize, + point: &[F], +) -> Vec { + let expected = log_t + register_log_k; + assert_eq!( + point.len(), + expected, + "Stage 4 registers point length mismatch" + ); + let (cycle, address) = point.split_at(log_t); + address + .iter() + .rev() + .copied() + .chain(cycle.iter().rev().copied()) + .collect() +} + +/// Extracts the Stage 5 instruction read-RAF cycle point. +pub fn stage5_instruction_cycle_point( + stage5_point: &[F], + instruction_ra_virtual_d: usize, + ra_virtual_log_k_chunk: usize, + log_t: usize, +) -> Vec { + let address_len = instruction_ra_virtual_d * ra_virtual_log_k_chunk; + let end = address_len + log_t; + assert!( + end <= stage5_point.len(), + "Stage 5 point is shorter than instruction address plus cycle arity" + ); + reverse_point(&stage5_point[address_len..end]) +} + +/// Builds a Stage 5 instruction RA opening point for one virtual address chunk. +pub fn stage5_instruction_ra_point( + stage5_point: &[F], + instruction_ra_virtual_d: usize, + ra_virtual_log_k_chunk: usize, + log_t: usize, + index: usize, +) -> Vec { + let start = index * ra_virtual_log_k_chunk; + let end = start + ra_virtual_log_k_chunk; + assert!( + end <= stage5_point.len(), + "Stage 5 point is shorter than instruction RA chunk {index}" + ); + let mut point = stage5_point[start..end].to_vec(); + point.extend(stage5_instruction_cycle_point( + stage5_point, + instruction_ra_virtual_d, + ra_virtual_log_k_chunk, + log_t, + )); + point +} + +/// Builds the Stage 5 RAM RA opening point from its input address and cycle point. +pub fn stage5_ram_ra_point( + stage5_input_point: &[F], + stage5_point: &[F], + log_k_ram: usize, + log_t: usize, +) -> Vec { + assert!( + stage5_input_point.len() >= log_k_ram, + "Stage 5 RAM RA input point is shorter than RAM address arity" + ); + let mut point = stage5_input_point[..log_k_ram].to_vec(); + point.extend(reversed_suffix(stage5_point, log_t)); + point +} + +/// Builds the Stage 5 RegistersVal opening point from address and cycle points. +pub fn stage5_registers_val_point( + stage5_input_point: &[F], + stage5_point: &[F], + register_log_k: usize, + log_t: usize, +) -> Vec { + assert!( + stage5_input_point.len() >= register_log_k, + "Stage 5 RegistersVal input point is shorter than register address arity" + ); + let mut point = stage5_input_point[..register_log_k].to_vec(); + point.extend(reversed_suffix(stage5_point, log_t)); + point +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage6WitnessParams { + pub trace_len: usize, + pub log_k_chunk: usize, + pub log_k_bytecode: usize, + pub log_k_ram: usize, + pub lookups_ra_virtual_log_k_chunk: usize, + pub instruction_d: usize, + pub instruction_ra_virtual_d: usize, + pub bytecode_d: usize, + pub ram_d: usize, +} + +#[derive(Clone, Copy, Debug)] +pub struct Stage6BytecodeEntry { + pub address: F, + pub imm: F, + pub circuit_flags: [bool; 14], + pub rd: Option, + pub rs1: Option, + pub rs2: Option, + pub lookup_table: Option, + pub is_interleaved: bool, + pub is_branch: bool, + pub left_is_rs1: bool, + pub left_is_pc: bool, + pub right_is_rs2: bool, + pub right_is_imm: bool, + pub is_noop: bool, +} + +#[derive(Clone, Copy, Debug)] +pub struct Stage6OpeningInputRef<'a, F: Field> { + pub symbol: &'a str, + pub point: &'a [F], +} + +#[derive(Clone, Copy, Debug)] +pub struct Stage6WitnessInputs<'a, F: Field> { + pub params: Stage6WitnessParams, + pub cycle_inputs: &'a [CycleInput], + pub opening_inputs: &'a [Stage6OpeningInputRef<'a, F>], +} + +#[derive(Clone, Debug)] +pub struct Stage6WitnessPolynomials { + pub instruction_ra_indices: Vec>>, + pub bytecode_ra_indices: Vec>>, + pub ram_ra_indices: Vec>>, + pub instruction_ra_booleanity: Vec>, + pub bytecode_ra_booleanity: Vec>, + pub ram_ra_booleanity: Vec>, + pub bytecode_ra_read_raf: Vec>, + pub bytecode_ra_read_raf_chunk_lens: Vec, + pub instruction_ra_virtual: Vec>, + pub ram_ra_virtual: Vec>, + pub hamming_weight: Vec, + pub ram_inc: Vec, + pub rd_inc: Vec, +} + +#[derive(Clone, Debug)] +pub struct Stage6WitnessSlices<'a, F: Field> { + pub booleanity_chunks: Vec<&'a [F]>, + pub booleanity_index_chunks: Vec<&'a [Option]>, + pub bytecode_ra_read_raf_chunks: Vec<&'a [F]>, + pub bytecode_ra_read_raf_chunk_lens: Vec, + pub ram_ra_virtual_chunks: Vec<&'a [F]>, + pub instruction_ra_virtual_chunks: Vec<&'a [F]>, + pub instruction_ra_index_chunks: Vec<&'a [Option]>, + pub bytecode_ra_index_chunks: Vec<&'a [Option]>, + pub ram_ra_index_chunks: Vec<&'a [Option]>, +} + +impl Stage6WitnessPolynomials { + /// Returns borrowed slices in the order expected by the generated Stage 6/7 kernels. + pub fn slices(&self) -> Stage6WitnessSlices<'_, F> { + let mut booleanity_chunks = field_slices(&self.instruction_ra_booleanity); + booleanity_chunks.extend(field_slices(&self.bytecode_ra_booleanity)); + booleanity_chunks.extend(field_slices(&self.ram_ra_booleanity)); + + let mut booleanity_index_chunks = index_slices(&self.instruction_ra_indices); + booleanity_index_chunks.extend(index_slices(&self.bytecode_ra_indices)); + booleanity_index_chunks.extend(index_slices(&self.ram_ra_indices)); + + Stage6WitnessSlices { + booleanity_chunks, + booleanity_index_chunks, + bytecode_ra_read_raf_chunks: field_slices(&self.bytecode_ra_read_raf), + bytecode_ra_read_raf_chunk_lens: self.bytecode_ra_read_raf_chunk_lens.clone(), + ram_ra_virtual_chunks: field_slices(&self.ram_ra_virtual), + instruction_ra_virtual_chunks: field_slices(&self.instruction_ra_virtual), + instruction_ra_index_chunks: index_slices(&self.instruction_ra_indices), + bytecode_ra_index_chunks: index_slices(&self.bytecode_ra_indices), + ram_ra_index_chunks: index_slices(&self.ram_ra_indices), + } + } +} + +pub fn stage6_witness_polynomials( + inputs: Stage6WitnessInputs<'_, F>, +) -> Stage6WitnessPolynomials { + let params = inputs.params; + let trace_len = params.trace_len; + assert!( + inputs.cycle_inputs.len() <= trace_len, + "cycle input length {} exceeds trace length {trace_len}", + inputs.cycle_inputs.len() + ); + + let instruction_keys = one_hot_cycle_column(inputs.cycle_inputs, 0); + let bytecode_indices_source = one_hot_cycle_column(inputs.cycle_inputs, 1); + let ram_addresses = one_hot_cycle_column(inputs.cycle_inputs, 2); + + let instruction_indices = (0..params.instruction_d) + .map(|index| { + one_hot_chunk_indices( + &instruction_keys, + index, + params.instruction_d, + params.log_k_chunk, + trace_len, + Some(0), + ) + }) + .collect::>(); + let bytecode_indices = (0..params.bytecode_d) + .map(|index| { + one_hot_chunk_indices( + &bytecode_indices_source, + index, + params.bytecode_d, + params.log_k_chunk, + trace_len, + Some(0), + ) + }) + .collect::>(); + let ram_indices = (0..params.ram_d) + .map(|index| { + one_hot_chunk_indices( + &ram_addresses, + index, + params.ram_d, + params.log_k_chunk, + trace_len, + None, + ) + }) + .collect::>(); + + let bytecode_ra_read_raf_chunk_lens = + msb_chunk_bit_widths(params.log_k_bytecode, params.log_k_chunk, params.bytecode_d); + + let ram_address_chunks = stage6_ram_virtual_address_chunks(params, inputs.opening_inputs); + assert_eq!( + ram_address_chunks.len(), + params.ram_d, + "RAM Stage 6 address chunk count mismatch" + ); + let ram_ra_virtual = ram_indices + .iter() + .zip(&ram_address_chunks) + .map(|(indices, point)| one_hot_evals_at_chunk_point(indices, point)) + .collect::>(); + + let instruction_address_chunks = + stage6_instruction_virtual_address_chunks(params, inputs.opening_inputs); + assert_eq!( + instruction_address_chunks.len(), + params.instruction_d, + "instruction Stage 6 address chunk count mismatch" + ); + let instruction_ra_virtual = instruction_indices + .iter() + .zip(&instruction_address_chunks) + .map(|(indices, point)| one_hot_evals_at_chunk_point(indices, point)) + .collect::>(); + + Stage6WitnessPolynomials { + instruction_ra_indices: instruction_indices, + bytecode_ra_indices: bytecode_indices, + ram_ra_indices: ram_indices, + instruction_ra_booleanity: Vec::new(), + bytecode_ra_booleanity: Vec::new(), + ram_ra_booleanity: Vec::new(), + bytecode_ra_read_raf: Vec::new(), + bytecode_ra_read_raf_chunk_lens, + instruction_ra_virtual, + ram_ra_virtual, + hamming_weight: hamming_weight_from_cycle_inputs(inputs.cycle_inputs, trace_len), + ram_inc: dense_cycle_column_to_field(inputs.cycle_inputs, 1, trace_len), + rd_inc: dense_cycle_column_to_field(inputs.cycle_inputs, 0, trace_len), + } +} + +fn field_slices(values: &[Vec]) -> Vec<&[F]> { + values.iter().map(Vec::as_slice).collect() +} + +fn index_slices(values: &[Vec>]) -> Vec<&[Option]> { + values.iter().map(Vec::as_slice).collect() +} + +fn one_hot_cycle_column(cycle_inputs: &[CycleInput], slot: usize) -> Vec> { + cycle_inputs + .iter() + .map(|cycle| cycle.one_hot[slot]) + .collect() +} + +fn dense_cycle_column_to_field( + cycle_inputs: &[CycleInput], + slot: usize, + trace_len: usize, +) -> Vec { + assert!( + cycle_inputs.len() <= trace_len, + "cycle input length {} exceeds trace length {trace_len}", + cycle_inputs.len() + ); + let mut output = cycle_inputs + .iter() + .map(|cycle| F::from_i128(cycle.dense[slot])) + .collect::>(); + output.resize(trace_len, F::zero()); + output +} + +fn hamming_weight_from_cycle_inputs( + cycle_inputs: &[CycleInput], + trace_len: usize, +) -> Vec { + assert!( + cycle_inputs.len() <= trace_len, + "cycle input length {} exceeds trace length {trace_len}", + cycle_inputs.len() + ); + let mut output = cycle_inputs + .iter() + .map(|cycle| { + if cycle.one_hot[2].is_some() { + F::one() + } else { + F::zero() + } + }) + .collect::>(); + output.resize(trace_len, F::zero()); + output +} + +fn stage6_ram_virtual_address_chunks( + params: Stage6WitnessParams, + opening_inputs: &[Stage6OpeningInputRef<'_, F>], +) -> Vec> { + let point = stage6_opening_point( + opening_inputs, + "stage6.input.stage5.ram_ra_claim_reduction.RamRa", + ); + assert!( + point.len() >= params.log_k_ram, + "RAM RA opening point is shorter than the RAM address arity" + ); + msb_point_chunks(&point[..params.log_k_ram], params.log_k_chunk) +} + +fn stage6_instruction_virtual_address_chunks( + params: Stage6WitnessParams, + opening_inputs: &[Stage6OpeningInputRef<'_, F>], +) -> Vec> { + let mut address = Vec::with_capacity(params.instruction_d * params.log_k_chunk); + for index in 0..params.instruction_ra_virtual_d { + let symbol = format!("stage6.input.stage5.instruction_read_raf.InstructionRa_{index}"); + let point = stage6_opening_point(opening_inputs, &symbol); + assert!( + point.len() >= params.lookups_ra_virtual_log_k_chunk, + "instruction RA opening point is shorter than the virtual address chunk arity" + ); + address.extend_from_slice(&point[..params.lookups_ra_virtual_log_k_chunk]); + } + msb_point_chunks(&address, params.log_k_chunk) +} + +fn stage6_opening_point<'a, F: Field>( + opening_inputs: &'a [Stage6OpeningInputRef<'_, F>], + symbol: &str, +) -> &'a [F] { + let Some(input) = opening_inputs.iter().find(|input| input.symbol == symbol) else { + unreachable!("missing Stage 6 opening input `{symbol}`"); + }; + input.point +} + +#[cfg(test)] +mod tests { + use super::*; + use jolt_field::{Field, Fr}; + + fn fr(value: u64) -> Fr { + Fr::from_u64(value) + } + + #[test] + fn dense_column_converts_and_pads() { + let output = dense_i128_column_to_field::(&[5, -3], 4); + assert_eq!(output.len(), 4); + assert_eq!(output[0], Fr::from_i128(5)); + assert_eq!(output[1], Fr::from_i128(-3)); + assert_eq!(output[2], Fr::from_u64(0)); + assert_eq!(output[3], Fr::from_u64(0)); + } + + #[test] + fn cycle_sources_select_generated_trace_columns() { + let cycle_inputs = [ + CycleInput { + dense: [3, -2], + one_hot: [Some(7), Some(5), None], + }, + CycleInput { + dense: [8, 11], + one_hot: [Some(1), Some(4), Some(9)], + }, + ]; + let sources = commitment_trace_sources(&cycle_inputs); + assert_eq!(sources.rd_inc, vec![3, 8]); + assert_eq!(sources.ram_inc, vec![-2, 11]); + assert_eq!(sources.instruction_keys, vec![Some(7), Some(1)]); + assert_eq!(sources.ram_addresses, vec![None, Some(9)]); + assert_eq!(sources.bytecode_indices, vec![Some(5), Some(4)]); + assert_eq!( + dense_cycle_source(&cycle_inputs, "trace.rd_inc"), + vec![3, 8] + ); + assert_eq!( + dense_cycle_source(&cycle_inputs, "trace.ram_inc"), + vec![-2, 11] + ); + assert_eq!( + one_hot_cycle_source(&cycle_inputs, "trace.instruction_keys"), + vec![Some(7), Some(1)] + ); + assert_eq!( + one_hot_cycle_source(&cycle_inputs, "trace.bytecode_indices"), + vec![Some(5), Some(4)] + ); + assert_eq!( + one_hot_cycle_source(&cycle_inputs, "trace.ram_addresses"), + vec![None, Some(9)] + ); + } + + #[test] + fn increment_columns_compute_signed_field_deltas() { + assert_eq!(u64_increment::(2, 9), Fr::from_u64(7)); + assert_eq!(u64_increment::(9, 2), -Fr::from_u64(7)); + assert_eq!( + u64_increment_column::([(5, 8), (8, 3)]), + vec![Fr::from_u64(3), -Fr::from_u64(5)] + ); + assert_eq!( + optional_u64_increment_column::([Some((5, 8)), None, Some((8, 3))]), + vec![Fr::from_u64(3), Fr::from_u64(0), -Fr::from_u64(5)] + ); + } + + #[test] + fn stage4_5_sparse_trace_witness_groups_sparse_columns() { + let witness = stage4_5_sparse_trace_witness::( + [Some((2, 5, 8)), None, Some((3, 9, 4))], + [(Some(7), 10, 12), (None, 3, 3), (Some(8), 1, 0)], + ); + + assert_eq!(witness.rd_inc, vec![fr(3), fr(0), -fr(5)]); + assert_eq!(witness.rd_write_addresses, vec![Some(2), None, Some(3)]); + assert_eq!(witness.ram_addresses, vec![Some(7), None, Some(8)]); + assert_eq!(witness.ram_inc, vec![fr(2), fr(0), -fr(1)]); + } + + #[test] + fn mle_eval_u64_matches_boolean_hypercube_points() { + let values = [10, 20, 30, 40]; + let point = [Fr::from_u64(1), Fr::from_u64(0)]; + assert_eq!(mle_eval_u64(&values, &point), Fr::from_u64(30)); + } + + #[test] + fn stage4_ram_val_init_opening_uses_final_ram_point() { + let values = [10, 20, 30, 40]; + let point = [Fr::from_u64(1), Fr::from_u64(0)]; + let (opening_point, eval) = stage4_ram_val_init_opening(&values, &point); + + assert_eq!(opening_point, point); + assert_eq!(eval, Fr::from_u64(30)); + } + + #[test] + fn point_helpers_normalize_stage_points() { + let point = [fr(1), fr(2), fr(3), fr(4), fr(5)]; + assert_eq!( + reverse_point(&point), + vec![fr(5), fr(4), fr(3), fr(2), fr(1)] + ); + assert_eq!(reversed_suffix(&point, 3), vec![fr(5), fr(4), fr(3)]); + assert_eq!( + normalized_stage4_registers_rw_point(2, 3, &point), + vec![fr(5), fr(4), fr(3), fr(2), fr(1)] + ); + } + + #[test] + fn stage5_point_helpers_compose_address_and_cycle_points() { + let stage5_point = [fr(10), fr(11), fr(12), fr(13), fr(14), fr(15)]; + let input_point = [fr(20), fr(21), fr(22), fr(23)]; + assert_eq!( + stage5_instruction_cycle_point(&stage5_point, 2, 2, 2), + vec![fr(15), fr(14)] + ); + assert_eq!( + stage5_instruction_ra_point(&stage5_point, 2, 2, 2, 1), + vec![fr(12), fr(13), fr(15), fr(14)] + ); + assert_eq!( + stage5_ram_ra_point(&input_point, &stage5_point, 3, 2), + vec![fr(20), fr(21), fr(22), fr(15), fr(14)] + ); + assert_eq!( + stage5_registers_val_point(&input_point, &stage5_point, 2, 2), + vec![fr(20), fr(21), fr(15), fr(14)] + ); + } + + #[test] + fn one_hot_chunks_are_address_major_and_msb_first() { + let values = [Some(0xABu128), Some(0x12), None]; + let output = one_hot_chunk_address_major::(&values, 0, 2, 4, 4, Some(0)); + + assert_eq!(output.len(), 16 * 4); + assert_eq!(output[0xA * 4], Fr::from_u64(1)); + assert_eq!(output[5], Fr::from_u64(1)); + assert_eq!(output[2], Fr::from_u64(1)); + assert_eq!(output[3], Fr::from_u64(1)); + } + + #[test] + fn one_hot_address_major_from_indices_skips_none_entries() { + let output = one_hot_address_major_from_indices::(&[Some(2), None, Some(1)], 2); + + assert_eq!(output.len(), 12); + assert_eq!(output[2 * 3], Fr::from_u64(1)); + assert_eq!(output[5], Fr::from_u64(1)); + assert_eq!( + output + .iter() + .enumerate() + .filter(|(_, value)| **value == Fr::from_u64(1)) + .map(|(index, _)| index) + .collect::>(), + vec![5, 6] + ); + } + + #[test] + fn one_hot_cycle_major_from_indices_skips_none_entries() { + let output = one_hot_cycle_major_from_indices::(&[Some(2), None, Some(1)], 2); + + assert_eq!(output.len(), 12); + assert_eq!(output[2], Fr::from_u64(1)); + assert_eq!(output[2 * 4 + 1], Fr::from_u64(1)); + assert_eq!( + output + .iter() + .enumerate() + .filter(|(_, value)| **value == Fr::from_u64(1)) + .map(|(index, _)| index) + .collect::>(), + vec![2, 9] + ); + } + + #[test] + fn one_hot_evals_at_chunk_point_evaluates_sparse_indices() { + let point = [Fr::from_u64(5), Fr::from_u64(7)]; + let eq = EqPolynomial::::evals(&point, None); + let output = one_hot_evals_at_chunk_point(&[Some(0), Some(3), None], &point); + + assert_eq!(output, vec![eq[0], eq[3], Fr::from_u64(0)]); + } + + #[test] + fn stage6_witness_slices_preserve_kernel_order() { + let witness = Stage6WitnessPolynomials { + instruction_ra_indices: vec![vec![Some(1)]], + bytecode_ra_indices: vec![vec![Some(2)]], + ram_ra_indices: vec![vec![None]], + instruction_ra_booleanity: vec![vec![fr(10)]], + bytecode_ra_booleanity: vec![vec![fr(20)]], + ram_ra_booleanity: vec![vec![fr(30)]], + bytecode_ra_read_raf: vec![vec![fr(40)]], + bytecode_ra_read_raf_chunk_lens: vec![1], + instruction_ra_virtual: vec![vec![fr(50)]], + ram_ra_virtual: vec![vec![fr(60)]], + hamming_weight: vec![fr(70)], + ram_inc: vec![fr(80)], + rd_inc: vec![fr(90)], + }; + + let slices = witness.slices(); + assert_eq!( + slices.booleanity_chunks, + vec![ + witness.instruction_ra_booleanity[0].as_slice(), + witness.bytecode_ra_booleanity[0].as_slice(), + witness.ram_ra_booleanity[0].as_slice(), + ] + ); + assert_eq!( + slices.booleanity_index_chunks, + vec![ + witness.instruction_ra_indices[0].as_slice(), + witness.bytecode_ra_indices[0].as_slice(), + witness.ram_ra_indices[0].as_slice(), + ] + ); + assert_eq!( + slices.bytecode_ra_read_raf_chunks, + vec![witness.bytecode_ra_read_raf[0].as_slice()] + ); + assert_eq!(slices.bytecode_ra_read_raf_chunk_lens, vec![1]); + assert_eq!( + slices.instruction_ra_index_chunks, + vec![witness.instruction_ra_indices[0].as_slice()] + ); + assert_eq!( + slices.bytecode_ra_index_chunks, + vec![witness.bytecode_ra_indices[0].as_slice()] + ); + assert_eq!( + slices.ram_ra_index_chunks, + vec![witness.ram_ra_indices[0].as_slice()] + ); + } + + #[test] + fn msb_chunk_bit_widths_puts_partial_high_chunk_first() { + assert_eq!(msb_chunk_bit_widths(10, 4, 3), vec![2, 4, 4]); + assert_eq!(msb_chunk_bit_widths(12, 4, 3), vec![4, 4, 4]); + } + + #[test] + fn msb_point_chunks_left_pads_partial_high_chunk() { + let point = [Fr::from_u64(1), Fr::from_u64(2), Fr::from_u64(3)]; + let chunks = msb_point_chunks(&point, 2); + + assert_eq!( + chunks, + vec![ + vec![Fr::from_u64(0), Fr::from_u64(1)], + vec![Fr::from_u64(2), Fr::from_u64(3)] + ] + ); + } + + #[test] + fn one_hot_chunk_indices_are_msb_first_and_padded() { + let values = [Some(0xABu128), Some(0x12), None]; + let output = one_hot_chunk_indices(&values, 0, 2, 4, 4, Some(0)); + + assert_eq!(output, vec![Some(0xA), Some(0x1), Some(0), Some(0)]); + } + + #[test] + fn one_hot_chunk_indices_preserve_skipped_entries() { + let values = [Some(3u128), None]; + let output = one_hot_chunk_indices(&values, 0, 1, 2, 3, None); + + assert_eq!(output, vec![Some(3), None, None]); + } + + #[test] + fn one_hot_none_padding_skips_entries() { + let values = [Some(3u128), None]; + let output = one_hot_chunk_address_major::(&values, 0, 1, 2, 3, None); + + assert_eq!(output[3 * 3], Fr::from_u64(1)); + assert!(output + .iter() + .enumerate() + .all(|(index, value)| index == 9 || *value == Fr::from_u64(0))); + } +} From 70c52cdb88cef49f0defce548768991785b9717d Mon Sep 17 00:00:00 2001 From: Markos Georghiades <53157953+Markos-The-G@users.noreply.github.com> Date: Fri, 8 May 2026 00:11:58 -0400 Subject: [PATCH 04/14] feat(bolt): add Jolt protocol emitter Adds the Bolt compiler/emitter crate and its Jolt protocol lowering, IR, Rust artifact emission, MLIR dialect definitions, templates, and unit tests. This layer intentionally stops before checking in generated role crates or jolt-equivalence wiring. It depends on the jolt-witness/modular-helper layer below it and prepares the source generator used by the generated-role PR above it. Validation: - cargo check -p bolt -q was attempted but is blocked locally by missing llvm-config required by mlir-sys/tblgen. - Previous downstack modular package validation remains: clippy all-targets and nextest for touched primitive crates. --- Cargo.lock | 215 +- Cargo.toml | 2 + crates/bolt/Cargo.toml | 16 + crates/bolt/GENERIC_PROTOCOL_GOAL.md | 228 + crates/bolt/GOAL.md | 395 ++ crates/bolt/JOLT_PROTOCOL_IMPLEMENTATION.md | 74 + crates/bolt/README.md | 114 + crates/bolt/TESTING.md | 203 + crates/bolt/irdl/commit.mlir | 25 + crates/bolt/irdl/compute.mlir | 807 ++++ crates/bolt/irdl/cpu.mlir | 723 +++ crates/bolt/irdl/field.mlir | 67 + crates/bolt/irdl/hash.mlir | 7 + crates/bolt/irdl/party.mlir | 8 + crates/bolt/irdl/pcs.mlir | 89 + crates/bolt/irdl/piop.mlir | 270 ++ crates/bolt/irdl/poly.mlir | 68 + crates/bolt/irdl/protocol.mlir | 19 + crates/bolt/irdl/transcript.mlir | 62 + crates/bolt/src/dialects.rs | 39 + crates/bolt/src/emit/mod.rs | 1 + crates/bolt/src/emit/rust/artifacts.rs | 1653 +++++++ crates/bolt/src/emit/rust/mod.rs | 19 + crates/bolt/src/emit/rust/source.rs | 37 + crates/bolt/src/ir.rs | 160 + crates/bolt/src/lib.rs | 28 + crates/bolt/src/mlir.rs | 292 ++ crates/bolt/src/pass.rs | 316 ++ crates/bolt/src/protocols/jolt/artifacts.rs | 2349 ++++++++++ crates/bolt/src/protocols/jolt/emit/mod.rs | 1 + .../protocols/jolt/emit/rust/commitment.rs | 1744 +++++++ .../bolt/src/protocols/jolt/emit/rust/mod.rs | 27 + .../src/protocols/jolt/emit/rust/stage1.rs | 1653 +++++++ .../src/protocols/jolt/emit/rust/stage2.rs | 2695 +++++++++++ .../src/protocols/jolt/emit/rust/stage3.rs | 2245 +++++++++ .../src/protocols/jolt/emit/rust/stage4.rs | 2487 ++++++++++ .../src/protocols/jolt/emit/rust/stage5.rs | 2489 ++++++++++ .../src/protocols/jolt/emit/rust/stage6.rs | 2655 +++++++++++ .../src/protocols/jolt/emit/rust/stage7.rs | 2529 ++++++++++ .../src/protocols/jolt/emit/rust/stage8.rs | 516 ++ crates/bolt/src/protocols/jolt/mod.rs | 41 + crates/bolt/src/protocols/jolt/oracles.rs | 227 + crates/bolt/src/protocols/jolt/params.rs | 305 ++ .../src/protocols/jolt/phases/commitment.rs | 1663 +++++++ .../src/protocols/jolt/phases/lowering.rs | 641 +++ crates/bolt/src/protocols/jolt/phases/mod.rs | 11 + .../bolt/src/protocols/jolt/phases/stage1.rs | 1723 +++++++ .../bolt/src/protocols/jolt/phases/stage2.rs | 2082 +++++++++ .../bolt/src/protocols/jolt/phases/stage3.rs | 1762 +++++++ .../bolt/src/protocols/jolt/phases/stage4.rs | 1264 +++++ .../bolt/src/protocols/jolt/phases/stage5.rs | 1387 ++++++ .../bolt/src/protocols/jolt/phases/stage6.rs | 2365 ++++++++++ .../bolt/src/protocols/jolt/phases/stage7.rs | 1095 +++++ .../bolt/src/protocols/jolt/phases/stage8.rs | 293 ++ crates/bolt/src/protocols/jolt/validate.rs | 134 + .../jolt/verifier_common.rs.template | 1789 +++++++ crates/bolt/src/protocols/mod.rs | 1 + crates/bolt/src/schema.rs | 1466 ++++++ crates/bolt/tests/commitment_ir.rs | 4148 +++++++++++++++++ crates/bolt/tests/verifier_cleanup.rs | 597 +++ 60 files changed, 50320 insertions(+), 1 deletion(-) create mode 100644 crates/bolt/Cargo.toml create mode 100644 crates/bolt/GENERIC_PROTOCOL_GOAL.md create mode 100644 crates/bolt/GOAL.md create mode 100644 crates/bolt/JOLT_PROTOCOL_IMPLEMENTATION.md create mode 100644 crates/bolt/README.md create mode 100644 crates/bolt/TESTING.md create mode 100644 crates/bolt/irdl/commit.mlir create mode 100644 crates/bolt/irdl/compute.mlir create mode 100644 crates/bolt/irdl/cpu.mlir create mode 100644 crates/bolt/irdl/field.mlir create mode 100644 crates/bolt/irdl/hash.mlir create mode 100644 crates/bolt/irdl/party.mlir create mode 100644 crates/bolt/irdl/pcs.mlir create mode 100644 crates/bolt/irdl/piop.mlir create mode 100644 crates/bolt/irdl/poly.mlir create mode 100644 crates/bolt/irdl/protocol.mlir create mode 100644 crates/bolt/irdl/transcript.mlir create mode 100644 crates/bolt/src/dialects.rs create mode 100644 crates/bolt/src/emit/mod.rs create mode 100644 crates/bolt/src/emit/rust/artifacts.rs create mode 100644 crates/bolt/src/emit/rust/mod.rs create mode 100644 crates/bolt/src/emit/rust/source.rs create mode 100644 crates/bolt/src/ir.rs create mode 100644 crates/bolt/src/lib.rs create mode 100644 crates/bolt/src/mlir.rs create mode 100644 crates/bolt/src/pass.rs create mode 100644 crates/bolt/src/protocols/jolt/artifacts.rs create mode 100644 crates/bolt/src/protocols/jolt/emit/mod.rs create mode 100644 crates/bolt/src/protocols/jolt/emit/rust/commitment.rs create mode 100644 crates/bolt/src/protocols/jolt/emit/rust/mod.rs create mode 100644 crates/bolt/src/protocols/jolt/emit/rust/stage1.rs create mode 100644 crates/bolt/src/protocols/jolt/emit/rust/stage2.rs create mode 100644 crates/bolt/src/protocols/jolt/emit/rust/stage3.rs create mode 100644 crates/bolt/src/protocols/jolt/emit/rust/stage4.rs create mode 100644 crates/bolt/src/protocols/jolt/emit/rust/stage5.rs create mode 100644 crates/bolt/src/protocols/jolt/emit/rust/stage6.rs create mode 100644 crates/bolt/src/protocols/jolt/emit/rust/stage7.rs create mode 100644 crates/bolt/src/protocols/jolt/emit/rust/stage8.rs create mode 100644 crates/bolt/src/protocols/jolt/mod.rs create mode 100644 crates/bolt/src/protocols/jolt/oracles.rs create mode 100644 crates/bolt/src/protocols/jolt/params.rs create mode 100644 crates/bolt/src/protocols/jolt/phases/commitment.rs create mode 100644 crates/bolt/src/protocols/jolt/phases/lowering.rs create mode 100644 crates/bolt/src/protocols/jolt/phases/mod.rs create mode 100644 crates/bolt/src/protocols/jolt/phases/stage1.rs create mode 100644 crates/bolt/src/protocols/jolt/phases/stage2.rs create mode 100644 crates/bolt/src/protocols/jolt/phases/stage3.rs create mode 100644 crates/bolt/src/protocols/jolt/phases/stage4.rs create mode 100644 crates/bolt/src/protocols/jolt/phases/stage5.rs create mode 100644 crates/bolt/src/protocols/jolt/phases/stage6.rs create mode 100644 crates/bolt/src/protocols/jolt/phases/stage7.rs create mode 100644 crates/bolt/src/protocols/jolt/phases/stage8.rs create mode 100644 crates/bolt/src/protocols/jolt/validate.rs create mode 100644 crates/bolt/src/protocols/jolt/verifier_common.rs.template create mode 100644 crates/bolt/src/protocols/mod.rs create mode 100644 crates/bolt/src/schema.rs create mode 100644 crates/bolt/tests/commitment_ir.rs create mode 100644 crates/bolt/tests/verifier_cleanup.rs diff --git a/Cargo.lock b/Cargo.lock index be1f53eb9a..031c79d2dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -954,6 +954,26 @@ dependencies = [ "virtue", ] +[[package]] +name = "bindgen" +version = "0.72.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" +dependencies = [ + "bitflags 2.11.0", + "cexpr", + "clang-sys", + "itertools 0.13.0", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.117", +] + [[package]] name = "bit-set" version = "0.8.0" @@ -1075,6 +1095,13 @@ dependencies = [ "zeroize", ] +[[package]] +name = "bolt" +version = "0.1.0" +dependencies = [ + "melior", +] + [[package]] name = "borsh" version = "1.6.0" @@ -1188,6 +1215,15 @@ dependencies = [ "serde", ] +[[package]] +name = "caseless" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6fd507454086c8edfd769ca6ada439193cdb209c7681712ef6275cccbfe5d8" +dependencies = [ + "unicode-normalization", +] + [[package]] name = "cast" version = "0.3.0" @@ -1206,6 +1242,15 @@ dependencies = [ "shlex", ] +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfg-if" version = "1.0.4" @@ -1259,6 +1304,17 @@ dependencies = [ "half", ] +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "clap" version = "4.6.1" @@ -1347,6 +1403,23 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "comrak" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f07383e7799d964bf7ffa6fc4457d177c54a44614661c7458bb0bd91b108e32" +dependencies = [ + "caseless", + "entities", + "finl_unicode", + "jetscii", + "phf", + "phf_codegen", + "rustc-hash", + "smallvec", + "typed-arena", +] + [[package]] name = "const-hex" version = "1.18.1" @@ -1406,6 +1479,15 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "convert_case" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "affbf0190ed2caf063e3def54ff444b449371d55c58e513a95ab98eca50adb49" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -1746,7 +1828,7 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ - "convert_case", + "convert_case 0.10.0", "proc-macro2", "quote", "rustc_version 0.4.1", @@ -1928,6 +2010,12 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" +[[package]] +name = "entities" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5320ae4c3782150d900b79807611a59a99fc9a1d61d686faafc24b93fc8d7ca" + [[package]] name = "enum-ordinalize" version = "4.3.2" @@ -2117,6 +2205,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "finl_unicode" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9844ddc3a6e533d62bba727eb6c28b5d360921d5175e9ff0f1e621a5c590a4d5" + [[package]] name = "fixed-hash" version = "0.8.0" @@ -2644,6 +2738,12 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" +[[package]] +name = "jetscii" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47f142fe24a9c9944451e8349de0a56af5f3e7226dc46f3ed4d4ecc0b85af75e" + [[package]] name = "jiff" version = "0.2.23" @@ -3220,6 +3320,16 @@ version = "0.2.182" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + [[package]] name = "libm" version = "0.2.16" @@ -3319,6 +3429,32 @@ dependencies = [ "regex-automata", ] +[[package]] +name = "melior" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c388c08773539126c32f2a9c65260695ed9e2b9376164ce8b839826e3085d8d" +dependencies = [ + "melior-macro", + "mlir-sys", +] + +[[package]] +name = "melior-macro" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aac876dfce9f514df46c6d4b7267f1fc513126ddc34dfde11909584fdfc87bd" +dependencies = [ + "comrak", + "convert_case 0.11.0", + "proc-macro2", + "quote", + "regex", + "syn 2.0.117", + "tblgen", + "unindent", +] + [[package]] name = "memchr" version = "2.8.0" @@ -3407,6 +3543,12 @@ name = "mini-template" version = "0.1.0" source = "git+https://github.com/LayerZero-Labs/ZeroOS.git?rev=3b132ce862ba6769a4261d151f69ff32c5f0dc30#3b132ce862ba6769a4261d151f69ff32c5f0dc30" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.8.9" @@ -3417,6 +3559,15 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "mlir-sys" +version = "220.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55f8c5781dc23ebe7456f9e9aaecab9eee9e542f7e9051b95b0a31b1d5d4b61f" +dependencies = [ + "bindgen", +] + [[package]] name = "modinv" version = "0.1.0" @@ -3506,6 +3657,16 @@ dependencies = [ "libc", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "ntapi" version = "0.4.3" @@ -3914,6 +4075,16 @@ dependencies = [ "serde", ] +[[package]] +name = "phf_codegen" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49aa7f9d80421bca176ca8dbfebe668cc7a2684708594ec9f3c0db0805d5d6e1" +dependencies = [ + "phf_generator", + "phf_shared", +] + [[package]] name = "phf_generator" version = "0.13.1" @@ -5586,6 +5757,18 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +[[package]] +name = "tblgen" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15a6768dc51535aeaecbe812e2a792a77cbef10b1c4529e29bea5864a738dc6a" +dependencies = [ + "bindgen", + "cc", + "paste", + "thiserror 2.0.18", +] + [[package]] name = "tempfile" version = "3.27.0" @@ -5713,6 +5896,21 @@ dependencies = [ "serde_json", ] +[[package]] +name = "tinyvec" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "toml_datetime" version = "1.1.1+spec-1.1.0" @@ -6026,6 +6224,15 @@ version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "unicode-normalization" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" +dependencies = [ + "tinyvec", +] + [[package]] name = "unicode-segmentation" version = "1.12.0" @@ -6038,6 +6245,12 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "unindent" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3" + [[package]] name = "unsafe-libyaml" version = "0.2.11" diff --git a/Cargo.toml b/Cargo.toml index 4f1428d30b..d82737b259 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,6 +36,7 @@ members = [ "crates/jolt-riscv", "crates/jolt-transcript", "crates/jolt-witness", + "crates/bolt", "crates/jolt-profiling", "crates/jolt-field", "jolt-core", @@ -385,6 +386,7 @@ jolt-transcript = { path = "./crates/jolt-transcript" } jolt-sumcheck = { path = "./crates/jolt-sumcheck" } jolt-r1cs = { path = "./crates/jolt-r1cs" } jolt-witness = { path = "./crates/jolt-witness" } +bolt = { path = "./crates/bolt" } jolt-riscv = { path = "./crates/jolt-riscv" } jolt-trace = { path = "./crates/jolt-trace" } jolt-lookup-tables = { path = "./crates/jolt-lookup-tables" } diff --git a/crates/bolt/Cargo.toml b/crates/bolt/Cargo.toml new file mode 100644 index 0000000000..31ca735f59 --- /dev/null +++ b/crates/bolt/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "bolt" +version = "0.1.0" +authors = ["Jolt Contributors"] +edition = "2021" +license = "MIT OR Apache-2.0" +description = "Bolt-shaped compiler prototype for the Jolt zkVM" +repository = "https://github.com/a16z/jolt" +keywords = ["SNARK", "compiler", "mlir", "protocol"] +categories = ["cryptography"] + +[lints] +workspace = true + +[dependencies] +melior = "0.27" diff --git a/crates/bolt/GENERIC_PROTOCOL_GOAL.md b/crates/bolt/GENERIC_PROTOCOL_GOAL.md new file mode 100644 index 0000000000..607035f3b3 --- /dev/null +++ b/crates/bolt/GENERIC_PROTOCOL_GOAL.md @@ -0,0 +1,228 @@ +# Bolt Generic Protocol Goal + +Bolt should be a compiler framework for SNARK/PIOP-style protocols, not a +Jolt-shaped compiler with configurable names. Jolt is the first complete +protocol package and the correctness/performance oracle, but generic Bolt +layers must remain reusable for other protocols. + +## Objective + +Refactor the compiler boundaries so generic IRs, passes, validation, and Rust +artifact assembly operate over protocol concepts: + +```text +roles +stages +transcript events +oracles and commitments +claims and relations +sumcheck obligations +opening obligations +proof slots +role-specific execution plans +``` + +Jolt-specific facts should enter only through the Jolt protocol package: + +```text +protocol params +stage ordering +oracle names +relation definitions +proof-slot names +transcript labels +artifact crate names +prover kernel ABI mappings +Jolt-specific evaluation-proof composition +``` + +The result should make adding another protocol a matter of adding a new +`src/protocols//` package plus artifact config and any required prover +kernels, not editing Bolt's generic compiler core. + +## Non-Negotiables + +- Generic Bolt modules must not branch on Jolt stage names, Jolt relation + symbols, or Jolt artifact names. +- Jolt symbols may appear as ordinary MLIR symbol data carried by Jolt-built + modules, but generic passes may only preserve, validate structurally, or emit + that data. +- Generic lowering remains: + +```text +protocol -> concrete -> party -> compute -> cpu -> Rust +``` + +- Rust emission is the final target. Protocol behavior should be represented + in dialect ops or MLIR-derived typed plans before Rust is emitted. +- Verifier emission must remain kernel-free and protocol-auditable. +- Prover kernels are protocol-package implementation details below the + dialect boundary. +- Checked-in generated role crates remain generated artifacts, not + hand-maintained source. + +## Target Source Layout + +Generic compiler modules: + +```text +crates/bolt/src/dialects.rs +crates/bolt/src/ir.rs +crates/bolt/src/mlir.rs +crates/bolt/src/schema/ +crates/bolt/src/pass/ +crates/bolt/src/emit/rust/ +``` + +Jolt protocol package: + +```text +crates/bolt/src/protocols/jolt/ + params.rs + validate.rs + oracles.rs + phases/ + relations/ + emit/ + rust/ + artifacts.rs +``` + +The exact file split can evolve, but ownership should not: generic modules own +compiler mechanics; `protocols/jolt` owns Jolt instantiation facts. + +## Generic IR Criteria + +Generic IR should expose enough structure for passes and emitters to reason +without protocol-specific string matching: + +- `protocol` declares roles, stage boundaries, protocol params, and proof + boundaries. +- `transcript` declares absorb/squeeze events and explicit state threading. +- `piop` declares oracles, claims, sumchecks, relation obligations, opening + claims, opening equalities, and proof slots. +- `pcs` declares commitment, opening, verification, and evaluation-aggregation + obligations over abstract PCS schemes. +- `party` represents role projection without deleting semantic obligations + needed by later validation. +- `compute` represents executable obligations and optional prover kernel hooks. +- `cpu` represents backend-ready execution plans while staying + protocol-agnostic. + +If a generic emitter needs to branch on a string like +`jolt.stage6.booleanity`, the IR has not been lowered into a sufficiently +typed plan. + +## Generic Pass Criteria + +Generic passes may branch on: + +```text +dialect op name +role +phase +declared proof-slot kind +declared relation-plan kind +declared PCS/transcript operation kind +backend target +``` + +Generic passes must not branch on: + +```text +Jolt stage names +Jolt relation symbols +Jolt oracle names +Jolt artifact crate names +Jolt kernel ABI strings +``` + +Jolt-specific lowering is allowed inside `protocols/jolt`, but it should +produce generic dialect ops and typed plans consumed by the shared compiler. + +## Generic Artifact Criteria + +The generic Rust artifact assembler should be driven by `ProtocolArtifactConfig` +and ordered `ProtocolRustArtifact` values: + +- Protocol name, type prefix, transcript label, role crate names, dependencies, + forbidden imports, and type paths are config data. +- Stage modules are emitted from `ProtocolStage` data, not hardcoded enums in + generic artifact code. +- Top-level `prover.rs` and `verifier.rs` are generated from role/stage/proof + plans. +- Protocol-specific proof extensions are represented by explicit extension + config or generic PCS/evaluation IR, not by checks like + `type_prefix == "Jolt"`. +- `jolt-prover` may import verifier-owned proof types; `jolt-verifier` must + never import prover or kernel code. + +## Jolt Quarantine Criteria + +These are the only acceptable homes for Jolt-specific compiler knowledge: + +```text +crates/bolt/src/protocols/jolt/** +crates/bolt/tests/** when the test explicitly targets Jolt +crates/jolt-prover/** +crates/jolt-verifier/** +crates/jolt-kernels/** +crates/jolt-equivalence/** +``` + +Generic Bolt modules should have a hygiene gate rejecting `jolt`, `Jolt`, +`stage6`, `stage7`, `stage8`, and Jolt relation/policy names, with a small +temporary allowlist during migration. + +## Correctness Criteria + +Every genericity cleanup slice must preserve the existing semantic oracles: + +```text +generated role crates still compile +checked-in generated role crates match canonical generation +Bolt prover artifacts are accepted by the generated Bolt verifier +Bolt prover artifacts are accepted by the core oracle for implemented stages +Bolt/core transcript histories match for implemented stages +internal prover/verifier transcript histories match for implemented stages +tampering gates still reject malformed artifacts +generated verifier import boundaries remain intact +verifier CPU IR remains kernel-free +``` + +For pure file moves and namespace refactors, generated output should either be +byte-for-byte unchanged or intentionally regenerated with a clear explanation +of why the generated surface changed. + +## Migration Algorithm + +For each cleanup slice: + +1. Identify the Jolt-specific fact currently living in a generic module. +2. Decide whether it is protocol data, relation semantics, artifact config, or + a prover-kernel implementation detail. +3. Move that fact to `protocols/jolt` or encode it as generic IR/typed plan + data. +4. Keep generic APIs protocol-named (`Protocol*`) and provide Jolt convenience + wrappers only under `protocols::jolt`. +5. Add or tighten a hygiene gate so the leak does not reappear. +6. Regenerate artifacts only through the canonical generator. +7. Run the relevant schema, generation, import, equivalence, and tamper gates. + +Do not hide protocol semantics in opaque Rust helpers to pass the hygiene gate. +If the generic emitter needs new information, add a typed plan field or dialect +operation and validate it. + +## Definition Of Done + +- `crates/bolt/src/lib.rs` exports generic compiler APIs at the root and keeps + Jolt APIs namespaced under `bolt::protocols::jolt`. +- `crates/bolt/src/emit/rust` contains generic Rust backend mechanics only. +- `JoltProtocolStage`, Jolt artifact config, Jolt stage emitters, Jolt relation + mappings, and Jolt eval-proof composition live under `protocols/jolt`. +- Generic artifact assembly can produce role crates for a non-Jolt protocol + fixture using only `ProtocolArtifactConfig` and `ProtocolStage` data. +- Generic passes and validators have automated hygiene tests preventing Jolt + leakage. +- Existing Jolt correctness, transcript, tamper, import, generated-artifact, + and performance gates remain available and green for implemented stages. diff --git a/crates/bolt/GOAL.md b/crates/bolt/GOAL.md new file mode 100644 index 0000000000..4f0aa601ff --- /dev/null +++ b/crates/bolt/GOAL.md @@ -0,0 +1,395 @@ +# Bolt Jolt Verifier Goal + +Bolt's first full-field, non-zk Jolt implementation is semantically complete +enough to move the active goal from stage bring-up to verifier-pipeline +hardening. The next long-haul objective is to make the Bolt-generated Jolt +verifier compact, human-readable, auditable, and security-hardened while +preserving the existing full-`Fr` Jolt semantics. + +## Objective + +Refactor the Bolt-generated Jolt verifier pipeline so the generated verifier is +a small orchestration layer plus declarative verifier plans, backed by reusable +verifier runtime modules. The compiler should continue to own protocol facts +through MLIR and typed plan data; generated Rust should not rediscover Jolt +semantics late through ad hoc string matching or repeated stage-local helper +code. + +Starting baseline: + +```text +generated jolt-verifier: ~21.5k LOC +stage6 + stage7: ~13.2k LOC +verifier.rs: 649 LOC +``` + +Current locked cleanup baseline: + +```text +generated jolt-verifier total: 7,755 LOC +generated verifier surface: 5,966 LOC +shared verifier runtime: 1,789 LOC +stage6 + stage7: 1,669 LOC +verifier.rs: 487 LOC +``` + +Target: + +```text +generated verifier surface: <= 4k-6k LOC +stretch generated surface: <= 2k-3k LOC +verifier.rs orchestration: <= 350-500 LOC +stage6 + stage7 generated surface: <= 2k-3k LOC +shared runtime/helpers: allowed when generic, named, and reviewed +``` + +The goal is to reduce the human-facing generated verifier surface by roughly an +order of magnitude. Shared runtime code may exist, but it must be modular, +boring to audit, and driven by explicit MLIR-derived plan data. + +This verifier cleanup is coupled to the generic protocol cleanup in +`GENERIC_PROTOCOL_GOAL.md`: shrinking the generated verifier should move generic +mechanics into Bolt IR/typed plans and shared runtime, not into Jolt-specific +emitter special cases. + +## Locked Genericity Decisions + +The next cleanup track should make Jolt a quarantined protocol package over +generic Bolt compiler infrastructure: + +- Root `bolt::*` exports should be generic-only. Jolt APIs should be imported + from `bolt::protocols::jolt::*`. +- Jolt-specific emitters are not the long-term target. Quarantine them first so + leakage is explicit, then progressively lift stage emission into a generic + `cpu -> Rust` backend driven by typed MLIR-derived plans. +- Replace the current Jolt evaluation-proof special case with either a generic + protocol extension hook or generic PCS/evaluation IR. Start with the minimal + extension hook if that keeps the cleanup mechanical. +- Add hygiene gates for generic compiler modules, initially targeting + `crates/bolt/src/{schema.rs,pass.rs,emit/rust}`. Any temporary Jolt allowlist + must be explicit and shrink over time. +- Namespace and file-layout refactors should preserve generated + `jolt-prover`/`jolt-verifier` output byte-for-byte unless the change + intentionally updates artifact structure. +- At the end of each goal-mode slice, report which quarantined Jolt emitters are + still genuinely protocol-specific and which are ready to lift into generic + typed-plan emission. + +## Immediate Goal-Mode Slice + +First objective for another agent: + +```text +Quarantine Jolt-specific artifact APIs out of generic Rust artifact assembly +while preserving generated output and all current gates. +``` + +Required steps: + +1. Move `JoltProtocolStage`, `jolt_artifact_config`, `jolt_rust_artifact`, + `assemble_jolt_*`, `write_jolt_generated_crates`, and + `validate_jolt_rust_artifact_imports` out of generic + `crates/bolt/src/emit/rust/artifacts.rs` into a Jolt-owned module such as + `crates/bolt/src/protocols/jolt/artifacts.rs`. +2. Keep `ProtocolArtifactConfig`, `ProtocolStage`, `ProtocolRustArtifact`, + `GeneratedCrate`, `assemble_generated_crates`, `write_generated_crates`, and + `validate_rust_artifact_imports` in the generic artifact layer. +3. Stop re-exporting Jolt APIs from `crates/bolt/src/lib.rs`; update callers in + Bolt tests, `jolt-equivalence`, and perf harnesses to import from + `bolt::protocols::jolt`. +4. Add the first genericity hygiene test that rejects new Jolt protocol strings + in generic compiler modules, using a small documented allowlist only for + migration leftovers. +5. Run focused generation/import gates and confirm checked-in generated role + crates are unchanged unless an intentional artifact-structure change is + documented. + +Acceptance criteria: + +```text +generic artifact assembly has no Jolt stage enum or Jolt artifact config +root bolt exports are generic-only +Jolt artifact helpers are namespaced under protocols::jolt +generated jolt-prover/jolt-verifier are byte-for-byte unchanged, or changes are intentional +genericity hygiene gate exists +existing generated-artifact and verifier-boundary gates pass +``` + +## Non-Negotiables + +- Preserve the current full-field non-zk Jolt protocol path: + `Transcript`. +- `jolt-verifier` must not depend on `jolt-prover`, `jolt-kernels`, + `jolt-core`, `jolt-equivalence`, `jolt-profiling`, or tracer internals. +- Bolt compiler boundaries remain: + `protocol -> concrete -> party -> compute -> cpu -> Rust`. +- Verifier CPU IR must remain kernel-free. Prover kernels are temporary + implementation details below the dialect boundary. +- Jolt semantics should be represented in protocol builders, dialect ops, + validators, lowering passes, or typed verifier plans. The Rust emitter should + not infer protocol meaning from loose strings when a typed enum, attr, op, or + plan field can carry it. +- Generated verifier files should be mostly declarative: + +```rust +pub const STAGE_PLAN: StagePlan = ...; + +pub fn verify_stage(...) -> Result { + runtime::verify_stage(&STAGE_PLAN, ...) +} +``` + +## Target Architecture + +The final verifier shape should read like this: + +```text +crates/jolt-verifier + src/lib.rs + src/verifier.rs + public API + proof shape + stage ordering + error mapping + + src/stages/ + commitment.rs + stage1_outer.rs + stage2.rs + ... + mostly declarative generated plans + + src/runtime/ or shared verifier crate + generic stage verifier + generic field expression evaluator + generic opening-claim machinery + generic sumcheck/eval proof conversion + transcript helpers + typed relation evaluators +``` + +Generated stage files should answer: + +```text +What claims exist? +What expressions are evaluated? +What transcript events happen? +What openings are checked? +What relations are verified? +``` + +Runtime modules should answer: + +```text +How is a field expression plan evaluated? +How is a stage plan verified? +How are opening/eval consistency checks performed? +How are proof records converted into runtime verifier inputs? +``` + +## Main Refactor Tracks + +1. **Verifier runtime extraction** + + Move duplicated stage-local machinery into one runtime: + + ```text + field expression evaluation + opening claim lookup and equality checks + sumcheck driver verification + transcript squeeze/absorb helpers + stage proof conversion + stage plan execution + ``` + +2. **Shared verifier plan types** + + Replace stage-specific copies such as `Stage6FieldExprPlan` and + `Stage7OpeningClaimPlan` with shared plan structs: + + ```text + FieldExprPlan + OpeningClaimPlan + OpeningEqualityPlan + SumcheckClaimPlan + SumcheckDriverPlan + SumcheckEvalPlan + StagePlan + RelationPlan + ``` + +3. **Compact field expression encoding** + + Stage 6 and Stage 7 are bloated by per-expression constants and operand + arrays. Replace those with compact tables or pooled operand slices. + +4. **Typed relation dispatch** + + Replace stringly relation handling with typed plan data where practical: + + ```text + RelationKind::RamReadWrite + RelationKind::InstructionReadRaf + RelationKind::BytecodeReadRaf + RelationKind::Booleanity + RelationKind::HammingBooleanity + RelationKind::RegistersReadWrite + ... + ``` + + Any remaining string dispatch must be explicitly allowlisted and covered by + schema tests. + +5. **Clean top-level verifier API** + + `verifier.rs` should be readable orchestration: proof shape, verifier + inputs, verifier programs, stage ordering, evaluation proof handling, and + clear error mapping. Repeated per-stage proof conversion should disappear. + +## One-Time Hardening Work + +Before large readability refactors, add a durable verifier hardening suite. +The suite should include positive equivalence and negative tamper oracles. + +Verifier tamper cases: + +```text +valid generated proof verifies +core and Bolt verifier accept/reject agree +tampered sumcheck coefficient rejects +tampered sumcheck point rejects +tampered named eval rejects +tampered commitment rejects +missing commitment rejects +missing stage proof rejects +reordered stage proof rejects +stage proof in the wrong slot rejects +wrong transcript state rejects +wrong evaluation proof rejects +missing evaluation setup rejects +missing evaluation proof rejects +extra/missing opening claims reject +opening claims in the wrong order reject +opening equality mismatch rejects +PCS proof mismatch rejects +``` + +MLIR/compiler hardening cases: + +```text +unknown dialects rejected +prover-only ops rejected in verifier pipeline +verifier-only ops rejected in prover pipeline +unthreaded transcript ops rejected +hidden or reordered opening batch claims rejected +unsupported equality modes rejected +duplicate proof slots rejected +invalid point arity rejected +invalid round schedule rejected +invalid relation kind rejected +verifier CPU IR contains no kernel dispatch +generated verifier imports no forbidden crates +``` + +## Concrete Gates + +Readability and LOC gates: + +```text +total generated jolt-verifier LOC trends down +verifier.rs <= 500 LOC, stretch <= 350 +stage6 + stage7 generated LOC <= 3k-5k, stretch <= 2k-3k +no duplicate stage-local generic plan structs +no duplicate stage-local field-expression interpreter +no duplicate stage-local opening equality interpreter +no giant per-expression operand constants after compaction +stage files are mostly declarative plan data +``` + +Security and boundary gates: + +```text +jolt-verifier imports are allowlisted +no jolt-prover dependency from jolt-verifier +no jolt-kernels dependency from jolt-verifier +no jolt-core dependency from jolt-verifier +no prover role ops in verifier MLIR +no kernel attrs in verifier CPU IR +all transcript-producing ops thread transcript state +all opening batches preserve explicit ordered claims +all relation dispatch is typed or allowlisted +``` + +Semantic gates: + +```bash +cargo fmt --check +cargo check -p bolt -p jolt-verifier -p jolt-prover -p jolt-equivalence --quiet +cargo nextest run -p bolt --test verifier_cleanup --no-capture +cargo nextest run -p bolt --test commitment_ir --cargo-quiet +cargo nextest run -p jolt-equivalence --test generated_role_crates --cargo-quiet +cargo nextest run -p jolt-equivalence --test bolt_commitment --no-capture +``` + +Required semantic outcomes: + +```text +core accepts Bolt proof +Bolt verifier accepts Bolt proof +core and Bolt transcript state histories match +core and Bolt observable proof artifacts match +core and Bolt reject equivalent tampered proofs +generated prover/verifier crates stay in sync with artifact rail +``` + +Perf remains a regression guard, not the center of this task. The existing +`sha2-chain` e2e/proving Perfetto traces are useful for confirming cleanup does +not accidentally move prover cost, but the main objective is verifier +readability, simplicity, and security. + +## Iteration Algorithm + +Each cleanup loop should follow the same rule: + +```text +1. Measure current LOC, duplication, imports, and typed-vs-string dispatch. +2. Pick one duplication class or hygiene issue to eliminate. +3. Move generic logic into runtime only if semantics remain explicit in MLIR or + typed plan data. +4. Regenerate checked-in verifier artifacts through the compiler rail. +5. Run hardening, equivalence, import, and schema gates. +6. Keep the change only if readability improves and no oracle weakens. +``` + +Use this scoring function when choosing work: + +```text +score = + LOC reduction ++ fewer duplicate structs/functions ++ fewer string dispatch sites ++ fewer generated helper bodies ++ stronger negative oracles ++ clearer verifier.rs +- semantic opacity introduced into runtime +``` + +## Definition Of Done + +This long-haul cleanup is complete when: + +```text +generated verifier surface is <= 4k-6k LOC +verifier.rs is <= 500 LOC +stage files are mostly declarative plans +generic verifier mechanics live once +Jolt relation semantics are typed and auditable +MLIR verifier pathway has malformed-input rejection tests +tamper suite covers commitments, transcript, stages, openings, evals, and PCS proof +core/Bolt accept/reject equivalence is preserved +generated verifier import boundaries are enforced +``` + +The desired end state is not merely fewer lines. The verifier should be easy to +navigate, easy to audit, and hard for the compiler pipeline to accidentally +weaken. diff --git a/crates/bolt/JOLT_PROTOCOL_IMPLEMENTATION.md b/crates/bolt/JOLT_PROTOCOL_IMPLEMENTATION.md new file mode 100644 index 0000000000..a6034e37f8 --- /dev/null +++ b/crates/bolt/JOLT_PROTOCOL_IMPLEMENTATION.md @@ -0,0 +1,74 @@ +# Jolt Protocol Implementation Notes + +The original stage-by-stage bring-up plan has been completed for the first +full-field, non-zk Jolt-on-Bolt implementation. The active long-haul goal now +lives in `GOAL.md`: make the generated Jolt verifier much smaller, cleaner, +and better hardened. + +This file keeps the durable implementation rules that should continue to guide +that cleanup. + +The companion genericity goal lives in `GENERIC_PROTOCOL_GOAL.md`. It defines +the rule that Jolt is a protocol package over Bolt, not a special case inside +generic IRs, passes, validation, or Rust artifact assembly. + +## Permanent Compiler Rules + +- Protocol facts live in `crates/bolt/src/protocols/jolt` and typed MLIR/plan + structures, not in generated Rust control flow. +- Generic dialects should remain generic. Jolt-only names and parameters may be + ordinary attrs or SSA values carried by the Jolt protocol definition, but + they should not become hidden assumptions in generic lowering code. +- Generic artifact assembly should consume protocol config and ordered stage + artifacts; Jolt artifact names, stage enums, relation mappings, and eval-proof + composition belong under `crates/bolt/src/protocols/jolt`. +- Lowering order remains: + +```text +protocol -> concrete -> party -> compute -> cpu -> Rust +``` + +- Rust emission is the final target. Before emission, behavior should be + represented as dialect ops, validation passes, analyses, rewrites, lowerings, + or typed plan extraction. +- Prover code may use coarse CPU kernels while performance work continues. + Those kernels are below the dialect boundary. +- Verifier code must stay kernel-free and audit-stable. It should use modular + verifier crates and generated plan data, not `jolt-kernels` or `jolt-core`. + +## Verifier Cleanup Algorithm + +For every verifier cleanup iteration: + +1. Measure generated verifier LOC, stage LOC, duplicate plan structs, duplicate + helper functions, forbidden imports, and string-dispatch sites. +2. Pick one duplication class or compiler hygiene issue. +3. Move generic mechanics into shared verifier runtime only when protocol + semantics remain explicit in MLIR-derived typed plan data. +4. Regenerate checked-in `jolt-prover` and `jolt-verifier` artifacts through the + canonical artifact rail. +5. Run schema, import, equivalence, and tamper gates. +6. Keep the change only when generated code is easier to read and no semantic + oracle weakens. + +## Do Not Regress + +- Verifier CPU IR must not contain kernel attrs or prover-only ops. +- Generated verifier Rust must not import `jolt-kernels`, `jolt-core`, + `jolt-prover`, `jolt-equivalence`, `jolt-profiling`, or tracer internals. +- Transcript state must be explicitly threaded through MLIR. +- Opening batches must preserve ordered claim lists. +- Opening equality checks must reject incompatible claim metadata. +- Sumcheck relation dispatch should be typed or explicitly allowlisted. +- Full-field transcript challenges are the intended path: + `Transcript`. + +## Regeneration Rail + +Checked-in generated role crates are not hand-maintained. Regenerate them with: + +```bash +JOLT_UPDATE_GOLDENS=1 cargo nextest run -p bolt generated_jolt_artifacts_have_uniform_crate_layout_and_import_rules --cargo-quiet +``` + +Then run the gates in `TESTING.md`. diff --git a/crates/bolt/README.md b/crates/bolt/README.md new file mode 100644 index 0000000000..19301e32f6 --- /dev/null +++ b/crates/bolt/README.md @@ -0,0 +1,114 @@ +# bolt + +This crate is the Bolt-shaped compiler prototype for the full-field, non-zk +Jolt implementation. `melior::ir::Module` is the IR source of truth; Rust types +provide phase/role guardrails, schema validation, builders, analysis results, +and final Rust emission. + +## Active Goal + +The first Jolt-on-Bolt implementation is semantically complete enough that the +active work is verifier cleanup and hardening, not stage bring-up. See +`GOAL.md` for the long-haul target: + +```text +make the generated jolt-verifier compact, human-readable, auditable, +security-hardened, and driven by explicit MLIR-derived plan data +``` + +`GENERIC_PROTOCOL_GOAL.md` describes the parallel cleanup track that makes Bolt +generic over protocol packages instead of Jolt-shaped. `JOLT_PROTOCOL_IMPLEMENTATION.md` +keeps the durable compiler-boundary rules. `TESTING.md` lists the LOC, +readability, equivalence, import, MLIR, and tamper gates for this cleanup track. + +## Compiler Shape + +Protocol-specific facts live under `src/protocols/`. Generic compiler layers +understand Bolt dialect operations but should not learn Jolt-only protocol +semantics except as ordinary typed attrs, SSA values, or typed plan data carried +by a protocol definition. + +The intended lowering path is: + +```text +protocol -> concrete -> party -> compute -> cpu -> Rust +``` + +The dialect split matters: + +- `protocol`, `piop`, `poly`, `field`, `transcript`, `commit`, and `pcs` model + protocol obligations. +- `party` projects prover/verifier visibility. +- `compute` represents role-specific executable structure while preserving + semantic dataflow. +- `cpu` is the final MLIR target before Rust emission. +- Rust is generated output, not the place where protocol meaning should be + inferred. + +## Verifier Boundary + +The generated verifier must remain audit-stable: + +```text +no jolt-prover dependency +no jolt-kernels dependency +no jolt-core dependency +no jolt-equivalence dependency +no jolt-profiling dependency +no tracer internals +``` + +Verifier CPU IR must stay kernel-free. Prover code may still call coarse +`jolt-kernels` CPU kernels while performance work continues, but those kernels +are below the dialect boundary and must not become verifier infrastructure. + +The cleanup target is for generated verifier modules to become mostly +declarative plan data, with generic mechanics factored into named verifier +runtime modules. + +## Generated Artifacts + +Generated Jolt Rust artifacts are organized as two role crates: + +```text +crates/jolt-prover +crates/jolt-verifier +``` + +The checked-in role crates are generated artifacts, not hand-maintained code. +Regenerate them through the Rust artifact rail with: + +```bash +JOLT_UPDATE_GOLDENS=1 cargo nextest run -p bolt generated_jolt_artifacts_have_uniform_crate_layout_and_import_rules --cargo-quiet +``` + +The generator emits manifests, stage registries, `src/stages/*.rs`, and the +top-level `prover.rs`/`verifier.rs` APIs. `jolt-verifier` owns proof types and +verification. `jolt-prover` may construct verifier-owned proof types, but must +not import verifier stage internals. + +## Local MLIR Toolchain + +The easiest setup path on macOS is: + +```bash +make bolt-dev-setup +source .bolt-dev-env +``` + +The helper installs Homebrew LLVM, Rust components used by CI, and writes the +local environment required by `mlir-sys`. + +On macOS with Homebrew LLVM: + +```bash +brew install llvm +export MLIR_SYS_220_PREFIX=/opt/homebrew/opt/llvm +export PATH="/opt/homebrew/opt/llvm/bin:$PATH" +export SDKROOT="$(xcrun --show-sdk-path)" +export BINDGEN_EXTRA_CLANG_ARGS="-isysroot$(xcrun --show-sdk-path)" +``` + +Do not set `MLIR_SYS_LINK_SHARED=1` with the Homebrew LLVM 22 bottle; it does +not ship `libMLIR-C.dylib`, so `mlir-sys` needs its default static MLIR link +path. diff --git a/crates/bolt/TESTING.md b/crates/bolt/TESTING.md new file mode 100644 index 0000000000..d52f050473 --- /dev/null +++ b/crates/bolt/TESTING.md @@ -0,0 +1,203 @@ +# Jolt-on-Bolt Equivalence Gates + +The first full-field, non-zk Jolt-on-Bolt implementation is in equivalence, +hardening, and perf-gating mode. The active objective is in +`crates/jolt-equivalence/GOAL.md`: keep `jolt-equivalence` as a thin oracle and +gate suite while semantic construction lives in Bolt, generated crates, +`jolt-kernels`, or `jolt-witness`. + +## Fast Local Gates + +Run: + +```bash +cargo fmt --check +cargo check -p bolt -p jolt-verifier -p jolt-prover -p jolt-equivalence --quiet +cargo nextest run -p bolt --test verifier_cleanup --no-capture +cargo nextest run -p bolt --test commitment_ir --cargo-quiet +cargo nextest run -p jolt-equivalence --test generated_role_crates --cargo-quiet +``` + +`commitment_ir` can also materialize ignored MLIR/Rust scratch fixtures for +local inspection: + +```bash +JOLT_UPDATE_GOLDENS=1 cargo nextest run -p bolt --test commitment_ir --cargo-quiet +``` + +These gates cover: + +- MLIR dialect registration and schema validation. +- Concrete transcript threading. +- Prover/verifier party projection. +- `compute` and `cpu` schema validation. +- Prover-only kernel resolution. +- Kernel-free verifier CPU IR. +- Generated Rust compilation. +- Generated role-crate layout and import boundaries. +- Matching generated stage registries. +- Generated verifier LOC, duplication, relation-string, and boundary metrics. + +## Real-Data Equivalence Gate + +Run: + +```bash +cargo nextest run -p jolt-equivalence --test bolt_commitment --no-capture +``` + +This is the main semantic oracle. It should continue to prove: + +- Bolt verifier accepts Bolt proof artifacts on real trace data. +- Core accepts the corresponding Bolt proof path. +- Bolt/core transcript histories match. +- Bolt/core observable proof artifacts match. +- Generated standalone and top-level verifier paths agree. +- Representative tampering is rejected by the generated verifier. + +The `Bolt equivalence` workflow runs the generated role parity and real-data +tamper gates on pull requests. It also has an optional full +`jolt-equivalence` sweep that runs on the nightly schedule, or manually through +`workflow_dispatch` with `include_full_sweep=true`: + +```bash +cargo nextest run -p jolt-equivalence --cargo-quiet +``` + +## Required Hardening Coverage + +The verifier hardening suite should cover these negative cases: + +```text +tampered commitment +missing commitment +tampered sumcheck coefficient +tampered sumcheck point +tampered named eval +missing stage proof +reordered stage proof +stage proof in wrong slot +wrong transcript state +missing opening claim +extra opening claim +opening claims in wrong order +opening equality mismatch +wrong evaluation proof +missing evaluation setup +missing evaluation proof +PCS proof mismatch +``` + +The MLIR/compiler hardening suite should cover: + +```text +unknown dialect rejection +prover-only op rejection in verifier pipeline +verifier-only op rejection in prover pipeline +unthreaded transcript op rejection +hidden/reordered opening batch claim rejection +unsupported equality mode rejection +duplicate proof slot rejection +invalid point arity rejection +invalid round schedule rejection +invalid relation kind rejection +kernel attr rejection in verifier CPU IR +forbidden generated verifier imports +``` + +## LOC And Readability Gates + +Track these metrics before and after each cleanup iteration: + +```text +total generated jolt-verifier LOC +verifier.rs LOC +stage6 + stage7 generated LOC +number of stage-local generic plan structs +number of stage-local helper/interpreter functions +number of field-expression operand constants +number of relation string-dispatch sites +forbidden imports +``` + +Targets: + +```text +generated verifier surface: <= 4k-6k LOC +stretch generated surface: <= 2k-3k LOC +verifier.rs orchestration: <= 350-500 LOC +stage6 + stage7 generated surface: <= 2k-3k LOC +``` + +Do not accept a LOC reduction that hides semantics in opaque runtime code. The +generated surface should shrink because generic mechanics moved into named, +reviewable runtime modules and the remaining generated code became declarative +plan data. + +## Regeneration Gate + +Checked-in generated role crates must stay synchronized with the artifact rail: + +```bash +JOLT_UPDATE_GOLDENS=1 cargo nextest run -p bolt generated_jolt_artifacts_have_uniform_crate_layout_and_import_rules --cargo-quiet +``` + +After regenerating, rerun the fast local gates and the real-data equivalence +gate. + +## Perf Oracle Guard + +New Jolt-on-Bolt changes should preserve a core-vs-Bolt perf oracle that uses +`jolt-profiling` as the shared instrumentation layer. The gate should run the +same program, inputs, trace length, PCS setup size, and transcript mode through: + +```text +core reference path: + setup, prove, verify, proof size, peak RSS + +Bolt generated path: + setup, prove, verify, proof size, peak RSS +``` + +Both paths must emit the same named tracing spans through `jolt-profiling`, at +minimum: + +```text +core.setup +core.prove +core.verify +bolt.setup +bolt.prove +bolt.commitment +bolt.commitment.batch +bolt.commitment.dory_commit +bolt.stage1 ... bolt.stage8 +bolt.evaluate +bolt.evaluate.claims +bolt.evaluate.materialize_joint_polynomial +bolt.evaluate.joint_opening_hint +bolt.evaluate.dory_open +bolt.verify +bolt.verify.evaluation_state +bolt.verify.dory_verify +``` + +The checked-in CI smoke programs are: + +```text +PR gate: bolt_sha2_chain_2_16_core_vs_bolt_perf_oracle +PR gate: bolt_sha2_chain_2_20_core_vs_bolt_perf_oracle +``` + +Both tests live in `jolt-equivalence/tests/bolt_perf.rs` because they reuse the +real semantic oracle fixture and pass paired `PerfMetrics` into +`jolt-profiling`'s `check_core_vs_bolt_gate`. The workflow sets +`JOLT_BOLT_PERF_TRACE=1` so the same run writes Perfetto JSON traces under +`benchmark-runs/perfetto_traces/`. + +To run them locally after `source .bolt-dev-env`: + +```bash +JOLT_BOLT_PERF_TRACE=1 cargo nextest run -p jolt-equivalence --test bolt_perf --release --cargo-quiet --run-ignored only --no-capture bolt_sha2_chain_2_16_core_vs_bolt_perf_oracle +JOLT_BOLT_PERF_TRACE=1 cargo nextest run -p jolt-equivalence --test bolt_perf --release --cargo-quiet --run-ignored only --no-capture bolt_sha2_chain_2_20_core_vs_bolt_perf_oracle +``` diff --git a/crates/bolt/irdl/commit.mlir b/crates/bolt/irdl/commit.mlir new file mode 100644 index 0000000000..b759683bd2 --- /dev/null +++ b/crates/bolt/irdl/commit.mlir @@ -0,0 +1,25 @@ +irdl.dialect @commit { + irdl.type @artifact + irdl.operation @publish_batch { + %artifact_type = irdl.parametric @commit::@artifact<> + %sym = irdl.any + %oracle_family = irdl.any + %label = irdl.any + irdl.attributes {"sym_name" = %sym, "oracle_family" = %oracle_family, "label" = %label} + irdl.results(artifact: %artifact_type) + } + irdl.operation @publish_optional { + %artifact_type = irdl.parametric @commit::@artifact<> + %sym = irdl.any + %oracle = irdl.any + %label = irdl.any + %skip_policy = irdl.any + irdl.attributes { + "sym_name" = %sym, + "oracle" = %oracle, + "label" = %label, + "skip_policy" = %skip_policy + } + irdl.results(artifact: %artifact_type) + } +} diff --git a/crates/bolt/irdl/compute.mlir b/crates/bolt/irdl/compute.mlir new file mode 100644 index 0000000000..60c01c9eaa --- /dev/null +++ b/crates/bolt/irdl/compute.mlir @@ -0,0 +1,807 @@ +irdl.dialect @compute { + irdl.type @commitment_artifact + irdl.type @transcript_state + irdl.type @oracle_buffer + irdl.type @oracle_family + irdl.type @field_value + irdl.type @point + irdl.type @sumcheck_claim_type + irdl.type @sumcheck_batch_type + irdl.type @sumcheck_result_type + irdl.type @sumcheck_proof_type + irdl.type @opening_claim_type + irdl.type @opening_batch_type + irdl.type @opening_proof_type + + irdl.operation @params { + %sym = irdl.any + %field = irdl.any + %pcs = irdl.any + %transcript = irdl.any + irdl.attributes {"sym_name" = %sym, "field" = %field, "pcs" = %pcs, "transcript" = %transcript} + } + irdl.operation @function { + %sym = irdl.any + %source = irdl.any + irdl.attributes {"sym_name" = %sym, "source" = %source} + } + irdl.operation @relation { + %sym = irdl.any + %kind = irdl.any + %domain = irdl.any + %num_rounds = irdl.any + %degree = irdl.any + %output_count = irdl.any + irdl.attributes { + "sym_name" = %sym, + "kind" = %kind, + "domain" = %domain, + "num_rounds" = %num_rounds, + "degree" = %degree, + "output_count" = %output_count + } + } + irdl.operation @kernel { + %sym = irdl.any + %relation = irdl.any + %kind = irdl.any + %backend = irdl.any + %abi = irdl.any + irdl.attributes { + "sym_name" = %sym, + "relation" = %relation, + "kind" = %kind, + "backend" = %backend, + "abi" = %abi + } + } + irdl.operation @oracle_dense_trace { + %buffer = irdl.parametric @compute::@oracle_buffer<> + %sym = irdl.any + %oracle = irdl.any + %source = irdl.any + %domain = irdl.any + %num_vars = irdl.any + %padding = irdl.any + irdl.attributes { + "sym_name" = %sym, + "oracle" = %oracle, + "source" = %source, + "domain" = %domain, + "num_vars" = %num_vars, + "padding" = %padding + } + irdl.results(buffer: %buffer) + } + irdl.operation @oracle_one_hot_chunk { + %buffer = irdl.parametric @compute::@oracle_buffer<> + %sym = irdl.any + %oracle = irdl.any + %source = irdl.any + %domain = irdl.any + %num_vars = irdl.any + %trace_num_vars = irdl.any + %chunk = irdl.any + %num_chunks = irdl.any + %chunk_bits = irdl.any + %padding = irdl.any + %layout = irdl.any + irdl.attributes { + "sym_name" = %sym, + "oracle" = %oracle, + "source" = %source, + "domain" = %domain, + "num_vars" = %num_vars, + "trace_num_vars" = %trace_num_vars, + "chunk" = %chunk, + "num_chunks" = %num_chunks, + "chunk_bits" = %chunk_bits, + "padding" = %padding, + "layout" = %layout + } + irdl.results(buffer: %buffer) + } + irdl.operation @oracle_optional_advice { + %buffer = irdl.parametric @compute::@oracle_buffer<> + %sym = irdl.any + %oracle = irdl.any + %source = irdl.any + %domain = irdl.any + %num_vars = irdl.any + %skip_policy = irdl.any + irdl.attributes { + "sym_name" = %sym, + "oracle" = %oracle, + "source" = %source, + "domain" = %domain, + "num_vars" = %num_vars, + "skip_policy" = %skip_policy + } + irdl.results(buffer: %buffer) + } + irdl.operation @oracle_ref { + %buffer = irdl.parametric @compute::@oracle_buffer<> + %sym = irdl.any + %oracle = irdl.any + %domain = irdl.any + %num_vars = irdl.any + irdl.attributes {"sym_name" = %sym, "oracle" = %oracle, "domain" = %domain, "num_vars" = %num_vars} + irdl.results(buffer: %buffer) + } + irdl.operation @oracle_family_init { + %family_type = irdl.parametric @compute::@oracle_family<> + %sym = irdl.any + %family = irdl.any + %count = irdl.any + irdl.attributes {"sym_name" = %sym, "family" = %family, "count" = %count} + irdl.results(family: %family_type) + } + irdl.operation @oracle_family_append { + %family_type = irdl.parametric @compute::@oracle_family<> + %buffer = irdl.parametric @compute::@oracle_buffer<> + %sym = irdl.any + %family = irdl.any + %oracle = irdl.any + %index = irdl.any + irdl.attributes {"sym_name" = %sym, "family" = %family, "oracle" = %oracle, "index" = %index} + irdl.operands(input: %family_type, oracle_buffer: %buffer) + irdl.results(output: %family_type) + } + irdl.operation @pcs_commit_batch { + %artifact_type = irdl.parametric @compute::@commitment_artifact<> + %family_type = irdl.parametric @compute::@oracle_family<> + %sym = irdl.any + %artifact = irdl.any + %pcs = irdl.any + %oracle_family = irdl.any + %ordered_oracles = irdl.any + %label = irdl.any + %domain = irdl.any + %num_vars = irdl.any + %count = irdl.any + irdl.attributes { + "sym_name" = %sym, + "artifact" = %artifact, + "pcs" = %pcs, + "oracle_family" = %oracle_family, + "ordered_oracles" = %ordered_oracles, + "label" = %label, + "domain" = %domain, + "num_vars" = %num_vars, + "count" = %count + } + irdl.operands(oracles: %family_type) + irdl.results(artifact: %artifact_type) + } + irdl.operation @pcs_commit_optional { + %artifact_type = irdl.parametric @compute::@commitment_artifact<> + %buffer = irdl.parametric @compute::@oracle_buffer<> + %sym = irdl.any + %artifact = irdl.any + %pcs = irdl.any + %oracle = irdl.any + %label = irdl.any + %domain = irdl.any + %num_vars = irdl.any + %skip_policy = irdl.any + irdl.attributes { + "sym_name" = %sym, + "artifact" = %artifact, + "pcs" = %pcs, + "oracle" = %oracle, + "label" = %label, + "domain" = %domain, + "num_vars" = %num_vars, + "skip_policy" = %skip_policy + } + irdl.operands(oracle_buffer: %buffer) + irdl.results(artifact: %artifact_type) + } + irdl.operation @pcs_receive_batch { + %artifact_type = irdl.parametric @compute::@commitment_artifact<> + %family_type = irdl.parametric @compute::@oracle_family<> + %sym = irdl.any + %artifact = irdl.any + %pcs = irdl.any + %oracle_family = irdl.any + %ordered_oracles = irdl.any + %label = irdl.any + %domain = irdl.any + %num_vars = irdl.any + %count = irdl.any + irdl.attributes { + "sym_name" = %sym, + "artifact" = %artifact, + "pcs" = %pcs, + "oracle_family" = %oracle_family, + "ordered_oracles" = %ordered_oracles, + "label" = %label, + "domain" = %domain, + "num_vars" = %num_vars, + "count" = %count + } + irdl.operands(oracles: %family_type) + irdl.results(artifact: %artifact_type) + } + irdl.operation @pcs_receive_optional { + %artifact_type = irdl.parametric @compute::@commitment_artifact<> + %buffer = irdl.parametric @compute::@oracle_buffer<> + %sym = irdl.any + %artifact = irdl.any + %pcs = irdl.any + %oracle = irdl.any + %label = irdl.any + %domain = irdl.any + %num_vars = irdl.any + %skip_policy = irdl.any + irdl.attributes { + "sym_name" = %sym, + "artifact" = %artifact, + "pcs" = %pcs, + "oracle" = %oracle, + "label" = %label, + "domain" = %domain, + "num_vars" = %num_vars, + "skip_policy" = %skip_policy + } + irdl.operands(oracle_buffer: %buffer) + irdl.results(artifact: %artifact_type) + } + irdl.operation @transcript_init { + %state = irdl.parametric @compute::@transcript_state<> + %sym = irdl.any + %scheme = irdl.any + irdl.attributes {"sym_name" = %sym, "scheme" = %scheme} + irdl.results(state: %state) + } + irdl.operation @transcript_absorb { + %state = irdl.parametric @compute::@transcript_state<> + %artifact = irdl.parametric @compute::@commitment_artifact<> + %sym = irdl.any + %label = irdl.any + %optional = irdl.any + irdl.attributes { + "sym_name" = %sym, + "label" = %label, + "optional" = %optional + } + irdl.operands(input: %state, artifact: %artifact) + irdl.results(output: %state) + } + irdl.operation @transcript_absorb_bytes { + %state = irdl.parametric @compute::@transcript_state<> + %sym = irdl.any + %label = irdl.any + %payload = irdl.any + irdl.attributes { + "sym_name" = %sym, + "label" = %label, + "payload" = %payload + } + irdl.operands(input: %state) + irdl.results(output: %state) + } + irdl.operation @transcript_squeeze { + %state = irdl.parametric @compute::@transcript_state<> + %challenge = irdl.any + %sym = irdl.any + %label = irdl.any + %kind = irdl.any + %count = irdl.any + irdl.attributes { + "sym_name" = %sym, + "label" = %label, + "kind" = %kind, + "count" = %count + } + irdl.operands(input: %state) + irdl.results(output: %state, challenge: %challenge) + } + irdl.operation @opening_input { + %point = irdl.parametric @compute::@point<> + %eval = irdl.parametric @compute::@field_value<> + %claim = irdl.parametric @compute::@opening_claim_type<> + %sym = irdl.any + %source_stage = irdl.any + %source_claim = irdl.any + %oracle = irdl.any + %domain = irdl.any + %point_arity = irdl.any + %claim_kind = irdl.any + irdl.attributes { + "sym_name" = %sym, + "source_stage" = %source_stage, + "source_claim" = %source_claim, + "oracle" = %oracle, + "domain" = %domain, + "point_arity" = %point_arity, + "claim_kind" = %claim_kind + } + irdl.results(point: %point, eval: %eval, claim: %claim) + } + irdl.operation @point_slice { + %input = irdl.parametric @compute::@point<> + %output = irdl.parametric @compute::@point<> + %sym = irdl.any + %source = irdl.any + %offset = irdl.any + %length = irdl.any + irdl.attributes { + "sym_name" = %sym, + "source" = %source, + "offset" = %offset, + "length" = %length + } + irdl.operands(input: %input) + irdl.results(output: %output) + } + irdl.operation @point_zero { + %output = irdl.parametric @compute::@point<> + %sym = irdl.any + %field = irdl.any + %arity = irdl.any + irdl.attributes { + "sym_name" = %sym, + "field" = %field, + "arity" = %arity + } + irdl.results(output: %output) + } + irdl.operation @point_concat { + %input = irdl.parametric @compute::@point<> + %output = irdl.parametric @compute::@point<> + %sym = irdl.any + %layout = irdl.any + %arity = irdl.any + irdl.attributes { + "sym_name" = %sym, + "layout" = %layout, + "arity" = %arity + } + irdl.operands(inputs: variadic %input) + irdl.results(output: %output) + } + irdl.operation @field_const { + %value_type = irdl.parametric @compute::@field_value<> + %sym = irdl.any + %field = irdl.any + %value = irdl.any + irdl.attributes {"sym_name" = %sym, "field" = %field, "value" = %value} + irdl.results(value: %value_type) + } + irdl.operation @field_zero { + %value_type = irdl.parametric @compute::@field_value<> + %sym = irdl.any + %field = irdl.any + irdl.attributes {"sym_name" = %sym, "field" = %field} + irdl.results(value: %value_type) + } + irdl.operation @field_one { + %value_type = irdl.parametric @compute::@field_value<> + %sym = irdl.any + %field = irdl.any + irdl.attributes {"sym_name" = %sym, "field" = %field} + irdl.results(value: %value_type) + } + irdl.operation @field_add { + %value_type = irdl.parametric @compute::@field_value<> + %sym = irdl.any + irdl.attributes {"sym_name" = %sym} + irdl.operands(lhs: %value_type, rhs: %value_type) + irdl.results(value: %value_type) + } + irdl.operation @field_sub { + %value_type = irdl.parametric @compute::@field_value<> + %sym = irdl.any + irdl.attributes {"sym_name" = %sym} + irdl.operands(lhs: %value_type, rhs: %value_type) + irdl.results(value: %value_type) + } + irdl.operation @field_neg { + %value_type = irdl.parametric @compute::@field_value<> + %sym = irdl.any + irdl.attributes {"sym_name" = %sym} + irdl.operands(input: %value_type) + irdl.results(value: %value_type) + } + irdl.operation @field_mul { + %value_type = irdl.parametric @compute::@field_value<> + %sym = irdl.any + irdl.attributes {"sym_name" = %sym} + irdl.operands(lhs: %value_type, rhs: %value_type) + irdl.results(value: %value_type) + } + irdl.operation @field_pow { + %value_type = irdl.parametric @compute::@field_value<> + %sym = irdl.any + %exponent = irdl.any + irdl.attributes {"sym_name" = %sym, "exponent" = %exponent} + irdl.operands(input: %value_type) + irdl.results(value: %value_type) + } + irdl.operation @poly_lagrange_basis_eval { + %value_type = irdl.parametric @compute::@field_value<> + %sym = irdl.any + %domain_start = irdl.any + %domain_size = irdl.any + %index = irdl.any + irdl.attributes { + "sym_name" = %sym, + "domain_start" = %domain_start, + "domain_size" = %domain_size, + "index" = %index + } + irdl.operands(point: %value_type) + irdl.results(value: %value_type) + } + irdl.operation @sumcheck_claim { + %input_claim = irdl.parametric @compute::@field_value<> + %opening_claim = irdl.parametric @compute::@opening_claim_type<> + %claim_type = irdl.parametric @compute::@sumcheck_claim_type<> + %sym = irdl.any + %stage = irdl.any + %domain = irdl.any + %num_rounds = irdl.any + %degree = irdl.any + %claim = irdl.any + %relation = irdl.any + irdl.attributes { + "sym_name" = %sym, + "stage" = %stage, + "domain" = %domain, + "num_rounds" = %num_rounds, + "degree" = %degree, + "claim" = %claim, + "relation" = %relation + } + irdl.operands(input_claim: %input_claim, inputs: variadic %opening_claim) + irdl.results(claim: %claim_type) + } + irdl.operation @sumcheck_kernel_claim { + %input_claim = irdl.parametric @compute::@field_value<> + %opening_claim = irdl.parametric @compute::@opening_claim_type<> + %claim_type = irdl.parametric @compute::@sumcheck_claim_type<> + %sym = irdl.any + %stage = irdl.any + %domain = irdl.any + %num_rounds = irdl.any + %degree = irdl.any + %claim = irdl.any + %kernel = irdl.any + irdl.attributes { + "sym_name" = %sym, + "stage" = %stage, + "domain" = %domain, + "num_rounds" = %num_rounds, + "degree" = %degree, + "claim" = %claim, + "kernel" = %kernel + } + irdl.operands(input_claim: %input_claim, inputs: variadic %opening_claim) + irdl.results(claim: %claim_type) + } + irdl.operation @sumcheck_verify_claim { + %input_claim = irdl.parametric @compute::@field_value<> + %opening_claim = irdl.parametric @compute::@opening_claim_type<> + %claim_type = irdl.parametric @compute::@sumcheck_claim_type<> + %sym = irdl.any + %stage = irdl.any + %domain = irdl.any + %num_rounds = irdl.any + %degree = irdl.any + %claim = irdl.any + %relation = irdl.any + irdl.attributes { + "sym_name" = %sym, + "stage" = %stage, + "domain" = %domain, + "num_rounds" = %num_rounds, + "degree" = %degree, + "claim" = %claim, + "relation" = %relation + } + irdl.operands(input_claim: %input_claim, inputs: variadic %opening_claim) + irdl.results(claim: %claim_type) + } + irdl.operation @sumcheck_batch { + %claim_type = irdl.parametric @compute::@sumcheck_claim_type<> + %batch_type = irdl.parametric @compute::@sumcheck_batch_type<> + %sym = irdl.any + %stage = irdl.any + %proof_slot = irdl.any + %policy = irdl.any + %count = irdl.any + %ordered_claims = irdl.any + %claim_label = irdl.any + %round_label = irdl.any + %round_schedule = irdl.any + irdl.attributes { + "sym_name" = %sym, + "stage" = %stage, + "proof_slot" = %proof_slot, + "policy" = %policy, + "count" = %count, + "ordered_claims" = %ordered_claims, + "claim_label" = %claim_label, + "round_label" = %round_label, + "round_schedule" = %round_schedule + } + irdl.operands(claims: variadic %claim_type) + irdl.results(batch: %batch_type) + } + irdl.operation @sumcheck_driver { + %state = irdl.parametric @compute::@transcript_state<> + %batch_type = irdl.parametric @compute::@sumcheck_batch_type<> + %point = irdl.parametric @compute::@point<> + %result = irdl.parametric @compute::@sumcheck_result_type<> + %proof = irdl.parametric @compute::@sumcheck_proof_type<> + %sym = irdl.any + %stage = irdl.any + %proof_slot = irdl.any + %relation = irdl.any + %policy = irdl.any + %round_schedule = irdl.any + %claim_label = irdl.any + %round_label = irdl.any + %num_rounds = irdl.any + %degree = irdl.any + irdl.attributes { + "sym_name" = %sym, + "stage" = %stage, + "proof_slot" = %proof_slot, + "relation" = %relation, + "policy" = %policy, + "round_schedule" = %round_schedule, + "claim_label" = %claim_label, + "round_label" = %round_label, + "num_rounds" = %num_rounds, + "degree" = %degree + } + irdl.operands(input: %state, batch: %batch_type) + irdl.results(output: %state, point: %point, result: %result, proof: %proof) + } + irdl.operation @sumcheck_kernel_driver { + %state = irdl.parametric @compute::@transcript_state<> + %batch_type = irdl.parametric @compute::@sumcheck_batch_type<> + %point = irdl.parametric @compute::@point<> + %result = irdl.parametric @compute::@sumcheck_result_type<> + %proof = irdl.parametric @compute::@sumcheck_proof_type<> + %sym = irdl.any + %stage = irdl.any + %proof_slot = irdl.any + %kernel = irdl.any + %policy = irdl.any + %round_schedule = irdl.any + %claim_label = irdl.any + %round_label = irdl.any + %num_rounds = irdl.any + %degree = irdl.any + irdl.attributes { + "sym_name" = %sym, + "stage" = %stage, + "proof_slot" = %proof_slot, + "kernel" = %kernel, + "policy" = %policy, + "round_schedule" = %round_schedule, + "claim_label" = %claim_label, + "round_label" = %round_label, + "num_rounds" = %num_rounds, + "degree" = %degree + } + irdl.operands(input: %state, batch: %batch_type) + irdl.results(output: %state, point: %point, result: %result, proof: %proof) + } + irdl.operation @sumcheck_verify { + %state = irdl.parametric @compute::@transcript_state<> + %batch_type = irdl.parametric @compute::@sumcheck_batch_type<> + %point = irdl.parametric @compute::@point<> + %result = irdl.parametric @compute::@sumcheck_result_type<> + %proof = irdl.parametric @compute::@sumcheck_proof_type<> + %sym = irdl.any + %stage = irdl.any + %proof_slot = irdl.any + %relation = irdl.any + %policy = irdl.any + %round_schedule = irdl.any + %claim_label = irdl.any + %round_label = irdl.any + %num_rounds = irdl.any + %degree = irdl.any + irdl.attributes { + "sym_name" = %sym, + "stage" = %stage, + "proof_slot" = %proof_slot, + "relation" = %relation, + "policy" = %policy, + "round_schedule" = %round_schedule, + "claim_label" = %claim_label, + "round_label" = %round_label, + "num_rounds" = %num_rounds, + "degree" = %degree + } + irdl.operands(input: %state, batch: %batch_type) + irdl.results(output: %state, point: %point, result: %result, proof: %proof) + } + irdl.operation @sumcheck_eval { + %result = irdl.parametric @compute::@sumcheck_result_type<> + %eval = irdl.parametric @compute::@field_value<> + %sym = irdl.any + %source = irdl.any + %name = irdl.any + %index = irdl.any + %oracle = irdl.any + irdl.attributes { + "sym_name" = %sym, + "source" = %source, + "name" = %name, + "index" = %index, + "oracle" = %oracle + } + irdl.operands(result: %result) + irdl.results(eval: %eval) + } + irdl.operation @sumcheck_instance_result { + %input_point = irdl.parametric @compute::@point<> + %output_point = irdl.parametric @compute::@point<> + %input_result = irdl.parametric @compute::@sumcheck_result_type<> + %output_result = irdl.parametric @compute::@sumcheck_result_type<> + %sym = irdl.any + %source = irdl.any + %claim = irdl.any + %relation = irdl.any + %index = irdl.any + %point_arity = irdl.any + %num_rounds = irdl.any + %round_offset = irdl.any + %point_order = irdl.any + %degree = irdl.any + irdl.attributes { + "sym_name" = %sym, + "source" = %source, + "claim" = %claim, + "relation" = %relation, + "index" = %index, + "point_arity" = %point_arity, + "num_rounds" = %num_rounds, + "round_offset" = %round_offset, + "point_order" = %point_order, + "degree" = %degree + } + irdl.operands(input_point: %input_point, input_result: %input_result) + irdl.results(instance_point: %output_point, instance_result: %output_result) + } + irdl.operation @opening_claim { + %point = irdl.parametric @compute::@point<> + %eval = irdl.parametric @compute::@field_value<> + %claim = irdl.parametric @compute::@opening_claim_type<> + %sym = irdl.any + %oracle = irdl.any + %domain = irdl.any + %point_arity = irdl.any + %claim_kind = irdl.any + irdl.attributes { + "sym_name" = %sym, + "oracle" = %oracle, + "domain" = %domain, + "point_arity" = %point_arity, + "claim_kind" = %claim_kind + } + irdl.operands(point: %point, eval: %eval) + irdl.results(claim: %claim) + } + irdl.operation @opening_claim_equal { + %claim = irdl.parametric @compute::@opening_claim_type<> + %sym = irdl.any + %mode = irdl.any + irdl.attributes { + "sym_name" = %sym, + "mode" = %mode + } + irdl.operands(left: %claim, right: %claim) + } + irdl.operation @opening_batch { + %claim = irdl.parametric @compute::@opening_claim_type<> + %batch = irdl.parametric @compute::@opening_batch_type<> + %sym = irdl.any + %stage = irdl.any + %proof_slot = irdl.any + %policy = irdl.any + %count = irdl.any + %ordered_claims = irdl.any + irdl.attributes { + "sym_name" = %sym, + "stage" = %stage, + "proof_slot" = %proof_slot, + "policy" = %policy, + "count" = %count, + "ordered_claims" = %ordered_claims + } + irdl.operands(claims: variadic %claim) + irdl.results(batch: %batch) + } + irdl.operation @pcs_opening_claim { + %point = irdl.parametric @compute::@point<> + %eval = irdl.parametric @compute::@field_value<> + %claim = irdl.parametric @compute::@opening_claim_type<> + %sym = irdl.any + %oracle = irdl.any + %family = irdl.any + %domain = irdl.any + %point_arity = irdl.any + irdl.attributes { + "sym_name" = %sym, + "oracle" = %oracle, + "family" = %family, + "domain" = %domain, + "point_arity" = %point_arity + } + irdl.operands(point: %point, eval: %eval) + irdl.results(claim: %claim) + } + irdl.operation @pcs_opening_batch { + %claim = irdl.parametric @compute::@opening_claim_type<> + %batch = irdl.parametric @compute::@opening_batch_type<> + %sym = irdl.any + %proof_slot = irdl.any + %policy = irdl.any + %count = irdl.any + %ordered_claims = irdl.any + irdl.attributes { + "sym_name" = %sym, + "proof_slot" = %proof_slot, + "policy" = %policy, + "count" = %count, + "ordered_claims" = %ordered_claims + } + irdl.operands(claims: variadic %claim) + irdl.results(batch: %batch) + } + irdl.operation @pcs_batch_open { + %state = irdl.parametric @compute::@transcript_state<> + %batch = irdl.parametric @compute::@opening_batch_type<> + %proof = irdl.parametric @compute::@opening_proof_type<> + %sym = irdl.any + %pcs = irdl.any + %proof_slot = irdl.any + %transcript_label = irdl.any + irdl.attributes { + "sym_name" = %sym, + "pcs" = %pcs, + "proof_slot" = %proof_slot, + "transcript_label" = %transcript_label + } + irdl.operands(input: %state, batch: %batch) + irdl.results(output: %state, proof: %proof) + } + irdl.operation @pcs_batch_verify { + %state = irdl.parametric @compute::@transcript_state<> + %batch = irdl.parametric @compute::@opening_batch_type<> + %proof = irdl.parametric @compute::@opening_proof_type<> + %sym = irdl.any + %pcs = irdl.any + %proof_slot = irdl.any + %transcript_label = irdl.any + irdl.attributes { + "sym_name" = %sym, + "pcs" = %pcs, + "proof_slot" = %proof_slot, + "transcript_label" = %transcript_label + } + irdl.operands(input: %state, batch: %batch) + irdl.results(output: %state, proof: %proof) + } + irdl.operation @generate_oracle { + %sym = irdl.any + %oracle = irdl.any + %source = irdl.any + %generation = irdl.any + irdl.attributes {"sym_name" = %sym, "oracle" = %oracle, "source" = %source, "generation" = %generation} + } + irdl.operation @generate_oracle_family { + %sym = irdl.any + %family = irdl.any + %source = irdl.any + %generation = irdl.any + irdl.attributes {"sym_name" = %sym, "family" = %family, "source" = %source, "generation" = %generation} + } +} diff --git a/crates/bolt/irdl/cpu.mlir b/crates/bolt/irdl/cpu.mlir new file mode 100644 index 0000000000..22fe7ad519 --- /dev/null +++ b/crates/bolt/irdl/cpu.mlir @@ -0,0 +1,723 @@ +irdl.dialect @cpu { + irdl.type @commitment_artifact + irdl.type @transcript_state + irdl.type @oracle_buffer + irdl.type @oracle_family + irdl.type @field_value + irdl.type @point + irdl.type @sumcheck_claim_type + irdl.type @sumcheck_batch_type + irdl.type @sumcheck_result_type + irdl.type @sumcheck_proof_type + irdl.type @opening_claim_type + irdl.type @opening_batch_type + irdl.type @opening_proof_type + + irdl.operation @params { + %sym = irdl.any + %field = irdl.any + %pcs = irdl.any + %transcript = irdl.any + irdl.attributes {"sym_name" = %sym, "field" = %field, "pcs" = %pcs, "transcript" = %transcript} + } + irdl.operation @function { + %sym = irdl.any + %source = irdl.any + irdl.attributes {"sym_name" = %sym, "source" = %source} + } + irdl.operation @kernel { + %sym = irdl.any + %relation = irdl.any + %kind = irdl.any + %backend = irdl.any + %abi = irdl.any + irdl.attributes { + "sym_name" = %sym, + "relation" = %relation, + "kind" = %kind, + "backend" = %backend, + "abi" = %abi + } + } + irdl.operation @oracle_dense_trace { + %buffer = irdl.parametric @cpu::@oracle_buffer<> + %sym = irdl.any + %oracle = irdl.any + %source = irdl.any + %domain = irdl.any + %num_vars = irdl.any + %padding = irdl.any + irdl.attributes { + "sym_name" = %sym, + "oracle" = %oracle, + "source" = %source, + "domain" = %domain, + "num_vars" = %num_vars, + "padding" = %padding + } + irdl.results(buffer: %buffer) + } + irdl.operation @oracle_one_hot_chunk { + %buffer = irdl.parametric @cpu::@oracle_buffer<> + %sym = irdl.any + %oracle = irdl.any + %source = irdl.any + %domain = irdl.any + %num_vars = irdl.any + %trace_num_vars = irdl.any + %chunk = irdl.any + %num_chunks = irdl.any + %chunk_bits = irdl.any + %padding = irdl.any + %layout = irdl.any + irdl.attributes { + "sym_name" = %sym, + "oracle" = %oracle, + "source" = %source, + "domain" = %domain, + "num_vars" = %num_vars, + "trace_num_vars" = %trace_num_vars, + "chunk" = %chunk, + "num_chunks" = %num_chunks, + "chunk_bits" = %chunk_bits, + "padding" = %padding, + "layout" = %layout + } + irdl.results(buffer: %buffer) + } + irdl.operation @oracle_optional_advice { + %buffer = irdl.parametric @cpu::@oracle_buffer<> + %sym = irdl.any + %oracle = irdl.any + %source = irdl.any + %domain = irdl.any + %num_vars = irdl.any + %skip_policy = irdl.any + irdl.attributes { + "sym_name" = %sym, + "oracle" = %oracle, + "source" = %source, + "domain" = %domain, + "num_vars" = %num_vars, + "skip_policy" = %skip_policy + } + irdl.results(buffer: %buffer) + } + irdl.operation @oracle_ref { + %buffer = irdl.parametric @cpu::@oracle_buffer<> + %sym = irdl.any + %oracle = irdl.any + %domain = irdl.any + %num_vars = irdl.any + irdl.attributes {"sym_name" = %sym, "oracle" = %oracle, "domain" = %domain, "num_vars" = %num_vars} + irdl.results(buffer: %buffer) + } + irdl.operation @oracle_family_init { + %family_type = irdl.parametric @cpu::@oracle_family<> + %sym = irdl.any + %family = irdl.any + %count = irdl.any + irdl.attributes {"sym_name" = %sym, "family" = %family, "count" = %count} + irdl.results(family: %family_type) + } + irdl.operation @oracle_family_append { + %family_type = irdl.parametric @cpu::@oracle_family<> + %buffer = irdl.parametric @cpu::@oracle_buffer<> + %sym = irdl.any + %family = irdl.any + %oracle = irdl.any + %index = irdl.any + irdl.attributes {"sym_name" = %sym, "family" = %family, "oracle" = %oracle, "index" = %index} + irdl.operands(input: %family_type, oracle_buffer: %buffer) + irdl.results(output: %family_type) + } + irdl.operation @pcs_commit_batch { + %artifact_type = irdl.parametric @cpu::@commitment_artifact<> + %family_type = irdl.parametric @cpu::@oracle_family<> + %sym = irdl.any + %artifact = irdl.any + %pcs = irdl.any + %oracle_family = irdl.any + %ordered_oracles = irdl.any + %label = irdl.any + %domain = irdl.any + %num_vars = irdl.any + %count = irdl.any + irdl.attributes { + "sym_name" = %sym, + "artifact" = %artifact, + "pcs" = %pcs, + "oracle_family" = %oracle_family, + "ordered_oracles" = %ordered_oracles, + "label" = %label, + "domain" = %domain, + "num_vars" = %num_vars, + "count" = %count + } + irdl.operands(oracles: %family_type) + irdl.results(artifact: %artifact_type) + } + irdl.operation @pcs_commit_optional { + %artifact_type = irdl.parametric @cpu::@commitment_artifact<> + %buffer = irdl.parametric @cpu::@oracle_buffer<> + %sym = irdl.any + %artifact = irdl.any + %pcs = irdl.any + %oracle = irdl.any + %label = irdl.any + %domain = irdl.any + %num_vars = irdl.any + %skip_policy = irdl.any + irdl.attributes { + "sym_name" = %sym, + "artifact" = %artifact, + "pcs" = %pcs, + "oracle" = %oracle, + "label" = %label, + "domain" = %domain, + "num_vars" = %num_vars, + "skip_policy" = %skip_policy + } + irdl.operands(oracle_buffer: %buffer) + irdl.results(artifact: %artifact_type) + } + irdl.operation @pcs_receive_batch { + %artifact_type = irdl.parametric @cpu::@commitment_artifact<> + %family_type = irdl.parametric @cpu::@oracle_family<> + %sym = irdl.any + %artifact = irdl.any + %pcs = irdl.any + %oracle_family = irdl.any + %ordered_oracles = irdl.any + %label = irdl.any + %domain = irdl.any + %num_vars = irdl.any + %count = irdl.any + irdl.attributes { + "sym_name" = %sym, + "artifact" = %artifact, + "pcs" = %pcs, + "oracle_family" = %oracle_family, + "ordered_oracles" = %ordered_oracles, + "label" = %label, + "domain" = %domain, + "num_vars" = %num_vars, + "count" = %count + } + irdl.operands(oracles: %family_type) + irdl.results(artifact: %artifact_type) + } + irdl.operation @pcs_receive_optional { + %artifact_type = irdl.parametric @cpu::@commitment_artifact<> + %buffer = irdl.parametric @cpu::@oracle_buffer<> + %sym = irdl.any + %artifact = irdl.any + %pcs = irdl.any + %oracle = irdl.any + %label = irdl.any + %domain = irdl.any + %num_vars = irdl.any + %skip_policy = irdl.any + irdl.attributes { + "sym_name" = %sym, + "artifact" = %artifact, + "pcs" = %pcs, + "oracle" = %oracle, + "label" = %label, + "domain" = %domain, + "num_vars" = %num_vars, + "skip_policy" = %skip_policy + } + irdl.operands(oracle_buffer: %buffer) + irdl.results(artifact: %artifact_type) + } + irdl.operation @transcript_init { + %state = irdl.parametric @cpu::@transcript_state<> + %sym = irdl.any + %scheme = irdl.any + irdl.attributes {"sym_name" = %sym, "scheme" = %scheme} + irdl.results(state: %state) + } + irdl.operation @transcript_absorb { + %state = irdl.parametric @cpu::@transcript_state<> + %artifact = irdl.parametric @cpu::@commitment_artifact<> + %sym = irdl.any + %label = irdl.any + %optional = irdl.any + irdl.attributes { + "sym_name" = %sym, + "label" = %label, + "optional" = %optional + } + irdl.operands(input: %state, artifact: %artifact) + irdl.results(output: %state) + } + irdl.operation @transcript_absorb_bytes { + %state = irdl.parametric @cpu::@transcript_state<> + %sym = irdl.any + %label = irdl.any + %payload = irdl.any + irdl.attributes { + "sym_name" = %sym, + "label" = %label, + "payload" = %payload + } + irdl.operands(input: %state) + irdl.results(output: %state) + } + irdl.operation @transcript_squeeze { + %state = irdl.parametric @cpu::@transcript_state<> + %challenge = irdl.any + %sym = irdl.any + %label = irdl.any + %kind = irdl.any + %count = irdl.any + irdl.attributes { + "sym_name" = %sym, + "label" = %label, + "kind" = %kind, + "count" = %count + } + irdl.operands(input: %state) + irdl.results(output: %state, challenge: %challenge) + } + irdl.operation @opening_input { + %point = irdl.parametric @cpu::@point<> + %eval = irdl.parametric @cpu::@field_value<> + %claim = irdl.parametric @cpu::@opening_claim_type<> + %sym = irdl.any + %source_stage = irdl.any + %source_claim = irdl.any + %oracle = irdl.any + %domain = irdl.any + %point_arity = irdl.any + %claim_kind = irdl.any + irdl.attributes { + "sym_name" = %sym, + "source_stage" = %source_stage, + "source_claim" = %source_claim, + "oracle" = %oracle, + "domain" = %domain, + "point_arity" = %point_arity, + "claim_kind" = %claim_kind + } + irdl.results(point: %point, eval: %eval, claim: %claim) + } + irdl.operation @point_slice { + %input = irdl.parametric @cpu::@point<> + %output = irdl.parametric @cpu::@point<> + %sym = irdl.any + %source = irdl.any + %offset = irdl.any + %length = irdl.any + irdl.attributes { + "sym_name" = %sym, + "source" = %source, + "offset" = %offset, + "length" = %length + } + irdl.operands(input: %input) + irdl.results(output: %output) + } + irdl.operation @point_zero { + %output = irdl.parametric @cpu::@point<> + %sym = irdl.any + %field = irdl.any + %arity = irdl.any + irdl.attributes { + "sym_name" = %sym, + "field" = %field, + "arity" = %arity + } + irdl.results(output: %output) + } + irdl.operation @point_concat { + %input = irdl.parametric @cpu::@point<> + %output = irdl.parametric @cpu::@point<> + %sym = irdl.any + %layout = irdl.any + %arity = irdl.any + irdl.attributes { + "sym_name" = %sym, + "layout" = %layout, + "arity" = %arity + } + irdl.operands(inputs: variadic %input) + irdl.results(output: %output) + } + irdl.operation @field_const { + %value_type = irdl.parametric @cpu::@field_value<> + %sym = irdl.any + %field = irdl.any + %value = irdl.any + irdl.attributes {"sym_name" = %sym, "field" = %field, "value" = %value} + irdl.results(value: %value_type) + } + irdl.operation @field_zero { + %value_type = irdl.parametric @cpu::@field_value<> + %sym = irdl.any + %field = irdl.any + irdl.attributes {"sym_name" = %sym, "field" = %field} + irdl.results(value: %value_type) + } + irdl.operation @field_one { + %value_type = irdl.parametric @cpu::@field_value<> + %sym = irdl.any + %field = irdl.any + irdl.attributes {"sym_name" = %sym, "field" = %field} + irdl.results(value: %value_type) + } + irdl.operation @field_add { + %value_type = irdl.parametric @cpu::@field_value<> + %sym = irdl.any + irdl.attributes {"sym_name" = %sym} + irdl.operands(lhs: %value_type, rhs: %value_type) + irdl.results(value: %value_type) + } + irdl.operation @field_sub { + %value_type = irdl.parametric @cpu::@field_value<> + %sym = irdl.any + irdl.attributes {"sym_name" = %sym} + irdl.operands(lhs: %value_type, rhs: %value_type) + irdl.results(value: %value_type) + } + irdl.operation @field_neg { + %value_type = irdl.parametric @cpu::@field_value<> + %sym = irdl.any + irdl.attributes {"sym_name" = %sym} + irdl.operands(input: %value_type) + irdl.results(value: %value_type) + } + irdl.operation @field_mul { + %value_type = irdl.parametric @cpu::@field_value<> + %sym = irdl.any + irdl.attributes {"sym_name" = %sym} + irdl.operands(lhs: %value_type, rhs: %value_type) + irdl.results(value: %value_type) + } + irdl.operation @field_pow { + %value_type = irdl.parametric @cpu::@field_value<> + %sym = irdl.any + %exponent = irdl.any + irdl.attributes {"sym_name" = %sym, "exponent" = %exponent} + irdl.operands(input: %value_type) + irdl.results(value: %value_type) + } + irdl.operation @poly_lagrange_basis_eval { + %value_type = irdl.parametric @cpu::@field_value<> + %sym = irdl.any + %domain_start = irdl.any + %domain_size = irdl.any + %index = irdl.any + irdl.attributes { + "sym_name" = %sym, + "domain_start" = %domain_start, + "domain_size" = %domain_size, + "index" = %index + } + irdl.operands(point: %value_type) + irdl.results(value: %value_type) + } + irdl.operation @sumcheck_claim { + %input_claim = irdl.parametric @cpu::@field_value<> + %opening_claim = irdl.parametric @cpu::@opening_claim_type<> + %claim_type = irdl.parametric @cpu::@sumcheck_claim_type<> + %sym = irdl.any + %stage = irdl.any + %domain = irdl.any + %num_rounds = irdl.any + %degree = irdl.any + %claim = irdl.any + %kernel = irdl.any + irdl.attributes { + "sym_name" = %sym, + "stage" = %stage, + "domain" = %domain, + "num_rounds" = %num_rounds, + "degree" = %degree, + "claim" = %claim, + "kernel" = %kernel + } + irdl.operands(input_claim: %input_claim, inputs: variadic %opening_claim) + irdl.results(claim: %claim_type) + } + irdl.operation @sumcheck_verify_claim { + %input_claim = irdl.parametric @cpu::@field_value<> + %opening_claim = irdl.parametric @cpu::@opening_claim_type<> + %claim_type = irdl.parametric @cpu::@sumcheck_claim_type<> + %sym = irdl.any + %stage = irdl.any + %domain = irdl.any + %num_rounds = irdl.any + %degree = irdl.any + %claim = irdl.any + %relation = irdl.any + irdl.attributes { + "sym_name" = %sym, + "stage" = %stage, + "domain" = %domain, + "num_rounds" = %num_rounds, + "degree" = %degree, + "claim" = %claim, + "relation" = %relation + } + irdl.operands(input_claim: %input_claim, inputs: variadic %opening_claim) + irdl.results(claim: %claim_type) + } + irdl.operation @sumcheck_batch { + %claim_type = irdl.parametric @cpu::@sumcheck_claim_type<> + %batch_type = irdl.parametric @cpu::@sumcheck_batch_type<> + %sym = irdl.any + %stage = irdl.any + %proof_slot = irdl.any + %policy = irdl.any + %count = irdl.any + %ordered_claims = irdl.any + %claim_label = irdl.any + %round_label = irdl.any + %round_schedule = irdl.any + irdl.attributes { + "sym_name" = %sym, + "stage" = %stage, + "proof_slot" = %proof_slot, + "policy" = %policy, + "count" = %count, + "ordered_claims" = %ordered_claims, + "claim_label" = %claim_label, + "round_label" = %round_label, + "round_schedule" = %round_schedule + } + irdl.operands(claims: variadic %claim_type) + irdl.results(batch: %batch_type) + } + irdl.operation @sumcheck_driver { + %state = irdl.parametric @cpu::@transcript_state<> + %batch_type = irdl.parametric @cpu::@sumcheck_batch_type<> + %point = irdl.parametric @cpu::@point<> + %result = irdl.parametric @cpu::@sumcheck_result_type<> + %proof = irdl.parametric @cpu::@sumcheck_proof_type<> + %sym = irdl.any + %stage = irdl.any + %proof_slot = irdl.any + %kernel = irdl.any + %policy = irdl.any + %round_schedule = irdl.any + %claim_label = irdl.any + %round_label = irdl.any + %num_rounds = irdl.any + %degree = irdl.any + irdl.attributes { + "sym_name" = %sym, + "stage" = %stage, + "proof_slot" = %proof_slot, + "kernel" = %kernel, + "policy" = %policy, + "round_schedule" = %round_schedule, + "claim_label" = %claim_label, + "round_label" = %round_label, + "num_rounds" = %num_rounds, + "degree" = %degree + } + irdl.operands(input: %state, batch: %batch_type) + irdl.results(output: %state, point: %point, result: %result, proof: %proof) + } + irdl.operation @sumcheck_verify { + %state = irdl.parametric @cpu::@transcript_state<> + %batch_type = irdl.parametric @cpu::@sumcheck_batch_type<> + %point = irdl.parametric @cpu::@point<> + %result = irdl.parametric @cpu::@sumcheck_result_type<> + %proof = irdl.parametric @cpu::@sumcheck_proof_type<> + %sym = irdl.any + %stage = irdl.any + %proof_slot = irdl.any + %relation = irdl.any + %policy = irdl.any + %round_schedule = irdl.any + %claim_label = irdl.any + %round_label = irdl.any + %num_rounds = irdl.any + %degree = irdl.any + irdl.attributes { + "sym_name" = %sym, + "stage" = %stage, + "proof_slot" = %proof_slot, + "relation" = %relation, + "policy" = %policy, + "round_schedule" = %round_schedule, + "claim_label" = %claim_label, + "round_label" = %round_label, + "num_rounds" = %num_rounds, + "degree" = %degree + } + irdl.operands(input: %state, batch: %batch_type) + irdl.results(output: %state, point: %point, result: %result, proof: %proof) + } + irdl.operation @sumcheck_eval { + %result = irdl.parametric @cpu::@sumcheck_result_type<> + %eval = irdl.parametric @cpu::@field_value<> + %sym = irdl.any + %source = irdl.any + %name = irdl.any + %index = irdl.any + %oracle = irdl.any + irdl.attributes { + "sym_name" = %sym, + "source" = %source, + "name" = %name, + "index" = %index, + "oracle" = %oracle + } + irdl.operands(result: %result) + irdl.results(eval: %eval) + } + irdl.operation @sumcheck_instance_result { + %input_point = irdl.parametric @cpu::@point<> + %output_point = irdl.parametric @cpu::@point<> + %input_result = irdl.parametric @cpu::@sumcheck_result_type<> + %output_result = irdl.parametric @cpu::@sumcheck_result_type<> + %sym = irdl.any + %source = irdl.any + %claim = irdl.any + %relation = irdl.any + %index = irdl.any + %point_arity = irdl.any + %num_rounds = irdl.any + %round_offset = irdl.any + %point_order = irdl.any + %degree = irdl.any + irdl.attributes { + "sym_name" = %sym, + "source" = %source, + "claim" = %claim, + "relation" = %relation, + "index" = %index, + "point_arity" = %point_arity, + "num_rounds" = %num_rounds, + "round_offset" = %round_offset, + "point_order" = %point_order, + "degree" = %degree + } + irdl.operands(input_point: %input_point, input_result: %input_result) + irdl.results(instance_point: %output_point, instance_result: %output_result) + } + irdl.operation @opening_claim { + %point = irdl.parametric @cpu::@point<> + %eval = irdl.parametric @cpu::@field_value<> + %claim = irdl.parametric @cpu::@opening_claim_type<> + %sym = irdl.any + %oracle = irdl.any + %domain = irdl.any + %point_arity = irdl.any + %claim_kind = irdl.any + irdl.attributes { + "sym_name" = %sym, + "oracle" = %oracle, + "domain" = %domain, + "point_arity" = %point_arity, + "claim_kind" = %claim_kind + } + irdl.operands(point: %point, eval: %eval) + irdl.results(claim: %claim) + } + irdl.operation @opening_claim_equal { + %claim = irdl.parametric @cpu::@opening_claim_type<> + %sym = irdl.any + %mode = irdl.any + irdl.attributes { + "sym_name" = %sym, + "mode" = %mode + } + irdl.operands(left: %claim, right: %claim) + } + irdl.operation @opening_batch { + %claim = irdl.parametric @cpu::@opening_claim_type<> + %batch = irdl.parametric @cpu::@opening_batch_type<> + %sym = irdl.any + %stage = irdl.any + %proof_slot = irdl.any + %policy = irdl.any + %count = irdl.any + %ordered_claims = irdl.any + irdl.attributes { + "sym_name" = %sym, + "stage" = %stage, + "proof_slot" = %proof_slot, + "policy" = %policy, + "count" = %count, + "ordered_claims" = %ordered_claims + } + irdl.operands(claims: variadic %claim) + irdl.results(batch: %batch) + } + irdl.operation @pcs_opening_claim { + %point = irdl.parametric @cpu::@point<> + %eval = irdl.parametric @cpu::@field_value<> + %claim = irdl.parametric @cpu::@opening_claim_type<> + %sym = irdl.any + %oracle = irdl.any + %family = irdl.any + %domain = irdl.any + %point_arity = irdl.any + irdl.attributes { + "sym_name" = %sym, + "oracle" = %oracle, + "family" = %family, + "domain" = %domain, + "point_arity" = %point_arity + } + irdl.operands(point: %point, eval: %eval) + irdl.results(claim: %claim) + } + irdl.operation @pcs_opening_batch { + %claim = irdl.parametric @cpu::@opening_claim_type<> + %batch = irdl.parametric @cpu::@opening_batch_type<> + %sym = irdl.any + %proof_slot = irdl.any + %policy = irdl.any + %count = irdl.any + %ordered_claims = irdl.any + irdl.attributes { + "sym_name" = %sym, + "proof_slot" = %proof_slot, + "policy" = %policy, + "count" = %count, + "ordered_claims" = %ordered_claims + } + irdl.operands(claims: variadic %claim) + irdl.results(batch: %batch) + } + irdl.operation @pcs_batch_open { + %state = irdl.parametric @cpu::@transcript_state<> + %batch = irdl.parametric @cpu::@opening_batch_type<> + %proof = irdl.parametric @cpu::@opening_proof_type<> + %sym = irdl.any + %pcs = irdl.any + %proof_slot = irdl.any + %transcript_label = irdl.any + irdl.attributes { + "sym_name" = %sym, + "pcs" = %pcs, + "proof_slot" = %proof_slot, + "transcript_label" = %transcript_label + } + irdl.operands(input: %state, batch: %batch) + irdl.results(output: %state, proof: %proof) + } + irdl.operation @pcs_batch_verify { + %state = irdl.parametric @cpu::@transcript_state<> + %batch = irdl.parametric @cpu::@opening_batch_type<> + %proof = irdl.parametric @cpu::@opening_proof_type<> + %sym = irdl.any + %pcs = irdl.any + %proof_slot = irdl.any + %transcript_label = irdl.any + irdl.attributes { + "sym_name" = %sym, + "pcs" = %pcs, + "proof_slot" = %proof_slot, + "transcript_label" = %transcript_label + } + irdl.operands(input: %state, batch: %batch) + irdl.results(output: %state, proof: %proof) + } +} diff --git a/crates/bolt/irdl/field.mlir b/crates/bolt/irdl/field.mlir new file mode 100644 index 0000000000..2f14d2b061 --- /dev/null +++ b/crates/bolt/irdl/field.mlir @@ -0,0 +1,67 @@ +irdl.dialect @field { + irdl.type @scalar + irdl.operation @define { + %sym = irdl.any + %modulus_bits = irdl.any + %role = irdl.any + irdl.attributes {"sym_name" = %sym, "modulus_bits" = %modulus_bits, "role" = %role} + } + irdl.operation @const { + %scalar = irdl.parametric @field::@scalar<> + %sym = irdl.any + %field = irdl.any + %value = irdl.any + irdl.attributes {"sym_name" = %sym, "field" = %field, "value" = %value} + irdl.results(value: %scalar) + } + irdl.operation @zero { + %scalar = irdl.parametric @field::@scalar<> + %sym = irdl.any + %field = irdl.any + irdl.attributes {"sym_name" = %sym, "field" = %field} + irdl.results(value: %scalar) + } + irdl.operation @one { + %scalar = irdl.parametric @field::@scalar<> + %sym = irdl.any + %field = irdl.any + irdl.attributes {"sym_name" = %sym, "field" = %field} + irdl.results(value: %scalar) + } + irdl.operation @add { + %scalar = irdl.parametric @field::@scalar<> + %sym = irdl.any + irdl.attributes {"sym_name" = %sym} + irdl.operands(lhs: %scalar, rhs: %scalar) + irdl.results(value: %scalar) + } + irdl.operation @sub { + %scalar = irdl.parametric @field::@scalar<> + %sym = irdl.any + irdl.attributes {"sym_name" = %sym} + irdl.operands(lhs: %scalar, rhs: %scalar) + irdl.results(value: %scalar) + } + irdl.operation @neg { + %scalar = irdl.parametric @field::@scalar<> + %sym = irdl.any + irdl.attributes {"sym_name" = %sym} + irdl.operands(input: %scalar) + irdl.results(value: %scalar) + } + irdl.operation @mul { + %scalar = irdl.parametric @field::@scalar<> + %sym = irdl.any + irdl.attributes {"sym_name" = %sym} + irdl.operands(lhs: %scalar, rhs: %scalar) + irdl.results(value: %scalar) + } + irdl.operation @pow { + %scalar = irdl.parametric @field::@scalar<> + %sym = irdl.any + %exponent = irdl.any + irdl.attributes {"sym_name" = %sym, "exponent" = %exponent} + irdl.operands(input: %scalar) + irdl.results(value: %scalar) + } +} diff --git a/crates/bolt/irdl/hash.mlir b/crates/bolt/irdl/hash.mlir new file mode 100644 index 0000000000..66b2f984fa --- /dev/null +++ b/crates/bolt/irdl/hash.mlir @@ -0,0 +1,7 @@ +irdl.dialect @hash { + irdl.operation @function { + %sym = irdl.any + %algorithm = irdl.any + irdl.attributes {"sym_name" = %sym, "algorithm" = %algorithm} + } +} diff --git a/crates/bolt/irdl/party.mlir b/crates/bolt/irdl/party.mlir new file mode 100644 index 0000000000..46dfb26d30 --- /dev/null +++ b/crates/bolt/irdl/party.mlir @@ -0,0 +1,8 @@ +irdl.dialect @party { + irdl.operation @function { + %sym = irdl.any + %source = irdl.any + %role = irdl.any + irdl.attributes {"sym_name" = %sym, "source" = %source, "role" = %role} + } +} diff --git a/crates/bolt/irdl/pcs.mlir b/crates/bolt/irdl/pcs.mlir new file mode 100644 index 0000000000..a5fff00470 --- /dev/null +++ b/crates/bolt/irdl/pcs.mlir @@ -0,0 +1,89 @@ +irdl.dialect @pcs { + irdl.type @scheme_type + irdl.type @opening_claim_type + irdl.type @opening_batch_type + irdl.type @opening_proof_type + irdl.operation @scheme { + %sym = irdl.any + %field = irdl.any + irdl.attributes {"sym_name" = %sym, "field" = %field} + } + irdl.operation @commit_batch { + %artifact = irdl.parametric @commit::@artifact<> + %sym = irdl.any + %scheme = irdl.any + irdl.attributes {"sym_name" = %sym, "scheme" = %scheme} + irdl.operands(commitment: %artifact) + } + irdl.operation @opening_claim { + %point = irdl.parametric @poly::@point<> + %eval = irdl.parametric @field::@scalar<> + %claim = irdl.parametric @pcs::@opening_claim_type<> + %sym = irdl.any + %oracle = irdl.any + %family = irdl.any + %domain = irdl.any + %point_arity = irdl.any + irdl.attributes { + "sym_name" = %sym, + "oracle" = %oracle, + "family" = %family, + "domain" = %domain, + "point_arity" = %point_arity + } + irdl.operands(point: %point, eval: %eval) + irdl.results(claim: %claim) + } + irdl.operation @opening_batch { + %claim = irdl.parametric @pcs::@opening_claim_type<> + %batch = irdl.parametric @pcs::@opening_batch_type<> + %sym = irdl.any + %proof_slot = irdl.any + %policy = irdl.any + %count = irdl.any + %ordered_claims = irdl.any + irdl.attributes { + "sym_name" = %sym, + "proof_slot" = %proof_slot, + "policy" = %policy, + "count" = %count, + "ordered_claims" = %ordered_claims + } + irdl.operands(claims: variadic %claim) + irdl.results(batch: %batch) + } + irdl.operation @batch_open { + %state = irdl.parametric @transcript::@state_type<> + %batch = irdl.parametric @pcs::@opening_batch_type<> + %proof = irdl.parametric @pcs::@opening_proof_type<> + %sym = irdl.any + %pcs = irdl.any + %proof_slot = irdl.any + %transcript_label = irdl.any + irdl.attributes { + "sym_name" = %sym, + "pcs" = %pcs, + "proof_slot" = %proof_slot, + "transcript_label" = %transcript_label + } + irdl.operands(input: %state, batch: %batch) + irdl.results(output: %state, proof: %proof) + } + irdl.operation @batch_verify { + %state = irdl.parametric @transcript::@state_type<> + %batch = irdl.parametric @pcs::@opening_batch_type<> + %proof = irdl.parametric @pcs::@opening_proof_type<> + %sym = irdl.any + %pcs = irdl.any + %proof_slot = irdl.any + %transcript_label = irdl.any + irdl.attributes { + "sym_name" = %sym, + "pcs" = %pcs, + "proof_slot" = %proof_slot, + "transcript_label" = %transcript_label + } + irdl.operands(input: %state, batch: %batch) + irdl.results(output: %state, proof: %proof) + } +} diff --git a/crates/bolt/irdl/piop.mlir b/crates/bolt/irdl/piop.mlir new file mode 100644 index 0000000000..169bc5c9ab --- /dev/null +++ b/crates/bolt/irdl/piop.mlir @@ -0,0 +1,270 @@ +irdl.dialect @piop { + irdl.type @stage_type + irdl.type @sumcheck_claim_type + irdl.type @sumcheck_batch_type + irdl.type @sumcheck_result_type + irdl.type @sumcheck_proof_type + irdl.type @opening_claim_type + irdl.type @opening_batch_type + + irdl.operation @oracle { + %sym = irdl.any + %field = irdl.any + %domain = irdl.any + %commit_domain = irdl.any + %visibility = irdl.any + %layout = irdl.any + irdl.attributes { + "sym_name" = %sym, + "field" = %field, + "domain" = %domain, + "commit_domain" = %commit_domain, + "visibility" = %visibility, + "layout" = %layout + } + } + irdl.operation @oracle_family { + %sym = irdl.any + %ordered_oracles = irdl.any + %visibility = irdl.any + %count = irdl.any + %domain = irdl.any + irdl.attributes { + "sym_name" = %sym, + "ordered_oracles" = %ordered_oracles, + "visibility" = %visibility, + "count" = %count, + "domain" = %domain + } + } + irdl.operation @stage { + %stage_type = irdl.parametric @piop::@stage_type<> + %sym = irdl.any + %name = irdl.any + %order = irdl.any + %roles = irdl.any + irdl.attributes { + "sym_name" = %sym, + "name" = %name, + "order" = %order, + "roles" = %roles + } + irdl.results(stage: %stage_type) + } + irdl.operation @relation { + %sym = irdl.any + %kind = irdl.any + %domain = irdl.any + %num_rounds = irdl.any + %degree = irdl.any + %output_count = irdl.any + irdl.attributes { + "sym_name" = %sym, + "kind" = %kind, + "domain" = %domain, + "num_rounds" = %num_rounds, + "degree" = %degree, + "output_count" = %output_count + } + } + irdl.operation @sumcheck_claim { + %input_claim = irdl.parametric @field::@scalar<> + %opening_claim = irdl.parametric @piop::@opening_claim_type<> + %claim_type = irdl.parametric @piop::@sumcheck_claim_type<> + %sym = irdl.any + %stage = irdl.any + %domain = irdl.any + %num_rounds = irdl.any + %degree = irdl.any + %claim = irdl.any + %relation = irdl.any + irdl.attributes { + "sym_name" = %sym, + "stage" = %stage, + "domain" = %domain, + "num_rounds" = %num_rounds, + "degree" = %degree, + "claim" = %claim, + "relation" = %relation + } + irdl.operands(input_claim: %input_claim, inputs: variadic %opening_claim) + irdl.results(claim: %claim_type) + } + irdl.operation @opening_input { + %point = irdl.parametric @poly::@point<> + %eval = irdl.parametric @field::@scalar<> + %claim = irdl.parametric @piop::@opening_claim_type<> + %sym = irdl.any + %source_stage = irdl.any + %source_claim = irdl.any + %oracle = irdl.any + %domain = irdl.any + %point_arity = irdl.any + %claim_kind = irdl.any + irdl.attributes { + "sym_name" = %sym, + "source_stage" = %source_stage, + "source_claim" = %source_claim, + "oracle" = %oracle, + "domain" = %domain, + "point_arity" = %point_arity, + "claim_kind" = %claim_kind + } + irdl.results(point: %point, eval: %eval, claim: %claim) + } + irdl.operation @sumcheck_batch { + %stage_type = irdl.parametric @piop::@stage_type<> + %claim_type = irdl.parametric @piop::@sumcheck_claim_type<> + %batch_type = irdl.parametric @piop::@sumcheck_batch_type<> + %sym = irdl.any + %stage = irdl.any + %proof_slot = irdl.any + %policy = irdl.any + %count = irdl.any + %ordered_claims = irdl.any + %claim_label = irdl.any + %round_label = irdl.any + %round_schedule = irdl.any + irdl.attributes { + "sym_name" = %sym, + "stage" = %stage, + "proof_slot" = %proof_slot, + "policy" = %policy, + "count" = %count, + "ordered_claims" = %ordered_claims, + "claim_label" = %claim_label, + "round_label" = %round_label, + "round_schedule" = %round_schedule + } + irdl.operands(stage: %stage_type, claims: variadic %claim_type) + irdl.results(batch: %batch_type) + } + irdl.operation @sumcheck { + %state = irdl.parametric @transcript::@state_type<> + %batch_type = irdl.parametric @piop::@sumcheck_batch_type<> + %point = irdl.parametric @poly::@point<> + %result = irdl.parametric @piop::@sumcheck_result_type<> + %proof = irdl.parametric @piop::@sumcheck_proof_type<> + %sym = irdl.any + %stage = irdl.any + %proof_slot = irdl.any + %relation = irdl.any + %policy = irdl.any + %round_schedule = irdl.any + %claim_label = irdl.any + %round_label = irdl.any + %num_rounds = irdl.any + %degree = irdl.any + irdl.attributes { + "sym_name" = %sym, + "stage" = %stage, + "proof_slot" = %proof_slot, + "relation" = %relation, + "policy" = %policy, + "round_schedule" = %round_schedule, + "claim_label" = %claim_label, + "round_label" = %round_label, + "num_rounds" = %num_rounds, + "degree" = %degree + } + irdl.operands(input: %state, batch: %batch_type) + irdl.results(output: %state, point: %point, result: %result, proof: %proof) + } + irdl.operation @sumcheck_eval { + %result = irdl.parametric @piop::@sumcheck_result_type<> + %eval = irdl.parametric @field::@scalar<> + %sym = irdl.any + %source = irdl.any + %name = irdl.any + %index = irdl.any + %oracle = irdl.any + irdl.attributes { + "sym_name" = %sym, + "source" = %source, + "name" = %name, + "index" = %index, + "oracle" = %oracle + } + irdl.operands(result: %result) + irdl.results(eval: %eval) + } + irdl.operation @sumcheck_instance_result { + %input_point = irdl.parametric @poly::@point<> + %output_point = irdl.parametric @poly::@point<> + %input_result = irdl.parametric @piop::@sumcheck_result_type<> + %output_result = irdl.parametric @piop::@sumcheck_result_type<> + %sym = irdl.any + %source = irdl.any + %claim = irdl.any + %relation = irdl.any + %index = irdl.any + %point_arity = irdl.any + %num_rounds = irdl.any + %round_offset = irdl.any + %point_order = irdl.any + %degree = irdl.any + irdl.attributes { + "sym_name" = %sym, + "source" = %source, + "claim" = %claim, + "relation" = %relation, + "index" = %index, + "point_arity" = %point_arity, + "num_rounds" = %num_rounds, + "round_offset" = %round_offset, + "point_order" = %point_order, + "degree" = %degree + } + irdl.operands(input_point: %input_point, input_result: %input_result) + irdl.results(instance_point: %output_point, instance_result: %output_result) + } + irdl.operation @opening_claim { + %point = irdl.parametric @poly::@point<> + %eval = irdl.parametric @field::@scalar<> + %claim = irdl.parametric @piop::@opening_claim_type<> + %sym = irdl.any + %oracle = irdl.any + %domain = irdl.any + %point_arity = irdl.any + %claim_kind = irdl.any + irdl.attributes { + "sym_name" = %sym, + "oracle" = %oracle, + "domain" = %domain, + "point_arity" = %point_arity, + "claim_kind" = %claim_kind + } + irdl.operands(point: %point, eval: %eval) + irdl.results(claim: %claim) + } + irdl.operation @opening_claim_equal { + %claim = irdl.parametric @piop::@opening_claim_type<> + %sym = irdl.any + %mode = irdl.any + irdl.attributes { + "sym_name" = %sym, + "mode" = %mode + } + irdl.operands(left: %claim, right: %claim) + } + irdl.operation @opening_batch { + %claim = irdl.parametric @piop::@opening_claim_type<> + %batch = irdl.parametric @piop::@opening_batch_type<> + %sym = irdl.any + %stage = irdl.any + %proof_slot = irdl.any + %policy = irdl.any + %count = irdl.any + %ordered_claims = irdl.any + irdl.attributes { + "sym_name" = %sym, + "stage" = %stage, + "proof_slot" = %proof_slot, + "policy" = %policy, + "count" = %count, + "ordered_claims" = %ordered_claims + } + irdl.operands(claims: variadic %claim) + irdl.results(batch: %batch) + } +} diff --git a/crates/bolt/irdl/poly.mlir b/crates/bolt/irdl/poly.mlir new file mode 100644 index 0000000000..6ad0ea5951 --- /dev/null +++ b/crates/bolt/irdl/poly.mlir @@ -0,0 +1,68 @@ +irdl.dialect @poly { + irdl.type @domain_type + irdl.type @oracle + irdl.type @point + irdl.operation @domain { + %sym = irdl.any + %field = irdl.any + %log_size = irdl.any + irdl.attributes {"sym_name" = %sym, "field" = %field, "log_size" = %log_size} + } + irdl.operation @point_slice { + %input = irdl.parametric @poly::@point<> + %output = irdl.parametric @poly::@point<> + %sym = irdl.any + %source = irdl.any + %offset = irdl.any + %length = irdl.any + irdl.attributes { + "sym_name" = %sym, + "source" = %source, + "offset" = %offset, + "length" = %length + } + irdl.operands(input: %input) + irdl.results(output: %output) + } + irdl.operation @point_zero { + %output = irdl.parametric @poly::@point<> + %sym = irdl.any + %field = irdl.any + %arity = irdl.any + irdl.attributes { + "sym_name" = %sym, + "field" = %field, + "arity" = %arity + } + irdl.results(output: %output) + } + irdl.operation @point_concat { + %input = irdl.parametric @poly::@point<> + %output = irdl.parametric @poly::@point<> + %sym = irdl.any + %layout = irdl.any + %arity = irdl.any + irdl.attributes { + "sym_name" = %sym, + "layout" = %layout, + "arity" = %arity + } + irdl.operands(inputs: variadic %input) + irdl.results(output: %output) + } + irdl.operation @lagrange_basis_eval { + %scalar = irdl.parametric @field::@scalar<> + %sym = irdl.any + %domain_start = irdl.any + %domain_size = irdl.any + %index = irdl.any + irdl.attributes { + "sym_name" = %sym, + "domain_start" = %domain_start, + "domain_size" = %domain_size, + "index" = %index + } + irdl.operands(point: %scalar) + irdl.results(value: %scalar) + } +} diff --git a/crates/bolt/irdl/protocol.mlir b/crates/bolt/irdl/protocol.mlir new file mode 100644 index 0000000000..f17629f4b9 --- /dev/null +++ b/crates/bolt/irdl/protocol.mlir @@ -0,0 +1,19 @@ +irdl.dialect @protocol { + irdl.operation @params { + %sym = irdl.any + %field = irdl.any + %pcs = irdl.any + %transcript = irdl.any + irdl.attributes { + "sym_name" = %sym, + "field" = %field, + "pcs" = %pcs, + "transcript" = %transcript + } + } + irdl.operation @boundary { + %sym = irdl.any + %roles = irdl.any + irdl.attributes {"sym_name" = %sym, "roles" = %roles} + } +} diff --git a/crates/bolt/irdl/transcript.mlir b/crates/bolt/irdl/transcript.mlir new file mode 100644 index 0000000000..7e2dd926bf --- /dev/null +++ b/crates/bolt/irdl/transcript.mlir @@ -0,0 +1,62 @@ +irdl.dialect @transcript { + irdl.type @state_type + irdl.operation @scheme { + %sym = irdl.any + %hash = irdl.any + irdl.attributes {"sym_name" = %sym, "hash" = %hash} + } + irdl.operation @state { + %state = irdl.parametric @transcript::@state_type<> + %sym = irdl.any + %scheme = irdl.any + irdl.attributes {"sym_name" = %sym, "scheme" = %scheme} + irdl.results(state: %state) + } + irdl.operation @absorb { + %state = irdl.parametric @transcript::@state_type<> + %artifact = irdl.parametric @commit::@artifact<> + %sym = irdl.any + %label = irdl.any + irdl.attributes {"sym_name" = %sym, "label" = %label} + irdl.operands(input: %state, artifact: %artifact) + irdl.results(output: %state) + } + irdl.operation @absorb_optional { + %state = irdl.parametric @transcript::@state_type<> + %artifact = irdl.parametric @commit::@artifact<> + %sym = irdl.any + %label = irdl.any + irdl.attributes {"sym_name" = %sym, "label" = %label} + irdl.operands(input: %state, artifact: %artifact) + irdl.results(output: %state) + } + irdl.operation @absorb_bytes { + %state = irdl.parametric @transcript::@state_type<> + %sym = irdl.any + %label = irdl.any + %payload = irdl.any + irdl.attributes { + "sym_name" = %sym, + "label" = %label, + "payload" = %payload + } + irdl.operands(input: %state) + irdl.results(output: %state) + } + irdl.operation @squeeze { + %state = irdl.parametric @transcript::@state_type<> + %challenge = irdl.any + %sym = irdl.any + %label = irdl.any + %kind = irdl.any + %count = irdl.any + irdl.attributes { + "sym_name" = %sym, + "label" = %label, + "kind" = %kind, + "count" = %count + } + irdl.operands(input: %state) + irdl.results(output: %state, challenge: %challenge) + } +} diff --git a/crates/bolt/src/dialects.rs b/crates/bolt/src/dialects.rs new file mode 100644 index 0000000000..655ae7c43f --- /dev/null +++ b/crates/bolt/src/dialects.rs @@ -0,0 +1,39 @@ +use melior::ir::Module; +use melior::utility::load_irdl_dialects; +use melior::Context; + +pub const BOLT_IRDL: &str = concat!( + "module {\n", + include_str!("../irdl/field.mlir"), + "\n", + include_str!("../irdl/poly.mlir"), + "\n", + include_str!("../irdl/hash.mlir"), + "\n", + include_str!("../irdl/transcript.mlir"), + "\n", + include_str!("../irdl/commit.mlir"), + "\n", + include_str!("../irdl/pcs.mlir"), + "\n", + include_str!("../irdl/protocol.mlir"), + "\n", + include_str!("../irdl/piop.mlir"), + "\n", + include_str!("../irdl/party.mlir"), + "\n", + include_str!("../irdl/compute.mlir"), + "\n", + include_str!("../irdl/cpu.mlir"), + "\n}\n" +); + +pub fn load_bolt_dialects(context: &Context) -> Result<(), String> { + let module = Module::parse(context, BOLT_IRDL) + .ok_or_else(|| "failed to parse Bolt IRDL dialect definitions".to_owned())?; + if load_irdl_dialects(&module) { + Ok(()) + } else { + Err("failed to load Bolt IRDL dialect definitions".to_owned()) + } +} diff --git a/crates/bolt/src/emit/mod.rs b/crates/bolt/src/emit/mod.rs new file mode 100644 index 0000000000..0ad9e7d3d7 --- /dev/null +++ b/crates/bolt/src/emit/mod.rs @@ -0,0 +1 @@ +pub mod rust; diff --git a/crates/bolt/src/emit/rust/artifacts.rs b/crates/bolt/src/emit/rust/artifacts.rs new file mode 100644 index 0000000000..ec2d2a6c7f --- /dev/null +++ b/crates/bolt/src/emit/rust/artifacts.rs @@ -0,0 +1,1653 @@ +#![expect( + clippy::format_push_string, + reason = "Rust artifact emission assembles generated source text from format templates" +)] + +use std::path::{Component, Path}; + +use crate::ir::Role; + +use super::{EmitError, RustSourceFile}; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct ProtocolArtifactConfig { + pub protocol_name: String, + pub type_prefix: String, + pub transcript_label: String, + pub repository: Option, + pub prover_crate_name: String, + pub verifier_crate_name: String, + pub crates_io_patches: Vec, + pub standalone_dependency_overrides: Vec, + pub common_dependencies: Vec, + pub prover_dependencies: Vec, + pub verifier_dependencies: Vec, + pub instrumentation_prefix: Option, + pub prover_forbidden_imports: Vec, + pub verifier_forbidden_imports: Vec, + pub kernel_crate: Option, + pub field_type: RustTypeRef, + pub default_transcript_type: RustTypeRef, + pub transcript_trait: RustTypeRef, + pub commitment_type: RustTypeRef, + pub prover_setup_type: RustTypeRef, + pub role_api_extension: Option, + pub verifier_runtime_modules: Vec, + pub verifier_named_eval_type: RustTypeRef, + pub verifier_sumcheck_output_type: RustTypeRef, + pub verifier_stage_proof_type: RustTypeRef, +} + +impl ProtocolArtifactConfig { + fn protocol_snake(&self) -> String { + snake_case(&self.protocol_name) + } + + fn crate_name(&self, role: &Role) -> &str { + match role { + Role::Prover => &self.prover_crate_name, + Role::Verifier => &self.verifier_crate_name, + } + } + + fn dependencies(&self, role: &Role) -> Vec { + let mut dependencies = self.common_dependencies.clone(); + match role { + Role::Prover => { + dependencies.extend(self.prover_dependencies.clone()); + if !dependencies.contains(&self.verifier_crate_name) { + dependencies.push(self.verifier_crate_name.clone()); + } + } + Role::Verifier => dependencies.extend(self.verifier_dependencies.clone()), + } + dependencies.sort(); + dependencies.dedup(); + dependencies + } + + fn forbidden_imports(&self, role: &Role) -> &[String] { + match role { + Role::Prover => &self.prover_forbidden_imports, + Role::Verifier => &self.verifier_forbidden_imports, + } + } + + fn verifier_crate_import(&self) -> String { + rust_crate_ident(&self.verifier_crate_name) + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct ProtocolStandaloneDependency { + pub package: String, + pub manifest_entry: String, +} + +impl ProtocolStandaloneDependency { + pub fn new(package: impl Into, manifest_entry: impl Into) -> Self { + Self { + package: package.into(), + manifest_entry: manifest_entry.into(), + } + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct ProtocolArtifactExtension { + pub required_commitment: bool, + pub required_proof_stages: Vec, + pub required_artifact_stages: Vec, + pub prover: ProtocolProverApiExtension, + pub verifier: ProtocolVerifierApiExtension, +} + +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub struct ProtocolProverApiExtension { + pub lib_module: String, + pub imports: String, + pub input_fields: String, + pub program_fields: String, + pub default_program_fields: String, + pub error_variants: String, + pub error_items: String, + pub error_conversions: String, + pub after_stage_execution: String, + pub proof_fields: String, + pub helper_items: String, +} + +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub struct ProtocolVerifierApiExtension { + pub lib_module: String, + pub imports: String, + pub proof_fields: String, + pub proof_items: String, + pub inputs_derive: Option, + pub input_fields: String, + pub program_fields: String, + pub default_program_fields: String, + pub error_variants: String, + pub error_items: String, + pub error_conversions: String, + pub after_default_verify: String, + pub with_programs_body_intro: String, + pub stage_verification_override: String, + pub after_stage_verification: String, + pub helper_items: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct ProtocolCrateRef { + pub package: String, + pub import: String, +} + +impl ProtocolCrateRef { + pub fn new(package: impl Into, import: impl Into) -> Self { + Self { + package: package.into(), + import: import.into(), + } + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct RustTypeRef { + pub path: String, +} + +impl RustTypeRef { + pub fn new(path: impl Into) -> Self { + Self { path: path.into() } + } + + fn ident(&self) -> &str { + self.path.rsplit("::").next().unwrap_or(&self.path) + } + + fn use_line(&self) -> String { + format!("use {};\n", self.path) + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum ProtocolStageKind { + Commitment, + Proof, + Evaluation, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct ProtocolStage { + name: String, + module_name: String, + ordinal: usize, + kind: ProtocolStageKind, +} + +impl ProtocolStage { + pub fn new( + name: impl Into, + module_name: impl Into, + ordinal: usize, + kind: ProtocolStageKind, + ) -> Self { + Self { + name: name.into(), + module_name: module_name.into(), + ordinal, + kind, + } + } + + pub fn name(&self) -> &str { + &self.name + } + + pub fn module_name(&self) -> &str { + &self.module_name + } + + pub fn order(&self) -> usize { + self.ordinal + } + + pub fn is_commitment(&self) -> bool { + self.kind == ProtocolStageKind::Commitment + } + + pub fn is_proof(&self) -> bool { + self.kind == ProtocolStageKind::Proof + } + + pub fn is_evaluation(&self) -> bool { + self.kind == ProtocolStageKind::Evaluation + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum ArtifactCrateRole { + Prover, + Verifier, +} + +impl ArtifactCrateRole { + pub fn for_role(role: &Role) -> Self { + match role { + Role::Prover => Self::Prover, + Role::Verifier => Self::Verifier, + } + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct ProtocolRustArtifact { + pub role: Role, + pub stage: ProtocolStage, + pub crate_name: String, + pub path: String, + pub source: RustSourceFile, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct GeneratedCrate { + pub crate_name: String, + pub files: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct GeneratedFile { + pub path: String, + pub source: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct ProtocolRuntimeModule { + pub module_name: String, + pub file: GeneratedFile, +} + +impl GeneratedCrate { + pub fn write_to(&self, output_root: impl AsRef) -> Result<(), EmitError> { + let crate_root = output_root.as_ref().join(&self.crate_name); + for file in &self.files { + let path = generated_file_path(&crate_root, &file.path)?; + if let Some(parent) = path.parent() { + std::fs::create_dir_all(parent).map_err(|error| { + EmitError::new(format!( + "failed to create generated crate directory `{}`: {error}", + parent.display() + )) + })?; + } + std::fs::write(&path, &file.source).map_err(|error| { + EmitError::new(format!( + "failed to write generated crate file `{}`: {error}", + path.display() + )) + })?; + } + Ok(()) + } +} + +pub fn write_generated_crates( + generated_crates: &[GeneratedCrate], + output_root: impl AsRef, +) -> Result<(), EmitError> { + for generated_crate in generated_crates { + generated_crate.write_to(output_root.as_ref())?; + } + Ok(()) +} + +pub fn protocol_rust_artifact( + config: &ProtocolArtifactConfig, + stage: ProtocolStage, + role: Role, + source: RustSourceFile, +) -> ProtocolRustArtifact { + let crate_name = config.crate_name(&role).to_owned(); + let path = format!("{crate_name}/src/stages/{}.rs", stage.module_name()); + ProtocolRustArtifact { + role, + stage, + crate_name, + path, + source, + } +} + +pub fn validate_rust_artifact_imports( + config: &ProtocolArtifactConfig, + artifact: &ProtocolRustArtifact, +) -> Result<(), EmitError> { + for import in config.forbidden_imports(&artifact.role) { + if artifact.source.source.contains(import) { + return Err(EmitError::new(format!( + "{} artifact `{}` for {} imports forbidden `{import}`", + artifact.crate_name, + artifact.path, + artifact.stage.name() + ))); + } + } + Ok(()) +} + +pub fn assemble_generated_crates( + config: &ProtocolArtifactConfig, + artifacts: Vec, + dependency_root: &str, +) -> Result, EmitError> { + assemble_generated_crates_with_manifest( + config, + artifacts, + ManifestMode::Standalone { dependency_root }, + ) +} + +pub fn assemble_workspace_generated_crates( + config: &ProtocolArtifactConfig, + artifacts: Vec, +) -> Result, EmitError> { + assemble_generated_crates_with_manifest(config, artifacts, ManifestMode::Workspace) +} + +fn assemble_generated_crates_with_manifest( + config: &ProtocolArtifactConfig, + artifacts: Vec, + manifest_mode: ManifestMode<'_>, +) -> Result, EmitError> { + let mut prover = Vec::new(); + let mut verifier = Vec::new(); + for artifact in artifacts { + validate_rust_artifact_imports(config, &artifact)?; + match artifact.role { + Role::Prover => prover.push(artifact), + Role::Verifier => verifier.push(artifact), + } + } + Ok(vec![ + generated_crate(config, Role::Prover, prover, manifest_mode), + generated_crate(config, Role::Verifier, verifier, manifest_mode), + ]) +} + +fn generated_crate( + config: &ProtocolArtifactConfig, + role: Role, + mut artifacts: Vec, + manifest_mode: ManifestMode<'_>, +) -> GeneratedCrate { + artifacts.sort_by_key(|artifact| artifact.stage.order()); + let crate_name = config.crate_name(&role).to_owned(); + let mut stage_module_lines = Vec::new(); + if role == Role::Verifier { + stage_module_lines.extend( + config + .verifier_runtime_modules + .iter() + .map(|module| format!("pub mod {};", module.module_name)), + ); + } + stage_module_lines.extend(artifacts.iter().map(|artifact| { + format!( + "#[rustfmt::skip]\npub mod {};", + artifact.stage.module_name() + ) + })); + let stage_modules = stage_module_lines.join("\n"); + let mut files = vec![ + GeneratedFile { + path: "Cargo.toml".to_owned(), + source: generated_manifest(config, &role, manifest_mode), + }, + GeneratedFile { + path: "src/lib.rs".to_owned(), + source: generated_lib(config, &role, &artifacts), + }, + generated_role_api_file(config, &role, &artifacts), + GeneratedFile { + path: "src/stages/mod.rs".to_owned(), + source: format!("{stage_modules}\n"), + }, + ]; + if role == Role::Verifier { + files.extend( + config + .verifier_runtime_modules + .iter() + .map(|module| module.file.clone()), + ); + } + files.extend(artifacts.into_iter().map(|artifact| GeneratedFile { + path: format!("src/stages/{}.rs", artifact.stage.module_name()), + source: artifact.source.source, + })); + GeneratedCrate { crate_name, files } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +enum ManifestMode<'a> { + Standalone { dependency_root: &'a str }, + Workspace, +} + +fn generated_manifest( + config: &ProtocolArtifactConfig, + role: &Role, + manifest_mode: ManifestMode<'_>, +) -> String { + let crate_name = config.crate_name(role); + let dependencies = config.dependencies(role); + match manifest_mode { + ManifestMode::Standalone { dependency_root } => { + let patch_section = if config.crates_io_patches.is_empty() { + String::new() + } else { + format!( + "\n[patch.crates-io]\n{}\n", + config.crates_io_patches.join("\n") + ) + }; + let dependencies = dependencies + .into_iter() + .map(|name| standalone_dependency_entry(config, dependency_root, &name)) + .collect::>() + .join("\n"); + format!( + "[package]\nname = \"{crate_name}\"\nversion = \"0.0.0\"\nedition = \"2021\"\n{patch_section}\n[dependencies]\n{dependencies}\n" + ) + } + ManifestMode::Workspace => { + let dependencies = dependencies + .into_iter() + .map(|name| format!("{name}.workspace = true")) + .collect::>() + .join("\n"); + let role_name = match role { + Role::Prover => "prover", + Role::Verifier => "verifier", + }; + let repository = config + .repository + .as_ref() + .map(|repository| format!("repository = \"{repository}\"\n")) + .unwrap_or_default(); + format!( + "[package]\nname = \"{crate_name}\"\nversion = \"0.0.0\"\nedition = \"2021\"\nlicense = \"MIT OR Apache-2.0\"\ndescription = \"Bolt-generated {} {role_name} role crate\"\n{repository}\n[lints]\nworkspace = true\n\n[dependencies]\n{dependencies}\n", + config.protocol_name + ) + } + } +} + +fn standalone_dependency_entry( + config: &ProtocolArtifactConfig, + dependency_root: &str, + package: &str, +) -> String { + config + .standalone_dependency_overrides + .iter() + .find(|dependency| dependency.package == package) + .map_or_else( + || format!("{package} = {{ path = \"{dependency_root}/{package}\" }}"), + |dependency| dependency.manifest_entry.clone(), + ) +} + +fn generated_lib( + config: &ProtocolArtifactConfig, + role: &Role, + artifacts: &[ProtocolRustArtifact], +) -> String { + let protocol_snake = config.protocol_snake(); + let prefix = &config.type_prefix; + let stage_apis = stage_apis(config, artifacts); + let commitment_api = commitment_api(artifacts); + let extension = + active_role_api_extension(config, &stage_apis, commitment_api.as_ref(), artifacts); + let role_module = match (role, extension) { + (Role::Prover, Some(extension)) => extension.prover.lib_module.clone(), + (Role::Prover, None) => format!( + "#[rustfmt::skip]\npub mod prover;\npub mod stages;\n\npub use prover::{{\n default_prover_programs, prove_{protocol_snake}, prove_{protocol_snake}_with_programs,\n Default{prefix}Transcript, {prefix}ProveError, {prefix}ProverArtifacts, {prefix}ProverInputs,\n {prefix}ProverPrograms,\n}};" + ), + (Role::Verifier, Some(extension)) => extension.verifier.lib_module.clone(), + (Role::Verifier, None) => format!( + "pub mod stages;\n#[rustfmt::skip]\npub mod verifier;\n\npub use verifier::{{\n default_verifier_programs, verify_{protocol_snake}, verify_{protocol_snake}_with_programs, {prefix}NamedEval, {prefix}Proof,\n {prefix}StageProof, {prefix}SumcheckOutput, {prefix}VerificationArtifacts, {prefix}VerifierInputs,\n {prefix}VerifierPrograms, {prefix}VerifyError,\n}};" + ), + }; + let stages = artifacts + .iter() + .map(|artifact| { + format!( + " GeneratedStage {{\n name: \"{}\",\n module: \"{}\",\n ordinal: {},\n }},", + artifact.stage.name(), + artifact.stage.module_name(), + artifact.stage.order() + ) + }) + .collect::>() + .join("\n"); + format!( + "{role_module}\n\npub const TRANSCRIPT_LABEL: &[u8] = {};\n\n#[derive(Clone, Copy, Debug, PartialEq, Eq)]\npub struct GeneratedStage {{\n pub name: &'static str,\n pub module: &'static str,\n pub ordinal: usize,\n}}\n\npub const GENERATED_STAGES: &[GeneratedStage] = &[\n{stages}\n];\n\npub fn generated_stage_names() -> impl Iterator {{\n GENERATED_STAGES.iter().map(|stage| stage.name)\n}}\n", + byte_string_literal(&config.transcript_label) + ) +} + +fn generated_role_api_file( + config: &ProtocolArtifactConfig, + role: &Role, + artifacts: &[ProtocolRustArtifact], +) -> GeneratedFile { + match role { + Role::Prover => GeneratedFile { + path: "src/prover.rs".to_owned(), + source: generated_prover_api(config, artifacts), + }, + Role::Verifier => GeneratedFile { + path: "src/verifier.rs".to_owned(), + source: generated_verifier_api(config, artifacts), + }, + } +} + +#[derive(Clone, Debug)] +struct StageRustApi { + field_name: String, + module_alias: String, + variant_name: String, + output_type: String, + eval_type: String, + artifacts_type: String, + error_type: String, + verifier_fn: Option, + with_program_verifier_fn: Option, + program_type: Option, + program_const: Option, + prover_fn: Option, + with_program_prover_fn: Option, + kernel_module: Option, + opening_input_type: Option, + ram_data_type: Option, + verifier_data_type: Option, +} + +#[derive(Clone, Debug)] +struct CommitmentRustApi { + field_name: String, + module_alias: String, + variant_name: String, + artifacts_type: String, + error_type: String, + verifier_fn: Option, + with_program_verifier_fn: Option, + program_type: Option, + program_const: Option, + prover_fn: Option, + with_program_prover_fn: Option, + input_provider_trait: Option, +} + +fn generated_verifier_api( + config: &ProtocolArtifactConfig, + artifacts: &[ProtocolRustArtifact], +) -> String { + let stages = stage_apis(config, artifacts); + let modules = role_modules(artifacts); + let commitment = commitment_api(artifacts); + let extension = active_role_api_extension(config, &stages, commitment.as_ref(), artifacts); + let prefix = &config.type_prefix; + let protocol_snake = config.protocol_snake(); + let field_type = config.field_type.ident(); + let transcript_trait = config.transcript_trait.ident(); + let commitment_type = config.commitment_type.ident(); + let runtime_named_eval_type = &config.verifier_named_eval_type.path; + let runtime_sumcheck_output_type = &config.verifier_sumcheck_output_type.path; + let runtime_stage_proof_type = &config.verifier_stage_proof_type.path; + let named_eval_type = format!("{prefix}NamedEval"); + let sumcheck_output_type = format!("{prefix}SumcheckOutput"); + let stage_proof_type = format!("{prefix}StageProof"); + let proof_type = format!("{prefix}Proof"); + let verifier_inputs_type = format!("{prefix}VerifierInputs"); + let verifier_programs_type = format!("{prefix}VerifierPrograms"); + let verification_artifacts_type = format!("{prefix}VerificationArtifacts"); + let verify_error_type = format!("{prefix}VerifyError"); + + let mut source = String::new(); + if let Some(extension) = extension { + source.push_str(&extension.verifier.imports); + } else { + if commitment.is_some() { + source.push_str(&config.commitment_type.use_line()); + } + source.push_str(&config.field_type.use_line()); + source.push_str(&config.transcript_trait.use_line()); + } + source.push('\n'); + if !modules.is_empty() { + source.push_str(&format!( + "use crate::stages::{{{}}};\n\n", + aliased_modules(&modules).join(", ") + )); + } + + source.push_str(&format!( + "pub type {named_eval_type} = {runtime_named_eval_type}<{field_type}>;\n\ + pub type {sumcheck_output_type} = {runtime_sumcheck_output_type}<{field_type}>;\n\ + pub type {stage_proof_type} = {runtime_stage_proof_type}<{field_type}>;\n\n", + )); + source.push_str(&format!( + "#[derive(Clone, Debug)]\npub struct {proof_type} {{\n" + )); + if commitment.is_some() { + source.push_str(&format!( + " pub commitments: Vec>,\n" + )); + } + for stage in &stages { + source.push_str(&format!( + " pub {}: {stage_proof_type},\n", + stage.field_name + )); + } + if let Some(extension) = extension { + source.push_str(&extension.verifier.proof_fields); + } + source.push_str("}\n\n"); + + if let Some(extension) = extension { + source.push_str(&extension.verifier.proof_items); + } + + let verifier_inputs_derive = extension + .and_then(|extension| extension.verifier.inputs_derive.as_deref()) + .unwrap_or("#[derive(Clone, Copy, Debug)]"); + source.push_str(&format!( + "{verifier_inputs_derive}\npub struct {verifier_inputs_type}<'a> {{\n" + )); + for stage in &stages { + if let Some(opening_type) = &stage.opening_input_type { + source.push_str(&format!( + " pub {}_openings: &'a [{}::{}<{field_type}>],\n", + stage.field_name, stage.module_alias, opening_type + )); + } + if let Some(ram_type) = &stage.ram_data_type { + source.push_str(&format!( + " pub {}_ram: Option<&'a {}::{}<'a>>,\n", + stage.field_name, stage.module_alias, ram_type + )); + } + if let Some(data_type) = &stage.verifier_data_type { + source.push_str(&format!( + " pub {}_data: Option<&'a {}::{}>,\n", + stage.field_name, stage.module_alias, data_type + )); + } + } + if let Some(extension) = extension { + source.push_str(&extension.verifier.input_fields); + } + source.push_str("}\n\n"); + + source.push_str(&format!( + "#[derive(Clone, Copy, Debug)]\npub struct {verifier_programs_type} {{\n" + )); + if let Some(commitment) = &commitment { + if let (Some(program_type), Some(_), Some(_)) = ( + &commitment.program_type, + &commitment.program_const, + &commitment.with_program_verifier_fn, + ) { + source.push_str(&format!( + " pub {}: &'static {}::{},\n", + commitment.field_name, commitment.module_alias, program_type + )); + } + } + for stage in &stages { + if let (Some(program_type), Some(_), Some(_)) = ( + &stage.program_type, + &stage.program_const, + &stage.with_program_verifier_fn, + ) { + source.push_str(&format!( + " pub {}: &'static {}::{},\n", + stage.field_name, stage.module_alias, program_type + )); + } + } + if let Some(extension) = extension { + source.push_str(&extension.verifier.program_fields); + } + source.push_str("}\n\n"); + + source.push_str(&format!( + "pub fn default_verifier_programs() -> {verifier_programs_type} {{\n {verifier_programs_type} {{\n" + )); + if let Some(commitment) = &commitment { + if let (Some(_), Some(program_const), Some(_)) = ( + &commitment.program_type, + &commitment.program_const, + &commitment.with_program_verifier_fn, + ) { + source.push_str(&format!( + " {}: &{}::{},\n", + commitment.field_name, commitment.module_alias, program_const + )); + } + } + for stage in &stages { + if let (Some(_), Some(program_const), Some(_)) = ( + &stage.program_type, + &stage.program_const, + &stage.with_program_verifier_fn, + ) { + source.push_str(&format!( + " {}: &{}::{},\n", + stage.field_name, stage.module_alias, program_const + )); + } + } + if let Some(extension) = extension { + source.push_str(&extension.verifier.default_program_fields); + } + source.push_str(" }\n}\n\n"); + + source.push_str(&format!( + "#[derive(Clone, Debug)]\npub struct {verification_artifacts_type} {{\n" + )); + if let Some(commitment) = &commitment { + source.push_str(&format!( + " pub {}: {}::{},\n", + commitment.field_name, commitment.module_alias, commitment.artifacts_type + )); + } + for stage in &stages { + source.push_str(&format!( + " pub {}: {}::{}<{field_type}>,\n", + stage.field_name, stage.module_alias, stage.artifacts_type + )); + } + source.push_str("}\n\n"); + + source.push_str(&format!( + "#[derive(Debug)]\npub enum {verify_error_type} {{\n" + )); + if let Some(commitment) = &commitment { + source.push_str(&format!( + " {}({}::{}),\n", + commitment.variant_name, commitment.module_alias, commitment.error_type + )); + } + for stage in &stages { + source.push_str(&format!( + " {}({}::{}),\n", + stage.variant_name, stage.module_alias, stage.error_type + )); + } + if let Some(extension) = extension { + source.push_str(&extension.verifier.error_variants); + } + source.push_str("}\n\n"); + + if let Some(extension) = extension { + source.push_str(&extension.verifier.error_items); + } + + source.push_str(&format!( + "macro_rules! define_{protocol_snake}_verify_error_from {{\n ($module:ident, $error_ty:ident, $variant:ident) => {{\n impl From<$module::$error_ty> for {verify_error_type} {{\n fn from(error: $module::$error_ty) -> Self {{\n Self::$variant(error)\n }}\n }}\n }};\n}}\n\n" + )); + if let Some(commitment) = &commitment { + source.push_str(&format!( + "define_{protocol_snake}_verify_error_from!({module}, {error}, {variant});\n", + module = commitment.module_alias, + error = commitment.error_type, + variant = commitment.variant_name, + )); + } + for stage in &stages { + source.push_str(&format!( + "define_{protocol_snake}_verify_error_from!({}, {}, {});\n", + stage.module_alias, stage.error_type, stage.variant_name + )); + } + if commitment.is_some() || !stages.is_empty() { + source.push('\n'); + } + if let Some(extension) = extension { + source.push_str(&extension.verifier.error_conversions); + } + + source.push_str(&format!( + "pub fn verify_{protocol_snake}>(proof: &{proof_type}, inputs: {verifier_inputs_type}<'_>, transcript: &mut T) -> Result<{verification_artifacts_type}, {verify_error_type}> {{\n", + )); + source.push_str(&format!( + " verify_{protocol_snake}_with_programs(proof, inputs, default_verifier_programs(), transcript)\n}}\n\n" + )); + if let Some(extension) = extension { + source.push_str(&extension.verifier.after_default_verify); + } + source.push_str(&format!( + "pub fn verify_{protocol_snake}_with_programs>(proof: &{proof_type}, inputs: {verifier_inputs_type}<'_>, programs: {verifier_programs_type}, transcript: &mut T) -> Result<{verification_artifacts_type}, {verify_error_type}> {{\n", + )); + if let Some(extension) = extension { + source.push_str(&extension.verifier.with_programs_body_intro); + } + if let Some(prefix) = &config.instrumentation_prefix { + source.push_str(&format!( + " let _verify_span = tracing::info_span!(\"{prefix}.verify\").entered();\n" + )); + } + if let Some(commitment) = &commitment { + let verifier_fn = commitment + .with_program_verifier_fn + .as_deref() + .or(commitment.verifier_fn.as_deref()) + .unwrap_or("missing_commitment_verifier_function"); + let program_arg = if commitment.with_program_verifier_fn.is_some() + && commitment.program_type.is_some() + && commitment.program_const.is_some() + { + format!("programs.{}, ", commitment.field_name) + } else { + String::new() + }; + source.push_str(&format!( + " let {field} = {module}::{verifier_fn}({program_arg}&proof.commitments, transcript)?;\n", + field = commitment.field_name, + module = commitment.module_alias, + )); + } + if let Some(extension) = extension { + if !extension.verifier.stage_verification_override.is_empty() { + source.push_str(&extension.verifier.stage_verification_override); + } else { + emit_verifier_stage_calls(&mut source, &stages); + } + } else { + emit_verifier_stage_calls(&mut source, &stages); + } + if let Some(extension) = extension { + source.push_str(&extension.verifier.after_stage_verification); + } + source.push_str(&format!("\n Ok({verification_artifacts_type} {{\n")); + if let Some(commitment) = &commitment { + source.push_str(&format!(" {},\n", commitment.field_name)); + } + for stage in &stages { + source.push_str(&format!(" {},\n", stage.field_name)); + } + source.push_str(" })\n}\n\n"); + + if let Some(extension) = extension { + source.push_str(&extension.verifier.helper_items); + } + + source +} + +fn emit_verifier_stage_calls(source: &mut String, stages: &[StageRustApi]) { + for stage in stages { + let verifier_fn = stage + .with_program_verifier_fn + .as_deref() + .or(stage.verifier_fn.as_deref()) + .unwrap_or("missing_verifier_function"); + let mut args = vec![format!("&proof.{}", stage.field_name)]; + if stage.with_program_verifier_fn.is_some() + && stage.program_type.is_some() + && stage.program_const.is_some() + { + args.insert(0, format!("programs.{}", stage.field_name)); + } + if stage.opening_input_type.is_some() { + args.push(format!("inputs.{}_openings", stage.field_name)); + } + if stage.ram_data_type.is_some() { + args.push(format!("inputs.{}_ram", stage.field_name)); + } + if stage.verifier_data_type.is_some() { + args.push(format!("inputs.{}_data", stage.field_name)); + } + args.push("transcript".to_owned()); + source.push_str(&format!( + " let {} = {}::{}({})?;\n", + stage.field_name, + stage.module_alias, + verifier_fn, + args.join(", ") + )); + } +} + +fn generated_prover_api( + config: &ProtocolArtifactConfig, + artifacts: &[ProtocolRustArtifact], +) -> String { + let stages = stage_apis(config, artifacts); + let modules = role_modules(artifacts); + let kernel_modules = unique_kernel_modules(&stages); + let commitment = commitment_api(artifacts); + let has_commitment = commitment.is_some(); + let extension = active_role_api_extension(config, &stages, commitment.as_ref(), artifacts); + let generic_params = prover_generic_params(&stages, has_commitment); + let prefix = &config.type_prefix; + let protocol_snake = config.protocol_snake(); + let field_type = config.field_type.ident(); + let default_transcript_type = config.default_transcript_type.ident(); + let transcript_trait = config.transcript_trait.ident(); + let prover_setup_type = config.prover_setup_type.ident(); + let verifier_import = config.verifier_crate_import(); + let named_eval_type = format!("{prefix}NamedEval"); + let sumcheck_output_type = format!("{prefix}SumcheckOutput"); + let stage_proof_type = format!("{prefix}StageProof"); + let proof_type = format!("{prefix}Proof"); + let prover_inputs_type = format!("{prefix}ProverInputs"); + let prover_programs_type = format!("{prefix}ProverPrograms"); + let prover_artifacts_type = format!("{prefix}ProverArtifacts"); + let prove_error_type = format!("{prefix}ProveError"); + let default_transcript_alias = format!("Default{prefix}Transcript"); + + let mut source = String::new(); + if let Some(extension) = extension { + source.push_str(&extension.prover.imports); + } else { + if has_commitment { + source.push_str(&config.prover_setup_type.use_line()); + } + source.push_str(&config.field_type.use_line()); + if !kernel_modules.is_empty() { + let kernel_crate = config + .kernel_crate + .as_ref() + .map_or("missing_kernel_crate", |kernel_crate| { + kernel_crate.import.as_str() + }); + source.push_str(&format!( + "use {kernel_crate}::{{{}}};\n", + kernel_modules.join(", ") + )); + } + source.push_str(&config.default_transcript_type.use_line()); + source.push_str(&config.transcript_trait.use_line()); + source.push_str(&format!( + "use {verifier_import}::{{{named_eval_type}, {proof_type}, {stage_proof_type}, {sumcheck_output_type}}};\n\n", + )); + } + if !modules.is_empty() { + source.push_str(&format!( + "use crate::stages::{{{}}};\n\n", + aliased_modules(&modules).join(", ") + )); + } + source.push_str(&format!( + "pub type {default_transcript_alias} = {default_transcript_type}<{field_type}>;\n\n" + )); + + source.push_str(&format!( + "pub struct {prover_inputs_type}<'a, {}> {{\n", + generic_params.join(", ") + )); + if has_commitment { + source.push_str(" pub commitment_inputs: &'a mut CommitmentInputs,\n"); + source.push_str(&format!(" pub prover_setup: &'a {prover_setup_type},\n")); + } + for stage in &stages { + source.push_str(&format!( + " pub {}_executor: &'a mut {}Executor,\n", + stage.field_name, stage.variant_name + )); + } + if let Some(extension) = extension { + source.push_str(&extension.prover.input_fields); + } + source.push_str("}\n\n"); + + source.push_str(&format!( + "#[derive(Clone, Copy, Debug)]\npub struct {prover_programs_type} {{\n" + )); + if let Some(commitment) = &commitment { + if let (Some(program_type), Some(_), Some(_)) = ( + &commitment.program_type, + &commitment.program_const, + &commitment.with_program_prover_fn, + ) { + source.push_str(&format!( + " pub {}: &'static {}::{},\n", + commitment.field_name, commitment.module_alias, program_type + )); + } + } + for stage in &stages { + if let (Some(program_type), Some(_), Some(_)) = ( + &stage.program_type, + &stage.program_const, + &stage.with_program_prover_fn, + ) { + let program_module = stage + .kernel_module + .as_deref() + .unwrap_or(stage.module_alias.as_str()); + source.push_str(&format!( + " pub {}: &'static {}::{},\n", + stage.field_name, program_module, program_type + )); + } + } + if let Some(extension) = extension { + source.push_str(&extension.prover.program_fields); + } + source.push_str("}\n\n"); + + source.push_str(&format!( + "pub fn default_prover_programs() -> {prover_programs_type} {{\n {prover_programs_type} {{\n" + )); + if let Some(commitment) = &commitment { + if let (Some(_), Some(program_const), Some(_)) = ( + &commitment.program_type, + &commitment.program_const, + &commitment.with_program_prover_fn, + ) { + source.push_str(&format!( + " {}: &{}::{},\n", + commitment.field_name, commitment.module_alias, program_const + )); + } + } + for stage in &stages { + if let (Some(_), Some(program_const), Some(_)) = ( + &stage.program_type, + &stage.program_const, + &stage.with_program_prover_fn, + ) { + source.push_str(&format!( + " {}: &{}::{},\n", + stage.field_name, stage.module_alias, program_const + )); + } + } + if let Some(extension) = extension { + source.push_str(&extension.prover.default_program_fields); + } + source.push_str(" }\n}\n\n"); + + source.push_str(&format!( + "#[derive(Clone, Debug)]\npub struct {prover_artifacts_type} {{\n" + )); + if let Some(commitment) = &commitment { + source.push_str(&format!( + " pub {}: {}::{},\n", + commitment.field_name, commitment.module_alias, commitment.artifacts_type + )); + } + for stage in &stages { + let kernel_module = stage + .kernel_module + .as_deref() + .unwrap_or(stage.module_alias.as_str()); + source.push_str(&format!( + " pub {}: {}::{}<{field_type}>,\n", + stage.field_name, kernel_module, stage.artifacts_type + )); + } + source.push_str("}\n\n"); + + source.push_str(&format!( + "#[derive(Debug)]\npub enum {prove_error_type} {{\n" + )); + if let Some(commitment) = &commitment { + source.push_str(&format!( + " {}({}::{}),\n", + commitment.variant_name, commitment.module_alias, commitment.error_type + )); + } + for stage in &stages { + let kernel_module = stage + .kernel_module + .as_deref() + .unwrap_or(stage.module_alias.as_str()); + source.push_str(&format!( + " {}({}::{}),\n", + stage.variant_name, kernel_module, stage.error_type + )); + } + if let Some(extension) = extension { + source.push_str(&extension.prover.error_variants); + } + source.push_str("}\n\n"); + + if let Some(extension) = extension { + source.push_str(&extension.prover.error_items); + } + + if let Some(commitment) = &commitment { + source.push_str(&format!( + "impl From<{module}::{error}> for {prove_error_type} {{\n fn from(error: {module}::{error}) -> Self {{\n Self::{variant}(error)\n }}\n}}\n\n", + module = commitment.module_alias, + error = commitment.error_type, + variant = commitment.variant_name, + )); + } + for stage in &stages { + let kernel_module = stage + .kernel_module + .as_deref() + .unwrap_or(stage.module_alias.as_str()); + source.push_str(&format!( + "impl From<{}::{}> for {prove_error_type} {{\n fn from(error: {}::{}) -> Self {{\n Self::{}(error)\n }}\n}}\n\n", + kernel_module, stage.error_type, kernel_module, stage.error_type, stage.variant_name + )); + } + if let Some(extension) = extension { + source.push_str(&extension.prover.error_conversions); + } + + source.push_str(&format!( + "pub fn prove_{protocol_snake}<{}, T>(\n inputs: {prover_inputs_type}<'_, {}>,\n transcript: &mut T,\n) -> Result<({proof_type}, {prover_artifacts_type}), {prove_error_type}>\nwhere\n", + generic_params.join(", "), + generic_params.join(", ") + )); + if let Some(commitment) = &commitment { + let input_provider = commitment + .input_provider_trait + .as_deref() + .unwrap_or("MissingCommitmentInputProvider"); + source.push_str(&format!( + " CommitmentInputs: {}::{input_provider},\n", + commitment.module_alias + )); + } + for stage in &stages { + let kernel_module = stage + .kernel_module + .as_deref() + .unwrap_or(stage.module_alias.as_str()); + let kernel_trait = kernel_executor_type(&stage.error_type); + source.push_str(&format!( + " {}Executor: {}::{}<{field_type}>,\n", + stage.variant_name, kernel_module, kernel_trait + )); + } + source.push_str(&format!( + " T: {transcript_trait},\n" + )); + source.push_str("{\n"); + source.push_str(&format!( + " prove_{protocol_snake}_with_programs(inputs, default_prover_programs(), transcript)\n}}\n\n" + )); + + source.push_str(&format!( + "pub fn prove_{protocol_snake}_with_programs<{}, T>(\n inputs: {prover_inputs_type}<'_, {}>,\n programs: {prover_programs_type},\n transcript: &mut T,\n) -> Result<({proof_type}, {prover_artifacts_type}), {prove_error_type}>\nwhere\n", + generic_params.join(", "), + generic_params.join(", ") + )); + if let Some(commitment) = &commitment { + let input_provider = commitment + .input_provider_trait + .as_deref() + .unwrap_or("MissingCommitmentInputProvider"); + source.push_str(&format!( + " CommitmentInputs: {}::{input_provider},\n", + commitment.module_alias + )); + } + for stage in &stages { + let kernel_module = stage + .kernel_module + .as_deref() + .unwrap_or(stage.module_alias.as_str()); + let kernel_trait = kernel_executor_type(&stage.error_type); + source.push_str(&format!( + " {}Executor: {}::{}<{field_type}>,\n", + stage.variant_name, kernel_module, kernel_trait + )); + } + source.push_str(&format!( + " T: {transcript_trait},\n" + )); + source.push_str("{\n"); + if let Some(prefix) = &config.instrumentation_prefix { + source.push_str(&format!( + " let _prove_span = tracing::info_span!(\"{prefix}.prove\").entered();\n" + )); + } + if let Some(commitment) = &commitment { + let prover_fn = commitment + .with_program_prover_fn + .as_deref() + .or(commitment.prover_fn.as_deref()) + .unwrap_or("missing_commitment_prover_function"); + let program_arg = if commitment.with_program_prover_fn.is_some() + && commitment.program_type.is_some() + && commitment.program_const.is_some() + { + format!("programs.{}, ", commitment.field_name) + } else { + String::new() + }; + if let Some(prefix) = &config.instrumentation_prefix { + source.push_str(&format!( + " let _{field}_span = tracing::info_span!(\"{prefix}.{field}\").entered();\n", + field = commitment.field_name + )); + } + source.push_str(&format!( + " let {field} = {module}::{prover_fn}(\n {program_arg}inputs.commitment_inputs,\n inputs.prover_setup,\n transcript,\n )?;\n", + field = commitment.field_name, + module = commitment.module_alias + )); + if config.instrumentation_prefix.is_some() { + source.push_str(&format!(" drop(_{}_span);\n", commitment.field_name)); + } + } + for stage in &stages { + let prover_fn = stage + .with_program_prover_fn + .as_deref() + .or(stage.prover_fn.as_deref()) + .unwrap_or("missing_prover_function"); + let program_arg = if stage.with_program_prover_fn.is_some() + && stage.program_type.is_some() + && stage.program_const.is_some() + { + format!("programs.{}, ", stage.field_name) + } else { + String::new() + }; + if let Some(prefix) = &config.instrumentation_prefix { + source.push_str(&format!( + " let _{field}_span = tracing::info_span!(\"{prefix}.{span}\").entered();\n", + field = stage.field_name, + span = generated_stage_span_name(&stage.field_name) + )); + } + source.push_str(&format!( + " let {} = {}::{}({program_arg}inputs.{}_executor, transcript)?;\n", + stage.field_name, stage.module_alias, prover_fn, stage.field_name + )); + if config.instrumentation_prefix.is_some() { + source.push_str(&format!(" drop(_{}_span);\n", stage.field_name)); + } + } + if let Some(extension) = extension { + source.push_str(&extension.prover.after_stage_execution); + } + source.push_str(&format!("\n let proof = {proof_type} {{\n")); + if let Some(commitment) = &commitment { + source.push_str(&format!( + " commitments: {}.commitments.clone(),\n", + commitment.field_name + )); + } + for stage in &stages { + source.push_str(&format!( + " {}: {}_proof(&{}),\n", + stage.field_name, stage.field_name, stage.field_name + )); + } + if let Some(extension) = extension { + source.push_str(&extension.prover.proof_fields); + } + source.push_str(&format!( + " }};\n let artifacts = {prover_artifacts_type} {{\n" + )); + if let Some(commitment) = &commitment { + source.push_str(&format!(" {},\n", commitment.field_name)); + } + for stage in &stages { + source.push_str(&format!(" {},\n", stage.field_name)); + } + source.push_str(" };\n Ok((proof, artifacts))\n}\n\n"); + + if let Some(extension) = extension { + source.push_str(&extension.prover.helper_items); + } + + for stage in &stages { + let kernel_module = stage + .kernel_module + .as_deref() + .unwrap_or(stage.module_alias.as_str()); + source.push_str(&format!( + "pub fn {field}_proof(artifacts: &{kernel}::{artifacts_ty}<{field_type}>) -> {stage_proof_type} {{\n {stage_proof_type} {{\n sumchecks: artifacts.sumchecks.iter().map({field}_sumcheck).collect(),\n }}\n}}\n\n", + field = stage.field_name, + kernel = kernel_module, + artifacts_ty = stage.artifacts_type + )); + source.push_str(&format!( + "fn {field}_sumcheck(output: &{kernel}::{output_ty}<{field_type}>) -> {sumcheck_output_type} {{\n {sumcheck_output_type} {{\n driver: output.driver,\n point: output.point.clone(),\n evals: output.evals.iter().map({field}_eval).collect(),\n proof: output.proof.clone(),\n }}\n}}\n\n", + field = stage.field_name, + kernel = kernel_module, + output_ty = stage.output_type + )); + source.push_str(&format!( + "fn {field}_eval(eval: &{kernel}::{eval_ty}<{field_type}>) -> {named_eval_type} {{\n {named_eval_type} {{\n name: eval.name,\n oracle: eval.oracle,\n value: eval.value,\n }}\n}}\n\n", + field = stage.field_name, + kernel = kernel_module, + eval_ty = stage.eval_type + )); + } + source +} + +fn stage_apis( + config: &ProtocolArtifactConfig, + artifacts: &[ProtocolRustArtifact], +) -> Vec { + artifacts + .iter() + .filter(|artifact| artifact.stage.is_proof()) + .map(|artifact| stage_api(config, artifact)) + .collect() +} + +fn stage_api(config: &ProtocolArtifactConfig, artifact: &ProtocolRustArtifact) -> StageRustApi { + let source = artifact.source.source.as_str(); + let artifacts_type = find_type_with_suffix(source, "ExecutionArtifacts").unwrap_or_else(|| { + format!( + "{}ExecutionArtifacts", + upper_camel(artifact.stage.module_name()) + ) + }); + let prefix = artifacts_type + .strip_suffix("ExecutionArtifacts") + .unwrap_or(&artifacts_type); + let opening_input_name = format!("{prefix}OpeningInputValue"); + let ram_data_name = format!("{prefix}RamData"); + let verifier_data_name = format!("{prefix}VerifierData"); + let program_type_suffix = match artifact.role { + Role::Prover => "CpuProgramPlan", + Role::Verifier => "VerifierProgramPlan", + }; + let program_type = find_type_with_suffix(source, program_type_suffix); + let program_const = program_type + .as_deref() + .and_then(|program_type| find_public_const_of_type(source, program_type)); + let error_type = match artifact.role { + Role::Prover => find_type_with_suffix(source, "KernelError") + .unwrap_or_else(|| format!("{prefix}KernelError")), + Role::Verifier => find_public_item(source, "pub enum ", "Error") + .unwrap_or_else(|| format!("Verify{prefix}Error")), + }; + StageRustApi { + field_name: artifact.stage.module_name().to_owned(), + module_alias: module_alias(artifact.stage.module_name()), + variant_name: upper_camel(artifact.stage.module_name()), + output_type: format!("{prefix}SumcheckOutput"), + eval_type: format!("{prefix}NamedEval"), + artifacts_type, + error_type, + verifier_fn: find_public_fn(source, &["verify_"]), + with_program_verifier_fn: find_public_fn_containing(source, &["verify_"], "_with_program"), + program_type, + program_const, + prover_fn: find_public_fn(source, &["prove_", "execute_"]), + with_program_prover_fn: find_public_fn_containing( + source, + &["prove_", "execute_"], + "_with_program", + ), + kernel_module: find_kernel_module(config, source), + opening_input_type: has_public_type_name(source, &opening_input_name) + .then_some(opening_input_name), + ram_data_type: has_public_type_name(source, &ram_data_name).then_some(ram_data_name), + verifier_data_type: has_public_type_name(source, &verifier_data_name) + .then_some(verifier_data_name), + } +} + +fn generated_stage_span_name(field_name: &str) -> &str { + field_name.strip_suffix("_outer").unwrap_or(field_name) +} + +fn commitment_api(artifacts: &[ProtocolRustArtifact]) -> Option { + let artifact = artifacts + .iter() + .find(|artifact| artifact.stage.is_commitment())?; + let source = artifact.source.source.as_str(); + let artifacts_type = find_type_with_suffix(source, "Artifacts") + .unwrap_or_else(|| format!("{}Artifacts", upper_camel(artifact.stage.module_name()))); + let error_type = find_public_item(source, "pub enum ", "Error") + .unwrap_or_else(|| format!("{}Error", upper_camel(artifact.stage.module_name()))); + let input_provider_trait = find_public_item(source, "pub trait ", "InputProvider"); + let program_type_suffix = match artifact.role { + Role::Prover => "ProverProgramPlan", + Role::Verifier => "VerifierProgramPlan", + }; + let program_type = find_type_with_suffix(source, program_type_suffix); + let program_const = program_type + .as_deref() + .and_then(|program_type| find_public_const_of_type(source, program_type)); + Some(CommitmentRustApi { + field_name: artifact.stage.module_name().to_owned(), + module_alias: module_alias(artifact.stage.module_name()), + variant_name: upper_camel(artifact.stage.module_name()), + artifacts_type, + error_type, + verifier_fn: find_public_fn(source, &["verify_"]), + with_program_verifier_fn: find_public_fn_containing(source, &["verify_"], "_with_program"), + program_type, + program_const, + prover_fn: find_public_fn(source, &["prove_"]), + with_program_prover_fn: find_public_fn_containing(source, &["prove_"], "_with_program"), + input_provider_trait, + }) +} + +fn active_role_api_extension<'a>( + config: &'a ProtocolArtifactConfig, + stages: &[StageRustApi], + commitment: Option<&CommitmentRustApi>, + artifacts: &[ProtocolRustArtifact], +) -> Option<&'a ProtocolArtifactExtension> { + let extension = config.role_api_extension.as_ref()?; + if extension.required_commitment && commitment.is_none() { + return None; + } + if !extension + .required_proof_stages + .iter() + .all(|required| stages.iter().any(|stage| &stage.field_name == required)) + { + return None; + } + if !extension.required_artifact_stages.iter().all(|required| { + artifacts + .iter() + .any(|artifact| artifact.stage.module_name() == required) + }) { + return None; + } + Some(extension) +} + +fn role_modules(artifacts: &[ProtocolRustArtifact]) -> Vec { + artifacts + .iter() + .map(|artifact| artifact.stage.module_name().to_owned()) + .collect() +} + +fn aliased_modules(modules: &[String]) -> Vec { + modules + .iter() + .map(|module| format!("{module} as {}", module_alias(module))) + .collect() +} + +fn module_alias(module: &str) -> String { + format!("{module}_stage") +} + +fn unique_kernel_modules(stages: &[StageRustApi]) -> Vec { + let mut modules = Vec::new(); + for stage in stages { + if let Some(kernel_module) = &stage.kernel_module { + if !modules.contains(kernel_module) { + modules.push(kernel_module.clone()); + } + } + } + modules +} + +fn prover_generic_params(stages: &[StageRustApi], has_commitment: bool) -> Vec { + let mut params = if has_commitment { + vec!["CommitmentInputs".to_owned()] + } else { + Vec::new() + }; + params.extend( + stages + .iter() + .map(|stage| format!("{}Executor", stage.variant_name)), + ); + params +} + +fn find_public_item(source: &str, prefix: &str, suffix: &str) -> Option { + source.lines().find_map(|line| { + let trimmed = line.trim_start(); + let rest = trimmed.strip_prefix(prefix)?; + let name = rest + .split(|character: char| { + matches!(character, '<' | '(' | '{') || character.is_whitespace() + }) + .next()?; + name.ends_with(suffix).then(|| name.to_owned()) + }) +} + +fn find_type_with_suffix(source: &str, suffix: &str) -> Option { + source + .split(|character: char| !character.is_ascii_alphanumeric() && character != '_') + .find(|token| token.ends_with(suffix) && token.len() > suffix.len()) + .map(ToOwned::to_owned) +} + +fn find_public_fn(source: &str, prefixes: &[&str]) -> Option { + source.lines().find_map(|line| { + let trimmed = line.trim_start(); + let rest = trimmed.strip_prefix("pub fn ")?; + let name = rest + .split(|character: char| matches!(character, '<' | '(') || character.is_whitespace()) + .next()?; + prefixes + .iter() + .any(|prefix| name.starts_with(prefix)) + .then(|| name.to_owned()) + }) +} + +fn find_public_fn_containing(source: &str, prefixes: &[&str], needle: &str) -> Option { + source.lines().find_map(|line| { + let trimmed = line.trim_start(); + let rest = trimmed.strip_prefix("pub fn ")?; + let name = rest + .split(|character: char| matches!(character, '<' | '(') || character.is_whitespace()) + .next()?; + (name.contains(needle) && prefixes.iter().any(|prefix| name.starts_with(prefix))) + .then(|| name.to_owned()) + }) +} + +fn find_public_const_of_type(source: &str, type_name: &str) -> Option { + source.lines().find_map(|line| { + let trimmed = line.trim_start(); + let rest = trimmed.strip_prefix("pub const ")?; + let name = rest + .split(|character: char| character == ':' || character.is_whitespace()) + .next()?; + rest.contains(&format!(": {type_name}")) + .then(|| name.to_owned()) + }) +} + +fn has_public_type_name(source: &str, type_name: &str) -> bool { + source.contains(&format!("pub struct {type_name}")) + || source.contains(&format!("pub type {type_name}")) + || source.contains(&format!(" as {type_name}")) +} + +fn kernel_executor_type(error_type: &str) -> String { + error_type.strip_suffix("KernelError").map_or_else( + || { + error_type + .replace("Verify", "") + .replace("Error", "KernelExecutor") + }, + |prefix| format!("{prefix}KernelExecutor"), + ) +} + +fn find_kernel_module(config: &ProtocolArtifactConfig, source: &str) -> Option { + let kernel_import = config.kernel_crate.as_ref()?.import.as_str(); + let prefix = format!("use {kernel_import}::"); + source.lines().find_map(|line| { + let rest = line.trim_start().strip_prefix(&prefix)?; + rest.split(|character: char| matches!(character, ':' | '{') || character.is_whitespace()) + .next() + .filter(|name| !name.is_empty()) + .map(ToOwned::to_owned) + }) +} + +fn upper_camel(name: &str) -> String { + let mut output = String::new(); + for segment in name.split('_') { + let mut chars = segment.chars(); + if let Some(first) = chars.next() { + output.extend(first.to_uppercase()); + output.push_str(chars.as_str()); + } + } + output +} + +fn snake_case(name: &str) -> String { + let mut output = String::new(); + for (index, character) in name.chars().enumerate() { + if character.is_ascii_uppercase() { + if index != 0 { + output.push('_'); + } + output.extend(character.to_lowercase()); + } else if character == '-' || character == ' ' { + output.push('_'); + } else { + output.push(character); + } + } + output +} + +fn rust_crate_ident(package_name: &str) -> String { + package_name.replace('-', "_") +} + +fn byte_string_literal(label: &str) -> String { + let escaped = label.escape_default().to_string(); + format!("b\"{escaped}\"") +} + +fn generated_file_path(root: &Path, relative_path: &str) -> Result { + let path = Path::new(relative_path); + if path.is_absolute() + || path.components().any(|component| { + matches!( + component, + Component::ParentDir | Component::RootDir | Component::Prefix(_) + ) + }) + { + return Err(EmitError::new(format!( + "generated crate file path `{relative_path}` must be relative and stay inside the crate" + ))); + } + Ok(root.join(path)) +} diff --git a/crates/bolt/src/emit/rust/mod.rs b/crates/bolt/src/emit/rust/mod.rs new file mode 100644 index 0000000000..aeb2a0bcf2 --- /dev/null +++ b/crates/bolt/src/emit/rust/mod.rs @@ -0,0 +1,19 @@ +mod artifacts; +mod source; + +pub(crate) fn push_format(source: &mut String, args: std::fmt::Arguments<'_>) { + use std::fmt::Write as _; + + if source.write_fmt(args).is_err() { + std::process::abort(); + } +} + +pub use artifacts::{ + assemble_generated_crates, assemble_workspace_generated_crates, protocol_rust_artifact, + validate_rust_artifact_imports, write_generated_crates, ArtifactCrateRole, GeneratedCrate, + GeneratedFile, ProtocolArtifactConfig, ProtocolArtifactExtension, ProtocolCrateRef, + ProtocolProverApiExtension, ProtocolRuntimeModule, ProtocolRustArtifact, ProtocolStage, + ProtocolStageKind, ProtocolStandaloneDependency, ProtocolVerifierApiExtension, RustTypeRef, +}; +pub use source::{EmitError, RustSourceFile}; diff --git a/crates/bolt/src/emit/rust/source.rs b/crates/bolt/src/emit/rust/source.rs new file mode 100644 index 0000000000..8adfb86d44 --- /dev/null +++ b/crates/bolt/src/emit/rust/source.rs @@ -0,0 +1,37 @@ +use std::error::Error; +use std::fmt::{self, Display, Formatter}; + +use crate::schema::SchemaError; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct RustSourceFile { + pub filename: String, + pub source: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct EmitError { + message: String, +} + +impl EmitError { + pub(crate) fn new(message: impl Into) -> Self { + Self { + message: message.into(), + } + } +} + +impl Display for EmitError { + fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result { + formatter.write_str(&self.message) + } +} + +impl Error for EmitError {} + +impl From for EmitError { + fn from(error: SchemaError) -> Self { + Self::new(error.to_string()) + } +} diff --git a/crates/bolt/src/ir.rs b/crates/bolt/src/ir.rs new file mode 100644 index 0000000000..f4721730ea --- /dev/null +++ b/crates/bolt/src/ir.rs @@ -0,0 +1,160 @@ +use std::fmt::{self, Display, Formatter}; +use std::marker::PhantomData; + +use melior::ir::operation::OperationLike; +use melior::ir::{Attribute, Module}; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Protocol; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Concrete; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Party; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Compute; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Cpu; + +pub trait Phase { + const NAME: &'static str; +} + +impl Phase for Protocol { + const NAME: &'static str = "protocol"; +} + +impl Phase for Concrete { + const NAME: &'static str = "concrete"; +} + +impl Phase for Party { + const NAME: &'static str = "party"; +} + +impl Phase for Compute { + const NAME: &'static str = "compute"; +} + +impl Phase for Cpu { + const NAME: &'static str = "cpu"; +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum Role { + Prover, + Verifier, +} + +impl Role { + pub fn as_str(&self) -> &'static str { + match self { + Self::Prover => "prover", + Self::Verifier => "verifier", + } + } + + fn parse(value: &str) -> Option { + match value { + "prover" => Some(Self::Prover), + "verifier" => Some(Self::Verifier), + _ => None, + } + } +} + +impl Display for Role { + fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result { + formatter.write_str(self.as_str()) + } +} + +#[derive(Debug)] +pub struct BoltModule<'c, P: Phase> { + module: Module<'c>, + phase: PhantomData

, +} + +impl<'c, P: Phase> BoltModule<'c, P> { + pub(crate) fn from_mlir(module: Module<'c>) -> Self { + Self { + module, + phase: PhantomData, + } + } + + pub fn as_mlir_module(&self) -> &Module<'c> { + &self.module + } + + pub fn as_mlir_module_mut(&mut self) -> &mut Module<'c> { + &mut self.module + } + + pub fn into_mlir_module(self) -> Module<'c> { + self.module + } + + pub fn name(&self) -> String { + self.string_attr("sym_name") + .unwrap_or_else(|| "anonymous".to_owned()) + } + + pub fn role(&self) -> Option { + self.string_attr("bolt.role") + .and_then(|value| Role::parse(&value)) + } + + pub fn verify(&self) -> bool { + self.module.as_operation().verify() + } + + fn string_attr(&self, name: &str) -> Option { + self.module + .as_operation() + .attribute(name) + .ok() + .and_then(string_attribute_value) + } +} + +pub trait TextMlir { + fn to_text_mlir(&self) -> String; +} + +impl TextMlir for BoltModule<'_, P> { + fn to_text_mlir(&self) -> String { + self.module.as_operation().to_string() + } +} + +pub(crate) fn string_attribute_value(attribute: Attribute<'_>) -> Option { + let value = attribute.to_string(); + value + .strip_prefix('"') + .and_then(|value| value.strip_suffix('"')) + .map(ToOwned::to_owned) +} + +pub(crate) fn symbol_attribute_value(attribute: Attribute<'_>) -> Option { + attribute + .to_string() + .strip_prefix('@') + .map(ToOwned::to_owned) +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Diagnostic { + pub message: String, +} + +impl Diagnostic { + pub fn new(message: impl Into) -> Self { + Self { + message: message.into(), + } + } +} diff --git a/crates/bolt/src/lib.rs b/crates/bolt/src/lib.rs new file mode 100644 index 0000000000..c802d446ca --- /dev/null +++ b/crates/bolt/src/lib.rs @@ -0,0 +1,28 @@ +pub mod dialects; +pub mod emit; +pub mod ir; +pub mod mlir; +pub mod pass; +pub mod protocols; +pub mod schema; + +pub use emit::rust::{ + assemble_generated_crates, assemble_workspace_generated_crates, protocol_rust_artifact, + validate_rust_artifact_imports, write_generated_crates, ArtifactCrateRole, EmitError, + GeneratedCrate, GeneratedFile, ProtocolArtifactConfig, ProtocolArtifactExtension, + ProtocolCrateRef, ProtocolProverApiExtension, ProtocolRuntimeModule, ProtocolRustArtifact, + ProtocolStage, ProtocolStageKind, ProtocolStandaloneDependency, ProtocolVerifierApiExtension, + RustSourceFile, RustTypeRef, +}; +pub use ir::{ + BoltModule, Compute, Concrete, Cpu, Diagnostic, Party, Phase, Protocol, Role, TextMlir, +}; +pub use mlir::{MeliorContext, MlirError}; +pub use pass::{ + derive_prover_role, derive_verifier_role, lower_piop_and_fiat_shamir, project_party, + project_prover_party, project_verifier_party, verify_concrete_transcript, VerifyError, +}; +pub use schema::{ + verify_compute_schema, verify_concrete_schema, verify_cpu_schema, verify_party_schema, + verify_protocol_schema, SchemaError, +}; diff --git a/crates/bolt/src/mlir.rs b/crates/bolt/src/mlir.rs new file mode 100644 index 0000000000..263bbcbad6 --- /dev/null +++ b/crates/bolt/src/mlir.rs @@ -0,0 +1,292 @@ +use std::error::Error; +use std::fmt::{self, Display, Formatter}; + +use melior::dialect::DialectRegistry; +use melior::ir::attribute::StringAttribute; +use melior::ir::block::BlockLike; +use melior::ir::operation::{OperationBuilder, OperationMutLike}; +use melior::ir::{Attribute, Identifier, Location, Module, OperationRef, Type, Value}; +use melior::utility::register_all_dialects; +use melior::Context; + +use crate::dialects::load_bolt_dialects; +use crate::ir::{BoltModule, Phase, Role, TextMlir}; + +#[derive(Debug)] +pub struct MeliorContext { + context: Context, +} + +impl MeliorContext { + pub fn new() -> Self { + Self::try_new().unwrap_or_else(Self::abort_init_error) + } + + pub fn try_new() -> Result { + let registry = DialectRegistry::new(); + register_all_dialects(®istry); + let context = Context::new_with_registry(®istry, false); + context.load_all_available_dialects(); + load_bolt_dialects(&context) + .map_err(|message| MlirError::DialectRegistration { message })?; + context.set_allow_unregistered_dialects(false); + Ok(Self { context }) + } + + fn abort_init_error(error: MlirError) -> Self { + drop(error); + std::process::abort(); + } + + pub fn context(&self) -> &Context { + &self.context + } + + pub fn new_module<'c, P: Phase>(&'c self, name: &str, role: Option) -> BoltModule<'c, P> { + let mut module = Module::new(Location::unknown(&self.context)); + module + .as_operation_mut() + .set_attribute("sym_name", StringAttribute::new(&self.context, name).into()); + module.as_operation_mut().set_attribute( + "bolt.phase", + StringAttribute::new(&self.context, P::NAME).into(), + ); + if let Some(role) = role { + module.as_operation_mut().set_attribute( + "bolt.role", + StringAttribute::new(&self.context, role.as_str()).into(), + ); + } + BoltModule::from_mlir(module) + } + + pub fn parse_module<'c, P: Phase>( + &'c self, + source: &str, + ) -> Result, MlirError> { + Module::parse(&self.context, source) + .map(BoltModule::from_mlir) + .ok_or_else(|| MlirError::ParseFailed { + source: source.to_owned(), + }) + } + + pub fn append_op<'c, P: Phase>( + &'c self, + module: &BoltModule<'c, P>, + name: &str, + symbol: Option<&str>, + attrs: &[(&str, &str)], + ) -> Result<(), MlirError> { + self.append_op_from_iter(module, name, symbol, attrs.iter().copied()) + } + + pub fn append_op_with_owned_attrs<'c, P: Phase>( + &'c self, + module: &BoltModule<'c, P>, + name: &str, + symbol: Option<&str>, + attrs: &[(String, String)], + ) -> Result<(), MlirError> { + self.append_op_from_iter( + module, + name, + symbol, + attrs + .iter() + .map(|(name, value)| (name.as_str(), value.as_str())), + ) + } + + fn append_op_from_iter<'c, P: Phase, I, K, V>( + &'c self, + module: &BoltModule<'c, P>, + name: &str, + symbol: Option<&str>, + attrs: I, + ) -> Result<(), MlirError> + where + I: IntoIterator, + K: AsRef, + V: AsRef, + { + let mut attributes = Vec::new(); + if let Some(symbol) = symbol { + attributes.push(( + Identifier::new(&self.context, "sym_name"), + StringAttribute::new(&self.context, symbol).into(), + )); + } + for (name, source) in attrs { + let name = name.as_ref(); + let source = source.as_ref(); + attributes.push(( + Identifier::new(&self.context, name), + self.parse_attr(name, source)?, + )); + } + + let operation = OperationBuilder::new(name, Location::unknown(&self.context)) + .add_attributes(&attributes) + .build() + .map_err(|source| MlirError::OperationBuild { + op: name.to_owned(), + source, + })?; + let _operation = module.as_mlir_module().body().append_operation(operation); + Ok(()) + } + + pub(crate) fn append_typed_op<'c, 'a, P: Phase>( + &'c self, + module: &'a BoltModule<'c, P>, + name: &str, + symbol: Option<&str>, + attrs: &[(&str, &str)], + operands: &[Value<'c, 'a>], + result_types: &[&str], + ) -> Result, MlirError> { + self.append_typed_op_from_iter( + module, + name, + symbol, + attrs.iter().copied(), + operands, + result_types, + ) + } + + pub(crate) fn append_typed_op_with_owned_attrs<'c, 'a, P: Phase>( + &'c self, + module: &'a BoltModule<'c, P>, + name: &str, + symbol: Option<&str>, + attrs: &[(String, String)], + operands: &[Value<'c, 'a>], + result_types: &[&str], + ) -> Result, MlirError> { + self.append_typed_op_from_iter( + module, + name, + symbol, + attrs + .iter() + .map(|(name, value)| (name.as_str(), value.as_str())), + operands, + result_types, + ) + } + + fn append_typed_op_from_iter<'c, 'a, P: Phase, I, K, V>( + &'c self, + module: &'a BoltModule<'c, P>, + name: &str, + symbol: Option<&str>, + attrs: I, + operands: &[Value<'c, 'a>], + result_types: &[&str], + ) -> Result, MlirError> + where + I: IntoIterator, + K: AsRef, + V: AsRef, + { + let mut attributes = Vec::new(); + if let Some(symbol) = symbol { + attributes.push(( + Identifier::new(&self.context, "sym_name"), + StringAttribute::new(&self.context, symbol).into(), + )); + } + for (name, source) in attrs { + let name = name.as_ref(); + let source = source.as_ref(); + attributes.push(( + Identifier::new(&self.context, name), + self.parse_attr(name, source)?, + )); + } + let result_types = result_types + .iter() + .map(|source| { + Type::parse(&self.context, source).ok_or_else(|| MlirError::TypeParse { + source: (*source).to_owned(), + }) + }) + .collect::, _>>()?; + + let operation = OperationBuilder::new(name, Location::unknown(&self.context)) + .add_operands(operands) + .add_results(&result_types) + .add_attributes(&attributes) + .build() + .map_err(|source| MlirError::OperationBuild { + op: name.to_owned(), + source, + })?; + Ok(module.as_mlir_module().body().append_operation(operation)) + } + + fn parse_attr<'c>(&'c self, name: &str, source: &str) -> Result, MlirError> { + Attribute::parse(&self.context, source).ok_or_else(|| MlirError::AttributeParse { + name: name.to_owned(), + source: source.to_owned(), + }) + } +} + +impl Default for MeliorContext { + fn default() -> Self { + Self::new() + } +} + +#[derive(Debug)] +pub enum MlirError { + AttributeParse { name: String, source: String }, + TypeParse { source: String }, + OperationBuild { op: String, source: melior::Error }, + ParseFailed { source: String }, + Schema { message: String }, + DialectRegistration { message: String }, + VerificationFailed { source: String }, +} + +impl Display for MlirError { + fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result { + match self { + Self::AttributeParse { name, source } => { + write!( + formatter, + "failed to parse MLIR attribute `{name}` from `{source}`" + ) + } + Self::TypeParse { source } => { + write!(formatter, "failed to parse MLIR type `{source}`") + } + Self::OperationBuild { op, source } => { + write!(formatter, "failed to build MLIR operation `{op}`: {source}") + } + Self::ParseFailed { source } => { + write!(formatter, "failed to parse MLIR module:\n{source}") + } + Self::Schema { message } => formatter.write_str(message), + Self::DialectRegistration { message } => formatter.write_str(message), + Self::VerificationFailed { source } => { + write!(formatter, "MLIR module verification failed:\n{source}") + } + } + } +} + +impl Error for MlirError {} + +pub(crate) fn verify_module(module: &BoltModule<'_, P>) -> Result<(), MlirError> { + if module.verify() { + Ok(()) + } else { + Err(MlirError::VerificationFailed { + source: module.to_text_mlir(), + }) + } +} diff --git a/crates/bolt/src/pass.rs b/crates/bolt/src/pass.rs new file mode 100644 index 0000000000..8b883a1f6b --- /dev/null +++ b/crates/bolt/src/pass.rs @@ -0,0 +1,316 @@ +use std::error::Error; +use std::fmt::{self, Display, Formatter}; + +use melior::ir::block::BlockLike; +use melior::ir::operation::OperationLike; + +use crate::ir::{BoltModule, Concrete, Party, Phase, Protocol, Role}; +use crate::mlir::{verify_module, MeliorContext, MlirError}; +use crate::schema::{verify_concrete_schema, verify_party_schema, verify_protocol_schema}; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct VerifyError { + message: String, +} + +impl VerifyError { + fn new(message: impl Into) -> Self { + Self { + message: message.into(), + } + } +} + +impl Display for VerifyError { + fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result { + formatter.write_str(&self.message) + } +} + +impl Error for VerifyError {} + +pub fn lower_piop_and_fiat_shamir<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, +) -> Result, MlirError> { + verify_protocol_schema(module)?; + let source = phase_copy_source(module, Concrete::NAME, None, &[]); + let concrete = context.parse_module::(&source)?; + verify_module(&concrete)?; + verify_concrete_schema(&concrete)?; + Ok(concrete) +} + +pub fn derive_prover_role<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Concrete>, +) -> Result, MlirError> { + derive_role(context, module, Role::Prover) +} + +pub fn derive_verifier_role<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Concrete>, +) -> Result, MlirError> { + derive_role(context, module, Role::Verifier) +} + +pub fn project_prover_party<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Concrete>, +) -> Result, MlirError> { + project_party(context, module, Role::Prover) +} + +pub fn project_verifier_party<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Concrete>, +) -> Result, MlirError> { + project_party(context, module, Role::Verifier) +} + +pub fn project_party<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Concrete>, + role: Role, +) -> Result, MlirError> { + verify_concrete_schema(module)?; + require_declared_role(module, &role)?; + let party_function = format!( + " \"party.function\"() {{role = \"{}\", source = @{}, sym_name = \"{}.{}\"}} : () -> ()", + role.as_str(), + module.name(), + module.name(), + role.as_str() + ); + let source = phase_copy_source(module, Party::NAME, Some(&role), &[party_function]); + let party = context.parse_module::(&source)?; + verify_module(&party)?; + verify_party_schema(&party)?; + Ok(party) +} + +pub fn verify_concrete_transcript

(module: &BoltModule<'_, P>) -> Result<(), VerifyError> +where + P: Phase, +{ + let mut current_state = None; + let mut error = None; + let mut operation = module.as_mlir_module().body().first_operation(); + while let Some(op) = operation { + operation = op.next_in_block(); + match operation_name(op).as_str() { + "transcript.state" => { + if current_state.is_some() { + error = Some(VerifyError::new("multiple transcript.state ops")); + break; + } + let Ok(result) = op.result(0) else { + error = Some(VerifyError::new("transcript.state requires one result")); + break; + }; + current_state = Some(result.to_string()); + } + "transcript.absorb" | "transcript.absorb_optional" => { + let Some(expected_input) = current_state.as_deref() else { + error = Some(VerifyError::new( + "transcript absorb requires a prior transcript.state result", + )); + break; + }; + let Ok(input) = op.operand(0) else { + error = Some(VerifyError::new(format!( + "{} requires transcript-state operand 0", + operation_name(op) + ))); + break; + }; + let input = input.to_string(); + if input != expected_input { + error = Some(VerifyError::new(format!( + "{} consumed transcript state {input}, expected {expected_input}", + operation_name(op) + ))); + break; + } + if op.operand(1).is_err() { + error = Some(VerifyError::new(format!( + "{} requires commitment artifact operand 1", + operation_name(op) + ))); + break; + } + let Ok(result) = op.result(0) else { + error = Some(VerifyError::new(format!( + "{} requires one transcript-state result", + operation_name(op) + ))); + break; + }; + current_state = Some(result.to_string()); + } + "transcript.absorb_bytes" => { + let Some(expected_input) = current_state.as_deref() else { + error = Some(VerifyError::new( + "transcript absorb_bytes requires a prior transcript.state result", + )); + break; + }; + let Ok(input) = op.operand(0) else { + error = Some(VerifyError::new( + "transcript.absorb_bytes requires transcript-state operand 0", + )); + break; + }; + let input = input.to_string(); + if input != expected_input { + error = Some(VerifyError::new(format!( + "transcript.absorb_bytes consumed transcript state {input}, expected {expected_input}", + ))); + break; + } + let Ok(result) = op.result(0) else { + error = Some(VerifyError::new( + "transcript.absorb_bytes requires one transcript-state result", + )); + break; + }; + current_state = Some(result.to_string()); + } + "transcript.squeeze" | "piop.sumcheck" | "pcs.batch_open" | "pcs.batch_verify" => { + let Some(expected_input) = current_state.as_deref() else { + error = Some(VerifyError::new(format!( + "{} requires a prior transcript.state result", + operation_name(op) + ))); + break; + }; + let Ok(input) = op.operand(0) else { + error = Some(VerifyError::new(format!( + "{} requires transcript-state operand 0", + operation_name(op) + ))); + break; + }; + let input = input.to_string(); + if input != expected_input { + error = Some(VerifyError::new(format!( + "{} consumed transcript state {input}, expected {expected_input}", + operation_name(op) + ))); + break; + } + let Ok(result) = op.result(0) else { + error = Some(VerifyError::new(format!( + "{} requires transcript-state result 0", + operation_name(op) + ))); + break; + }; + current_state = Some(result.to_string()); + } + _ => {} + } + } + + match error { + Some(error) => Err(error), + None => Ok(()), + } +} + +fn derive_role<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Concrete>, + role: Role, +) -> Result, MlirError> { + let source = phase_copy_source(module, Concrete::NAME, Some(&role), &[]); + context.parse_module::(&source) +} + +fn phase_copy_source( + module: &BoltModule<'_, P>, + target_phase: &str, + role: Option<&Role>, + prefix_ops: &[String], +) -> String { + let mut source = format!( + "module @{} attributes {{bolt.phase = \"{target_phase}\"", + module.name() + ); + if let Some(role) = role { + source.push_str(", bolt.role = \""); + source.push_str(role.as_str()); + source.push('"'); + } + source.push_str("} {\n"); + for op in prefix_ops { + source.push_str(op); + source.push('\n'); + } + append_body_text(&mut source, module); + source.push_str("}\n"); + source +} + +fn require_declared_role(module: &BoltModule<'_, Concrete>, role: &Role) -> Result<(), MlirError> { + let mut operation = module.as_mlir_module().body().first_operation(); + while let Some(op) = operation { + operation = op.next_in_block(); + if operation_name(op) != "protocol.boundary" { + continue; + } + let roles = op + .attribute("roles") + .ok() + .and_then(|attribute| parse_string_array(&attribute.to_string())) + .ok_or_else(|| MlirError::Schema { + message: "protocol.boundary requires string array attr `roles`".to_owned(), + })?; + if roles.iter().any(|declared| declared == role.as_str()) { + return Ok(()); + } + return Err(MlirError::Schema { + message: format!("protocol.boundary does not declare role `{role}`"), + }); + } + + Err(MlirError::Schema { + message: "module missing required op `protocol.boundary`".to_owned(), + }) +} + +fn parse_string_array(attribute: &str) -> Option> { + let inner = attribute.strip_prefix('[')?.strip_suffix(']')?.trim(); + if inner.is_empty() { + return Some(Vec::new()); + } + inner + .split(',') + .map(|item| { + item.trim() + .strip_prefix('"') + .and_then(|item| item.strip_suffix('"')) + .map(ToOwned::to_owned) + }) + .collect() +} + +fn operation_name<'c: 'a, 'a>(operation: impl OperationLike<'c, 'a>) -> String { + operation + .name() + .as_string_ref() + .as_str() + .unwrap_or("") + .to_owned() +} + +fn append_body_text(module_source: &mut String, module: &BoltModule<'_, P>) { + let mut operation = module.as_mlir_module().body().first_operation(); + while let Some(op) = operation { + operation = op.next_in_block(); + module_source.push_str(" "); + module_source.push_str(&op.to_string()); + module_source.push('\n'); + } +} diff --git a/crates/bolt/src/protocols/jolt/artifacts.rs b/crates/bolt/src/protocols/jolt/artifacts.rs new file mode 100644 index 0000000000..0a13379d7d --- /dev/null +++ b/crates/bolt/src/protocols/jolt/artifacts.rs @@ -0,0 +1,2349 @@ +use std::path::Path; + +use crate::emit::rust::{ + assemble_generated_crates, assemble_workspace_generated_crates, protocol_rust_artifact, + validate_rust_artifact_imports, write_generated_crates, EmitError, GeneratedCrate, + GeneratedFile, ProtocolArtifactConfig, ProtocolArtifactExtension, ProtocolCrateRef, + ProtocolProverApiExtension, ProtocolRuntimeModule, ProtocolRustArtifact, ProtocolStage, + ProtocolStageKind, ProtocolStandaloneDependency, ProtocolVerifierApiExtension, RustSourceFile, + RustTypeRef, +}; +use crate::ir::Role; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum JoltProtocolStage { + Commitment, + Stage1Outer, + Stage2, + Stage3, + Stage4, + Stage5, + Stage6, + Stage7, + Stage8, +} + +impl JoltProtocolStage { + pub fn name(self) -> &'static str { + match self { + Self::Commitment => "commitment", + Self::Stage1Outer => "stage1_outer", + Self::Stage2 => "stage2", + Self::Stage3 => "stage3", + Self::Stage4 => "stage4", + Self::Stage5 => "stage5", + Self::Stage6 => "stage6", + Self::Stage7 => "stage7", + Self::Stage8 => "stage8", + } + } + + fn expected_filename(self, role: &Role) -> &'static str { + match (self, role) { + (Self::Commitment, Role::Prover) => "prove_commitment_phase.rs", + (Self::Commitment, Role::Verifier) => "verify_commitment_phase.rs", + (Self::Stage1Outer, Role::Prover) => "prove_stage1_outer.rs", + (Self::Stage1Outer, Role::Verifier) => "verify_stage1_outer.rs", + (Self::Stage2, Role::Prover) => "prove_stage2.rs", + (Self::Stage2, Role::Verifier) => "verify_stage2.rs", + (Self::Stage3, Role::Prover) => "prove_stage3.rs", + (Self::Stage3, Role::Verifier) => "verify_stage3.rs", + (Self::Stage4, Role::Prover) => "prove_stage4.rs", + (Self::Stage4, Role::Verifier) => "verify_stage4.rs", + (Self::Stage5, Role::Prover) => "prove_stage5.rs", + (Self::Stage5, Role::Verifier) => "verify_stage5.rs", + (Self::Stage6, Role::Prover) => "prove_stage6.rs", + (Self::Stage6, Role::Verifier) => "verify_stage6.rs", + (Self::Stage7, Role::Prover) => "prove_stage7.rs", + (Self::Stage7, Role::Verifier) => "verify_stage7.rs", + (Self::Stage8, Role::Prover) => "prove_stage8.rs", + (Self::Stage8, Role::Verifier) => "verify_stage8.rs", + } + } +} + +impl From for ProtocolStage { + fn from(stage: JoltProtocolStage) -> Self { + match stage { + JoltProtocolStage::Commitment => { + ProtocolStage::new("commitment", "commitment", 0, ProtocolStageKind::Commitment) + } + JoltProtocolStage::Stage1Outer => { + ProtocolStage::new("stage1_outer", "stage1_outer", 1, ProtocolStageKind::Proof) + } + JoltProtocolStage::Stage2 => { + ProtocolStage::new("stage2", "stage2", 2, ProtocolStageKind::Proof) + } + JoltProtocolStage::Stage3 => { + ProtocolStage::new("stage3", "stage3", 3, ProtocolStageKind::Proof) + } + JoltProtocolStage::Stage4 => { + ProtocolStage::new("stage4", "stage4", 4, ProtocolStageKind::Proof) + } + JoltProtocolStage::Stage5 => { + ProtocolStage::new("stage5", "stage5", 5, ProtocolStageKind::Proof) + } + JoltProtocolStage::Stage6 => { + ProtocolStage::new("stage6", "stage6", 6, ProtocolStageKind::Proof) + } + JoltProtocolStage::Stage7 => { + ProtocolStage::new("stage7", "stage7", 7, ProtocolStageKind::Proof) + } + JoltProtocolStage::Stage8 => { + ProtocolStage::new("stage8", "stage8", 8, ProtocolStageKind::Evaluation) + } + } + } +} + +impl PartialEq for ProtocolStage { + fn eq(&self, other: &JoltProtocolStage) -> bool { + self == &ProtocolStage::from(*other) + } +} + +impl PartialEq for JoltProtocolStage { + fn eq(&self, other: &ProtocolStage) -> bool { + other == self + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum JoltArtifactCrate { + Prover, + Verifier, +} + +impl JoltArtifactCrate { + pub fn for_role(role: &Role) -> Self { + match role { + Role::Prover => Self::Prover, + Role::Verifier => Self::Verifier, + } + } + + pub fn name(self) -> &'static str { + match self { + Self::Prover => "jolt-prover", + Self::Verifier => "jolt-verifier", + } + } +} + +pub type JoltRustArtifact = ProtocolRustArtifact; +pub type JoltGeneratedCrate = GeneratedCrate; +pub type JoltGeneratedFile = GeneratedFile; + +pub fn write_jolt_generated_crates( + generated_crates: &[GeneratedCrate], + output_root: impl AsRef, +) -> Result<(), EmitError> { + write_generated_crates(generated_crates, output_root) +} + +pub fn jolt_rust_artifact( + stage: JoltProtocolStage, + role: Role, + source: RustSourceFile, +) -> Result { + let expected = stage.expected_filename(&role); + if source.filename != expected { + return Err(EmitError::new(format!( + "generated {} artifact for {} expected filename `{expected}`, got `{}`", + role, + stage.name(), + source.filename + ))); + } + + Ok(protocol_rust_artifact( + &jolt_artifact_config(), + ProtocolStage::from(stage), + role, + source, + )) +} + +pub fn validate_jolt_rust_artifact_imports( + artifact: &ProtocolRustArtifact, +) -> Result<(), EmitError> { + validate_rust_artifact_imports(&jolt_artifact_config(), artifact) +} + +pub fn assemble_jolt_generated_crates( + artifacts: Vec, + dependency_root: &str, +) -> Result, EmitError> { + assemble_generated_crates(&jolt_artifact_config(), artifacts, dependency_root) +} + +pub fn assemble_jolt_workspace_generated_crates( + artifacts: Vec, +) -> Result, EmitError> { + assemble_workspace_generated_crates(&jolt_artifact_config(), artifacts) +} + +pub fn jolt_artifact_config() -> ProtocolArtifactConfig { + ProtocolArtifactConfig { + protocol_name: "Jolt".to_owned(), + type_prefix: "Jolt".to_owned(), + transcript_label: "Jolt".to_owned(), + repository: Some("https://github.com/a16z/jolt".to_owned()), + prover_crate_name: "jolt-prover".to_owned(), + verifier_crate_name: "jolt-verifier".to_owned(), + crates_io_patches: vec![ + "ark-bn254 = { git = \"https://github.com/a16z/arkworks-algebra\", branch = \"dev/twist-shout\" }".to_owned(), + "ark-ec = { git = \"https://github.com/a16z/arkworks-algebra\", branch = \"dev/twist-shout\" }".to_owned(), + "ark-ff = { git = \"https://github.com/a16z/arkworks-algebra\", branch = \"dev/twist-shout\" }".to_owned(), + "ark-serialize = { git = \"https://github.com/a16z/arkworks-algebra\", branch = \"dev/twist-shout\" }".to_owned(), + ], + standalone_dependency_overrides: vec![ProtocolStandaloneDependency::new( + "rayon", + "rayon = \"1.12.0\"", + ), ProtocolStandaloneDependency::new( + "serde", + "serde = { version = \"1.0\", default-features = false, features = [\"derive\"] }", + ), ProtocolStandaloneDependency::new( + "tracing", + "tracing = { version = \"0.1.37\", default-features = false, features = [\"attributes\"] }", + )], + common_dependencies: vec![ + "jolt-field".to_owned(), + "jolt-openings".to_owned(), + "jolt-poly".to_owned(), + "jolt-transcript".to_owned(), + "tracing".to_owned(), + ], + prover_dependencies: vec![ + "jolt-dory".to_owned(), + "jolt-kernels".to_owned(), + "jolt-witness".to_owned(), + "rayon".to_owned(), + ], + verifier_dependencies: vec![ + "jolt-dory".to_owned(), + "jolt-lookup-tables".to_owned(), + "jolt-sumcheck".to_owned(), + "serde".to_owned(), + ], + instrumentation_prefix: Some("bolt".to_owned()), + prover_forbidden_imports: PROVER_FORBIDDEN_IMPORTS + .iter() + .map(ToString::to_string) + .collect(), + verifier_forbidden_imports: VERIFIER_FORBIDDEN_IMPORTS + .iter() + .map(ToString::to_string) + .collect(), + kernel_crate: Some(ProtocolCrateRef::new("jolt-kernels", "jolt_kernels")), + field_type: RustTypeRef::new("jolt_field::Fr"), + default_transcript_type: RustTypeRef::new("jolt_transcript::Blake2bTranscript"), + transcript_trait: RustTypeRef::new("jolt_transcript::Transcript"), + commitment_type: RustTypeRef::new("jolt_dory::DoryCommitment"), + prover_setup_type: RustTypeRef::new("jolt_dory::DoryProverSetup"), + role_api_extension: Some(jolt_evaluation_role_api_extension()), + verifier_runtime_modules: vec![ProtocolRuntimeModule { + module_name: "common".to_owned(), + file: GeneratedFile { + path: "src/stages/common.rs".to_owned(), + source: include_str!("verifier_common.rs.template").to_owned(), + }, + }], + verifier_named_eval_type: RustTypeRef::new("crate::stages::common::StageNamedEval"), + verifier_sumcheck_output_type: RustTypeRef::new( + "crate::stages::common::StageSumcheckOutput", + ), + verifier_stage_proof_type: RustTypeRef::new("crate::stages::common::StageProof"), + } +} + +fn jolt_prover_lib_module() -> String { + r"#[rustfmt::skip] +pub mod prover; +pub mod stages; + +pub use prover::{ + default_prover_programs, jolt_proof_through_stage5, jolt_proof_through_stage6, + jolt_proof_through_stage7, prove_jolt, prove_jolt_evaluation_proof, prove_jolt_with_programs, + prove_jolt_with_stage_inputs, prove_jolt_with_witness_inputs, + prove_stage1_outer_inputs_with_program, prove_stage2_inputs_with_program, + prove_stage3_inputs_with_program, prove_stage4_inputs_with_program, + prove_stage5_inputs_with_program, prove_stage6_inputs_with_program, + prove_stage7_inputs_with_program, replay_stage1_outer_proof_with_program, + replay_stage2_proof_with_program, replay_stage3_proof_with_program, + replay_stage4_proof_with_program, replay_stage5_proof_with_program, + replay_stage6_proof_with_program, replay_stage7_proof_with_program, stage1_outer_proof, + stage1_outer_proof_from_kernel_proof, stage1_outer_prover_inputs, + stage2_opening_inputs_from_artifacts, stage2_proof, stage2_prover_inputs, + stage2_verifier_ram_data, stage3_opening_inputs_from_artifacts, stage3_proof, + stage3_prover_inputs, stage4_opening_inputs_from_artifacts, stage4_proof, stage4_prover_inputs, + stage5_kernel_proof, stage5_opening_inputs_from_artifacts, stage5_proof, stage5_prover_inputs, + stage6_bytecode_read_raf_data_from_witness_entries, stage6_execution_artifacts, + stage6_kernel_proof, stage6_opening_inputs_from_artifacts, stage6_proof, stage6_prover_inputs, + stage6_witness_from_opening_inputs, stage7_execution_artifacts, stage7_kernel_proof, + stage7_opening_inputs_from_stage6_artifacts, + stage7_opening_inputs_from_stage6_artifacts_with_program, stage7_proof, stage7_prover_inputs, + verifier_opening_inputs_from_kernel, DefaultJoltTranscript, JoltEvaluationProveError, + JoltKernelOpeningInput, JoltOpeningInputError, JoltProveError, JoltProverArtifacts, + JoltProverInputs, JoltProverPrograms, JoltProverStageInputs, JoltProverWitnessInputs, + JoltStage2RamDataStorage, +}; + +pub use prover::{ + prove_stage1_outer_with_witness_inputs, prove_stage2_with_witness_inputs, + prove_stage3_with_witness_inputs, prove_stage4_with_trace_witness_inputs, + prove_stage4_with_witness_inputs, prove_stage5_with_trace_witness_inputs, + prove_stage5_with_witness_inputs, prove_stage6_with_trace_witness_inputs, + prove_stage6_with_witness_inputs, prove_stage7_with_trace_witness_inputs, + prove_stage7_with_witness_inputs, stage6_verifier_data_from_witness_entries, +};" + .to_owned() +} + +fn jolt_verifier_lib_module() -> String { + r"pub mod stages; +#[rustfmt::skip] +pub mod verifier; + +pub use stages::{ + stage1_outer::{verify_stage1_outer_with_program, Stage1VerifierProgramPlan}, + stage2::{verify_stage2_with_program, Stage2VerifierProgramPlan}, + stage3::{verify_stage3_with_program, Stage3VerifierProgramPlan}, + stage4::{verify_stage4_with_program, Stage4VerifierProgramPlan}, + stage5::{verify_stage5_with_program, Stage5VerifierProgramPlan}, + stage6::{verify_stage6_with_program, Stage6VerifierProgramPlan}, + stage7::{verify_stage7_with_program, Stage7VerifierProgramPlan}, +}; + +pub use verifier::{ + default_verifier_programs, verify_jolt, verify_jolt_evaluation_proof, verify_jolt_prefix, + verify_jolt_prefix_with_programs, verify_jolt_through_stage5, + verify_jolt_through_stage5_with_programs, verify_jolt_through_stage6, + verify_jolt_through_stage6_with_programs, verify_jolt_through_stage7, + verify_jolt_through_stage7_with_programs, verify_jolt_with_programs, JoltEvaluationProof, + JoltEvaluationProofError, JoltNamedEval, JoltProof, JoltStage2RamAccess, JoltStage2RamData, + JoltStage2RamOutputLayout, JoltStageChallengeVector, JoltStageExecutionArtifacts, + JoltStage6BytecodeEntry, JoltStage6BytecodeReadRafData, JoltStage6VerifierData, + JoltStageOpeningInputValue, JoltStageProof, JoltSumcheckOutput, JoltVerificationArtifacts, + JoltVerifierInputs, JoltVerifierPrograms, JoltVerifierTarget, JoltVerifyError, +};" + .to_owned() +} + +fn jolt_evaluation_role_api_extension() -> ProtocolArtifactExtension { + ProtocolArtifactExtension { + required_commitment: true, + required_proof_stages: vec!["stage6".to_owned(), "stage7".to_owned()], + required_artifact_stages: vec!["stage8".to_owned()], + prover: ProtocolProverApiExtension { + lib_module: jolt_prover_lib_module(), + imports: "#![expect(\n clippy::too_many_arguments,\n reason = \"generated prover helpers mirror staged protocol ABIs\"\n)]\n\nuse jolt_dory::{DoryCommitment, DoryHint, DoryProverSetup, DoryScheme};\nuse jolt_field::{Field, Fr};\nuse jolt_kernels::{stage1, stage2, stage3, stage4, stage5, stage6, stage7};\nuse jolt_openings::{AdditivelyHomomorphic, CommitmentScheme};\nuse jolt_poly::{EqPolynomial, Polynomial};\nuse jolt_transcript::{AppendToTranscript, Blake2bTranscript, LabelWithCount, Transcript};\nuse jolt_verifier::{JoltEvaluationProof, JoltNamedEval, JoltProof, JoltStage2RamAccess, JoltStage2RamData, JoltStage2RamOutputLayout, JoltStage6BytecodeEntry, JoltStage6BytecodeReadRafData, JoltStage6VerifierData, JoltStageChallengeVector, JoltStageExecutionArtifacts, JoltStageOpeningInputValue, JoltStageProof, JoltSumcheckOutput};\nuse jolt_witness::{stage4_ram_val_init_opening, CycleInput, Stage45SparseTraceWitness, Stage6BytecodeEntry as WitnessStage6BytecodeEntry, Stage6WitnessParams, Stage6WitnessPolynomials, Stage6WitnessSlices};\nuse rayon::prelude::*;\n\n".to_owned(), + input_fields: + " pub stage7_openings: Option<&'a [stage7::Stage7OpeningInputValue]>,\n" + .to_owned(), + program_fields: + " pub stage8: &'static stage8_stage::Stage8EvaluationProgramPlan,\n".to_owned(), + default_program_fields: " stage8: &stage8_stage::STAGE8_PROGRAM,\n".to_owned(), + error_variants: " Evaluation(JoltEvaluationProveError),\n".to_owned(), + error_items: "#[derive(Debug)]\npub enum JoltEvaluationProveError {\n MissingOracle { oracle: &'static str },\n MissingOpeningHint { oracle: &'static str },\n MissingStageEval { stage: &'static str, eval: &'static str },\n MissingStage7RaEval,\n MissingStage7EvaluationPoint,\n InvalidPointLength {\n artifact: &'static str,\n expected: usize,\n actual: usize,\n },\n TargetSizeOverflow { num_vars: usize },\n}\n\n#[derive(Debug)]\npub enum JoltOpeningInputError {\n MissingOpeningClaim { stage: &'static str, source_claim: &'static str },\n MissingStage6OpeningClaim { source_claim: &'static str },\n UnsupportedOpeningInputSource { stage: &'static str, symbol: &'static str, source_stage: &'static str },\n UnsupportedStage7InputSource { symbol: &'static str, source_stage: &'static str },\n InvalidPointLength {\n symbol: &'static str,\n expected: usize,\n actual: usize,\n },\n}\n\n".to_owned(), + error_conversions: "impl From for JoltProveError {\n fn from(error: JoltEvaluationProveError) -> Self {\n Self::Evaluation(error)\n }\n}\n\n".to_owned(), + after_stage_execution: " let evaluation = if let Some(stage7_openings) = inputs.stage7_openings {\n let _stage8_span = tracing::info_span!(\"bolt.stage8\").entered();\n let _evaluate_span = tracing::info_span!(\"bolt.evaluate\").entered();\n Some(prove_jolt_evaluation_proof(\n programs.stage8,\n inputs.commitment_inputs,\n inputs.prover_setup,\n &commitment,\n &stage6,\n &stage7,\n stage7_openings,\n transcript,\n )?)\n } else {\n None\n };\n".to_owned(), + proof_fields: " evaluation,\n".to_owned(), + helper_items: format!( + "{}{}", + jolt_prover_evaluation_helpers("Fr"), + jolt_prover_stage7_opening_input_helpers("Fr") + ), + }, + verifier: ProtocolVerifierApiExtension { + lib_module: jolt_verifier_lib_module(), + imports: "use std::collections::BTreeMap;\n\nuse jolt_dory::{DoryCommitment, DoryProof, DoryScheme, DoryVerifierSetup};\nuse jolt_field::{Field, Fr};\nuse jolt_openings::{AdditivelyHomomorphic, CommitmentScheme, OpeningsError};\nuse jolt_poly::EqPolynomial;\nuse jolt_transcript::{AppendToTranscript, LabelWithCount, Transcript};\n".to_owned(), + proof_fields: " pub evaluation: Option,\n".to_owned(), + proof_items: "pub type JoltStage2RamAccess = crate::stages::stage2::Stage2RamAccess;\npub type JoltStage2RamOutputLayout = crate::stages::stage2::Stage2RamOutputLayout;\npub type JoltStage2RamData<'a> = crate::stages::stage2::Stage2RamData<'a>;\npub type JoltStageChallengeVector = crate::stages::common::StageChallengeVector;\npub type JoltStageExecutionArtifacts = crate::stages::common::StageExecutionArtifacts;\npub type JoltStageOpeningInputValue = crate::stages::common::StageOpeningInputValue;\n\n#[derive(Clone, Debug)]\npub struct JoltEvaluationProof {\n pub joint_opening_proof: DoryProof,\n}\n\n".to_owned(), + inputs_derive: Some("#[derive(Clone, Copy)]".to_owned()), + input_fields: " pub evaluation_setup: Option<&'a DoryVerifierSetup>,\n".to_owned(), + program_fields: + " pub stage8: &'static stage8_stage::Stage8EvaluationProgramPlan,\n".to_owned(), + default_program_fields: " stage8: &stage8_stage::STAGE8_PROGRAM,\n".to_owned(), + error_variants: " Evaluation(JoltEvaluationProofError),\n".to_owned(), + error_items: format!("{}{}", jolt_verifier_target_items(), "#[derive(Debug)]\npub enum JoltEvaluationProofError {\n MissingProof,\n MissingVerifierSetup,\n MissingStageEval { stage: &'static str, eval: &'static str },\n MissingStage7RaEval,\n MissingStage7EvaluationPoint,\n MissingCommitment { oracle: &'static str },\n InvalidPointLength {\n artifact: &'static str,\n expected: usize,\n actual: usize,\n },\n Opening(OpeningsError),\n}\n\n"), + error_conversions: "impl From for JoltVerifyError {\n fn from(error: JoltEvaluationProofError) -> Self {\n Self::Evaluation(error)\n }\n}\n\nimpl From for JoltEvaluationProofError {\n fn from(error: OpeningsError) -> Self {\n Self::Opening(error)\n }\n}\n\n".to_owned(), + after_default_verify: "pub fn verify_jolt_prefix>(proof: &JoltProof, inputs: JoltVerifierInputs<'_>, transcript: &mut T) -> Result { verify_jolt_prefix_with_programs(proof, inputs, default_verifier_programs(), transcript) }\n\npub fn verify_jolt_through_stage5>(proof: &JoltProof, inputs: JoltVerifierInputs<'_>, transcript: &mut T) -> Result { verify_jolt_through_stage5_with_programs(proof, inputs, default_verifier_programs(), transcript) }\n\npub fn verify_jolt_through_stage6>(proof: &JoltProof, inputs: JoltVerifierInputs<'_>, transcript: &mut T) -> Result { verify_jolt_through_stage6_with_programs(proof, inputs, default_verifier_programs(), transcript) }\n\npub fn verify_jolt_through_stage7>(proof: &JoltProof, inputs: JoltVerifierInputs<'_>, transcript: &mut T) -> Result { verify_jolt_through_stage7_with_programs(proof, inputs, default_verifier_programs(), transcript) }\n\n".to_owned(), + with_programs_body_intro: " verify_jolt_with_programs_inner(proof, inputs, programs, transcript, JoltVerifierTarget::Full)\n}\n\npub fn verify_jolt_through_stage5_with_programs>(proof: &JoltProof, inputs: JoltVerifierInputs<'_>, programs: JoltVerifierPrograms, transcript: &mut T) -> Result { verify_jolt_with_programs_inner(proof, inputs, programs, transcript, JoltVerifierTarget::ThroughStage5) }\n\npub fn verify_jolt_through_stage6_with_programs>(proof: &JoltProof, inputs: JoltVerifierInputs<'_>, programs: JoltVerifierPrograms, transcript: &mut T) -> Result { verify_jolt_with_programs_inner(proof, inputs, programs, transcript, JoltVerifierTarget::ThroughStage6) }\n\npub fn verify_jolt_through_stage7_with_programs>(proof: &JoltProof, inputs: JoltVerifierInputs<'_>, programs: JoltVerifierPrograms, transcript: &mut T) -> Result { verify_jolt_with_programs_inner(proof, inputs, programs, transcript, JoltVerifierTarget::ThroughStage7) }\n\npub fn verify_jolt_prefix_with_programs>(proof: &JoltProof, inputs: JoltVerifierInputs<'_>, programs: JoltVerifierPrograms, transcript: &mut T) -> Result { verify_jolt_through_stage7_with_programs(proof, inputs, programs, transcript) }\n\nfn verify_jolt_with_programs_inner>(proof: &JoltProof, inputs: JoltVerifierInputs<'_>, programs: JoltVerifierPrograms, transcript: &mut T, target: JoltVerifierTarget) -> Result {\n".to_owned(), + stage_verification_override: jolt_verifier_stage_verification(), + after_stage_verification: jolt_verifier_evaluation_check(), + helper_items: format!( + "{}{}", + jolt_verifier_input_helpers("Jolt"), + jolt_verifier_evaluation_helpers("Jolt", "Fr") + ), + }, + } +} + +fn jolt_verifier_target_items() -> String { + "#[derive(Clone, Copy, Debug, PartialEq, Eq)]\npub enum JoltVerifierTarget {\n ThroughStage5,\n ThroughStage6,\n ThroughStage7,\n Full,\n}\n\nimpl JoltVerifierTarget {\n fn verifies_stage6(self) -> bool { matches!(self, Self::ThroughStage6 | Self::ThroughStage7 | Self::Full) }\n fn verifies_stage7(self) -> bool { matches!(self, Self::ThroughStage7 | Self::Full) }\n fn verifies_evaluation(self) -> bool { matches!(self, Self::Full) }\n fn allows_optional_evaluation(self) -> bool { matches!(self, Self::ThroughStage7 | Self::Full) }\n}\n\n".to_owned() +} + +fn jolt_verifier_stage_verification() -> String { + " let stage1_outer = stage1_outer_stage::verify_stage1_outer_with_program(programs.stage1_outer, &proof.stage1_outer, transcript)?;\n let stage2 = stage2_stage::verify_stage2_with_program(programs.stage2, &proof.stage2, inputs.stage2_openings, inputs.stage2_ram, transcript)?;\n let stage3 = stage3_stage::verify_stage3_with_program(programs.stage3, &proof.stage3, inputs.stage3_openings, transcript)?;\n let stage4 = stage4_stage::verify_stage4_with_program(programs.stage4, &proof.stage4, inputs.stage4_openings, transcript)?;\n let stage5 = stage5_stage::verify_stage5_with_program(programs.stage5, &proof.stage5, inputs.stage5_openings, transcript)?;\n let stage6 = if target.verifies_stage6() {\n stage6_stage::verify_stage6_with_program(programs.stage6, &proof.stage6, inputs.stage6_openings, inputs.stage6_data, transcript)?\n } else {\n stage6_stage::Stage6ExecutionArtifacts::default()\n };\n let stage7 = if target.verifies_stage7() {\n stage7_stage::verify_stage7_with_program(programs.stage7, &proof.stage7, inputs.stage7_openings, transcript)?\n } else {\n stage7_stage::Stage7ExecutionArtifacts::default()\n };\n".to_owned() +} + +fn jolt_verifier_evaluation_check() -> String { + " if target.allows_optional_evaluation() {\n match (&proof.evaluation, inputs.evaluation_setup) {\n (Some(evaluation), Some(setup)) => {\n verify_jolt_evaluation_proof(\n programs.stage8,\n evaluation,\n &commitment,\n &proof.stage6,\n &proof.stage7,\n inputs.stage7_openings,\n setup,\n transcript,\n )?;\n }\n (Some(_), None) => return Err(JoltEvaluationProofError::MissingVerifierSetup.into()),\n (None, Some(_)) => return Err(JoltEvaluationProofError::MissingProof.into()),\n (None, None) if target.verifies_evaluation() => return Err(JoltEvaluationProofError::MissingProof.into()),\n (None, None) => {}\n }\n }\n".to_owned() +} + +fn jolt_verifier_input_helpers(prefix: &str) -> String { + format!( + "impl<'a> {prefix}VerifierInputs<'a> {{\n pub fn through_stage5(mut self) -> Self {{ self.stage6_openings = &[]; self.stage7_openings = &[]; self.evaluation_setup = None; self }}\n pub fn through_stage6(mut self) -> Self {{ self.stage7_openings = &[]; self.evaluation_setup = None; self }}\n pub fn through_stage7(mut self) -> Self {{ self.evaluation_setup = None; self }}\n pub fn full(mut self, evaluation_setup: &'a DoryVerifierSetup) -> Self {{ self.evaluation_setup = Some(evaluation_setup); self }}\n}}\n\n" + ) +} + +fn jolt_verifier_evaluation_helpers(prefix: &str, field_type: &str) -> String { + format!( + r#"pub type {prefix}Stage6BytecodeEntry = crate::stages::stage6::Stage6BytecodeEntry; +pub type {prefix}Stage6BytecodeReadRafData = crate::stages::stage6::Stage6BytecodeReadRafData; +pub type {prefix}Stage6VerifierData = crate::stages::stage6::Stage6VerifierData; + +#[expect( + clippy::too_many_arguments, + reason = "generated verifier entry point follows the Jolt proof artifact boundary" +)] +pub fn verify_jolt_evaluation_proof( + program: &'static stage8_stage::Stage8EvaluationProgramPlan, + proof: &{prefix}EvaluationProof, + commitments: &commitment_stage::CommitmentArtifacts, + stage6: &{prefix}StageProof, + stage7: &{prefix}StageProof, + stage7_openings: &[stage7_stage::Stage7OpeningInputValue<{field_type}>], + verifier_setup: &DoryVerifierSetup, + transcript: &mut T, +) -> Result<(), {prefix}EvaluationProofError> +where + T: Transcript, +{{ + let _state_span = tracing::info_span!("bolt.verify.evaluation_state").entered(); + let state = + evaluation_proof_state(program, commitments, stage6, stage7, stage7_openings, transcript)?; + drop(_state_span); + let _dory_verify_span = tracing::info_span!("bolt.verify.dory_verify").entered(); + ::verify( + &state.joint_commitment, + &state.opening_point, + state.joint_claim, + &proof.joint_opening_proof, + verifier_setup, + transcript, + )?; + drop(_dory_verify_span); + let _bind_span = tracing::info_span!("bolt.verify.bind_opening_inputs").entered(); + ::bind_opening_inputs( + transcript, + &state.opening_point, + &state.joint_claim, + ); + drop(_bind_span); + Ok(()) +}} + +struct EvaluationProofState {{ + opening_point: Vec<{field_type}>, + joint_claim: {field_type}, + joint_commitment: DoryCommitment, +}} + +struct EvaluationClaim {{ + oracle: &'static str, + value: {field_type}, +}} + +fn evaluation_proof_state( + program: &'static stage8_stage::Stage8EvaluationProgramPlan, + commitments: &commitment_stage::CommitmentArtifacts, + stage6: &{prefix}StageProof, + stage7: &{prefix}StageProof, + stage7_openings: &[stage7_stage::Stage7OpeningInputValue<{field_type}>], + transcript: &mut T, +) -> Result +where + T: Transcript, +{{ + let (sumcheck_address_point, stage7_values) = stage7_claim_values(program, stage7)?; + let address_point = reverse_point(&sumcheck_address_point); + let opening_point = stage7_evaluation_opening_point(program, &address_point, stage7_openings)?; + let lagrange_factor = EqPolynomial::<{field_type}>::zero_selector(&address_point); + let claims = evaluation_claims(program, stage6, &stage7_values, lagrange_factor)?; + + append_rlc_claims(transcript, &claims); + let gamma_powers = gamma_powers(transcript, claims.len()); + let joint_claim = claims + .iter() + .zip(&gamma_powers) + .map(|(claim, gamma)| claim.value * *gamma) + .sum(); + let joint_commitment = joint_commitment(commitments, &claims, &gamma_powers)?; + + Ok(EvaluationProofState {{ + opening_point, + joint_claim, + joint_commitment, + }}) +}} + +fn stage_eval( + proof: &{prefix}StageProof, + stage: &'static str, + eval_name: &'static str, +) -> Result<{field_type}, {prefix}EvaluationProofError> {{ + for output in &proof.sumchecks {{ + if let Some(eval) = output.evals.iter().find(|eval| eval.name == eval_name) {{ + return Ok(eval.value); + }} + }} + Err({prefix}EvaluationProofError::MissingStageEval {{ + stage, + eval: eval_name, + }}) +}} + +fn evaluation_claims( + program: &'static stage8_stage::Stage8EvaluationProgramPlan, + stage6: &{prefix}StageProof, + stage7_values: &BTreeMap<&'static str, {field_type}>, + lagrange_factor: {field_type}, +) -> Result, {prefix}EvaluationProofError> {{ + let mut claims = Vec::with_capacity(program.opening_claims.len()); + for plan in program.opening_claims {{ + let value = match plan.source_stage {{ + "stage6" => stage_eval(stage6, plan.source_stage, plan.source_claim)? * lagrange_factor, + "stage7" => *stage7_values.get(plan.source_claim).ok_or( + {prefix}EvaluationProofError::MissingStageEval {{ + stage: plan.source_stage, + eval: plan.source_claim, + }}, + )?, + _ => {{ + return Err({prefix}EvaluationProofError::MissingStageEval {{ + stage: plan.source_stage, + eval: plan.source_claim, + }}); + }} + }}; + claims.push(EvaluationClaim {{ + oracle: plan.oracle, + value, + }}); + }} + Ok(claims) +}} + +fn stage7_claim_values( + program: &'static stage8_stage::Stage8EvaluationProgramPlan, + proof: &{prefix}StageProof, +) -> Result<(Vec<{field_type}>, BTreeMap<&'static str, {field_type}>), {prefix}EvaluationProofError> {{ + let stage7_plans = program + .opening_claims + .iter() + .filter(|plan| plan.source_stage == "stage7") + .collect::>(); + for output in &proof.sumchecks {{ + let mut values = BTreeMap::new(); + for plan in &stage7_plans {{ + if let Some(eval) = output.evals.iter().find(|eval| eval.name == plan.source_claim) {{ + let _ = values.insert(plan.source_claim, eval.value); + }} + }} + if values.len() == stage7_plans.len() {{ + return Ok((output.point.clone(), values)); + }} + }} + Err({prefix}EvaluationProofError::MissingStage7RaEval) +}} + +fn reverse_point(point: &[{field_type}]) -> Vec<{field_type}> {{ + point.iter().rev().copied().collect() +}} + +fn stage7_evaluation_opening_point( + program: &'static stage8_stage::Stage8EvaluationProgramPlan, + address_point: &[{field_type}], + stage7_openings: &[stage7_stage::Stage7OpeningInputValue<{field_type}>], +) -> Result, {prefix}EvaluationProofError> {{ + let cycle_source_symbol = program.evaluation_point_source.source_claim; + let cycle_source = stage7_openings + .iter() + .find(|input| input.symbol == cycle_source_symbol) + .ok_or({prefix}EvaluationProofError::MissingStage7EvaluationPoint)?; + if cycle_source.point.len() < address_point.len() {{ + return Err({prefix}EvaluationProofError::InvalidPointLength {{ + artifact: cycle_source_symbol, + expected: address_point.len(), + actual: cycle_source.point.len(), + }}); + }} + let mut point = Vec::with_capacity(cycle_source.point.len()); + point.extend_from_slice(address_point); + point.extend_from_slice(&cycle_source.point[address_point.len()..]); + Ok(point) +}} + +fn append_rlc_claims(transcript: &mut T, claims: &[EvaluationClaim]) +where + T: Transcript, +{{ + transcript.append(&LabelWithCount(b"rlc_claims", claims.len() as u64)); + for claim in claims {{ + claim.value.append_to_transcript(transcript); + }} +}} + +fn gamma_powers(transcript: &mut T, count: usize) -> Vec<{field_type}> +where + T: Transcript, +{{ + let gamma = transcript.challenge(); + let mut powers = Vec::with_capacity(count); + let mut power = {field_type}::from_u64(1); + for _ in 0..count {{ + powers.push(power); + power *= gamma; + }} + powers +}} + +fn joint_commitment( + commitments: &commitment_stage::CommitmentArtifacts, + claims: &[EvaluationClaim], + gamma_powers: &[{field_type}], +) -> Result {{ + let mut coefficients = BTreeMap::<&'static str, {field_type}>::new(); + for (claim, gamma) in claims.iter().zip(gamma_powers) {{ + let coefficient = coefficients.entry(claim.oracle).or_insert({field_type}::from_u64(0)); + *coefficient += *gamma; + }} + let mut commitment_values = Vec::with_capacity(coefficients.len()); + let mut scalars = Vec::with_capacity(coefficients.len()); + for (oracle, coefficient) in coefficients {{ + commitment_values.push(commitment_for_oracle(commitments, oracle)?); + scalars.push(coefficient); + }} + Ok(::combine( + &commitment_values, + &scalars, + )) +}} + +fn commitment_for_oracle( + commitments: &commitment_stage::CommitmentArtifacts, + oracle: &'static str, +) -> Result {{ + for (record, commitment) in commitments.records.iter().zip(&commitments.commitments) {{ + if record.oracle == oracle {{ + return commitment + .clone() + .ok_or({prefix}EvaluationProofError::MissingCommitment {{ oracle }}); + }} + }} + Err({prefix}EvaluationProofError::MissingCommitment {{ oracle }}) +}} + +"# + ) +} + +fn jolt_prover_stage7_opening_input_helpers(field_type: &str) -> String { + format!( + r#"pub struct JoltProverStageInputs<'a, CommitmentInputs> {{ + pub commitment_inputs: &'a mut CommitmentInputs, + pub prover_setup: &'a DoryProverSetup, + pub stage1_outer: stage1::Stage1ProverInputs<'a, {field_type}>, + pub stage2: stage2::Stage2ProverInputs<'a, {field_type}>, + pub stage3: stage3::Stage3ProverInputs<'a, {field_type}>, + pub stage4: stage4::Stage4ProverInputs<'a, {field_type}>, + pub stage5: stage5::Stage5ProverInputs<'a, {field_type}>, + pub stage6: stage6::Stage6ProverInputs<'a, {field_type}>, + pub stage7: stage7::Stage7ProverInputs<'a, {field_type}>, + pub stage7_openings: Option<&'a [stage7::Stage7OpeningInputValue<{field_type}>]>, +}} + +pub fn prove_jolt_with_stage_inputs( + inputs: JoltProverStageInputs<'_, CommitmentInputs>, + programs: JoltProverPrograms, + transcript: &mut T, +) -> Result<(JoltProof, JoltProverArtifacts), JoltProveError> +where + CommitmentInputs: commitment_stage::CommitmentInputProvider, + T: Transcript, +{{ + let JoltProverStageInputs {{ + commitment_inputs, + prover_setup, + stage1_outer, + stage2, + stage3, + stage4, + stage5, + stage6, + stage7, + stage7_openings, + }} = inputs; + let mut stage1_outer_executor = stage1::Stage1ProverKernelExecutor::new(stage1_outer); + let mut stage2_executor = stage2::Stage2ProverKernelExecutor::new(stage2); + let mut stage3_executor = stage3::Stage3ProverKernelExecutor::new(stage3); + let mut stage4_executor = stage4::Stage4ProverKernelExecutor::new(stage4); + let mut stage5_executor = stage5::Stage5ProverKernelExecutor::new(stage5); + let mut stage6_executor = stage6::Stage6ProverKernelExecutor::new(stage6); + let mut stage7_executor = stage7::Stage7ProverKernelExecutor::new(stage7); + prove_jolt_with_programs( + JoltProverInputs {{ + commitment_inputs, + prover_setup, + stage1_outer_executor: &mut stage1_outer_executor, + stage2_executor: &mut stage2_executor, + stage3_executor: &mut stage3_executor, + stage4_executor: &mut stage4_executor, + stage5_executor: &mut stage5_executor, + stage6_executor: &mut stage6_executor, + stage7_executor: &mut stage7_executor, + stage7_openings, + }}, + programs, + transcript, + ) +}} + +pub struct JoltProverWitnessInputs<'a, CommitmentInputs> {{ + pub commitment_inputs: &'a mut CommitmentInputs, + pub prover_setup: &'a DoryProverSetup, + pub stage1_trace_num_vars: usize, + pub stage1_outer_evaluator: &'a dyn stage1::Stage1OuterRemainingEvaluator<{field_type}>, + pub stage2_openings: &'a [stage2::Stage2OpeningInputValue<{field_type}>], + pub product_virtual_cycles: &'a [stage2::Stage2ProductVirtualCycle], + pub instruction_lookup_cycles: &'a [stage2::Stage2InstructionLookupCycle], + pub ram: &'a stage2::Stage2RamData<'a>, + pub stage3_openings: &'a [stage3::Stage3OpeningInputValue<{field_type}>], + pub stage3_cycles: &'a [stage3::Stage3Cycle], + pub stage4_openings: &'a [stage4::Stage4OpeningInputValue<{field_type}>], + pub register_count: usize, + pub trace_len: usize, + pub ram_k: usize, + pub register_accesses: &'a [stage4::Stage4RegisterAccess], + pub stage5_openings: &'a [stage5::Stage5OpeningInputValue<{field_type}>], + pub lookup_indices: &'a [u128], + pub lookup_table_indices: &'a [Option], + pub is_interleaved_operands: &'a [bool], + pub ra_virtual_log_k_chunk: usize, + pub stage6_openings: &'a [stage6::Stage6OpeningInputValue<{field_type}>], + pub stage6_bytecode_data: stage6::Stage6BytecodeReadRafData<'a, {field_type}>, + pub stage6_witness_params: Stage6WitnessParams, + pub cycle_inputs: &'a [CycleInput], + pub instruction_ra_virtual_d: usize, + pub stage7_openings: &'a [stage7::Stage7OpeningInputValue<{field_type}>], + pub evaluation_openings: Option<&'a [stage7::Stage7OpeningInputValue<{field_type}>]>, +}} + +pub fn prove_jolt_with_witness_inputs( + inputs: JoltProverWitnessInputs<'_, CommitmentInputs>, + programs: JoltProverPrograms, + transcript: &mut T, +) -> Result<(JoltProof, JoltProverArtifacts), JoltProveError> +where + CommitmentInputs: commitment_stage::CommitmentInputProvider, + T: Transcript, +{{ + let _input_span = tracing::info_span!("bolt.prove.inputs").entered(); + let _stage1_input_span = tracing::info_span!("bolt.prove.inputs.stage1").entered(); + let stage1_outer = + stage1_outer_prover_inputs(inputs.stage1_trace_num_vars, inputs.stage1_outer_evaluator); + drop(_stage1_input_span); + let _stage2_input_span = tracing::info_span!("bolt.prove.inputs.stage2").entered(); + let stage2 = stage2_prover_inputs( + inputs.stage2_openings, + inputs.product_virtual_cycles, + inputs.instruction_lookup_cycles, + inputs.ram, + )?; + drop(_stage2_input_span); + let _stage3_input_span = tracing::info_span!("bolt.prove.inputs.stage3").entered(); + let stage3 = stage3_prover_inputs(inputs.stage3_openings, inputs.stage3_cycles); + drop(_stage3_input_span); + let _stage45_witness_span = tracing::info_span!("bolt.prove.inputs.stage45_witness").entered(); + let stage45_witness = stage4::stage4_5_sparse_trace_witness_from_accesses( + inputs.register_accesses, + inputs.ram.accesses, + ); + drop(_stage45_witness_span); + let _stage4_input_span = tracing::info_span!("bolt.prove.inputs.stage4").entered(); + let stage4 = stage4_prover_inputs( + inputs.stage4_openings, + inputs.register_count, + inputs.trace_len, + inputs.ram_k, + inputs.register_accesses, + &stage45_witness, + ); + drop(_stage4_input_span); + let _stage5_input_span = tracing::info_span!("bolt.prove.inputs.stage5").entered(); + let stage5 = stage5_prover_inputs( + inputs.stage5_openings, + inputs.trace_len, + inputs.ram_k, + inputs.register_count, + inputs.lookup_indices, + inputs.lookup_table_indices, + inputs.is_interleaved_operands, + inputs.ra_virtual_log_k_chunk, + &stage45_witness, + ); + drop(_stage5_input_span); + let _stage6_witness_span = tracing::info_span!("bolt.prove.inputs.stage6_witness").entered(); + let stage6_witness = stage6_witness_from_opening_inputs( + inputs.stage6_witness_params, + inputs.cycle_inputs, + inputs.stage6_openings, + ); + let stage6_witness_slices = stage6_witness.slices(); + drop(_stage6_witness_span); + let _stage6_input_span = tracing::info_span!("bolt.prove.inputs.stage6").entered(); + let stage6 = stage6_prover_inputs( + inputs.stage6_openings, + inputs.stage6_bytecode_data, + &stage6_witness, + &stage6_witness_slices, + inputs.instruction_ra_virtual_d, + ); + drop(_stage6_input_span); + let _stage7_input_span = tracing::info_span!("bolt.prove.inputs.stage7").entered(); + let stage7 = stage7_prover_inputs(inputs.stage7_openings, &stage6_witness_slices); + drop(_stage7_input_span); + drop(_input_span); + prove_jolt_with_stage_inputs( + JoltProverStageInputs {{ + commitment_inputs: inputs.commitment_inputs, + prover_setup: inputs.prover_setup, + stage1_outer, + stage2, + stage3, + stage4, + stage5, + stage6, + stage7, + stage7_openings: inputs.evaluation_openings, + }}, + programs, + transcript, + ) +}} + +pub fn stage1_outer_prover_inputs( + trace_num_vars: usize, + evaluator: &dyn stage1::Stage1OuterRemainingEvaluator<{field_type}>, +) -> stage1::Stage1ProverInputs<'_, {field_type}> {{ + stage1::Stage1ProverInputs::empty(trace_num_vars).with_outer_remaining_evaluator(evaluator) +}} + +pub fn prove_stage1_outer_inputs_with_program( + program: &'static stage1::Stage1CpuProgramPlan, + inputs: stage1::Stage1ProverInputs<'_, {field_type}>, + transcript: &mut T, +) -> Result, stage1::Stage1KernelError> +where + T: Transcript, +{{ + let mut executor = stage1::Stage1ProverKernelExecutor::new(inputs); + stage1_outer_stage::prove_stage1_outer_with_program(program, &mut executor, transcript) +}} + +pub fn prove_stage1_outer_with_witness_inputs( + program: &'static stage1::Stage1CpuProgramPlan, + trace_num_vars: usize, + evaluator: &dyn stage1::Stage1OuterRemainingEvaluator<{field_type}>, + transcript: &mut T, +) -> Result, stage1::Stage1KernelError> +where + T: Transcript, +{{ + let inputs = stage1_outer_prover_inputs(trace_num_vars, evaluator); + prove_stage1_outer_inputs_with_program(program, inputs, transcript) +}} + +pub fn replay_stage1_outer_proof_with_program( + program: &'static stage1::Stage1CpuProgramPlan, + proof: &stage1::Stage1Proof<{field_type}>, + transcript: &mut T, +) -> Result, stage1::Stage1KernelError> +where + T: Transcript, +{{ + let mut executor = stage1::Stage1VerifierKernelExecutor::new(proof); + stage1::execute_stage1_program( + program, + stage1::Stage1ExecutionMode::Verifier, + &mut executor, + transcript, + ) +}} + +pub fn stage1_outer_proof_from_kernel_proof( + proof: &stage1::Stage1Proof<{field_type}>, +) -> JoltStageProof {{ + JoltStageProof {{ + sumchecks: proof + .sumchecks + .iter() + .map(stage1_outer_sumcheck) + .collect(), + }} +}} + +pub fn stage2_prover_inputs<'a>( + opening_inputs: &'a [stage2::Stage2OpeningInputValue<{field_type}>], + product_virtual_cycles: &'a [stage2::Stage2ProductVirtualCycle], + instruction_lookup_cycles: &'a [stage2::Stage2InstructionLookupCycle], + ram: &'a stage2::Stage2RamData<'a>, +) -> Result, stage2::Stage2KernelError> {{ + Ok(stage2::Stage2ProverInputs::new(opening_inputs) + .with_product_virtual_witness(product_virtual_cycles)? + .with_instruction_lookup_cycles(instruction_lookup_cycles) + .with_ram_data(ram)) +}} + +pub struct JoltStage2RamDataStorage<'a> {{ + log_k: usize, + start_address: u64, + initial_ram: &'a [u64], + final_ram: &'a [u64], + accesses: Vec, + output_layout: Option, +}} + +impl<'a> JoltStage2RamDataStorage<'a> {{ + pub fn from_kernel(ram: &stage2::Stage2RamData<'a>) -> Self {{ + Self {{ + log_k: ram.log_k, + start_address: ram.start_address, + initial_ram: ram.initial_ram, + final_ram: ram.final_ram, + accesses: ram + .accesses + .iter() + .map(|access| JoltStage2RamAccess {{ + remapped_address: access.remapped_address, + read_value: access.read_value, + write_value: access.write_value, + }}) + .collect(), + output_layout: ram.output_layout.map(|layout| JoltStage2RamOutputLayout {{ + io_start: layout.io_start, + io_end: layout.io_end, + }}), + }} + }} + + pub fn as_input(&self) -> JoltStage2RamData<'_> {{ + JoltStage2RamData {{ + log_k: self.log_k, + start_address: self.start_address, + initial_ram: self.initial_ram, + final_ram: self.final_ram, + accesses: &self.accesses, + output_layout: self.output_layout, + }} + }} +}} + +pub fn stage2_verifier_ram_data<'a>( + ram: &stage2::Stage2RamData<'a>, +) -> JoltStage2RamDataStorage<'a> {{ + JoltStage2RamDataStorage::from_kernel(ram) +}} + +pub trait JoltKernelOpeningInput {{ + fn symbol(&self) -> &'static str; + fn point(&self) -> &[{field_type}]; + fn eval(&self) -> {field_type}; +}} + +macro_rules! impl_jolt_kernel_opening_input {{ + ($opening:ty) => {{ + impl JoltKernelOpeningInput for $opening {{ + fn symbol(&self) -> &'static str {{ + self.symbol + }} + + fn point(&self) -> &[{field_type}] {{ + &self.point + }} + + fn eval(&self) -> {field_type} {{ + self.eval + }} + }} + }}; +}} + +impl_jolt_kernel_opening_input!(stage2::Stage2OpeningInputValue<{field_type}>); +impl_jolt_kernel_opening_input!(stage3::Stage3OpeningInputValue<{field_type}>); +impl_jolt_kernel_opening_input!(stage4::Stage4OpeningInputValue<{field_type}>); + +pub fn verifier_opening_inputs_from_kernel(inputs: &[I]) -> Vec +where + I: JoltKernelOpeningInput, +{{ + inputs + .iter() + .map(|input| JoltStageOpeningInputValue {{ + symbol: input.symbol(), + point: input.point().to_vec(), + eval: input.eval(), + }}) + .collect() +}} + +pub fn prove_stage2_inputs_with_program( + program: &'static stage2::Stage2CpuProgramPlan, + inputs: stage2::Stage2ProverInputs<'_, {field_type}>, + transcript: &mut T, +) -> Result, stage2::Stage2KernelError> +where + T: Transcript, +{{ + let mut executor = stage2::Stage2ProverKernelExecutor::new(inputs); + stage2_stage::execute_stage2_prover_with_program(program, &mut executor, transcript) +}} + +pub fn prove_stage2_with_witness_inputs<'a, T>( + program: &'static stage2::Stage2CpuProgramPlan, + opening_inputs: &'a [stage2::Stage2OpeningInputValue<{field_type}>], + product_virtual_cycles: &'a [stage2::Stage2ProductVirtualCycle], + instruction_lookup_cycles: &'a [stage2::Stage2InstructionLookupCycle], + ram: &'a stage2::Stage2RamData<'a>, + transcript: &mut T, +) -> Result, stage2::Stage2KernelError> +where + T: Transcript, +{{ + let inputs = stage2_prover_inputs( + opening_inputs, + product_virtual_cycles, + instruction_lookup_cycles, + ram, + )?; + prove_stage2_inputs_with_program(program, inputs, transcript) +}} + +pub fn stage2_opening_inputs_from_artifacts( + program: &'static stage2::Stage2CpuProgramPlan, + stage1_artifacts: &stage1::Stage1ExecutionArtifacts<{field_type}>, +) -> Result>, JoltOpeningInputError> {{ + program + .opening_inputs + .iter() + .map(|input| {{ + let (point, eval) = match input.source_stage {{ + "stage1" => stage1_opening_claim(stage1_artifacts, input.source_claim)?, + source_stage => {{ + return Err(JoltOpeningInputError::UnsupportedOpeningInputSource {{ + stage: "stage2", + symbol: input.symbol, + source_stage, + }}); + }} + }}; + validate_point_len(input.symbol, input.point_arity, point.len())?; + Ok(stage2::Stage2OpeningInputValue {{ + symbol: input.symbol, + point, + eval, + }}) + }}) + .collect() +}} + +pub fn replay_stage2_proof_with_program<'a, T>( + program: &'static stage2::Stage2CpuProgramPlan, + proof: &'a stage2::Stage2Proof<{field_type}>, + opening_inputs: &'a [stage2::Stage2OpeningInputValue<{field_type}>], + ram: Option<&'a stage2::Stage2RamData<'a>>, + transcript: &mut T, +) -> Result, stage2::Stage2KernelError> +where + T: Transcript, +{{ + let mut executor = stage2::Stage2VerifierKernelExecutor::new(proof, opening_inputs); + if let Some(ram) = ram {{ + executor = executor.with_ram_data(ram); + }} + stage2::execute_stage2_program( + program, + stage2::Stage2ExecutionMode::Verifier, + &mut executor, + transcript, + ) +}} + +pub fn stage3_prover_inputs<'a>( + opening_inputs: &'a [stage3::Stage3OpeningInputValue<{field_type}>], + cycles: &'a [stage3::Stage3Cycle], +) -> stage3::Stage3ProverInputs<'a, {field_type}> {{ + stage3::Stage3ProverInputs::new(opening_inputs).with_cycles(cycles) +}} + +pub fn prove_stage3_inputs_with_program( + program: &'static stage3::Stage3CpuProgramPlan, + inputs: stage3::Stage3ProverInputs<'_, {field_type}>, + transcript: &mut T, +) -> Result, stage3::Stage3KernelError> +where + T: Transcript, +{{ + let mut executor = stage3::Stage3ProverKernelExecutor::new(inputs); + stage3_stage::execute_stage3_prover_with_program(program, &mut executor, transcript) +}} + +pub fn prove_stage3_with_witness_inputs( + program: &'static stage3::Stage3CpuProgramPlan, + opening_inputs: &[stage3::Stage3OpeningInputValue<{field_type}>], + cycles: &[stage3::Stage3Cycle], + transcript: &mut T, +) -> Result, stage3::Stage3KernelError> +where + T: Transcript, +{{ + let inputs = stage3_prover_inputs(opening_inputs, cycles); + prove_stage3_inputs_with_program(program, inputs, transcript) +}} + +pub fn stage3_opening_inputs_from_artifacts( + program: &'static stage3::Stage3CpuProgramPlan, + stage1_artifacts: &stage1::Stage1ExecutionArtifacts<{field_type}>, + stage2_artifacts: &stage2::Stage2ExecutionArtifacts<{field_type}>, +) -> Result>, JoltOpeningInputError> {{ + program + .opening_inputs + .iter() + .map(|input| {{ + let (point, eval) = match input.source_stage {{ + "stage1" => stage1_opening_claim(stage1_artifacts, input.source_claim)?, + "stage2" => stage2_opening_claim(stage2_artifacts, input.source_claim)?, + source_stage => {{ + return Err(JoltOpeningInputError::UnsupportedOpeningInputSource {{ + stage: "stage3", + symbol: input.symbol, + source_stage, + }}); + }} + }}; + validate_point_len(input.symbol, input.point_arity, point.len())?; + Ok(stage3::Stage3OpeningInputValue {{ + symbol: input.symbol, + point, + eval, + }}) + }}) + .collect() +}} + +pub fn replay_stage3_proof_with_program( + program: &'static stage3::Stage3CpuProgramPlan, + proof: &stage3::Stage3Proof<{field_type}>, + opening_inputs: &[stage3::Stage3OpeningInputValue<{field_type}>], + transcript: &mut T, +) -> Result, stage3::Stage3KernelError> +where + T: Transcript, +{{ + let mut executor = stage3::Stage3VerifierKernelExecutor::new(proof, opening_inputs); + stage3::execute_stage3_program( + program, + stage3::Stage3ExecutionMode::Verifier, + &mut executor, + transcript, + ) +}} + +pub fn stage4_prover_inputs<'a>( + opening_inputs: &'a [stage4::Stage4OpeningInputValue<{field_type}>], + register_count: usize, + trace_len: usize, + ram_k: usize, + register_accesses: &'a [stage4::Stage4RegisterAccess], + witness: &'a Stage45SparseTraceWitness<{field_type}>, +) -> stage4::Stage4ProverInputs<'a, {field_type}> {{ + stage4::Stage4ProverInputs::new(opening_inputs).with_stage45_sparse_trace_witness( + register_count, + trace_len, + ram_k, + register_accesses, + witness, + ) +}} + +pub fn prove_stage4_inputs_with_program( + program: &'static stage4::Stage4CpuProgramPlan, + inputs: stage4::Stage4ProverInputs<'_, {field_type}>, + transcript: &mut T, +) -> Result, stage4::Stage4KernelError> +where + T: Transcript, +{{ + let mut executor = stage4::Stage4ProverKernelExecutor::new(inputs); + stage4_stage::execute_stage4_prover_with_program(program, &mut executor, transcript) +}} + +pub fn prove_stage4_with_witness_inputs( + program: &'static stage4::Stage4CpuProgramPlan, + opening_inputs: &[stage4::Stage4OpeningInputValue<{field_type}>], + register_count: usize, + trace_len: usize, + ram_k: usize, + register_accesses: &[stage4::Stage4RegisterAccess], + witness: &Stage45SparseTraceWitness<{field_type}>, + transcript: &mut T, +) -> Result, stage4::Stage4KernelError> +where + T: Transcript, +{{ + let inputs = stage4_prover_inputs( + opening_inputs, + register_count, + trace_len, + ram_k, + register_accesses, + witness, + ); + prove_stage4_inputs_with_program(program, inputs, transcript) +}} + +pub fn prove_stage4_with_trace_witness_inputs( + program: &'static stage4::Stage4CpuProgramPlan, + opening_inputs: &[stage4::Stage4OpeningInputValue<{field_type}>], + register_count: usize, + trace_len: usize, + ram_k: usize, + register_accesses: &[stage4::Stage4RegisterAccess], + ram_accesses: &[stage2::Stage2RamAccess], + transcript: &mut T, +) -> Result, stage4::Stage4KernelError> +where + T: Transcript, +{{ + let witness = stage4::stage4_5_sparse_trace_witness_from_accesses( + register_accesses, + ram_accesses, + ); + prove_stage4_with_witness_inputs( + program, + opening_inputs, + register_count, + trace_len, + ram_k, + register_accesses, + &witness, + transcript, + ) +}} + +pub fn stage4_opening_inputs_from_artifacts( + program: &'static stage4::Stage4CpuProgramPlan, + initial_ram_state: &[u64], + stage2_artifacts: &stage2::Stage2ExecutionArtifacts<{field_type}>, + stage3_artifacts: &stage3::Stage3ExecutionArtifacts<{field_type}>, +) -> Result>, JoltOpeningInputError> {{ + program + .opening_inputs + .iter() + .map(|input| {{ + let (point, eval) = match input.source_stage {{ + "stage2" => stage2_opening_claim(stage2_artifacts, input.source_claim)?, + "stage3" => stage3_opening_claim(stage3_artifacts, input.source_claim)?, + "stage4_precomputed" => {{ + let (point, _) = stage2_opening_claim( + stage2_artifacts, + "stage2.ram_output.opening.RamValFinal", + )?; + stage4_ram_val_init_opening(initial_ram_state, &point) + }} + source_stage => {{ + return Err(JoltOpeningInputError::UnsupportedOpeningInputSource {{ + stage: "stage4", + symbol: input.symbol, + source_stage, + }}); + }} + }}; + opening_input_value(input.symbol, input.point_arity, point, eval) + }}) + .collect() +}} + +pub fn replay_stage4_proof_with_program( + program: &'static stage4::Stage4CpuProgramPlan, + proof: &stage4::Stage4Proof<{field_type}>, + opening_inputs: &[stage4::Stage4OpeningInputValue<{field_type}>], + transcript: &mut T, +) -> Result, stage4::Stage4KernelError> +where + T: Transcript, +{{ + let mut executor = stage4::Stage4VerifierKernelExecutor::new(proof, opening_inputs); + stage4::execute_stage4_program( + program, + stage4::Stage4ExecutionMode::Verifier, + &mut executor, + transcript, + ) +}} + +pub fn stage5_prover_inputs<'a>( + opening_inputs: &'a [stage5::Stage5OpeningInputValue<{field_type}>], + trace_len: usize, + ram_k: usize, + register_count: usize, + lookup_indices: &'a [u128], + lookup_table_indices: &'a [Option], + is_interleaved_operands: &'a [bool], + ra_virtual_log_k_chunk: usize, + witness: &'a Stage45SparseTraceWitness<{field_type}>, +) -> stage5::Stage5ProverInputs<'a, {field_type}> {{ + stage5::Stage5ProverInputs::new(opening_inputs).with_stage45_sparse_trace_witness( + trace_len, + ram_k, + register_count, + lookup_indices, + lookup_table_indices, + is_interleaved_operands, + ra_virtual_log_k_chunk, + witness, + ) +}} + +pub fn prove_stage5_inputs_with_program( + program: &'static stage5::Stage5CpuProgramPlan, + inputs: stage5::Stage5ProverInputs<'_, {field_type}>, + transcript: &mut T, +) -> Result, stage5::Stage5KernelError> +where + T: Transcript, +{{ + let mut executor = stage5::Stage5ProverKernelExecutor::new(inputs); + stage5_stage::execute_stage5_prover_with_program(program, &mut executor, transcript) +}} + +pub fn prove_stage5_with_witness_inputs( + program: &'static stage5::Stage5CpuProgramPlan, + opening_inputs: &[stage5::Stage5OpeningInputValue<{field_type}>], + trace_len: usize, + ram_k: usize, + register_count: usize, + lookup_indices: &[u128], + lookup_table_indices: &[Option], + is_interleaved_operands: &[bool], + ra_virtual_log_k_chunk: usize, + witness: &Stage45SparseTraceWitness<{field_type}>, + transcript: &mut T, +) -> Result, stage5::Stage5KernelError> +where + T: Transcript, +{{ + let inputs = stage5_prover_inputs( + opening_inputs, + trace_len, + ram_k, + register_count, + lookup_indices, + lookup_table_indices, + is_interleaved_operands, + ra_virtual_log_k_chunk, + witness, + ); + prove_stage5_inputs_with_program(program, inputs, transcript) +}} + +pub fn prove_stage5_with_trace_witness_inputs( + program: &'static stage5::Stage5CpuProgramPlan, + opening_inputs: &[stage5::Stage5OpeningInputValue<{field_type}>], + trace_len: usize, + ram_k: usize, + register_count: usize, + lookup_indices: &[u128], + lookup_table_indices: &[Option], + is_interleaved_operands: &[bool], + ra_virtual_log_k_chunk: usize, + register_accesses: &[stage4::Stage4RegisterAccess], + ram_accesses: &[stage2::Stage2RamAccess], + transcript: &mut T, +) -> Result, stage5::Stage5KernelError> +where + T: Transcript, +{{ + let witness = stage4::stage4_5_sparse_trace_witness_from_accesses( + register_accesses, + ram_accesses, + ); + prove_stage5_with_witness_inputs( + program, + opening_inputs, + trace_len, + ram_k, + register_count, + lookup_indices, + lookup_table_indices, + is_interleaved_operands, + ra_virtual_log_k_chunk, + &witness, + transcript, + ) +}} + +pub fn stage5_opening_inputs_from_artifacts( + program: &'static stage5::Stage5CpuProgramPlan, + stage2_artifacts: &stage2::Stage2ExecutionArtifacts<{field_type}>, + stage4_artifacts: &stage4::Stage4ExecutionArtifacts<{field_type}>, +) -> Result>, JoltOpeningInputError> {{ + program + .opening_inputs + .iter() + .map(|input| {{ + let (point, eval) = match input.source_stage {{ + "stage2" => stage2_opening_claim(stage2_artifacts, input.source_claim)?, + "stage4" => stage4_opening_claim(stage4_artifacts, input.source_claim)?, + source_stage => {{ + return Err(JoltOpeningInputError::UnsupportedOpeningInputSource {{ + stage: "stage5", + symbol: input.symbol, + source_stage, + }}); + }} + }}; + opening_input_value(input.symbol, input.point_arity, point, eval) + }}) + .collect() +}} + +pub fn stage5_kernel_proof( + artifacts: &stage5::Stage5ExecutionArtifacts<{field_type}>, +) -> stage5::Stage5Proof<{field_type}> {{ + stage5::Stage5Proof {{ + sumchecks: artifacts.sumchecks.clone(), + }} +}} + +pub fn jolt_proof_through_stage5( + commitments: &[Option], + stage1_artifacts: &stage1::Stage1ExecutionArtifacts<{field_type}>, + stage2_artifacts: &stage2::Stage2ExecutionArtifacts<{field_type}>, + stage3_artifacts: &stage3::Stage3ExecutionArtifacts<{field_type}>, + stage4_artifacts: &stage4::Stage4ExecutionArtifacts<{field_type}>, + stage5_proof: &JoltStageProof, +) -> JoltProof {{ + JoltProof {{ + commitments: commitments.to_vec(), + stage1_outer: stage1_outer_proof(stage1_artifacts), + stage2: stage2_proof(stage2_artifacts), + stage3: stage3_proof(stage3_artifacts), + stage4: stage4_proof(stage4_artifacts), + stage5: stage5_proof.clone(), + stage6: JoltStageProof::default(), + stage7: JoltStageProof::default(), + evaluation: None, + }} +}} + +pub fn jolt_proof_through_stage6( + commitments: &[Option], + stage1_artifacts: &stage1::Stage1ExecutionArtifacts<{field_type}>, + stage2_artifacts: &stage2::Stage2ExecutionArtifacts<{field_type}>, + stage3_artifacts: &stage3::Stage3ExecutionArtifacts<{field_type}>, + stage4_artifacts: &stage4::Stage4ExecutionArtifacts<{field_type}>, + stage5_proof: &JoltStageProof, + stage6_proof: &JoltStageProof, +) -> JoltProof {{ + let mut proof = jolt_proof_through_stage5( + commitments, + stage1_artifacts, + stage2_artifacts, + stage3_artifacts, + stage4_artifacts, + stage5_proof, + ); + proof.stage6 = stage6_proof.clone(); + proof +}} + +pub fn jolt_proof_through_stage7( + commitments: &[Option], + stage1_artifacts: &stage1::Stage1ExecutionArtifacts<{field_type}>, + stage2_artifacts: &stage2::Stage2ExecutionArtifacts<{field_type}>, + stage3_artifacts: &stage3::Stage3ExecutionArtifacts<{field_type}>, + stage4_artifacts: &stage4::Stage4ExecutionArtifacts<{field_type}>, + stage5_proof: &JoltStageProof, + stage6_proof: &JoltStageProof, + stage7_proof: &JoltStageProof, +) -> JoltProof {{ + let mut proof = jolt_proof_through_stage6( + commitments, + stage1_artifacts, + stage2_artifacts, + stage3_artifacts, + stage4_artifacts, + stage5_proof, + stage6_proof, + ); + proof.stage7 = stage7_proof.clone(); + proof +}} + +pub fn replay_stage5_proof_with_program( + program: &'static stage5::Stage5CpuProgramPlan, + proof: &stage5::Stage5Proof<{field_type}>, + opening_inputs: &[stage5::Stage5OpeningInputValue<{field_type}>], + transcript: &mut T, +) -> Result, stage5::Stage5KernelError> +where + T: Transcript, +{{ + let mut executor = stage5::Stage5ProofCarryingKernelExecutor::new(proof, opening_inputs); + stage5_stage::execute_stage5_prover_with_program(program, &mut executor, transcript) +}} + +pub fn stage6_witness_from_opening_inputs( + params: Stage6WitnessParams, + cycle_inputs: &[CycleInput], + opening_inputs: &[stage6::Stage6OpeningInputValue<{field_type}>], +) -> Stage6WitnessPolynomials<{field_type}> {{ + stage6::stage6_witness_from_opening_inputs(params, cycle_inputs, opening_inputs) +}} + +pub fn stage6_bytecode_read_raf_data_from_witness_entries( + entries: &[WitnessStage6BytecodeEntry<{field_type}>], + entry_bytecode_index: usize, + num_lookup_tables: usize, +) -> stage6::Stage6BytecodeReadRafDataStorage<{field_type}> {{ + stage6::Stage6BytecodeReadRafDataStorage::from_witness_entries( + entries, + entry_bytecode_index, + num_lookup_tables, + ) +}} + +pub fn stage6_verifier_data_from_witness_entries( + entries: &[WitnessStage6BytecodeEntry<{field_type}>], + entry_bytecode_index: usize, + num_lookup_tables: usize, +) -> JoltStage6VerifierData {{ + JoltStage6VerifierData {{ + bytecode_read_raf: Some(JoltStage6BytecodeReadRafData {{ + entries: entries + .iter() + .map(|entry| JoltStage6BytecodeEntry {{ + address: entry.address, + imm: entry.imm, + circuit_flags: entry.circuit_flags, + rd: entry.rd, + rs1: entry.rs1, + rs2: entry.rs2, + lookup_table: entry.lookup_table, + is_interleaved: entry.is_interleaved, + is_branch: entry.is_branch, + left_is_rs1: entry.left_is_rs1, + left_is_pc: entry.left_is_pc, + right_is_rs2: entry.right_is_rs2, + right_is_imm: entry.right_is_imm, + is_noop: entry.is_noop, + }}) + .collect(), + entry_bytecode_index, + num_lookup_tables, + }}), + }} +}} + +pub fn stage6_prover_inputs<'a>( + opening_inputs: &'a [stage6::Stage6OpeningInputValue<{field_type}>], + bytecode_data: stage6::Stage6BytecodeReadRafData<'a, {field_type}>, + witness: &'a Stage6WitnessPolynomials<{field_type}>, + slices: &'a Stage6WitnessSlices<'a, {field_type}>, + instruction_ra_virtual_d: usize, +) -> stage6::Stage6ProverInputs<'a, {field_type}> {{ + stage6::Stage6ProverInputs::new(opening_inputs).with_stage6_witness( + bytecode_data, + witness, + slices, + instruction_ra_virtual_d, + ) +}} + +pub fn prove_stage6_inputs_with_program( + program: &'static stage6::Stage6CpuProgramPlan, + inputs: stage6::Stage6ProverInputs<'_, {field_type}>, + transcript: &mut T, +) -> Result, stage6::Stage6KernelError> +where + T: Transcript, +{{ + let mut executor = stage6::Stage6ProverKernelExecutor::new(inputs); + stage6_stage::execute_stage6_prover_with_program(program, &mut executor, transcript) +}} + +pub fn prove_stage6_with_witness_inputs( + program: &'static stage6::Stage6CpuProgramPlan, + opening_inputs: &[stage6::Stage6OpeningInputValue<{field_type}>], + bytecode_data: stage6::Stage6BytecodeReadRafData<'_, {field_type}>, + witness: &Stage6WitnessPolynomials<{field_type}>, + slices: &Stage6WitnessSlices<'_, {field_type}>, + instruction_ra_virtual_d: usize, + transcript: &mut T, +) -> Result, stage6::Stage6KernelError> +where + T: Transcript, +{{ + let inputs = stage6_prover_inputs( + opening_inputs, + bytecode_data, + witness, + slices, + instruction_ra_virtual_d, + ); + prove_stage6_inputs_with_program(program, inputs, transcript) +}} + +pub fn prove_stage6_with_trace_witness_inputs( + program: &'static stage6::Stage6CpuProgramPlan, + opening_inputs: &[stage6::Stage6OpeningInputValue<{field_type}>], + bytecode_data: stage6::Stage6BytecodeReadRafData<'_, {field_type}>, + witness_params: Stage6WitnessParams, + cycle_inputs: &[CycleInput], + instruction_ra_virtual_d: usize, + transcript: &mut T, +) -> Result, stage6::Stage6KernelError> +where + T: Transcript, +{{ + let witness = stage6_witness_from_opening_inputs(witness_params, cycle_inputs, opening_inputs); + let slices = witness.slices(); + prove_stage6_with_witness_inputs( + program, + opening_inputs, + bytecode_data, + &witness, + &slices, + instruction_ra_virtual_d, + transcript, + ) +}} + +pub fn stage6_opening_inputs_from_artifacts( + program: &'static stage6::Stage6CpuProgramPlan, + stage1_artifacts: &stage1::Stage1ExecutionArtifacts<{field_type}>, + stage2_artifacts: &stage2::Stage2ExecutionArtifacts<{field_type}>, + stage3_artifacts: &stage3::Stage3ExecutionArtifacts<{field_type}>, + stage4_artifacts: &stage4::Stage4ExecutionArtifacts<{field_type}>, + stage5_artifacts: &stage5::Stage5ExecutionArtifacts<{field_type}>, +) -> Result>, JoltOpeningInputError> {{ + program + .opening_inputs + .iter() + .map(|input| {{ + let (point, eval) = match input.source_stage {{ + "stage1" => stage1_opening_claim(stage1_artifacts, input.source_claim)?, + "stage2" => stage2_opening_claim(stage2_artifacts, input.source_claim)?, + "stage3" => stage3_opening_claim(stage3_artifacts, input.source_claim)?, + "stage4" => stage4_opening_claim(stage4_artifacts, input.source_claim)?, + "stage5" => stage5_opening_claim(stage5_artifacts, input.source_claim)?, + source_stage => {{ + return Err(JoltOpeningInputError::UnsupportedOpeningInputSource {{ + stage: "stage6", + symbol: input.symbol, + source_stage, + }}); + }} + }}; + opening_input_value(input.symbol, input.point_arity, point, eval) + }}) + .collect() +}} + +pub fn stage6_kernel_proof(proof: &JoltStageProof) -> stage6::Stage6Proof<{field_type}> {{ + stage6::Stage6Proof {{ + sumchecks: proof + .sumchecks + .iter() + .map(stage6_kernel_sumcheck_output) + .collect(), + }} +}} + +fn stage6_kernel_sumcheck_output( + output: &JoltSumcheckOutput, +) -> stage6::Stage6SumcheckOutput<{field_type}> {{ + stage6::Stage6SumcheckOutput {{ + driver: output.driver, + point: output.point.clone(), + evals: output.evals.iter().map(stage6_kernel_eval).collect(), + opening_claims: Vec::new(), + proof: output.proof.clone(), + }} +}} + +fn stage6_kernel_eval(eval: &JoltNamedEval) -> stage6::Stage6NamedEval<{field_type}> {{ + stage6::Stage6NamedEval {{ + name: eval.name, + oracle: eval.oracle, + value: eval.value, + }} +}} + +pub fn stage6_execution_artifacts( + artifacts: &stage6::Stage6ExecutionArtifacts<{field_type}>, +) -> JoltStageExecutionArtifacts {{ + JoltStageExecutionArtifacts {{ + challenge_vectors: artifacts + .challenge_vectors + .iter() + .map(|challenge| JoltStageChallengeVector {{ + symbol: challenge.symbol, + values: challenge.values.clone(), + }}) + .collect(), + sumchecks: stage6_proof(artifacts).sumchecks, + opening_batches: Vec::new(), + }} +}} + +pub fn replay_stage6_proof_with_program<'a, T>( + program: &'static stage6::Stage6CpuProgramPlan, + proof: &'a stage6::Stage6Proof<{field_type}>, + opening_inputs: &'a [stage6::Stage6OpeningInputValue<{field_type}>], + bytecode_data: Option>, + transcript: &mut T, +) -> Result, stage6::Stage6KernelError> +where + T: Transcript, +{{ + let mut executor = stage6::Stage6ProofCarryingKernelExecutor::new(proof, opening_inputs); + if let Some(bytecode_data) = bytecode_data {{ + executor = executor.with_bytecode_read_raf_data(bytecode_data); + }} + stage6_stage::execute_stage6_prover_with_program(program, &mut executor, transcript) +}} + +pub fn stage7_prover_inputs<'a>( + opening_inputs: &'a [stage7::Stage7OpeningInputValue<{field_type}>], + slices: &'a Stage6WitnessSlices<'a, {field_type}>, +) -> stage7::Stage7ProverInputs<'a, {field_type}> {{ + stage7::Stage7ProverInputs::new(opening_inputs).with_stage6_witness_indices(slices) +}} + +pub fn prove_stage7_inputs_with_program( + program: &'static stage7::Stage7CpuProgramPlan, + inputs: stage7::Stage7ProverInputs<'_, {field_type}>, + transcript: &mut T, +) -> Result, stage7::Stage7KernelError> +where + T: Transcript, +{{ + let mut executor = stage7::Stage7ProverKernelExecutor::new(inputs); + stage7_stage::execute_stage7_prover_with_program(program, &mut executor, transcript) +}} + +pub fn prove_stage7_with_witness_inputs( + program: &'static stage7::Stage7CpuProgramPlan, + opening_inputs: &[stage7::Stage7OpeningInputValue<{field_type}>], + slices: &Stage6WitnessSlices<'_, {field_type}>, + transcript: &mut T, +) -> Result, stage7::Stage7KernelError> +where + T: Transcript, +{{ + let inputs = stage7_prover_inputs(opening_inputs, slices); + prove_stage7_inputs_with_program(program, inputs, transcript) +}} + +pub fn prove_stage7_with_trace_witness_inputs( + program: &'static stage7::Stage7CpuProgramPlan, + opening_inputs: &[stage7::Stage7OpeningInputValue<{field_type}>], + witness_params: Stage6WitnessParams, + cycle_inputs: &[CycleInput], + stage6_openings: &[stage6::Stage6OpeningInputValue<{field_type}>], + transcript: &mut T, +) -> Result, stage7::Stage7KernelError> +where + T: Transcript, +{{ + let witness = stage6_witness_from_opening_inputs(witness_params, cycle_inputs, stage6_openings); + let slices = witness.slices(); + prove_stage7_with_witness_inputs(program, opening_inputs, &slices, transcript) +}} + +pub fn stage7_kernel_proof(proof: &JoltStageProof) -> stage7::Stage7Proof<{field_type}> {{ + stage7::Stage7Proof {{ + sumchecks: proof + .sumchecks + .iter() + .map(stage7_kernel_sumcheck_output) + .collect(), + }} +}} + +fn stage7_kernel_sumcheck_output( + output: &JoltSumcheckOutput, +) -> stage7::Stage7SumcheckOutput<{field_type}> {{ + stage7::Stage7SumcheckOutput {{ + driver: output.driver, + point: output.point.clone(), + evals: output.evals.iter().map(stage7_kernel_eval).collect(), + opening_claims: Vec::new(), + proof: output.proof.clone(), + }} +}} + +fn stage7_kernel_eval(eval: &JoltNamedEval) -> stage7::Stage7NamedEval<{field_type}> {{ + stage7::Stage7NamedEval {{ + name: eval.name, + oracle: eval.oracle, + value: eval.value, + }} +}} + +pub fn stage7_execution_artifacts( + artifacts: &stage7::Stage7ExecutionArtifacts<{field_type}>, +) -> JoltStageExecutionArtifacts {{ + JoltStageExecutionArtifacts {{ + challenge_vectors: artifacts + .challenge_vectors + .iter() + .map(|challenge| JoltStageChallengeVector {{ + symbol: challenge.symbol, + values: challenge.values.clone(), + }}) + .collect(), + sumchecks: stage7_proof(artifacts).sumchecks, + opening_batches: Vec::new(), + }} +}} + +pub fn replay_stage7_proof_with_program( + program: &'static stage7::Stage7CpuProgramPlan, + proof: &stage7::Stage7Proof<{field_type}>, + opening_inputs: &[stage7::Stage7OpeningInputValue<{field_type}>], + transcript: &mut T, +) -> Result, stage7::Stage7KernelError> +where + T: Transcript, +{{ + let mut executor = stage7::Stage7ProofCarryingKernelExecutor::new(proof, opening_inputs); + stage7_stage::execute_stage7_prover_with_program(program, &mut executor, transcript) +}} + +pub fn stage7_opening_inputs_from_stage6_artifacts( + artifacts: &stage6::Stage6ExecutionArtifacts<{field_type}>, +) -> Result>, JoltOpeningInputError> {{ + stage7_opening_inputs_from_stage6_artifacts_with_program(&stage7_stage::STAGE7_PROGRAM, artifacts) +}} + +pub fn stage7_opening_inputs_from_stage6_artifacts_with_program( + program: &'static stage7::Stage7CpuProgramPlan, + artifacts: &stage6::Stage6ExecutionArtifacts<{field_type}>, +) -> Result>, JoltOpeningInputError> {{ + program + .opening_inputs + .iter() + .map(|input| {{ + let (point, eval) = stage6_opening_claim(artifacts, input.symbol, input.source_stage, input.source_claim, input.point_arity)?; + Ok(stage7::Stage7OpeningInputValue {{ + symbol: input.symbol, + point, + eval, + }}) + }}) + .collect() +}} + +fn stage6_opening_claim( + artifacts: &stage6::Stage6ExecutionArtifacts<{field_type}>, + symbol: &'static str, + source_stage: &'static str, + source_claim: &'static str, + point_arity: usize, +) -> Result<(Vec<{field_type}>, {field_type}), JoltOpeningInputError> {{ + if source_stage != "stage6" {{ + return Err(JoltOpeningInputError::UnsupportedStage7InputSource {{ + symbol, + source_stage, + }}); + }} + let opening = artifacts + .opening_claims + .iter() + .find(|opening| opening.symbol == source_claim) + .ok_or(JoltOpeningInputError::MissingStage6OpeningClaim {{ source_claim }})?; + if opening.point.len() != point_arity {{ + return Err(JoltOpeningInputError::InvalidPointLength {{ + symbol, + expected: point_arity, + actual: opening.point.len(), + }}); + }} + Ok((opening.point.clone(), opening.eval)) +}} + +fn opening_input_value( + symbol: &'static str, + point_arity: usize, + point: Vec<{field_type}>, + eval: {field_type}, +) -> Result, JoltOpeningInputError> {{ + validate_point_len(symbol, point_arity, point.len())?; + Ok(stage4::Stage4OpeningInputValue {{ + symbol, + point, + eval, + }}) +}} + +fn validate_point_len( + symbol: &'static str, + expected: usize, + actual: usize, +) -> Result<(), JoltOpeningInputError> {{ + if actual != expected {{ + return Err(JoltOpeningInputError::InvalidPointLength {{ + symbol, + expected, + actual, + }}); + }} + Ok(()) +}} + +fn stage1_opening_claim( + artifacts: &stage1::Stage1ExecutionArtifacts<{field_type}>, + source_claim: &'static str, +) -> Result<(Vec<{field_type}>, {field_type}), JoltOpeningInputError> {{ + let opening = artifacts.opening_value(source_claim).ok_or( + JoltOpeningInputError::MissingOpeningClaim {{ + stage: "stage1", + source_claim, + }}, + )?; + Ok((opening.point.clone(), opening.eval)) +}} + +fn stage2_opening_claim( + artifacts: &stage2::Stage2ExecutionArtifacts<{field_type}>, + source_claim: &'static str, +) -> Result<(Vec<{field_type}>, {field_type}), JoltOpeningInputError> {{ + artifacts + .opening_claims + .iter() + .find(|opening| opening.symbol == source_claim) + .map(|opening| (opening.point.clone(), opening.eval)) + .ok_or(JoltOpeningInputError::MissingOpeningClaim {{ + stage: "stage2", + source_claim, + }}) +}} + +fn stage3_opening_claim( + artifacts: &stage3::Stage3ExecutionArtifacts<{field_type}>, + source_claim: &'static str, +) -> Result<(Vec<{field_type}>, {field_type}), JoltOpeningInputError> {{ + artifacts + .opening_claims + .iter() + .find(|opening| opening.symbol == source_claim) + .map(|opening| (opening.point.clone(), opening.eval)) + .ok_or(JoltOpeningInputError::MissingOpeningClaim {{ + stage: "stage3", + source_claim, + }}) +}} + +fn stage4_opening_claim( + artifacts: &stage4::Stage4ExecutionArtifacts<{field_type}>, + source_claim: &'static str, +) -> Result<(Vec<{field_type}>, {field_type}), JoltOpeningInputError> {{ + artifacts + .opening_claims + .iter() + .find(|opening| opening.symbol == source_claim) + .map(|opening| (opening.point.clone(), opening.eval)) + .ok_or(JoltOpeningInputError::MissingOpeningClaim {{ + stage: "stage4", + source_claim, + }}) +}} + +fn stage5_opening_claim( + artifacts: &stage5::Stage5ExecutionArtifacts<{field_type}>, + source_claim: &'static str, +) -> Result<(Vec<{field_type}>, {field_type}), JoltOpeningInputError> {{ + artifacts + .opening_claims + .iter() + .find(|opening| opening.symbol == source_claim) + .map(|opening| (opening.point.clone(), opening.eval)) + .ok_or(JoltOpeningInputError::MissingOpeningClaim {{ + stage: "stage5", + source_claim, + }}) +}} + +"# + ) +} + +fn jolt_prover_evaluation_helpers(field_type: &str) -> String { + format!( + r#"pub fn prove_jolt_evaluation_proof( + program: &'static stage8_stage::Stage8EvaluationProgramPlan, + commitment_inputs: &mut I, + prover_setup: &DoryProverSetup, + commitments: &commitment_stage::CommitmentArtifacts, + stage6: &stage6::Stage6ExecutionArtifacts<{field_type}>, + stage7: &stage7::Stage7ExecutionArtifacts<{field_type}>, + stage7_openings: &[stage7::Stage7OpeningInputValue<{field_type}>], + transcript: &mut T, +) -> Result +where + I: commitment_stage::CommitmentInputProvider, + T: Transcript, +{{ + let _claims_span = tracing::info_span!("bolt.evaluate.claims").entered(); + let (sumcheck_address_point, stage7_values) = stage7_claim_values(program, stage7)?; + let address_point = reverse_point(&sumcheck_address_point); + let (opening_point, log_t) = + stage7_evaluation_opening_point(program, &address_point, stage7_openings)?; + let lagrange_factor = EqPolynomial::<{field_type}>::zero_selector(&address_point); + let claims = evaluation_claims(program, stage6, &stage7_values, lagrange_factor)?; + drop(_claims_span); + + let _rlc_span = tracing::info_span!("bolt.evaluate.rlc_claims").entered(); + append_rlc_claims(transcript, &claims); + let gamma_powers = gamma_powers(transcript, claims.len()); + let joint_claim = claims + .iter() + .zip(&gamma_powers) + .map(|(claim, gamma)| claim.value * *gamma) + .sum(); + drop(_rlc_span); + let _materialize_span = + tracing::info_span!("bolt.evaluate.materialize_joint_polynomial").entered(); + let joint_evals = materialize_joint_polynomial( + commitment_inputs, + &claims, + &gamma_powers, + log_t, + opening_point.len(), + )?; + drop(_materialize_span); + let joint_poly = Polynomial::new(joint_evals); + let _hint_span = tracing::info_span!("bolt.evaluate.joint_opening_hint").entered(); + let joint_hint = joint_opening_hint(commitments, &claims, &gamma_powers)?; + drop(_hint_span); + let _dory_open_span = tracing::info_span!("bolt.evaluate.dory_open").entered(); + let joint_opening_proof = ::open( + &joint_poly, + &opening_point, + joint_claim, + prover_setup, + Some(joint_hint), + transcript, + ); + drop(_dory_open_span); + let _bind_span = tracing::info_span!("bolt.evaluate.bind_opening_inputs").entered(); + ::bind_opening_inputs( + transcript, + &opening_point, + &joint_claim, + ); + drop(_bind_span); + Ok(JoltEvaluationProof {{ joint_opening_proof }}) +}} + +struct EvaluationClaim {{ + oracle: &'static str, + source_stage: &'static str, + value: {field_type}, +}} + +fn stage6_eval_claim( + artifacts: &stage6::Stage6ExecutionArtifacts<{field_type}>, + eval_name: &'static str, +) -> Result<{field_type}, JoltEvaluationProveError> {{ + for output in &artifacts.sumchecks {{ + if let Some(eval) = output.evals.iter().find(|eval| eval.name == eval_name) {{ + return Ok(eval.value); + }} + }} + Err(JoltEvaluationProveError::MissingStageEval {{ + stage: "stage6", + eval: eval_name, + }}) +}} + +fn evaluation_claims( + program: &'static stage8_stage::Stage8EvaluationProgramPlan, + stage6: &stage6::Stage6ExecutionArtifacts<{field_type}>, + stage7_values: &std::collections::BTreeMap<&'static str, {field_type}>, + lagrange_factor: {field_type}, +) -> Result, JoltEvaluationProveError> {{ + let mut claims = Vec::with_capacity(program.opening_claims.len()); + for plan in program.opening_claims {{ + let value = match plan.source_stage {{ + "stage6" => stage6_eval_claim(stage6, plan.source_claim)? * lagrange_factor, + "stage7" => *stage7_values.get(plan.source_claim).ok_or( + JoltEvaluationProveError::MissingStageEval {{ + stage: plan.source_stage, + eval: plan.source_claim, + }}, + )?, + _ => {{ + return Err(JoltEvaluationProveError::MissingStageEval {{ + stage: plan.source_stage, + eval: plan.source_claim, + }}); + }} + }}; + claims.push(EvaluationClaim {{ + oracle: plan.oracle, + source_stage: plan.source_stage, + value, + }}); + }} + Ok(claims) +}} + +fn stage7_claim_values( + program: &'static stage8_stage::Stage8EvaluationProgramPlan, + artifacts: &stage7::Stage7ExecutionArtifacts<{field_type}>, +) -> Result<(Vec<{field_type}>, std::collections::BTreeMap<&'static str, {field_type}>), JoltEvaluationProveError> {{ + let stage7_plans = program + .opening_claims + .iter() + .filter(|plan| plan.source_stage == "stage7") + .collect::>(); + for output in &artifacts.sumchecks {{ + let mut values = std::collections::BTreeMap::new(); + for plan in &stage7_plans {{ + if let Some(eval) = output.evals.iter().find(|eval| eval.name == plan.source_claim) {{ + let _ = values.insert(plan.source_claim, eval.value); + }} + }} + if values.len() == stage7_plans.len() {{ + return Ok((output.point.clone(), values)); + }} + }} + Err(JoltEvaluationProveError::MissingStage7RaEval) +}} + +fn reverse_point(point: &[{field_type}]) -> Vec<{field_type}> {{ + point.iter().rev().copied().collect() +}} + +fn stage7_evaluation_opening_point( + program: &'static stage8_stage::Stage8EvaluationProgramPlan, + address_point: &[{field_type}], + stage7_openings: &[stage7::Stage7OpeningInputValue<{field_type}>], +) -> Result<(Vec<{field_type}>, usize), JoltEvaluationProveError> {{ + let cycle_source_symbol = program.evaluation_point_source.source_claim; + let cycle_source = stage7_openings + .iter() + .find(|input| input.symbol == cycle_source_symbol) + .ok_or(JoltEvaluationProveError::MissingStage7EvaluationPoint)?; + if cycle_source.point.len() < address_point.len() {{ + return Err(JoltEvaluationProveError::InvalidPointLength {{ + artifact: cycle_source_symbol, + expected: address_point.len(), + actual: cycle_source.point.len(), + }}); + }} + let cycle_len = cycle_source.point.len() - address_point.len(); + let mut point = Vec::with_capacity(cycle_source.point.len()); + point.extend_from_slice(address_point); + point.extend_from_slice(&cycle_source.point[address_point.len()..]); + Ok((point, cycle_len)) +}} + +fn append_rlc_claims(transcript: &mut T, claims: &[EvaluationClaim]) +where + T: Transcript, +{{ + transcript.append(&LabelWithCount(b"rlc_claims", claims.len() as u64)); + for claim in claims {{ + claim.value.append_to_transcript(transcript); + }} +}} + +fn gamma_powers(transcript: &mut T, count: usize) -> Vec<{field_type}> +where + T: Transcript, +{{ + let gamma = transcript.challenge(); + let mut powers = Vec::with_capacity(count); + let mut power = {field_type}::from_u64(1); + for _ in 0..count {{ + powers.push(power); + power *= gamma; + }} + powers +}} + +fn materialize_joint_polynomial( + commitment_inputs: &mut I, + claims: &[EvaluationClaim], + gamma_powers: &[{field_type}], + log_t: usize, + main_num_vars: usize, +) -> Result, JoltEvaluationProveError> +where + I: commitment_stage::CommitmentInputProvider, +{{ + let trace_len = target_len(log_t)?; + let main_len = target_len(main_num_vars)?; + let mut joint = vec![{field_type}::from_u64(0); main_len]; + for (claim, gamma) in claims.iter().zip(gamma_powers) {{ + if claim.source_stage == "stage6" {{ + add_oracle_scaled(commitment_inputs, &mut joint, claim.oracle, log_t, trace_len, *gamma)?; + }} else {{ + add_oracle_scaled( + commitment_inputs, + &mut joint, + claim.oracle, + main_num_vars, + main_len, + *gamma, + )?; + }} + }} + Ok(joint) +}} + +fn add_oracle_scaled( + commitment_inputs: &mut I, + joint: &mut [{field_type}], + oracle: &'static str, + num_vars: usize, + limit: usize, + scalar: {field_type}, +) -> Result<(), JoltEvaluationProveError> +where + I: commitment_stage::CommitmentInputProvider, +{{ + if commitment_inputs.add_scaled_to_joint(oracle, joint, num_vars, limit, scalar) {{ + return Ok(()); + }} + let target_len = target_len(num_vars)?; + let data = commitment_inputs + .materialize_with_num_vars(oracle, num_vars) + .ok_or(JoltEvaluationProveError::MissingOracle {{ oracle }})?; + if data.len() > target_len {{ + return Err(JoltEvaluationProveError::InvalidPointLength {{ + artifact: oracle, + expected: target_len, + actual: data.len(), + }}); + }} + let zero = {field_type}::from_u64(0); + let one = {field_type}::from_u64(1); + let len = limit.min(joint.len()).min(data.len()); + if len >= 1 << 15 {{ + joint[..len] + .par_iter_mut() + .zip(data[..len].par_iter()) + .for_each(|(dst, value)| {{ + if *value == zero {{ + return; + }} + if *value == one {{ + *dst += scalar; + }} else {{ + *dst += *value * scalar; + }} + }}); + }} else {{ + for (dst, value) in joint.iter_mut().take(len).zip(data.iter()) {{ + if *value == zero {{ + continue; + }} + if *value == one {{ + *dst += scalar; + }} else {{ + *dst += *value * scalar; + }} + }} + }} + Ok(()) +}} + +fn joint_opening_hint( + commitments: &commitment_stage::CommitmentArtifacts, + claims: &[EvaluationClaim], + gamma_powers: &[{field_type}], +) -> Result {{ + let mut coefficients = std::collections::BTreeMap::<&'static str, {field_type}>::new(); + for (claim, gamma) in claims.iter().zip(gamma_powers) {{ + let coefficient = coefficients.entry(claim.oracle).or_insert({field_type}::from_u64(0)); + *coefficient += *gamma; + }} + + let mut hints = Vec::with_capacity(coefficients.len()); + let mut scalars = Vec::with_capacity(coefficients.len()); + for (oracle, coefficient) in coefficients {{ + hints.push(opening_hint_for_oracle(commitments, oracle)?); + scalars.push(coefficient); + }} + + Ok(::combine_hints( + hints, &scalars, + )) +}} + +fn opening_hint_for_oracle( + commitments: &commitment_stage::CommitmentArtifacts, + oracle: &'static str, +) -> Result {{ + commitments + .hints + .iter() + .find(|hint| hint.oracle == oracle) + .map(|hint| hint.hint.clone()) + .ok_or(JoltEvaluationProveError::MissingOpeningHint {{ oracle }}) +}} + +fn target_len(num_vars: usize) -> Result {{ + if num_vars >= usize::BITS as usize {{ + return Err(JoltEvaluationProveError::TargetSizeOverflow {{ num_vars }}); + }} + Ok(1usize << num_vars) +}} + +"# + ) +} + +const PROVER_FORBIDDEN_IMPORTS: &[&str] = &[ + "use jolt_core", + "jolt_core::", + "use jolt_verifier::stages", + "jolt_verifier::stages::", + "use jolt_equivalence", + "jolt_equivalence::", + "use jolt_profiling", + "jolt_profiling::", +]; + +const VERIFIER_FORBIDDEN_IMPORTS: &[&str] = &[ + "use jolt_kernels", + "jolt_kernels::", + "use jolt_prover", + "jolt_prover::", + "use jolt_core", + "jolt_core::", + "use jolt_equivalence", + "jolt_equivalence::", + "use jolt_profiling", + "jolt_profiling::", + "tracer::", +]; diff --git a/crates/bolt/src/protocols/jolt/emit/mod.rs b/crates/bolt/src/protocols/jolt/emit/mod.rs new file mode 100644 index 0000000000..0ad9e7d3d7 --- /dev/null +++ b/crates/bolt/src/protocols/jolt/emit/mod.rs @@ -0,0 +1 @@ +pub mod rust; diff --git a/crates/bolt/src/protocols/jolt/emit/rust/commitment.rs b/crates/bolt/src/protocols/jolt/emit/rust/commitment.rs new file mode 100644 index 0000000000..66186d2419 --- /dev/null +++ b/crates/bolt/src/protocols/jolt/emit/rust/commitment.rs @@ -0,0 +1,1744 @@ +use melior::ir::block::BlockLike; +use melior::ir::operation::{OperationLike, OperationResult}; +use melior::ir::{Attribute, OperationRef}; + +use crate::ir::{string_attribute_value, symbol_attribute_value, BoltModule, Cpu, Role}; +use crate::schema::verify_cpu_schema; + +use crate::emit::rust::{push_format, EmitError, RustSourceFile}; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct CommitmentCpuProgram { + pub role: Role, + pub params: CommitmentParams, + pub oracle_plans: Vec, + pub batch_plans: Vec, + pub optional_plans: Vec, + pub transcript_steps: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct CommitmentParams { + pub field: String, + pub pcs: String, + pub transcript: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct OraclePlan { + pub oracle: String, + pub source: String, + pub domain: String, + pub num_vars: usize, + pub generation: OracleGeneration, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum OracleGeneration { + Reference, + DenseTrace { + padding: String, + }, + OneHotChunk { + trace_num_vars: usize, + chunk: usize, + num_chunks: usize, + chunk_bits: usize, + padding: String, + layout: String, + }, + OptionalAdvice { + skip_policy: OptionalSkipPolicy, + }, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct CommitmentBatchPlan { + pub artifact: String, + pub pcs: String, + pub oracle_family: String, + pub label: String, + pub oracles: Vec, + pub count: usize, + pub domain: String, + pub num_vars: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct OptionalCommitmentPlan { + pub artifact: String, + pub pcs: String, + pub oracle: String, + pub label: String, + pub domain: String, + pub num_vars: usize, + pub skip_policy: OptionalSkipPolicy, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum OptionalSkipPolicy { + MissingOrZero, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct TranscriptStep { + pub label: String, + pub source: String, + pub optional: bool, +} + +pub fn emit_commitment_rust(module: &BoltModule<'_, Cpu>) -> Result { + let program = commitment_cpu_program(module)?; + + Ok(RustSourceFile { + filename: program.filename().to_owned(), + source: program.emit_source()?, + }) +} + +pub fn commitment_cpu_program( + module: &BoltModule<'_, Cpu>, +) -> Result { + verify_cpu_schema(module)?; + let program = CommitmentCpuProgram::from_module(module)?; + program.verify_supported_target()?; + Ok(program) +} + +impl CommitmentCpuProgram { + fn from_module(module: &BoltModule<'_, Cpu>) -> Result { + let mut params = None; + let mut oracle_plans = Vec::new(); + let mut batch_plans = Vec::new(); + let mut optional_plans = Vec::new(); + let mut transcript_steps = Vec::new(); + + let mut operation = module.as_mlir_module().body().first_operation(); + while let Some(op) = operation { + operation = op.next_in_block(); + match operation_name(op).as_str() { + "cpu.params" => { + params = Some(CommitmentParams { + field: symbol_attr(op, "field")?, + pcs: symbol_attr(op, "pcs")?, + transcript: symbol_attr(op, "transcript")?, + }); + } + "cpu.oracle_dense_trace" => { + oracle_plans.push(OraclePlan { + oracle: symbol_attr(op, "oracle")?, + source: symbol_attr(op, "source")?, + domain: symbol_attr(op, "domain")?, + num_vars: int_attr(op, "num_vars")?, + generation: OracleGeneration::DenseTrace { + padding: string_attr(op, "padding")?, + }, + }); + } + "cpu.oracle_one_hot_chunk" => { + oracle_plans.push(OraclePlan { + oracle: symbol_attr(op, "oracle")?, + source: symbol_attr(op, "source")?, + domain: symbol_attr(op, "domain")?, + num_vars: int_attr(op, "num_vars")?, + generation: OracleGeneration::OneHotChunk { + trace_num_vars: int_attr(op, "trace_num_vars")?, + chunk: int_attr(op, "chunk")?, + num_chunks: int_attr(op, "num_chunks")?, + chunk_bits: int_attr(op, "chunk_bits")?, + padding: string_attr(op, "padding")?, + layout: string_attr(op, "layout")?, + }, + }); + } + "cpu.oracle_optional_advice" => { + oracle_plans.push(OraclePlan { + oracle: symbol_attr(op, "oracle")?, + source: symbol_attr(op, "source")?, + domain: symbol_attr(op, "domain")?, + num_vars: int_attr(op, "num_vars")?, + generation: OracleGeneration::OptionalAdvice { + skip_policy: skip_policy_attr(op, "skip_policy")?, + }, + }); + } + "cpu.oracle_ref" => { + oracle_plans.push(OraclePlan { + oracle: symbol_attr(op, "oracle")?, + source: String::new(), + domain: symbol_attr(op, "domain")?, + num_vars: int_attr(op, "num_vars")?, + generation: OracleGeneration::Reference, + }); + } + "cpu.pcs_commit_batch" | "cpu.pcs_receive_batch" => { + batch_plans.push(CommitmentBatchPlan { + artifact: symbol_attr(op, "artifact")?, + pcs: symbol_attr(op, "pcs")?, + oracle_family: symbol_attr(op, "oracle_family")?, + label: string_attr(op, "label")?, + oracles: symbol_array_attr(op, "ordered_oracles")?, + count: int_attr(op, "count")?, + domain: symbol_attr(op, "domain")?, + num_vars: int_attr(op, "num_vars")?, + }); + } + "cpu.pcs_commit_optional" | "cpu.pcs_receive_optional" => { + optional_plans.push(OptionalCommitmentPlan { + artifact: symbol_attr(op, "artifact")?, + pcs: symbol_attr(op, "pcs")?, + oracle: symbol_attr(op, "oracle")?, + label: string_attr(op, "label")?, + domain: symbol_attr(op, "domain")?, + num_vars: int_attr(op, "num_vars")?, + skip_policy: skip_policy_attr(op, "skip_policy")?, + }); + } + "cpu.transcript_absorb" => { + transcript_steps.push(TranscriptStep { + label: string_attr(op, "label")?, + source: transcript_artifact_source(op)?, + optional: bool_attr(op, "optional")?, + }); + } + _ => {} + } + } + + Ok(Self { + params: params.ok_or_else(|| EmitError::new("missing cpu.params"))?, + role: module + .role() + .ok_or_else(|| EmitError::new("missing cpu party role"))?, + oracle_plans, + batch_plans, + optional_plans, + transcript_steps, + }) + } + + fn verify_supported_target(&self) -> Result<(), EmitError> { + require_supported_symbol("field", &self.params.field, "bn254_fr")?; + require_supported_symbol("pcs", &self.params.pcs, "dory")?; + require_supported_symbol("transcript", &self.params.transcript, "blake2b_transcript")?; + for plan in &self.batch_plans { + require_supported_symbol("batch pcs", &plan.pcs, "dory")?; + } + for plan in &self.optional_plans { + require_supported_symbol("optional pcs", &plan.pcs, "dory")?; + } + Ok(()) + } + + fn emit_source(&self) -> Result { + let mut source = String::new(); + source.push_str("#![allow(dead_code)]\n\n"); + source.push_str(self.emit_imports()); + source.push_str("\n\n"); + source.push_str(&self.emit_types()?); + source.push('\n'); + source.push_str(&self.emit_constants()); + source.push('\n'); + source.push_str(self.emit_entrypoint()); + Ok(source) + } + + fn filename(&self) -> &'static str { + match self.role { + Role::Prover => "prove_commitment_phase.rs", + Role::Verifier => "verify_commitment_phase.rs", + } + } + + fn emit_imports(&self) -> &'static str { + match self.role { + Role::Prover => { + "use std::borrow::Cow;\n\ + \n\ + use jolt_dory::{DoryCommitment, DoryHint, DoryProverSetup, DoryScheme};\n\ + use jolt_field::{Field, Fr};\n\ + use jolt_openings::CommitmentScheme as _;\n\ + use jolt_poly::{EqPolynomial, MultilinearPoly};\n\ + use jolt_transcript::{AppendToTranscript, Blake2bTranscript, LabelWithCount, Transcript};\n\ + use jolt_witness::{dense_i128_column_to_field, one_hot_chunk_address_major, one_hot_chunk_indices, optional_field_oracle, CommitmentTraceSources};\n\ + use rayon::prelude::*;" + } + Role::Verifier => { + "use jolt_dory::DoryCommitment;\n\ + use jolt_field::Fr;\n\ + use jolt_transcript::{AppendToTranscript, Blake2bTranscript, LabelWithCount, Transcript};" + } + } + } + + fn emit_types(&self) -> Result { + match self.role { + Role::Prover => { + let mut types = Self::emit_prover_types().to_owned(); + types.push('\n'); + types.push_str(&self.emit_oracle_store_types()?); + Ok(types) + } + Role::Verifier => Ok(Self::emit_verifier_types().to_owned()), + } + } + + fn emit_prover_types() -> &'static str { + r"pub type DefaultCommitmentTranscript = Blake2bTranscript; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct CommitmentParams { + pub field: &'static str, + pub pcs: &'static str, + pub transcript: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct OraclePlan { + pub oracle: &'static str, + pub domain: &'static str, + pub num_vars: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct CommitmentBatchPlan { + pub artifact: &'static str, + pub pcs: &'static str, + pub oracle_family: &'static str, + pub label: &'static str, + pub oracles: &'static [&'static str], + pub count: usize, + pub domain: &'static str, + pub num_vars: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum OptionalSkipPolicy { + MissingOrZero, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct OptionalCommitmentPlan { + pub artifact: &'static str, + pub pcs: &'static str, + pub oracle: &'static str, + pub label: &'static str, + pub domain: &'static str, + pub num_vars: usize, + pub skip_policy: OptionalSkipPolicy, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct TranscriptStep { + pub label: &'static str, + pub source: &'static str, + pub optional: bool, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct CommitmentProverProgramPlan { + pub params: CommitmentParams, + pub oracle_plans: &'static [OraclePlan], + pub batch_plans: &'static [CommitmentBatchPlan], + pub optional_plans: &'static [OptionalCommitmentPlan], + pub transcript_steps: &'static [TranscriptStep], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct CommitmentRecord { + pub artifact: &'static str, + pub oracle: &'static str, + pub label: &'static str, + pub num_vars: usize, +} + +#[derive(Clone, Debug)] +pub struct OracleOpeningHint { + pub oracle: &'static str, + pub hint: DoryHint, +} + +#[derive(Clone, Debug)] +pub struct CommittedOracle { + pub commitment: Option, + pub record: CommitmentRecord, + pub hint: Option, +} + +#[derive(Clone, Debug, Default)] +pub struct CommitmentArtifacts { + pub commitments: Vec>, + pub records: Vec, + pub hints: Vec, +} + +pub trait CommitmentInputProvider { + fn materialize(&mut self, oracle: &'static str) -> Option>; + + fn materialize_with_num_vars( + &mut self, + oracle: &'static str, + _num_vars: usize, + ) -> Option> { + self.materialize(oracle) + } + + fn commit_batch( + &mut self, + _program: &CommitmentProverProgramPlan, + _plan: &CommitmentBatchPlan, + _prover_setup: &DoryProverSetup, + ) -> Option, CommitmentPhaseError>> { + None + } + + fn add_scaled_to_joint( + &mut self, + _oracle: &'static str, + _joint: &mut [Fr], + _num_vars: usize, + _limit: usize, + _scalar: Fr, + ) -> bool { + false + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum CommitmentPhaseError { + MissingOracle { oracle: &'static str }, + MissingTranscriptSource { source: &'static str }, + PlanCountMismatch { artifact: &'static str, expected: usize, actual: usize }, + OracleTooLarge { oracle: &'static str, len: usize, target_len: usize }, + TargetSizeOverflow { num_vars: usize }, +}" + } + + fn emit_oracle_store_types(&self) -> Result { + let input_type = r" +pub struct CommitmentOracleInputs<'a> { + pub rd_inc: &'a [i128], + pub ram_inc: &'a [i128], + pub instruction_keys: &'a [Option], + pub ram_addresses: &'a [Option], + pub bytecode_indices: &'a [Option], + pub untrusted_advice: Option<&'a [Fr]>, + pub trusted_advice: Option<&'a [Fr]>, +} + +impl<'a> CommitmentOracleInputs<'a> { + pub fn from_trace_sources( + sources: &'a CommitmentTraceSources, + untrusted_advice: Option<&'a [Fr]>, + trusted_advice: Option<&'a [Fr]>, + ) -> Self { + Self { + rd_inc: &sources.rd_inc, + ram_inc: &sources.ram_inc, + instruction_keys: &sources.instruction_keys, + ram_addresses: &sources.ram_addresses, + bytecode_indices: &sources.bytecode_indices, + untrusted_advice, + trusted_advice, + } + } +} +"; + let sparse_provider = r#" +struct AddressMajorOneHotPolynomial { + trace_len: usize, + chunk_domain: usize, + indices: Vec>, + num_vars: usize, +} + +impl AddressMajorOneHotPolynomial { + fn new( + trace_len: usize, + chunk_domain: usize, + indices: Vec>, + num_vars: usize, + ) -> Result { + let active_len = trace_len + .checked_mul(chunk_domain) + .ok_or(CommitmentPhaseError::TargetSizeOverflow { num_vars })?; + let target_len = target_len(num_vars)?; + if active_len > target_len { + return Err(CommitmentPhaseError::OracleTooLarge { + oracle: "one_hot", + len: active_len, + target_len, + }); + } + Ok(Self { + trace_len, + chunk_domain, + indices, + num_vars, + }) + } + + fn nonzero_flat_indices(&self) -> impl Iterator + '_ { + self.indices + .iter() + .enumerate() + .filter_map(|(cycle, &index)| { + index.map(|index| { + let index = index as usize; + assert!( + index < self.chunk_domain, + "one-hot index {index} exceeds domain {}", + self.chunk_domain + ); + index * self.trace_len + cycle + }) + }) + } +} + +impl MultilinearPoly for AddressMajorOneHotPolynomial { + fn num_vars(&self) -> usize { + self.num_vars + } + + fn evaluate(&self, point: &[Fr]) -> Fr { + assert_eq!(point.len(), self.num_vars); + let eq_evals = EqPolynomial::new(point.to_vec()).evaluations(); + self.nonzero_flat_indices() + .fold(Fr::from_u64(0), |acc, flat| acc + eq_evals[flat]) + } + + fn for_each_row(&self, sigma: usize, f: &mut dyn FnMut(usize, &[Fr])) { + let num_cols = 1usize << sigma; + let num_rows = 1usize << (self.num_vars - sigma); + let mut entries = Vec::with_capacity(self.indices.len()); + for flat in self.nonzero_flat_indices() { + entries.push((flat / num_cols, flat % num_cols)); + } + entries.sort_unstable_by_key(|(row, _)| *row); + + let mut cursor = 0; + let mut row = vec![Fr::from_u64(0); num_cols]; + for row_index in 0..num_rows { + row.fill(Fr::from_u64(0)); + while cursor < entries.len() && entries[cursor].0 == row_index { + row[entries[cursor].1] = Fr::from_u64(1); + cursor += 1; + } + f(row_index, &row); + } + } + + fn fold_rows(&self, left: &[Fr], sigma: usize) -> Vec { + let num_cols = 1usize << sigma; + let num_rows = 1usize << (self.num_vars - sigma); + assert_eq!(left.len(), num_rows); + let mut result = vec![Fr::from_u64(0); num_cols]; + for flat in self.nonzero_flat_indices() { + result[flat % num_cols] += left[flat / num_cols]; + } + result + } + + fn is_sparse(&self) -> bool { + true + } + + fn for_each_nonzero(&self, f: &mut dyn FnMut(usize, Fr)) { + for flat in self.nonzero_flat_indices() { + f(flat, Fr::from_u64(1)); + } + } +} + +pub struct SparseCommitmentInputs<'a> { + pub inputs: CommitmentOracleInputs<'a>, + cache: std::collections::BTreeMap<(&'static str, usize), Option>>, + chunk_counts: OneHotChunkCounts, +} + +impl<'a> SparseCommitmentInputs<'a> { + pub fn new(inputs: CommitmentOracleInputs<'a>) -> Self { + Self { + inputs, + cache: std::collections::BTreeMap::new(), + chunk_counts: OneHotChunkCounts::default(), + } + } + + fn update_chunk_counts(&mut self, program: &CommitmentProverProgramPlan) { + let mut counts = OneHotChunkCounts::default(); + let mut instruction = 0; + let mut ram = 0; + let mut bytecode = 0; + for plan in program.oracle_plans { + if plan.oracle.strip_prefix("InstructionRa_").is_some() { + instruction += 1; + } else if plan.oracle.strip_prefix("RamRa_").is_some() { + ram += 1; + } else if plan.oracle.strip_prefix("BytecodeRa_").is_some() { + bytecode += 1; + } + } + if instruction > 0 { + counts.instruction = instruction; + } + if ram > 0 { + counts.ram = ram; + } + if bytecode > 0 { + counts.bytecode = bytecode; + } + self.chunk_counts = counts; + } + + fn one_hot_spec(&self, oracle: &'static str) -> Option { + let (prefix, num_chunks, values, padding) = + if let Some(suffix) = oracle.strip_prefix("InstructionRa_") { + ( + suffix, + self.chunk_counts.instruction, + OneHotSource::InstructionKeys, + Some(0), + ) + } else if let Some(suffix) = oracle.strip_prefix("RamRa_") { + ( + suffix, + self.chunk_counts.ram, + OneHotSource::RamAddresses, + None, + ) + } else if let Some(suffix) = oracle.strip_prefix("BytecodeRa_") { + ( + suffix, + self.chunk_counts.bytecode, + OneHotSource::BytecodeIndices, + Some(0), + ) + } else { + return None; + }; + let chunk = prefix.parse::().ok()?; + if chunk >= num_chunks { + return None; + } + Some(OneHotSpec { + source: values, + chunk, + num_chunks, + chunk_bits: 4, + padding, + }) + } + + fn source_values(&self, source: OneHotSource) -> &'a [Option] { + match source { + OneHotSource::InstructionKeys => self.inputs.instruction_keys, + OneHotSource::RamAddresses => self.inputs.ram_addresses, + OneHotSource::BytecodeIndices => self.inputs.bytecode_indices, + } + } + + fn one_hot_indices( + &self, + oracle: &'static str, + trace_len: usize, + ) -> Option>> { + let spec = self.one_hot_spec(oracle)?; + let values = self.source_values(spec.source); + Some(one_hot_chunk_indices( + values, + spec.chunk, + spec.num_chunks, + spec.chunk_bits, + trace_len, + spec.padding, + )) + } + + #[expect( + clippy::option_option, + reason = "distinguishes missing oracle from present optional oracle" + )] + fn materialize_oracle( + &self, + oracle: &'static str, + num_vars: usize, + ) -> Option>> { + let materialized = match oracle { + "RdInc" => Some(dense_i128_column_to_field( + self.inputs.rd_inc, + target_len(num_vars).ok()?, + )), + "RamInc" => Some(dense_i128_column_to_field( + self.inputs.ram_inc, + target_len(num_vars).ok()?, + )), + "UntrustedAdvice" => optional_field_oracle( + self.inputs.untrusted_advice, + target_len(num_vars).ok()?, + ), + "TrustedAdvice" => { + optional_field_oracle(self.inputs.trusted_advice, target_len(num_vars).ok()?) + } + _ => { + let spec = self.one_hot_spec(oracle)?; + let trace_len = target_len(num_vars.checked_sub(spec.chunk_bits)?).ok()?; + let values = self.source_values(spec.source); + Some(one_hot_chunk_address_major( + values, + spec.chunk, + spec.num_chunks, + spec.chunk_bits, + trace_len, + spec.padding, + )) + } + }; + Some(materialized) + } + + fn commit_oracle( + &self, + program: &CommitmentProverProgramPlan, + oracle: &'static str, + layout_num_vars: usize, + prover_setup: &DoryProverSetup, + ) -> Result<(DoryCommitment, DoryHint), CommitmentPhaseError> { + let oracle_num_vars = oracle_num_vars(program, oracle, layout_num_vars); + if let Some(spec) = self.one_hot_spec(oracle) { + let trace_len = target_len(oracle_num_vars - spec.chunk_bits)?; + let chunk_domain = target_len(spec.chunk_bits)?; + let indices = self + .one_hot_indices(oracle, trace_len) + .ok_or(CommitmentPhaseError::MissingOracle { oracle })?; + let poly = AddressMajorOneHotPolynomial::new( + trace_len, + chunk_domain, + indices, + layout_num_vars, + )?; + let _dory_commit_span = tracing::info_span!("bolt.commitment.dory_commit").entered(); + Ok(DoryScheme::commit(&poly, prover_setup)) + } else { + let data = self + .materialize_oracle(oracle, oracle_num_vars) + .flatten() + .ok_or(CommitmentPhaseError::MissingOracle { oracle })?; + let data = into_padded_oracle(oracle, oracle_num_vars, Cow::Owned(data))?; + commit_with_layout(&data, layout_num_vars, prover_setup) + } + } +} + +impl CommitmentInputProvider for SparseCommitmentInputs<'_> { + fn materialize(&mut self, oracle: &'static str) -> Option> { + let num_vars = match oracle { + "RdInc" | "RamInc" | "UntrustedAdvice" | "TrustedAdvice" => 16, + _ if self.one_hot_spec(oracle).is_some() => 20, + _ => return None, + }; + self.materialize_with_num_vars(oracle, num_vars) + } + + fn materialize_with_num_vars( + &mut self, + oracle: &'static str, + num_vars: usize, + ) -> Option> { + if !self.cache.contains_key(&(oracle, num_vars)) { + let materialized = self.materialize_oracle(oracle, num_vars).flatten(); + let _ = self.cache.insert((oracle, num_vars), materialized); + } + self.cache + .get(&(oracle, num_vars)) + .and_then(|values| values.as_ref()) + .map(|values| Cow::Borrowed(values.as_slice())) + } + + fn commit_batch( + &mut self, + program: &CommitmentProverProgramPlan, + plan: &CommitmentBatchPlan, + prover_setup: &DoryProverSetup, + ) -> Option, CommitmentPhaseError>> { + self.update_chunk_counts(program); + Some( + plan.oracles + .par_iter() + .map(|&oracle| { + let oracle_num_vars = oracle_num_vars(program, oracle, plan.num_vars); + let (commitment, hint) = + self.commit_oracle(program, oracle, plan.num_vars, prover_setup)?; + Ok(CommittedOracle { + commitment: Some(commitment), + record: CommitmentRecord { + artifact: plan.artifact, + oracle, + label: plan.label, + num_vars: oracle_num_vars, + }, + hint: Some(OracleOpeningHint { oracle, hint }), + }) + }) + .collect(), + ) + } + + fn add_scaled_to_joint( + &mut self, + oracle: &'static str, + joint: &mut [Fr], + num_vars: usize, + limit: usize, + scalar: Fr, + ) -> bool { + let dense = match oracle { + "RdInc" => Some(self.inputs.rd_inc), + "RamInc" => Some(self.inputs.ram_inc), + _ => None, + }; + if let Some(values) = dense { + let Ok(target_len) = target_len(num_vars) else { + return false; + }; + let len = limit.min(joint.len()).min(values.len()).min(target_len); + for (dst, &value) in joint.iter_mut().take(len).zip(values.iter()) { + if value != 0 { + *dst += Fr::from_i128(value) * scalar; + } + } + return true; + } + + let Some(spec) = self.one_hot_spec(oracle) else { + return false; + }; + let Some(trace_num_vars) = num_vars.checked_sub(spec.chunk_bits) else { + return false; + }; + let Ok(trace_len) = target_len(trace_num_vars) else { + return false; + }; + let Ok(chunk_domain) = target_len(spec.chunk_bits) else { + return false; + }; + let Some(active_len) = trace_len.checked_mul(chunk_domain) else { + return false; + }; + let max_flat = limit.min(joint.len()).min(active_len); + let Some(indices) = self.one_hot_indices(oracle, trace_len) else { + return false; + }; + for (cycle, index) in indices.into_iter().enumerate() { + let Some(index) = index else { + continue; + }; + let flat = index as usize * trace_len + cycle; + if flat < max_flat { + joint[flat] += scalar; + } + } + true + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +enum OneHotSource { + InstructionKeys, + RamAddresses, + BytecodeIndices, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +struct OneHotSpec { + source: OneHotSource, + chunk: usize, + num_chunks: usize, + chunk_bits: usize, + padding: Option, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +struct OneHotChunkCounts { + instruction: usize, + ram: usize, + bytecode: usize, +} + +impl Default for OneHotChunkCounts { + fn default() -> Self { + Self { + instruction: 32, + ram: 4, + bytecode: 3, + } + } +} +"#; + let mut fields = Vec::new(); + let mut provider_arms = Vec::new(); + let mut initializers = Vec::new(); + for plan in &self.oracle_plans { + match &plan.generation { + OracleGeneration::Reference => {} + OracleGeneration::OptionalAdvice { .. } => { + let field = rust_field_name(&plan.oracle); + fields.push(format!(" pub {field}: Option>,")); + provider_arms.push(format!( + " {} => self.{field}.as_deref().map(Cow::Borrowed),", + rust_str(&plan.oracle) + )); + initializers.push(format!( + " {field}: {},", + Self::oracle_initializer(plan)? + )); + } + _ => { + let field = rust_field_name(&plan.oracle); + fields.push(format!(" pub {field}: Vec,")); + provider_arms.push(format!( + " {} => Some(Cow::Borrowed(&self.{field})),", + rust_str(&plan.oracle) + )); + initializers.push(format!( + " {field}: {},", + Self::oracle_initializer(plan)? + )); + } + } + } + let fields = fields.join("\n"); + let provider_arms = provider_arms.join("\n"); + let initializers = initializers.join("\n"); + + Ok(format!( + "{input_type} +{sparse_provider} +#[derive(Clone, Debug, Default)] +pub struct CommitmentOracles {{ +{fields} +}} + +impl CommitmentInputProvider for CommitmentOracles {{ + fn materialize(&mut self, oracle: &'static str) -> Option> {{ + match oracle {{ +{provider_arms} + _ => None, + }} + }} +}} + +pub fn build_commitment_oracles( + inputs: &CommitmentOracleInputs<'_>, +) -> Result {{ + Ok(CommitmentOracles {{ +{initializers} + }}) +}} +" + )) + } + + fn oracle_initializer(plan: &OraclePlan) -> Result { + match &plan.generation { + OracleGeneration::Reference => Err(EmitError::new(format!( + "reference oracle @{} has no prover initializer", + plan.oracle + ))), + OracleGeneration::DenseTrace { .. } => Ok(format!( + "dense_i128_column_to_field(inputs.{}, target_len({})?)", + rust_input_field(&plan.source)?, + plan.num_vars + )), + OracleGeneration::OneHotChunk { + trace_num_vars, + chunk, + num_chunks, + chunk_bits, + padding, + .. + } => Ok(format!( + "one_hot_chunk_address_major(inputs.{}, {chunk}, {num_chunks}, {chunk_bits}, target_len({trace_num_vars})?, {})", + rust_input_field(&plan.source)?, + rust_padding_value(padding)? + )), + OracleGeneration::OptionalAdvice { .. } => Ok(format!( + "optional_field_oracle(inputs.{}, target_len({})?)", + rust_input_field(&plan.source)?, + plan.num_vars + )), + } + } + + fn emit_verifier_types() -> &'static str { + r"pub type DefaultCommitmentTranscript = Blake2bTranscript; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct CommitmentParams { + pub field: &'static str, + pub pcs: &'static str, + pub transcript: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct OraclePlan { + pub oracle: &'static str, + pub domain: &'static str, + pub num_vars: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct CommitmentBatchPlan { + pub artifact: &'static str, + pub pcs: &'static str, + pub oracle_family: &'static str, + pub label: &'static str, + pub oracles: &'static [&'static str], + pub count: usize, + pub domain: &'static str, + pub num_vars: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum OptionalSkipPolicy { + MissingOrZero, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct OptionalCommitmentPlan { + pub artifact: &'static str, + pub pcs: &'static str, + pub oracle: &'static str, + pub label: &'static str, + pub domain: &'static str, + pub num_vars: usize, + pub skip_policy: OptionalSkipPolicy, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct TranscriptStep { + pub label: &'static str, + pub source: &'static str, + pub optional: bool, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct CommitmentVerifierProgramPlan { + pub params: CommitmentParams, + pub oracle_plans: &'static [OraclePlan], + pub batch_plans: &'static [CommitmentBatchPlan], + pub optional_plans: &'static [OptionalCommitmentPlan], + pub transcript_steps: &'static [TranscriptStep], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct CommitmentRecord { + pub artifact: &'static str, + pub oracle: &'static str, + pub label: &'static str, + pub num_vars: usize, +} + +#[derive(Clone, Debug, Default)] +pub struct CommitmentArtifacts { + pub commitments: Vec>, + pub records: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum CommitmentPhaseError { + MissingProofCommitment { oracle: &'static str }, + MissingProofCommitmentSlot { artifact: &'static str, oracle: &'static str }, + MissingTranscriptSource { source: &'static str }, + PlanCountMismatch { artifact: &'static str, expected: usize, actual: usize }, + ProofCommitmentCountMismatch { expected: usize, actual: usize }, +}" + } + + fn emit_constants(&self) -> String { + let mut source = String::new(); + push_format( + &mut source, + format_args!( + "pub const COMMITMENT_PARAMS: CommitmentParams = CommitmentParams {{\n\ + \x20 field: {},\n\ + \x20 pcs: {},\n\ + \x20 transcript: {},\n\ + }};\n", + rust_str(&self.params.field), + rust_str(&self.params.pcs), + rust_str(&self.params.transcript) + ), + ); + + let oracle_plans = self + .oracle_plans + .iter() + .map(|plan| { + format!( + " OraclePlan {{ oracle: {}, domain: {}, num_vars: {} }},", + rust_str(&plan.oracle), + rust_str(&plan.domain), + plan.num_vars + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!("pub const ORACLE_PLANS: &[OraclePlan] = &[\n{oracle_plans}\n];\n"), + ); + + for (index, plan) in self.batch_plans.iter().enumerate() { + let oracles = plan + .oracles + .iter() + .map(|oracle| format!(" {},", rust_str(oracle))) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const COMMITMENT_BATCH_{index}_ORACLES: &[&str] = &[\n{oracles}\n];\n" + ), + ); + } + + let batch_plans = self + .batch_plans + .iter() + .enumerate() + .map(|(index, plan)| { + format!( + " CommitmentBatchPlan {{ artifact: {}, pcs: {}, oracle_family: {}, label: {}, oracles: COMMITMENT_BATCH_{index}_ORACLES, count: {}, domain: {}, num_vars: {} }},", + rust_str(&plan.artifact), + rust_str(&plan.pcs), + rust_str(&plan.oracle_family), + rust_str(&plan.label), + plan.count, + rust_str(&plan.domain), + plan.num_vars + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const COMMITMENT_BATCH_PLANS: &[CommitmentBatchPlan] = &[\n{batch_plans}\n];\n" + ), + ); + + let optional_plans = self + .optional_plans + .iter() + .map(|plan| { + format!( + " OptionalCommitmentPlan {{ artifact: {}, pcs: {}, oracle: {}, label: {}, domain: {}, num_vars: {}, skip_policy: {} }},", + rust_str(&plan.artifact), + rust_str(&plan.pcs), + rust_str(&plan.oracle), + rust_str(&plan.label), + rust_str(&plan.domain), + plan.num_vars, + plan.skip_policy.rust_variant() + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const OPTIONAL_COMMITMENT_PLANS: &[OptionalCommitmentPlan] = &[\n{optional_plans}\n];\n" + ), + ); + + let steps = self + .transcript_steps + .iter() + .map(|step| { + format!( + " TranscriptStep {{ label: {}, source: {}, optional: {} }},", + rust_str(&step.label), + rust_str(&step.source), + step.optional + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!("pub const TRANSCRIPT_PLAN: &[TranscriptStep] = &[\n{steps}\n];"), + ); + source.push('\n'); + let program_type = match self.role { + Role::Prover => "CommitmentProverProgramPlan", + Role::Verifier => "CommitmentVerifierProgramPlan", + }; + push_format( + &mut source, + format_args!( + "pub const COMMITMENT_PROGRAM: {program_type} = {program_type} {{\n\ + \x20 params: COMMITMENT_PARAMS,\n\ + \x20 oracle_plans: ORACLE_PLANS,\n\ + \x20 batch_plans: COMMITMENT_BATCH_PLANS,\n\ + \x20 optional_plans: OPTIONAL_COMMITMENT_PLANS,\n\ + \x20 transcript_steps: TRANSCRIPT_PLAN,\n\ + }};\n" + ), + ); + + source + } + + fn emit_entrypoint(&self) -> &'static str { + match self.role { + Role::Prover => Self::emit_prover_entrypoint(), + Role::Verifier => Self::emit_verifier_entrypoint(), + } + } + + fn emit_prover_entrypoint() -> &'static str { + r#"pub fn prove_commitment_phase( + inputs: &mut I, + prover_setup: &DoryProverSetup, + transcript: &mut T, +) -> Result +where + I: CommitmentInputProvider, + T: Transcript, +{ + prove_commitment_phase_with_program(&COMMITMENT_PROGRAM, inputs, prover_setup, transcript) +} + +pub fn prove_commitment_phase_with_program( + program: &'static CommitmentProverProgramPlan, + inputs: &mut I, + prover_setup: &DoryProverSetup, + transcript: &mut T, +) -> Result +where + I: CommitmentInputProvider, + T: Transcript, +{ + let mut artifacts = CommitmentArtifacts::default(); + for plan in program.batch_plans { + let _batch_span = tracing::info_span!("bolt.commitment.batch").entered(); + commit_batch(program, inputs, prover_setup, &mut artifacts, plan)?; + } + for plan in program.optional_plans { + let _optional_span = tracing::info_span!("bolt.commitment.optional").entered(); + commit_optional(program, inputs, prover_setup, &mut artifacts, plan)?; + } + absorb_transcript(program, &artifacts, transcript)?; + Ok(artifacts) +} + +fn commit_batch( + program: &CommitmentProverProgramPlan, + inputs: &mut I, + prover_setup: &DoryProverSetup, + artifacts: &mut CommitmentArtifacts, + plan: &CommitmentBatchPlan, +) -> Result<(), CommitmentPhaseError> +where + I: CommitmentInputProvider, +{ + if plan.count != plan.oracles.len() { + return Err(CommitmentPhaseError::PlanCountMismatch { + artifact: plan.artifact, + expected: plan.count, + actual: plan.oracles.len(), + }); + } + if let Some(committed) = inputs.commit_batch(program, plan, prover_setup) { + for committed in committed? { + artifacts.records.push(committed.record); + artifacts.commitments.push(committed.commitment); + if let Some(hint) = committed.hint { + artifacts.hints.push(hint); + } + } + return Ok(()); + } + for &oracle in plan.oracles { + let data = inputs + .materialize_with_num_vars(oracle, oracle_num_vars(program, oracle, plan.num_vars)) + .ok_or(CommitmentPhaseError::MissingOracle { oracle })?; + let oracle_num_vars = oracle_num_vars(program, oracle, plan.num_vars); + let data = into_padded_oracle(oracle, oracle_num_vars, data)?; + let (commitment, hint) = commit_with_layout(&data, plan.num_vars, prover_setup)?; + artifacts.records.push(CommitmentRecord { + artifact: plan.artifact, + oracle, + label: plan.label, + num_vars: oracle_num_vars, + }); + artifacts.commitments.push(Some(commitment)); + artifacts.hints.push(OracleOpeningHint { oracle, hint }); + } + Ok(()) +} + +fn commit_optional( + program: &CommitmentProverProgramPlan, + inputs: &mut I, + prover_setup: &DoryProverSetup, + artifacts: &mut CommitmentArtifacts, + plan: &OptionalCommitmentPlan, +) -> Result<(), CommitmentPhaseError> +where + I: CommitmentInputProvider, +{ + let Some(data) = inputs.materialize_with_num_vars(plan.oracle, plan.num_vars) else { + return push_skipped_optional(program, artifacts, plan); + }; + if should_skip_optional(plan.skip_policy, data.as_ref()) { + return push_skipped_optional(program, artifacts, plan); + } + let data = into_padded_oracle(plan.oracle, plan.num_vars, data)?; + let (commitment, hint) = commit_with_layout(&data, plan.num_vars, prover_setup)?; + artifacts.records.push(CommitmentRecord { + artifact: plan.artifact, + oracle: plan.oracle, + label: plan.label, + num_vars: oracle_num_vars(program, plan.oracle, plan.num_vars), + }); + artifacts.commitments.push(Some(commitment)); + artifacts.hints.push(OracleOpeningHint { + oracle: plan.oracle, + hint, + }); + Ok(()) +} + +fn push_skipped_optional( + program: &CommitmentProverProgramPlan, + artifacts: &mut CommitmentArtifacts, + plan: &OptionalCommitmentPlan, +) -> Result<(), CommitmentPhaseError> { + artifacts.records.push(CommitmentRecord { + artifact: plan.artifact, + oracle: plan.oracle, + label: plan.label, + num_vars: oracle_num_vars(program, plan.oracle, plan.num_vars), + }); + artifacts.commitments.push(None); + Ok(()) +} + +fn should_skip_optional(policy: OptionalSkipPolicy, data: &[Fr]) -> bool { + match policy { + OptionalSkipPolicy::MissingOrZero => data.iter().all(|value| *value == Fr::from_u64(0)), + } +} + +fn into_padded_oracle( + oracle: &'static str, + num_vars: usize, + data: Cow<'_, [Fr]>, +) -> Result, CommitmentPhaseError> { + let target_len = target_len(num_vars)?; + if data.len() > target_len { + return Err(CommitmentPhaseError::OracleTooLarge { + oracle, + len: data.len(), + target_len, + }); + } + let mut data = data.into_owned(); + data.resize(target_len, Fr::from_u64(0)); + Ok(data) +} + +fn oracle_num_vars( + program: &CommitmentProverProgramPlan, + oracle: &'static str, + fallback: usize, +) -> usize { + program + .oracle_plans + .iter() + .find(|plan| plan.oracle == oracle) + .map_or(fallback, |plan| plan.num_vars) +} + +fn commit_with_layout( + data: &[Fr], + layout_num_vars: usize, + prover_setup: &DoryProverSetup, +) -> Result<(DoryCommitment, DoryHint), CommitmentPhaseError> { + let row_len = target_len(layout_num_vars.div_ceil(2))?; + let _dory_commit_span = tracing::info_span!("bolt.commitment.dory_commit").entered(); + Ok(DoryScheme::commit_evaluations_with_row_len( + data, + row_len, + prover_setup, + )) +} + +fn target_len(num_vars: usize) -> Result { + if num_vars >= usize::BITS as usize { + return Err(CommitmentPhaseError::TargetSizeOverflow { num_vars }); + } + Ok(1usize << num_vars) +} + +fn absorb_transcript( + program: &CommitmentProverProgramPlan, + artifacts: &CommitmentArtifacts, + transcript: &mut T, +) -> Result<(), CommitmentPhaseError> +where + T: Transcript, +{ + for step in program.transcript_steps { + let mut appended = false; + for (record, commitment) in artifacts.records.iter().zip(&artifacts.commitments) { + if record.artifact != step.source { + continue; + } + if let Some(commitment) = commitment { + transcript.append(&LabelWithCount(step.label.as_bytes(), commitment.serialized_len())); + commitment.append_to_transcript(transcript); + appended = true; + } + } + if !step.optional && !appended { + return Err(CommitmentPhaseError::MissingTranscriptSource { + source: step.source, + }); + } + } + Ok(()) +} +"# + } + + fn emit_verifier_entrypoint() -> &'static str { + r"pub fn verify_commitment_phase( + proof_commitments: &[Option], + transcript: &mut T, +) -> Result +where + T: Transcript, +{ + verify_commitment_phase_with_program(&COMMITMENT_PROGRAM, proof_commitments, transcript) +} + +pub fn verify_commitment_phase_with_program( + program: &'static CommitmentVerifierProgramPlan, + proof_commitments: &[Option], + transcript: &mut T, +) -> Result +where + T: Transcript, +{ + let mut artifacts = CommitmentArtifacts::default(); + let mut cursor = 0usize; + for plan in program.batch_plans { + receive_batch(program, proof_commitments, &mut cursor, &mut artifacts, plan)?; + } + for plan in program.optional_plans { + receive_optional(program, proof_commitments, &mut cursor, &mut artifacts, plan)?; + } + if cursor != proof_commitments.len() { + return Err(CommitmentPhaseError::ProofCommitmentCountMismatch { + expected: cursor, + actual: proof_commitments.len(), + }); + } + absorb_transcript(program, &artifacts, transcript)?; + Ok(artifacts) +} + +fn receive_batch( + program: &'static CommitmentVerifierProgramPlan, + proof_commitments: &[Option], + cursor: &mut usize, + artifacts: &mut CommitmentArtifacts, + plan: &CommitmentBatchPlan, +) -> Result<(), CommitmentPhaseError> { + if plan.count != plan.oracles.len() { + return Err(CommitmentPhaseError::PlanCountMismatch { + artifact: plan.artifact, + expected: plan.count, + actual: plan.oracles.len(), + }); + } + for &oracle in plan.oracles { + let commitment = proof_commitments + .get(*cursor) + .ok_or(CommitmentPhaseError::MissingProofCommitmentSlot { + artifact: plan.artifact, + oracle, + })? + .as_ref() + .ok_or(CommitmentPhaseError::MissingProofCommitment { oracle })? + .clone(); + *cursor += 1; + let oracle_num_vars = oracle_num_vars(program, oracle, plan.num_vars); + artifacts.records.push(CommitmentRecord { + artifact: plan.artifact, + oracle, + label: plan.label, + num_vars: oracle_num_vars, + }); + artifacts.commitments.push(Some(commitment)); + } + Ok(()) +} + +fn receive_optional( + program: &'static CommitmentVerifierProgramPlan, + proof_commitments: &[Option], + cursor: &mut usize, + artifacts: &mut CommitmentArtifacts, + plan: &OptionalCommitmentPlan, +) -> Result<(), CommitmentPhaseError> { + let commitment = proof_commitments + .get(*cursor) + .ok_or(CommitmentPhaseError::MissingProofCommitmentSlot { + artifact: plan.artifact, + oracle: plan.oracle, + })? + .clone(); + *cursor += 1; + artifacts.records.push(CommitmentRecord { + artifact: plan.artifact, + oracle: plan.oracle, + label: plan.label, + num_vars: oracle_num_vars(program, plan.oracle, plan.num_vars), + }); + artifacts.commitments.push(commitment); + Ok(()) +} + +pub fn commitment_verifier_program() -> &'static CommitmentVerifierProgramPlan { + &COMMITMENT_PROGRAM +} + +fn oracle_num_vars( + program: &'static CommitmentVerifierProgramPlan, + oracle: &'static str, + fallback: usize, +) -> usize { + program + .oracle_plans + .iter() + .find(|plan| plan.oracle == oracle) + .map_or(fallback, |plan| plan.num_vars) +} + +fn absorb_transcript( + program: &'static CommitmentVerifierProgramPlan, + artifacts: &CommitmentArtifacts, + transcript: &mut T, +) -> Result<(), CommitmentPhaseError> +where + T: Transcript, +{ + for step in program.transcript_steps { + let mut appended = false; + for (record, commitment) in artifacts.records.iter().zip(&artifacts.commitments) { + if record.artifact != step.source { + continue; + } + if let Some(commitment) = commitment { + transcript.append(&LabelWithCount(step.label.as_bytes(), commitment.serialized_len())); + commitment.append_to_transcript(transcript); + appended = true; + } + } + if !step.optional && !appended { + return Err(CommitmentPhaseError::MissingTranscriptSource { + source: step.source, + }); + } + } + Ok(()) +} +" + } +} + +impl OptionalSkipPolicy { + fn parse(value: &str) -> Result { + match value { + "missing_or_zero" => Ok(Self::MissingOrZero), + _ => Err(EmitError::new(format!( + "unsupported optional commitment skip policy `{value}`" + ))), + } + } + + fn rust_variant(&self) -> &'static str { + match self { + Self::MissingOrZero => "OptionalSkipPolicy::MissingOrZero", + } + } +} + +fn string_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .ok() + .and_then(string_attribute_value) + .ok_or_else(|| attr_error(operation, attr, "string")) +} + +fn skip_policy_attr( + operation: OperationRef<'_, '_>, + attr: &str, +) -> Result { + OptionalSkipPolicy::parse(&string_attr(operation, attr)?) +} + +fn symbol_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .ok() + .and_then(symbol_attribute_value) + .ok_or_else(|| attr_error(operation, attr, "symbol")) +} + +fn symbol_array_attr( + operation: OperationRef<'_, '_>, + attr: &str, +) -> Result, EmitError> { + let attribute = operation + .attribute(attr) + .map(|attribute| attribute.to_string()) + .ok() + .ok_or_else(|| attr_error(operation, attr, "symbol array"))?; + parse_symbol_array(&attribute).ok_or_else(|| attr_error(operation, attr, "symbol array")) +} + +fn parse_symbol_array(attribute: &str) -> Option> { + let inner = attribute.strip_prefix('[')?.strip_suffix(']')?.trim(); + if inner.is_empty() { + return Some(Vec::new()); + } + inner + .split(',') + .map(|item| item.trim().strip_prefix('@').map(ToOwned::to_owned)) + .collect() +} + +fn int_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .map(parse_integer_attr) + .ok() + .flatten() + .ok_or_else(|| attr_error(operation, attr, "integer")) +} + +fn parse_integer_attr(attribute: Attribute<'_>) -> Option { + attribute + .to_string() + .split_whitespace() + .next() + .and_then(|value| value.parse().ok()) +} + +fn bool_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .map(|attribute| match attribute.to_string().as_str() { + "true" => Some(true), + "false" => Some(false), + _ => None, + }) + .ok() + .flatten() + .ok_or_else(|| attr_error(operation, attr, "bool")) +} + +fn transcript_artifact_source(operation: OperationRef<'_, '_>) -> Result { + let artifact = operation + .operand(1) + .map_err(|_| attr_error(operation, "artifact operand", "value"))?; + let owner = OperationResult::try_from(artifact) + .map_err(|_| EmitError::new("cpu.transcript_absorb artifact operand must be op result"))? + .owner(); + symbol_attr(owner, "artifact") +} + +fn attr_error(operation: OperationRef<'_, '_>, attr: &str, expected: &str) -> EmitError { + EmitError::new(format!( + "{} attr `{attr}` is not a {expected}", + operation_name(operation) + )) +} + +fn operation_name(operation: OperationRef<'_, '_>) -> String { + operation + .name() + .as_string_ref() + .as_str() + .unwrap_or("") + .to_owned() +} + +fn rust_str(value: &str) -> String { + format!("{value:?}") +} + +fn rust_field_name(value: &str) -> String { + let mut output = String::new(); + let mut previous_was_separator = false; + for (index, character) in value.chars().enumerate() { + if character == '_' { + output.push('_'); + previous_was_separator = true; + continue; + } + if character.is_ascii_uppercase() { + if index != 0 && !previous_was_separator { + output.push('_'); + } + output.push(character.to_ascii_lowercase()); + } else { + output.push(character); + } + previous_was_separator = false; + } + output +} + +fn rust_input_field(source: &str) -> Result<&'static str, EmitError> { + match source { + "trace.rd_inc" => Ok("rd_inc"), + "trace.ram_inc" => Ok("ram_inc"), + "trace.instruction_keys" => Ok("instruction_keys"), + "trace.ram_addresses" => Ok("ram_addresses"), + "trace.bytecode_indices" => Ok("bytecode_indices"), + "advice.untrusted" => Ok("untrusted_advice"), + "advice.trusted" => Ok("trusted_advice"), + _ => Err(EmitError::new(format!( + "unsupported oracle source `{source}`" + ))), + } +} + +fn rust_padding_value(padding: &str) -> Result<&'static str, EmitError> { + match padding { + "zero" => Ok("Some(0)"), + "none" => Ok("None"), + _ => Err(EmitError::new(format!( + "unsupported oracle padding `{padding}`" + ))), + } +} + +fn require_supported_symbol(kind: &str, actual: &str, expected: &str) -> Result<(), EmitError> { + if actual == expected { + Ok(()) + } else { + Err(EmitError::new(format!( + "unsupported {kind} @{actual}; Rust commitment emitter currently supports @{expected}" + ))) + } +} diff --git a/crates/bolt/src/protocols/jolt/emit/rust/mod.rs b/crates/bolt/src/protocols/jolt/emit/rust/mod.rs new file mode 100644 index 0000000000..50f36ba9f7 --- /dev/null +++ b/crates/bolt/src/protocols/jolt/emit/rust/mod.rs @@ -0,0 +1,27 @@ +mod commitment; +mod stage1; +mod stage2; +mod stage3; +mod stage4; +mod stage5; +mod stage6; +mod stage7; +mod stage8; + +pub use commitment::{ + commitment_cpu_program, emit_commitment_rust, CommitmentBatchPlan, CommitmentCpuProgram, + CommitmentParams, OptionalCommitmentPlan, OptionalSkipPolicy, OracleGeneration, OraclePlan, + TranscriptStep, +}; +pub use stage1::{ + emit_stage1_rust, stage1_cpu_program, Stage1CpuProgram, Stage1KernelPlan, + Stage1OpeningBatchPlan, Stage1OpeningClaimPlan, Stage1Params, Stage1SumcheckBatchPlan, + Stage1SumcheckClaimPlan, Stage1SumcheckDriverPlan, Stage1SumcheckEvalPlan, +}; +pub use stage2::{emit_stage2_rust, stage2_cpu_program, Stage2CpuProgram}; +pub use stage3::{emit_stage3_rust, stage3_cpu_program, Stage3CpuProgram}; +pub use stage4::{emit_stage4_rust, stage4_cpu_program, Stage4CpuProgram}; +pub use stage5::{emit_stage5_rust, stage5_cpu_program, Stage5CpuProgram}; +pub use stage6::{emit_stage6_rust, stage6_cpu_program, Stage6CpuProgram}; +pub use stage7::{emit_stage7_rust, stage7_cpu_program, Stage7CpuProgram}; +pub use stage8::{emit_stage8_rust, stage8_cpu_program, Stage8CpuProgram}; diff --git a/crates/bolt/src/protocols/jolt/emit/rust/stage1.rs b/crates/bolt/src/protocols/jolt/emit/rust/stage1.rs new file mode 100644 index 0000000000..0755beb79d --- /dev/null +++ b/crates/bolt/src/protocols/jolt/emit/rust/stage1.rs @@ -0,0 +1,1653 @@ +use std::collections::{BTreeMap, BTreeSet}; + +use melior::ir::block::BlockLike; +use melior::ir::operation::{OperationLike, OperationResult}; +use melior::ir::{Attribute, OperationRef}; + +use crate::emit::rust::{push_format, EmitError, RustSourceFile}; +use crate::ir::{string_attribute_value, symbol_attribute_value, BoltModule, Cpu, Role}; +use crate::schema::verify_cpu_schema; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage1CpuProgram { + pub role: Role, + pub params: Stage1Params, + pub transcript_squeezes: Vec, + pub kernels: Vec, + pub claims: Vec, + pub batches: Vec, + pub drivers: Vec, + pub instance_results: Vec, + pub evals: Vec, + pub opening_claims: Vec, + pub opening_batches: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage1Params { + pub field: String, + pub pcs: String, + pub transcript: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage1KernelPlan { + pub symbol: String, + pub relation: String, + pub kind: String, + pub backend: String, + pub abi: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage1TranscriptSqueezePlan { + pub symbol: String, + pub label: String, + pub kind: String, + pub count: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage1SumcheckClaimPlan { + pub symbol: String, + pub stage: String, + pub domain: String, + pub num_rounds: usize, + pub degree: usize, + pub claim: String, + pub kernel: Option, + pub relation: Option, + pub claim_value: String, + pub input_openings: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage1SumcheckBatchPlan { + pub symbol: String, + pub stage: String, + pub proof_slot: String, + pub policy: String, + pub count: usize, + pub ordered_claims: Vec, + pub claim_operands: Vec, + pub claim_label: String, + pub round_label: String, + pub round_schedule: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage1SumcheckDriverPlan { + pub symbol: String, + pub stage: String, + pub proof_slot: String, + pub kernel: Option, + pub relation: Option, + pub batch: String, + pub policy: String, + pub round_schedule: Vec, + pub claim_label: String, + pub round_label: String, + pub num_rounds: usize, + pub degree: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage1SumcheckInstanceResultPlan { + pub symbol: String, + pub source: String, + pub claim: String, + pub relation: String, + pub index: usize, + pub point_arity: usize, + pub num_rounds: usize, + pub round_offset: usize, + pub point_order: String, + pub degree: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage1SumcheckEvalPlan { + pub symbol: String, + pub source: String, + pub name: String, + pub index: usize, + pub oracle: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage1OpeningClaimPlan { + pub symbol: String, + pub oracle: String, + pub domain: String, + pub point_arity: usize, + pub claim_kind: String, + pub point_source: String, + pub eval_source: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage1OpeningBatchPlan { + pub symbol: String, + pub stage: String, + pub proof_slot: String, + pub policy: String, + pub count: usize, + pub ordered_claims: Vec, + pub claim_operands: Vec, +} + +pub fn stage1_cpu_program(module: &BoltModule<'_, Cpu>) -> Result { + verify_cpu_schema(module)?; + let program = Stage1CpuProgram::from_module(module)?; + program.verify_supported_target()?; + Ok(program) +} + +pub fn emit_stage1_rust(module: &BoltModule<'_, Cpu>) -> Result { + let program = stage1_cpu_program(module)?; + + Ok(RustSourceFile { + filename: program.filename().to_owned(), + source: program.emit_source()?, + }) +} + +impl Stage1CpuProgram { + fn from_module(module: &BoltModule<'_, Cpu>) -> Result { + let mut params = None; + let mut transcript_squeezes = Vec::new(); + let mut kernels = Vec::new(); + let mut claims = Vec::new(); + let mut batches = Vec::new(); + let mut drivers = Vec::new(); + let mut instance_results = Vec::new(); + let mut evals = Vec::new(); + let mut opening_claims = Vec::new(); + let mut opening_batches = Vec::new(); + + let mut operation = module.as_mlir_module().body().first_operation(); + while let Some(op) = operation { + operation = op.next_in_block(); + match operation_name(op).as_str() { + "cpu.params" => { + params = Some(Stage1Params { + field: symbol_attr(op, "field")?, + pcs: symbol_attr(op, "pcs")?, + transcript: symbol_attr(op, "transcript")?, + }); + } + "cpu.kernel" => { + kernels.push(Stage1KernelPlan { + symbol: string_attr(op, "sym_name")?, + relation: symbol_attr(op, "relation")?, + kind: string_attr(op, "kind")?, + backend: string_attr(op, "backend")?, + abi: string_attr(op, "abi")?, + }); + } + "cpu.transcript_squeeze" => { + transcript_squeezes.push(Stage1TranscriptSqueezePlan { + symbol: string_attr(op, "sym_name")?, + label: string_attr(op, "label")?, + kind: string_attr(op, "kind")?, + count: int_attr(op, "count")?, + }); + } + "cpu.sumcheck_claim" => { + claims.push(Stage1SumcheckClaimPlan { + symbol: string_attr(op, "sym_name")?, + stage: symbol_attr(op, "stage")?, + domain: symbol_attr(op, "domain")?, + num_rounds: int_attr(op, "num_rounds")?, + degree: int_attr(op, "degree")?, + claim: symbol_attr(op, "claim")?, + kernel: Some(symbol_attr(op, "kernel")?), + relation: None, + claim_value: operand_symbol(op, 0)?, + input_openings: operand_symbols(op, 1)?, + }); + } + "cpu.sumcheck_verify_claim" => { + claims.push(Stage1SumcheckClaimPlan { + symbol: string_attr(op, "sym_name")?, + stage: symbol_attr(op, "stage")?, + domain: symbol_attr(op, "domain")?, + num_rounds: int_attr(op, "num_rounds")?, + degree: int_attr(op, "degree")?, + claim: symbol_attr(op, "claim")?, + kernel: None, + relation: Some(symbol_attr(op, "relation")?), + claim_value: operand_symbol(op, 0)?, + input_openings: operand_symbols(op, 1)?, + }); + } + "cpu.sumcheck_batch" => { + batches.push(Stage1SumcheckBatchPlan { + symbol: string_attr(op, "sym_name")?, + stage: symbol_attr(op, "stage")?, + proof_slot: symbol_attr(op, "proof_slot")?, + policy: string_attr(op, "policy")?, + count: int_attr(op, "count")?, + ordered_claims: symbol_array_attr(op, "ordered_claims")?, + claim_operands: operand_symbols(op, 0)?, + claim_label: string_attr(op, "claim_label")?, + round_label: string_attr(op, "round_label")?, + round_schedule: int_array_attr(op, "round_schedule")?, + }); + } + "cpu.sumcheck_driver" => { + drivers.push(Stage1SumcheckDriverPlan { + symbol: string_attr(op, "sym_name")?, + stage: symbol_attr(op, "stage")?, + proof_slot: symbol_attr(op, "proof_slot")?, + kernel: Some(symbol_attr(op, "kernel")?), + relation: None, + batch: operand_symbol(op, 1)?, + policy: string_attr(op, "policy")?, + round_schedule: int_array_attr(op, "round_schedule")?, + claim_label: string_attr(op, "claim_label")?, + round_label: string_attr(op, "round_label")?, + num_rounds: int_attr(op, "num_rounds")?, + degree: int_attr(op, "degree")?, + }); + } + "cpu.sumcheck_verify" => { + drivers.push(Stage1SumcheckDriverPlan { + symbol: string_attr(op, "sym_name")?, + stage: symbol_attr(op, "stage")?, + proof_slot: symbol_attr(op, "proof_slot")?, + kernel: None, + relation: Some(symbol_attr(op, "relation")?), + batch: operand_symbol(op, 1)?, + policy: string_attr(op, "policy")?, + round_schedule: int_array_attr(op, "round_schedule")?, + claim_label: string_attr(op, "claim_label")?, + round_label: string_attr(op, "round_label")?, + num_rounds: int_attr(op, "num_rounds")?, + degree: int_attr(op, "degree")?, + }); + } + "cpu.sumcheck_eval" => { + evals.push(Stage1SumcheckEvalPlan { + symbol: string_attr(op, "sym_name")?, + source: symbol_attr(op, "source")?, + name: symbol_attr(op, "name")?, + index: int_attr(op, "index")?, + oracle: symbol_attr(op, "oracle")?, + }); + } + "cpu.sumcheck_instance_result" => { + instance_results.push(Stage1SumcheckInstanceResultPlan { + symbol: string_attr(op, "sym_name")?, + source: symbol_attr(op, "source")?, + claim: symbol_attr(op, "claim")?, + relation: symbol_attr(op, "relation")?, + index: int_attr(op, "index")?, + point_arity: int_attr(op, "point_arity")?, + num_rounds: int_attr(op, "num_rounds")?, + round_offset: int_attr(op, "round_offset")?, + point_order: string_attr(op, "point_order")?, + degree: int_attr(op, "degree")?, + }); + } + "cpu.opening_claim" => { + opening_claims.push(Stage1OpeningClaimPlan { + symbol: string_attr(op, "sym_name")?, + oracle: symbol_attr(op, "oracle")?, + domain: symbol_attr(op, "domain")?, + point_arity: int_attr(op, "point_arity")?, + claim_kind: string_attr(op, "claim_kind")?, + point_source: operand_symbol(op, 0)?, + eval_source: operand_symbol(op, 1)?, + }); + } + "cpu.opening_batch" => { + opening_batches.push(Stage1OpeningBatchPlan { + symbol: string_attr(op, "sym_name")?, + stage: symbol_attr(op, "stage")?, + proof_slot: symbol_attr(op, "proof_slot")?, + policy: string_attr(op, "policy")?, + count: int_attr(op, "count")?, + ordered_claims: symbol_array_attr(op, "ordered_claims")?, + claim_operands: operand_symbols(op, 0)?, + }); + } + _ => {} + } + } + + Ok(Self { + params: params.ok_or_else(|| EmitError::new("missing cpu.params"))?, + role: module + .role() + .ok_or_else(|| EmitError::new("missing cpu party role"))?, + transcript_squeezes, + kernels, + claims, + batches, + drivers, + instance_results, + evals, + opening_claims, + opening_batches, + }) + } + + fn verify_supported_target(&self) -> Result<(), EmitError> { + require_supported_symbol("field", &self.params.field, "bn254_fr")?; + require_supported_symbol("pcs", &self.params.pcs, "dory")?; + require_supported_symbol("transcript", &self.params.transcript, "blake2b_transcript")?; + self.verify_transcript_squeezes()?; + self.verify_claim_batches()?; + match self.role { + Role::Prover => { + self.verify_kernel_definitions()?; + self.verify_prover_driver_bindings()?; + } + Role::Verifier => self.verify_verifier_driver_bindings()?, + } + self.verify_opening_flow() + } + + fn verify_transcript_squeezes(&self) -> Result<(), EmitError> { + for squeeze in &self.transcript_squeezes { + if squeeze.kind != "challenge_vector" { + return Err(EmitError::new(format!( + "stage1 transcript squeeze @{} has unsupported kind `{}`", + squeeze.symbol, squeeze.kind + ))); + } + if squeeze.count == 0 { + return Err(EmitError::new(format!( + "stage1 transcript squeeze @{} has zero count", + squeeze.symbol + ))); + } + } + Ok(()) + } + + fn verify_kernel_definitions(&self) -> Result<(), EmitError> { + for kernel in &self.kernels { + if kernel.backend != "cpu" { + return Err(EmitError::new(format!( + "stage1 kernel @{} targets unsupported backend `{}`", + kernel.symbol, kernel.backend + ))); + } + if kernel.kind != "sumcheck" { + return Err(EmitError::new(format!( + "stage1 kernel @{} has unsupported kind `{}`", + kernel.symbol, kernel.kind + ))); + } + let expected_abi = match kernel.relation.as_str() { + "jolt.stage1.outer.uniskip" => "jolt_stage1_outer_uniskip", + "jolt.stage1.outer.remaining" => "jolt_stage1_outer_remaining", + _ => { + return Err(EmitError::new(format!( + "unsupported stage1 kernel relation @{}", + kernel.relation + ))); + } + }; + if kernel.abi != expected_abi { + return Err(EmitError::new(format!( + "stage1 kernel @{} ABI `{}` does not match relation @{}", + kernel.symbol, kernel.abi, kernel.relation + ))); + } + } + Ok(()) + } + + fn verify_claim_batches(&self) -> Result<(), EmitError> { + let claims = symbols(self.claims.iter().map(|claim| &claim.symbol)); + for batch in &self.batches { + verify_count( + "sumcheck batch", + &batch.symbol, + batch.count, + batch.ordered_claims.len(), + )?; + verify_count( + "sumcheck batch operands", + &batch.symbol, + batch.count, + batch.claim_operands.len(), + )?; + if batch.ordered_claims != batch.claim_operands { + return Err(EmitError::new(format!( + "sumcheck batch @{} operand order does not match ordered_claims", + batch.symbol + ))); + } + for claim in &batch.ordered_claims { + if !claims.contains(claim) { + return Err(EmitError::new(format!( + "sumcheck batch @{} references missing claim @{claim}", + batch.symbol + ))); + } + } + } + Ok(()) + } + + fn verify_prover_driver_bindings(&self) -> Result<(), EmitError> { + let kernels = symbols(self.kernels.iter().map(|kernel| &kernel.symbol)); + let batches: BTreeMap<_, _> = self + .batches + .iter() + .map(|batch| (batch.symbol.as_str(), batch)) + .collect(); + let claims: BTreeMap<_, _> = self + .claims + .iter() + .map(|claim| (claim.symbol.as_str(), claim)) + .collect(); + for claim in &self.claims { + let Some(kernel) = claim.kernel.as_deref() else { + return Err(EmitError::new(format!( + "prover sumcheck claim @{} is missing kernel", + claim.symbol + ))); + }; + if !kernels.contains(kernel) { + return Err(EmitError::new(format!( + "sumcheck claim @{} references missing kernel @{kernel}", + claim.symbol + ))); + } + } + for driver in &self.drivers { + let Some(kernel) = driver.kernel.as_deref() else { + return Err(EmitError::new(format!( + "prover sumcheck driver @{} is missing kernel", + driver.symbol + ))); + }; + if !kernels.contains(kernel) { + return Err(EmitError::new(format!( + "sumcheck driver @{} references missing kernel @{kernel}", + driver.symbol + ))); + } + let batch = batches.get(driver.batch.as_str()).ok_or_else(|| { + EmitError::new(format!( + "sumcheck driver @{} references missing batch @{}", + driver.symbol, driver.batch + )) + })?; + verify_count( + "sumcheck driver round_schedule", + &driver.symbol, + driver.num_rounds, + driver.round_schedule.iter().sum(), + )?; + if driver.round_schedule != batch.round_schedule { + return Err(EmitError::new(format!( + "sumcheck driver @{} round_schedule differs from batch @{}", + driver.symbol, batch.symbol + ))); + } + for claim in &batch.ordered_claims { + let claim = claims.get(claim.as_str()).ok_or_else(|| { + EmitError::new(format!( + "sumcheck driver @{} references missing claim @{claim}", + driver.symbol + )) + })?; + if claim.kernel.as_deref() != Some(kernel) { + return Err(EmitError::new(format!( + "sumcheck driver @{} kernel @{kernel} differs from claim @{} kernel {:?}", + driver.symbol, claim.symbol, claim.kernel + ))); + } + } + } + Ok(()) + } + + fn verify_verifier_driver_bindings(&self) -> Result<(), EmitError> { + if !self.kernels.is_empty() { + return Err(EmitError::new( + "verifier stage1 program must not contain kernels", + )); + } + let batches: BTreeMap<_, _> = self + .batches + .iter() + .map(|batch| (batch.symbol.as_str(), batch)) + .collect(); + let claims: BTreeMap<_, _> = self + .claims + .iter() + .map(|claim| (claim.symbol.as_str(), claim)) + .collect(); + for claim in &self.claims { + if claim.kernel.is_some() || claim.relation.is_none() { + return Err(EmitError::new(format!( + "verifier sumcheck claim @{} must carry relation and no kernel", + claim.symbol + ))); + } + } + for driver in &self.drivers { + let Some(relation) = driver.relation.as_deref() else { + return Err(EmitError::new(format!( + "verifier sumcheck driver @{} is missing relation", + driver.symbol + ))); + }; + if driver.kernel.is_some() { + return Err(EmitError::new(format!( + "verifier sumcheck driver @{} must not carry kernel", + driver.symbol + ))); + } + let batch = batches.get(driver.batch.as_str()).ok_or_else(|| { + EmitError::new(format!( + "sumcheck driver @{} references missing batch @{}", + driver.symbol, driver.batch + )) + })?; + verify_count( + "sumcheck driver round_schedule", + &driver.symbol, + driver.num_rounds, + driver.round_schedule.iter().sum(), + )?; + if driver.round_schedule != batch.round_schedule { + return Err(EmitError::new(format!( + "sumcheck driver @{} round_schedule differs from batch @{}", + driver.symbol, batch.symbol + ))); + } + for claim in &batch.ordered_claims { + let claim = claims.get(claim.as_str()).ok_or_else(|| { + EmitError::new(format!( + "sumcheck driver @{} references missing claim @{claim}", + driver.symbol + )) + })?; + if claim.relation.as_deref() != Some(relation) { + return Err(EmitError::new(format!( + "sumcheck driver @{} relation @{relation} differs from claim @{} relation {:?}", + driver.symbol, claim.symbol, claim.relation + ))); + } + } + } + Ok(()) + } + + fn verify_opening_flow(&self) -> Result<(), EmitError> { + let drivers = symbols(self.drivers.iter().map(|driver| &driver.symbol)); + let instance_results = symbols( + self.instance_results + .iter() + .map(|instance| &instance.symbol), + ); + for instance in &self.instance_results { + if !drivers.contains(&instance.source) { + return Err(EmitError::new(format!( + "sumcheck instance result @{} references missing driver @{}", + instance.symbol, instance.source + ))); + } + } + let mut point_sources = drivers.clone(); + point_sources.extend(instance_results); + let evals = symbols(self.evals.iter().map(|eval| &eval.symbol)); + let openings = symbols(self.opening_claims.iter().map(|claim| &claim.symbol)); + for eval in &self.evals { + if !drivers.contains(&eval.source) { + return Err(EmitError::new(format!( + "sumcheck eval @{} references missing driver @{}", + eval.symbol, eval.source + ))); + } + } + for claim in &self.opening_claims { + if !point_sources.contains(&claim.point_source) { + return Err(EmitError::new(format!( + "opening claim @{} uses missing point source @{}", + claim.symbol, claim.point_source + ))); + } + if !evals.contains(&claim.eval_source) { + return Err(EmitError::new(format!( + "opening claim @{} uses missing eval source @{}", + claim.symbol, claim.eval_source + ))); + } + } + for batch in &self.opening_batches { + verify_count( + "opening batch", + &batch.symbol, + batch.count, + batch.ordered_claims.len(), + )?; + verify_count( + "opening batch operands", + &batch.symbol, + batch.count, + batch.claim_operands.len(), + )?; + if batch.ordered_claims != batch.claim_operands { + return Err(EmitError::new(format!( + "opening batch @{} operand order does not match ordered_claims", + batch.symbol + ))); + } + for claim in &batch.ordered_claims { + if !openings.contains(claim) { + return Err(EmitError::new(format!( + "opening batch @{} references missing opening @{claim}", + batch.symbol + ))); + } + } + } + Ok(()) + } + + fn emit_source(&self) -> Result { + match self.role { + Role::Prover => self.emit_prover_source(), + Role::Verifier => self.emit_verifier_source(), + } + } + + fn emit_prover_source(&self) -> Result { + let mut source = String::new(); + source.push_str("#![allow(dead_code)]\n\n"); + source.push_str(Self::emit_prover_imports()); + source.push_str("\n\n"); + source.push_str(Self::emit_prover_types()); + source.push('\n'); + source.push_str(&self.emit_prover_constants()?); + source.push('\n'); + source.push_str(Self::emit_prover_entrypoint()); + Ok(source) + } + + fn emit_verifier_source(&self) -> Result { + let mut source = String::new(); + source.push_str("#![allow(dead_code)]\n\n"); + source.push_str(Self::emit_verifier_imports()); + source.push_str("\n\n"); + source.push_str(Self::emit_verifier_types()); + source.push('\n'); + source.push_str(&self.emit_verifier_constants()?); + source.push('\n'); + source.push_str(Self::emit_verifier_entrypoint()); + Ok(source) + } + + fn filename(&self) -> &'static str { + match self.role { + Role::Prover => "prove_stage1_outer.rs", + Role::Verifier => "verify_stage1_outer.rs", + } + } + + fn emit_prover_imports() -> &'static str { + "use jolt_field::Fr;\n\ + use jolt_kernels::stage1::{execute_stage1_program, Stage1CpuProgramPlan, Stage1ExecutionArtifacts, Stage1ExecutionMode, Stage1KernelError, Stage1KernelExecutor, Stage1KernelPlan, Stage1OpeningBatchPlan, Stage1OpeningClaimPlan, Stage1Params, Stage1SumcheckBatchPlan, Stage1SumcheckClaimPlan, Stage1SumcheckDriverPlan, Stage1SumcheckEvalPlan, Stage1SumcheckInstanceResultPlan, Stage1TranscriptSqueezePlan};\n\ + use jolt_transcript::{Blake2bTranscript, Transcript};" + } + + fn emit_prover_types() -> &'static str { + "pub type DefaultStage1Transcript = Blake2bTranscript;\n" + } + + fn emit_prover_constants(&self) -> Result { + let mut source = String::new(); + push_format( + &mut source, + format_args!( + "pub const STAGE1_PARAMS: Stage1Params = Stage1Params {{\n\ + \x20 field: {},\n\ + \x20 pcs: {},\n\ + \x20 transcript: {},\n\ + }};\n", + rust_str(&self.params.field), + rust_str(&self.params.pcs), + rust_str(&self.params.transcript) + ), + ); + + source.push_str(&self.emit_transcript_squeeze_constants()); + source.push_str(&self.emit_kernel_constants()); + source.push_str(&self.emit_sumcheck_claim_constants()?); + source.push_str(&self.emit_sumcheck_batch_constants()); + source.push_str(&self.emit_sumcheck_driver_constants()?); + source.push_str(&self.emit_sumcheck_instance_result_constants()); + source.push_str(&self.emit_sumcheck_eval_constants()); + source.push_str(&self.emit_opening_claim_constants()); + source.push_str(&self.emit_opening_batch_constants()); + source.push_str( + "pub const STAGE1_PROGRAM: Stage1CpuProgramPlan = Stage1CpuProgramPlan {\n\ + \x20 params: STAGE1_PARAMS,\n\ + \x20 transcript_squeezes: STAGE1_TRANSCRIPT_SQUEEZES,\n\ + \x20 kernels: STAGE1_KERNELS,\n\ + \x20 claims: STAGE1_SUMCHECK_CLAIMS,\n\ + \x20 batches: STAGE1_SUMCHECK_BATCHES,\n\ + \x20 drivers: STAGE1_SUMCHECK_DRIVERS,\n\ + \x20 instance_results: STAGE1_SUMCHECK_INSTANCE_RESULTS,\n\ + \x20 evals: STAGE1_SUMCHECK_EVALS,\n\ + \x20 opening_claims: STAGE1_OPENING_CLAIMS,\n\ + \x20 opening_batches: STAGE1_OPENING_BATCHES,\n\ + };\n", + ); + Ok(source) + } + + fn emit_sumcheck_instance_result_constants(&self) -> String { + let instances = self + .instance_results + .iter() + .map(|instance| { + format!( + " Stage1SumcheckInstanceResultPlan {{ symbol: {}, source: {}, claim: {}, relation: {}, index: {}, point_arity: {}, num_rounds: {}, round_offset: {}, point_order: {}, degree: {} }},", + rust_str(&instance.symbol), + rust_str(&instance.source), + rust_str(&instance.claim), + rust_str(&instance.relation), + instance.index, + instance.point_arity, + instance.num_rounds, + instance.round_offset, + rust_str(&instance.point_order), + instance.degree + ) + }) + .collect::>() + .join("\n"); + format!( + "pub const STAGE1_SUMCHECK_INSTANCE_RESULTS: &[Stage1SumcheckInstanceResultPlan] = &[\n{instances}\n];\n\n" + ) + } + + fn emit_transcript_squeeze_constants(&self) -> String { + let squeezes = self + .transcript_squeezes + .iter() + .map(|squeeze| { + format!( + " Stage1TranscriptSqueezePlan {{ symbol: {}, label: {}, kind: {}, count: {} }},", + rust_str(&squeeze.symbol), + rust_str(&squeeze.label), + rust_str(&squeeze.kind), + squeeze.count, + ) + }) + .collect::>() + .join("\n"); + format!( + "pub const STAGE1_TRANSCRIPT_SQUEEZES: &[Stage1TranscriptSqueezePlan] = &[\n{squeezes}\n];\n\n" + ) + } + + fn emit_kernel_constants(&self) -> String { + let kernels = self + .kernels + .iter() + .map(|kernel| { + format!( + " Stage1KernelPlan {{ symbol: {}, relation: {}, kind: {}, backend: {}, abi: {} }},", + rust_str(&kernel.symbol), + rust_str(&kernel.relation), + rust_str(&kernel.kind), + rust_str(&kernel.backend), + rust_str(&kernel.abi) + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE1_KERNELS: &[Stage1KernelPlan] = &[\n{kernels}\n];\n\n") + } + + fn emit_sumcheck_claim_constants(&self) -> Result { + let mut source = String::new(); + for (index, claim) in self.claims.iter().enumerate() { + source.push_str(&emit_str_array( + &format!("STAGE1_SUMCHECK_CLAIM_{index}_INPUT_OPENINGS"), + &claim.input_openings, + )); + } + let mut claims = Vec::new(); + for (index, claim) in self.claims.iter().enumerate() { + let kernel = claim + .kernel + .as_deref() + .ok_or_else(|| missing_role_binding("prover claim kernel", &claim.symbol))?; + claims.push(format!( + " Stage1SumcheckClaimPlan {{ symbol: {}, stage: {}, domain: {}, num_rounds: {}, degree: {}, claim: {}, kernel: Some({}), relation: None, claim_value: {}, input_openings: STAGE1_SUMCHECK_CLAIM_{index}_INPUT_OPENINGS }},", + rust_str(&claim.symbol), + rust_str(&claim.stage), + rust_str(&claim.domain), + claim.num_rounds, + claim.degree, + rust_str(&claim.claim), + rust_str(kernel), + rust_str(&claim.claim_value) + )); + } + let claims = claims.join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE1_SUMCHECK_CLAIMS: &[Stage1SumcheckClaimPlan] = &[\n{claims}\n];\n" + ), + ); + Ok(source) + } + + fn emit_sumcheck_batch_constants(&self) -> String { + if self.role == Role::Verifier { + let mut source = String::new(); + for (index, batch) in self.batches.iter().enumerate() { + source.push_str(&emit_usize_array( + &format!("STAGE1_SUMCHECK_BATCH_{index}_ROUND_SCHEDULE"), + &batch.round_schedule, + )); + } + let batches = self + .batches + .iter() + .enumerate() + .map(|(index, batch)| { + format!( + " Stage1SumcheckBatchPlan {{ symbol: {}, stage: {}, proof_slot: {}, policy: {}, count: {}, ordered_claims: {}, claim_operands: {}, claim_label: {}, round_label: {}, round_schedule: STAGE1_SUMCHECK_BATCH_{index}_ROUND_SCHEDULE }},", + rust_str(&batch.symbol), + rust_str(&batch.stage), + rust_str(&batch.proof_slot), + rust_str(&batch.policy), + batch.count, + rust_str(&batch.ordered_claims.join("|")), + rust_str(&batch.claim_operands.join("|")), + rust_str(&batch.claim_label), + rust_str(&batch.round_label) + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE1_SUMCHECK_BATCHES: &[Stage1SumcheckBatchPlan] = &[\n{batches}\n];\n" + ), + ); + return source; + } + + let mut source = String::new(); + for (index, batch) in self.batches.iter().enumerate() { + source.push_str(&emit_str_array( + &format!("STAGE1_SUMCHECK_BATCH_{index}_ORDERED_CLAIMS"), + &batch.ordered_claims, + )); + source.push_str(&emit_str_array( + &format!("STAGE1_SUMCHECK_BATCH_{index}_CLAIM_OPERANDS"), + &batch.claim_operands, + )); + source.push_str(&emit_usize_array( + &format!("STAGE1_SUMCHECK_BATCH_{index}_ROUND_SCHEDULE"), + &batch.round_schedule, + )); + } + let batches = self + .batches + .iter() + .enumerate() + .map(|(index, batch)| { + format!( + " Stage1SumcheckBatchPlan {{ symbol: {}, stage: {}, proof_slot: {}, policy: {}, count: {}, ordered_claims: STAGE1_SUMCHECK_BATCH_{index}_ORDERED_CLAIMS, claim_operands: STAGE1_SUMCHECK_BATCH_{index}_CLAIM_OPERANDS, claim_label: {}, round_label: {}, round_schedule: STAGE1_SUMCHECK_BATCH_{index}_ROUND_SCHEDULE }},", + rust_str(&batch.symbol), + rust_str(&batch.stage), + rust_str(&batch.proof_slot), + rust_str(&batch.policy), + batch.count, + rust_str(&batch.claim_label), + rust_str(&batch.round_label) + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE1_SUMCHECK_BATCHES: &[Stage1SumcheckBatchPlan] = &[\n{batches}\n];\n" + ), + ); + source + } + + fn emit_sumcheck_driver_constants(&self) -> Result { + let mut source = String::new(); + for (index, driver) in self.drivers.iter().enumerate() { + source.push_str(&emit_usize_array( + &format!("STAGE1_SUMCHECK_DRIVER_{index}_ROUND_SCHEDULE"), + &driver.round_schedule, + )); + } + let mut drivers = Vec::new(); + for (index, driver) in self.drivers.iter().enumerate() { + let kernel = driver + .kernel + .as_deref() + .ok_or_else(|| missing_role_binding("prover driver kernel", &driver.symbol))?; + drivers.push(format!( + " Stage1SumcheckDriverPlan {{ symbol: {}, stage: {}, proof_slot: {}, kernel: Some({}), relation: None, batch: {}, policy: {}, round_schedule: STAGE1_SUMCHECK_DRIVER_{index}_ROUND_SCHEDULE, claim_label: {}, round_label: {}, num_rounds: {}, degree: {} }},", + rust_str(&driver.symbol), + rust_str(&driver.stage), + rust_str(&driver.proof_slot), + rust_str(kernel), + rust_str(&driver.batch), + rust_str(&driver.policy), + rust_str(&driver.claim_label), + rust_str(&driver.round_label), + driver.num_rounds, + driver.degree + )); + } + let drivers = drivers.join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE1_SUMCHECK_DRIVERS: &[Stage1SumcheckDriverPlan] = &[\n{drivers}\n];\n" + ), + ); + Ok(source) + } + + fn emit_sumcheck_eval_constants(&self) -> String { + let evals = self + .evals + .iter() + .map(|eval| { + format!( + " Stage1SumcheckEvalPlan {{ symbol: {}, source: {}, name: {}, index: {}, oracle: {} }},", + rust_str(&eval.symbol), + rust_str(&eval.source), + rust_str(&eval.name), + eval.index, + rust_str(&eval.oracle) + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE1_SUMCHECK_EVALS: &[Stage1SumcheckEvalPlan] = &[\n{evals}\n];\n\n") + } + + fn emit_opening_claim_constants(&self) -> String { + let claims = self + .opening_claims + .iter() + .map(|claim| { + format!( + " Stage1OpeningClaimPlan {{ symbol: {}, oracle: {}, domain: {}, point_arity: {}, claim_kind: {}, point_source: {}, eval_source: {} }},", + rust_str(&claim.symbol), + rust_str(&claim.oracle), + rust_str(&claim.domain), + claim.point_arity, + rust_str(&claim.claim_kind), + rust_str(&claim.point_source), + rust_str(&claim.eval_source) + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE1_OPENING_CLAIMS: &[Stage1OpeningClaimPlan] = &[\n{claims}\n];\n\n") + } + + fn emit_opening_batch_constants(&self) -> String { + if self.role == Role::Verifier { + let batches = self + .opening_batches + .iter() + .map(|batch| { + format!( + " Stage1OpeningBatchPlan {{ symbol: {}, stage: {}, proof_slot: {}, policy: {}, count: {}, ordered_claims: {}, claim_operands: {} }},", + rust_str(&batch.symbol), + rust_str(&batch.stage), + rust_str(&batch.proof_slot), + rust_str(&batch.policy), + batch.count, + rust_str(&batch.ordered_claims.join("|")), + rust_str(&batch.claim_operands.join("|")) + ) + }) + .collect::>() + .join("\n"); + return format!( + "pub const STAGE1_OPENING_BATCHES: &[Stage1OpeningBatchPlan] = &[\n{batches}\n];\n" + ); + } + + let mut source = String::new(); + for (index, batch) in self.opening_batches.iter().enumerate() { + source.push_str(&emit_str_array( + &format!("STAGE1_OPENING_BATCH_{index}_ORDERED_CLAIMS"), + &batch.ordered_claims, + )); + source.push_str(&emit_str_array( + &format!("STAGE1_OPENING_BATCH_{index}_CLAIM_OPERANDS"), + &batch.claim_operands, + )); + } + let batches = self + .opening_batches + .iter() + .enumerate() + .map(|(index, batch)| { + format!( + " Stage1OpeningBatchPlan {{ symbol: {}, stage: {}, proof_slot: {}, policy: {}, count: {}, ordered_claims: STAGE1_OPENING_BATCH_{index}_ORDERED_CLAIMS, claim_operands: STAGE1_OPENING_BATCH_{index}_CLAIM_OPERANDS }},", + rust_str(&batch.symbol), + rust_str(&batch.stage), + rust_str(&batch.proof_slot), + rust_str(&batch.policy), + batch.count + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE1_OPENING_BATCHES: &[Stage1OpeningBatchPlan] = &[\n{batches}\n];\n" + ), + ); + source + } + + fn emit_verifier_imports() -> &'static str { + "use super::common::append_labeled_scalar;\n\ + use jolt_field::{Field, Fr};\n\ + use jolt_sumcheck::{CompressedLabeledRoundPoly, LabeledRoundPoly, SumcheckClaim, SumcheckError, SumcheckVerifier};\n\ + use jolt_transcript::{Blake2bTranscript, Transcript};" + } + + fn emit_verifier_types() -> &'static str { + r"pub type DefaultStage1Transcript = Blake2bTranscript; + +pub type Stage1Params = super::common::StageParams; +pub type Stage1NamedEval = super::common::StageNamedEval; +pub type Stage1SumcheckOutput = super::common::StageSumcheckOutput; +pub type Stage1ChallengeVector = super::common::StageChallengeVector; +pub type Stage1ExecutionArtifacts = super::common::StageExecutionArtifacts; +pub type Stage1Proof = super::common::StageProof; +pub type Stage1VerifierProgramPlan = super::common::VerifierProgramPlanMinimal; + +pub use super::common::{ + OpeningBatchPlan as Stage1OpeningBatchPlan, OpeningClaimPlan as Stage1OpeningClaimPlan, + SumcheckBatchPlan as Stage1SumcheckBatchPlan, SumcheckEvalPlan as Stage1SumcheckEvalPlan, + SumcheckInstanceResultPlan as Stage1SumcheckInstanceResultPlan, + TranscriptSqueezePlan as Stage1TranscriptSqueezePlan, + SumcheckClaimPlan as Stage1SumcheckClaimPlan, + SumcheckDriverPlan as Stage1SumcheckDriverPlan, +}; + +#[derive(Debug)] +pub enum VerifyStage1Error { + UnexpectedProofCount { expected: usize, got: usize }, + MissingProof { driver: &'static str }, + MissingBatch { driver: &'static str, batch: &'static str }, + MissingClaim { driver: &'static str, claim: &'static str }, + MissingDependency { driver: &'static str, dependency: &'static str }, + InvalidProof { driver: &'static str, reason: &'static str }, + UnsupportedRelation { relation: &'static str }, + Sumcheck { driver: &'static str, error: SumcheckError }, +} +" + } + + fn emit_verifier_constants(&self) -> Result { + let mut source = String::new(); + push_format( + &mut source, + format_args!( + "pub const STAGE1_PARAMS: Stage1Params = Stage1Params {{\n\ + \x20 field: {},\n\ + \x20 pcs: {},\n\ + \x20 transcript: {},\n\ + }};\n", + rust_str(&self.params.field), + rust_str(&self.params.pcs), + rust_str(&self.params.transcript) + ), + ); + + source.push_str(&self.emit_transcript_squeeze_constants()); + source.push_str(&self.emit_verifier_sumcheck_claim_constants()?); + source.push_str(&self.emit_sumcheck_batch_constants()); + source.push_str(&self.emit_verifier_sumcheck_driver_constants()?); + source.push_str(&self.emit_sumcheck_instance_result_constants()); + source.push_str(&self.emit_sumcheck_eval_constants()); + source.push_str(&self.emit_opening_claim_constants()); + source.push_str(&self.emit_opening_batch_constants()); + source.push_str( + "pub const STAGE1_PROGRAM: Stage1VerifierProgramPlan = Stage1VerifierProgramPlan {\n\ + \x20 params: STAGE1_PARAMS,\n\ + \x20 transcript_squeezes: STAGE1_TRANSCRIPT_SQUEEZES,\n\ + \x20 claims: STAGE1_SUMCHECK_CLAIMS,\n\ + \x20 batches: STAGE1_SUMCHECK_BATCHES,\n\ + \x20 drivers: STAGE1_SUMCHECK_DRIVERS,\n\ + \x20 instance_results: STAGE1_SUMCHECK_INSTANCE_RESULTS,\n\ + \x20 evals: STAGE1_SUMCHECK_EVALS,\n\ + \x20 opening_claims: STAGE1_OPENING_CLAIMS,\n\ + \x20 opening_batches: STAGE1_OPENING_BATCHES,\n\ + };\n", + ); + Ok(source) + } + + fn emit_verifier_sumcheck_claim_constants(&self) -> Result { + let mut claims = Vec::new(); + for claim in &self.claims { + let relation = claim + .relation + .as_deref() + .ok_or_else(|| missing_role_binding("verifier claim relation", &claim.symbol))?; + claims.push(format!( + " Stage1SumcheckClaimPlan {{ symbol: {}, stage: {}, domain: {}, num_rounds: {}, degree: {}, claim: {}, kernel: None, relation: Some({}), claim_value: {}, input_openings: {} }},", + rust_str(&claim.symbol), + rust_str(&claim.stage), + rust_str(&claim.domain), + claim.num_rounds, + claim.degree, + rust_str(&claim.claim), + rust_str(relation), + rust_str(&claim.claim_value), + rust_str(&claim.input_openings.join("|")) + )); + } + let claims = claims.join("\n"); + Ok(format!( + "pub const STAGE1_SUMCHECK_CLAIMS: &[Stage1SumcheckClaimPlan] = &[\n{claims}\n];\n" + )) + } + + fn emit_verifier_sumcheck_driver_constants(&self) -> Result { + let mut source = String::new(); + for (index, driver) in self.drivers.iter().enumerate() { + source.push_str(&emit_usize_array( + &format!("STAGE1_SUMCHECK_DRIVER_{index}_ROUND_SCHEDULE"), + &driver.round_schedule, + )); + } + let mut drivers = Vec::new(); + for (index, driver) in self.drivers.iter().enumerate() { + let relation = driver + .relation + .as_deref() + .ok_or_else(|| missing_role_binding("verifier driver relation", &driver.symbol))?; + drivers.push(format!( + " Stage1SumcheckDriverPlan {{ symbol: {}, stage: {}, proof_slot: {}, kernel: None, relation: Some({}), batch: {}, policy: {}, round_schedule: STAGE1_SUMCHECK_DRIVER_{index}_ROUND_SCHEDULE, claim_label: {}, round_label: {}, num_rounds: {}, degree: {} }},", + rust_str(&driver.symbol), + rust_str(&driver.stage), + rust_str(&driver.proof_slot), + rust_str(relation), + rust_str(&driver.batch), + rust_str(&driver.policy), + rust_str(&driver.claim_label), + rust_str(&driver.round_label), + driver.num_rounds, + driver.degree + )); + } + let drivers = drivers.join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE1_SUMCHECK_DRIVERS: &[Stage1SumcheckDriverPlan] = &[\n{drivers}\n];\n" + ), + ); + Ok(source) + } + + fn emit_prover_entrypoint() -> &'static str { + r"pub fn prove_stage1_outer( + executor: &mut E, + transcript: &mut T, +) -> Result, Stage1KernelError> +where + E: Stage1KernelExecutor, + T: Transcript, +{ + prove_stage1_outer_with_program(&STAGE1_PROGRAM, executor, transcript) +} + +pub fn prove_stage1_outer_with_program( + program: &'static Stage1CpuProgramPlan, + executor: &mut E, + transcript: &mut T, +) -> Result, Stage1KernelError> +where + E: Stage1KernelExecutor, + T: Transcript, +{ + execute_stage1_program( + program, + Stage1ExecutionMode::Prover, + executor, + transcript, + ) +} +" + } + + fn emit_verifier_entrypoint() -> &'static str { + r#"pub fn verify_stage1_outer( + proof: &Stage1Proof, + transcript: &mut T, +) -> Result, VerifyStage1Error> +where + T: Transcript, +{ + verify_stage1_outer_with_program(&STAGE1_PROGRAM, proof, transcript) +} + +pub fn verify_stage1_outer_with_program( + program: &'static Stage1VerifierProgramPlan, + proof: &Stage1Proof, + transcript: &mut T, +) -> Result, VerifyStage1Error> +where + T: Transcript, +{ + if proof.sumchecks.len() != program.drivers.len() { + return Err(VerifyStage1Error::UnexpectedProofCount { + expected: program.drivers.len(), + got: proof.sumchecks.len(), + }); + } + let mut artifacts = Stage1ExecutionArtifacts::default(); + for squeeze in program.transcript_squeezes { + let values = transcript.challenge_vector(squeeze.count); + artifacts.challenge_vectors.push(Stage1ChallengeVector { + symbol: squeeze.symbol, + values, + }); + } + for (index, driver) in program.drivers.iter().enumerate() { + let proof = proof.sumchecks.get(index).ok_or(VerifyStage1Error::MissingProof { + driver: driver.symbol, + })?; + let output = verify_stage1_driver(program, driver, proof, &artifacts.sumchecks, transcript)?; + artifacts.sumchecks.push(output); + } + artifacts + .opening_batches + .extend(program.opening_batches.iter()); + Ok(artifacts) +} + +pub fn stage1_outer_verifier_program() -> &'static Stage1VerifierProgramPlan { + &STAGE1_PROGRAM +} + +fn verify_stage1_driver( + program: &'static Stage1VerifierProgramPlan, + driver: &'static Stage1SumcheckDriverPlan, + proof: &Stage1SumcheckOutput, + completed: &[Stage1SumcheckOutput], + transcript: &mut T, +) -> Result, VerifyStage1Error> +where + T: Transcript, +{ + if proof.driver != driver.symbol { + return Err(VerifyStage1Error::InvalidProof { + driver: driver.symbol, + reason: "driver symbol mismatch", + }); + } + let relation = driver.relation.unwrap_or(""); + match relation { + "jolt.stage1.outer.uniskip" => verify_outer_uniskip(program, driver, proof, transcript), + "jolt.stage1.outer.remaining" => { + verify_outer_remaining(program, driver, proof, completed, transcript) + } + relation => Err(VerifyStage1Error::UnsupportedRelation { relation }), + } +} + +fn verify_outer_uniskip( + program: &'static Stage1VerifierProgramPlan, + driver: &'static Stage1SumcheckDriverPlan, + proof: &Stage1SumcheckOutput, + transcript: &mut T, +) -> Result, VerifyStage1Error> +where + T: Transcript, +{ + let claim = SumcheckClaim::new(driver.num_rounds, driver.degree, Fr::from_u64(0)); + let round_proofs = proof + .proof + .round_polynomials + .iter() + .map(|poly| LabeledRoundPoly::new(poly, driver.round_label.as_bytes())) + .collect::>(); + let output = SumcheckVerifier::verify(&claim, &round_proofs, transcript) + .map_err(|error| VerifyStage1Error::Sumcheck { + driver: driver.symbol, + error, + })?; + let eval = output.value; + let point = output.point; + if !proof.point.is_empty() && proof.point != point { + return Err(VerifyStage1Error::InvalidProof { + driver: driver.symbol, + reason: "uniskip point mismatch", + }); + } + validate_eval_shape(program, driver, &proof.evals, Some(eval))?; + append_labeled_scalar(transcript, "opening_claim", &eval); + Ok(Stage1SumcheckOutput { + driver: driver.symbol, + point, + evals: driver_evals(program, driver.symbol, eval), + proof: proof.proof.clone(), + }) +} + +fn verify_outer_remaining( + program: &'static Stage1VerifierProgramPlan, + driver: &'static Stage1SumcheckDriverPlan, + proof: &Stage1SumcheckOutput, + completed: &[Stage1SumcheckOutput], + transcript: &mut T, +) -> Result, VerifyStage1Error> +where + T: Transcript, +{ + let input_claim = completed + .iter() + .find(|output| output.driver == "stage1.uniskip.sumcheck") + .and_then(|output| output.evals.first()) + .map(|eval| eval.value) + .ok_or(VerifyStage1Error::MissingDependency { + driver: driver.symbol, + dependency: "stage1.uniskip.eval", + })?; + append_labeled_scalar(transcript, driver.claim_label, &input_claim); + let batching_coeff = transcript.challenge(); + let claim = SumcheckClaim::new( + driver.num_rounds, + driver.degree, + input_claim * batching_coeff, + ); + let round_proofs = proof + .proof + .round_polynomials + .iter() + .map(|poly| CompressedLabeledRoundPoly::new(poly, driver.round_label.as_bytes())) + .collect::>(); + let output = SumcheckVerifier::verify(&claim, &round_proofs, transcript) + .map_err(|error| VerifyStage1Error::Sumcheck { + driver: driver.symbol, + error, + })?; + let point = output.point; + if !proof.point.is_empty() && proof.point != point { + return Err(VerifyStage1Error::InvalidProof { + driver: driver.symbol, + reason: "outer remaining point mismatch", + }); + } + validate_eval_shape(program, driver, &proof.evals, None)?; + append_opening_claims(transcript, &proof.evals); + Ok(Stage1SumcheckOutput { + driver: driver.symbol, + point, + evals: proof.evals.clone(), + proof: proof.proof.clone(), + }) +} + +fn driver_evals( + program: &'static Stage1VerifierProgramPlan, + driver: &'static str, + value: Fr, +) -> Vec> { + program + .evals + .iter() + .filter(|eval| eval.source == driver) + .map(|eval| Stage1NamedEval { + name: eval.name, + oracle: eval.oracle, + value, + }) + .collect() +} + +fn validate_eval_shape( + program: &'static Stage1VerifierProgramPlan, + driver: &'static Stage1SumcheckDriverPlan, + actual: &[Stage1NamedEval], + expected_value: Option, +) -> Result<(), VerifyStage1Error> { + let expected = program + .evals + .iter() + .filter(|eval| eval.source == driver.symbol) + .collect::>(); + if actual.len() != expected.len() { + return Err(VerifyStage1Error::InvalidProof { + driver: driver.symbol, + reason: "eval count mismatch", + }); + } + for (actual, expected) in actual.iter().zip(expected) { + if actual.name != expected.name { + return Err(VerifyStage1Error::InvalidProof { + driver: driver.symbol, + reason: "eval name mismatch", + }); + } + if actual.oracle != expected.oracle { + return Err(VerifyStage1Error::InvalidProof { + driver: driver.symbol, + reason: "eval oracle mismatch", + }); + } + if expected_value.is_some_and(|value| actual.value != value) { + return Err(VerifyStage1Error::InvalidProof { + driver: driver.symbol, + reason: "eval value mismatch", + }); + } + } + Ok(()) +} + +fn append_opening_claims(transcript: &mut T, evals: &[Stage1NamedEval]) +where + T: Transcript, +{ + for eval in evals { + append_labeled_scalar(transcript, "opening_claim", &eval.value); + } +} +"# + } +} + +fn emit_str_array(name: &str, values: &[String]) -> String { + if values.is_empty() { + return format!("pub const {name}: &[&str] = &[];\n\n"); + } + if let [value] = values { + return format!("pub const {name}: &[&str] = &[{}];\n\n", rust_str(value)); + } + let entries = values + .iter() + .map(|value| format!(" {},", rust_str(value))) + .collect::>() + .join("\n"); + format!("pub const {name}: &[&str] = &[\n{entries}\n];\n\n") +} + +fn emit_usize_array(name: &str, values: &[usize]) -> String { + let entries = values + .iter() + .map(|value| format!(" {value},")) + .collect::>() + .join("\n"); + format!("pub const {name}: &[usize] = &[\n{entries}\n];\n\n") +} + +fn rust_str(value: &str) -> String { + format!("{value:?}") +} + +fn verify_count(kind: &str, symbol: &str, expected: usize, actual: usize) -> Result<(), EmitError> { + if expected == actual { + Ok(()) + } else { + Err(EmitError::new(format!( + "{kind} @{symbol} count mismatch: expected {expected}, got {actual}" + ))) + } +} + +fn missing_role_binding(kind: &str, symbol: &str) -> EmitError { + EmitError::new(format!("missing {kind} for `{symbol}`")) +} + +fn symbols<'a>(values: impl Iterator) -> BTreeSet { + values.cloned().collect() +} + +fn string_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .ok() + .and_then(string_attribute_value) + .ok_or_else(|| attr_error(operation, attr, "string")) +} + +fn symbol_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .ok() + .and_then(symbol_attribute_value) + .ok_or_else(|| attr_error(operation, attr, "symbol")) +} + +fn symbol_array_attr( + operation: OperationRef<'_, '_>, + attr: &str, +) -> Result, EmitError> { + let attribute = operation + .attribute(attr) + .map(|attribute| attribute.to_string()) + .ok() + .ok_or_else(|| attr_error(operation, attr, "symbol array"))?; + parse_symbol_array(&attribute).ok_or_else(|| attr_error(operation, attr, "symbol array")) +} + +fn parse_symbol_array(attribute: &str) -> Option> { + let inner = attribute.strip_prefix('[')?.strip_suffix(']')?.trim(); + if inner.is_empty() { + return Some(Vec::new()); + } + inner + .split(',') + .map(|item| item.trim().strip_prefix('@').map(ToOwned::to_owned)) + .collect() +} + +fn int_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .map(parse_integer_attr) + .ok() + .flatten() + .ok_or_else(|| attr_error(operation, attr, "integer")) +} + +fn parse_integer_attr(attribute: Attribute<'_>) -> Option { + attribute + .to_string() + .split_whitespace() + .next() + .and_then(|value| value.parse().ok()) +} + +fn int_array_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result, EmitError> { + let attribute = operation + .attribute(attr) + .map(|attribute| attribute.to_string()) + .ok() + .ok_or_else(|| attr_error(operation, attr, "integer array"))?; + parse_int_array(&attribute).ok_or_else(|| attr_error(operation, attr, "integer array")) +} + +fn parse_int_array(attribute: &str) -> Option> { + let inner = attribute.strip_prefix('[')?.strip_suffix(']')?.trim(); + if inner.is_empty() { + return Some(Vec::new()); + } + inner + .split(',') + .map(|item| item.trim().parse().ok()) + .collect() +} + +fn operand_symbols( + operation: OperationRef<'_, '_>, + start_index: usize, +) -> Result, EmitError> { + (start_index..operation.operand_count()) + .map(|index| operand_symbol(operation, index)) + .collect() +} + +fn operand_symbol(operation: OperationRef<'_, '_>, index: usize) -> Result { + let operand = operation.operand(index).map_err(|_| { + EmitError::new(format!( + "{} requires operand {index}", + operation_name(operation) + )) + })?; + let owner = OperationResult::try_from(operand).map_err(|_| { + EmitError::new(format!( + "{} operand {index} must be an op result", + operation_name(operation) + )) + })?; + string_attr(owner.owner(), "sym_name") +} + +fn attr_error(operation: OperationRef<'_, '_>, attr: &str, expected: &str) -> EmitError { + EmitError::new(format!( + "{} attr `{attr}` is not a {expected}", + operation_name(operation) + )) +} + +fn operation_name(operation: OperationRef<'_, '_>) -> String { + operation + .name() + .as_string_ref() + .as_str() + .unwrap_or("") + .to_owned() +} + +fn require_supported_symbol(kind: &str, actual: &str, expected: &str) -> Result<(), EmitError> { + if actual == expected { + Ok(()) + } else { + Err(EmitError::new(format!( + "unsupported {kind} @{actual}; Rust stage1 emitter currently supports @{expected}" + ))) + } +} diff --git a/crates/bolt/src/protocols/jolt/emit/rust/stage2.rs b/crates/bolt/src/protocols/jolt/emit/rust/stage2.rs new file mode 100644 index 0000000000..eb8eceadb7 --- /dev/null +++ b/crates/bolt/src/protocols/jolt/emit/rust/stage2.rs @@ -0,0 +1,2695 @@ +use std::collections::{BTreeMap, BTreeSet}; + +use melior::ir::block::BlockLike; +use melior::ir::operation::{OperationLike, OperationResult}; +use melior::ir::{Attribute, OperationRef}; + +use crate::emit::rust::{push_format, EmitError, RustSourceFile}; +use crate::ir::{string_attribute_value, symbol_attribute_value, BoltModule, Cpu, Role}; +use crate::schema::verify_cpu_schema; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage2CpuProgram { + pub role: Role, + pub params: Stage2Params, + pub steps: Vec, + pub transcript_squeezes: Vec, + pub opening_inputs: Vec, + pub field_constants: Vec, + pub field_exprs: Vec, + pub kernels: Vec, + pub claims: Vec, + pub batches: Vec, + pub drivers: Vec, + pub instance_results: Vec, + pub evals: Vec, + pub point_slices: Vec, + pub point_concats: Vec, + pub opening_claims: Vec, + pub opening_batches: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage2Params { + pub field: String, + pub pcs: String, + pub transcript: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage2KernelPlan { + pub symbol: String, + pub relation: String, + pub kind: String, + pub backend: String, + pub abi: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage2TranscriptSqueezePlan { + pub symbol: String, + pub label: String, + pub kind: String, + pub count: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage2ProgramStepPlan { + pub kind: String, + pub symbol: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage2OpeningInputPlan { + pub symbol: String, + pub source_stage: String, + pub source_claim: String, + pub oracle: String, + pub domain: String, + pub point_arity: usize, + pub claim_kind: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage2FieldConstantPlan { + pub symbol: String, + pub field: String, + pub value: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage2FieldExprPlan { + pub symbol: String, + pub kind: String, + pub formula: String, + pub operand_names: Vec, + pub operands: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage2SumcheckClaimPlan { + pub symbol: String, + pub stage: String, + pub domain: String, + pub num_rounds: usize, + pub degree: usize, + pub claim: String, + pub kernel: Option, + pub relation: Option, + pub claim_value: String, + pub input_openings: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage2SumcheckBatchPlan { + pub symbol: String, + pub stage: String, + pub proof_slot: String, + pub policy: String, + pub count: usize, + pub ordered_claims: Vec, + pub claim_operands: Vec, + pub claim_label: String, + pub round_label: String, + pub round_schedule: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage2SumcheckDriverPlan { + pub symbol: String, + pub stage: String, + pub proof_slot: String, + pub kernel: Option, + pub relation: Option, + pub batch: String, + pub policy: String, + pub round_schedule: Vec, + pub claim_label: String, + pub round_label: String, + pub num_rounds: usize, + pub degree: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage2SumcheckInstanceResultPlan { + pub symbol: String, + pub source: String, + pub claim: String, + pub relation: String, + pub index: usize, + pub point_arity: usize, + pub num_rounds: usize, + pub round_offset: usize, + pub point_order: String, + pub degree: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage2SumcheckEvalPlan { + pub symbol: String, + pub source: String, + pub name: String, + pub index: usize, + pub oracle: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage2PointSlicePlan { + pub symbol: String, + pub source: String, + pub offset: usize, + pub length: usize, + pub input: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage2PointConcatPlan { + pub symbol: String, + pub layout: String, + pub arity: usize, + pub inputs: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage2OpeningClaimPlan { + pub symbol: String, + pub oracle: String, + pub domain: String, + pub point_arity: usize, + pub claim_kind: String, + pub point_source: String, + pub eval_source: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage2OpeningBatchPlan { + pub symbol: String, + pub stage: String, + pub proof_slot: String, + pub policy: String, + pub count: usize, + pub ordered_claims: Vec, + pub claim_operands: Vec, +} + +pub fn stage2_cpu_program(module: &BoltModule<'_, Cpu>) -> Result { + verify_cpu_schema(module)?; + let program = Stage2CpuProgram::from_module(module)?; + program.verify_supported_target()?; + Ok(program) +} + +pub fn emit_stage2_rust(module: &BoltModule<'_, Cpu>) -> Result { + let program = stage2_cpu_program(module)?; + + Ok(RustSourceFile { + filename: program.filename().to_owned(), + source: program.emit_source()?, + }) +} + +impl Stage2CpuProgram { + fn from_module(module: &BoltModule<'_, Cpu>) -> Result { + let mut params = None; + let mut steps = Vec::new(); + let mut transcript_squeezes = Vec::new(); + let mut opening_inputs = Vec::new(); + let mut field_constants = Vec::new(); + let mut field_exprs = Vec::new(); + let mut kernels = Vec::new(); + let mut claims = Vec::new(); + let mut batches = Vec::new(); + let mut drivers = Vec::new(); + let mut instance_results = Vec::new(); + let mut evals = Vec::new(); + let mut point_slices = Vec::new(); + let mut point_concats = Vec::new(); + let mut opening_claims = Vec::new(); + let mut opening_batches = Vec::new(); + + let mut operation = module.as_mlir_module().body().first_operation(); + while let Some(op) = operation { + operation = op.next_in_block(); + match operation_name(op).as_str() { + "cpu.params" => { + params = Some(Stage2Params { + field: symbol_attr(op, "field")?, + pcs: symbol_attr(op, "pcs")?, + transcript: symbol_attr(op, "transcript")?, + }); + } + "cpu.kernel" => { + kernels.push(Stage2KernelPlan { + symbol: string_attr(op, "sym_name")?, + relation: symbol_attr(op, "relation")?, + kind: string_attr(op, "kind")?, + backend: string_attr(op, "backend")?, + abi: string_attr(op, "abi")?, + }); + } + "cpu.transcript_squeeze" => { + let symbol = string_attr(op, "sym_name")?; + steps.push(Stage2ProgramStepPlan { + kind: "transcript_squeeze".to_owned(), + symbol: symbol.clone(), + }); + transcript_squeezes.push(Stage2TranscriptSqueezePlan { + symbol, + label: string_attr(op, "label")?, + kind: string_attr(op, "kind")?, + count: int_attr(op, "count")?, + }); + } + "cpu.opening_input" => { + opening_inputs.push(Stage2OpeningInputPlan { + symbol: string_attr(op, "sym_name")?, + source_stage: symbol_attr(op, "source_stage")?, + source_claim: symbol_attr(op, "source_claim")?, + oracle: symbol_attr(op, "oracle")?, + domain: symbol_attr(op, "domain")?, + point_arity: int_attr(op, "point_arity")?, + claim_kind: string_attr(op, "claim_kind")?, + }); + } + "cpu.field_const" => { + field_constants.push(Stage2FieldConstantPlan { + symbol: string_attr(op, "sym_name")?, + field: symbol_attr(op, "field")?, + value: int_attr(op, "value")?, + }); + } + "cpu.field_zero" => { + field_constants.push(Stage2FieldConstantPlan { + symbol: string_attr(op, "sym_name")?, + field: symbol_attr(op, "field")?, + value: 0, + }); + } + "cpu.field_one" => { + field_constants.push(Stage2FieldConstantPlan { + symbol: string_attr(op, "sym_name")?, + field: symbol_attr(op, "field")?, + value: 1, + }); + } + "cpu.field_add" | "cpu.field_sub" | "cpu.field_mul" | "cpu.field_neg" => { + let operands = operand_symbols(op, 0)?; + field_exprs.push(Stage2FieldExprPlan { + symbol: string_attr(op, "sym_name")?, + kind: "op".to_owned(), + formula: operation_name(op).replace("cpu.field_", "field."), + operand_names: operands.clone(), + operands, + }); + } + "cpu.field_pow" => { + let exponent = int_attr(op, "exponent")?; + let operands = operand_symbols(op, 0)?; + field_exprs.push(Stage2FieldExprPlan { + symbol: string_attr(op, "sym_name")?, + kind: "op".to_owned(), + formula: format!("field.pow:{exponent}"), + operand_names: operands.clone(), + operands, + }); + } + "cpu.poly_lagrange_basis_eval" => { + let domain_start = signed_int_attr(op, "domain_start")?; + let domain_size = int_attr(op, "domain_size")?; + let index = int_attr(op, "index")?; + let operands = operand_symbols(op, 0)?; + field_exprs.push(Stage2FieldExprPlan { + symbol: string_attr(op, "sym_name")?, + kind: "op".to_owned(), + formula: format!( + "poly.lagrange_basis_eval:{domain_start}:{domain_size}:{index}" + ), + operand_names: operands.clone(), + operands, + }); + } + "cpu.sumcheck_claim" => { + claims.push(Stage2SumcheckClaimPlan { + symbol: string_attr(op, "sym_name")?, + stage: symbol_attr(op, "stage")?, + domain: symbol_attr(op, "domain")?, + num_rounds: int_attr(op, "num_rounds")?, + degree: int_attr(op, "degree")?, + claim: symbol_attr(op, "claim")?, + kernel: Some(symbol_attr(op, "kernel")?), + relation: None, + claim_value: operand_symbol(op, 0)?, + input_openings: operand_symbols(op, 1)?, + }); + } + "cpu.sumcheck_verify_claim" => { + claims.push(Stage2SumcheckClaimPlan { + symbol: string_attr(op, "sym_name")?, + stage: symbol_attr(op, "stage")?, + domain: symbol_attr(op, "domain")?, + num_rounds: int_attr(op, "num_rounds")?, + degree: int_attr(op, "degree")?, + claim: symbol_attr(op, "claim")?, + kernel: None, + relation: Some(symbol_attr(op, "relation")?), + claim_value: operand_symbol(op, 0)?, + input_openings: operand_symbols(op, 1)?, + }); + } + "cpu.sumcheck_batch" => { + batches.push(Stage2SumcheckBatchPlan { + symbol: string_attr(op, "sym_name")?, + stage: symbol_attr(op, "stage")?, + proof_slot: symbol_attr(op, "proof_slot")?, + policy: string_attr(op, "policy")?, + count: int_attr(op, "count")?, + ordered_claims: symbol_array_attr(op, "ordered_claims")?, + claim_operands: operand_symbols(op, 0)?, + claim_label: string_attr(op, "claim_label")?, + round_label: string_attr(op, "round_label")?, + round_schedule: int_array_attr(op, "round_schedule")?, + }); + } + "cpu.sumcheck_driver" => { + let symbol = string_attr(op, "sym_name")?; + steps.push(Stage2ProgramStepPlan { + kind: "sumcheck_driver".to_owned(), + symbol: symbol.clone(), + }); + drivers.push(Stage2SumcheckDriverPlan { + symbol, + stage: symbol_attr(op, "stage")?, + proof_slot: symbol_attr(op, "proof_slot")?, + kernel: Some(symbol_attr(op, "kernel")?), + relation: None, + batch: operand_symbol(op, 1)?, + policy: string_attr(op, "policy")?, + round_schedule: int_array_attr(op, "round_schedule")?, + claim_label: string_attr(op, "claim_label")?, + round_label: string_attr(op, "round_label")?, + num_rounds: int_attr(op, "num_rounds")?, + degree: int_attr(op, "degree")?, + }); + } + "cpu.sumcheck_verify" => { + let symbol = string_attr(op, "sym_name")?; + steps.push(Stage2ProgramStepPlan { + kind: "sumcheck_driver".to_owned(), + symbol: symbol.clone(), + }); + drivers.push(Stage2SumcheckDriverPlan { + symbol, + stage: symbol_attr(op, "stage")?, + proof_slot: symbol_attr(op, "proof_slot")?, + kernel: None, + relation: Some(symbol_attr(op, "relation")?), + batch: operand_symbol(op, 1)?, + policy: string_attr(op, "policy")?, + round_schedule: int_array_attr(op, "round_schedule")?, + claim_label: string_attr(op, "claim_label")?, + round_label: string_attr(op, "round_label")?, + num_rounds: int_attr(op, "num_rounds")?, + degree: int_attr(op, "degree")?, + }); + } + "cpu.sumcheck_instance_result" => { + instance_results.push(Stage2SumcheckInstanceResultPlan { + symbol: string_attr(op, "sym_name")?, + source: symbol_attr(op, "source")?, + claim: symbol_attr(op, "claim")?, + relation: symbol_attr(op, "relation")?, + index: int_attr(op, "index")?, + point_arity: int_attr(op, "point_arity")?, + num_rounds: int_attr(op, "num_rounds")?, + round_offset: int_attr(op, "round_offset")?, + point_order: string_attr(op, "point_order")?, + degree: int_attr(op, "degree")?, + }); + } + "cpu.sumcheck_eval" => { + evals.push(Stage2SumcheckEvalPlan { + symbol: string_attr(op, "sym_name")?, + source: symbol_attr(op, "source")?, + name: symbol_attr(op, "name")?, + index: int_attr(op, "index")?, + oracle: symbol_attr(op, "oracle")?, + }); + } + "cpu.point_slice" => { + point_slices.push(Stage2PointSlicePlan { + symbol: string_attr(op, "sym_name")?, + source: symbol_attr(op, "source")?, + offset: int_attr(op, "offset")?, + length: int_attr(op, "length")?, + input: operand_symbol(op, 0)?, + }); + } + "cpu.point_concat" => { + point_concats.push(Stage2PointConcatPlan { + symbol: string_attr(op, "sym_name")?, + layout: string_attr(op, "layout")?, + arity: int_attr(op, "arity")?, + inputs: operand_symbols(op, 0)?, + }); + } + "cpu.opening_claim" => { + opening_claims.push(Stage2OpeningClaimPlan { + symbol: string_attr(op, "sym_name")?, + oracle: symbol_attr(op, "oracle")?, + domain: symbol_attr(op, "domain")?, + point_arity: int_attr(op, "point_arity")?, + claim_kind: string_attr(op, "claim_kind")?, + point_source: operand_symbol(op, 0)?, + eval_source: operand_symbol(op, 1)?, + }); + } + "cpu.opening_batch" => { + opening_batches.push(Stage2OpeningBatchPlan { + symbol: string_attr(op, "sym_name")?, + stage: symbol_attr(op, "stage")?, + proof_slot: symbol_attr(op, "proof_slot")?, + policy: string_attr(op, "policy")?, + count: int_attr(op, "count")?, + ordered_claims: symbol_array_attr(op, "ordered_claims")?, + claim_operands: operand_symbols(op, 0)?, + }); + } + _ => {} + } + } + + Ok(Self { + params: params.ok_or_else(|| EmitError::new("missing cpu.params"))?, + role: module + .role() + .ok_or_else(|| EmitError::new("missing cpu party role"))?, + steps, + transcript_squeezes, + opening_inputs, + field_constants, + field_exprs, + kernels, + claims, + batches, + drivers, + instance_results, + evals, + point_slices, + point_concats, + opening_claims, + opening_batches, + }) + } + + fn verify_supported_target(&self) -> Result<(), EmitError> { + require_supported_symbol("field", &self.params.field, "bn254_fr")?; + require_supported_symbol("pcs", &self.params.pcs, "dory")?; + require_supported_symbol("transcript", &self.params.transcript, "blake2b_transcript")?; + self.verify_transcript_squeezes()?; + self.verify_field_flow()?; + self.verify_claim_batches()?; + match self.role { + Role::Prover => { + self.verify_kernel_definitions()?; + self.verify_prover_driver_bindings()?; + } + Role::Verifier => self.verify_verifier_driver_bindings()?, + } + self.verify_opening_flow() + } + + fn verify_transcript_squeezes(&self) -> Result<(), EmitError> { + for squeeze in &self.transcript_squeezes { + if !matches!( + squeeze.kind.as_str(), + "challenge_scalar" | "challenge_vector" + ) { + return Err(EmitError::new(format!( + "stage2 transcript squeeze @{} has unsupported kind `{}`", + squeeze.symbol, squeeze.kind + ))); + } + if squeeze.count == 0 { + return Err(EmitError::new(format!( + "stage2 transcript squeeze @{} has zero count", + squeeze.symbol + ))); + } + } + Ok(()) + } + + fn verify_field_flow(&self) -> Result<(), EmitError> { + for constant in &self.field_constants { + require_supported_symbol("field constant field", &constant.field, "bn254_fr")?; + } + let field_values = self.field_value_symbols(); + for expr in &self.field_exprs { + verify_count( + "field expr operands", + &expr.symbol, + expr.operand_names.len(), + expr.operands.len(), + )?; + for operand in &expr.operands { + if !field_values.contains(operand) { + return Err(EmitError::new(format!( + "field expr @{} references missing field value @{operand}", + expr.symbol + ))); + } + } + } + for claim in &self.claims { + if !field_values.contains(&claim.claim_value) { + return Err(EmitError::new(format!( + "sumcheck claim @{} uses missing claim value @{}", + claim.symbol, claim.claim_value + ))); + } + } + Ok(()) + } + + fn field_value_symbols(&self) -> BTreeSet { + let mut values = symbols(self.opening_inputs.iter().map(|input| &input.symbol)); + values.extend(symbols( + self.field_constants.iter().map(|constant| &constant.symbol), + )); + values.extend(symbols( + self.transcript_squeezes + .iter() + .filter(|squeeze| matches!(squeeze.kind.as_str(), "challenge_scalar" | "scalar")) + .map(|squeeze| &squeeze.symbol), + )); + values.extend(symbols(self.field_exprs.iter().map(|expr| &expr.symbol))); + values.extend(symbols(self.evals.iter().map(|eval| &eval.symbol))); + values + } + + fn verify_kernel_definitions(&self) -> Result<(), EmitError> { + for kernel in &self.kernels { + if kernel.backend != "cpu" { + return Err(EmitError::new(format!( + "stage2 kernel @{} targets unsupported backend `{}`", + kernel.symbol, kernel.backend + ))); + } + if kernel.kind != "sumcheck" { + return Err(EmitError::new(format!( + "stage2 kernel @{} has unsupported kind `{}`", + kernel.symbol, kernel.kind + ))); + } + let expected_abi = match kernel.relation.as_str() { + "jolt.stage2.product_virtual.uniskip" => "jolt_stage2_product_virtual_uniskip", + "jolt.stage2.ram.read_write" => "jolt_stage2_ram_read_write", + "jolt.stage2.product_virtual.remainder" => "jolt_stage2_product_virtual_remainder", + "jolt.stage2.instruction_lookup.claim_reduction" => { + "jolt_stage2_instruction_lookup_claim_reduction" + } + "jolt.stage2.ram.raf_evaluation" => "jolt_stage2_ram_raf_evaluation", + "jolt.stage2.ram.output_check" => "jolt_stage2_ram_output_check", + "jolt.stage2.batched" => "jolt_stage2_batched", + _ => { + return Err(EmitError::new(format!( + "unsupported stage2 kernel relation @{}", + kernel.relation + ))); + } + }; + if kernel.abi != expected_abi { + return Err(EmitError::new(format!( + "stage2 kernel @{} ABI `{}` does not match relation @{}", + kernel.symbol, kernel.abi, kernel.relation + ))); + } + } + Ok(()) + } + + fn verify_claim_batches(&self) -> Result<(), EmitError> { + let claims = symbols(self.claims.iter().map(|claim| &claim.symbol)); + for batch in &self.batches { + verify_count( + "sumcheck batch", + &batch.symbol, + batch.count, + batch.ordered_claims.len(), + )?; + verify_count( + "sumcheck batch operands", + &batch.symbol, + batch.count, + batch.claim_operands.len(), + )?; + if batch.ordered_claims != batch.claim_operands { + return Err(EmitError::new(format!( + "sumcheck batch @{} operand order does not match ordered_claims", + batch.symbol + ))); + } + for claim in &batch.ordered_claims { + if !claims.contains(claim) { + return Err(EmitError::new(format!( + "sumcheck batch @{} references missing claim @{claim}", + batch.symbol + ))); + } + } + } + Ok(()) + } + + fn verify_prover_driver_bindings(&self) -> Result<(), EmitError> { + let kernels = symbols(self.kernels.iter().map(|kernel| &kernel.symbol)); + let batches: BTreeMap<_, _> = self + .batches + .iter() + .map(|batch| (batch.symbol.as_str(), batch)) + .collect(); + for claim in &self.claims { + let Some(kernel) = claim.kernel.as_deref() else { + return Err(EmitError::new(format!( + "prover sumcheck claim @{} is missing kernel", + claim.symbol + ))); + }; + if !kernels.contains(kernel) { + return Err(EmitError::new(format!( + "sumcheck claim @{} references missing kernel @{kernel}", + claim.symbol + ))); + } + } + for driver in &self.drivers { + let Some(kernel) = driver.kernel.as_deref() else { + return Err(EmitError::new(format!( + "prover sumcheck driver @{} is missing kernel", + driver.symbol + ))); + }; + if !kernels.contains(kernel) { + return Err(EmitError::new(format!( + "sumcheck driver @{} references missing kernel @{kernel}", + driver.symbol + ))); + } + let batch = batches.get(driver.batch.as_str()).ok_or_else(|| { + EmitError::new(format!( + "sumcheck driver @{} references missing batch @{}", + driver.symbol, driver.batch + )) + })?; + verify_count( + "sumcheck driver round_schedule", + &driver.symbol, + driver.num_rounds, + driver.round_schedule.iter().sum(), + )?; + if driver.round_schedule != batch.round_schedule { + return Err(EmitError::new(format!( + "sumcheck driver @{} round_schedule differs from batch @{}", + driver.symbol, batch.symbol + ))); + } + } + Ok(()) + } + + fn verify_verifier_driver_bindings(&self) -> Result<(), EmitError> { + if !self.kernels.is_empty() { + return Err(EmitError::new( + "verifier stage2 program must not contain kernels", + )); + } + let batches: BTreeMap<_, _> = self + .batches + .iter() + .map(|batch| (batch.symbol.as_str(), batch)) + .collect(); + for claim in &self.claims { + if claim.kernel.is_some() || claim.relation.is_none() { + return Err(EmitError::new(format!( + "verifier sumcheck claim @{} must carry relation and no kernel", + claim.symbol + ))); + } + } + for driver in &self.drivers { + if driver.kernel.is_some() || driver.relation.is_none() { + return Err(EmitError::new(format!( + "verifier sumcheck driver @{} must carry relation and no kernel", + driver.symbol + ))); + } + let batch = batches.get(driver.batch.as_str()).ok_or_else(|| { + EmitError::new(format!( + "sumcheck driver @{} references missing batch @{}", + driver.symbol, driver.batch + )) + })?; + verify_count( + "sumcheck driver round_schedule", + &driver.symbol, + driver.num_rounds, + driver.round_schedule.iter().sum(), + )?; + if driver.round_schedule != batch.round_schedule { + return Err(EmitError::new(format!( + "sumcheck driver @{} round_schedule differs from batch @{}", + driver.symbol, batch.symbol + ))); + } + } + Ok(()) + } + + fn verify_opening_flow(&self) -> Result<(), EmitError> { + let mut point_sources = symbols(self.drivers.iter().map(|driver| &driver.symbol)); + point_sources.extend(symbols( + self.instance_results + .iter() + .map(|instance| &instance.symbol), + )); + point_sources.extend(symbols( + self.opening_inputs.iter().map(|input| &input.symbol), + )); + point_sources.extend(symbols(self.point_slices.iter().map(|slice| &slice.symbol))); + point_sources.extend(symbols( + self.point_concats.iter().map(|concat| &concat.symbol), + )); + for slice in &self.point_slices { + if !point_sources.contains(&slice.input) { + return Err(EmitError::new(format!( + "point slice @{} uses missing point source @{}", + slice.symbol, slice.input + ))); + } + } + for concat in &self.point_concats { + for input in &concat.inputs { + if !point_sources.contains(input) { + return Err(EmitError::new(format!( + "point concat @{} uses missing point source @{input}", + concat.symbol + ))); + } + } + } + let eval_sources = self.field_value_symbols(); + let mut opening_sources = symbols(self.opening_inputs.iter().map(|input| &input.symbol)); + opening_sources.extend(symbols( + self.opening_claims.iter().map(|claim| &claim.symbol), + )); + for claim in &self.claims { + for input in &claim.input_openings { + if !opening_sources.contains(input) { + return Err(EmitError::new(format!( + "sumcheck claim @{} uses missing opening @{input}", + claim.symbol + ))); + } + } + } + let drivers = symbols(self.drivers.iter().map(|driver| &driver.symbol)); + for instance in &self.instance_results { + if !drivers.contains(&instance.source) { + return Err(EmitError::new(format!( + "sumcheck instance result @{} references missing driver @{}", + instance.symbol, instance.source + ))); + } + } + for eval in &self.evals { + if !drivers.contains(&eval.source) { + return Err(EmitError::new(format!( + "sumcheck eval @{} references missing driver @{}", + eval.symbol, eval.source + ))); + } + } + for claim in &self.opening_claims { + if !point_sources.contains(&claim.point_source) { + return Err(EmitError::new(format!( + "opening claim @{} uses missing point source @{}", + claim.symbol, claim.point_source + ))); + } + if !eval_sources.contains(&claim.eval_source) { + return Err(EmitError::new(format!( + "opening claim @{} uses missing eval source @{}", + claim.symbol, claim.eval_source + ))); + } + } + let openings = symbols(self.opening_claims.iter().map(|claim| &claim.symbol)); + for batch in &self.opening_batches { + verify_count( + "opening batch", + &batch.symbol, + batch.count, + batch.ordered_claims.len(), + )?; + verify_count( + "opening batch operands", + &batch.symbol, + batch.count, + batch.claim_operands.len(), + )?; + if batch.ordered_claims != batch.claim_operands { + return Err(EmitError::new(format!( + "opening batch @{} operand order does not match ordered_claims", + batch.symbol + ))); + } + for claim in &batch.ordered_claims { + if !openings.contains(claim) { + return Err(EmitError::new(format!( + "opening batch @{} references missing opening @{claim}", + batch.symbol + ))); + } + } + } + Ok(()) + } + + fn emit_source(&self) -> Result { + match self.role { + Role::Prover => self.emit_prover_source(), + Role::Verifier => self.emit_verifier_source(), + } + } + + fn emit_prover_source(&self) -> Result { + let mut source = String::new(); + source.push_str("#![allow(dead_code)]\n\n"); + source.push_str(Self::emit_prover_imports()); + source.push_str("\n\n"); + source.push_str(Self::emit_prover_types()); + source.push('\n'); + source.push_str(&self.emit_prover_constants()?); + source.push('\n'); + source.push_str(Self::emit_prover_entrypoint()); + Ok(source) + } + + fn emit_verifier_source(&self) -> Result { + let mut source = String::new(); + source.push_str("#![allow(dead_code)]\n\n"); + source.push_str(Self::emit_verifier_imports()); + source.push_str("\n\n"); + source.push_str(Self::emit_verifier_types()); + source.push('\n'); + source.push_str(&self.emit_verifier_constants()?); + source.push('\n'); + source.push_str(Self::emit_verifier_entrypoint()); + Ok(source) + } + + fn filename(&self) -> &'static str { + match self.role { + Role::Prover => "prove_stage2.rs", + Role::Verifier => "verify_stage2.rs", + } + } + + fn emit_prover_imports() -> &'static str { + "use jolt_field::Fr;\n\ + use jolt_kernels::stage2::{execute_stage2_program, Stage2CpuProgramPlan, Stage2ExecutionArtifacts, Stage2ExecutionMode, Stage2FieldConstantPlan, Stage2FieldExprPlan, Stage2KernelError, Stage2KernelExecutor, Stage2KernelPlan, Stage2OpeningBatchPlan, Stage2OpeningClaimPlan, Stage2OpeningInputPlan, Stage2Params, Stage2PointConcatPlan, Stage2PointSlicePlan, Stage2ProgramStepPlan, Stage2SumcheckBatchPlan, Stage2SumcheckClaimPlan, Stage2SumcheckDriverPlan, Stage2SumcheckEvalPlan, Stage2SumcheckInstanceResultPlan, Stage2TranscriptSqueezePlan};\n\ + use jolt_transcript::{Blake2bTranscript, Transcript};" + } + + fn emit_prover_types() -> &'static str { + "pub type DefaultStage2Transcript = Blake2bTranscript;\n" + } + + fn emit_verifier_imports() -> &'static str { + "use super::common::{append_labeled_scalar, batch_claims, eval_by_name, find_batch, find_plan, pow_field, require_operand_count, reverse_slice, single_operand};\n\ + use jolt_field::{Field, Fr};\n\ + use jolt_poly::lagrange::{lagrange_evals, lagrange_kernel_eval};\n\ + use jolt_poly::{EqPolynomial, UnivariatePoly};\n\ + use jolt_sumcheck::{CompressedLabeledRoundPoly, SumcheckClaim, SumcheckError, SumcheckVerifier};\n\ + use jolt_transcript::{Blake2bTranscript, LabelWithCount, Transcript};" + } + + fn emit_verifier_types() -> &'static str { + r"pub type DefaultStage2Transcript = Blake2bTranscript; + +pub type Stage2NamedEval = super::common::StageNamedEval; +pub type Stage2SumcheckOutput = super::common::StageSumcheckOutput; +pub type Stage2ChallengeVector = super::common::StageChallengeVector; +pub type Stage2ExecutionArtifacts = super::common::StageExecutionArtifacts; +pub type Stage2Proof = super::common::StageProof; +pub type Stage2OpeningInputValue = super::common::StageOpeningInputValue; +pub type Stage2VerifierProgramPlan = super::common::StageVerifierProgramPlanNoEqualities; + +pub use super::common::{ + FieldConstantPlan as Stage2FieldConstantPlan, FieldExprPlan as Stage2FieldExprPlan, + OpeningBatchPlan as Stage2OpeningBatchPlan, OpeningClaimPlan as Stage2OpeningClaimPlan, + OpeningInputPlan as Stage2OpeningInputPlan, PointConcatPlan as Stage2PointConcatPlan, + PointSlicePlan as Stage2PointSlicePlan, ProgramStepPlan as Stage2ProgramStepPlan, + StageParams as Stage2Params, SumcheckBatchPlan as Stage2SumcheckBatchPlan, + SumcheckEvalPlan as Stage2SumcheckEvalPlan, + SumcheckInstanceResultPlan as Stage2SumcheckInstanceResultPlan, + TranscriptSqueezePlan as Stage2TranscriptSqueezePlan, + SumcheckClaimPlan as Stage2SumcheckClaimPlan, + SumcheckDriverPlan as Stage2SumcheckDriverPlan, +}; + +#[derive(Clone, Copy, Debug)] +pub struct Stage2RamAccess { + pub remapped_address: Option, + pub read_value: u64, + pub write_value: u64, +} + +#[derive(Clone, Copy, Debug)] +pub struct Stage2RamOutputLayout { + pub io_start: usize, + pub io_end: usize, +} + +#[derive(Clone, Copy, Debug)] +pub struct Stage2RamData<'a> { + pub log_k: usize, + pub start_address: u64, + pub initial_ram: &'a [u64], + pub final_ram: &'a [u64], + pub accesses: &'a [Stage2RamAccess], + pub output_layout: Option, +} + +#[derive(Clone, Debug, Default)] +struct Stage2ValueStore(super::common::ValueStore); + +#[derive(Debug)] +pub enum VerifyStage2Error { + UnexpectedProofCount { expected: usize, got: usize }, + MissingProof { driver: &'static str }, + MissingBatch { driver: &'static str, batch: &'static str }, + MissingClaim { batch: &'static str, claim: &'static str }, + MissingValue { symbol: &'static str }, + InvalidInputLength { input: &'static str, expected: usize, actual: usize }, + InvalidProof { driver: &'static str, reason: &'static str }, + UnsupportedFieldExpr { symbol: &'static str, formula: &'static str }, + UnsupportedRelation { relation: &'static str }, + MissingRam { relation: &'static str }, + Sumcheck { driver: &'static str, error: SumcheckError }, +} + +super::common::impl_runtime_plan_error_conversion!(VerifyStage2Error); +" + } + + fn emit_prover_constants(&self) -> Result { + let mut source = self.emit_shared_constants(); + source.push_str(&self.emit_kernel_constants()); + source.push_str(&self.emit_prover_sumcheck_claim_constants()?); + source.push_str(&self.emit_sumcheck_batch_constants()); + source.push_str(&self.emit_prover_sumcheck_driver_constants()?); + source.push_str(&self.emit_tail_constants()); + source.push_str( + "pub const STAGE2_PROGRAM: Stage2CpuProgramPlan = Stage2CpuProgramPlan {\n\ + \x20 params: STAGE2_PARAMS,\n\ + \x20 steps: STAGE2_PROGRAM_STEPS,\n\ + \x20 transcript_squeezes: STAGE2_TRANSCRIPT_SQUEEZES,\n\ + \x20 opening_inputs: STAGE2_OPENING_INPUTS,\n\ + \x20 field_constants: STAGE2_FIELD_CONSTANTS,\n\ + \x20 field_exprs: STAGE2_FIELD_EXPRS,\n\ + \x20 kernels: STAGE2_KERNELS,\n\ + \x20 claims: STAGE2_SUMCHECK_CLAIMS,\n\ + \x20 batches: STAGE2_SUMCHECK_BATCHES,\n\ + \x20 drivers: STAGE2_SUMCHECK_DRIVERS,\n\ + \x20 instance_results: STAGE2_SUMCHECK_INSTANCE_RESULTS,\n\ + \x20 evals: STAGE2_SUMCHECK_EVALS,\n\ + \x20 point_slices: STAGE2_POINT_SLICES,\n\ + \x20 point_concats: STAGE2_POINT_CONCATS,\n\ + \x20 opening_claims: STAGE2_OPENING_CLAIMS,\n\ + \x20 opening_batches: STAGE2_OPENING_BATCHES,\n\ + };\n", + ); + Ok(source) + } + + fn emit_verifier_constants(&self) -> Result { + let mut source = self.emit_shared_constants(); + source.push_str(&self.emit_verifier_sumcheck_claim_constants()?); + source.push_str(&self.emit_sumcheck_batch_constants()); + source.push_str(&self.emit_verifier_sumcheck_driver_constants()?); + source.push_str(&self.emit_tail_constants()); + source.push_str( + "pub const STAGE2_PROGRAM: Stage2VerifierProgramPlan = Stage2VerifierProgramPlan {\n\ + \x20 params: STAGE2_PARAMS,\n\ + \x20 steps: STAGE2_PROGRAM_STEPS,\n\ + \x20 transcript_squeezes: STAGE2_TRANSCRIPT_SQUEEZES,\n\ + \x20 opening_inputs: STAGE2_OPENING_INPUTS,\n\ + \x20 field_constants: STAGE2_FIELD_CONSTANTS,\n\ + \x20 field_exprs: STAGE2_FIELD_EXPRS,\n\ + \x20 claims: STAGE2_SUMCHECK_CLAIMS,\n\ + \x20 batches: STAGE2_SUMCHECK_BATCHES,\n\ + \x20 drivers: STAGE2_SUMCHECK_DRIVERS,\n\ + \x20 instance_results: STAGE2_SUMCHECK_INSTANCE_RESULTS,\n\ + \x20 evals: STAGE2_SUMCHECK_EVALS,\n\ + \x20 point_slices: STAGE2_POINT_SLICES,\n\ + \x20 point_concats: STAGE2_POINT_CONCATS,\n\ + \x20 opening_claims: STAGE2_OPENING_CLAIMS,\n\ + \x20 opening_batches: STAGE2_OPENING_BATCHES,\n\ + };\n", + ); + Ok(source) + } + + fn emit_shared_constants(&self) -> String { + let mut source = String::new(); + push_format( + &mut source, + format_args!( + "pub const STAGE2_PARAMS: Stage2Params = Stage2Params {{\n\ + \x20 field: {},\n\ + \x20 pcs: {},\n\ + \x20 transcript: {},\n\ + }};\n", + rust_str(&self.params.field), + rust_str(&self.params.pcs), + rust_str(&self.params.transcript) + ), + ); + source.push_str(&self.emit_program_step_constants()); + source.push_str(&self.emit_transcript_squeeze_constants()); + source.push_str(&self.emit_opening_input_constants()); + source.push_str(&self.emit_field_constant_constants()); + source.push_str(&self.emit_field_expr_constants()); + source + } + + fn emit_program_step_constants(&self) -> String { + let steps = self + .steps + .iter() + .map(|step| { + format!( + " Stage2ProgramStepPlan {{ kind: {}, symbol: {} }},", + rust_str(&step.kind), + rust_str(&step.symbol), + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE2_PROGRAM_STEPS: &[Stage2ProgramStepPlan] = &[\n{steps}\n];\n\n") + } + + fn emit_transcript_squeeze_constants(&self) -> String { + let squeezes = self + .transcript_squeezes + .iter() + .map(|squeeze| { + format!( + " Stage2TranscriptSqueezePlan {{ symbol: {}, label: {}, kind: {}, count: {} }},", + rust_str(&squeeze.symbol), + rust_str(&squeeze.label), + rust_str(&squeeze.kind), + squeeze.count, + ) + }) + .collect::>() + .join("\n"); + format!( + "pub const STAGE2_TRANSCRIPT_SQUEEZES: &[Stage2TranscriptSqueezePlan] = &[\n{squeezes}\n];\n\n" + ) + } + + fn emit_opening_input_constants(&self) -> String { + let inputs = self + .opening_inputs + .iter() + .map(|input| { + format!( + " Stage2OpeningInputPlan {{ symbol: {}, source_stage: {}, source_claim: {}, oracle: {}, domain: {}, point_arity: {}, claim_kind: {} }},", + rust_str(&input.symbol), + rust_str(&input.source_stage), + rust_str(&input.source_claim), + rust_str(&input.oracle), + rust_str(&input.domain), + input.point_arity, + rust_str(&input.claim_kind) + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE2_OPENING_INPUTS: &[Stage2OpeningInputPlan] = &[\n{inputs}\n];\n\n") + } + + fn emit_field_constant_constants(&self) -> String { + let constants = self + .field_constants + .iter() + .map(|constant| { + format!( + " Stage2FieldConstantPlan {{ symbol: {}, field: {}, value: {} }},", + rust_str(&constant.symbol), + rust_str(&constant.field), + constant.value + ) + }) + .collect::>() + .join("\n"); + format!( + "pub const STAGE2_FIELD_CONSTANTS: &[Stage2FieldConstantPlan] = &[\n{constants}\n];\n\n" + ) + } + + fn emit_field_expr_constants(&self) -> String { + if self.role == Role::Verifier { + let exprs = self + .field_exprs + .iter() + .map(|expr| { + format!( + " Stage2FieldExprPlan {{ symbol: {}, kind: {}, formula: {}, operands: {} }},", + rust_str(&expr.symbol), + rust_str(&expr.kind), + rust_str(&expr.formula), + rust_str(&expr.operands.join("|")) + ) + }) + .collect::>() + .join("\n"); + return format!( + "pub const STAGE2_FIELD_EXPRS: &[Stage2FieldExprPlan] = &[\n{exprs}\n];\n" + ); + } + + let mut source = String::new(); + let mut arrays = Vec::new(); + let mut array_refs = Vec::new(); + for (index, expr) in self.field_exprs.iter().enumerate() { + let operands = intern_str_array( + &mut source, + &mut arrays, + "STAGE2_FIELD_EXPR_OPERANDS", + &expr.operands, + ); + let operand_names = intern_str_array( + &mut source, + &mut arrays, + "STAGE2_FIELD_EXPR_OPERANDS", + &expr.operand_names, + ); + array_refs.push((index, operand_names, operands)); + } + let exprs = self + .field_exprs + .iter() + .enumerate() + .map(|(index, expr)| { + let (_, operand_names, operands) = &array_refs[index]; + format!( + " Stage2FieldExprPlan {{ symbol: {}, kind: {}, formula: {}, operand_names: {operand_names}, operands: {operands} }},", + rust_str(&expr.symbol), + rust_str(&expr.kind), + rust_str(&expr.formula) + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE2_FIELD_EXPRS: &[Stage2FieldExprPlan] = &[\n{exprs}\n];\n" + ), + ); + source + } + + fn emit_kernel_constants(&self) -> String { + let kernels = self + .kernels + .iter() + .map(|kernel| { + format!( + " Stage2KernelPlan {{ symbol: {}, relation: {}, kind: {}, backend: {}, abi: {} }},", + rust_str(&kernel.symbol), + rust_str(&kernel.relation), + rust_str(&kernel.kind), + rust_str(&kernel.backend), + rust_str(&kernel.abi) + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE2_KERNELS: &[Stage2KernelPlan] = &[\n{kernels}\n];\n\n") + } + + fn emit_prover_sumcheck_claim_constants(&self) -> Result { + self.emit_sumcheck_claim_constants(true) + } + + fn emit_verifier_sumcheck_claim_constants(&self) -> Result { + self.emit_sumcheck_claim_constants(false) + } + + fn emit_sumcheck_claim_constants(&self, prover: bool) -> Result { + let mut source = String::new(); + if prover { + for (index, claim) in self.claims.iter().enumerate() { + source.push_str(&emit_str_array( + &format!("STAGE2_SUMCHECK_CLAIM_{index}_INPUT_OPENINGS"), + &claim.input_openings, + )); + } + } + let mut claims = Vec::new(); + for (index, claim) in self.claims.iter().enumerate() { + if prover { + let kernel = claim + .kernel + .as_deref() + .ok_or_else(|| missing_role_binding("prover claim kernel", &claim.symbol))?; + claims.push(format!( + " Stage2SumcheckClaimPlan {{ symbol: {}, stage: {}, domain: {}, num_rounds: {}, degree: {}, claim: {}, kernel: Some({}), relation: None, claim_value: {}, input_openings: STAGE2_SUMCHECK_CLAIM_{index}_INPUT_OPENINGS }},", + rust_str(&claim.symbol), + rust_str(&claim.stage), + rust_str(&claim.domain), + claim.num_rounds, + claim.degree, + rust_str(&claim.claim), + rust_str(kernel), + rust_str(&claim.claim_value) + )); + } else { + let relation = claim.relation.as_deref().ok_or_else(|| { + missing_role_binding("verifier claim relation", &claim.symbol) + })?; + claims.push(format!( + " Stage2SumcheckClaimPlan {{ symbol: {}, stage: {}, domain: {}, num_rounds: {}, degree: {}, claim: {}, kernel: None, relation: Some({}), claim_value: {}, input_openings: {} }},", + rust_str(&claim.symbol), + rust_str(&claim.stage), + rust_str(&claim.domain), + claim.num_rounds, + claim.degree, + rust_str(&claim.claim), + rust_str(relation), + rust_str(&claim.claim_value), + rust_str(&claim.input_openings.join("|")) + )); + } + } + let claims = claims.join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE2_SUMCHECK_CLAIMS: &[Stage2SumcheckClaimPlan] = &[\n{claims}\n];\n" + ), + ); + Ok(source) + } + + fn emit_sumcheck_batch_constants(&self) -> String { + if self.role == Role::Verifier { + let mut source = String::new(); + for (index, batch) in self.batches.iter().enumerate() { + source.push_str(&emit_usize_array( + &format!("STAGE2_SUMCHECK_BATCH_{index}_ROUND_SCHEDULE"), + &batch.round_schedule, + )); + } + let batches = self + .batches + .iter() + .enumerate() + .map(|(index, batch)| { + format!( + " Stage2SumcheckBatchPlan {{ symbol: {}, stage: {}, proof_slot: {}, policy: {}, count: {}, ordered_claims: {}, claim_operands: {}, claim_label: {}, round_label: {}, round_schedule: STAGE2_SUMCHECK_BATCH_{index}_ROUND_SCHEDULE }},", + rust_str(&batch.symbol), + rust_str(&batch.stage), + rust_str(&batch.proof_slot), + rust_str(&batch.policy), + batch.count, + rust_str(&batch.ordered_claims.join("|")), + rust_str(&batch.claim_operands.join("|")), + rust_str(&batch.claim_label), + rust_str(&batch.round_label) + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE2_SUMCHECK_BATCHES: &[Stage2SumcheckBatchPlan] = &[\n{batches}\n];\n" + ), + ); + return source; + } + + let mut source = String::new(); + for (index, batch) in self.batches.iter().enumerate() { + source.push_str(&emit_str_array( + &format!("STAGE2_SUMCHECK_BATCH_{index}_ORDERED_CLAIMS"), + &batch.ordered_claims, + )); + source.push_str(&emit_str_array( + &format!("STAGE2_SUMCHECK_BATCH_{index}_CLAIM_OPERANDS"), + &batch.claim_operands, + )); + source.push_str(&emit_usize_array( + &format!("STAGE2_SUMCHECK_BATCH_{index}_ROUND_SCHEDULE"), + &batch.round_schedule, + )); + } + let batches = self + .batches + .iter() + .enumerate() + .map(|(index, batch)| { + format!( + " Stage2SumcheckBatchPlan {{ symbol: {}, stage: {}, proof_slot: {}, policy: {}, count: {}, ordered_claims: STAGE2_SUMCHECK_BATCH_{index}_ORDERED_CLAIMS, claim_operands: STAGE2_SUMCHECK_BATCH_{index}_CLAIM_OPERANDS, claim_label: {}, round_label: {}, round_schedule: STAGE2_SUMCHECK_BATCH_{index}_ROUND_SCHEDULE }},", + rust_str(&batch.symbol), + rust_str(&batch.stage), + rust_str(&batch.proof_slot), + rust_str(&batch.policy), + batch.count, + rust_str(&batch.claim_label), + rust_str(&batch.round_label) + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE2_SUMCHECK_BATCHES: &[Stage2SumcheckBatchPlan] = &[\n{batches}\n];\n" + ), + ); + source + } + + fn emit_prover_sumcheck_driver_constants(&self) -> Result { + self.emit_sumcheck_driver_constants(true) + } + + fn emit_verifier_sumcheck_driver_constants(&self) -> Result { + self.emit_sumcheck_driver_constants(false) + } + + fn emit_sumcheck_driver_constants(&self, prover: bool) -> Result { + let mut source = String::new(); + for (index, driver) in self.drivers.iter().enumerate() { + source.push_str(&emit_usize_array( + &format!("STAGE2_SUMCHECK_DRIVER_{index}_ROUND_SCHEDULE"), + &driver.round_schedule, + )); + } + let mut drivers = Vec::new(); + for (index, driver) in self.drivers.iter().enumerate() { + if prover { + let kernel = driver + .kernel + .as_deref() + .ok_or_else(|| missing_role_binding("prover driver kernel", &driver.symbol))?; + drivers.push(format!( + " Stage2SumcheckDriverPlan {{ symbol: {}, stage: {}, proof_slot: {}, kernel: Some({}), relation: None, batch: {}, policy: {}, round_schedule: STAGE2_SUMCHECK_DRIVER_{index}_ROUND_SCHEDULE, claim_label: {}, round_label: {}, num_rounds: {}, degree: {} }},", + rust_str(&driver.symbol), + rust_str(&driver.stage), + rust_str(&driver.proof_slot), + rust_str(kernel), + rust_str(&driver.batch), + rust_str(&driver.policy), + rust_str(&driver.claim_label), + rust_str(&driver.round_label), + driver.num_rounds, + driver.degree + )); + } else { + let relation = driver.relation.as_deref().ok_or_else(|| { + missing_role_binding("verifier driver relation", &driver.symbol) + })?; + drivers.push(format!( + " Stage2SumcheckDriverPlan {{ symbol: {}, stage: {}, proof_slot: {}, kernel: None, relation: Some({}), batch: {}, policy: {}, round_schedule: STAGE2_SUMCHECK_DRIVER_{index}_ROUND_SCHEDULE, claim_label: {}, round_label: {}, num_rounds: {}, degree: {} }},", + rust_str(&driver.symbol), + rust_str(&driver.stage), + rust_str(&driver.proof_slot), + rust_str(relation), + rust_str(&driver.batch), + rust_str(&driver.policy), + rust_str(&driver.claim_label), + rust_str(&driver.round_label), + driver.num_rounds, + driver.degree + )); + } + } + let drivers = drivers.join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE2_SUMCHECK_DRIVERS: &[Stage2SumcheckDriverPlan] = &[\n{drivers}\n];\n" + ), + ); + Ok(source) + } + + fn emit_tail_constants(&self) -> String { + let mut source = String::new(); + source.push_str(&self.emit_sumcheck_instance_result_constants()); + source.push_str(&self.emit_sumcheck_eval_constants()); + source.push_str(&self.emit_point_slice_constants()); + source.push_str(&self.emit_point_concat_constants()); + source.push_str(&self.emit_opening_claim_constants()); + source.push_str(&self.emit_opening_batch_constants()); + source + } + + fn emit_sumcheck_instance_result_constants(&self) -> String { + let instances = self + .instance_results + .iter() + .map(|instance| { + format!( + " Stage2SumcheckInstanceResultPlan {{ symbol: {}, source: {}, claim: {}, relation: {}, index: {}, point_arity: {}, num_rounds: {}, round_offset: {}, point_order: {}, degree: {} }},", + rust_str(&instance.symbol), + rust_str(&instance.source), + rust_str(&instance.claim), + rust_str(&instance.relation), + instance.index, + instance.point_arity, + instance.num_rounds, + instance.round_offset, + rust_str(&instance.point_order), + instance.degree + ) + }) + .collect::>() + .join("\n"); + format!( + "pub const STAGE2_SUMCHECK_INSTANCE_RESULTS: &[Stage2SumcheckInstanceResultPlan] = &[\n{instances}\n];\n\n" + ) + } + + fn emit_sumcheck_eval_constants(&self) -> String { + let evals = self + .evals + .iter() + .map(|eval| { + format!( + " Stage2SumcheckEvalPlan {{ symbol: {}, source: {}, name: {}, index: {}, oracle: {} }},", + rust_str(&eval.symbol), + rust_str(&eval.source), + rust_str(&eval.name), + eval.index, + rust_str(&eval.oracle) + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE2_SUMCHECK_EVALS: &[Stage2SumcheckEvalPlan] = &[\n{evals}\n];\n\n") + } + + fn emit_point_slice_constants(&self) -> String { + let slices = self + .point_slices + .iter() + .map(|slice| { + format!( + " Stage2PointSlicePlan {{ symbol: {}, source: {}, offset: {}, length: {}, input: {} }},", + rust_str(&slice.symbol), + rust_str(&slice.source), + slice.offset, + slice.length, + rust_str(&slice.input) + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE2_POINT_SLICES: &[Stage2PointSlicePlan] = &[\n{slices}\n];\n\n") + } + + fn emit_point_concat_constants(&self) -> String { + if self.role == Role::Verifier { + let concats = self + .point_concats + .iter() + .map(|concat| { + format!( + " Stage2PointConcatPlan {{ symbol: {}, layout: {}, arity: {}, inputs: {} }},", + rust_str(&concat.symbol), + rust_str(&concat.layout), + concat.arity, + rust_str(&concat.inputs.join("|")) + ) + }) + .collect::>() + .join("\n"); + return format!( + "pub const STAGE2_POINT_CONCATS: &[Stage2PointConcatPlan] = &[\n{concats}\n];\n" + ); + } + + let mut source = String::new(); + for (index, concat) in self.point_concats.iter().enumerate() { + source.push_str(&emit_str_array( + &format!("STAGE2_POINT_CONCAT_{index}_INPUTS"), + &concat.inputs, + )); + } + let concats = self + .point_concats + .iter() + .enumerate() + .map(|(index, concat)| { + format!( + " Stage2PointConcatPlan {{ symbol: {}, layout: {}, arity: {}, inputs: STAGE2_POINT_CONCAT_{index}_INPUTS }},", + rust_str(&concat.symbol), + rust_str(&concat.layout), + concat.arity + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE2_POINT_CONCATS: &[Stage2PointConcatPlan] = &[\n{concats}\n];\n" + ), + ); + source + } + + fn emit_opening_claim_constants(&self) -> String { + let claims = self + .opening_claims + .iter() + .map(|claim| { + format!( + " Stage2OpeningClaimPlan {{ symbol: {}, oracle: {}, domain: {}, point_arity: {}, claim_kind: {}, point_source: {}, eval_source: {} }},", + rust_str(&claim.symbol), + rust_str(&claim.oracle), + rust_str(&claim.domain), + claim.point_arity, + rust_str(&claim.claim_kind), + rust_str(&claim.point_source), + rust_str(&claim.eval_source) + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE2_OPENING_CLAIMS: &[Stage2OpeningClaimPlan] = &[\n{claims}\n];\n\n") + } + + fn emit_opening_batch_constants(&self) -> String { + if self.role == Role::Verifier { + let batches = self + .opening_batches + .iter() + .map(|batch| { + format!( + " Stage2OpeningBatchPlan {{ symbol: {}, stage: {}, proof_slot: {}, policy: {}, count: {}, ordered_claims: {}, claim_operands: {} }},", + rust_str(&batch.symbol), + rust_str(&batch.stage), + rust_str(&batch.proof_slot), + rust_str(&batch.policy), + batch.count, + rust_str(&batch.ordered_claims.join("|")), + rust_str(&batch.claim_operands.join("|")) + ) + }) + .collect::>() + .join("\n"); + return format!( + "pub const STAGE2_OPENING_BATCHES: &[Stage2OpeningBatchPlan] = &[\n{batches}\n];\n" + ); + } + + let mut source = String::new(); + for (index, batch) in self.opening_batches.iter().enumerate() { + source.push_str(&emit_str_array( + &format!("STAGE2_OPENING_BATCH_{index}_ORDERED_CLAIMS"), + &batch.ordered_claims, + )); + source.push_str(&emit_str_array( + &format!("STAGE2_OPENING_BATCH_{index}_CLAIM_OPERANDS"), + &batch.claim_operands, + )); + } + let batches = self + .opening_batches + .iter() + .enumerate() + .map(|(index, batch)| { + format!( + " Stage2OpeningBatchPlan {{ symbol: {}, stage: {}, proof_slot: {}, policy: {}, count: {}, ordered_claims: STAGE2_OPENING_BATCH_{index}_ORDERED_CLAIMS, claim_operands: STAGE2_OPENING_BATCH_{index}_CLAIM_OPERANDS }},", + rust_str(&batch.symbol), + rust_str(&batch.stage), + rust_str(&batch.proof_slot), + rust_str(&batch.policy), + batch.count + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE2_OPENING_BATCHES: &[Stage2OpeningBatchPlan] = &[\n{batches}\n];\n" + ), + ); + source + } + + fn emit_prover_entrypoint() -> &'static str { + "pub fn execute_stage2_prover(\n\ + \x20 executor: &mut E,\n\ + \x20 transcript: &mut T,\n\ + ) -> Result, Stage2KernelError>\n\ + where\n\ + \x20 E: Stage2KernelExecutor,\n\ + \x20 T: Transcript,\n\ + {\n\ + \x20 execute_stage2_prover_with_program(&STAGE2_PROGRAM, executor, transcript)\n\ + }\n\ + \n\ + pub fn execute_stage2_prover_with_program(\n\ + \x20 program: &'static Stage2CpuProgramPlan,\n\ + \x20 executor: &mut E,\n\ + \x20 transcript: &mut T,\n\ + ) -> Result, Stage2KernelError>\n\ + where\n\ + \x20 E: Stage2KernelExecutor,\n\ + \x20 T: Transcript,\n\ + {\n\ + \x20 execute_stage2_program(program, Stage2ExecutionMode::Prover, executor, transcript)\n\ + }\n" + } + + fn emit_verifier_entrypoint() -> &'static str { + r#"const PRODUCT_VIRTUAL_UNISKIP_DOMAIN_START: i64 = -1; +const PRODUCT_VIRTUAL_UNISKIP_DOMAIN_SIZE: usize = 3; + +pub fn verify_stage2( + proof: &Stage2Proof, + opening_inputs: &[Stage2OpeningInputValue], + ram: Option<&Stage2RamData<'_>>, + transcript: &mut T, +) -> Result, VerifyStage2Error> +where + T: Transcript, +{ + verify_stage2_with_program(&STAGE2_PROGRAM, proof, opening_inputs, ram, transcript) +} + +pub fn verify_stage2_with_program( + program: &'static Stage2VerifierProgramPlan, + proof: &Stage2Proof, + opening_inputs: &[Stage2OpeningInputValue], + ram: Option<&Stage2RamData<'_>>, + transcript: &mut T, +) -> Result, VerifyStage2Error> +where + T: Transcript, +{ + if proof.sumchecks.len() != program.drivers.len() { + return Err(VerifyStage2Error::UnexpectedProofCount { + expected: program.drivers.len(), + got: proof.sumchecks.len(), + }); + } + let mut store = Stage2ValueStore::with_opening_inputs(program, opening_inputs)?; + store.seed_constants(program); + let mut artifacts = Stage2ExecutionArtifacts::default(); + if program.steps.is_empty() { + for squeeze in program.transcript_squeezes { + verify_stage2_squeeze(program, squeeze, &mut store, transcript, &mut artifacts)?; + } + for driver in program.drivers { + verify_stage2_driver(program, driver, proof, ram, &mut store, transcript, &mut artifacts)?; + } + } else { + for step in program.steps { + match step.kind { + "transcript_squeeze" => { + let squeeze = find_plan(program.transcript_squeezes, step.symbol).ok_or(VerifyStage2Error::MissingValue { + symbol: step.symbol, + })?; + verify_stage2_squeeze(program, squeeze, &mut store, transcript, &mut artifacts)?; + } + "sumcheck_driver" => { + let driver = find_plan(program.drivers, step.symbol).ok_or(VerifyStage2Error::MissingProof { + driver: step.symbol, + })?; + verify_stage2_driver(program, driver, proof, ram, &mut store, transcript, &mut artifacts)?; + } + _ => { + return Err(VerifyStage2Error::InvalidProof { + driver: step.symbol, + reason: "unsupported stage2 program step", + }); + } + } + } + } + artifacts + .opening_batches + .extend(program.opening_batches.iter()); + Ok(artifacts) +} + +pub fn stage2_verifier_program() -> &'static Stage2VerifierProgramPlan { + &STAGE2_PROGRAM +} + +fn verify_stage2_squeeze( + program: &'static Stage2VerifierProgramPlan, + squeeze: &'static Stage2TranscriptSqueezePlan, + store: &mut Stage2ValueStore, + transcript: &mut T, + artifacts: &mut Stage2ExecutionArtifacts, +) -> Result<(), VerifyStage2Error> +where + T: Transcript, +{ + let values = transcript.challenge_vector(squeeze.count); + store.observe_challenge_vector(program, squeeze, &values)?; + artifacts.challenge_vectors.push(Stage2ChallengeVector { + symbol: squeeze.symbol, + values, + }); + Ok(()) +} + +fn verify_stage2_driver( + program: &'static Stage2VerifierProgramPlan, + driver: &'static Stage2SumcheckDriverPlan, + proof: &Stage2Proof, + ram: Option<&Stage2RamData<'_>>, + store: &mut Stage2ValueStore, + transcript: &mut T, + artifacts: &mut Stage2ExecutionArtifacts, +) -> Result<(), VerifyStage2Error> +where + T: Transcript, +{ + let proof = proof + .sumchecks + .get(artifacts.sumchecks.len()) + .ok_or(VerifyStage2Error::MissingProof { + driver: driver.symbol, + })?; + let relation = driver.relation.unwrap_or(""); + let output = match relation { + "jolt.stage2.product_virtual.uniskip" => { + verify_product_virtual_uniskip(program, driver, proof, store, transcript)? + } + "jolt.stage2.batched" => verify_batched_stage2(program, driver, proof, ram, store, transcript)?, + relation => return Err(VerifyStage2Error::UnsupportedRelation { relation }), + }; + artifacts.sumchecks.push(output); + Ok(()) +} + +fn verify_product_virtual_uniskip( + program: &'static Stage2VerifierProgramPlan, + driver: &'static Stage2SumcheckDriverPlan, + proof: &Stage2SumcheckOutput, + store: &mut Stage2ValueStore, + transcript: &mut T, +) -> Result, VerifyStage2Error> +where + T: Transcript, +{ + validate_driver_symbol(driver, proof)?; + let [poly] = proof.proof.round_polynomials.as_slice() else { + return Err(VerifyStage2Error::InvalidProof { + driver: driver.symbol, + reason: "unexpected product uniskip round count", + }); + }; + if polynomial_degree(poly) > driver.degree { + return Err(VerifyStage2Error::InvalidProof { + driver: driver.symbol, + reason: "product uniskip polynomial exceeds degree bound", + }); + } + let batch = find_batch(program.batches, driver.symbol, driver.batch)?; + let claim = batch_claims(program.claims, batch)? + .into_iter() + .next() + .ok_or(VerifyStage2Error::MissingClaim { + batch: batch.symbol, + claim: "stage2.product_virtual.uniskip.input", + })?; + let input_claim = store.claim_value(program, claim)?; + if !product_uniskip_sum_matches(poly, input_claim) { + return Err(VerifyStage2Error::InvalidProof { + driver: driver.symbol, + reason: "product uniskip input claim mismatch", + }); + } + append_univariate_poly(transcript, driver.round_label, poly); + let r0 = transcript.challenge(); + if !proof.point.is_empty() && proof.point != [r0] { + return Err(VerifyStage2Error::InvalidProof { + driver: driver.symbol, + reason: "product uniskip point mismatch", + }); + } + let eval = poly.evaluate(r0); + append_labeled_scalar(transcript, "opening_claim", &eval); + let output = Stage2SumcheckOutput { + driver: driver.symbol, + point: vec![r0], + evals: driver_evals(program, driver.symbol, eval), + proof: proof.proof.clone(), + }; + verify_named_evals(driver.symbol, &output.evals, &proof.evals)?; + store.observe_sumcheck_output(program, &output)?; + Ok(output) +} + +fn verify_batched_stage2( + program: &'static Stage2VerifierProgramPlan, + driver: &'static Stage2SumcheckDriverPlan, + proof: &Stage2SumcheckOutput, + ram: Option<&Stage2RamData<'_>>, + store: &mut Stage2ValueStore, + transcript: &mut T, +) -> Result, VerifyStage2Error> +where + T: Transcript, +{ + validate_driver_symbol(driver, proof)?; + let batch = find_batch(program.batches, driver.symbol, driver.batch)?; + let claims = batch_claims(program.claims, batch)?; + let input_claims = store.batch_claim_values(program, batch)?; + for claim in &input_claims { + append_labeled_scalar(transcript, batch.claim_label, claim); + } + let batching_coeffs = transcript.challenge_vector(claims.len()); + let claimed_sum = input_claims + .iter() + .zip(claims.iter()) + .zip(&batching_coeffs) + .map(|((claim, plan), coefficient)| { + claim.mul_pow_2(driver.num_rounds - plan.num_rounds) * *coefficient + }) + .sum::(); + let claim = SumcheckClaim::new(driver.num_rounds, driver.degree, claimed_sum); + let round_proofs = proof + .proof + .round_polynomials + .iter() + .map(|poly| CompressedLabeledRoundPoly::new(poly, driver.round_label.as_bytes())) + .collect::>(); + let output = SumcheckVerifier::verify(&claim, &round_proofs, transcript) + .map_err(|error| VerifyStage2Error::Sumcheck { + driver: driver.symbol, + error, + })?; + if !proof.point.is_empty() && proof.point != output.point { + return Err(VerifyStage2Error::InvalidProof { + driver: driver.symbol, + reason: "batched point mismatch", + }); + } + let expected = + expected_batched_output_claim(program, driver, &*store, &proof.evals, &output.point, &batching_coeffs, ram)?; + if output.value != expected { + return Err(VerifyStage2Error::InvalidProof { + driver: driver.symbol, + reason: "batched output claim mismatch", + }); + } + let verified = Stage2SumcheckOutput { + driver: driver.symbol, + point: output.point, + evals: proof.evals.clone(), + proof: proof.proof.clone(), + }; + store.observe_sumcheck_output(program, &verified)?; + super::common::append_opening_claims( + program.opening_inputs, + program.opening_claims, + program.opening_batches, + &mut store.0, + transcript, + &verified.evals, + |batch, claim| VerifyStage2Error::MissingClaim { batch, claim }, + |symbol| VerifyStage2Error::MissingValue { symbol }, + )?; + Ok(verified) +} + +impl Stage2ValueStore { + fn with_opening_inputs( + program: &'static Stage2VerifierProgramPlan, + inputs: &[Stage2OpeningInputValue], + ) -> Result { + Ok(Self(super::common::ValueStore::with_opening_inputs( + inputs, + program.opening_inputs, + )?)) + } + + fn seed_constants(&mut self, program: &'static Stage2VerifierProgramPlan) { + self.0.seed_constants(program.field_constants); + } + + fn observe_challenge_vector( + &mut self, + program: &'static Stage2VerifierProgramPlan, + plan: &'static Stage2TranscriptSqueezePlan, + values: &[F], + ) -> Result<(), VerifyStage2Error> { + self.0.observe_challenge_vector(plan, values, |input, expected, actual| { + VerifyStage2Error::InvalidInputLength { input, expected, actual } + })?; + self.evaluate_available_points(program)?; + self.evaluate_available_field_exprs(program)?; + Ok(()) + } + + fn observe_sumcheck_output( + &mut self, + program: &'static Stage2VerifierProgramPlan, + output: &Stage2SumcheckOutput, + ) -> Result<(), VerifyStage2Error> { + self.0.observe_sumcheck_output( + program.instance_results, + program.evals, + output, + |instance, mut point| { + match instance.point_order { + "as_is" => {} + "reverse" => point.reverse(), + _ => { + return Err(VerifyStage2Error::InvalidProof { + driver: output.driver, + reason: "unsupported point order", + }); + } + } + Ok(point) + }, + |input, expected, actual| VerifyStage2Error::InvalidInputLength { + input, + expected, + actual, + }, + |symbol| VerifyStage2Error::MissingValue { symbol }, + )?; + self.evaluate_available_points(program)?; + self.evaluate_available_field_exprs(program)?; + Ok(()) + } + + fn claim_value( + &mut self, + program: &'static Stage2VerifierProgramPlan, + claim: &Stage2SumcheckClaimPlan, + ) -> Result { + self.evaluate_available_field_exprs(program)?; + self.scalar(claim.claim_value) + } + + fn batch_claim_values( + &mut self, + program: &'static Stage2VerifierProgramPlan, + batch: &Stage2SumcheckBatchPlan, + ) -> Result, VerifyStage2Error> { + super::common::symbol_list(batch.claim_operands) + .map(|symbol| { + let claim = find_plan(program.claims, symbol).ok_or(VerifyStage2Error::MissingClaim { + batch: batch.symbol, + claim: symbol, + })?; + self.claim_value(program, claim) + }) + .collect() + } + + fn evaluate_available_points( + &mut self, + program: &'static Stage2VerifierProgramPlan, + ) -> Result<(), VerifyStage2Error> { + self.0.evaluate_available_points( + program.point_slices, + program.point_concats, + |input, expected, actual| VerifyStage2Error::InvalidInputLength { + input, + expected, + actual, + }, + ) + } + + fn evaluate_available_field_exprs( + &mut self, + program: &'static Stage2VerifierProgramPlan, + ) -> Result<(), VerifyStage2Error> { + self.0 + .evaluate_available_field_exprs(program.field_exprs, evaluate_stage2_field_expr) + } + + fn scalar(&self, symbol: &'static str) -> Result { + self.0 + .scalar_or(symbol, |symbol| VerifyStage2Error::MissingValue { symbol }) + } + + fn point(&self, symbol: &'static str) -> Result<&[F], VerifyStage2Error> { + self.0 + .point_or(symbol, |symbol| VerifyStage2Error::MissingValue { symbol }) + } + + fn try_point(&self, symbol: &str) -> Option<&[F]> { + self.0.try_point(symbol) + } +} + +fn evaluate_stage2_field_expr( + expr: &Stage2FieldExprPlan, + operands: &[F], +) -> Result { + match expr.formula { + "opening_eval" => Ok(single_operand(expr.symbol, operands)?), + "jolt_stage2_product_virtual_uniskip_input" => { + require_operand_count(expr.symbol, 4, operands.len())?; + let weights = lagrange_evals( + PRODUCT_VIRTUAL_UNISKIP_DOMAIN_START, + PRODUCT_VIRTUAL_UNISKIP_DOMAIN_SIZE, + operands[0], + ); + Ok(weights[0] * operands[1] + weights[1] * operands[2] + weights[2] * operands[3]) + } + "jolt_stage2_ram_read_write_input" => { + require_operand_count(expr.symbol, 3, operands.len())?; + Ok(operands[1] + operands[0] * operands[2]) + } + "jolt_stage2_instruction_lookup_input" => { + require_operand_count(expr.symbol, 6, operands.len())?; + let gamma = operands[0]; + let gamma2 = gamma.square(); + let gamma3 = gamma2 * gamma; + let gamma4 = gamma2.square(); + Ok(operands[1] + + gamma * operands[2] + + gamma2 * operands[3] + + gamma3 * operands[4] + + gamma4 * operands[5]) + } + "field.add" => { + require_operand_count(expr.symbol, 2, operands.len())?; + Ok(operands[0] + operands[1]) + } + "field.sub" => { + require_operand_count(expr.symbol, 2, operands.len())?; + Ok(operands[0] - operands[1]) + } + "field.mul" => { + require_operand_count(expr.symbol, 2, operands.len())?; + Ok(operands[0] * operands[1]) + } + "field.neg" => { + require_operand_count(expr.symbol, 1, operands.len())?; + Ok(-operands[0]) + } + formula => { + if let Some(exponent) = formula.strip_prefix("field.pow:") { + require_operand_count(expr.symbol, 1, operands.len())?; + let exponent = exponent.parse::().map_err(|_| { + VerifyStage2Error::UnsupportedFieldExpr { + symbol: expr.symbol, + formula, + } + })?; + return Ok(pow_field(operands[0], exponent)); + } + if let Some(spec) = formula.strip_prefix("poly.lagrange_basis_eval:") { + require_operand_count(expr.symbol, 1, operands.len())?; + let parts = spec.split(':').collect::>(); + if parts.len() != 3 { + return Err(VerifyStage2Error::UnsupportedFieldExpr { + symbol: expr.symbol, + formula, + }); + } + let domain_start = parts[0].parse::().map_err(|_| { + VerifyStage2Error::UnsupportedFieldExpr { + symbol: expr.symbol, + formula, + } + })?; + let domain_size = parts[1].parse::().map_err(|_| { + VerifyStage2Error::UnsupportedFieldExpr { + symbol: expr.symbol, + formula, + } + })?; + let index = parts[2].parse::().map_err(|_| { + VerifyStage2Error::UnsupportedFieldExpr { + symbol: expr.symbol, + formula, + } + })?; + let weights = lagrange_evals(domain_start, domain_size, operands[0]); + return weights + .get(index) + .copied() + .ok_or(VerifyStage2Error::InvalidInputLength { + input: expr.symbol, + expected: index + 1, + actual: weights.len(), + }); + } + Err(VerifyStage2Error::UnsupportedFieldExpr { + symbol: expr.symbol, + formula, + }) + } + } +} + +fn expected_batched_output_claim( + program: &'static Stage2VerifierProgramPlan, + driver: &'static Stage2SumcheckDriverPlan, + store: &Stage2ValueStore, + evals: &[Stage2NamedEval], + point: &[Fr], + batching_coeffs: &[Fr], + ram: Option<&Stage2RamData<'_>>, +) -> Result { + let batch = find_batch(program.batches, driver.symbol, driver.batch)?; + let claims = batch_claims(program.claims, batch)?; + let mut expected = Fr::from_u64(0); + for (claim, coefficient) in claims.iter().zip(batching_coeffs) { + let instance = program + .instance_results + .iter() + .find(|instance| instance.claim == claim.symbol && instance.source == driver.symbol) + .ok_or(VerifyStage2Error::MissingClaim { + batch: batch.symbol, + claim: claim.symbol, + })?; + let local_point = point + .get(instance.round_offset..instance.round_offset + instance.num_rounds) + .ok_or(VerifyStage2Error::InvalidInputLength { + input: instance.symbol, + expected: instance.round_offset + instance.num_rounds, + actual: point.len(), + })?; + let value = match instance.relation { + "jolt.stage2.ram.read_write" => expected_ram_read_write(store, evals, local_point)?, + "jolt.stage2.product_virtual.remainder" => { + expected_product_remainder(store, evals, local_point)? + } + "jolt.stage2.instruction_lookup.claim_reduction" => { + expected_instruction_lookup(store, evals, local_point)? + } + "jolt.stage2.ram.raf_evaluation" => expected_ram_raf(evals, local_point, ram)?, + "jolt.stage2.ram.output_check" => expected_ram_output(store, evals, local_point, ram)?, + relation => return Err(VerifyStage2Error::UnsupportedRelation { relation }), + }; + expected += *coefficient * value; + } + Ok(expected) +} + +fn expected_ram_read_write( + store: &Stage2ValueStore, + evals: &[Stage2NamedEval], + local_point: &[Fr], +) -> Result { + let r_cycle_stage1 = store.point("stage2.input.stage1.RamReadValue")?; + let log_t = r_cycle_stage1.len(); + let r_cycle = reverse_slice(&local_point[..log_t]); + let eq_eval = EqPolynomial::::mle(r_cycle_stage1, &r_cycle); + let gamma = store.scalar("stage2.ram_read_write.gamma")?; + let val = eval_by_name(evals, "stage2.ram_read_write.eval.RamVal")?; + let ra = eval_by_name(evals, "stage2.ram_read_write.eval.RamRa")?; + let inc = eval_by_name(evals, "stage2.ram_read_write.eval.RamInc")?; + Ok(eq_eval * ra * (val + gamma * (val + inc))) +} + +fn expected_product_remainder( + store: &Stage2ValueStore, + evals: &[Stage2NamedEval], + local_point: &[Fr], +) -> Result { + let tau_low = store.point("stage2.input.stage1.Product")?; + let tau_high = store.scalar("stage2.product_virtual.tau_high")?; + let r0 = *store + .point("stage2.product_virtual.uniskip.sumcheck")? + .first() + .ok_or(VerifyStage2Error::MissingValue { + symbol: "stage2.product_virtual.uniskip.sumcheck", + })?; + let r_tail = reverse_slice(local_point); + let low = EqPolynomial::::mle(tau_low, &r_tail); + let high = lagrange_kernel_eval( + PRODUCT_VIRTUAL_UNISKIP_DOMAIN_START, + PRODUCT_VIRTUAL_UNISKIP_DOMAIN_SIZE, + tau_high, + r0, + ); + let weights = lagrange_evals( + PRODUCT_VIRTUAL_UNISKIP_DOMAIN_START, + PRODUCT_VIRTUAL_UNISKIP_DOMAIN_SIZE, + r0, + ); + let left = weights[0] + * eval_by_name(evals, "stage2.product_virtual.remainder.eval.LeftInstructionInput")? + + weights[1] * eval_by_name(evals, "stage2.product_virtual.remainder.eval.LookupOutput")? + + weights[2] * eval_by_name(evals, "stage2.product_virtual.remainder.eval.OpFlagJump")?; + let right = weights[0] + * eval_by_name(evals, "stage2.product_virtual.remainder.eval.RightInstructionInput")? + + weights[1] + * eval_by_name(evals, "stage2.product_virtual.remainder.eval.InstructionFlagBranch")? + + weights[2] + * (Fr::from_u64(1) + - eval_by_name(evals, "stage2.product_virtual.remainder.eval.NextIsNoop")?); + Ok(high * low * left * right) +} + +fn expected_instruction_lookup( + store: &Stage2ValueStore, + evals: &[Stage2NamedEval], + local_point: &[Fr], +) -> Result { + let opening_point = reverse_slice(local_point); + let r_spartan = store.point("stage2.input.stage1.LookupOutput")?; + let eq_eval = EqPolynomial::::mle(&opening_point, r_spartan); + let gamma = store.scalar("stage2.instruction_lookup.gamma")?; + let gamma2 = gamma.square(); + let gamma3 = gamma2 * gamma; + let gamma4 = gamma2.square(); + let weighted = eval_by_name( + evals, + "stage2.instruction_lookup.claim_reduction.eval.LookupOutput", + )? + gamma + * eval_by_name( + evals, + "stage2.instruction_lookup.claim_reduction.eval.LeftLookupOperand", + )? + + gamma2 + * eval_by_name( + evals, + "stage2.instruction_lookup.claim_reduction.eval.RightLookupOperand", + )? + + gamma3 + * eval_by_name( + evals, + "stage2.instruction_lookup.claim_reduction.eval.LeftInstructionInput", + )? + + gamma4 + * eval_by_name( + evals, + "stage2.instruction_lookup.claim_reduction.eval.RightInstructionInput", + )?; + Ok(eq_eval * weighted) +} + +fn expected_ram_raf( + evals: &[Stage2NamedEval], + local_point: &[Fr], + ram: Option<&Stage2RamData<'_>>, +) -> Result { + let ram = ram.ok_or(VerifyStage2Error::MissingRam { + relation: "jolt.stage2.ram.raf_evaluation", + })?; + let address = reverse_slice(local_point); + let unmap = unmap_eval(ram.log_k, ram.start_address, &address); + Ok(unmap * eval_by_name(evals, "stage2.ram_raf.eval.RamRa")?) +} + +fn expected_ram_output( + store: &Stage2ValueStore, + evals: &[Stage2NamedEval], + local_point: &[Fr], + ram: Option<&Stage2RamData<'_>>, +) -> Result { + let ram = ram.ok_or(VerifyStage2Error::MissingRam { + relation: "jolt.stage2.ram.output_check", + })?; + let layout = ram.output_layout.ok_or(VerifyStage2Error::MissingRam { + relation: "jolt.stage2.ram.output_check.layout", + })?; + let r_address = store.point("stage2.ram_output.r_address")?; + let opening_point = reverse_slice(local_point); + let eq_eval = EqPolynomial::::mle(r_address, &opening_point); + let io_mask = range_mask_eval(layout.io_start, layout.io_end, &opening_point); + let val_io = sparse_final_ram_eval( + ram.final_ram, + layout.io_start, + layout.io_end, + &opening_point, + ); + let val_final = eval_by_name(evals, "stage2.ram_output.eval.RamValFinal")?; + Ok(eq_eval * io_mask * (val_final - val_io)) +} + +fn driver_evals( + program: &'static Stage2VerifierProgramPlan, + driver: &'static str, + value: Fr, +) -> Vec> { + program + .evals + .iter() + .filter(|eval| eval.source == driver) + .map(|eval| Stage2NamedEval { + name: eval.name, + oracle: eval.oracle, + value, + }) + .collect() +} + +fn verify_named_evals( + driver: &'static str, + expected: &[Stage2NamedEval], + actual: &[Stage2NamedEval], +) -> Result<(), VerifyStage2Error> { + if expected.len() != actual.len() { + return Err(VerifyStage2Error::InvalidProof { + driver, + reason: "eval count mismatch", + }); + } + for (expected, actual) in expected.iter().zip(actual) { + if expected.name != actual.name || expected.oracle != actual.oracle || expected.value != actual.value { + return Err(VerifyStage2Error::InvalidProof { + driver, + reason: "eval mismatch", + }); + } + } + Ok(()) +} + +fn validate_driver_symbol( + driver: &'static Stage2SumcheckDriverPlan, + proof: &Stage2SumcheckOutput, +) -> Result<(), VerifyStage2Error> { + if proof.driver == driver.symbol { + Ok(()) + } else { + Err(VerifyStage2Error::InvalidProof { + driver: driver.symbol, + reason: "driver symbol mismatch", + }) + } +} + +fn append_univariate_poly(transcript: &mut T, label: &'static str, poly: &UnivariatePoly) +where + T: Transcript, +{ + transcript.append(&LabelWithCount( + label.as_bytes(), + poly.coefficients().len() as u64, + )); + for coefficient in poly.coefficients() { + transcript.append(coefficient); + } +} + +fn product_uniskip_sum_matches(poly: &UnivariatePoly, claim: Fr) -> bool { + (0..PRODUCT_VIRTUAL_UNISKIP_DOMAIN_SIZE) + .map(|index| { + poly.evaluate(Fr::from_i64( + PRODUCT_VIRTUAL_UNISKIP_DOMAIN_START + index as i64, + )) + }) + .sum::() + == claim +} + +fn polynomial_degree(poly: &UnivariatePoly) -> usize { + poly.coefficients() + .iter() + .rposition(|coefficient| *coefficient != Fr::from_u64(0)) + .unwrap_or(0) +} + +fn unmap_eval(log_k: usize, start_address: u64, point: &[Fr]) -> Fr { + point + .iter() + .enumerate() + .fold(Fr::from_u64(start_address), |acc, (index, value)| { + acc + value.mul_pow_2(log_k - 1 - index).mul_u64(8) + }) +} + +fn range_mask_eval(start: usize, end: usize, point: &[Fr]) -> Fr { + eq_prefix_sum(end, point) - eq_prefix_sum(start, point) +} + +fn sparse_final_ram_eval(values: &[u64], start: usize, end: usize, point: &[Fr]) -> Fr { + values[start..end] + .iter() + .enumerate() + .filter(|(_, value)| **value != 0) + .map(|(offset, value)| Fr::from_u64(*value) * eq_eval_at_index(start + offset, point)) + .sum() +} + +fn eq_prefix_sum(end: usize, point: &[Fr]) -> Fr { + let domain_len = 1usize << point.len(); + if end >= domain_len { + return Fr::from_u64(1); + } + let mut sum = Fr::from_u64(0); + let mut prefix = Fr::from_u64(1); + for (bit, r) in point.iter().enumerate() { + let mask = 1usize << (point.len() - 1 - bit); + if end & mask == 0 { + prefix *= Fr::from_u64(1) - *r; + } else { + sum += prefix * (Fr::from_u64(1) - *r); + prefix *= *r; + } + } + sum +} + +fn eq_eval_at_index(index: usize, point: &[Fr]) -> Fr { + point.iter().enumerate().fold(Fr::from_u64(1), |acc, (bit, r)| { + let mask = 1usize << (point.len() - 1 - bit); + if index & mask == 0 { + acc * (Fr::from_u64(1) - *r) + } else { + acc * *r + } + }) +} +"# + } +} + +fn require_supported_symbol(kind: &str, actual: &str, expected: &str) -> Result<(), EmitError> { + if actual == expected { + Ok(()) + } else { + Err(EmitError::new(format!( + "unsupported {kind} @{actual}; expected @{expected}" + ))) + } +} + +fn emit_str_array(name: &str, values: &[String]) -> String { + if values.is_empty() { + return format!("pub const {name}: &[&str] = &[];\n\n"); + } + if let [value] = values { + return format!("pub const {name}: &[&str] = &[{}];\n\n", rust_str(value)); + } + let entries = values + .iter() + .map(|value| format!(" {},", rust_str(value))) + .collect::>() + .join("\n"); + format!("pub const {name}: &[&str] = &[\n{entries}\n];\n\n") +} + +fn emit_usize_array(name: &str, values: &[usize]) -> String { + let entries = values + .iter() + .map(|value| format!(" {value},")) + .collect::>() + .join("\n"); + format!("pub const {name}: &[usize] = &[\n{entries}\n];\n\n") +} + +fn intern_str_array( + source: &mut String, + arrays: &mut Vec<(Vec, String)>, + name_prefix: &str, + values: &[String], +) -> String { + if let Some((_, name)) = arrays + .iter() + .find(|(existing, _)| existing.as_slice() == values) + { + return name.clone(); + } + let name = format!("{name_prefix}_{}", arrays.len()); + source.push_str(&emit_str_array(&name, values)); + arrays.push((values.to_vec(), name.clone())); + name +} + +fn rust_str(value: &str) -> String { + format!("{value:?}") +} + +fn verify_count(kind: &str, symbol: &str, expected: usize, actual: usize) -> Result<(), EmitError> { + if expected == actual { + Ok(()) + } else { + Err(EmitError::new(format!( + "{kind} @{symbol} count mismatch: expected {expected}, got {actual}" + ))) + } +} + +fn missing_role_binding(kind: &str, symbol: &str) -> EmitError { + EmitError::new(format!("missing {kind} for `{symbol}`")) +} + +fn symbols<'a>(values: impl Iterator) -> BTreeSet { + values.cloned().collect() +} + +fn string_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .ok() + .and_then(string_attribute_value) + .ok_or_else(|| attr_error(operation, attr, "string")) +} + +fn symbol_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .ok() + .and_then(symbol_attribute_value) + .ok_or_else(|| attr_error(operation, attr, "symbol")) +} + +fn symbol_array_attr( + operation: OperationRef<'_, '_>, + attr: &str, +) -> Result, EmitError> { + let attribute = operation + .attribute(attr) + .map(|attribute| attribute.to_string()) + .ok() + .ok_or_else(|| attr_error(operation, attr, "symbol array"))?; + parse_symbol_array(&attribute).ok_or_else(|| attr_error(operation, attr, "symbol array")) +} + +fn parse_symbol_array(attribute: &str) -> Option> { + let inner = attribute.strip_prefix('[')?.strip_suffix(']')?.trim(); + if inner.is_empty() { + return Some(Vec::new()); + } + inner + .split(',') + .map(|item| item.trim().strip_prefix('@').map(ToOwned::to_owned)) + .collect() +} + +fn int_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .map(parse_integer_attr) + .ok() + .flatten() + .ok_or_else(|| attr_error(operation, attr, "integer")) +} + +fn signed_int_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .map(parse_signed_integer_attr) + .ok() + .flatten() + .ok_or_else(|| attr_error(operation, attr, "signed integer")) +} + +fn parse_integer_attr(attribute: Attribute<'_>) -> Option { + attribute + .to_string() + .split_whitespace() + .next() + .and_then(|value| value.parse().ok()) +} + +fn parse_signed_integer_attr(attribute: Attribute<'_>) -> Option { + attribute + .to_string() + .split_whitespace() + .next() + .and_then(|value| value.parse().ok()) +} + +fn int_array_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result, EmitError> { + let attribute = operation + .attribute(attr) + .map(|attribute| attribute.to_string()) + .ok() + .ok_or_else(|| attr_error(operation, attr, "integer array"))?; + parse_int_array(&attribute).ok_or_else(|| attr_error(operation, attr, "integer array")) +} + +fn parse_int_array(attribute: &str) -> Option> { + let inner = attribute.strip_prefix('[')?.strip_suffix(']')?.trim(); + if inner.is_empty() { + return Some(Vec::new()); + } + inner + .split(',') + .map(|item| item.trim().parse().ok()) + .collect() +} + +fn operand_symbols( + operation: OperationRef<'_, '_>, + start_index: usize, +) -> Result, EmitError> { + (start_index..operation.operand_count()) + .map(|index| operand_symbol(operation, index)) + .collect() +} + +fn operand_symbol(operation: OperationRef<'_, '_>, index: usize) -> Result { + let operand = operation.operand(index).map_err(|_| { + EmitError::new(format!( + "{} requires operand {index}", + operation_name(operation) + )) + })?; + let owner = OperationResult::try_from(operand).map_err(|_| { + EmitError::new(format!( + "{} operand {index} must be an op result", + operation_name(operation) + )) + })?; + string_attr(owner.owner(), "sym_name") +} + +fn attr_error(operation: OperationRef<'_, '_>, attr: &str, expected: &str) -> EmitError { + EmitError::new(format!( + "{} attr `{attr}` is not a {expected}", + operation_name(operation) + )) +} + +fn operation_name<'c: 'a, 'a>(operation: impl OperationLike<'c, 'a>) -> String { + operation + .name() + .as_string_ref() + .as_str() + .unwrap_or("") + .to_owned() +} diff --git a/crates/bolt/src/protocols/jolt/emit/rust/stage3.rs b/crates/bolt/src/protocols/jolt/emit/rust/stage3.rs new file mode 100644 index 0000000000..936557f08a --- /dev/null +++ b/crates/bolt/src/protocols/jolt/emit/rust/stage3.rs @@ -0,0 +1,2245 @@ +use std::collections::{BTreeMap, BTreeSet}; + +use melior::ir::block::BlockLike; +use melior::ir::operation::{OperationLike, OperationResult}; +use melior::ir::{Attribute, OperationRef}; + +use crate::emit::rust::{push_format, EmitError, RustSourceFile}; +use crate::ir::{string_attribute_value, symbol_attribute_value, BoltModule, Cpu, Role}; +use crate::schema::verify_cpu_schema; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage3CpuProgram { + pub role: Role, + pub params: Stage3Params, + pub steps: Vec, + pub transcript_squeezes: Vec, + pub opening_inputs: Vec, + pub field_constants: Vec, + pub field_exprs: Vec, + pub kernels: Vec, + pub claims: Vec, + pub batches: Vec, + pub drivers: Vec, + pub instance_results: Vec, + pub evals: Vec, + pub point_slices: Vec, + pub point_concats: Vec, + pub opening_claims: Vec, + pub opening_equalities: Vec, + pub opening_batches: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage3Params { + pub field: String, + pub pcs: String, + pub transcript: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage3KernelPlan { + pub symbol: String, + pub relation: String, + pub kind: String, + pub backend: String, + pub abi: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage3TranscriptSqueezePlan { + pub symbol: String, + pub label: String, + pub kind: String, + pub count: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage3ProgramStepPlan { + pub kind: String, + pub symbol: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage3OpeningInputPlan { + pub symbol: String, + pub source_stage: String, + pub source_claim: String, + pub oracle: String, + pub domain: String, + pub point_arity: usize, + pub claim_kind: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage3FieldConstantPlan { + pub symbol: String, + pub field: String, + pub value: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage3FieldExprPlan { + pub symbol: String, + pub kind: String, + pub formula: String, + pub operand_names: Vec, + pub operands: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage3SumcheckClaimPlan { + pub symbol: String, + pub stage: String, + pub domain: String, + pub num_rounds: usize, + pub degree: usize, + pub claim: String, + pub kernel: Option, + pub relation: Option, + pub claim_value: String, + pub input_openings: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage3SumcheckBatchPlan { + pub symbol: String, + pub stage: String, + pub proof_slot: String, + pub policy: String, + pub count: usize, + pub ordered_claims: Vec, + pub claim_operands: Vec, + pub claim_label: String, + pub round_label: String, + pub round_schedule: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage3SumcheckDriverPlan { + pub symbol: String, + pub stage: String, + pub proof_slot: String, + pub kernel: Option, + pub relation: Option, + pub batch: String, + pub policy: String, + pub round_schedule: Vec, + pub claim_label: String, + pub round_label: String, + pub num_rounds: usize, + pub degree: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage3SumcheckInstanceResultPlan { + pub symbol: String, + pub source: String, + pub claim: String, + pub relation: String, + pub index: usize, + pub point_arity: usize, + pub num_rounds: usize, + pub round_offset: usize, + pub point_order: String, + pub degree: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage3SumcheckEvalPlan { + pub symbol: String, + pub source: String, + pub name: String, + pub index: usize, + pub oracle: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage3PointSlicePlan { + pub symbol: String, + pub source: String, + pub offset: usize, + pub length: usize, + pub input: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage3PointConcatPlan { + pub symbol: String, + pub layout: String, + pub arity: usize, + pub inputs: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage3OpeningClaimPlan { + pub symbol: String, + pub oracle: String, + pub domain: String, + pub point_arity: usize, + pub claim_kind: String, + pub point_source: String, + pub eval_source: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage3OpeningClaimEqualityPlan { + pub symbol: String, + pub mode: String, + pub lhs: String, + pub rhs: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage3OpeningBatchPlan { + pub symbol: String, + pub stage: String, + pub proof_slot: String, + pub policy: String, + pub count: usize, + pub ordered_claims: Vec, + pub claim_operands: Vec, +} + +pub fn stage3_cpu_program(module: &BoltModule<'_, Cpu>) -> Result { + verify_cpu_schema(module)?; + let program = Stage3CpuProgram::from_module(module)?; + program.verify_supported_target()?; + Ok(program) +} + +pub fn emit_stage3_rust(module: &BoltModule<'_, Cpu>) -> Result { + let program = stage3_cpu_program(module)?; + + Ok(RustSourceFile { + filename: program.filename().to_owned(), + source: program.emit_source()?, + }) +} + +impl Stage3CpuProgram { + fn from_module(module: &BoltModule<'_, Cpu>) -> Result { + let mut params = None; + let mut steps = Vec::new(); + let mut transcript_squeezes = Vec::new(); + let mut opening_inputs = Vec::new(); + let mut field_constants = Vec::new(); + let mut field_exprs = Vec::new(); + let mut kernels = Vec::new(); + let mut claims = Vec::new(); + let mut batches = Vec::new(); + let mut drivers = Vec::new(); + let mut instance_results = Vec::new(); + let mut evals = Vec::new(); + let mut point_slices = Vec::new(); + let mut point_concats = Vec::new(); + let mut opening_claims = Vec::new(); + let mut opening_equalities = Vec::new(); + let mut opening_batches = Vec::new(); + + let mut operation = module.as_mlir_module().body().first_operation(); + while let Some(op) = operation { + operation = op.next_in_block(); + match operation_name(op).as_str() { + "cpu.params" => { + params = Some(Stage3Params { + field: symbol_attr(op, "field")?, + pcs: symbol_attr(op, "pcs")?, + transcript: symbol_attr(op, "transcript")?, + }); + } + "cpu.kernel" => { + kernels.push(Stage3KernelPlan { + symbol: string_attr(op, "sym_name")?, + relation: symbol_attr(op, "relation")?, + kind: string_attr(op, "kind")?, + backend: string_attr(op, "backend")?, + abi: string_attr(op, "abi")?, + }); + } + "cpu.transcript_squeeze" => { + let symbol = string_attr(op, "sym_name")?; + steps.push(Stage3ProgramStepPlan { + kind: "transcript_squeeze".to_owned(), + symbol: symbol.clone(), + }); + transcript_squeezes.push(Stage3TranscriptSqueezePlan { + symbol, + label: string_attr(op, "label")?, + kind: string_attr(op, "kind")?, + count: int_attr(op, "count")?, + }); + } + "cpu.opening_input" => { + opening_inputs.push(Stage3OpeningInputPlan { + symbol: string_attr(op, "sym_name")?, + source_stage: symbol_attr(op, "source_stage")?, + source_claim: symbol_attr(op, "source_claim")?, + oracle: symbol_attr(op, "oracle")?, + domain: symbol_attr(op, "domain")?, + point_arity: int_attr(op, "point_arity")?, + claim_kind: string_attr(op, "claim_kind")?, + }); + } + "cpu.field_const" => { + field_constants.push(Stage3FieldConstantPlan { + symbol: string_attr(op, "sym_name")?, + field: symbol_attr(op, "field")?, + value: int_attr(op, "value")?, + }); + } + "cpu.field_zero" => { + field_constants.push(Stage3FieldConstantPlan { + symbol: string_attr(op, "sym_name")?, + field: symbol_attr(op, "field")?, + value: 0, + }); + } + "cpu.field_one" => { + field_constants.push(Stage3FieldConstantPlan { + symbol: string_attr(op, "sym_name")?, + field: symbol_attr(op, "field")?, + value: 1, + }); + } + "cpu.field_add" | "cpu.field_sub" | "cpu.field_mul" | "cpu.field_neg" => { + let operands = operand_symbols(op, 0)?; + field_exprs.push(Stage3FieldExprPlan { + symbol: string_attr(op, "sym_name")?, + kind: "op".to_owned(), + formula: operation_name(op).replace("cpu.field_", "field."), + operand_names: operands.clone(), + operands, + }); + } + "cpu.field_pow" => { + let exponent = int_attr(op, "exponent")?; + let operands = operand_symbols(op, 0)?; + field_exprs.push(Stage3FieldExprPlan { + symbol: string_attr(op, "sym_name")?, + kind: "op".to_owned(), + formula: format!("field.pow:{exponent}"), + operand_names: operands.clone(), + operands, + }); + } + "cpu.poly_lagrange_basis_eval" => { + let domain_start = signed_int_attr(op, "domain_start")?; + let domain_size = int_attr(op, "domain_size")?; + let index = int_attr(op, "index")?; + let operands = operand_symbols(op, 0)?; + field_exprs.push(Stage3FieldExprPlan { + symbol: string_attr(op, "sym_name")?, + kind: "op".to_owned(), + formula: format!( + "poly.lagrange_basis_eval:{domain_start}:{domain_size}:{index}" + ), + operand_names: operands.clone(), + operands, + }); + } + "cpu.sumcheck_claim" => { + claims.push(Stage3SumcheckClaimPlan { + symbol: string_attr(op, "sym_name")?, + stage: symbol_attr(op, "stage")?, + domain: symbol_attr(op, "domain")?, + num_rounds: int_attr(op, "num_rounds")?, + degree: int_attr(op, "degree")?, + claim: symbol_attr(op, "claim")?, + kernel: Some(symbol_attr(op, "kernel")?), + relation: None, + claim_value: operand_symbol(op, 0)?, + input_openings: operand_symbols(op, 1)?, + }); + } + "cpu.sumcheck_verify_claim" => { + claims.push(Stage3SumcheckClaimPlan { + symbol: string_attr(op, "sym_name")?, + stage: symbol_attr(op, "stage")?, + domain: symbol_attr(op, "domain")?, + num_rounds: int_attr(op, "num_rounds")?, + degree: int_attr(op, "degree")?, + claim: symbol_attr(op, "claim")?, + kernel: None, + relation: Some(symbol_attr(op, "relation")?), + claim_value: operand_symbol(op, 0)?, + input_openings: operand_symbols(op, 1)?, + }); + } + "cpu.sumcheck_batch" => { + batches.push(Stage3SumcheckBatchPlan { + symbol: string_attr(op, "sym_name")?, + stage: symbol_attr(op, "stage")?, + proof_slot: symbol_attr(op, "proof_slot")?, + policy: string_attr(op, "policy")?, + count: int_attr(op, "count")?, + ordered_claims: symbol_array_attr(op, "ordered_claims")?, + claim_operands: operand_symbols(op, 0)?, + claim_label: string_attr(op, "claim_label")?, + round_label: string_attr(op, "round_label")?, + round_schedule: int_array_attr(op, "round_schedule")?, + }); + } + "cpu.sumcheck_driver" => { + let symbol = string_attr(op, "sym_name")?; + steps.push(Stage3ProgramStepPlan { + kind: "sumcheck_driver".to_owned(), + symbol: symbol.clone(), + }); + drivers.push(Stage3SumcheckDriverPlan { + symbol, + stage: symbol_attr(op, "stage")?, + proof_slot: symbol_attr(op, "proof_slot")?, + kernel: Some(symbol_attr(op, "kernel")?), + relation: None, + batch: operand_symbol(op, 1)?, + policy: string_attr(op, "policy")?, + round_schedule: int_array_attr(op, "round_schedule")?, + claim_label: string_attr(op, "claim_label")?, + round_label: string_attr(op, "round_label")?, + num_rounds: int_attr(op, "num_rounds")?, + degree: int_attr(op, "degree")?, + }); + } + "cpu.sumcheck_verify" => { + let symbol = string_attr(op, "sym_name")?; + steps.push(Stage3ProgramStepPlan { + kind: "sumcheck_driver".to_owned(), + symbol: symbol.clone(), + }); + drivers.push(Stage3SumcheckDriverPlan { + symbol, + stage: symbol_attr(op, "stage")?, + proof_slot: symbol_attr(op, "proof_slot")?, + kernel: None, + relation: Some(symbol_attr(op, "relation")?), + batch: operand_symbol(op, 1)?, + policy: string_attr(op, "policy")?, + round_schedule: int_array_attr(op, "round_schedule")?, + claim_label: string_attr(op, "claim_label")?, + round_label: string_attr(op, "round_label")?, + num_rounds: int_attr(op, "num_rounds")?, + degree: int_attr(op, "degree")?, + }); + } + "cpu.sumcheck_instance_result" => { + instance_results.push(Stage3SumcheckInstanceResultPlan { + symbol: string_attr(op, "sym_name")?, + source: symbol_attr(op, "source")?, + claim: symbol_attr(op, "claim")?, + relation: symbol_attr(op, "relation")?, + index: int_attr(op, "index")?, + point_arity: int_attr(op, "point_arity")?, + num_rounds: int_attr(op, "num_rounds")?, + round_offset: int_attr(op, "round_offset")?, + point_order: string_attr(op, "point_order")?, + degree: int_attr(op, "degree")?, + }); + } + "cpu.sumcheck_eval" => { + evals.push(Stage3SumcheckEvalPlan { + symbol: string_attr(op, "sym_name")?, + source: symbol_attr(op, "source")?, + name: symbol_attr(op, "name")?, + index: int_attr(op, "index")?, + oracle: symbol_attr(op, "oracle")?, + }); + } + "cpu.point_slice" => { + point_slices.push(Stage3PointSlicePlan { + symbol: string_attr(op, "sym_name")?, + source: symbol_attr(op, "source")?, + offset: int_attr(op, "offset")?, + length: int_attr(op, "length")?, + input: operand_symbol(op, 0)?, + }); + } + "cpu.point_concat" => { + point_concats.push(Stage3PointConcatPlan { + symbol: string_attr(op, "sym_name")?, + layout: string_attr(op, "layout")?, + arity: int_attr(op, "arity")?, + inputs: operand_symbols(op, 0)?, + }); + } + "cpu.opening_claim" => { + opening_claims.push(Stage3OpeningClaimPlan { + symbol: string_attr(op, "sym_name")?, + oracle: symbol_attr(op, "oracle")?, + domain: symbol_attr(op, "domain")?, + point_arity: int_attr(op, "point_arity")?, + claim_kind: string_attr(op, "claim_kind")?, + point_source: operand_symbol(op, 0)?, + eval_source: operand_symbol(op, 1)?, + }); + } + "cpu.opening_claim_equal" => { + opening_equalities.push(Stage3OpeningClaimEqualityPlan { + symbol: string_attr(op, "sym_name")?, + mode: string_attr(op, "mode")?, + lhs: operand_symbol(op, 0)?, + rhs: operand_symbol(op, 1)?, + }); + } + "cpu.opening_batch" => { + opening_batches.push(Stage3OpeningBatchPlan { + symbol: string_attr(op, "sym_name")?, + stage: symbol_attr(op, "stage")?, + proof_slot: symbol_attr(op, "proof_slot")?, + policy: string_attr(op, "policy")?, + count: int_attr(op, "count")?, + ordered_claims: symbol_array_attr(op, "ordered_claims")?, + claim_operands: operand_symbols(op, 0)?, + }); + } + _ => {} + } + } + + Ok(Self { + params: params.ok_or_else(|| EmitError::new("missing cpu.params"))?, + role: module + .role() + .ok_or_else(|| EmitError::new("missing cpu party role"))?, + steps, + transcript_squeezes, + opening_inputs, + field_constants, + field_exprs, + kernels, + claims, + batches, + drivers, + instance_results, + evals, + point_slices, + point_concats, + opening_claims, + opening_equalities, + opening_batches, + }) + } + + fn verify_supported_target(&self) -> Result<(), EmitError> { + require_supported_symbol("field", &self.params.field, "bn254_fr")?; + require_supported_symbol("pcs", &self.params.pcs, "dory")?; + require_supported_symbol("transcript", &self.params.transcript, "blake2b_transcript")?; + self.verify_transcript_squeezes()?; + self.verify_field_flow()?; + self.verify_claim_batches()?; + match self.role { + Role::Prover => { + self.verify_kernel_definitions()?; + self.verify_prover_driver_bindings()?; + } + Role::Verifier => self.verify_verifier_driver_bindings()?, + } + self.verify_opening_flow() + } + + fn verify_transcript_squeezes(&self) -> Result<(), EmitError> { + for squeeze in &self.transcript_squeezes { + if !matches!( + squeeze.kind.as_str(), + "challenge_scalar" | "challenge_vector" + ) { + return Err(EmitError::new(format!( + "stage3 transcript squeeze @{} has unsupported kind `{}`", + squeeze.symbol, squeeze.kind + ))); + } + if squeeze.count == 0 { + return Err(EmitError::new(format!( + "stage3 transcript squeeze @{} has zero count", + squeeze.symbol + ))); + } + } + Ok(()) + } + + fn verify_field_flow(&self) -> Result<(), EmitError> { + for constant in &self.field_constants { + require_supported_symbol("field constant field", &constant.field, "bn254_fr")?; + } + let field_values = self.field_value_symbols(); + for expr in &self.field_exprs { + verify_count( + "field expr operands", + &expr.symbol, + expr.operand_names.len(), + expr.operands.len(), + )?; + for operand in &expr.operands { + if !field_values.contains(operand) { + return Err(EmitError::new(format!( + "field expr @{} references missing field value @{operand}", + expr.symbol + ))); + } + } + } + for claim in &self.claims { + if !field_values.contains(&claim.claim_value) { + return Err(EmitError::new(format!( + "sumcheck claim @{} uses missing claim value @{}", + claim.symbol, claim.claim_value + ))); + } + } + Ok(()) + } + + fn field_value_symbols(&self) -> BTreeSet { + let mut values = symbols(self.opening_inputs.iter().map(|input| &input.symbol)); + values.extend(symbols( + self.field_constants.iter().map(|constant| &constant.symbol), + )); + values.extend(symbols( + self.transcript_squeezes + .iter() + .filter(|squeeze| matches!(squeeze.kind.as_str(), "challenge_scalar" | "scalar")) + .map(|squeeze| &squeeze.symbol), + )); + values.extend(symbols(self.field_exprs.iter().map(|expr| &expr.symbol))); + values.extend(symbols(self.evals.iter().map(|eval| &eval.symbol))); + values + } + + fn verify_kernel_definitions(&self) -> Result<(), EmitError> { + for kernel in &self.kernels { + if kernel.backend != "cpu" { + return Err(EmitError::new(format!( + "stage3 kernel @{} targets unsupported backend `{}`", + kernel.symbol, kernel.backend + ))); + } + if kernel.kind != "sumcheck" { + return Err(EmitError::new(format!( + "stage3 kernel @{} has unsupported kind `{}`", + kernel.symbol, kernel.kind + ))); + } + let expected_abi = match kernel.relation.as_str() { + "jolt.stage3.spartan_shift" => "jolt_stage3_spartan_shift", + "jolt.stage3.instruction_input" => "jolt_stage3_instruction_input", + "jolt.stage3.registers_claim_reduction" => "jolt_stage3_registers_claim_reduction", + "jolt.stage3.batched" => "jolt_stage3_batched", + _ => { + return Err(EmitError::new(format!( + "unsupported stage3 kernel relation @{}", + kernel.relation + ))); + } + }; + if kernel.abi != expected_abi { + return Err(EmitError::new(format!( + "stage3 kernel @{} ABI `{}` does not match relation @{}", + kernel.symbol, kernel.abi, kernel.relation + ))); + } + } + Ok(()) + } + + fn verify_claim_batches(&self) -> Result<(), EmitError> { + let claims = symbols(self.claims.iter().map(|claim| &claim.symbol)); + for batch in &self.batches { + verify_count( + "sumcheck batch", + &batch.symbol, + batch.count, + batch.ordered_claims.len(), + )?; + verify_count( + "sumcheck batch operands", + &batch.symbol, + batch.count, + batch.claim_operands.len(), + )?; + if batch.ordered_claims != batch.claim_operands { + return Err(EmitError::new(format!( + "sumcheck batch @{} operand order does not match ordered_claims", + batch.symbol + ))); + } + for claim in &batch.ordered_claims { + if !claims.contains(claim) { + return Err(EmitError::new(format!( + "sumcheck batch @{} references missing claim @{claim}", + batch.symbol + ))); + } + } + } + Ok(()) + } + + fn verify_prover_driver_bindings(&self) -> Result<(), EmitError> { + let kernels = symbols(self.kernels.iter().map(|kernel| &kernel.symbol)); + let batches: BTreeMap<_, _> = self + .batches + .iter() + .map(|batch| (batch.symbol.as_str(), batch)) + .collect(); + for claim in &self.claims { + let Some(kernel) = claim.kernel.as_deref() else { + return Err(EmitError::new(format!( + "prover sumcheck claim @{} is missing kernel", + claim.symbol + ))); + }; + if !kernels.contains(kernel) { + return Err(EmitError::new(format!( + "sumcheck claim @{} references missing kernel @{kernel}", + claim.symbol + ))); + } + } + for driver in &self.drivers { + let Some(kernel) = driver.kernel.as_deref() else { + return Err(EmitError::new(format!( + "prover sumcheck driver @{} is missing kernel", + driver.symbol + ))); + }; + if !kernels.contains(kernel) { + return Err(EmitError::new(format!( + "sumcheck driver @{} references missing kernel @{kernel}", + driver.symbol + ))); + } + let batch = batches.get(driver.batch.as_str()).ok_or_else(|| { + EmitError::new(format!( + "sumcheck driver @{} references missing batch @{}", + driver.symbol, driver.batch + )) + })?; + verify_count( + "sumcheck driver round_schedule", + &driver.symbol, + driver.num_rounds, + driver.round_schedule.iter().sum(), + )?; + if driver.round_schedule != batch.round_schedule { + return Err(EmitError::new(format!( + "sumcheck driver @{} round_schedule differs from batch @{}", + driver.symbol, batch.symbol + ))); + } + } + Ok(()) + } + + fn verify_verifier_driver_bindings(&self) -> Result<(), EmitError> { + if !self.kernels.is_empty() { + return Err(EmitError::new( + "verifier stage3 program must not contain kernels", + )); + } + let batches: BTreeMap<_, _> = self + .batches + .iter() + .map(|batch| (batch.symbol.as_str(), batch)) + .collect(); + for claim in &self.claims { + if claim.kernel.is_some() || claim.relation.is_none() { + return Err(EmitError::new(format!( + "verifier sumcheck claim @{} must carry relation and no kernel", + claim.symbol + ))); + } + } + for driver in &self.drivers { + if driver.kernel.is_some() || driver.relation.is_none() { + return Err(EmitError::new(format!( + "verifier sumcheck driver @{} must carry relation and no kernel", + driver.symbol + ))); + } + let batch = batches.get(driver.batch.as_str()).ok_or_else(|| { + EmitError::new(format!( + "sumcheck driver @{} references missing batch @{}", + driver.symbol, driver.batch + )) + })?; + verify_count( + "sumcheck driver round_schedule", + &driver.symbol, + driver.num_rounds, + driver.round_schedule.iter().sum(), + )?; + if driver.round_schedule != batch.round_schedule { + return Err(EmitError::new(format!( + "sumcheck driver @{} round_schedule differs from batch @{}", + driver.symbol, batch.symbol + ))); + } + } + Ok(()) + } + + fn verify_opening_flow(&self) -> Result<(), EmitError> { + let mut point_sources = symbols(self.drivers.iter().map(|driver| &driver.symbol)); + point_sources.extend(symbols( + self.instance_results + .iter() + .map(|instance| &instance.symbol), + )); + point_sources.extend(symbols( + self.opening_inputs.iter().map(|input| &input.symbol), + )); + point_sources.extend(symbols(self.point_slices.iter().map(|slice| &slice.symbol))); + point_sources.extend(symbols( + self.point_concats.iter().map(|concat| &concat.symbol), + )); + for slice in &self.point_slices { + if !point_sources.contains(&slice.input) { + return Err(EmitError::new(format!( + "point slice @{} uses missing point source @{}", + slice.symbol, slice.input + ))); + } + } + for concat in &self.point_concats { + for input in &concat.inputs { + if !point_sources.contains(input) { + return Err(EmitError::new(format!( + "point concat @{} uses missing point source @{input}", + concat.symbol + ))); + } + } + } + let eval_sources = self.field_value_symbols(); + let mut opening_sources = symbols(self.opening_inputs.iter().map(|input| &input.symbol)); + opening_sources.extend(symbols( + self.opening_claims.iter().map(|claim| &claim.symbol), + )); + for equality in &self.opening_equalities { + if !opening_sources.contains(&equality.lhs) { + return Err(EmitError::new(format!( + "opening equality @{} uses missing lhs opening @{}", + equality.symbol, equality.lhs + ))); + } + if !opening_sources.contains(&equality.rhs) { + return Err(EmitError::new(format!( + "opening equality @{} uses missing rhs opening @{}", + equality.symbol, equality.rhs + ))); + } + } + for claim in &self.claims { + for input in &claim.input_openings { + if !opening_sources.contains(input) { + return Err(EmitError::new(format!( + "sumcheck claim @{} uses missing opening @{input}", + claim.symbol + ))); + } + } + } + let drivers = symbols(self.drivers.iter().map(|driver| &driver.symbol)); + for instance in &self.instance_results { + if !drivers.contains(&instance.source) { + return Err(EmitError::new(format!( + "sumcheck instance result @{} references missing driver @{}", + instance.symbol, instance.source + ))); + } + } + for eval in &self.evals { + if !drivers.contains(&eval.source) { + return Err(EmitError::new(format!( + "sumcheck eval @{} references missing driver @{}", + eval.symbol, eval.source + ))); + } + } + for claim in &self.opening_claims { + if !point_sources.contains(&claim.point_source) { + return Err(EmitError::new(format!( + "opening claim @{} uses missing point source @{}", + claim.symbol, claim.point_source + ))); + } + if !eval_sources.contains(&claim.eval_source) { + return Err(EmitError::new(format!( + "opening claim @{} uses missing eval source @{}", + claim.symbol, claim.eval_source + ))); + } + } + let openings = symbols(self.opening_claims.iter().map(|claim| &claim.symbol)); + for batch in &self.opening_batches { + verify_count( + "opening batch", + &batch.symbol, + batch.count, + batch.ordered_claims.len(), + )?; + verify_count( + "opening batch operands", + &batch.symbol, + batch.count, + batch.claim_operands.len(), + )?; + if batch.ordered_claims != batch.claim_operands { + return Err(EmitError::new(format!( + "opening batch @{} operand order does not match ordered_claims", + batch.symbol + ))); + } + for claim in &batch.ordered_claims { + if !openings.contains(claim) { + return Err(EmitError::new(format!( + "opening batch @{} references missing opening @{claim}", + batch.symbol + ))); + } + } + } + Ok(()) + } + + fn emit_source(&self) -> Result { + match self.role { + Role::Prover => self.emit_prover_source(), + Role::Verifier => self.emit_verifier_source(), + } + } + + fn emit_prover_source(&self) -> Result { + let mut source = String::new(); + source.push_str("#![allow(dead_code)]\n\n"); + source.push_str(Self::emit_prover_imports()); + source.push_str("\n\n"); + source.push_str(Self::emit_prover_types()); + source.push('\n'); + source.push_str(&self.emit_prover_constants()?); + source.push('\n'); + source.push_str(Self::emit_prover_entrypoint()); + Ok(source) + } + + fn emit_verifier_source(&self) -> Result { + let mut source = String::new(); + source.push_str("#![allow(dead_code)]\n\n"); + source.push_str(Self::emit_verifier_imports()); + source.push_str("\n\n"); + source.push_str(Self::emit_verifier_types()); + source.push('\n'); + source.push_str(&self.emit_verifier_constants()?); + source.push('\n'); + source.push_str(Self::emit_verifier_entrypoint()); + Ok(source) + } + + fn filename(&self) -> &'static str { + match self.role { + Role::Prover => "prove_stage3.rs", + Role::Verifier => "verify_stage3.rs", + } + } + + fn emit_prover_imports() -> &'static str { + "use jolt_field::Fr;\n\ + use jolt_kernels::stage3::{execute_stage3_program, Stage3CpuProgramPlan, Stage3ExecutionArtifacts, Stage3ExecutionMode, Stage3FieldConstantPlan, Stage3FieldExprPlan, Stage3KernelError, Stage3KernelExecutor, Stage3KernelPlan, Stage3OpeningBatchPlan, Stage3OpeningClaimEqualityPlan, Stage3OpeningClaimPlan, Stage3OpeningInputPlan, Stage3Params, Stage3PointConcatPlan, Stage3PointSlicePlan, Stage3ProgramStepPlan, Stage3SumcheckBatchPlan, Stage3SumcheckClaimPlan, Stage3SumcheckDriverPlan, Stage3SumcheckEvalPlan, Stage3SumcheckInstanceResultPlan, Stage3TranscriptSqueezePlan};\n\ + use jolt_transcript::{Blake2bTranscript, Transcript};" + } + + fn emit_prover_types() -> &'static str { + "pub type DefaultStage3Transcript = Blake2bTranscript;\n" + } + + fn emit_verifier_imports() -> &'static str { + "use super::common::{batch_claims, eval_by_name, find_batch, find_plan, reverse_slice};\n\ + use jolt_field::{Field, Fr};\n\ + use jolt_poly::{EqPlusOnePolynomial, EqPolynomial};\n\ + use jolt_sumcheck::SumcheckError;\n\ + use jolt_transcript::{Blake2bTranscript, Transcript};" + } + + fn emit_verifier_types() -> &'static str { + r"pub type DefaultStage3Transcript = Blake2bTranscript; + +pub type Stage3NamedEval = super::common::StageNamedEval; +pub type Stage3SumcheckOutput = super::common::StageSumcheckOutput; +pub type Stage3ChallengeVector = super::common::StageChallengeVector; +pub type Stage3ExecutionArtifacts = super::common::StageExecutionArtifacts; +pub type Stage3Proof = super::common::StageProof; +pub type Stage3OpeningInputValue = super::common::StageOpeningInputValue; +pub type Stage3VerifierProgramPlan = super::common::StageVerifierProgramPlan; + +pub use super::common::{ + FieldConstantPlan as Stage3FieldConstantPlan, FieldExprPlan as Stage3FieldExprPlan, + OpeningBatchPlan as Stage3OpeningBatchPlan, + OpeningClaimEqualityPlan as Stage3OpeningClaimEqualityPlan, + OpeningClaimPlan as Stage3OpeningClaimPlan, OpeningInputPlan as Stage3OpeningInputPlan, + PointConcatPlan as Stage3PointConcatPlan, PointSlicePlan as Stage3PointSlicePlan, + ProgramStepPlan as Stage3ProgramStepPlan, StageParams as Stage3Params, + SumcheckBatchPlan as Stage3SumcheckBatchPlan, SumcheckEvalPlan as Stage3SumcheckEvalPlan, + SumcheckInstanceResultPlan as Stage3SumcheckInstanceResultPlan, + TranscriptSqueezePlan as Stage3TranscriptSqueezePlan, + SumcheckClaimPlan as Stage3SumcheckClaimPlan, + SumcheckDriverPlan as Stage3SumcheckDriverPlan, +}; + +#[derive(Debug)] +pub enum VerifyStage3Error { + UnexpectedProofCount { expected: usize, got: usize }, + MissingProof { driver: &'static str }, + MissingBatch { driver: &'static str, batch: &'static str }, + MissingClaim { batch: &'static str, claim: &'static str }, + MissingValue { symbol: &'static str }, + InvalidInputLength { input: &'static str, expected: usize, actual: usize }, + InvalidProof { driver: &'static str, reason: &'static str }, + UnsupportedFieldExpr { symbol: &'static str, formula: &'static str }, + UnsupportedRelation { relation: &'static str }, + Sumcheck { driver: &'static str, error: SumcheckError }, +} + +super::common::impl_runtime_plan_error_conversion!(VerifyStage3Error); +" + } + + fn emit_prover_constants(&self) -> Result { + let mut source = self.emit_shared_constants(); + source.push_str(&self.emit_kernel_constants()); + source.push_str(&self.emit_prover_sumcheck_claim_constants()?); + source.push_str(&self.emit_sumcheck_batch_constants()); + source.push_str(&self.emit_prover_sumcheck_driver_constants()?); + source.push_str(&self.emit_tail_constants()); + source.push_str( + "pub const STAGE3_PROGRAM: Stage3CpuProgramPlan = Stage3CpuProgramPlan {\n\ + \x20 params: STAGE3_PARAMS,\n\ + \x20 steps: STAGE3_PROGRAM_STEPS,\n\ + \x20 transcript_squeezes: STAGE3_TRANSCRIPT_SQUEEZES,\n\ + \x20 opening_inputs: STAGE3_OPENING_INPUTS,\n\ + \x20 field_constants: STAGE3_FIELD_CONSTANTS,\n\ + \x20 field_exprs: STAGE3_FIELD_EXPRS,\n\ + \x20 kernels: STAGE3_KERNELS,\n\ + \x20 claims: STAGE3_SUMCHECK_CLAIMS,\n\ + \x20 batches: STAGE3_SUMCHECK_BATCHES,\n\ + \x20 drivers: STAGE3_SUMCHECK_DRIVERS,\n\ + \x20 instance_results: STAGE3_SUMCHECK_INSTANCE_RESULTS,\n\ + \x20 evals: STAGE3_SUMCHECK_EVALS,\n\ + \x20 point_slices: STAGE3_POINT_SLICES,\n\ + \x20 point_concats: STAGE3_POINT_CONCATS,\n\ + \x20 opening_claims: STAGE3_OPENING_CLAIMS,\n\ + \x20 opening_equalities: STAGE3_OPENING_EQUALITIES,\n\ + \x20 opening_batches: STAGE3_OPENING_BATCHES,\n\ + };\n", + ); + Ok(source) + } + + fn emit_verifier_constants(&self) -> Result { + let mut source = self.emit_shared_constants(); + source.push_str(&self.emit_verifier_sumcheck_claim_constants()?); + source.push_str(&self.emit_sumcheck_batch_constants()); + source.push_str(&self.emit_verifier_sumcheck_driver_constants()?); + source.push_str(&self.emit_tail_constants()); + source.push_str( + "pub const STAGE3_PROGRAM: Stage3VerifierProgramPlan = Stage3VerifierProgramPlan {\n\ + \x20 params: STAGE3_PARAMS,\n\ + \x20 steps: STAGE3_PROGRAM_STEPS,\n\ + \x20 transcript_squeezes: STAGE3_TRANSCRIPT_SQUEEZES,\n\ + \x20 opening_inputs: STAGE3_OPENING_INPUTS,\n\ + \x20 field_constants: STAGE3_FIELD_CONSTANTS,\n\ + \x20 field_exprs: STAGE3_FIELD_EXPRS,\n\ + \x20 claims: STAGE3_SUMCHECK_CLAIMS,\n\ + \x20 batches: STAGE3_SUMCHECK_BATCHES,\n\ + \x20 drivers: STAGE3_SUMCHECK_DRIVERS,\n\ + \x20 instance_results: STAGE3_SUMCHECK_INSTANCE_RESULTS,\n\ + \x20 evals: STAGE3_SUMCHECK_EVALS,\n\ + \x20 point_slices: STAGE3_POINT_SLICES,\n\ + \x20 point_concats: STAGE3_POINT_CONCATS,\n\ + \x20 opening_claims: STAGE3_OPENING_CLAIMS,\n\ + \x20 opening_equalities: STAGE3_OPENING_EQUALITIES,\n\ + \x20 opening_batches: STAGE3_OPENING_BATCHES,\n\ + };\n", + ); + Ok(source) + } + + fn emit_shared_constants(&self) -> String { + let mut source = String::new(); + push_format( + &mut source, + format_args!( + "pub const STAGE3_PARAMS: Stage3Params = Stage3Params {{\n\ + \x20 field: {},\n\ + \x20 pcs: {},\n\ + \x20 transcript: {},\n\ + }};\n", + rust_str(&self.params.field), + rust_str(&self.params.pcs), + rust_str(&self.params.transcript) + ), + ); + source.push_str(&self.emit_program_step_constants()); + source.push_str(&self.emit_transcript_squeeze_constants()); + source.push_str(&self.emit_opening_input_constants()); + source.push_str(&self.emit_field_constant_constants()); + source.push_str(&self.emit_field_expr_constants()); + source + } + + fn emit_program_step_constants(&self) -> String { + let steps = self + .steps + .iter() + .map(|step| { + format!( + " Stage3ProgramStepPlan {{ kind: {}, symbol: {} }},", + rust_str(&step.kind), + rust_str(&step.symbol), + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE3_PROGRAM_STEPS: &[Stage3ProgramStepPlan] = &[\n{steps}\n];\n\n") + } + + fn emit_transcript_squeeze_constants(&self) -> String { + let squeezes = self + .transcript_squeezes + .iter() + .map(|squeeze| { + format!( + " Stage3TranscriptSqueezePlan {{ symbol: {}, label: {}, kind: {}, count: {} }},", + rust_str(&squeeze.symbol), + rust_str(&squeeze.label), + rust_str(&squeeze.kind), + squeeze.count, + ) + }) + .collect::>() + .join("\n"); + format!( + "pub const STAGE3_TRANSCRIPT_SQUEEZES: &[Stage3TranscriptSqueezePlan] = &[\n{squeezes}\n];\n\n" + ) + } + + fn emit_opening_input_constants(&self) -> String { + let inputs = self + .opening_inputs + .iter() + .map(|input| { + format!( + " Stage3OpeningInputPlan {{ symbol: {}, source_stage: {}, source_claim: {}, oracle: {}, domain: {}, point_arity: {}, claim_kind: {} }},", + rust_str(&input.symbol), + rust_str(&input.source_stage), + rust_str(&input.source_claim), + rust_str(&input.oracle), + rust_str(&input.domain), + input.point_arity, + rust_str(&input.claim_kind) + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE3_OPENING_INPUTS: &[Stage3OpeningInputPlan] = &[\n{inputs}\n];\n\n") + } + + fn emit_field_constant_constants(&self) -> String { + let constants = self + .field_constants + .iter() + .map(|constant| { + format!( + " Stage3FieldConstantPlan {{ symbol: {}, field: {}, value: {} }},", + rust_str(&constant.symbol), + rust_str(&constant.field), + constant.value + ) + }) + .collect::>() + .join("\n"); + format!( + "pub const STAGE3_FIELD_CONSTANTS: &[Stage3FieldConstantPlan] = &[\n{constants}\n];\n\n" + ) + } + + fn emit_field_expr_constants(&self) -> String { + if self.role == Role::Verifier { + let exprs = self + .field_exprs + .iter() + .map(|expr| { + format!( + " Stage3FieldExprPlan {{ symbol: {}, kind: {}, formula: {}, operands: {} }},", + rust_str(&expr.symbol), + rust_str(&expr.kind), + rust_str(&expr.formula), + rust_str(&expr.operands.join("|")) + ) + }) + .collect::>() + .join("\n"); + return format!( + "pub const STAGE3_FIELD_EXPRS: &[Stage3FieldExprPlan] = &[\n{exprs}\n];\n" + ); + } + + let mut source = String::new(); + let mut arrays = Vec::new(); + let mut array_refs = Vec::new(); + for (index, expr) in self.field_exprs.iter().enumerate() { + let operands = intern_str_array( + &mut source, + &mut arrays, + "STAGE3_FIELD_EXPR_OPERANDS", + &expr.operands, + ); + let operand_names = intern_str_array( + &mut source, + &mut arrays, + "STAGE3_FIELD_EXPR_OPERANDS", + &expr.operand_names, + ); + array_refs.push((index, operand_names, operands)); + } + let exprs = self + .field_exprs + .iter() + .enumerate() + .map(|(index, expr)| { + let (_, operand_names, operands) = &array_refs[index]; + format!( + " Stage3FieldExprPlan {{ symbol: {}, kind: {}, formula: {}, operand_names: {operand_names}, operands: {operands} }},", + rust_str(&expr.symbol), + rust_str(&expr.kind), + rust_str(&expr.formula) + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE3_FIELD_EXPRS: &[Stage3FieldExprPlan] = &[\n{exprs}\n];\n" + ), + ); + source + } + + fn emit_kernel_constants(&self) -> String { + let kernels = self + .kernels + .iter() + .map(|kernel| { + format!( + " Stage3KernelPlan {{ symbol: {}, relation: {}, kind: {}, backend: {}, abi: {} }},", + rust_str(&kernel.symbol), + rust_str(&kernel.relation), + rust_str(&kernel.kind), + rust_str(&kernel.backend), + rust_str(&kernel.abi) + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE3_KERNELS: &[Stage3KernelPlan] = &[\n{kernels}\n];\n\n") + } + + fn emit_prover_sumcheck_claim_constants(&self) -> Result { + self.emit_sumcheck_claim_constants(true) + } + + fn emit_verifier_sumcheck_claim_constants(&self) -> Result { + self.emit_sumcheck_claim_constants(false) + } + + fn emit_sumcheck_claim_constants(&self, prover: bool) -> Result { + let mut source = String::new(); + if prover { + for (index, claim) in self.claims.iter().enumerate() { + source.push_str(&emit_str_array( + &format!("STAGE3_SUMCHECK_CLAIM_{index}_INPUT_OPENINGS"), + &claim.input_openings, + )); + } + } + let mut claims = Vec::new(); + for (index, claim) in self.claims.iter().enumerate() { + if prover { + let kernel = claim + .kernel + .as_deref() + .ok_or_else(|| missing_role_binding("prover claim kernel", &claim.symbol))?; + claims.push(format!( + " Stage3SumcheckClaimPlan {{ symbol: {}, stage: {}, domain: {}, num_rounds: {}, degree: {}, claim: {}, kernel: Some({}), relation: None, claim_value: {}, input_openings: STAGE3_SUMCHECK_CLAIM_{index}_INPUT_OPENINGS }},", + rust_str(&claim.symbol), + rust_str(&claim.stage), + rust_str(&claim.domain), + claim.num_rounds, + claim.degree, + rust_str(&claim.claim), + rust_str(kernel), + rust_str(&claim.claim_value) + )); + } else { + let relation = claim.relation.as_deref().ok_or_else(|| { + missing_role_binding("verifier claim relation", &claim.symbol) + })?; + claims.push(format!( + " Stage3SumcheckClaimPlan {{ symbol: {}, stage: {}, domain: {}, num_rounds: {}, degree: {}, claim: {}, kernel: None, relation: Some({}), claim_value: {}, input_openings: {} }},", + rust_str(&claim.symbol), + rust_str(&claim.stage), + rust_str(&claim.domain), + claim.num_rounds, + claim.degree, + rust_str(&claim.claim), + rust_str(relation), + rust_str(&claim.claim_value), + rust_str(&claim.input_openings.join("|")) + )); + } + } + let claims = claims.join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE3_SUMCHECK_CLAIMS: &[Stage3SumcheckClaimPlan] = &[\n{claims}\n];\n" + ), + ); + Ok(source) + } + + fn emit_sumcheck_batch_constants(&self) -> String { + if self.role == Role::Verifier { + let mut source = String::new(); + for (index, batch) in self.batches.iter().enumerate() { + source.push_str(&emit_usize_array( + &format!("STAGE3_SUMCHECK_BATCH_{index}_ROUND_SCHEDULE"), + &batch.round_schedule, + )); + } + let batches = self + .batches + .iter() + .enumerate() + .map(|(index, batch)| { + format!( + " Stage3SumcheckBatchPlan {{ symbol: {}, stage: {}, proof_slot: {}, policy: {}, count: {}, ordered_claims: {}, claim_operands: {}, claim_label: {}, round_label: {}, round_schedule: STAGE3_SUMCHECK_BATCH_{index}_ROUND_SCHEDULE }},", + rust_str(&batch.symbol), + rust_str(&batch.stage), + rust_str(&batch.proof_slot), + rust_str(&batch.policy), + batch.count, + rust_str(&batch.ordered_claims.join("|")), + rust_str(&batch.claim_operands.join("|")), + rust_str(&batch.claim_label), + rust_str(&batch.round_label) + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE3_SUMCHECK_BATCHES: &[Stage3SumcheckBatchPlan] = &[\n{batches}\n];\n" + ), + ); + return source; + } + + let mut source = String::new(); + for (index, batch) in self.batches.iter().enumerate() { + source.push_str(&emit_str_array( + &format!("STAGE3_SUMCHECK_BATCH_{index}_ORDERED_CLAIMS"), + &batch.ordered_claims, + )); + source.push_str(&emit_str_array( + &format!("STAGE3_SUMCHECK_BATCH_{index}_CLAIM_OPERANDS"), + &batch.claim_operands, + )); + source.push_str(&emit_usize_array( + &format!("STAGE3_SUMCHECK_BATCH_{index}_ROUND_SCHEDULE"), + &batch.round_schedule, + )); + } + let batches = self + .batches + .iter() + .enumerate() + .map(|(index, batch)| { + format!( + " Stage3SumcheckBatchPlan {{ symbol: {}, stage: {}, proof_slot: {}, policy: {}, count: {}, ordered_claims: STAGE3_SUMCHECK_BATCH_{index}_ORDERED_CLAIMS, claim_operands: STAGE3_SUMCHECK_BATCH_{index}_CLAIM_OPERANDS, claim_label: {}, round_label: {}, round_schedule: STAGE3_SUMCHECK_BATCH_{index}_ROUND_SCHEDULE }},", + rust_str(&batch.symbol), + rust_str(&batch.stage), + rust_str(&batch.proof_slot), + rust_str(&batch.policy), + batch.count, + rust_str(&batch.claim_label), + rust_str(&batch.round_label) + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE3_SUMCHECK_BATCHES: &[Stage3SumcheckBatchPlan] = &[\n{batches}\n];\n" + ), + ); + source + } + + fn emit_prover_sumcheck_driver_constants(&self) -> Result { + self.emit_sumcheck_driver_constants(true) + } + + fn emit_verifier_sumcheck_driver_constants(&self) -> Result { + self.emit_sumcheck_driver_constants(false) + } + + fn emit_sumcheck_driver_constants(&self, prover: bool) -> Result { + let mut source = String::new(); + for (index, driver) in self.drivers.iter().enumerate() { + source.push_str(&emit_usize_array( + &format!("STAGE3_SUMCHECK_DRIVER_{index}_ROUND_SCHEDULE"), + &driver.round_schedule, + )); + } + let mut drivers = Vec::new(); + for (index, driver) in self.drivers.iter().enumerate() { + if prover { + let kernel = driver + .kernel + .as_deref() + .ok_or_else(|| missing_role_binding("prover driver kernel", &driver.symbol))?; + drivers.push(format!( + " Stage3SumcheckDriverPlan {{ symbol: {}, stage: {}, proof_slot: {}, kernel: Some({}), relation: None, batch: {}, policy: {}, round_schedule: STAGE3_SUMCHECK_DRIVER_{index}_ROUND_SCHEDULE, claim_label: {}, round_label: {}, num_rounds: {}, degree: {} }},", + rust_str(&driver.symbol), + rust_str(&driver.stage), + rust_str(&driver.proof_slot), + rust_str(kernel), + rust_str(&driver.batch), + rust_str(&driver.policy), + rust_str(&driver.claim_label), + rust_str(&driver.round_label), + driver.num_rounds, + driver.degree + )); + } else { + let relation = driver.relation.as_deref().ok_or_else(|| { + missing_role_binding("verifier driver relation", &driver.symbol) + })?; + drivers.push(format!( + " Stage3SumcheckDriverPlan {{ symbol: {}, stage: {}, proof_slot: {}, kernel: None, relation: Some({}), batch: {}, policy: {}, round_schedule: STAGE3_SUMCHECK_DRIVER_{index}_ROUND_SCHEDULE, claim_label: {}, round_label: {}, num_rounds: {}, degree: {} }},", + rust_str(&driver.symbol), + rust_str(&driver.stage), + rust_str(&driver.proof_slot), + rust_str(relation), + rust_str(&driver.batch), + rust_str(&driver.policy), + rust_str(&driver.claim_label), + rust_str(&driver.round_label), + driver.num_rounds, + driver.degree + )); + } + } + let drivers = drivers.join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE3_SUMCHECK_DRIVERS: &[Stage3SumcheckDriverPlan] = &[\n{drivers}\n];\n" + ), + ); + Ok(source) + } + + fn emit_tail_constants(&self) -> String { + let mut source = String::new(); + source.push_str(&self.emit_sumcheck_instance_result_constants()); + source.push_str(&self.emit_sumcheck_eval_constants()); + source.push_str(&self.emit_point_slice_constants()); + source.push_str(&self.emit_point_concat_constants()); + source.push_str(&self.emit_opening_claim_constants()); + source.push_str(&self.emit_opening_claim_equality_constants()); + source.push_str(&self.emit_opening_batch_constants()); + source + } + + fn emit_sumcheck_instance_result_constants(&self) -> String { + let instances = self + .instance_results + .iter() + .map(|instance| { + format!( + " Stage3SumcheckInstanceResultPlan {{ symbol: {}, source: {}, claim: {}, relation: {}, index: {}, point_arity: {}, num_rounds: {}, round_offset: {}, point_order: {}, degree: {} }},", + rust_str(&instance.symbol), + rust_str(&instance.source), + rust_str(&instance.claim), + rust_str(&instance.relation), + instance.index, + instance.point_arity, + instance.num_rounds, + instance.round_offset, + rust_str(&instance.point_order), + instance.degree + ) + }) + .collect::>() + .join("\n"); + format!( + "pub const STAGE3_SUMCHECK_INSTANCE_RESULTS: &[Stage3SumcheckInstanceResultPlan] = &[\n{instances}\n];\n\n" + ) + } + + fn emit_sumcheck_eval_constants(&self) -> String { + let evals = self + .evals + .iter() + .map(|eval| { + format!( + " Stage3SumcheckEvalPlan {{ symbol: {}, source: {}, name: {}, index: {}, oracle: {} }},", + rust_str(&eval.symbol), + rust_str(&eval.source), + rust_str(&eval.name), + eval.index, + rust_str(&eval.oracle) + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE3_SUMCHECK_EVALS: &[Stage3SumcheckEvalPlan] = &[\n{evals}\n];\n\n") + } + + fn emit_point_slice_constants(&self) -> String { + let slices = self + .point_slices + .iter() + .map(|slice| { + format!( + " Stage3PointSlicePlan {{ symbol: {}, source: {}, offset: {}, length: {}, input: {} }},", + rust_str(&slice.symbol), + rust_str(&slice.source), + slice.offset, + slice.length, + rust_str(&slice.input) + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE3_POINT_SLICES: &[Stage3PointSlicePlan] = &[\n{slices}\n];\n\n") + } + + fn emit_point_concat_constants(&self) -> String { + if self.role == Role::Verifier { + let concats = self + .point_concats + .iter() + .map(|concat| { + format!( + " Stage3PointConcatPlan {{ symbol: {}, layout: {}, arity: {}, inputs: {} }},", + rust_str(&concat.symbol), + rust_str(&concat.layout), + concat.arity, + rust_str(&concat.inputs.join("|")) + ) + }) + .collect::>() + .join("\n"); + return format!( + "pub const STAGE3_POINT_CONCATS: &[Stage3PointConcatPlan] = &[\n{concats}\n];\n" + ); + } + + let mut source = String::new(); + for (index, concat) in self.point_concats.iter().enumerate() { + source.push_str(&emit_str_array( + &format!("STAGE3_POINT_CONCAT_{index}_INPUTS"), + &concat.inputs, + )); + } + let concats = self + .point_concats + .iter() + .enumerate() + .map(|(index, concat)| { + format!( + " Stage3PointConcatPlan {{ symbol: {}, layout: {}, arity: {}, inputs: STAGE3_POINT_CONCAT_{index}_INPUTS }},", + rust_str(&concat.symbol), + rust_str(&concat.layout), + concat.arity + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE3_POINT_CONCATS: &[Stage3PointConcatPlan] = &[\n{concats}\n];\n" + ), + ); + source + } + + fn emit_opening_claim_constants(&self) -> String { + let claims = self + .opening_claims + .iter() + .map(|claim| { + format!( + " Stage3OpeningClaimPlan {{ symbol: {}, oracle: {}, domain: {}, point_arity: {}, claim_kind: {}, point_source: {}, eval_source: {} }},", + rust_str(&claim.symbol), + rust_str(&claim.oracle), + rust_str(&claim.domain), + claim.point_arity, + rust_str(&claim.claim_kind), + rust_str(&claim.point_source), + rust_str(&claim.eval_source) + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE3_OPENING_CLAIMS: &[Stage3OpeningClaimPlan] = &[\n{claims}\n];\n\n") + } + + fn emit_opening_claim_equality_constants(&self) -> String { + let equalities = self + .opening_equalities + .iter() + .map(|equality| { + format!( + " Stage3OpeningClaimEqualityPlan {{ symbol: {}, mode: {}, lhs: {}, rhs: {} }},", + rust_str(&equality.symbol), + rust_str(&equality.mode), + rust_str(&equality.lhs), + rust_str(&equality.rhs) + ) + }) + .collect::>() + .join("\n"); + format!( + "pub const STAGE3_OPENING_EQUALITIES: &[Stage3OpeningClaimEqualityPlan] = &[\n{equalities}\n];\n\n" + ) + } + + fn emit_opening_batch_constants(&self) -> String { + if self.role == Role::Verifier { + let batches = self + .opening_batches + .iter() + .map(|batch| { + format!( + " Stage3OpeningBatchPlan {{ symbol: {}, stage: {}, proof_slot: {}, policy: {}, count: {}, ordered_claims: {}, claim_operands: {} }},", + rust_str(&batch.symbol), + rust_str(&batch.stage), + rust_str(&batch.proof_slot), + rust_str(&batch.policy), + batch.count, + rust_str(&batch.ordered_claims.join("|")), + rust_str(&batch.claim_operands.join("|")) + ) + }) + .collect::>() + .join("\n"); + return format!( + "pub const STAGE3_OPENING_BATCHES: &[Stage3OpeningBatchPlan] = &[\n{batches}\n];\n" + ); + } + + let mut source = String::new(); + for (index, batch) in self.opening_batches.iter().enumerate() { + source.push_str(&emit_str_array( + &format!("STAGE3_OPENING_BATCH_{index}_ORDERED_CLAIMS"), + &batch.ordered_claims, + )); + source.push_str(&emit_str_array( + &format!("STAGE3_OPENING_BATCH_{index}_CLAIM_OPERANDS"), + &batch.claim_operands, + )); + } + let batches = self + .opening_batches + .iter() + .enumerate() + .map(|(index, batch)| { + format!( + " Stage3OpeningBatchPlan {{ symbol: {}, stage: {}, proof_slot: {}, policy: {}, count: {}, ordered_claims: STAGE3_OPENING_BATCH_{index}_ORDERED_CLAIMS, claim_operands: STAGE3_OPENING_BATCH_{index}_CLAIM_OPERANDS }},", + rust_str(&batch.symbol), + rust_str(&batch.stage), + rust_str(&batch.proof_slot), + rust_str(&batch.policy), + batch.count + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE3_OPENING_BATCHES: &[Stage3OpeningBatchPlan] = &[\n{batches}\n];\n" + ), + ); + source + } + + fn emit_prover_entrypoint() -> &'static str { + "pub fn execute_stage3_prover(\n\ + \x20 executor: &mut E,\n\ + \x20 transcript: &mut T,\n\ + ) -> Result, Stage3KernelError>\n\ + where\n\ + \x20 E: Stage3KernelExecutor,\n\ + \x20 T: Transcript,\n\ + {\n\ + \x20 execute_stage3_prover_with_program(&STAGE3_PROGRAM, executor, transcript)\n\ + }\n\ + \n\ + pub fn execute_stage3_prover_with_program(\n\ + \x20 program: &'static Stage3CpuProgramPlan,\n\ + \x20 executor: &mut E,\n\ + \x20 transcript: &mut T,\n\ + ) -> Result, Stage3KernelError>\n\ + where\n\ + \x20 E: Stage3KernelExecutor,\n\ + \x20 T: Transcript,\n\ + {\n\ + \x20 execute_stage3_program(program, Stage3ExecutionMode::Prover, executor, transcript)\n\ + }\n" + } + + fn emit_verifier_entrypoint() -> &'static str { + r#"pub fn verify_stage3( + proof: &Stage3Proof, + opening_inputs: &[Stage3OpeningInputValue], + transcript: &mut T, +) -> Result, VerifyStage3Error> +where + T: Transcript, +{ + verify_stage3_with_program(&STAGE3_PROGRAM, proof, opening_inputs, transcript) +} + +pub fn verify_stage3_with_program( + program: &'static Stage3VerifierProgramPlan, + proof: &Stage3Proof, + opening_inputs: &[Stage3OpeningInputValue], + transcript: &mut T, +) -> Result, VerifyStage3Error> +where + T: Transcript, +{ + if proof.sumchecks.len() != program.drivers.len() { + return Err(VerifyStage3Error::UnexpectedProofCount { + expected: program.drivers.len(), + got: proof.sumchecks.len(), + }); + } + let mut store = + super::common::ValueStore::with_opening_inputs(opening_inputs, program.opening_inputs)?; + store.seed_constants(program.field_constants); + let mut artifacts = Stage3ExecutionArtifacts::default(); + for step in program.steps { + match step.kind { + "transcript_squeeze" => { + let squeeze = + find_plan(program.transcript_squeezes, step.symbol).ok_or(VerifyStage3Error::MissingValue { + symbol: step.symbol, + })?; + verify_stage3_squeeze(program, squeeze, &mut store, transcript, &mut artifacts)?; + } + "sumcheck_driver" => { + let driver = + find_plan(program.drivers, step.symbol).ok_or(VerifyStage3Error::MissingProof { + driver: step.symbol, + })?; + verify_stage3_driver(program, driver, proof, &mut store, transcript, &mut artifacts)?; + } + _ => { + return Err(VerifyStage3Error::InvalidProof { + driver: step.symbol, + reason: "unsupported stage3 program step", + }); + } + } + } + artifacts + .opening_batches + .extend(program.opening_batches.iter()); + Ok(artifacts) +} + +pub fn stage3_verifier_program() -> &'static Stage3VerifierProgramPlan { + &STAGE3_PROGRAM +} + +fn verify_stage3_squeeze( + program: &'static Stage3VerifierProgramPlan, + squeeze: &'static Stage3TranscriptSqueezePlan, + store: &mut super::common::ValueStore, + transcript: &mut T, + artifacts: &mut Stage3ExecutionArtifacts, +) -> Result<(), VerifyStage3Error> +where + T: Transcript, +{ + let values = transcript.challenge_vector(squeeze.count); + store.observe_challenge_vector(squeeze, &values, |input, expected, actual| { + VerifyStage3Error::InvalidInputLength { + input, + expected, + actual, + } + })?; + store + .evaluate_available_field_exprs(program.field_exprs, super::common::evaluate_field_expr) + .map_err(VerifyStage3Error::from)?; + artifacts.challenge_vectors.push(Stage3ChallengeVector { + symbol: squeeze.symbol, + values, + }); + Ok(()) +} + +fn verify_stage3_driver( + program: &'static Stage3VerifierProgramPlan, + driver: &'static Stage3SumcheckDriverPlan, + proof: &Stage3Proof, + store: &mut super::common::ValueStore, + transcript: &mut T, + artifacts: &mut Stage3ExecutionArtifacts, +) -> Result<(), VerifyStage3Error> +where + T: Transcript, +{ + let proof = proof + .sumchecks + .get(artifacts.sumchecks.len()) + .ok_or(VerifyStage3Error::MissingProof { + driver: driver.symbol, + })?; + let relation = driver.relation.unwrap_or(""); + let output = match relation { + "jolt.stage3.batched" => { + verify_batched_stage3(program, driver, proof, store, transcript)? + } + _ => { + return Err(VerifyStage3Error::UnsupportedRelation { + relation, + }); + } + }; + artifacts.sumchecks.push(output); + Ok(()) +} + +fn verify_batched_stage3( + program: &'static Stage3VerifierProgramPlan, + driver: &'static Stage3SumcheckDriverPlan, + proof: &Stage3SumcheckOutput, + store: &mut super::common::ValueStore, + transcript: &mut T, +) -> Result, VerifyStage3Error> +where + T: Transcript, +{ + super::common::verify_batched_sumcheck( + driver, + proof, + program.claims, + program.batches, + program.field_exprs, + program.opening_inputs, + program.opening_claims, + program.opening_batches, + store, + transcript, + |store, evals, point, batching_coeffs| { + expected_batched_output_claim(program, driver, store, evals, point, batching_coeffs) + }, + |store, verified| observe_stage3_sumcheck_output(program, store, verified), + |driver, error| VerifyStage3Error::Sumcheck { driver, error }, + ) +} + +fn observe_stage3_sumcheck_output( + program: &'static Stage3VerifierProgramPlan, + store: &mut super::common::ValueStore, + output: &Stage3SumcheckOutput, +) -> Result<(), VerifyStage3Error> { + store.observe_sumcheck_output( + program.instance_results, + program.evals, + output, + |instance, mut point| { + match instance.point_order { + "as_is" => {} + "reverse" => point.reverse(), + _ => { + return Err(VerifyStage3Error::InvalidProof { + driver: output.driver, + reason: "unsupported point order", + }); + } + } + Ok(point) + }, + |input, expected, actual| VerifyStage3Error::InvalidInputLength { + input, + expected, + actual, + }, + |symbol| VerifyStage3Error::MissingValue { symbol }, + )?; + store.evaluate_available_points( + program.point_slices, + program.point_concats, + |input, expected, actual| VerifyStage3Error::InvalidInputLength { + input, + expected, + actual, + }, + )?; + store + .evaluate_available_field_exprs(program.field_exprs, super::common::evaluate_field_expr) + .map_err(VerifyStage3Error::from)?; + store.verify_opening_equalities( + program.opening_equalities, + |driver, reason| VerifyStage3Error::InvalidProof { driver, reason }, + |symbol| VerifyStage3Error::MissingValue { symbol }, + ) +} + +fn expected_batched_output_claim( + program: &'static Stage3VerifierProgramPlan, + driver: &'static Stage3SumcheckDriverPlan, + store: &super::common::ValueStore, + evals: &[Stage3NamedEval], + point: &[Fr], + batching_coeffs: &[Fr], +) -> Result { + let batch = find_batch(program.batches, driver.symbol, driver.batch)?; + let claims = batch_claims(program.claims, batch)?; + let mut expected = Fr::from_u64(0); + for (claim, coefficient) in claims.iter().zip(batching_coeffs) { + let instance = program + .instance_results + .iter() + .find(|instance| instance.claim == claim.symbol && instance.source == driver.symbol) + .ok_or(VerifyStage3Error::MissingClaim { + batch: batch.symbol, + claim: claim.symbol, + })?; + let local_point = point + .get(instance.round_offset..instance.round_offset + instance.num_rounds) + .ok_or(VerifyStage3Error::InvalidInputLength { + input: instance.symbol, + expected: instance.round_offset + instance.num_rounds, + actual: point.len(), + })?; + let value = match instance.relation { + "jolt.stage3.spartan_shift" => { + expected_spartan_shift(store, evals, local_point)? + } + "jolt.stage3.instruction_input" => { + expected_instruction_input(store, evals, local_point)? + } + "jolt.stage3.registers_claim_reduction" => { + expected_registers(store, evals, local_point)? + } + _ => { + return Err(VerifyStage3Error::UnsupportedRelation { + relation: instance.relation, + }); + } + }; + expected += *coefficient * value; + } + Ok(expected) +} + +fn expected_spartan_shift( + store: &super::common::ValueStore, + evals: &[Stage3NamedEval], + local_point: &[Fr], +) -> Result { + let opening_point = reverse_slice(local_point); + let eq_outer = + EqPlusOnePolynomial::::new(super::common::store_point(store, "stage3.input.stage1.NextPC")?.to_vec()) + .evaluate(&opening_point); + let eq_product = EqPlusOnePolynomial::::new( + super::common::store_point(store, "stage3.input.stage2.product_virtual.NextIsNoop")? + .to_vec(), + ) + .evaluate(&opening_point); + let weighted_outer = eval_by_name(evals, "stage3.spartan_shift.eval.UnexpandedPC")? + + super::common::store_scalar(store, "stage3.spartan_shift.gamma")? + * eval_by_name(evals, "stage3.spartan_shift.eval.PC")? + + super::common::store_scalar(store, "stage3.spartan_shift.gamma2")? + * eval_by_name(evals, "stage3.spartan_shift.eval.OpFlagVirtualInstruction")? + + super::common::store_scalar(store, "stage3.spartan_shift.gamma3")? + * eval_by_name(evals, "stage3.spartan_shift.eval.OpFlagIsFirstInSequence")?; + Ok(eq_outer * weighted_outer + + super::common::store_scalar(store, "stage3.spartan_shift.gamma4")? + * eq_product + * (Fr::from_u64(1) + - eval_by_name(evals, "stage3.spartan_shift.eval.InstructionFlagIsNoop")?)) +} + +fn expected_instruction_input( + store: &super::common::ValueStore, + evals: &[Stage3NamedEval], + local_point: &[Fr], +) -> Result { + let opening_point = reverse_slice(local_point); + let eq_eval = EqPolynomial::::mle( + &opening_point, + super::common::store_point(store, "stage3.input.stage2.product_virtual.LeftInstructionInput")?, + ); + let left = eval_by_name( + evals, + "stage3.instruction_input.eval.InstructionFlagLeftOperandIsRs1Value", + )? * eval_by_name(evals, "stage3.instruction_input.eval.Rs1Value")? + + eval_by_name( + evals, + "stage3.instruction_input.eval.InstructionFlagLeftOperandIsPC", + )? * eval_by_name(evals, "stage3.instruction_input.eval.UnexpandedPC")?; + let right = eval_by_name( + evals, + "stage3.instruction_input.eval.InstructionFlagRightOperandIsRs2Value", + )? * eval_by_name(evals, "stage3.instruction_input.eval.Rs2Value")? + + eval_by_name( + evals, + "stage3.instruction_input.eval.InstructionFlagRightOperandIsImm", + )? * eval_by_name(evals, "stage3.instruction_input.eval.Imm")?; + Ok(eq_eval * (right + super::common::store_scalar(store, "stage3.instruction_input.gamma")? * left)) +} + +fn expected_registers( + store: &super::common::ValueStore, + evals: &[Stage3NamedEval], + local_point: &[Fr], +) -> Result { + let opening_point = reverse_slice(local_point); + let eq_eval = EqPolynomial::::mle( + &opening_point, + super::common::store_point(store, "stage3.input.stage1.RdWriteValue")?, + ); + Ok(eq_eval + * (eval_by_name(evals, "stage3.registers_claim_reduction.eval.RdWriteValue")? + + super::common::store_scalar(store, "stage3.registers.gamma")? + * eval_by_name(evals, "stage3.registers_claim_reduction.eval.Rs1Value")? + + super::common::store_scalar(store, "stage3.registers.gamma2")? + * eval_by_name(evals, "stage3.registers_claim_reduction.eval.Rs2Value")?)) +} + +"# + } +} + +fn require_supported_symbol(kind: &str, actual: &str, expected: &str) -> Result<(), EmitError> { + if actual == expected { + Ok(()) + } else { + Err(EmitError::new(format!( + "unsupported {kind} @{actual}; expected @{expected}" + ))) + } +} + +fn emit_str_array(name: &str, values: &[String]) -> String { + if values.is_empty() { + return format!("pub const {name}: &[&str] = &[];\n\n"); + } + if let [value] = values { + return format!("pub const {name}: &[&str] = &[{}];\n\n", rust_str(value)); + } + let entries = values + .iter() + .map(|value| format!(" {},", rust_str(value))) + .collect::>() + .join("\n"); + format!("pub const {name}: &[&str] = &[\n{entries}\n];\n\n") +} + +fn emit_usize_array(name: &str, values: &[usize]) -> String { + let entries = values + .iter() + .map(|value| format!(" {value},")) + .collect::>() + .join("\n"); + format!("pub const {name}: &[usize] = &[\n{entries}\n];\n\n") +} + +fn intern_str_array( + source: &mut String, + arrays: &mut Vec<(Vec, String)>, + name_prefix: &str, + values: &[String], +) -> String { + if let Some((_, name)) = arrays + .iter() + .find(|(existing, _)| existing.as_slice() == values) + { + return name.clone(); + } + let name = format!("{name_prefix}_{}", arrays.len()); + source.push_str(&emit_str_array(&name, values)); + arrays.push((values.to_vec(), name.clone())); + name +} + +fn rust_str(value: &str) -> String { + format!("{value:?}") +} + +fn verify_count(kind: &str, symbol: &str, expected: usize, actual: usize) -> Result<(), EmitError> { + if expected == actual { + Ok(()) + } else { + Err(EmitError::new(format!( + "{kind} @{symbol} count mismatch: expected {expected}, got {actual}" + ))) + } +} + +fn missing_role_binding(kind: &str, symbol: &str) -> EmitError { + EmitError::new(format!("missing {kind} for `{symbol}`")) +} + +fn symbols<'a>(values: impl Iterator) -> BTreeSet { + values.cloned().collect() +} + +fn string_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .ok() + .and_then(string_attribute_value) + .ok_or_else(|| attr_error(operation, attr, "string")) +} + +fn symbol_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .ok() + .and_then(symbol_attribute_value) + .ok_or_else(|| attr_error(operation, attr, "symbol")) +} + +fn symbol_array_attr( + operation: OperationRef<'_, '_>, + attr: &str, +) -> Result, EmitError> { + let attribute = operation + .attribute(attr) + .map(|attribute| attribute.to_string()) + .ok() + .ok_or_else(|| attr_error(operation, attr, "symbol array"))?; + parse_symbol_array(&attribute).ok_or_else(|| attr_error(operation, attr, "symbol array")) +} + +fn parse_symbol_array(attribute: &str) -> Option> { + let inner = attribute.strip_prefix('[')?.strip_suffix(']')?.trim(); + if inner.is_empty() { + return Some(Vec::new()); + } + inner + .split(',') + .map(|item| item.trim().strip_prefix('@').map(ToOwned::to_owned)) + .collect() +} + +fn int_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .map(parse_integer_attr) + .ok() + .flatten() + .ok_or_else(|| attr_error(operation, attr, "integer")) +} + +fn signed_int_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .map(parse_signed_integer_attr) + .ok() + .flatten() + .ok_or_else(|| attr_error(operation, attr, "signed integer")) +} + +fn parse_integer_attr(attribute: Attribute<'_>) -> Option { + attribute + .to_string() + .split_whitespace() + .next() + .and_then(|value| value.parse().ok()) +} + +fn parse_signed_integer_attr(attribute: Attribute<'_>) -> Option { + attribute + .to_string() + .split_whitespace() + .next() + .and_then(|value| value.parse().ok()) +} + +fn int_array_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result, EmitError> { + let attribute = operation + .attribute(attr) + .map(|attribute| attribute.to_string()) + .ok() + .ok_or_else(|| attr_error(operation, attr, "integer array"))?; + parse_int_array(&attribute).ok_or_else(|| attr_error(operation, attr, "integer array")) +} + +fn parse_int_array(attribute: &str) -> Option> { + let inner = attribute.strip_prefix('[')?.strip_suffix(']')?.trim(); + if inner.is_empty() { + return Some(Vec::new()); + } + inner + .split(',') + .map(|item| item.trim().parse().ok()) + .collect() +} + +fn operand_symbols( + operation: OperationRef<'_, '_>, + start_index: usize, +) -> Result, EmitError> { + (start_index..operation.operand_count()) + .map(|index| operand_symbol(operation, index)) + .collect() +} + +fn operand_symbol(operation: OperationRef<'_, '_>, index: usize) -> Result { + let operand = operation.operand(index).map_err(|_| { + EmitError::new(format!( + "{} requires operand {index}", + operation_name(operation) + )) + })?; + let owner = OperationResult::try_from(operand).map_err(|_| { + EmitError::new(format!( + "{} operand {index} must be an op result", + operation_name(operation) + )) + })?; + string_attr(owner.owner(), "sym_name") +} + +fn attr_error(operation: OperationRef<'_, '_>, attr: &str, expected: &str) -> EmitError { + EmitError::new(format!( + "{} attr `{attr}` is not a {expected}", + operation_name(operation) + )) +} + +fn operation_name<'c: 'a, 'a>(operation: impl OperationLike<'c, 'a>) -> String { + operation + .name() + .as_string_ref() + .as_str() + .unwrap_or("") + .to_owned() +} diff --git a/crates/bolt/src/protocols/jolt/emit/rust/stage4.rs b/crates/bolt/src/protocols/jolt/emit/rust/stage4.rs new file mode 100644 index 0000000000..b0b5c0ca63 --- /dev/null +++ b/crates/bolt/src/protocols/jolt/emit/rust/stage4.rs @@ -0,0 +1,2487 @@ +#![expect( + clippy::needless_raw_string_hashes, + reason = "generated Rust templates are kept as raw string blocks for copyable output" +)] + +use std::collections::{BTreeMap, BTreeSet}; + +use melior::ir::block::BlockLike; +use melior::ir::operation::{OperationLike, OperationResult}; +use melior::ir::{Attribute, OperationRef}; + +use crate::emit::rust::{push_format, EmitError, RustSourceFile}; +use crate::ir::{string_attribute_value, symbol_attribute_value, BoltModule, Cpu, Role}; +use crate::schema::verify_cpu_schema; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage4CpuProgram { + pub role: Role, + pub params: Stage4Params, + pub steps: Vec, + pub transcript_squeezes: Vec, + pub transcript_absorb_bytes: Vec, + pub opening_inputs: Vec, + pub field_constants: Vec, + pub field_exprs: Vec, + pub kernels: Vec, + pub claims: Vec, + pub batches: Vec, + pub drivers: Vec, + pub instance_results: Vec, + pub evals: Vec, + pub point_slices: Vec, + pub point_concats: Vec, + pub opening_claims: Vec, + pub opening_equalities: Vec, + pub opening_batches: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage4Params { + pub field: String, + pub pcs: String, + pub transcript: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage4KernelPlan { + pub symbol: String, + pub relation: String, + pub kind: String, + pub backend: String, + pub abi: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage4TranscriptSqueezePlan { + pub symbol: String, + pub label: String, + pub kind: String, + pub count: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage4TranscriptAbsorbBytesPlan { + pub symbol: String, + pub label: String, + pub payload: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage4ProgramStepPlan { + pub kind: String, + pub symbol: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage4OpeningInputPlan { + pub symbol: String, + pub source_stage: String, + pub source_claim: String, + pub oracle: String, + pub domain: String, + pub point_arity: usize, + pub claim_kind: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage4FieldConstantPlan { + pub symbol: String, + pub field: String, + pub value: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage4FieldExprPlan { + pub symbol: String, + pub kind: String, + pub formula: String, + pub operand_names: Vec, + pub operands: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage4SumcheckClaimPlan { + pub symbol: String, + pub stage: String, + pub domain: String, + pub num_rounds: usize, + pub degree: usize, + pub claim: String, + pub kernel: Option, + pub relation: Option, + pub claim_value: String, + pub input_openings: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage4SumcheckBatchPlan { + pub symbol: String, + pub stage: String, + pub proof_slot: String, + pub policy: String, + pub count: usize, + pub ordered_claims: Vec, + pub claim_operands: Vec, + pub claim_label: String, + pub round_label: String, + pub round_schedule: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage4SumcheckDriverPlan { + pub symbol: String, + pub stage: String, + pub proof_slot: String, + pub kernel: Option, + pub relation: Option, + pub batch: String, + pub policy: String, + pub round_schedule: Vec, + pub claim_label: String, + pub round_label: String, + pub num_rounds: usize, + pub degree: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage4SumcheckInstanceResultPlan { + pub symbol: String, + pub source: String, + pub claim: String, + pub relation: String, + pub index: usize, + pub point_arity: usize, + pub num_rounds: usize, + pub round_offset: usize, + pub point_order: String, + pub degree: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage4SumcheckEvalPlan { + pub symbol: String, + pub source: String, + pub name: String, + pub index: usize, + pub oracle: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage4PointSlicePlan { + pub symbol: String, + pub source: String, + pub offset: usize, + pub length: usize, + pub input: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage4PointConcatPlan { + pub symbol: String, + pub layout: String, + pub arity: usize, + pub inputs: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage4OpeningClaimPlan { + pub symbol: String, + pub oracle: String, + pub domain: String, + pub point_arity: usize, + pub claim_kind: String, + pub point_source: String, + pub eval_source: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage4OpeningClaimEqualityPlan { + pub symbol: String, + pub mode: String, + pub lhs: String, + pub rhs: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage4OpeningBatchPlan { + pub symbol: String, + pub stage: String, + pub proof_slot: String, + pub policy: String, + pub count: usize, + pub ordered_claims: Vec, + pub claim_operands: Vec, +} + +pub fn stage4_cpu_program(module: &BoltModule<'_, Cpu>) -> Result { + verify_cpu_schema(module)?; + let program = Stage4CpuProgram::from_module(module)?; + program.verify_supported_target()?; + Ok(program) +} + +pub fn emit_stage4_rust(module: &BoltModule<'_, Cpu>) -> Result { + let program = stage4_cpu_program(module)?; + + Ok(RustSourceFile { + filename: program.filename().to_owned(), + source: program.emit_source(), + }) +} + +impl Stage4CpuProgram { + fn from_module(module: &BoltModule<'_, Cpu>) -> Result { + let mut params = None; + let mut steps = Vec::new(); + let mut transcript_squeezes = Vec::new(); + let mut transcript_absorb_bytes = Vec::new(); + let mut opening_inputs = Vec::new(); + let mut field_constants = Vec::new(); + let mut field_exprs = Vec::new(); + let mut kernels = Vec::new(); + let mut claims = Vec::new(); + let mut batches = Vec::new(); + let mut drivers = Vec::new(); + let mut instance_results = Vec::new(); + let mut evals = Vec::new(); + let mut point_slices = Vec::new(); + let mut point_concats = Vec::new(); + let mut opening_claims = Vec::new(); + let mut opening_equalities = Vec::new(); + let mut opening_batches = Vec::new(); + + let mut operation = module.as_mlir_module().body().first_operation(); + while let Some(op) = operation { + operation = op.next_in_block(); + match operation_name(op).as_str() { + "cpu.params" => { + params = Some(Stage4Params { + field: symbol_attr(op, "field")?, + pcs: symbol_attr(op, "pcs")?, + transcript: symbol_attr(op, "transcript")?, + }); + } + "cpu.kernel" => { + kernels.push(Stage4KernelPlan { + symbol: string_attr(op, "sym_name")?, + relation: symbol_attr(op, "relation")?, + kind: string_attr(op, "kind")?, + backend: string_attr(op, "backend")?, + abi: string_attr(op, "abi")?, + }); + } + "cpu.transcript_squeeze" => { + let symbol = string_attr(op, "sym_name")?; + steps.push(Stage4ProgramStepPlan { + kind: "transcript_squeeze".to_owned(), + symbol: symbol.clone(), + }); + transcript_squeezes.push(Stage4TranscriptSqueezePlan { + symbol, + label: string_attr(op, "label")?, + kind: string_attr(op, "kind")?, + count: int_attr(op, "count")?, + }); + } + "cpu.transcript_absorb_bytes" => { + let symbol = string_attr(op, "sym_name")?; + steps.push(Stage4ProgramStepPlan { + kind: "transcript_absorb_bytes".to_owned(), + symbol: symbol.clone(), + }); + transcript_absorb_bytes.push(Stage4TranscriptAbsorbBytesPlan { + symbol, + label: string_attr(op, "label")?, + payload: string_attr(op, "payload")?, + }); + } + "cpu.opening_input" => { + opening_inputs.push(Stage4OpeningInputPlan { + symbol: string_attr(op, "sym_name")?, + source_stage: symbol_attr(op, "source_stage")?, + source_claim: symbol_attr(op, "source_claim")?, + oracle: symbol_attr(op, "oracle")?, + domain: symbol_attr(op, "domain")?, + point_arity: int_attr(op, "point_arity")?, + claim_kind: string_attr(op, "claim_kind")?, + }); + } + "cpu.field_const" => { + field_constants.push(Stage4FieldConstantPlan { + symbol: string_attr(op, "sym_name")?, + field: symbol_attr(op, "field")?, + value: int_attr(op, "value")?, + }); + } + "cpu.field_zero" => { + field_constants.push(Stage4FieldConstantPlan { + symbol: string_attr(op, "sym_name")?, + field: symbol_attr(op, "field")?, + value: 0, + }); + } + "cpu.field_one" => { + field_constants.push(Stage4FieldConstantPlan { + symbol: string_attr(op, "sym_name")?, + field: symbol_attr(op, "field")?, + value: 1, + }); + } + "cpu.field_add" | "cpu.field_sub" | "cpu.field_mul" | "cpu.field_neg" => { + let operands = operand_symbols(op, 0)?; + field_exprs.push(Stage4FieldExprPlan { + symbol: string_attr(op, "sym_name")?, + kind: "op".to_owned(), + formula: operation_name(op).replace("cpu.field_", "field."), + operand_names: operands.clone(), + operands, + }); + } + "cpu.field_pow" => { + let exponent = int_attr(op, "exponent")?; + let operands = operand_symbols(op, 0)?; + field_exprs.push(Stage4FieldExprPlan { + symbol: string_attr(op, "sym_name")?, + kind: "op".to_owned(), + formula: format!("field.pow:{exponent}"), + operand_names: operands.clone(), + operands, + }); + } + "cpu.sumcheck_claim" => { + claims.push(Stage4SumcheckClaimPlan { + symbol: string_attr(op, "sym_name")?, + stage: symbol_attr(op, "stage")?, + domain: symbol_attr(op, "domain")?, + num_rounds: int_attr(op, "num_rounds")?, + degree: int_attr(op, "degree")?, + claim: symbol_attr(op, "claim")?, + kernel: Some(symbol_attr(op, "kernel")?), + relation: None, + claim_value: operand_symbol(op, 0)?, + input_openings: operand_symbols(op, 1)?, + }); + } + "cpu.sumcheck_verify_claim" => { + claims.push(Stage4SumcheckClaimPlan { + symbol: string_attr(op, "sym_name")?, + stage: symbol_attr(op, "stage")?, + domain: symbol_attr(op, "domain")?, + num_rounds: int_attr(op, "num_rounds")?, + degree: int_attr(op, "degree")?, + claim: symbol_attr(op, "claim")?, + kernel: None, + relation: Some(symbol_attr(op, "relation")?), + claim_value: operand_symbol(op, 0)?, + input_openings: operand_symbols(op, 1)?, + }); + } + "cpu.sumcheck_batch" => { + batches.push(Stage4SumcheckBatchPlan { + symbol: string_attr(op, "sym_name")?, + stage: symbol_attr(op, "stage")?, + proof_slot: symbol_attr(op, "proof_slot")?, + policy: string_attr(op, "policy")?, + count: int_attr(op, "count")?, + ordered_claims: symbol_array_attr(op, "ordered_claims")?, + claim_operands: operand_symbols(op, 0)?, + claim_label: string_attr(op, "claim_label")?, + round_label: string_attr(op, "round_label")?, + round_schedule: int_array_attr(op, "round_schedule")?, + }); + } + "cpu.sumcheck_driver" => { + let symbol = string_attr(op, "sym_name")?; + steps.push(Stage4ProgramStepPlan { + kind: "sumcheck_driver".to_owned(), + symbol: symbol.clone(), + }); + drivers.push(Stage4SumcheckDriverPlan { + symbol, + stage: symbol_attr(op, "stage")?, + proof_slot: symbol_attr(op, "proof_slot")?, + kernel: Some(symbol_attr(op, "kernel")?), + relation: None, + batch: operand_symbol(op, 1)?, + policy: string_attr(op, "policy")?, + round_schedule: int_array_attr(op, "round_schedule")?, + claim_label: string_attr(op, "claim_label")?, + round_label: string_attr(op, "round_label")?, + num_rounds: int_attr(op, "num_rounds")?, + degree: int_attr(op, "degree")?, + }); + } + "cpu.sumcheck_verify" => { + let symbol = string_attr(op, "sym_name")?; + steps.push(Stage4ProgramStepPlan { + kind: "sumcheck_driver".to_owned(), + symbol: symbol.clone(), + }); + drivers.push(Stage4SumcheckDriverPlan { + symbol, + stage: symbol_attr(op, "stage")?, + proof_slot: symbol_attr(op, "proof_slot")?, + kernel: None, + relation: Some(symbol_attr(op, "relation")?), + batch: operand_symbol(op, 1)?, + policy: string_attr(op, "policy")?, + round_schedule: int_array_attr(op, "round_schedule")?, + claim_label: string_attr(op, "claim_label")?, + round_label: string_attr(op, "round_label")?, + num_rounds: int_attr(op, "num_rounds")?, + degree: int_attr(op, "degree")?, + }); + } + "cpu.sumcheck_instance_result" => { + instance_results.push(Stage4SumcheckInstanceResultPlan { + symbol: string_attr(op, "sym_name")?, + source: symbol_attr(op, "source")?, + claim: symbol_attr(op, "claim")?, + relation: symbol_attr(op, "relation")?, + index: int_attr(op, "index")?, + point_arity: int_attr(op, "point_arity")?, + num_rounds: int_attr(op, "num_rounds")?, + round_offset: int_attr(op, "round_offset")?, + point_order: string_attr(op, "point_order")?, + degree: int_attr(op, "degree")?, + }); + } + "cpu.sumcheck_eval" => { + evals.push(Stage4SumcheckEvalPlan { + symbol: string_attr(op, "sym_name")?, + source: symbol_attr(op, "source")?, + name: symbol_attr(op, "name")?, + index: int_attr(op, "index")?, + oracle: symbol_attr(op, "oracle")?, + }); + } + "cpu.point_slice" => { + point_slices.push(Stage4PointSlicePlan { + symbol: string_attr(op, "sym_name")?, + source: symbol_attr(op, "source")?, + offset: int_attr(op, "offset")?, + length: int_attr(op, "length")?, + input: operand_symbol(op, 0)?, + }); + } + "cpu.point_concat" => { + point_concats.push(Stage4PointConcatPlan { + symbol: string_attr(op, "sym_name")?, + layout: string_attr(op, "layout")?, + arity: int_attr(op, "arity")?, + inputs: operand_symbols(op, 0)?, + }); + } + "cpu.opening_claim" => { + opening_claims.push(Stage4OpeningClaimPlan { + symbol: string_attr(op, "sym_name")?, + oracle: symbol_attr(op, "oracle")?, + domain: symbol_attr(op, "domain")?, + point_arity: int_attr(op, "point_arity")?, + claim_kind: string_attr(op, "claim_kind")?, + point_source: operand_symbol(op, 0)?, + eval_source: operand_symbol(op, 1)?, + }); + } + "cpu.opening_claim_equal" => { + opening_equalities.push(Stage4OpeningClaimEqualityPlan { + symbol: string_attr(op, "sym_name")?, + mode: string_attr(op, "mode")?, + lhs: operand_symbol(op, 0)?, + rhs: operand_symbol(op, 1)?, + }); + } + "cpu.opening_batch" => { + opening_batches.push(Stage4OpeningBatchPlan { + symbol: string_attr(op, "sym_name")?, + stage: symbol_attr(op, "stage")?, + proof_slot: symbol_attr(op, "proof_slot")?, + policy: string_attr(op, "policy")?, + count: int_attr(op, "count")?, + ordered_claims: symbol_array_attr(op, "ordered_claims")?, + claim_operands: operand_symbols(op, 0)?, + }); + } + _ => {} + } + } + + Ok(Self { + params: params.ok_or_else(|| EmitError::new("missing cpu.params"))?, + role: module + .role() + .ok_or_else(|| EmitError::new("missing cpu party role"))?, + steps, + transcript_squeezes, + transcript_absorb_bytes, + opening_inputs, + field_constants, + field_exprs, + kernels, + claims, + batches, + drivers, + instance_results, + evals, + point_slices, + point_concats, + opening_claims, + opening_equalities, + opening_batches, + }) + } + + fn verify_supported_target(&self) -> Result<(), EmitError> { + require_supported_symbol("field", &self.params.field, "bn254_fr")?; + require_supported_symbol("pcs", &self.params.pcs, "dory")?; + require_supported_symbol("transcript", &self.params.transcript, "blake2b_transcript")?; + self.verify_transcript_steps()?; + self.verify_field_flow()?; + self.verify_claim_batches()?; + match self.role { + Role::Prover => { + self.verify_kernel_definitions()?; + self.verify_prover_driver_bindings()?; + } + Role::Verifier => self.verify_verifier_driver_bindings()?, + } + self.verify_opening_flow() + } + + fn verify_transcript_steps(&self) -> Result<(), EmitError> { + for squeeze in &self.transcript_squeezes { + if !matches!( + squeeze.kind.as_str(), + "challenge_scalar" | "challenge_vector" + ) { + return Err(EmitError::new(format!( + "stage4 transcript squeeze @{} has unsupported kind `{}`", + squeeze.symbol, squeeze.kind + ))); + } + if squeeze.count == 0 { + return Err(EmitError::new(format!( + "stage4 transcript squeeze @{} has zero count", + squeeze.symbol + ))); + } + } + for absorb in &self.transcript_absorb_bytes { + if absorb.label.is_empty() { + return Err(EmitError::new(format!( + "stage4 transcript byte absorb @{} has empty label", + absorb.symbol + ))); + } + } + Ok(()) + } + + fn verify_field_flow(&self) -> Result<(), EmitError> { + for constant in &self.field_constants { + require_supported_symbol("field constant field", &constant.field, "bn254_fr")?; + } + let field_values = self.field_value_symbols(); + for expr in &self.field_exprs { + verify_count( + "field expr operands", + &expr.symbol, + expr.operand_names.len(), + expr.operands.len(), + )?; + for operand in &expr.operands { + if !field_values.contains(operand) { + return Err(EmitError::new(format!( + "field expr @{} references missing field value @{operand}", + expr.symbol + ))); + } + } + } + for claim in &self.claims { + if !field_values.contains(&claim.claim_value) { + return Err(EmitError::new(format!( + "sumcheck claim @{} uses missing claim value @{}", + claim.symbol, claim.claim_value + ))); + } + } + Ok(()) + } + + fn field_value_symbols(&self) -> BTreeSet { + let mut values = symbols(self.opening_inputs.iter().map(|input| &input.symbol)); + values.extend(symbols( + self.field_constants.iter().map(|constant| &constant.symbol), + )); + values.extend(symbols( + self.transcript_squeezes + .iter() + .filter(|squeeze| matches!(squeeze.kind.as_str(), "challenge_scalar" | "scalar")) + .map(|squeeze| &squeeze.symbol), + )); + values.extend(symbols(self.field_exprs.iter().map(|expr| &expr.symbol))); + values.extend(symbols(self.evals.iter().map(|eval| &eval.symbol))); + values + } + + fn verify_kernel_definitions(&self) -> Result<(), EmitError> { + for kernel in &self.kernels { + if kernel.backend != "cpu" { + return Err(EmitError::new(format!( + "stage4 kernel @{} targets unsupported backend `{}`", + kernel.symbol, kernel.backend + ))); + } + if kernel.kind != "sumcheck" { + return Err(EmitError::new(format!( + "stage4 kernel @{} has unsupported kind `{}`", + kernel.symbol, kernel.kind + ))); + } + let expected_abi = match kernel.relation.as_str() { + "jolt.stage4.registers_read_write" => "jolt_stage4_registers_read_write", + "jolt.stage4.ram_val_check" => "jolt_stage4_ram_val_check", + "jolt.stage4.batched" => "jolt_stage4_batched", + _ => { + return Err(EmitError::new(format!( + "unsupported stage4 kernel relation @{}", + kernel.relation + ))); + } + }; + if kernel.abi != expected_abi { + return Err(EmitError::new(format!( + "stage4 kernel @{} ABI `{}` does not match relation @{}", + kernel.symbol, kernel.abi, kernel.relation + ))); + } + } + Ok(()) + } + + fn verify_claim_batches(&self) -> Result<(), EmitError> { + let claims = symbols(self.claims.iter().map(|claim| &claim.symbol)); + for batch in &self.batches { + verify_count( + "sumcheck batch", + &batch.symbol, + batch.count, + batch.ordered_claims.len(), + )?; + verify_count( + "sumcheck batch operands", + &batch.symbol, + batch.count, + batch.claim_operands.len(), + )?; + if batch.ordered_claims != batch.claim_operands { + return Err(EmitError::new(format!( + "sumcheck batch @{} operand order does not match ordered_claims", + batch.symbol + ))); + } + for claim in &batch.ordered_claims { + if !claims.contains(claim) { + return Err(EmitError::new(format!( + "sumcheck batch @{} references missing claim @{claim}", + batch.symbol + ))); + } + } + } + Ok(()) + } + + fn verify_prover_driver_bindings(&self) -> Result<(), EmitError> { + let kernels = symbols(self.kernels.iter().map(|kernel| &kernel.symbol)); + let batches: BTreeMap<_, _> = self + .batches + .iter() + .map(|batch| (batch.symbol.as_str(), batch)) + .collect(); + for claim in &self.claims { + let Some(kernel) = claim.kernel.as_deref() else { + return Err(EmitError::new(format!( + "prover sumcheck claim @{} is missing kernel", + claim.symbol + ))); + }; + if !kernels.contains(kernel) { + return Err(EmitError::new(format!( + "sumcheck claim @{} references missing kernel @{kernel}", + claim.symbol + ))); + } + } + for driver in &self.drivers { + let Some(kernel) = driver.kernel.as_deref() else { + return Err(EmitError::new(format!( + "prover sumcheck driver @{} is missing kernel", + driver.symbol + ))); + }; + if !kernels.contains(kernel) { + return Err(EmitError::new(format!( + "sumcheck driver @{} references missing kernel @{kernel}", + driver.symbol + ))); + } + let batch = batches.get(driver.batch.as_str()).ok_or_else(|| { + EmitError::new(format!( + "sumcheck driver @{} references missing batch @{}", + driver.symbol, driver.batch + )) + })?; + verify_count( + "sumcheck driver round_schedule", + &driver.symbol, + driver.num_rounds, + driver.round_schedule.iter().sum(), + )?; + if driver.round_schedule != batch.round_schedule { + return Err(EmitError::new(format!( + "sumcheck driver @{} round_schedule differs from batch @{}", + driver.symbol, batch.symbol + ))); + } + } + Ok(()) + } + + fn verify_verifier_driver_bindings(&self) -> Result<(), EmitError> { + if !self.kernels.is_empty() { + return Err(EmitError::new( + "verifier stage4 program must not contain kernels", + )); + } + let batches: BTreeMap<_, _> = self + .batches + .iter() + .map(|batch| (batch.symbol.as_str(), batch)) + .collect(); + for claim in &self.claims { + if claim.kernel.is_some() || claim.relation.is_none() { + return Err(EmitError::new(format!( + "verifier sumcheck claim @{} must carry relation and no kernel", + claim.symbol + ))); + } + } + for driver in &self.drivers { + if driver.kernel.is_some() || driver.relation.is_none() { + return Err(EmitError::new(format!( + "verifier sumcheck driver @{} must carry relation and no kernel", + driver.symbol + ))); + } + let batch = batches.get(driver.batch.as_str()).ok_or_else(|| { + EmitError::new(format!( + "sumcheck driver @{} references missing batch @{}", + driver.symbol, driver.batch + )) + })?; + verify_count( + "sumcheck driver round_schedule", + &driver.symbol, + driver.num_rounds, + driver.round_schedule.iter().sum(), + )?; + if driver.round_schedule != batch.round_schedule { + return Err(EmitError::new(format!( + "sumcheck driver @{} round_schedule differs from batch @{}", + driver.symbol, batch.symbol + ))); + } + } + Ok(()) + } + + fn verify_opening_flow(&self) -> Result<(), EmitError> { + let mut point_sources = symbols(self.drivers.iter().map(|driver| &driver.symbol)); + point_sources.extend(symbols( + self.instance_results + .iter() + .map(|instance| &instance.symbol), + )); + point_sources.extend(symbols( + self.opening_inputs.iter().map(|input| &input.symbol), + )); + point_sources.extend(symbols(self.point_slices.iter().map(|slice| &slice.symbol))); + point_sources.extend(symbols( + self.point_concats.iter().map(|concat| &concat.symbol), + )); + for slice in &self.point_slices { + if !point_sources.contains(&slice.input) { + return Err(EmitError::new(format!( + "point slice @{} uses missing point source @{}", + slice.symbol, slice.input + ))); + } + } + for concat in &self.point_concats { + for input in &concat.inputs { + if !point_sources.contains(input) { + return Err(EmitError::new(format!( + "point concat @{} uses missing point source @{input}", + concat.symbol + ))); + } + } + } + let eval_sources = self.field_value_symbols(); + let mut opening_sources = symbols(self.opening_inputs.iter().map(|input| &input.symbol)); + opening_sources.extend(symbols( + self.opening_claims.iter().map(|claim| &claim.symbol), + )); + for equality in &self.opening_equalities { + if !opening_sources.contains(&equality.lhs) { + return Err(EmitError::new(format!( + "opening equality @{} uses missing lhs opening @{}", + equality.symbol, equality.lhs + ))); + } + if !opening_sources.contains(&equality.rhs) { + return Err(EmitError::new(format!( + "opening equality @{} uses missing rhs opening @{}", + equality.symbol, equality.rhs + ))); + } + } + for claim in &self.claims { + for input in &claim.input_openings { + if !opening_sources.contains(input) { + return Err(EmitError::new(format!( + "sumcheck claim @{} uses missing opening @{input}", + claim.symbol + ))); + } + } + } + let drivers = symbols(self.drivers.iter().map(|driver| &driver.symbol)); + for instance in &self.instance_results { + if !drivers.contains(&instance.source) { + return Err(EmitError::new(format!( + "sumcheck instance result @{} references missing driver @{}", + instance.symbol, instance.source + ))); + } + } + for eval in &self.evals { + if !drivers.contains(&eval.source) { + return Err(EmitError::new(format!( + "sumcheck eval @{} references missing driver @{}", + eval.symbol, eval.source + ))); + } + } + for claim in &self.opening_claims { + if !point_sources.contains(&claim.point_source) { + return Err(EmitError::new(format!( + "opening claim @{} uses missing point source @{}", + claim.symbol, claim.point_source + ))); + } + if !eval_sources.contains(&claim.eval_source) { + return Err(EmitError::new(format!( + "opening claim @{} uses missing eval source @{}", + claim.symbol, claim.eval_source + ))); + } + } + let openings = symbols(self.opening_claims.iter().map(|claim| &claim.symbol)); + for batch in &self.opening_batches { + verify_count( + "opening batch", + &batch.symbol, + batch.count, + batch.ordered_claims.len(), + )?; + verify_count( + "opening batch operands", + &batch.symbol, + batch.count, + batch.claim_operands.len(), + )?; + if batch.ordered_claims != batch.claim_operands { + return Err(EmitError::new(format!( + "opening batch @{} operand order does not match ordered_claims", + batch.symbol + ))); + } + for claim in &batch.ordered_claims { + if !openings.contains(claim) { + return Err(EmitError::new(format!( + "opening batch @{} references missing opening @{claim}", + batch.symbol + ))); + } + } + } + Ok(()) + } + + fn filename(&self) -> &'static str { + match self.role { + Role::Prover => "prove_stage4.rs", + Role::Verifier => "verify_stage4.rs", + } + } + + fn emit_source(&self) -> String { + let mut source = String::new(); + source.push_str("#![allow(dead_code)]\n\n"); + match self.role { + Role::Prover => { + source.push_str(Self::emit_prover_imports()); + source.push_str("\n\n"); + source.push_str(Self::emit_prover_types()); + } + Role::Verifier => { + source.push_str(Self::emit_verifier_imports()); + source.push_str("\n\n"); + source.push_str(&Self::emit_verifier_types()); + } + } + source.push('\n'); + source.push_str(&self.emit_constants()); + source.push('\n'); + source.push_str(self.emit_entrypoint()); + source + } + + fn emit_prover_imports() -> &'static str { + "use jolt_field::Fr;\n\ + use jolt_kernels::stage4::{execute_stage4_program, Stage4CpuProgramPlan, Stage4ExecutionArtifacts, Stage4ExecutionMode, Stage4FieldConstantPlan, Stage4FieldExprPlan, Stage4KernelError, Stage4KernelExecutor, Stage4KernelPlan, Stage4OpeningBatchPlan, Stage4OpeningClaimEqualityPlan, Stage4OpeningClaimPlan, Stage4OpeningInputPlan, Stage4Params, Stage4PointConcatPlan, Stage4PointSlicePlan, Stage4ProgramStepPlan, Stage4SumcheckBatchPlan, Stage4SumcheckClaimPlan, Stage4SumcheckDriverPlan, Stage4SumcheckEvalPlan, Stage4SumcheckInstanceResultPlan, Stage4TranscriptAbsorbBytesPlan, Stage4TranscriptSqueezePlan};\n\ + use jolt_transcript::{Blake2bTranscript, Transcript};" + } + + fn emit_prover_types() -> &'static str { + "pub type DefaultStage4Transcript = Blake2bTranscript;\n" + } + + fn emit_verifier_imports() -> &'static str { + "use super::common::{batch_claims, eval_by_name, find_batch, find_plan, lt_polynomial_eval, reverse_slice};\n\ + use jolt_field::{Field, Fr};\n\ + use jolt_poly::EqPolynomial;\n\ + use jolt_sumcheck::SumcheckError;\n\ + use jolt_transcript::{Blake2bTranscript, LabelWithCount, Transcript};" + } + + #[expect(dead_code)] + fn emit_types() -> &'static str { + r#"#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4Params { + pub field: &'static str, + pub pcs: &'static str, + pub transcript: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4KernelPlan { + pub symbol: &'static str, + pub relation: &'static str, + pub kind: &'static str, + pub backend: &'static str, + pub abi: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4TranscriptSqueezePlan { + pub symbol: &'static str, + pub label: &'static str, + pub kind: &'static str, + pub count: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4TranscriptAbsorbBytesPlan { + pub symbol: &'static str, + pub label: &'static str, + pub payload: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4ProgramStepPlan { + pub kind: &'static str, + pub symbol: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4OpeningInputPlan { + pub symbol: &'static str, + pub source_stage: &'static str, + pub source_claim: &'static str, + pub oracle: &'static str, + pub domain: &'static str, + pub point_arity: usize, + pub claim_kind: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4FieldConstantPlan { + pub symbol: &'static str, + pub field: &'static str, + pub value: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4FieldExprPlan { + pub symbol: &'static str, + pub kind: &'static str, + pub formula: &'static str, + pub operand_names: &'static [&'static str], + pub operands: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4SumcheckClaimPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub domain: &'static str, + pub num_rounds: usize, + pub degree: usize, + pub claim: &'static str, + pub kernel: Option<&'static str>, + pub relation: Option<&'static str>, + pub claim_value: &'static str, + pub input_openings: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4SumcheckBatchPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub proof_slot: &'static str, + pub policy: &'static str, + pub count: usize, + pub ordered_claims: &'static [&'static str], + pub claim_operands: &'static [&'static str], + pub claim_label: &'static str, + pub round_label: &'static str, + pub round_schedule: &'static [usize], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4SumcheckDriverPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub proof_slot: &'static str, + pub kernel: Option<&'static str>, + pub relation: Option<&'static str>, + pub batch: &'static str, + pub policy: &'static str, + pub round_schedule: &'static [usize], + pub claim_label: &'static str, + pub round_label: &'static str, + pub num_rounds: usize, + pub degree: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4SumcheckInstanceResultPlan { + pub symbol: &'static str, + pub source: &'static str, + pub claim: &'static str, + pub relation: &'static str, + pub index: usize, + pub point_arity: usize, + pub num_rounds: usize, + pub round_offset: usize, + pub point_order: &'static str, + pub degree: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4SumcheckEvalPlan { + pub symbol: &'static str, + pub source: &'static str, + pub name: &'static str, + pub index: usize, + pub oracle: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4PointSlicePlan { + pub symbol: &'static str, + pub source: &'static str, + pub offset: usize, + pub length: usize, + pub input: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4PointConcatPlan { + pub symbol: &'static str, + pub layout: &'static str, + pub arity: usize, + pub inputs: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4OpeningClaimPlan { + pub symbol: &'static str, + pub oracle: &'static str, + pub domain: &'static str, + pub point_arity: usize, + pub claim_kind: &'static str, + pub point_source: &'static str, + pub eval_source: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4OpeningClaimEqualityPlan { + pub symbol: &'static str, + pub mode: &'static str, + pub lhs: &'static str, + pub rhs: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4OpeningBatchPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub proof_slot: &'static str, + pub policy: &'static str, + pub count: usize, + pub ordered_claims: &'static [&'static str], + pub claim_operands: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4CpuProgramPlan { + pub role: &'static str, + pub params: Stage4Params, + pub steps: &'static [Stage4ProgramStepPlan], + pub transcript_squeezes: &'static [Stage4TranscriptSqueezePlan], + pub transcript_absorb_bytes: &'static [Stage4TranscriptAbsorbBytesPlan], + pub opening_inputs: &'static [Stage4OpeningInputPlan], + pub field_constants: &'static [Stage4FieldConstantPlan], + pub field_exprs: &'static [Stage4FieldExprPlan], + pub kernels: &'static [Stage4KernelPlan], + pub claims: &'static [Stage4SumcheckClaimPlan], + pub batches: &'static [Stage4SumcheckBatchPlan], + pub drivers: &'static [Stage4SumcheckDriverPlan], + pub instance_results: &'static [Stage4SumcheckInstanceResultPlan], + pub evals: &'static [Stage4SumcheckEvalPlan], + pub point_slices: &'static [Stage4PointSlicePlan], + pub point_concats: &'static [Stage4PointConcatPlan], + pub opening_claims: &'static [Stage4OpeningClaimPlan], + pub opening_equalities: &'static [Stage4OpeningClaimEqualityPlan], + pub opening_batches: &'static [Stage4OpeningBatchPlan], +} +"# + } + + fn emit_verifier_type_aliases() -> &'static str { + r#"pub type Stage4NamedEval = super::common::StageNamedEval; +pub type Stage4SumcheckOutput = super::common::StageSumcheckOutput; +pub type Stage4ChallengeVector = super::common::StageChallengeVector; +pub type Stage4ExecutionArtifacts = super::common::StageExecutionArtifacts; +pub type Stage4Proof = super::common::StageProof; +pub type Stage4OpeningInputValue = super::common::StageOpeningInputValue; + +pub use super::common::{ + FieldConstantPlan as Stage4FieldConstantPlan, FieldExprPlan as Stage4FieldExprPlan, + KernelPlan as Stage4KernelPlan, OpeningBatchPlan as Stage4OpeningBatchPlan, + OpeningClaimEqualityPlan as Stage4OpeningClaimEqualityPlan, + OpeningClaimPlan as Stage4OpeningClaimPlan, OpeningInputPlan as Stage4OpeningInputPlan, + PointConcatPlan as Stage4PointConcatPlan, PointSlicePlan as Stage4PointSlicePlan, + ProgramStepPlan as Stage4ProgramStepPlan, StageParams as Stage4Params, + StageProgramPlanNoPointZeros as Stage4CpuProgramPlan, + SumcheckBatchPlan as Stage4SumcheckBatchPlan, + SumcheckClaimPlan as Stage4SumcheckClaimPlan, SumcheckDriverPlan as Stage4SumcheckDriverPlan, + SumcheckEvalPlan as Stage4SumcheckEvalPlan, + SumcheckInstanceResultPlan as Stage4SumcheckInstanceResultPlan, + TranscriptAbsorbBytesPlan as Stage4TranscriptAbsorbBytesPlan, + TranscriptSqueezePlan as Stage4TranscriptSqueezePlan, +}; +"# + } + + fn emit_verifier_types() -> String { + let mut source = Self::emit_verifier_type_aliases().to_owned(); + source.push_str( + r#" +pub type DefaultStage4Transcript = Blake2bTranscript; +pub type Stage4VerifierProgramPlan = Stage4CpuProgramPlan; + +#[derive(Debug)] +pub enum VerifyStage4Error { + UnexpectedProofCount { expected: usize, got: usize }, + MissingProof { driver: &'static str }, + MissingBatch { driver: &'static str, batch: &'static str }, + MissingClaim { batch: &'static str, claim: &'static str }, + MissingValue { symbol: &'static str }, + InvalidInputLength { input: &'static str, expected: usize, actual: usize }, + InvalidProof { driver: &'static str, reason: &'static str }, + UnsupportedFieldExpr { symbol: &'static str, formula: &'static str }, + UnsupportedRelation { relation: &'static str }, + Sumcheck { driver: &'static str, error: SumcheckError }, +} + +super::common::impl_runtime_plan_error_conversion!(VerifyStage4Error); +"#, + ); + source + } + + fn emit_constants(&self) -> String { + let mut source = self.emit_shared_constants(); + source.push_str(&self.emit_kernel_constants()); + source.push_str(&self.emit_sumcheck_claim_constants()); + source.push_str(&self.emit_sumcheck_batch_constants()); + source.push_str(&self.emit_sumcheck_driver_constants()); + source.push_str(&self.emit_tail_constants()); + push_format( + &mut source, + format_args!( + "pub const STAGE4_PROGRAM: {} = Stage4CpuProgramPlan {{\n\ + \x20 role: {},\n\ + \x20 params: STAGE4_PARAMS,\n\ + \x20 steps: STAGE4_PROGRAM_STEPS,\n\ + \x20 transcript_squeezes: STAGE4_TRANSCRIPT_SQUEEZES,\n\ + \x20 transcript_absorb_bytes: STAGE4_TRANSCRIPT_ABSORB_BYTES,\n\ + \x20 opening_inputs: STAGE4_OPENING_INPUTS,\n\ + \x20 field_constants: STAGE4_FIELD_CONSTANTS,\n\ + \x20 field_exprs: STAGE4_FIELD_EXPRS,\n\ + \x20 kernels: STAGE4_KERNELS,\n\ + \x20 claims: STAGE4_SUMCHECK_CLAIMS,\n\ + \x20 batches: STAGE4_SUMCHECK_BATCHES,\n\ + \x20 drivers: STAGE4_SUMCHECK_DRIVERS,\n\ + \x20 instance_results: STAGE4_SUMCHECK_INSTANCE_RESULTS,\n\ + \x20 evals: STAGE4_SUMCHECK_EVALS,\n\ + \x20 point_slices: STAGE4_POINT_SLICES,\n\ + \x20 point_concats: STAGE4_POINT_CONCATS,\n\ + \x20 opening_claims: STAGE4_OPENING_CLAIMS,\n\ + \x20 opening_equalities: STAGE4_OPENING_EQUALITIES,\n\ + \x20 opening_batches: STAGE4_OPENING_BATCHES,\n\ + }};\n", + self.program_plan_type(), + rust_str(self.role_label()) + ), + ); + source + } + + fn emit_shared_constants(&self) -> String { + let mut source = String::new(); + push_format( + &mut source, + format_args!( + "pub const STAGE4_PARAMS: Stage4Params = Stage4Params {{\n\ + \x20 field: {},\n\ + \x20 pcs: {},\n\ + \x20 transcript: {},\n\ + }};\n", + rust_str(&self.params.field), + rust_str(&self.params.pcs), + rust_str(&self.params.transcript) + ), + ); + source.push_str(&self.emit_program_step_constants()); + source.push_str(&self.emit_transcript_squeeze_constants()); + source.push_str(&self.emit_transcript_absorb_bytes_constants()); + source.push_str(&self.emit_opening_input_constants()); + source.push_str(&self.emit_field_constant_constants()); + source.push_str(&self.emit_field_expr_constants()); + source + } + + fn emit_program_step_constants(&self) -> String { + let steps = self + .steps + .iter() + .map(|step| { + format!( + " Stage4ProgramStepPlan {{ kind: {}, symbol: {} }},", + rust_str(&step.kind), + rust_str(&step.symbol), + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE4_PROGRAM_STEPS: &[Stage4ProgramStepPlan] = &[\n{steps}\n];\n\n") + } + + fn emit_transcript_squeeze_constants(&self) -> String { + let squeezes = self + .transcript_squeezes + .iter() + .map(|squeeze| { + format!( + " Stage4TranscriptSqueezePlan {{ symbol: {}, label: {}, kind: {}, count: {} }},", + rust_str(&squeeze.symbol), + rust_str(&squeeze.label), + rust_str(&squeeze.kind), + squeeze.count, + ) + }) + .collect::>() + .join("\n"); + format!( + "pub const STAGE4_TRANSCRIPT_SQUEEZES: &[Stage4TranscriptSqueezePlan] = &[\n{squeezes}\n];\n\n" + ) + } + + fn emit_transcript_absorb_bytes_constants(&self) -> String { + let absorbs = self + .transcript_absorb_bytes + .iter() + .map(|absorb| { + format!( + " Stage4TranscriptAbsorbBytesPlan {{ symbol: {}, label: {}, payload: {} }},", + rust_str(&absorb.symbol), + rust_str(&absorb.label), + rust_str(&absorb.payload), + ) + }) + .collect::>() + .join("\n"); + format!( + "pub const STAGE4_TRANSCRIPT_ABSORB_BYTES: &[Stage4TranscriptAbsorbBytesPlan] = &[\n{absorbs}\n];\n\n" + ) + } + + fn emit_opening_input_constants(&self) -> String { + let inputs = self + .opening_inputs + .iter() + .map(|input| { + format!( + " Stage4OpeningInputPlan {{ symbol: {}, source_stage: {}, source_claim: {}, oracle: {}, domain: {}, point_arity: {}, claim_kind: {} }},", + rust_str(&input.symbol), + rust_str(&input.source_stage), + rust_str(&input.source_claim), + rust_str(&input.oracle), + rust_str(&input.domain), + input.point_arity, + rust_str(&input.claim_kind) + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE4_OPENING_INPUTS: &[Stage4OpeningInputPlan] = &[\n{inputs}\n];\n\n") + } + + fn emit_field_constant_constants(&self) -> String { + let constants = self + .field_constants + .iter() + .map(|constant| { + format!( + " Stage4FieldConstantPlan {{ symbol: {}, field: {}, value: {} }},", + rust_str(&constant.symbol), + rust_str(&constant.field), + constant.value + ) + }) + .collect::>() + .join("\n"); + format!( + "pub const STAGE4_FIELD_CONSTANTS: &[Stage4FieldConstantPlan] = &[\n{constants}\n];\n\n" + ) + } + + fn emit_field_expr_constants(&self) -> String { + if self.role == Role::Verifier { + let exprs = self + .field_exprs + .iter() + .map(|expr| { + format!( + " Stage4FieldExprPlan {{ symbol: {}, kind: {}, formula: {}, operands: {} }},", + rust_str(&expr.symbol), + rust_str(&expr.kind), + rust_str(&expr.formula), + rust_str(&expr.operands.join("|")) + ) + }) + .collect::>() + .join("\n"); + return format!( + "pub const STAGE4_FIELD_EXPRS: &[Stage4FieldExprPlan] = &[\n{exprs}\n];\n" + ); + } + + let mut source = String::new(); + let mut arrays = Vec::new(); + let mut array_refs = Vec::new(); + for (index, expr) in self.field_exprs.iter().enumerate() { + let operands = intern_str_array( + &mut source, + &mut arrays, + "STAGE4_FIELD_EXPR_OPERANDS", + &expr.operands, + ); + let operand_names = intern_str_array( + &mut source, + &mut arrays, + "STAGE4_FIELD_EXPR_OPERANDS", + &expr.operand_names, + ); + array_refs.push((index, operand_names, operands)); + } + let exprs = self + .field_exprs + .iter() + .enumerate() + .map(|(index, expr)| { + let (_, operand_names, operands) = &array_refs[index]; + format!( + " Stage4FieldExprPlan {{ symbol: {}, kind: {}, formula: {}, operand_names: {operand_names}, operands: {operands} }},", + rust_str(&expr.symbol), + rust_str(&expr.kind), + rust_str(&expr.formula) + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE4_FIELD_EXPRS: &[Stage4FieldExprPlan] = &[\n{exprs}\n];\n" + ), + ); + source + } + + fn emit_kernel_constants(&self) -> String { + let kernels = self + .kernels + .iter() + .map(|kernel| { + format!( + " Stage4KernelPlan {{ symbol: {}, relation: {}, kind: {}, backend: {}, abi: {} }},", + rust_str(&kernel.symbol), + rust_str(&kernel.relation), + rust_str(&kernel.kind), + rust_str(&kernel.backend), + rust_str(&kernel.abi) + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE4_KERNELS: &[Stage4KernelPlan] = &[\n{kernels}\n];\n\n") + } + + fn emit_sumcheck_claim_constants(&self) -> String { + if self.role == Role::Verifier { + let claims = self + .claims + .iter() + .map(|claim| { + format!( + " Stage4SumcheckClaimPlan {{ symbol: {}, stage: {}, domain: {}, num_rounds: {}, degree: {}, claim: {}, kernel: {}, relation: {}, claim_value: {}, input_openings: {} }},", + rust_str(&claim.symbol), + rust_str(&claim.stage), + rust_str(&claim.domain), + claim.num_rounds, + claim.degree, + rust_str(&claim.claim), + rust_option_str(claim.kernel.as_deref()), + rust_option_str(claim.relation.as_deref()), + rust_str(&claim.claim_value), + rust_str(&claim.input_openings.join("|")) + ) + }) + .collect::>() + .join("\n"); + return format!( + "pub const STAGE4_SUMCHECK_CLAIMS: &[Stage4SumcheckClaimPlan] = &[\n{claims}\n];\n" + ); + } + + let mut source = String::new(); + for (index, claim) in self.claims.iter().enumerate() { + source.push_str(&emit_str_array( + &format!("STAGE4_SUMCHECK_CLAIM_{index}_INPUT_OPENINGS"), + &claim.input_openings, + )); + } + let claims = self + .claims + .iter() + .enumerate() + .map(|(index, claim)| { + format!( + " Stage4SumcheckClaimPlan {{ symbol: {}, stage: {}, domain: {}, num_rounds: {}, degree: {}, claim: {}, kernel: {}, relation: {}, claim_value: {}, input_openings: STAGE4_SUMCHECK_CLAIM_{index}_INPUT_OPENINGS }},", + rust_str(&claim.symbol), + rust_str(&claim.stage), + rust_str(&claim.domain), + claim.num_rounds, + claim.degree, + rust_str(&claim.claim), + rust_option_str(claim.kernel.as_deref()), + rust_option_str(claim.relation.as_deref()), + rust_str(&claim.claim_value) + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE4_SUMCHECK_CLAIMS: &[Stage4SumcheckClaimPlan] = &[\n{claims}\n];\n" + ), + ); + source + } + + fn emit_sumcheck_batch_constants(&self) -> String { + if self.role == Role::Verifier { + let mut source = String::new(); + for (index, batch) in self.batches.iter().enumerate() { + source.push_str(&emit_usize_array( + &format!("STAGE4_SUMCHECK_BATCH_{index}_ROUND_SCHEDULE"), + &batch.round_schedule, + )); + } + let batches = self + .batches + .iter() + .enumerate() + .map(|(index, batch)| { + format!( + " Stage4SumcheckBatchPlan {{ symbol: {}, stage: {}, proof_slot: {}, policy: {}, count: {}, ordered_claims: {}, claim_operands: {}, claim_label: {}, round_label: {}, round_schedule: STAGE4_SUMCHECK_BATCH_{index}_ROUND_SCHEDULE }},", + rust_str(&batch.symbol), + rust_str(&batch.stage), + rust_str(&batch.proof_slot), + rust_str(&batch.policy), + batch.count, + rust_str(&batch.ordered_claims.join("|")), + rust_str(&batch.claim_operands.join("|")), + rust_str(&batch.claim_label), + rust_str(&batch.round_label) + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE4_SUMCHECK_BATCHES: &[Stage4SumcheckBatchPlan] = &[\n{batches}\n];\n" + ), + ); + return source; + } + + let mut source = String::new(); + for (index, batch) in self.batches.iter().enumerate() { + source.push_str(&emit_str_array( + &format!("STAGE4_SUMCHECK_BATCH_{index}_ORDERED_CLAIMS"), + &batch.ordered_claims, + )); + source.push_str(&emit_str_array( + &format!("STAGE4_SUMCHECK_BATCH_{index}_CLAIM_OPERANDS"), + &batch.claim_operands, + )); + source.push_str(&emit_usize_array( + &format!("STAGE4_SUMCHECK_BATCH_{index}_ROUND_SCHEDULE"), + &batch.round_schedule, + )); + } + let batches = self + .batches + .iter() + .enumerate() + .map(|(index, batch)| { + format!( + " Stage4SumcheckBatchPlan {{ symbol: {}, stage: {}, proof_slot: {}, policy: {}, count: {}, ordered_claims: STAGE4_SUMCHECK_BATCH_{index}_ORDERED_CLAIMS, claim_operands: STAGE4_SUMCHECK_BATCH_{index}_CLAIM_OPERANDS, claim_label: {}, round_label: {}, round_schedule: STAGE4_SUMCHECK_BATCH_{index}_ROUND_SCHEDULE }},", + rust_str(&batch.symbol), + rust_str(&batch.stage), + rust_str(&batch.proof_slot), + rust_str(&batch.policy), + batch.count, + rust_str(&batch.claim_label), + rust_str(&batch.round_label) + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE4_SUMCHECK_BATCHES: &[Stage4SumcheckBatchPlan] = &[\n{batches}\n];\n" + ), + ); + source + } + + fn emit_sumcheck_driver_constants(&self) -> String { + let mut source = String::new(); + for (index, driver) in self.drivers.iter().enumerate() { + source.push_str(&emit_usize_array( + &format!("STAGE4_SUMCHECK_DRIVER_{index}_ROUND_SCHEDULE"), + &driver.round_schedule, + )); + } + let drivers = self + .drivers + .iter() + .enumerate() + .map(|(index, driver)| { + format!( + " Stage4SumcheckDriverPlan {{ symbol: {}, stage: {}, proof_slot: {}, kernel: {}, relation: {}, batch: {}, policy: {}, round_schedule: STAGE4_SUMCHECK_DRIVER_{index}_ROUND_SCHEDULE, claim_label: {}, round_label: {}, num_rounds: {}, degree: {} }},", + rust_str(&driver.symbol), + rust_str(&driver.stage), + rust_str(&driver.proof_slot), + rust_option_str(driver.kernel.as_deref()), + rust_option_str(driver.relation.as_deref()), + rust_str(&driver.batch), + rust_str(&driver.policy), + rust_str(&driver.claim_label), + rust_str(&driver.round_label), + driver.num_rounds, + driver.degree + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE4_SUMCHECK_DRIVERS: &[Stage4SumcheckDriverPlan] = &[\n{drivers}\n];\n" + ), + ); + source + } + + fn emit_tail_constants(&self) -> String { + let mut source = String::new(); + source.push_str(&self.emit_sumcheck_instance_result_constants()); + source.push_str(&self.emit_sumcheck_eval_constants()); + source.push_str(&self.emit_point_slice_constants()); + source.push_str(&self.emit_point_concat_constants()); + source.push_str(&self.emit_opening_claim_constants()); + source.push_str(&self.emit_opening_claim_equality_constants()); + source.push_str(&self.emit_opening_batch_constants()); + source + } + + fn emit_sumcheck_instance_result_constants(&self) -> String { + let instances = self + .instance_results + .iter() + .map(|instance| { + format!( + " Stage4SumcheckInstanceResultPlan {{ symbol: {}, source: {}, claim: {}, relation: {}, index: {}, point_arity: {}, num_rounds: {}, round_offset: {}, point_order: {}, degree: {} }},", + rust_str(&instance.symbol), + rust_str(&instance.source), + rust_str(&instance.claim), + rust_str(&instance.relation), + instance.index, + instance.point_arity, + instance.num_rounds, + instance.round_offset, + rust_str(&instance.point_order), + instance.degree + ) + }) + .collect::>() + .join("\n"); + format!( + "pub const STAGE4_SUMCHECK_INSTANCE_RESULTS: &[Stage4SumcheckInstanceResultPlan] = &[\n{instances}\n];\n\n" + ) + } + + fn emit_sumcheck_eval_constants(&self) -> String { + let evals = self + .evals + .iter() + .map(|eval| { + format!( + " Stage4SumcheckEvalPlan {{ symbol: {}, source: {}, name: {}, index: {}, oracle: {} }},", + rust_str(&eval.symbol), + rust_str(&eval.source), + rust_str(&eval.name), + eval.index, + rust_str(&eval.oracle) + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE4_SUMCHECK_EVALS: &[Stage4SumcheckEvalPlan] = &[\n{evals}\n];\n\n") + } + + fn emit_point_slice_constants(&self) -> String { + let slices = self + .point_slices + .iter() + .map(|slice| { + format!( + " Stage4PointSlicePlan {{ symbol: {}, source: {}, offset: {}, length: {}, input: {} }},", + rust_str(&slice.symbol), + rust_str(&slice.source), + slice.offset, + slice.length, + rust_str(&slice.input) + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE4_POINT_SLICES: &[Stage4PointSlicePlan] = &[\n{slices}\n];\n\n") + } + + fn emit_point_concat_constants(&self) -> String { + if self.role == Role::Verifier { + let concats = self + .point_concats + .iter() + .map(|concat| { + format!( + " Stage4PointConcatPlan {{ symbol: {}, layout: {}, arity: {}, inputs: {} }},", + rust_str(&concat.symbol), + rust_str(&concat.layout), + concat.arity, + rust_str(&concat.inputs.join("|")) + ) + }) + .collect::>() + .join("\n"); + return format!( + "pub const STAGE4_POINT_CONCATS: &[Stage4PointConcatPlan] = &[\n{concats}\n];\n" + ); + } + + let mut source = String::new(); + for (index, concat) in self.point_concats.iter().enumerate() { + source.push_str(&emit_str_array( + &format!("STAGE4_POINT_CONCAT_{index}_INPUTS"), + &concat.inputs, + )); + } + let concats = self + .point_concats + .iter() + .enumerate() + .map(|(index, concat)| { + format!( + " Stage4PointConcatPlan {{ symbol: {}, layout: {}, arity: {}, inputs: STAGE4_POINT_CONCAT_{index}_INPUTS }},", + rust_str(&concat.symbol), + rust_str(&concat.layout), + concat.arity + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE4_POINT_CONCATS: &[Stage4PointConcatPlan] = &[\n{concats}\n];\n" + ), + ); + source + } + + fn emit_opening_claim_constants(&self) -> String { + let claims = self + .opening_claims + .iter() + .map(|claim| { + format!( + " Stage4OpeningClaimPlan {{ symbol: {}, oracle: {}, domain: {}, point_arity: {}, claim_kind: {}, point_source: {}, eval_source: {} }},", + rust_str(&claim.symbol), + rust_str(&claim.oracle), + rust_str(&claim.domain), + claim.point_arity, + rust_str(&claim.claim_kind), + rust_str(&claim.point_source), + rust_str(&claim.eval_source) + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE4_OPENING_CLAIMS: &[Stage4OpeningClaimPlan] = &[\n{claims}\n];\n\n") + } + + fn emit_opening_claim_equality_constants(&self) -> String { + let equalities = self + .opening_equalities + .iter() + .map(|equality| { + format!( + " Stage4OpeningClaimEqualityPlan {{ symbol: {}, mode: {}, lhs: {}, rhs: {} }},", + rust_str(&equality.symbol), + rust_str(&equality.mode), + rust_str(&equality.lhs), + rust_str(&equality.rhs) + ) + }) + .collect::>() + .join("\n"); + format!( + "pub const STAGE4_OPENING_EQUALITIES: &[Stage4OpeningClaimEqualityPlan] = &[\n{equalities}\n];\n\n" + ) + } + + fn emit_opening_batch_constants(&self) -> String { + if self.role == Role::Verifier { + let batches = self + .opening_batches + .iter() + .map(|batch| { + format!( + " Stage4OpeningBatchPlan {{ symbol: {}, stage: {}, proof_slot: {}, policy: {}, count: {}, ordered_claims: {}, claim_operands: {} }},", + rust_str(&batch.symbol), + rust_str(&batch.stage), + rust_str(&batch.proof_slot), + rust_str(&batch.policy), + batch.count, + rust_str(&batch.ordered_claims.join("|")), + rust_str(&batch.claim_operands.join("|")) + ) + }) + .collect::>() + .join("\n"); + return format!( + "pub const STAGE4_OPENING_BATCHES: &[Stage4OpeningBatchPlan] = &[\n{batches}\n];\n" + ); + } + + let mut source = String::new(); + for (index, batch) in self.opening_batches.iter().enumerate() { + source.push_str(&emit_str_array( + &format!("STAGE4_OPENING_BATCH_{index}_ORDERED_CLAIMS"), + &batch.ordered_claims, + )); + source.push_str(&emit_str_array( + &format!("STAGE4_OPENING_BATCH_{index}_CLAIM_OPERANDS"), + &batch.claim_operands, + )); + } + let batches = self + .opening_batches + .iter() + .enumerate() + .map(|(index, batch)| { + format!( + " Stage4OpeningBatchPlan {{ symbol: {}, stage: {}, proof_slot: {}, policy: {}, count: {}, ordered_claims: STAGE4_OPENING_BATCH_{index}_ORDERED_CLAIMS, claim_operands: STAGE4_OPENING_BATCH_{index}_CLAIM_OPERANDS }},", + rust_str(&batch.symbol), + rust_str(&batch.stage), + rust_str(&batch.proof_slot), + rust_str(&batch.policy), + batch.count + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE4_OPENING_BATCHES: &[Stage4OpeningBatchPlan] = &[\n{batches}\n];\n" + ), + ); + source + } + + fn emit_entrypoint(&self) -> &'static str { + match self.role { + Role::Prover => { + "pub fn execute_stage4_prover(\n\ + \x20 executor: &mut E,\n\ + \x20 transcript: &mut T,\n\ + ) -> Result, Stage4KernelError>\n\ + where\n\ + \x20 E: Stage4KernelExecutor,\n\ + \x20 T: Transcript,\n\ + {\n\ + \x20 execute_stage4_prover_with_program(&STAGE4_PROGRAM, executor, transcript)\n\ + }\n\ + \n\ + pub fn execute_stage4_prover_with_program(\n\ + \x20 program: &'static Stage4CpuProgramPlan,\n\ + \x20 executor: &mut E,\n\ + \x20 transcript: &mut T,\n\ + ) -> Result, Stage4KernelError>\n\ + where\n\ + \x20 E: Stage4KernelExecutor,\n\ + \x20 T: Transcript,\n\ + {\n\ + \x20 execute_stage4_program(program, Stage4ExecutionMode::Prover, executor, transcript)\n\ + }\n" + } + Role::Verifier => { + r#"pub fn verify_stage4( + proof: &Stage4Proof, + opening_inputs: &[Stage4OpeningInputValue], + transcript: &mut T, +) -> Result, VerifyStage4Error> +where + T: Transcript, +{ + verify_stage4_with_program(&STAGE4_PROGRAM, proof, opening_inputs, transcript) +} + +pub fn verify_stage4_with_program( + program: &'static Stage4VerifierProgramPlan, + proof: &Stage4Proof, + opening_inputs: &[Stage4OpeningInputValue], + transcript: &mut T, +) -> Result, VerifyStage4Error> +where + T: Transcript, +{ + if proof.sumchecks.len() != program.drivers.len() { + return Err(VerifyStage4Error::UnexpectedProofCount { + expected: program.drivers.len(), + got: proof.sumchecks.len(), + }); + } + let mut store = + super::common::ValueStore::with_opening_inputs(opening_inputs, program.opening_inputs)?; + store.seed_constants(program.field_constants); + let mut artifacts = Stage4ExecutionArtifacts::default(); + for step in program.steps { + match step.kind { + "transcript_squeeze" => { + let squeeze = + find_plan(program.transcript_squeezes, step.symbol).ok_or(VerifyStage4Error::MissingValue { + symbol: step.symbol, + })?; + verify_stage4_squeeze(program, squeeze, &mut store, transcript, &mut artifacts)?; + } + "transcript_absorb_bytes" => { + let absorb = find_plan(program.transcript_absorb_bytes, step.symbol).ok_or( + VerifyStage4Error::MissingValue { + symbol: step.symbol, + }, + )?; + absorb_stage4_bytes(absorb, transcript); + } + "sumcheck_driver" => { + let driver = + find_plan(program.drivers, step.symbol).ok_or(VerifyStage4Error::MissingProof { + driver: step.symbol, + })?; + verify_stage4_driver(program, driver, proof, &mut store, transcript, &mut artifacts)?; + } + _ => { + return Err(VerifyStage4Error::InvalidProof { + driver: step.symbol, + reason: "unsupported stage4 program step", + }); + } + } + } + artifacts + .opening_batches + .extend(program.opening_batches.iter()); + Ok(artifacts) +} + +pub fn stage4_verifier_program() -> &'static Stage4VerifierProgramPlan { + &STAGE4_PROGRAM +} + +fn verify_stage4_squeeze( + program: &'static Stage4VerifierProgramPlan, + squeeze: &'static Stage4TranscriptSqueezePlan, + store: &mut super::common::ValueStore, + transcript: &mut T, + artifacts: &mut Stage4ExecutionArtifacts, +) -> Result<(), VerifyStage4Error> +where + T: Transcript, +{ + let values = transcript.challenge_vector(squeeze.count); + store.observe_challenge_vector(squeeze, &values, |input, expected, actual| { + VerifyStage4Error::InvalidInputLength { + input, + expected, + actual, + } + })?; + store + .evaluate_available_field_exprs(program.field_exprs, super::common::evaluate_field_expr) + .map_err(VerifyStage4Error::from)?; + artifacts.challenge_vectors.push(Stage4ChallengeVector { + symbol: squeeze.symbol, + values, + }); + Ok(()) +} + +fn absorb_stage4_bytes(absorb: &'static Stage4TranscriptAbsorbBytesPlan, transcript: &mut T) +where + T: Transcript, +{ + transcript.append(&LabelWithCount( + absorb.label.as_bytes(), + absorb.payload.len() as u64, + )); + transcript.append_bytes(absorb.payload.as_bytes()); +} + +fn verify_stage4_driver( + program: &'static Stage4VerifierProgramPlan, + driver: &'static Stage4SumcheckDriverPlan, + proof: &Stage4Proof, + store: &mut super::common::ValueStore, + transcript: &mut T, + artifacts: &mut Stage4ExecutionArtifacts, +) -> Result<(), VerifyStage4Error> +where + T: Transcript, +{ + let proof = proof + .sumchecks + .get(artifacts.sumchecks.len()) + .ok_or(VerifyStage4Error::MissingProof { + driver: driver.symbol, + })?; + let relation = driver.relation.unwrap_or(""); + let output = match relation { + "jolt.stage4.batched" => { + verify_batched_stage4(program, driver, proof, store, transcript)? + } + _ => return Err(VerifyStage4Error::UnsupportedRelation { relation }), + }; + artifacts.sumchecks.push(output); + Ok(()) +} + +fn verify_batched_stage4( + program: &'static Stage4VerifierProgramPlan, + driver: &'static Stage4SumcheckDriverPlan, + proof: &Stage4SumcheckOutput, + store: &mut super::common::ValueStore, + transcript: &mut T, +) -> Result, VerifyStage4Error> +where + T: Transcript, +{ + super::common::verify_batched_sumcheck( + driver, + proof, + program.claims, + program.batches, + program.field_exprs, + program.opening_inputs, + program.opening_claims, + program.opening_batches, + store, + transcript, + |store, evals, point, batching_coeffs| { + expected_batched_output_claim(program, driver, store, evals, point, batching_coeffs) + }, + |store, verified| observe_stage4_sumcheck_output(program, store, verified), + |driver, error| VerifyStage4Error::Sumcheck { driver, error }, + ) +} + +fn observe_stage4_sumcheck_output( + program: &'static Stage4VerifierProgramPlan, + store: &mut super::common::ValueStore, + output: &Stage4SumcheckOutput, +) -> Result<(), VerifyStage4Error> { + store.observe_sumcheck_output( + program.instance_results, + program.evals, + output, + |instance, mut point| { + match instance.point_order { + "as_is" => {} + "reverse" => point.reverse(), + "stage4_registers_rw" => { + point = normalize_stage4_registers_rw_point(program, output.driver, &point)?; + } + _ => { + return Err(VerifyStage4Error::InvalidProof { + driver: output.driver, + reason: "unsupported point order", + }); + } + } + Ok(point) + }, + |input, expected, actual| VerifyStage4Error::InvalidInputLength { + input, + expected, + actual, + }, + |symbol| VerifyStage4Error::MissingValue { symbol }, + )?; + store.evaluate_available_points( + program.point_slices, + program.point_concats, + |input, expected, actual| VerifyStage4Error::InvalidInputLength { + input, + expected, + actual, + }, + )?; + store + .evaluate_available_field_exprs(program.field_exprs, super::common::evaluate_field_expr) + .map_err(VerifyStage4Error::from)?; + store.verify_opening_equalities( + program.opening_equalities, + |driver, reason| VerifyStage4Error::InvalidProof { driver, reason }, + |symbol| VerifyStage4Error::MissingValue { symbol }, + ) +} + +fn expected_batched_output_claim( + program: &'static Stage4VerifierProgramPlan, + driver: &'static Stage4SumcheckDriverPlan, + store: &super::common::ValueStore, + evals: &[Stage4NamedEval], + point: &[Fr], + batching_coeffs: &[Fr], +) -> Result { + let batch = find_batch(program.batches, driver.symbol, driver.batch)?; + let claims = batch_claims(program.claims, batch)?; + let mut expected = Fr::from_u64(0); + for (claim, coefficient) in claims.iter().zip(batching_coeffs) { + let instance = program + .instance_results + .iter() + .find(|instance| instance.claim == claim.symbol && instance.source == driver.symbol) + .ok_or(VerifyStage4Error::MissingClaim { + batch: batch.symbol, + claim: claim.symbol, + })?; + let local_point = point + .get(instance.round_offset..instance.round_offset + instance.num_rounds) + .ok_or(VerifyStage4Error::InvalidInputLength { + input: instance.symbol, + expected: instance.round_offset + instance.num_rounds, + actual: point.len(), + })?; + let relation = claim.relation.unwrap_or(""); + let value = match relation { + "jolt.stage4.registers_read_write" => { + expected_registers_read_write(store, evals, local_point)? + } + "jolt.stage4.ram_val_check" => { + expected_ram_val_check(store, evals, local_point)? + } + _ => return Err(VerifyStage4Error::UnsupportedRelation { relation }), + }; + expected += *coefficient * value; + } + Ok(expected) +} + +fn expected_registers_read_write( + store: &super::common::ValueStore, + evals: &[Stage4NamedEval], + local_point: &[Fr], +) -> Result { + let trace_point = super::common::store_point(store, "stage4.input.stage3.registers.RdWriteValue")?; + let r_cycle = normalize_stage4_registers_rw_cycle_point( + local_point, + trace_point.len(), + "stage4.registers_read_write.instance", + )?; + let eq_eval = EqPolynomial::::mle(&r_cycle, trace_point); + let registers_val = eval_by_name( + evals, + "stage4.registers_read_write.eval.RegistersVal", + )?; + let rs1_ra = eval_by_name(evals, "stage4.registers_read_write.eval.Rs1Ra")?; + let rs2_ra = eval_by_name(evals, "stage4.registers_read_write.eval.Rs2Ra")?; + let rd_wa = eval_by_name(evals, "stage4.registers_read_write.eval.RdWa")?; + let rd_inc = eval_by_name(evals, "stage4.registers_read_write.eval.RdInc")?; + let gamma = super::common::store_scalar(store, "stage4.registers_read_write.gamma")?; + Ok(eq_eval + * (rd_wa * (registers_val + rd_inc) + + gamma * (rs1_ra * registers_val + gamma * rs2_ra * registers_val))) +} + +fn expected_ram_val_check( + store: &super::common::ValueStore, + evals: &[Stage4NamedEval], + local_point: &[Fr], +) -> Result { + let ram_val_point = super::common::store_point(store, "stage4.input.stage2.RamVal")?; + let r_cycle_prime = reverse_slice(local_point); + let r_cycle = suffix_point( + ram_val_point, + r_cycle_prime.len(), + "stage4.input.stage2.RamVal", + )?; + let lt_eval = lt_polynomial_eval(&r_cycle_prime, r_cycle); + let gamma = super::common::store_scalar(store, "stage4.ram_val_check.gamma")?; + let ram_ra = eval_by_name(evals, "stage4.ram_val_check.eval.RamRa")?; + let ram_inc = eval_by_name(evals, "stage4.ram_val_check.eval.RamInc")?; + Ok(ram_inc * ram_ra * (lt_eval + gamma)) +} + +fn suffix_point<'a>( + point: &'a [Fr], + length: usize, + input: &'static str, +) -> Result<&'a [Fr], VerifyStage4Error> { + point + .get(point.len().saturating_sub(length)..) + .filter(|suffix| suffix.len() == length) + .ok_or(VerifyStage4Error::InvalidInputLength { + input, + expected: length, + actual: point.len(), + }) +} + +fn normalize_stage4_registers_rw_point( + program: &'static Stage4VerifierProgramPlan, + driver: &'static str, + point: &[F], +) -> Result, VerifyStage4Error> { + let driver_plan = find_plan(program.drivers, driver).ok_or(VerifyStage4Error::MissingProof { + driver, + })?; + if driver_plan.round_schedule.len() != 2 { + return Err(VerifyStage4Error::InvalidProof { + driver, + reason: "stage4 registers point normalization requires [cycle, address] schedule", + }); + } + let cycle_rounds = driver_plan.round_schedule[0]; + let address_rounds = driver_plan.round_schedule[1]; + if point.len() != cycle_rounds + address_rounds { + return Err(VerifyStage4Error::InvalidInputLength { + input: "stage4.registers_read_write.instance", + expected: cycle_rounds + address_rounds, + actual: point.len(), + }); + } + let (cycle, address) = point.split_at(cycle_rounds); + Ok(address + .iter() + .rev() + .copied() + .chain(cycle.iter().rev().copied()) + .collect()) +} + +fn normalize_stage4_registers_rw_cycle_point( + point: &[F], + cycle_rounds: usize, + input: &'static str, +) -> Result, VerifyStage4Error> { + let cycle = point + .get(..cycle_rounds) + .filter(|cycle| cycle.len() == cycle_rounds) + .ok_or(VerifyStage4Error::InvalidInputLength { + input, + expected: cycle_rounds, + actual: point.len(), + })?; + Ok(cycle.iter().rev().copied().collect()) +} + +"# + } + } + } + + fn role_label(&self) -> &'static str { + match self.role { + Role::Prover => "prover", + Role::Verifier => "verifier", + } + } + + fn program_plan_type(&self) -> &'static str { + match self.role { + Role::Prover => "Stage4CpuProgramPlan", + Role::Verifier => "Stage4VerifierProgramPlan", + } + } +} + +fn require_supported_symbol(kind: &str, actual: &str, expected: &str) -> Result<(), EmitError> { + if actual == expected { + Ok(()) + } else { + Err(EmitError::new(format!( + "unsupported {kind} @{actual}; expected @{expected}" + ))) + } +} + +fn emit_str_array(name: &str, values: &[String]) -> String { + if values.is_empty() { + return format!("pub const {name}: &[&str] = &[];\n\n"); + } + if let [value] = values { + return format!("pub const {name}: &[&str] = &[{}];\n\n", rust_str(value)); + } + let entries = values + .iter() + .map(|value| format!(" {},", rust_str(value))) + .collect::>() + .join("\n"); + format!("pub const {name}: &[&str] = &[\n{entries}\n];\n\n") +} + +fn emit_usize_array(name: &str, values: &[usize]) -> String { + let entries = values + .iter() + .map(|value| format!(" {value},")) + .collect::>() + .join("\n"); + format!("pub const {name}: &[usize] = &[\n{entries}\n];\n\n") +} + +fn intern_str_array( + source: &mut String, + arrays: &mut Vec<(Vec, String)>, + name_prefix: &str, + values: &[String], +) -> String { + if let Some((_, name)) = arrays + .iter() + .find(|(existing, _)| existing.as_slice() == values) + { + return name.clone(); + } + let name = format!("{name_prefix}_{}", arrays.len()); + source.push_str(&emit_str_array(&name, values)); + arrays.push((values.to_vec(), name.clone())); + name +} + +fn rust_str(value: &str) -> String { + format!("{value:?}") +} + +fn rust_option_str(value: Option<&str>) -> String { + value.map_or_else( + || "None".to_owned(), + |value| format!("Some({})", rust_str(value)), + ) +} + +fn verify_count(kind: &str, symbol: &str, expected: usize, actual: usize) -> Result<(), EmitError> { + if expected == actual { + Ok(()) + } else { + Err(EmitError::new(format!( + "{kind} @{symbol} count mismatch: expected {expected}, got {actual}" + ))) + } +} + +fn symbols<'a>(values: impl Iterator) -> BTreeSet { + values.cloned().collect() +} + +fn string_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .ok() + .and_then(string_attribute_value) + .ok_or_else(|| attr_error(operation, attr, "string")) +} + +fn symbol_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .ok() + .and_then(symbol_attribute_value) + .ok_or_else(|| attr_error(operation, attr, "symbol")) +} + +fn symbol_array_attr( + operation: OperationRef<'_, '_>, + attr: &str, +) -> Result, EmitError> { + let attribute = operation + .attribute(attr) + .map(|attribute| attribute.to_string()) + .ok() + .ok_or_else(|| attr_error(operation, attr, "symbol array"))?; + parse_symbol_array(&attribute).ok_or_else(|| attr_error(operation, attr, "symbol array")) +} + +fn parse_symbol_array(attribute: &str) -> Option> { + let inner = attribute.strip_prefix('[')?.strip_suffix(']')?.trim(); + if inner.is_empty() { + return Some(Vec::new()); + } + inner + .split(',') + .map(|item| item.trim().strip_prefix('@').map(ToOwned::to_owned)) + .collect() +} + +fn int_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .map(parse_integer_attr) + .ok() + .flatten() + .ok_or_else(|| attr_error(operation, attr, "integer")) +} + +fn parse_integer_attr(attribute: Attribute<'_>) -> Option { + attribute + .to_string() + .split_whitespace() + .next() + .and_then(|value| value.parse().ok()) +} + +fn int_array_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result, EmitError> { + let attribute = operation + .attribute(attr) + .map(|attribute| attribute.to_string()) + .ok() + .ok_or_else(|| attr_error(operation, attr, "integer array"))?; + parse_int_array(&attribute).ok_or_else(|| attr_error(operation, attr, "integer array")) +} + +fn parse_int_array(attribute: &str) -> Option> { + let inner = attribute.strip_prefix('[')?.strip_suffix(']')?.trim(); + if inner.is_empty() { + return Some(Vec::new()); + } + inner + .split(',') + .map(|item| item.trim().parse().ok()) + .collect() +} + +fn operand_symbols( + operation: OperationRef<'_, '_>, + start_index: usize, +) -> Result, EmitError> { + (start_index..operation.operand_count()) + .map(|index| operand_symbol(operation, index)) + .collect() +} + +fn operand_symbol(operation: OperationRef<'_, '_>, index: usize) -> Result { + let operand = operation.operand(index).map_err(|_| { + EmitError::new(format!( + "{} requires operand {index}", + operation_name(operation) + )) + })?; + let owner = OperationResult::try_from(operand).map_err(|_| { + EmitError::new(format!( + "{} operand {index} must be an op result", + operation_name(operation) + )) + })?; + string_attr(owner.owner(), "sym_name") +} + +fn attr_error(operation: OperationRef<'_, '_>, attr: &str, expected: &str) -> EmitError { + EmitError::new(format!( + "{} attr `{attr}` is not a {expected}", + operation_name(operation) + )) +} + +fn operation_name<'c: 'a, 'a>(operation: impl OperationLike<'c, 'a>) -> String { + operation + .name() + .as_string_ref() + .as_str() + .unwrap_or("") + .to_owned() +} diff --git a/crates/bolt/src/protocols/jolt/emit/rust/stage5.rs b/crates/bolt/src/protocols/jolt/emit/rust/stage5.rs new file mode 100644 index 0000000000..30ab3d7edc --- /dev/null +++ b/crates/bolt/src/protocols/jolt/emit/rust/stage5.rs @@ -0,0 +1,2489 @@ +#![expect( + clippy::needless_raw_string_hashes, + reason = "generated Rust templates are kept as raw string blocks for copyable output" +)] + +use std::collections::{BTreeMap, BTreeSet}; + +use melior::ir::block::BlockLike; +use melior::ir::operation::{OperationLike, OperationResult}; +use melior::ir::{Attribute, OperationRef}; + +use crate::emit::rust::{push_format, EmitError, RustSourceFile}; +use crate::ir::{string_attribute_value, symbol_attribute_value, BoltModule, Cpu, Role}; +use crate::schema::verify_cpu_schema; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage5CpuProgram { + pub role: Role, + pub params: Stage5Params, + pub steps: Vec, + pub transcript_squeezes: Vec, + pub transcript_absorb_bytes: Vec, + pub opening_inputs: Vec, + pub field_constants: Vec, + pub field_exprs: Vec, + pub kernels: Vec, + pub claims: Vec, + pub batches: Vec, + pub drivers: Vec, + pub instance_results: Vec, + pub evals: Vec, + pub point_slices: Vec, + pub point_concats: Vec, + pub opening_claims: Vec, + pub opening_equalities: Vec, + pub opening_batches: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage5Params { + pub field: String, + pub pcs: String, + pub transcript: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage5KernelPlan { + pub symbol: String, + pub relation: String, + pub kind: String, + pub backend: String, + pub abi: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage5TranscriptSqueezePlan { + pub symbol: String, + pub label: String, + pub kind: String, + pub count: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage5TranscriptAbsorbBytesPlan { + pub symbol: String, + pub label: String, + pub payload: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage5ProgramStepPlan { + pub kind: String, + pub symbol: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage5OpeningInputPlan { + pub symbol: String, + pub source_stage: String, + pub source_claim: String, + pub oracle: String, + pub domain: String, + pub point_arity: usize, + pub claim_kind: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage5FieldConstantPlan { + pub symbol: String, + pub field: String, + pub value: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage5FieldExprPlan { + pub symbol: String, + pub kind: String, + pub formula: String, + pub operand_names: Vec, + pub operands: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage5SumcheckClaimPlan { + pub symbol: String, + pub stage: String, + pub domain: String, + pub num_rounds: usize, + pub degree: usize, + pub claim: String, + pub kernel: Option, + pub relation: Option, + pub claim_value: String, + pub input_openings: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage5SumcheckBatchPlan { + pub symbol: String, + pub stage: String, + pub proof_slot: String, + pub policy: String, + pub count: usize, + pub ordered_claims: Vec, + pub claim_operands: Vec, + pub claim_label: String, + pub round_label: String, + pub round_schedule: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage5SumcheckDriverPlan { + pub symbol: String, + pub stage: String, + pub proof_slot: String, + pub kernel: Option, + pub relation: Option, + pub batch: String, + pub policy: String, + pub round_schedule: Vec, + pub claim_label: String, + pub round_label: String, + pub num_rounds: usize, + pub degree: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage5SumcheckInstanceResultPlan { + pub symbol: String, + pub source: String, + pub claim: String, + pub relation: String, + pub index: usize, + pub point_arity: usize, + pub num_rounds: usize, + pub round_offset: usize, + pub point_order: String, + pub degree: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage5SumcheckEvalPlan { + pub symbol: String, + pub source: String, + pub name: String, + pub index: usize, + pub oracle: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage5PointSlicePlan { + pub symbol: String, + pub source: String, + pub offset: usize, + pub length: usize, + pub input: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage5PointConcatPlan { + pub symbol: String, + pub layout: String, + pub arity: usize, + pub inputs: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage5OpeningClaimPlan { + pub symbol: String, + pub oracle: String, + pub domain: String, + pub point_arity: usize, + pub claim_kind: String, + pub point_source: String, + pub eval_source: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage5OpeningClaimEqualityPlan { + pub symbol: String, + pub mode: String, + pub lhs: String, + pub rhs: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage5OpeningBatchPlan { + pub symbol: String, + pub stage: String, + pub proof_slot: String, + pub policy: String, + pub count: usize, + pub ordered_claims: Vec, + pub claim_operands: Vec, +} + +pub fn stage5_cpu_program(module: &BoltModule<'_, Cpu>) -> Result { + verify_cpu_schema(module)?; + let program = Stage5CpuProgram::from_module(module)?; + program.verify_supported_target()?; + Ok(program) +} + +pub fn emit_stage5_rust(module: &BoltModule<'_, Cpu>) -> Result { + let program = stage5_cpu_program(module)?; + + Ok(RustSourceFile { + filename: program.filename().to_owned(), + source: program.emit_source(), + }) +} + +impl Stage5CpuProgram { + fn from_module(module: &BoltModule<'_, Cpu>) -> Result { + let mut params = None; + let mut steps = Vec::new(); + let mut transcript_squeezes = Vec::new(); + let mut transcript_absorb_bytes = Vec::new(); + let mut opening_inputs = Vec::new(); + let mut field_constants = Vec::new(); + let mut field_exprs = Vec::new(); + let mut kernels = Vec::new(); + let mut claims = Vec::new(); + let mut batches = Vec::new(); + let mut drivers = Vec::new(); + let mut instance_results = Vec::new(); + let mut evals = Vec::new(); + let mut point_slices = Vec::new(); + let mut point_concats = Vec::new(); + let mut opening_claims = Vec::new(); + let mut opening_equalities = Vec::new(); + let mut opening_batches = Vec::new(); + + let mut operation = module.as_mlir_module().body().first_operation(); + while let Some(op) = operation { + operation = op.next_in_block(); + match operation_name(op).as_str() { + "cpu.params" => { + params = Some(Stage5Params { + field: symbol_attr(op, "field")?, + pcs: symbol_attr(op, "pcs")?, + transcript: symbol_attr(op, "transcript")?, + }); + } + "cpu.kernel" => { + kernels.push(Stage5KernelPlan { + symbol: string_attr(op, "sym_name")?, + relation: symbol_attr(op, "relation")?, + kind: string_attr(op, "kind")?, + backend: string_attr(op, "backend")?, + abi: string_attr(op, "abi")?, + }); + } + "cpu.transcript_squeeze" => { + let symbol = string_attr(op, "sym_name")?; + steps.push(Stage5ProgramStepPlan { + kind: "transcript_squeeze".to_owned(), + symbol: symbol.clone(), + }); + transcript_squeezes.push(Stage5TranscriptSqueezePlan { + symbol, + label: string_attr(op, "label")?, + kind: string_attr(op, "kind")?, + count: int_attr(op, "count")?, + }); + } + "cpu.transcript_absorb_bytes" => { + let symbol = string_attr(op, "sym_name")?; + steps.push(Stage5ProgramStepPlan { + kind: "transcript_absorb_bytes".to_owned(), + symbol: symbol.clone(), + }); + transcript_absorb_bytes.push(Stage5TranscriptAbsorbBytesPlan { + symbol, + label: string_attr(op, "label")?, + payload: string_attr(op, "payload")?, + }); + } + "cpu.opening_input" => { + opening_inputs.push(Stage5OpeningInputPlan { + symbol: string_attr(op, "sym_name")?, + source_stage: symbol_attr(op, "source_stage")?, + source_claim: symbol_attr(op, "source_claim")?, + oracle: symbol_attr(op, "oracle")?, + domain: symbol_attr(op, "domain")?, + point_arity: int_attr(op, "point_arity")?, + claim_kind: string_attr(op, "claim_kind")?, + }); + } + "cpu.field_const" => { + field_constants.push(Stage5FieldConstantPlan { + symbol: string_attr(op, "sym_name")?, + field: symbol_attr(op, "field")?, + value: int_attr(op, "value")?, + }); + } + "cpu.field_zero" => { + field_constants.push(Stage5FieldConstantPlan { + symbol: string_attr(op, "sym_name")?, + field: symbol_attr(op, "field")?, + value: 0, + }); + } + "cpu.field_one" => { + field_constants.push(Stage5FieldConstantPlan { + symbol: string_attr(op, "sym_name")?, + field: symbol_attr(op, "field")?, + value: 1, + }); + } + "cpu.field_add" | "cpu.field_sub" | "cpu.field_mul" | "cpu.field_neg" => { + let operands = operand_symbols(op, 0)?; + field_exprs.push(Stage5FieldExprPlan { + symbol: string_attr(op, "sym_name")?, + kind: "op".to_owned(), + formula: operation_name(op).replace("cpu.field_", "field."), + operand_names: operands.clone(), + operands, + }); + } + "cpu.field_pow" => { + let exponent = int_attr(op, "exponent")?; + let operands = operand_symbols(op, 0)?; + field_exprs.push(Stage5FieldExprPlan { + symbol: string_attr(op, "sym_name")?, + kind: "op".to_owned(), + formula: format!("field.pow:{exponent}"), + operand_names: operands.clone(), + operands, + }); + } + "cpu.sumcheck_claim" => { + claims.push(Stage5SumcheckClaimPlan { + symbol: string_attr(op, "sym_name")?, + stage: symbol_attr(op, "stage")?, + domain: symbol_attr(op, "domain")?, + num_rounds: int_attr(op, "num_rounds")?, + degree: int_attr(op, "degree")?, + claim: symbol_attr(op, "claim")?, + kernel: Some(symbol_attr(op, "kernel")?), + relation: None, + claim_value: operand_symbol(op, 0)?, + input_openings: operand_symbols(op, 1)?, + }); + } + "cpu.sumcheck_verify_claim" => { + claims.push(Stage5SumcheckClaimPlan { + symbol: string_attr(op, "sym_name")?, + stage: symbol_attr(op, "stage")?, + domain: symbol_attr(op, "domain")?, + num_rounds: int_attr(op, "num_rounds")?, + degree: int_attr(op, "degree")?, + claim: symbol_attr(op, "claim")?, + kernel: None, + relation: Some(symbol_attr(op, "relation")?), + claim_value: operand_symbol(op, 0)?, + input_openings: operand_symbols(op, 1)?, + }); + } + "cpu.sumcheck_batch" => { + batches.push(Stage5SumcheckBatchPlan { + symbol: string_attr(op, "sym_name")?, + stage: symbol_attr(op, "stage")?, + proof_slot: symbol_attr(op, "proof_slot")?, + policy: string_attr(op, "policy")?, + count: int_attr(op, "count")?, + ordered_claims: symbol_array_attr(op, "ordered_claims")?, + claim_operands: operand_symbols(op, 0)?, + claim_label: string_attr(op, "claim_label")?, + round_label: string_attr(op, "round_label")?, + round_schedule: int_array_attr(op, "round_schedule")?, + }); + } + "cpu.sumcheck_driver" => { + let symbol = string_attr(op, "sym_name")?; + steps.push(Stage5ProgramStepPlan { + kind: "sumcheck_driver".to_owned(), + symbol: symbol.clone(), + }); + drivers.push(Stage5SumcheckDriverPlan { + symbol, + stage: symbol_attr(op, "stage")?, + proof_slot: symbol_attr(op, "proof_slot")?, + kernel: Some(symbol_attr(op, "kernel")?), + relation: None, + batch: operand_symbol(op, 1)?, + policy: string_attr(op, "policy")?, + round_schedule: int_array_attr(op, "round_schedule")?, + claim_label: string_attr(op, "claim_label")?, + round_label: string_attr(op, "round_label")?, + num_rounds: int_attr(op, "num_rounds")?, + degree: int_attr(op, "degree")?, + }); + } + "cpu.sumcheck_verify" => { + let symbol = string_attr(op, "sym_name")?; + steps.push(Stage5ProgramStepPlan { + kind: "sumcheck_driver".to_owned(), + symbol: symbol.clone(), + }); + drivers.push(Stage5SumcheckDriverPlan { + symbol, + stage: symbol_attr(op, "stage")?, + proof_slot: symbol_attr(op, "proof_slot")?, + kernel: None, + relation: Some(symbol_attr(op, "relation")?), + batch: operand_symbol(op, 1)?, + policy: string_attr(op, "policy")?, + round_schedule: int_array_attr(op, "round_schedule")?, + claim_label: string_attr(op, "claim_label")?, + round_label: string_attr(op, "round_label")?, + num_rounds: int_attr(op, "num_rounds")?, + degree: int_attr(op, "degree")?, + }); + } + "cpu.sumcheck_instance_result" => { + instance_results.push(Stage5SumcheckInstanceResultPlan { + symbol: string_attr(op, "sym_name")?, + source: symbol_attr(op, "source")?, + claim: symbol_attr(op, "claim")?, + relation: symbol_attr(op, "relation")?, + index: int_attr(op, "index")?, + point_arity: int_attr(op, "point_arity")?, + num_rounds: int_attr(op, "num_rounds")?, + round_offset: int_attr(op, "round_offset")?, + point_order: string_attr(op, "point_order")?, + degree: int_attr(op, "degree")?, + }); + } + "cpu.sumcheck_eval" => { + evals.push(Stage5SumcheckEvalPlan { + symbol: string_attr(op, "sym_name")?, + source: symbol_attr(op, "source")?, + name: symbol_attr(op, "name")?, + index: int_attr(op, "index")?, + oracle: symbol_attr(op, "oracle")?, + }); + } + "cpu.point_slice" => { + point_slices.push(Stage5PointSlicePlan { + symbol: string_attr(op, "sym_name")?, + source: symbol_attr(op, "source")?, + offset: int_attr(op, "offset")?, + length: int_attr(op, "length")?, + input: operand_symbol(op, 0)?, + }); + } + "cpu.point_concat" => { + point_concats.push(Stage5PointConcatPlan { + symbol: string_attr(op, "sym_name")?, + layout: string_attr(op, "layout")?, + arity: int_attr(op, "arity")?, + inputs: operand_symbols(op, 0)?, + }); + } + "cpu.opening_claim" => { + opening_claims.push(Stage5OpeningClaimPlan { + symbol: string_attr(op, "sym_name")?, + oracle: symbol_attr(op, "oracle")?, + domain: symbol_attr(op, "domain")?, + point_arity: int_attr(op, "point_arity")?, + claim_kind: string_attr(op, "claim_kind")?, + point_source: operand_symbol(op, 0)?, + eval_source: operand_symbol(op, 1)?, + }); + } + "cpu.opening_claim_equal" => { + opening_equalities.push(Stage5OpeningClaimEqualityPlan { + symbol: string_attr(op, "sym_name")?, + mode: string_attr(op, "mode")?, + lhs: operand_symbol(op, 0)?, + rhs: operand_symbol(op, 1)?, + }); + } + "cpu.opening_batch" => { + opening_batches.push(Stage5OpeningBatchPlan { + symbol: string_attr(op, "sym_name")?, + stage: symbol_attr(op, "stage")?, + proof_slot: symbol_attr(op, "proof_slot")?, + policy: string_attr(op, "policy")?, + count: int_attr(op, "count")?, + ordered_claims: symbol_array_attr(op, "ordered_claims")?, + claim_operands: operand_symbols(op, 0)?, + }); + } + _ => {} + } + } + + Ok(Self { + params: params.ok_or_else(|| EmitError::new("missing cpu.params"))?, + role: module + .role() + .ok_or_else(|| EmitError::new("missing cpu party role"))?, + steps, + transcript_squeezes, + transcript_absorb_bytes, + opening_inputs, + field_constants, + field_exprs, + kernels, + claims, + batches, + drivers, + instance_results, + evals, + point_slices, + point_concats, + opening_claims, + opening_equalities, + opening_batches, + }) + } + + fn verify_supported_target(&self) -> Result<(), EmitError> { + require_supported_symbol("field", &self.params.field, "bn254_fr")?; + require_supported_symbol("pcs", &self.params.pcs, "dory")?; + require_supported_symbol("transcript", &self.params.transcript, "blake2b_transcript")?; + self.verify_transcript_steps()?; + self.verify_field_flow()?; + self.verify_claim_batches()?; + match self.role { + Role::Prover => { + self.verify_kernel_definitions()?; + self.verify_prover_driver_bindings()?; + } + Role::Verifier => self.verify_verifier_driver_bindings()?, + } + self.verify_opening_flow() + } + + fn verify_transcript_steps(&self) -> Result<(), EmitError> { + for squeeze in &self.transcript_squeezes { + if !matches!( + squeeze.kind.as_str(), + "challenge_scalar" | "challenge_vector" + ) { + return Err(EmitError::new(format!( + "stage5 transcript squeeze @{} has unsupported kind `{}`", + squeeze.symbol, squeeze.kind + ))); + } + if squeeze.count == 0 { + return Err(EmitError::new(format!( + "stage5 transcript squeeze @{} has zero count", + squeeze.symbol + ))); + } + } + for absorb in &self.transcript_absorb_bytes { + if absorb.label.is_empty() { + return Err(EmitError::new(format!( + "stage5 transcript byte absorb @{} has empty label", + absorb.symbol + ))); + } + } + Ok(()) + } + + fn verify_field_flow(&self) -> Result<(), EmitError> { + for constant in &self.field_constants { + require_supported_symbol("field constant field", &constant.field, "bn254_fr")?; + } + let field_values = self.field_value_symbols(); + for expr in &self.field_exprs { + verify_count( + "field expr operands", + &expr.symbol, + expr.operand_names.len(), + expr.operands.len(), + )?; + for operand in &expr.operands { + if !field_values.contains(operand) { + return Err(EmitError::new(format!( + "field expr @{} references missing field value @{operand}", + expr.symbol + ))); + } + } + } + for claim in &self.claims { + if !field_values.contains(&claim.claim_value) { + return Err(EmitError::new(format!( + "sumcheck claim @{} uses missing claim value @{}", + claim.symbol, claim.claim_value + ))); + } + } + Ok(()) + } + + fn field_value_symbols(&self) -> BTreeSet { + let mut values = symbols(self.opening_inputs.iter().map(|input| &input.symbol)); + values.extend(symbols( + self.field_constants.iter().map(|constant| &constant.symbol), + )); + values.extend(symbols( + self.transcript_squeezes + .iter() + .filter(|squeeze| matches!(squeeze.kind.as_str(), "challenge_scalar" | "scalar")) + .map(|squeeze| &squeeze.symbol), + )); + values.extend(symbols(self.field_exprs.iter().map(|expr| &expr.symbol))); + values.extend(symbols(self.evals.iter().map(|eval| &eval.symbol))); + values + } + + fn verify_kernel_definitions(&self) -> Result<(), EmitError> { + for kernel in &self.kernels { + if kernel.backend != "cpu" { + return Err(EmitError::new(format!( + "stage5 kernel @{} targets unsupported backend `{}`", + kernel.symbol, kernel.backend + ))); + } + if kernel.kind != "sumcheck" { + return Err(EmitError::new(format!( + "stage5 kernel @{} has unsupported kind `{}`", + kernel.symbol, kernel.kind + ))); + } + let expected_abi = match kernel.relation.as_str() { + "jolt.stage5.instruction_read_raf" => "jolt_stage5_instruction_read_raf", + "jolt.stage5.ram_ra_claim_reduction" => "jolt_stage5_ram_ra_claim_reduction", + "jolt.stage5.registers_val_evaluation" => "jolt_stage5_registers_val_evaluation", + "jolt.stage5.batched" => "jolt_stage5_batched", + _ => { + return Err(EmitError::new(format!( + "unsupported stage5 kernel relation @{}", + kernel.relation + ))); + } + }; + if kernel.abi != expected_abi { + return Err(EmitError::new(format!( + "stage5 kernel @{} ABI `{}` does not match relation @{}", + kernel.symbol, kernel.abi, kernel.relation + ))); + } + } + Ok(()) + } + + fn verify_claim_batches(&self) -> Result<(), EmitError> { + let claims = symbols(self.claims.iter().map(|claim| &claim.symbol)); + for batch in &self.batches { + verify_count( + "sumcheck batch", + &batch.symbol, + batch.count, + batch.ordered_claims.len(), + )?; + verify_count( + "sumcheck batch operands", + &batch.symbol, + batch.count, + batch.claim_operands.len(), + )?; + if batch.ordered_claims != batch.claim_operands { + return Err(EmitError::new(format!( + "sumcheck batch @{} operand order does not match ordered_claims", + batch.symbol + ))); + } + for claim in &batch.ordered_claims { + if !claims.contains(claim) { + return Err(EmitError::new(format!( + "sumcheck batch @{} references missing claim @{claim}", + batch.symbol + ))); + } + } + } + Ok(()) + } + + fn verify_prover_driver_bindings(&self) -> Result<(), EmitError> { + let kernels = symbols(self.kernels.iter().map(|kernel| &kernel.symbol)); + let batches: BTreeMap<_, _> = self + .batches + .iter() + .map(|batch| (batch.symbol.as_str(), batch)) + .collect(); + for claim in &self.claims { + let Some(kernel) = claim.kernel.as_deref() else { + return Err(EmitError::new(format!( + "prover sumcheck claim @{} is missing kernel", + claim.symbol + ))); + }; + if !kernels.contains(kernel) { + return Err(EmitError::new(format!( + "sumcheck claim @{} references missing kernel @{kernel}", + claim.symbol + ))); + } + } + for driver in &self.drivers { + let Some(kernel) = driver.kernel.as_deref() else { + return Err(EmitError::new(format!( + "prover sumcheck driver @{} is missing kernel", + driver.symbol + ))); + }; + if !kernels.contains(kernel) { + return Err(EmitError::new(format!( + "sumcheck driver @{} references missing kernel @{kernel}", + driver.symbol + ))); + } + let batch = batches.get(driver.batch.as_str()).ok_or_else(|| { + EmitError::new(format!( + "sumcheck driver @{} references missing batch @{}", + driver.symbol, driver.batch + )) + })?; + verify_count( + "sumcheck driver round_schedule", + &driver.symbol, + driver.num_rounds, + driver.round_schedule.iter().sum(), + )?; + if driver.round_schedule != batch.round_schedule { + return Err(EmitError::new(format!( + "sumcheck driver @{} round_schedule differs from batch @{}", + driver.symbol, batch.symbol + ))); + } + } + Ok(()) + } + + fn verify_verifier_driver_bindings(&self) -> Result<(), EmitError> { + if !self.kernels.is_empty() { + return Err(EmitError::new( + "verifier stage5 program must not contain kernels", + )); + } + let batches: BTreeMap<_, _> = self + .batches + .iter() + .map(|batch| (batch.symbol.as_str(), batch)) + .collect(); + for claim in &self.claims { + if claim.kernel.is_some() || claim.relation.is_none() { + return Err(EmitError::new(format!( + "verifier sumcheck claim @{} must carry relation and no kernel", + claim.symbol + ))); + } + } + for driver in &self.drivers { + if driver.kernel.is_some() || driver.relation.is_none() { + return Err(EmitError::new(format!( + "verifier sumcheck driver @{} must carry relation and no kernel", + driver.symbol + ))); + } + let batch = batches.get(driver.batch.as_str()).ok_or_else(|| { + EmitError::new(format!( + "sumcheck driver @{} references missing batch @{}", + driver.symbol, driver.batch + )) + })?; + verify_count( + "sumcheck driver round_schedule", + &driver.symbol, + driver.num_rounds, + driver.round_schedule.iter().sum(), + )?; + if driver.round_schedule != batch.round_schedule { + return Err(EmitError::new(format!( + "sumcheck driver @{} round_schedule differs from batch @{}", + driver.symbol, batch.symbol + ))); + } + } + Ok(()) + } + + fn verify_opening_flow(&self) -> Result<(), EmitError> { + let mut point_sources = symbols(self.drivers.iter().map(|driver| &driver.symbol)); + point_sources.extend(symbols( + self.instance_results + .iter() + .map(|instance| &instance.symbol), + )); + point_sources.extend(symbols( + self.opening_inputs.iter().map(|input| &input.symbol), + )); + point_sources.extend(symbols(self.point_slices.iter().map(|slice| &slice.symbol))); + point_sources.extend(symbols( + self.point_concats.iter().map(|concat| &concat.symbol), + )); + for slice in &self.point_slices { + if !point_sources.contains(&slice.input) { + return Err(EmitError::new(format!( + "point slice @{} uses missing point source @{}", + slice.symbol, slice.input + ))); + } + } + for concat in &self.point_concats { + for input in &concat.inputs { + if !point_sources.contains(input) { + return Err(EmitError::new(format!( + "point concat @{} uses missing point source @{input}", + concat.symbol + ))); + } + } + } + let eval_sources = self.field_value_symbols(); + let mut opening_sources = symbols(self.opening_inputs.iter().map(|input| &input.symbol)); + opening_sources.extend(symbols( + self.opening_claims.iter().map(|claim| &claim.symbol), + )); + for equality in &self.opening_equalities { + if !opening_sources.contains(&equality.lhs) { + return Err(EmitError::new(format!( + "opening equality @{} uses missing lhs opening @{}", + equality.symbol, equality.lhs + ))); + } + if !opening_sources.contains(&equality.rhs) { + return Err(EmitError::new(format!( + "opening equality @{} uses missing rhs opening @{}", + equality.symbol, equality.rhs + ))); + } + } + for claim in &self.claims { + for input in &claim.input_openings { + if !opening_sources.contains(input) { + return Err(EmitError::new(format!( + "sumcheck claim @{} uses missing opening @{input}", + claim.symbol + ))); + } + } + } + let drivers = symbols(self.drivers.iter().map(|driver| &driver.symbol)); + for instance in &self.instance_results { + if !drivers.contains(&instance.source) { + return Err(EmitError::new(format!( + "sumcheck instance result @{} references missing driver @{}", + instance.symbol, instance.source + ))); + } + } + for eval in &self.evals { + if !drivers.contains(&eval.source) { + return Err(EmitError::new(format!( + "sumcheck eval @{} references missing driver @{}", + eval.symbol, eval.source + ))); + } + } + for claim in &self.opening_claims { + if !point_sources.contains(&claim.point_source) { + return Err(EmitError::new(format!( + "opening claim @{} uses missing point source @{}", + claim.symbol, claim.point_source + ))); + } + if !eval_sources.contains(&claim.eval_source) { + return Err(EmitError::new(format!( + "opening claim @{} uses missing eval source @{}", + claim.symbol, claim.eval_source + ))); + } + } + let openings = symbols(self.opening_claims.iter().map(|claim| &claim.symbol)); + for batch in &self.opening_batches { + verify_count( + "opening batch", + &batch.symbol, + batch.count, + batch.ordered_claims.len(), + )?; + verify_count( + "opening batch operands", + &batch.symbol, + batch.count, + batch.claim_operands.len(), + )?; + if batch.ordered_claims != batch.claim_operands { + return Err(EmitError::new(format!( + "opening batch @{} operand order does not match ordered_claims", + batch.symbol + ))); + } + for claim in &batch.ordered_claims { + if !openings.contains(claim) { + return Err(EmitError::new(format!( + "opening batch @{} references missing opening @{claim}", + batch.symbol + ))); + } + } + } + Ok(()) + } + + fn filename(&self) -> &'static str { + match self.role { + Role::Prover => "prove_stage5.rs", + Role::Verifier => "verify_stage5.rs", + } + } + + fn emit_source(&self) -> String { + let mut source = String::new(); + source.push_str("#![allow(dead_code)]\n\n"); + match self.role { + Role::Prover => { + source.push_str(Self::emit_prover_imports()); + source.push_str("\n\n"); + source.push_str(Self::emit_prover_types()); + } + Role::Verifier => { + source.push_str(Self::emit_verifier_imports()); + source.push_str("\n\n"); + source.push_str(&Self::emit_verifier_types()); + } + } + source.push('\n'); + source.push_str(&self.emit_constants()); + source.push('\n'); + source.push_str(self.emit_entrypoint()); + source + } + + fn emit_prover_imports() -> &'static str { + "use jolt_field::Fr;\n\ + use jolt_kernels::stage5::{execute_stage5_program, Stage5CpuProgramPlan, Stage5ExecutionArtifacts, Stage5ExecutionMode, Stage5FieldConstantPlan, Stage5FieldExprPlan, Stage5KernelError, Stage5KernelExecutor, Stage5KernelPlan, Stage5OpeningBatchPlan, Stage5OpeningClaimEqualityPlan, Stage5OpeningClaimPlan, Stage5OpeningInputPlan, Stage5Params, Stage5PointConcatPlan, Stage5PointSlicePlan, Stage5ProgramStepPlan, Stage5SumcheckBatchPlan, Stage5SumcheckClaimPlan, Stage5SumcheckDriverPlan, Stage5SumcheckEvalPlan, Stage5SumcheckInstanceResultPlan, Stage5TranscriptAbsorbBytesPlan, Stage5TranscriptSqueezePlan};\n\ + use jolt_transcript::{Blake2bTranscript, Transcript};" + } + + fn emit_prover_types() -> &'static str { + "pub type DefaultStage5Transcript = Blake2bTranscript;\n" + } + + fn emit_verifier_imports() -> &'static str { + "use super::common::{batch_claims, eval_by_name, find_batch, find_plan, identity_polynomial_eval, indexed_evals_by_prefix, indexed_evals_by_prefix_any, lt_polynomial_eval, normalize_instruction_read_raf_point, operand_polynomial_eval, reverse_slice, suffix_point};\n\ + use jolt_field::{Field, Fr};\n\ + use jolt_lookup_tables::LookupTableKind;\n\ + use jolt_poly::EqPolynomial;\n\ + use jolt_sumcheck::SumcheckError;\n\ + use jolt_transcript::{Blake2bTranscript, LabelWithCount, Transcript};" + } + + #[expect(dead_code)] + fn emit_types() -> &'static str { + r#"#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage5Params { + pub field: &'static str, + pub pcs: &'static str, + pub transcript: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage5KernelPlan { + pub symbol: &'static str, + pub relation: &'static str, + pub kind: &'static str, + pub backend: &'static str, + pub abi: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage5TranscriptSqueezePlan { + pub symbol: &'static str, + pub label: &'static str, + pub kind: &'static str, + pub count: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage5TranscriptAbsorbBytesPlan { + pub symbol: &'static str, + pub label: &'static str, + pub payload: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage5ProgramStepPlan { + pub kind: &'static str, + pub symbol: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage5OpeningInputPlan { + pub symbol: &'static str, + pub source_stage: &'static str, + pub source_claim: &'static str, + pub oracle: &'static str, + pub domain: &'static str, + pub point_arity: usize, + pub claim_kind: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage5FieldConstantPlan { + pub symbol: &'static str, + pub field: &'static str, + pub value: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage5FieldExprPlan { + pub symbol: &'static str, + pub kind: &'static str, + pub formula: &'static str, + pub operand_names: &'static [&'static str], + pub operands: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage5SumcheckClaimPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub domain: &'static str, + pub num_rounds: usize, + pub degree: usize, + pub claim: &'static str, + pub kernel: Option<&'static str>, + pub relation: Option<&'static str>, + pub claim_value: &'static str, + pub input_openings: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage5SumcheckBatchPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub proof_slot: &'static str, + pub policy: &'static str, + pub count: usize, + pub ordered_claims: &'static [&'static str], + pub claim_operands: &'static [&'static str], + pub claim_label: &'static str, + pub round_label: &'static str, + pub round_schedule: &'static [usize], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage5SumcheckDriverPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub proof_slot: &'static str, + pub kernel: Option<&'static str>, + pub relation: Option<&'static str>, + pub batch: &'static str, + pub policy: &'static str, + pub round_schedule: &'static [usize], + pub claim_label: &'static str, + pub round_label: &'static str, + pub num_rounds: usize, + pub degree: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage5SumcheckInstanceResultPlan { + pub symbol: &'static str, + pub source: &'static str, + pub claim: &'static str, + pub relation: &'static str, + pub index: usize, + pub point_arity: usize, + pub num_rounds: usize, + pub round_offset: usize, + pub point_order: &'static str, + pub degree: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage5SumcheckEvalPlan { + pub symbol: &'static str, + pub source: &'static str, + pub name: &'static str, + pub index: usize, + pub oracle: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage5PointSlicePlan { + pub symbol: &'static str, + pub source: &'static str, + pub offset: usize, + pub length: usize, + pub input: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage5PointConcatPlan { + pub symbol: &'static str, + pub layout: &'static str, + pub arity: usize, + pub inputs: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage5OpeningClaimPlan { + pub symbol: &'static str, + pub oracle: &'static str, + pub domain: &'static str, + pub point_arity: usize, + pub claim_kind: &'static str, + pub point_source: &'static str, + pub eval_source: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage5OpeningClaimEqualityPlan { + pub symbol: &'static str, + pub mode: &'static str, + pub lhs: &'static str, + pub rhs: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage5OpeningBatchPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub proof_slot: &'static str, + pub policy: &'static str, + pub count: usize, + pub ordered_claims: &'static [&'static str], + pub claim_operands: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage5CpuProgramPlan { + pub role: &'static str, + pub params: Stage5Params, + pub steps: &'static [Stage5ProgramStepPlan], + pub transcript_squeezes: &'static [Stage5TranscriptSqueezePlan], + pub transcript_absorb_bytes: &'static [Stage5TranscriptAbsorbBytesPlan], + pub opening_inputs: &'static [Stage5OpeningInputPlan], + pub field_constants: &'static [Stage5FieldConstantPlan], + pub field_exprs: &'static [Stage5FieldExprPlan], + pub kernels: &'static [Stage5KernelPlan], + pub claims: &'static [Stage5SumcheckClaimPlan], + pub batches: &'static [Stage5SumcheckBatchPlan], + pub drivers: &'static [Stage5SumcheckDriverPlan], + pub instance_results: &'static [Stage5SumcheckInstanceResultPlan], + pub evals: &'static [Stage5SumcheckEvalPlan], + pub point_slices: &'static [Stage5PointSlicePlan], + pub point_concats: &'static [Stage5PointConcatPlan], + pub opening_claims: &'static [Stage5OpeningClaimPlan], + pub opening_equalities: &'static [Stage5OpeningClaimEqualityPlan], + pub opening_batches: &'static [Stage5OpeningBatchPlan], +} +"# + } + + fn emit_verifier_type_aliases() -> &'static str { + r#"pub type Stage5NamedEval = super::common::StageNamedEval; +pub type Stage5SumcheckOutput = super::common::StageSumcheckOutput; +pub type Stage5ChallengeVector = super::common::StageChallengeVector; +pub type Stage5ExecutionArtifacts = super::common::StageExecutionArtifacts; +pub type Stage5Proof = super::common::StageProof; +pub type Stage5OpeningInputValue = super::common::StageOpeningInputValue; + +pub use super::common::{ + FieldConstantPlan as Stage5FieldConstantPlan, FieldExprPlan as Stage5FieldExprPlan, + KernelPlan as Stage5KernelPlan, OpeningBatchPlan as Stage5OpeningBatchPlan, + OpeningClaimEqualityPlan as Stage5OpeningClaimEqualityPlan, + OpeningClaimPlan as Stage5OpeningClaimPlan, OpeningInputPlan as Stage5OpeningInputPlan, + PointConcatPlan as Stage5PointConcatPlan, PointSlicePlan as Stage5PointSlicePlan, + ProgramStepPlan as Stage5ProgramStepPlan, StageParams as Stage5Params, + StageProgramPlanNoPointZeros as Stage5CpuProgramPlan, + SumcheckBatchPlan as Stage5SumcheckBatchPlan, + SumcheckClaimPlan as Stage5SumcheckClaimPlan, SumcheckDriverPlan as Stage5SumcheckDriverPlan, + SumcheckEvalPlan as Stage5SumcheckEvalPlan, + SumcheckInstanceResultPlan as Stage5SumcheckInstanceResultPlan, + TranscriptAbsorbBytesPlan as Stage5TranscriptAbsorbBytesPlan, + TranscriptSqueezePlan as Stage5TranscriptSqueezePlan, +}; +"# + } + + fn emit_verifier_types() -> String { + let mut source = Self::emit_verifier_type_aliases().to_owned(); + source.push_str( + r#" +pub type DefaultStage5Transcript = Blake2bTranscript; +pub type Stage5VerifierProgramPlan = Stage5CpuProgramPlan; + +#[derive(Debug)] +pub enum VerifyStage5Error { + UnexpectedProofCount { expected: usize, got: usize }, + MissingProof { driver: &'static str }, + MissingBatch { driver: &'static str, batch: &'static str }, + MissingClaim { batch: &'static str, claim: &'static str }, + MissingValue { symbol: &'static str }, + InvalidInputLength { input: &'static str, expected: usize, actual: usize }, + InvalidProof { driver: &'static str, reason: &'static str }, + UnsupportedFieldExpr { symbol: &'static str, formula: &'static str }, + UnsupportedRelation { relation: &'static str }, + Sumcheck { driver: &'static str, error: SumcheckError }, +} + +super::common::impl_runtime_plan_error_conversion!(VerifyStage5Error); +"#, + ); + source + } + + fn emit_constants(&self) -> String { + let mut source = self.emit_shared_constants(); + source.push_str(&self.emit_kernel_constants()); + source.push_str(&self.emit_sumcheck_claim_constants()); + source.push_str(&self.emit_sumcheck_batch_constants()); + source.push_str(&self.emit_sumcheck_driver_constants()); + source.push_str(&self.emit_tail_constants()); + push_format( + &mut source, + format_args!( + "pub const STAGE5_PROGRAM: {} = Stage5CpuProgramPlan {{\n\ + \x20 role: {},\n\ + \x20 params: STAGE5_PARAMS,\n\ + \x20 steps: STAGE5_PROGRAM_STEPS,\n\ + \x20 transcript_squeezes: STAGE5_TRANSCRIPT_SQUEEZES,\n\ + \x20 transcript_absorb_bytes: STAGE5_TRANSCRIPT_ABSORB_BYTES,\n\ + \x20 opening_inputs: STAGE5_OPENING_INPUTS,\n\ + \x20 field_constants: STAGE5_FIELD_CONSTANTS,\n\ + \x20 field_exprs: STAGE5_FIELD_EXPRS,\n\ + \x20 kernels: STAGE5_KERNELS,\n\ + \x20 claims: STAGE5_SUMCHECK_CLAIMS,\n\ + \x20 batches: STAGE5_SUMCHECK_BATCHES,\n\ + \x20 drivers: STAGE5_SUMCHECK_DRIVERS,\n\ + \x20 instance_results: STAGE5_SUMCHECK_INSTANCE_RESULTS,\n\ + \x20 evals: STAGE5_SUMCHECK_EVALS,\n\ + \x20 point_slices: STAGE5_POINT_SLICES,\n\ + \x20 point_concats: STAGE5_POINT_CONCATS,\n\ + \x20 opening_claims: STAGE5_OPENING_CLAIMS,\n\ + \x20 opening_equalities: STAGE5_OPENING_EQUALITIES,\n\ + \x20 opening_batches: STAGE5_OPENING_BATCHES,\n\ + }};\n", + self.program_plan_type(), + rust_str(self.role_label()) + ), + ); + source + } + + fn emit_shared_constants(&self) -> String { + let mut source = String::new(); + push_format( + &mut source, + format_args!( + "pub const STAGE5_PARAMS: Stage5Params = Stage5Params {{\n\ + \x20 field: {},\n\ + \x20 pcs: {},\n\ + \x20 transcript: {},\n\ + }};\n", + rust_str(&self.params.field), + rust_str(&self.params.pcs), + rust_str(&self.params.transcript) + ), + ); + source.push_str(&self.emit_program_step_constants()); + source.push_str(&self.emit_transcript_squeeze_constants()); + source.push_str(&self.emit_transcript_absorb_bytes_constants()); + source.push_str(&self.emit_opening_input_constants()); + source.push_str(&self.emit_field_constant_constants()); + source.push_str(&self.emit_field_expr_constants()); + source + } + + fn emit_program_step_constants(&self) -> String { + let steps = self + .steps + .iter() + .map(|step| { + format!( + " Stage5ProgramStepPlan {{ kind: {}, symbol: {} }},", + rust_str(&step.kind), + rust_str(&step.symbol), + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE5_PROGRAM_STEPS: &[Stage5ProgramStepPlan] = &[\n{steps}\n];\n\n") + } + + fn emit_transcript_squeeze_constants(&self) -> String { + let squeezes = self + .transcript_squeezes + .iter() + .map(|squeeze| { + format!( + " Stage5TranscriptSqueezePlan {{ symbol: {}, label: {}, kind: {}, count: {} }},", + rust_str(&squeeze.symbol), + rust_str(&squeeze.label), + rust_str(&squeeze.kind), + squeeze.count, + ) + }) + .collect::>() + .join("\n"); + format!( + "pub const STAGE5_TRANSCRIPT_SQUEEZES: &[Stage5TranscriptSqueezePlan] = &[\n{squeezes}\n];\n\n" + ) + } + + fn emit_transcript_absorb_bytes_constants(&self) -> String { + let absorbs = self + .transcript_absorb_bytes + .iter() + .map(|absorb| { + format!( + " Stage5TranscriptAbsorbBytesPlan {{ symbol: {}, label: {}, payload: {} }},", + rust_str(&absorb.symbol), + rust_str(&absorb.label), + rust_str(&absorb.payload), + ) + }) + .collect::>() + .join("\n"); + format!( + "pub const STAGE5_TRANSCRIPT_ABSORB_BYTES: &[Stage5TranscriptAbsorbBytesPlan] = &[\n{absorbs}\n];\n\n" + ) + } + + fn emit_opening_input_constants(&self) -> String { + let inputs = self + .opening_inputs + .iter() + .map(|input| { + format!( + " Stage5OpeningInputPlan {{ symbol: {}, source_stage: {}, source_claim: {}, oracle: {}, domain: {}, point_arity: {}, claim_kind: {} }},", + rust_str(&input.symbol), + rust_str(&input.source_stage), + rust_str(&input.source_claim), + rust_str(&input.oracle), + rust_str(&input.domain), + input.point_arity, + rust_str(&input.claim_kind) + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE5_OPENING_INPUTS: &[Stage5OpeningInputPlan] = &[\n{inputs}\n];\n\n") + } + + fn emit_field_constant_constants(&self) -> String { + let constants = self + .field_constants + .iter() + .map(|constant| { + format!( + " Stage5FieldConstantPlan {{ symbol: {}, field: {}, value: {} }},", + rust_str(&constant.symbol), + rust_str(&constant.field), + constant.value + ) + }) + .collect::>() + .join("\n"); + format!( + "pub const STAGE5_FIELD_CONSTANTS: &[Stage5FieldConstantPlan] = &[\n{constants}\n];\n\n" + ) + } + + fn emit_field_expr_constants(&self) -> String { + if self.role == Role::Verifier { + let exprs = self + .field_exprs + .iter() + .map(|expr| { + format!( + " Stage5FieldExprPlan {{ symbol: {}, kind: {}, formula: {}, operands: {} }},", + rust_str(&expr.symbol), + rust_str(&expr.kind), + rust_str(&expr.formula), + rust_str(&expr.operands.join("|")) + ) + }) + .collect::>() + .join("\n"); + return format!( + "pub const STAGE5_FIELD_EXPRS: &[Stage5FieldExprPlan] = &[\n{exprs}\n];\n" + ); + } + + let mut source = String::new(); + let mut arrays = Vec::new(); + let mut array_refs = Vec::new(); + for (index, expr) in self.field_exprs.iter().enumerate() { + let operands = intern_str_array( + &mut source, + &mut arrays, + "STAGE5_FIELD_EXPR_OPERANDS", + &expr.operands, + ); + let operand_names = intern_str_array( + &mut source, + &mut arrays, + "STAGE5_FIELD_EXPR_OPERANDS", + &expr.operand_names, + ); + array_refs.push((index, operand_names, operands)); + } + let exprs = self + .field_exprs + .iter() + .enumerate() + .map(|(index, expr)| { + let (_, operand_names, operands) = &array_refs[index]; + format!( + " Stage5FieldExprPlan {{ symbol: {}, kind: {}, formula: {}, operand_names: {operand_names}, operands: {operands} }},", + rust_str(&expr.symbol), + rust_str(&expr.kind), + rust_str(&expr.formula) + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE5_FIELD_EXPRS: &[Stage5FieldExprPlan] = &[\n{exprs}\n];\n" + ), + ); + source + } + + fn emit_kernel_constants(&self) -> String { + let kernels = self + .kernels + .iter() + .map(|kernel| { + format!( + " Stage5KernelPlan {{ symbol: {}, relation: {}, kind: {}, backend: {}, abi: {} }},", + rust_str(&kernel.symbol), + rust_str(&kernel.relation), + rust_str(&kernel.kind), + rust_str(&kernel.backend), + rust_str(&kernel.abi) + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE5_KERNELS: &[Stage5KernelPlan] = &[\n{kernels}\n];\n\n") + } + + fn emit_sumcheck_claim_constants(&self) -> String { + if self.role == Role::Verifier { + let claims = self + .claims + .iter() + .map(|claim| { + format!( + " Stage5SumcheckClaimPlan {{ symbol: {}, stage: {}, domain: {}, num_rounds: {}, degree: {}, claim: {}, kernel: {}, relation: {}, claim_value: {}, input_openings: {} }},", + rust_str(&claim.symbol), + rust_str(&claim.stage), + rust_str(&claim.domain), + claim.num_rounds, + claim.degree, + rust_str(&claim.claim), + rust_option_str(claim.kernel.as_deref()), + rust_option_str(claim.relation.as_deref()), + rust_str(&claim.claim_value), + rust_str(&claim.input_openings.join("|")) + ) + }) + .collect::>() + .join("\n"); + return format!( + "pub const STAGE5_SUMCHECK_CLAIMS: &[Stage5SumcheckClaimPlan] = &[\n{claims}\n];\n" + ); + } + + let mut source = String::new(); + for (index, claim) in self.claims.iter().enumerate() { + source.push_str(&emit_str_array( + &format!("STAGE5_SUMCHECK_CLAIM_{index}_INPUT_OPENINGS"), + &claim.input_openings, + )); + } + let claims = self + .claims + .iter() + .enumerate() + .map(|(index, claim)| { + format!( + " Stage5SumcheckClaimPlan {{ symbol: {}, stage: {}, domain: {}, num_rounds: {}, degree: {}, claim: {}, kernel: {}, relation: {}, claim_value: {}, input_openings: STAGE5_SUMCHECK_CLAIM_{index}_INPUT_OPENINGS }},", + rust_str(&claim.symbol), + rust_str(&claim.stage), + rust_str(&claim.domain), + claim.num_rounds, + claim.degree, + rust_str(&claim.claim), + rust_option_str(claim.kernel.as_deref()), + rust_option_str(claim.relation.as_deref()), + rust_str(&claim.claim_value) + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE5_SUMCHECK_CLAIMS: &[Stage5SumcheckClaimPlan] = &[\n{claims}\n];\n" + ), + ); + source + } + + fn emit_sumcheck_batch_constants(&self) -> String { + if self.role == Role::Verifier { + let mut source = String::new(); + for (index, batch) in self.batches.iter().enumerate() { + source.push_str(&emit_usize_array( + &format!("STAGE5_SUMCHECK_BATCH_{index}_ROUND_SCHEDULE"), + &batch.round_schedule, + )); + } + let batches = self + .batches + .iter() + .enumerate() + .map(|(index, batch)| { + format!( + " Stage5SumcheckBatchPlan {{ symbol: {}, stage: {}, proof_slot: {}, policy: {}, count: {}, ordered_claims: {}, claim_operands: {}, claim_label: {}, round_label: {}, round_schedule: STAGE5_SUMCHECK_BATCH_{index}_ROUND_SCHEDULE }},", + rust_str(&batch.symbol), + rust_str(&batch.stage), + rust_str(&batch.proof_slot), + rust_str(&batch.policy), + batch.count, + rust_str(&batch.ordered_claims.join("|")), + rust_str(&batch.claim_operands.join("|")), + rust_str(&batch.claim_label), + rust_str(&batch.round_label) + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE5_SUMCHECK_BATCHES: &[Stage5SumcheckBatchPlan] = &[\n{batches}\n];\n" + ), + ); + return source; + } + + let mut source = String::new(); + for (index, batch) in self.batches.iter().enumerate() { + source.push_str(&emit_str_array( + &format!("STAGE5_SUMCHECK_BATCH_{index}_ORDERED_CLAIMS"), + &batch.ordered_claims, + )); + source.push_str(&emit_str_array( + &format!("STAGE5_SUMCHECK_BATCH_{index}_CLAIM_OPERANDS"), + &batch.claim_operands, + )); + source.push_str(&emit_usize_array( + &format!("STAGE5_SUMCHECK_BATCH_{index}_ROUND_SCHEDULE"), + &batch.round_schedule, + )); + } + let batches = self + .batches + .iter() + .enumerate() + .map(|(index, batch)| { + format!( + " Stage5SumcheckBatchPlan {{ symbol: {}, stage: {}, proof_slot: {}, policy: {}, count: {}, ordered_claims: STAGE5_SUMCHECK_BATCH_{index}_ORDERED_CLAIMS, claim_operands: STAGE5_SUMCHECK_BATCH_{index}_CLAIM_OPERANDS, claim_label: {}, round_label: {}, round_schedule: STAGE5_SUMCHECK_BATCH_{index}_ROUND_SCHEDULE }},", + rust_str(&batch.symbol), + rust_str(&batch.stage), + rust_str(&batch.proof_slot), + rust_str(&batch.policy), + batch.count, + rust_str(&batch.claim_label), + rust_str(&batch.round_label) + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE5_SUMCHECK_BATCHES: &[Stage5SumcheckBatchPlan] = &[\n{batches}\n];\n" + ), + ); + source + } + + fn emit_sumcheck_driver_constants(&self) -> String { + let mut source = String::new(); + for (index, driver) in self.drivers.iter().enumerate() { + source.push_str(&emit_usize_array( + &format!("STAGE5_SUMCHECK_DRIVER_{index}_ROUND_SCHEDULE"), + &driver.round_schedule, + )); + } + let drivers = self + .drivers + .iter() + .enumerate() + .map(|(index, driver)| { + format!( + " Stage5SumcheckDriverPlan {{ symbol: {}, stage: {}, proof_slot: {}, kernel: {}, relation: {}, batch: {}, policy: {}, round_schedule: STAGE5_SUMCHECK_DRIVER_{index}_ROUND_SCHEDULE, claim_label: {}, round_label: {}, num_rounds: {}, degree: {} }},", + rust_str(&driver.symbol), + rust_str(&driver.stage), + rust_str(&driver.proof_slot), + rust_option_str(driver.kernel.as_deref()), + rust_option_str(driver.relation.as_deref()), + rust_str(&driver.batch), + rust_str(&driver.policy), + rust_str(&driver.claim_label), + rust_str(&driver.round_label), + driver.num_rounds, + driver.degree + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE5_SUMCHECK_DRIVERS: &[Stage5SumcheckDriverPlan] = &[\n{drivers}\n];\n" + ), + ); + source + } + + fn emit_tail_constants(&self) -> String { + let mut source = String::new(); + source.push_str(&self.emit_sumcheck_instance_result_constants()); + source.push_str(&self.emit_sumcheck_eval_constants()); + source.push_str(&self.emit_point_slice_constants()); + source.push_str(&self.emit_point_concat_constants()); + source.push_str(&self.emit_opening_claim_constants()); + source.push_str(&self.emit_opening_claim_equality_constants()); + source.push_str(&self.emit_opening_batch_constants()); + source + } + + fn emit_sumcheck_instance_result_constants(&self) -> String { + let instances = self + .instance_results + .iter() + .map(|instance| { + format!( + " Stage5SumcheckInstanceResultPlan {{ symbol: {}, source: {}, claim: {}, relation: {}, index: {}, point_arity: {}, num_rounds: {}, round_offset: {}, point_order: {}, degree: {} }},", + rust_str(&instance.symbol), + rust_str(&instance.source), + rust_str(&instance.claim), + rust_str(&instance.relation), + instance.index, + instance.point_arity, + instance.num_rounds, + instance.round_offset, + rust_str(&instance.point_order), + instance.degree + ) + }) + .collect::>() + .join("\n"); + format!( + "pub const STAGE5_SUMCHECK_INSTANCE_RESULTS: &[Stage5SumcheckInstanceResultPlan] = &[\n{instances}\n];\n\n" + ) + } + + fn emit_sumcheck_eval_constants(&self) -> String { + let evals = self + .evals + .iter() + .map(|eval| { + format!( + " Stage5SumcheckEvalPlan {{ symbol: {}, source: {}, name: {}, index: {}, oracle: {} }},", + rust_str(&eval.symbol), + rust_str(&eval.source), + rust_str(&eval.name), + eval.index, + rust_str(&eval.oracle) + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE5_SUMCHECK_EVALS: &[Stage5SumcheckEvalPlan] = &[\n{evals}\n];\n\n") + } + + fn emit_point_slice_constants(&self) -> String { + let slices = self + .point_slices + .iter() + .map(|slice| { + format!( + " Stage5PointSlicePlan {{ symbol: {}, source: {}, offset: {}, length: {}, input: {} }},", + rust_str(&slice.symbol), + rust_str(&slice.source), + slice.offset, + slice.length, + rust_str(&slice.input) + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE5_POINT_SLICES: &[Stage5PointSlicePlan] = &[\n{slices}\n];\n\n") + } + + fn emit_point_concat_constants(&self) -> String { + if self.role == Role::Verifier { + let concats = self + .point_concats + .iter() + .map(|concat| { + format!( + " Stage5PointConcatPlan {{ symbol: {}, layout: {}, arity: {}, inputs: {} }},", + rust_str(&concat.symbol), + rust_str(&concat.layout), + concat.arity, + rust_str(&concat.inputs.join("|")) + ) + }) + .collect::>() + .join("\n"); + return format!( + "pub const STAGE5_POINT_CONCATS: &[Stage5PointConcatPlan] = &[\n{concats}\n];\n" + ); + } + + let mut source = String::new(); + for (index, concat) in self.point_concats.iter().enumerate() { + source.push_str(&emit_str_array( + &format!("STAGE5_POINT_CONCAT_{index}_INPUTS"), + &concat.inputs, + )); + } + let concats = self + .point_concats + .iter() + .enumerate() + .map(|(index, concat)| { + format!( + " Stage5PointConcatPlan {{ symbol: {}, layout: {}, arity: {}, inputs: STAGE5_POINT_CONCAT_{index}_INPUTS }},", + rust_str(&concat.symbol), + rust_str(&concat.layout), + concat.arity + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE5_POINT_CONCATS: &[Stage5PointConcatPlan] = &[\n{concats}\n];\n" + ), + ); + source + } + + fn emit_opening_claim_constants(&self) -> String { + let claims = self + .opening_claims + .iter() + .map(|claim| { + format!( + " Stage5OpeningClaimPlan {{ symbol: {}, oracle: {}, domain: {}, point_arity: {}, claim_kind: {}, point_source: {}, eval_source: {} }},", + rust_str(&claim.symbol), + rust_str(&claim.oracle), + rust_str(&claim.domain), + claim.point_arity, + rust_str(&claim.claim_kind), + rust_str(&claim.point_source), + rust_str(&claim.eval_source) + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE5_OPENING_CLAIMS: &[Stage5OpeningClaimPlan] = &[\n{claims}\n];\n\n") + } + + fn emit_opening_claim_equality_constants(&self) -> String { + let equalities = self + .opening_equalities + .iter() + .map(|equality| { + format!( + " Stage5OpeningClaimEqualityPlan {{ symbol: {}, mode: {}, lhs: {}, rhs: {} }},", + rust_str(&equality.symbol), + rust_str(&equality.mode), + rust_str(&equality.lhs), + rust_str(&equality.rhs) + ) + }) + .collect::>() + .join("\n"); + format!( + "pub const STAGE5_OPENING_EQUALITIES: &[Stage5OpeningClaimEqualityPlan] = &[\n{equalities}\n];\n\n" + ) + } + + fn emit_opening_batch_constants(&self) -> String { + if self.role == Role::Verifier { + let batches = self + .opening_batches + .iter() + .map(|batch| { + format!( + " Stage5OpeningBatchPlan {{ symbol: {}, stage: {}, proof_slot: {}, policy: {}, count: {}, ordered_claims: {}, claim_operands: {} }},", + rust_str(&batch.symbol), + rust_str(&batch.stage), + rust_str(&batch.proof_slot), + rust_str(&batch.policy), + batch.count, + rust_str(&batch.ordered_claims.join("|")), + rust_str(&batch.claim_operands.join("|")) + ) + }) + .collect::>() + .join("\n"); + return format!( + "pub const STAGE5_OPENING_BATCHES: &[Stage5OpeningBatchPlan] = &[\n{batches}\n];\n" + ); + } + + let mut source = String::new(); + for (index, batch) in self.opening_batches.iter().enumerate() { + source.push_str(&emit_str_array( + &format!("STAGE5_OPENING_BATCH_{index}_ORDERED_CLAIMS"), + &batch.ordered_claims, + )); + source.push_str(&emit_str_array( + &format!("STAGE5_OPENING_BATCH_{index}_CLAIM_OPERANDS"), + &batch.claim_operands, + )); + } + let batches = self + .opening_batches + .iter() + .enumerate() + .map(|(index, batch)| { + format!( + " Stage5OpeningBatchPlan {{ symbol: {}, stage: {}, proof_slot: {}, policy: {}, count: {}, ordered_claims: STAGE5_OPENING_BATCH_{index}_ORDERED_CLAIMS, claim_operands: STAGE5_OPENING_BATCH_{index}_CLAIM_OPERANDS }},", + rust_str(&batch.symbol), + rust_str(&batch.stage), + rust_str(&batch.proof_slot), + rust_str(&batch.policy), + batch.count + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE5_OPENING_BATCHES: &[Stage5OpeningBatchPlan] = &[\n{batches}\n];\n" + ), + ); + source + } + + fn emit_entrypoint(&self) -> &'static str { + match self.role { + Role::Prover => { + "pub fn execute_stage5_prover(\n\ + \x20 executor: &mut E,\n\ + \x20 transcript: &mut T,\n\ + ) -> Result, Stage5KernelError>\n\ + where\n\ + \x20 E: Stage5KernelExecutor,\n\ + \x20 T: Transcript,\n\ + {\n\ + \x20 execute_stage5_prover_with_program(&STAGE5_PROGRAM, executor, transcript)\n\ + }\n\ + \n\ + pub fn execute_stage5_prover_with_program(\n\ + \x20 program: &'static Stage5CpuProgramPlan,\n\ + \x20 executor: &mut E,\n\ + \x20 transcript: &mut T,\n\ + ) -> Result, Stage5KernelError>\n\ + where\n\ + \x20 E: Stage5KernelExecutor,\n\ + \x20 T: Transcript,\n\ + {\n\ + \x20 execute_stage5_program(program, Stage5ExecutionMode::Prover, executor, transcript)\n\ + }\n" + } + Role::Verifier => { + r#"pub fn verify_stage5( + proof: &Stage5Proof, + opening_inputs: &[Stage5OpeningInputValue], + transcript: &mut T, +) -> Result, VerifyStage5Error> +where + T: Transcript, +{ + verify_stage5_with_program(&STAGE5_PROGRAM, proof, opening_inputs, transcript) +} + +pub fn verify_stage5_with_program( + program: &'static Stage5VerifierProgramPlan, + proof: &Stage5Proof, + opening_inputs: &[Stage5OpeningInputValue], + transcript: &mut T, +) -> Result, VerifyStage5Error> +where + T: Transcript, +{ + if proof.sumchecks.len() != program.drivers.len() { + return Err(VerifyStage5Error::UnexpectedProofCount { + expected: program.drivers.len(), + got: proof.sumchecks.len(), + }); + } + let mut store = + super::common::ValueStore::with_opening_inputs(opening_inputs, program.opening_inputs)?; + store.seed_constants(program.field_constants); + let mut artifacts = Stage5ExecutionArtifacts::default(); + for step in program.steps { + match step.kind { + "transcript_squeeze" => { + let squeeze = + find_plan(program.transcript_squeezes, step.symbol).ok_or(VerifyStage5Error::MissingValue { + symbol: step.symbol, + })?; + verify_stage5_squeeze(program, squeeze, &mut store, transcript, &mut artifacts)?; + } + "transcript_absorb_bytes" => { + let absorb = find_plan(program.transcript_absorb_bytes, step.symbol).ok_or( + VerifyStage5Error::MissingValue { + symbol: step.symbol, + }, + )?; + absorb_stage5_bytes(absorb, transcript); + } + "sumcheck_driver" => { + let driver = + find_plan(program.drivers, step.symbol).ok_or(VerifyStage5Error::MissingProof { + driver: step.symbol, + })?; + verify_stage5_driver(program, driver, proof, &mut store, transcript, &mut artifacts)?; + } + _ => { + return Err(VerifyStage5Error::InvalidProof { + driver: step.symbol, + reason: "unsupported stage5 program step", + }); + } + } + } + artifacts + .opening_batches + .extend(program.opening_batches.iter()); + Ok(artifacts) +} + +pub fn stage5_verifier_program() -> &'static Stage5VerifierProgramPlan { + &STAGE5_PROGRAM +} + +fn verify_stage5_squeeze( + program: &'static Stage5VerifierProgramPlan, + squeeze: &'static Stage5TranscriptSqueezePlan, + store: &mut super::common::ValueStore, + transcript: &mut T, + artifacts: &mut Stage5ExecutionArtifacts, +) -> Result<(), VerifyStage5Error> +where + T: Transcript, +{ + let values = transcript.challenge_vector(squeeze.count); + store.observe_challenge_vector(squeeze, &values, |input, expected, actual| { + VerifyStage5Error::InvalidInputLength { + input, + expected, + actual, + } + })?; + store + .evaluate_available_field_exprs(program.field_exprs, super::common::evaluate_field_expr) + .map_err(VerifyStage5Error::from)?; + artifacts.challenge_vectors.push(Stage5ChallengeVector { + symbol: squeeze.symbol, + values, + }); + Ok(()) +} + +fn absorb_stage5_bytes(absorb: &'static Stage5TranscriptAbsorbBytesPlan, transcript: &mut T) +where + T: Transcript, +{ + transcript.append(&LabelWithCount( + absorb.label.as_bytes(), + absorb.payload.len() as u64, + )); + transcript.append_bytes(absorb.payload.as_bytes()); +} + +fn verify_stage5_driver( + program: &'static Stage5VerifierProgramPlan, + driver: &'static Stage5SumcheckDriverPlan, + proof: &Stage5Proof, + store: &mut super::common::ValueStore, + transcript: &mut T, + artifacts: &mut Stage5ExecutionArtifacts, +) -> Result<(), VerifyStage5Error> +where + T: Transcript, +{ + let proof = proof + .sumchecks + .get(artifacts.sumchecks.len()) + .ok_or(VerifyStage5Error::MissingProof { + driver: driver.symbol, + })?; + let relation = driver.relation.unwrap_or(""); + let output = match relation { + "jolt.stage5.batched" => { + verify_batched_stage5(program, driver, proof, store, transcript)? + } + _ => return Err(VerifyStage5Error::UnsupportedRelation { relation }), + }; + artifacts.sumchecks.push(output); + Ok(()) +} + +fn verify_batched_stage5( + program: &'static Stage5VerifierProgramPlan, + driver: &'static Stage5SumcheckDriverPlan, + proof: &Stage5SumcheckOutput, + store: &mut super::common::ValueStore, + transcript: &mut T, +) -> Result, VerifyStage5Error> +where + T: Transcript, +{ + super::common::verify_batched_sumcheck( + driver, + proof, + program.claims, + program.batches, + program.field_exprs, + program.opening_inputs, + program.opening_claims, + program.opening_batches, + store, + transcript, + |store, evals, point, batching_coeffs| { + expected_batched_output_claim(program, driver, store, evals, point, batching_coeffs) + }, + |store, verified| observe_stage5_sumcheck_output(program, store, verified), + |driver, error| VerifyStage5Error::Sumcheck { driver, error }, + ) +} + +fn observe_stage5_sumcheck_output( + program: &'static Stage5VerifierProgramPlan, + store: &mut super::common::ValueStore, + output: &Stage5SumcheckOutput, +) -> Result<(), VerifyStage5Error> { + store.observe_sumcheck_output( + program.instance_results, + program.evals, + output, + |instance, mut point| { + match instance.point_order { + "as_is" => {} + "reverse" => point.reverse(), + "instruction_read_raf" => { + point = normalize_instruction_read_raf_point(&point, "stage5.instruction_read_raf.point")?; + } + _ => { + return Err(VerifyStage5Error::InvalidProof { + driver: output.driver, + reason: "unsupported point order", + }); + } + } + Ok(point) + }, + |input, expected, actual| VerifyStage5Error::InvalidInputLength { + input, + expected, + actual, + }, + |symbol| VerifyStage5Error::MissingValue { symbol }, + )?; + store.evaluate_available_points( + program.point_slices, + program.point_concats, + |input, expected, actual| VerifyStage5Error::InvalidInputLength { + input, + expected, + actual, + }, + )?; + store + .evaluate_available_field_exprs(program.field_exprs, super::common::evaluate_field_expr) + .map_err(VerifyStage5Error::from)?; + store.verify_opening_equalities( + program.opening_equalities, + |driver, reason| VerifyStage5Error::InvalidProof { driver, reason }, + |symbol| VerifyStage5Error::MissingValue { symbol }, + ) +} + +fn expected_batched_output_claim( + program: &'static Stage5VerifierProgramPlan, + driver: &'static Stage5SumcheckDriverPlan, + store: &super::common::ValueStore, + evals: &[Stage5NamedEval], + point: &[Fr], + batching_coeffs: &[Fr], +) -> Result { + let batch = find_batch(program.batches, driver.symbol, driver.batch)?; + let claims = batch_claims(program.claims, batch)?; + let mut expected = Fr::from_u64(0); + for (claim, coefficient) in claims.iter().zip(batching_coeffs) { + let instance = program + .instance_results + .iter() + .find(|instance| instance.claim == claim.symbol && instance.source == driver.symbol) + .ok_or(VerifyStage5Error::MissingClaim { + batch: batch.symbol, + claim: claim.symbol, + })?; + let local_point = point + .get(instance.round_offset..instance.round_offset + instance.num_rounds) + .ok_or(VerifyStage5Error::InvalidInputLength { + input: instance.symbol, + expected: instance.round_offset + instance.num_rounds, + actual: point.len(), + })?; + let relation = claim.relation.unwrap_or(""); + let value = match relation { + "jolt.stage5.instruction_read_raf" => { + expected_instruction_read_raf(store, evals, local_point)? + } + "jolt.stage5.ram_ra_claim_reduction" => { + expected_ram_ra_claim_reduction(store, evals, local_point)? + } + "jolt.stage5.registers_val_evaluation" => { + expected_registers_val_evaluation(store, evals, local_point)? + } + _ => return Err(VerifyStage5Error::UnsupportedRelation { relation }), + }; + expected += *coefficient * value; + } + Ok(expected) +} + +fn expected_instruction_read_raf( + store: &super::common::ValueStore, + evals: &[Stage5NamedEval], + local_point: &[Fr], +) -> Result { + const LOG_K: usize = 128; + const XLEN: usize = 64; + + if local_point.len() < LOG_K { + return Err(VerifyStage5Error::InvalidInputLength { + input: "stage5.instruction_read_raf.point", + expected: LOG_K, + actual: local_point.len(), + }); + } + + let (r_address_prime, r_cycle) = local_point.split_at(LOG_K); + let r_cycle_prime = reverse_slice(r_cycle); + let r_reduction = super::common::store_point(store, "stage5.input.stage2.instruction.LookupOutput")?; + let eq_eval_r_reduction = EqPolynomial::::mle(r_reduction, &r_cycle_prime); + + let left_operand_eval = operand_polynomial_eval(r_address_prime, true); + let right_operand_eval = operand_polynomial_eval(r_address_prime, false); + let identity_poly_eval = identity_polynomial_eval(r_address_prime); + + let table_values = LookupTableKind::::all() + .iter() + .map(|table| table.evaluate_mle::(r_address_prime)) + .collect::>(); + let table_flag_claims = indexed_evals_by_prefix( + evals, + "stage5.instruction_read_raf.eval.LookupTableFlag_", + table_values.len(), + )?; + let val_claim = table_values + .into_iter() + .zip(table_flag_claims) + .map(|(table_value, flag_claim)| table_value * flag_claim) + .sum::(); + + let ra_claim = indexed_evals_by_prefix_any( + evals, + "stage5.instruction_read_raf.eval.InstructionRa_", + )? + .into_iter() + .product::(); + let raf_flag_claim = eval_by_name( + evals, + "stage5.instruction_read_raf.eval.InstructionRafFlag", + )?; + let gamma = super::common::store_scalar(store, "stage5.instruction_read_raf.gamma")?; + + let raf_claim = (Fr::from_u64(1) - raf_flag_claim) + * (left_operand_eval + gamma * right_operand_eval) + + raf_flag_claim * gamma * identity_poly_eval; + Ok(eq_eval_r_reduction * ra_claim * (val_claim + gamma * raf_claim)) +} + +fn expected_ram_ra_claim_reduction( + store: &super::common::ValueStore, + evals: &[Stage5NamedEval], + local_point: &[Fr], +) -> Result { + let r_cycle_reduced = reverse_slice(local_point); + let r_cycle_raf = suffix_point( + super::common::store_point(store, "stage5.input.stage2.ram_raf.RamRa")?, + r_cycle_reduced.len(), + "stage5.input.stage2.ram_raf.RamRa", + )?; + let r_cycle_rw = suffix_point( + super::common::store_point(store, "stage5.input.stage2.ram_read_write.RamRa")?, + r_cycle_reduced.len(), + "stage5.input.stage2.ram_read_write.RamRa", + )?; + let r_cycle_val = suffix_point( + super::common::store_point(store, "stage5.input.stage4.ram_val_check.RamRa")?, + r_cycle_reduced.len(), + "stage5.input.stage4.ram_val_check.RamRa", + )?; + let gamma = super::common::store_scalar(store, "stage5.ram_ra_claim_reduction.gamma")?; + let eq_combined = EqPolynomial::::mle(r_cycle_raf, &r_cycle_reduced) + + gamma * EqPolynomial::::mle(r_cycle_rw, &r_cycle_reduced) + + gamma.square() * EqPolynomial::::mle(r_cycle_val, &r_cycle_reduced); + let ram_ra = eval_by_name(evals, "stage5.ram_ra_claim_reduction.eval.RamRa")?; + Ok(eq_combined * ram_ra) +} + +fn expected_registers_val_evaluation( + store: &super::common::ValueStore, + evals: &[Stage5NamedEval], + local_point: &[Fr], +) -> Result { + let registers_val_point = super::common::store_point(store, "stage5.input.stage4.registers.RegistersVal")?; + let r_cycle = suffix_point( + registers_val_point, + local_point.len(), + "stage5.input.stage4.registers.RegistersVal", + )?; + let r_reduced = reverse_slice(local_point); + let lt_eval = lt_polynomial_eval(&r_reduced, r_cycle); + let rd_inc = eval_by_name(evals, "stage5.registers_val_evaluation.eval.RdInc")?; + let rd_wa = eval_by_name(evals, "stage5.registers_val_evaluation.eval.RdWa")?; + Ok(rd_inc * rd_wa * lt_eval) +} + +"# + } + } + } + + fn role_label(&self) -> &'static str { + match self.role { + Role::Prover => "prover", + Role::Verifier => "verifier", + } + } + + fn program_plan_type(&self) -> &'static str { + match self.role { + Role::Prover => "Stage5CpuProgramPlan", + Role::Verifier => "Stage5VerifierProgramPlan", + } + } +} + +fn require_supported_symbol(kind: &str, actual: &str, expected: &str) -> Result<(), EmitError> { + if actual == expected { + Ok(()) + } else { + Err(EmitError::new(format!( + "unsupported {kind} @{actual}; expected @{expected}" + ))) + } +} + +fn emit_str_array(name: &str, values: &[String]) -> String { + if values.is_empty() { + return format!("pub const {name}: &[&str] = &[];\n\n"); + } + if let [value] = values { + return format!("pub const {name}: &[&str] = &[{}];\n\n", rust_str(value)); + } + let entries = values + .iter() + .map(|value| format!(" {},", rust_str(value))) + .collect::>() + .join("\n"); + format!("pub const {name}: &[&str] = &[\n{entries}\n];\n\n") +} + +fn emit_usize_array(name: &str, values: &[usize]) -> String { + let entries = values + .iter() + .map(|value| format!(" {value},")) + .collect::>() + .join("\n"); + format!("pub const {name}: &[usize] = &[\n{entries}\n];\n\n") +} + +fn intern_str_array( + source: &mut String, + arrays: &mut Vec<(Vec, String)>, + name_prefix: &str, + values: &[String], +) -> String { + if let Some((_, name)) = arrays + .iter() + .find(|(existing, _)| existing.as_slice() == values) + { + return name.clone(); + } + let name = format!("{name_prefix}_{}", arrays.len()); + source.push_str(&emit_str_array(&name, values)); + arrays.push((values.to_vec(), name.clone())); + name +} + +fn rust_str(value: &str) -> String { + format!("{value:?}") +} + +fn rust_option_str(value: Option<&str>) -> String { + value.map_or_else( + || "None".to_owned(), + |value| format!("Some({})", rust_str(value)), + ) +} + +fn verify_count(kind: &str, symbol: &str, expected: usize, actual: usize) -> Result<(), EmitError> { + if expected == actual { + Ok(()) + } else { + Err(EmitError::new(format!( + "{kind} @{symbol} count mismatch: expected {expected}, got {actual}" + ))) + } +} + +fn symbols<'a>(values: impl Iterator) -> BTreeSet { + values.cloned().collect() +} + +fn string_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .ok() + .and_then(string_attribute_value) + .ok_or_else(|| attr_error(operation, attr, "string")) +} + +fn symbol_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .ok() + .and_then(symbol_attribute_value) + .ok_or_else(|| attr_error(operation, attr, "symbol")) +} + +fn symbol_array_attr( + operation: OperationRef<'_, '_>, + attr: &str, +) -> Result, EmitError> { + let attribute = operation + .attribute(attr) + .map(|attribute| attribute.to_string()) + .ok() + .ok_or_else(|| attr_error(operation, attr, "symbol array"))?; + parse_symbol_array(&attribute).ok_or_else(|| attr_error(operation, attr, "symbol array")) +} + +fn parse_symbol_array(attribute: &str) -> Option> { + let inner = attribute.strip_prefix('[')?.strip_suffix(']')?.trim(); + if inner.is_empty() { + return Some(Vec::new()); + } + inner + .split(',') + .map(|item| item.trim().strip_prefix('@').map(ToOwned::to_owned)) + .collect() +} + +fn int_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .map(parse_integer_attr) + .ok() + .flatten() + .ok_or_else(|| attr_error(operation, attr, "integer")) +} + +fn parse_integer_attr(attribute: Attribute<'_>) -> Option { + attribute + .to_string() + .split_whitespace() + .next() + .and_then(|value| value.parse().ok()) +} + +fn int_array_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result, EmitError> { + let attribute = operation + .attribute(attr) + .map(|attribute| attribute.to_string()) + .ok() + .ok_or_else(|| attr_error(operation, attr, "integer array"))?; + parse_int_array(&attribute).ok_or_else(|| attr_error(operation, attr, "integer array")) +} + +fn parse_int_array(attribute: &str) -> Option> { + let inner = attribute.strip_prefix('[')?.strip_suffix(']')?.trim(); + if inner.is_empty() { + return Some(Vec::new()); + } + inner + .split(',') + .map(|item| item.trim().parse().ok()) + .collect() +} + +fn operand_symbols( + operation: OperationRef<'_, '_>, + start_index: usize, +) -> Result, EmitError> { + (start_index..operation.operand_count()) + .map(|index| operand_symbol(operation, index)) + .collect() +} + +fn operand_symbol(operation: OperationRef<'_, '_>, index: usize) -> Result { + let operand = operation.operand(index).map_err(|_| { + EmitError::new(format!( + "{} requires operand {index}", + operation_name(operation) + )) + })?; + let owner = OperationResult::try_from(operand).map_err(|_| { + EmitError::new(format!( + "{} operand {index} must be an op result", + operation_name(operation) + )) + })?; + string_attr(owner.owner(), "sym_name") +} + +fn attr_error(operation: OperationRef<'_, '_>, attr: &str, expected: &str) -> EmitError { + EmitError::new(format!( + "{} attr `{attr}` is not a {expected}", + operation_name(operation) + )) +} + +fn operation_name<'c: 'a, 'a>(operation: impl OperationLike<'c, 'a>) -> String { + operation + .name() + .as_string_ref() + .as_str() + .unwrap_or("") + .to_owned() +} diff --git a/crates/bolt/src/protocols/jolt/emit/rust/stage6.rs b/crates/bolt/src/protocols/jolt/emit/rust/stage6.rs new file mode 100644 index 0000000000..800eed9731 --- /dev/null +++ b/crates/bolt/src/protocols/jolt/emit/rust/stage6.rs @@ -0,0 +1,2655 @@ +#![expect( + clippy::needless_raw_string_hashes, + reason = "generated Rust templates are kept as raw string blocks for copyable output" +)] + +use std::collections::{BTreeMap, BTreeSet}; + +use melior::ir::block::BlockLike; +use melior::ir::operation::{OperationLike, OperationResult}; +use melior::ir::{Attribute, OperationRef}; + +use crate::emit::rust::{push_format, EmitError, RustSourceFile}; +use crate::ir::{string_attribute_value, symbol_attribute_value, BoltModule, Cpu, Role}; +use crate::schema::verify_cpu_schema; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage6CpuProgram { + pub role: Role, + pub params: Stage6Params, + pub steps: Vec, + pub transcript_squeezes: Vec, + pub transcript_absorb_bytes: Vec, + pub opening_inputs: Vec, + pub field_constants: Vec, + pub field_exprs: Vec, + pub kernels: Vec, + pub claims: Vec, + pub batches: Vec, + pub drivers: Vec, + pub instance_results: Vec, + pub evals: Vec, + pub point_zeros: Vec, + pub point_slices: Vec, + pub point_concats: Vec, + pub opening_claims: Vec, + pub opening_equalities: Vec, + pub opening_batches: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage6Params { + pub field: String, + pub pcs: String, + pub transcript: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage6KernelPlan { + pub symbol: String, + pub relation: String, + pub kind: String, + pub backend: String, + pub abi: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage6TranscriptSqueezePlan { + pub symbol: String, + pub label: String, + pub kind: String, + pub count: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage6TranscriptAbsorbBytesPlan { + pub symbol: String, + pub label: String, + pub payload: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage6ProgramStepPlan { + pub kind: String, + pub symbol: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage6OpeningInputPlan { + pub symbol: String, + pub source_stage: String, + pub source_claim: String, + pub oracle: String, + pub domain: String, + pub point_arity: usize, + pub claim_kind: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage6FieldConstantPlan { + pub symbol: String, + pub field: String, + pub value: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage6FieldExprPlan { + pub symbol: String, + pub kind: String, + pub formula: String, + pub operand_names: Vec, + pub operands: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage6SumcheckClaimPlan { + pub symbol: String, + pub stage: String, + pub domain: String, + pub num_rounds: usize, + pub degree: usize, + pub claim: String, + pub kernel: Option, + pub relation: Option, + pub claim_value: String, + pub input_openings: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage6SumcheckBatchPlan { + pub symbol: String, + pub stage: String, + pub proof_slot: String, + pub policy: String, + pub count: usize, + pub ordered_claims: Vec, + pub claim_operands: Vec, + pub claim_label: String, + pub round_label: String, + pub round_schedule: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage6SumcheckDriverPlan { + pub symbol: String, + pub stage: String, + pub proof_slot: String, + pub kernel: Option, + pub relation: Option, + pub batch: String, + pub policy: String, + pub round_schedule: Vec, + pub claim_label: String, + pub round_label: String, + pub num_rounds: usize, + pub degree: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage6SumcheckInstanceResultPlan { + pub symbol: String, + pub source: String, + pub claim: String, + pub relation: String, + pub index: usize, + pub point_arity: usize, + pub num_rounds: usize, + pub round_offset: usize, + pub point_order: String, + pub degree: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage6SumcheckEvalPlan { + pub symbol: String, + pub source: String, + pub name: String, + pub index: usize, + pub oracle: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage6PointZeroPlan { + pub symbol: String, + pub field: String, + pub arity: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage6PointSlicePlan { + pub symbol: String, + pub source: String, + pub offset: usize, + pub length: usize, + pub input: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage6PointConcatPlan { + pub symbol: String, + pub layout: String, + pub arity: usize, + pub inputs: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage6OpeningClaimPlan { + pub symbol: String, + pub oracle: String, + pub domain: String, + pub point_arity: usize, + pub claim_kind: String, + pub point_source: String, + pub eval_source: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage6OpeningClaimEqualityPlan { + pub symbol: String, + pub mode: String, + pub lhs: String, + pub rhs: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage6OpeningBatchPlan { + pub symbol: String, + pub stage: String, + pub proof_slot: String, + pub policy: String, + pub count: usize, + pub ordered_claims: Vec, + pub claim_operands: Vec, +} + +pub fn stage6_cpu_program(module: &BoltModule<'_, Cpu>) -> Result { + verify_cpu_schema(module)?; + let program = Stage6CpuProgram::from_module(module)?; + program.verify_supported_target()?; + Ok(program) +} + +pub fn emit_stage6_rust(module: &BoltModule<'_, Cpu>) -> Result { + let program = stage6_cpu_program(module)?; + + Ok(RustSourceFile { + filename: program.filename().to_owned(), + source: program.emit_source(), + }) +} + +impl Stage6CpuProgram { + fn from_module(module: &BoltModule<'_, Cpu>) -> Result { + let mut params = None; + let mut steps = Vec::new(); + let mut transcript_squeezes = Vec::new(); + let mut transcript_absorb_bytes = Vec::new(); + let mut opening_inputs = Vec::new(); + let mut field_constants = Vec::new(); + let mut field_exprs = Vec::new(); + let mut kernels = Vec::new(); + let mut claims = Vec::new(); + let mut batches = Vec::new(); + let mut drivers = Vec::new(); + let mut instance_results = Vec::new(); + let mut evals = Vec::new(); + let mut point_zeros = Vec::new(); + let mut point_slices = Vec::new(); + let mut point_concats = Vec::new(); + let mut opening_claims = Vec::new(); + let mut opening_equalities = Vec::new(); + let mut opening_batches = Vec::new(); + + let mut operation = module.as_mlir_module().body().first_operation(); + while let Some(op) = operation { + operation = op.next_in_block(); + match operation_name(op).as_str() { + "cpu.params" => { + params = Some(Stage6Params { + field: symbol_attr(op, "field")?, + pcs: symbol_attr(op, "pcs")?, + transcript: symbol_attr(op, "transcript")?, + }); + } + "cpu.kernel" => { + kernels.push(Stage6KernelPlan { + symbol: string_attr(op, "sym_name")?, + relation: symbol_attr(op, "relation")?, + kind: string_attr(op, "kind")?, + backend: string_attr(op, "backend")?, + abi: string_attr(op, "abi")?, + }); + } + "cpu.transcript_squeeze" => { + let symbol = string_attr(op, "sym_name")?; + steps.push(Stage6ProgramStepPlan { + kind: "transcript_squeeze".to_owned(), + symbol: symbol.clone(), + }); + transcript_squeezes.push(Stage6TranscriptSqueezePlan { + symbol, + label: string_attr(op, "label")?, + kind: string_attr(op, "kind")?, + count: int_attr(op, "count")?, + }); + } + "cpu.transcript_absorb_bytes" => { + let symbol = string_attr(op, "sym_name")?; + steps.push(Stage6ProgramStepPlan { + kind: "transcript_absorb_bytes".to_owned(), + symbol: symbol.clone(), + }); + transcript_absorb_bytes.push(Stage6TranscriptAbsorbBytesPlan { + symbol, + label: string_attr(op, "label")?, + payload: string_attr(op, "payload")?, + }); + } + "cpu.opening_input" => { + opening_inputs.push(Stage6OpeningInputPlan { + symbol: string_attr(op, "sym_name")?, + source_stage: symbol_attr(op, "source_stage")?, + source_claim: symbol_attr(op, "source_claim")?, + oracle: symbol_attr(op, "oracle")?, + domain: symbol_attr(op, "domain")?, + point_arity: int_attr(op, "point_arity")?, + claim_kind: string_attr(op, "claim_kind")?, + }); + } + "cpu.field_const" => { + field_constants.push(Stage6FieldConstantPlan { + symbol: string_attr(op, "sym_name")?, + field: symbol_attr(op, "field")?, + value: int_attr(op, "value")?, + }); + } + "cpu.field_zero" => { + field_constants.push(Stage6FieldConstantPlan { + symbol: string_attr(op, "sym_name")?, + field: symbol_attr(op, "field")?, + value: 0, + }); + } + "cpu.field_one" => { + field_constants.push(Stage6FieldConstantPlan { + symbol: string_attr(op, "sym_name")?, + field: symbol_attr(op, "field")?, + value: 1, + }); + } + "cpu.field_add" | "cpu.field_sub" | "cpu.field_mul" | "cpu.field_neg" => { + let operands = operand_symbols(op, 0)?; + field_exprs.push(Stage6FieldExprPlan { + symbol: string_attr(op, "sym_name")?, + kind: "op".to_owned(), + formula: operation_name(op).replace("cpu.field_", "field."), + operand_names: operands.clone(), + operands, + }); + } + "cpu.field_pow" => { + let exponent = int_attr(op, "exponent")?; + let operands = operand_symbols(op, 0)?; + field_exprs.push(Stage6FieldExprPlan { + symbol: string_attr(op, "sym_name")?, + kind: "op".to_owned(), + formula: format!("field.pow:{exponent}"), + operand_names: operands.clone(), + operands, + }); + } + "cpu.sumcheck_claim" => { + claims.push(Stage6SumcheckClaimPlan { + symbol: string_attr(op, "sym_name")?, + stage: symbol_attr(op, "stage")?, + domain: symbol_attr(op, "domain")?, + num_rounds: int_attr(op, "num_rounds")?, + degree: int_attr(op, "degree")?, + claim: symbol_attr(op, "claim")?, + kernel: Some(symbol_attr(op, "kernel")?), + relation: None, + claim_value: operand_symbol(op, 0)?, + input_openings: operand_symbols(op, 1)?, + }); + } + "cpu.sumcheck_verify_claim" => { + claims.push(Stage6SumcheckClaimPlan { + symbol: string_attr(op, "sym_name")?, + stage: symbol_attr(op, "stage")?, + domain: symbol_attr(op, "domain")?, + num_rounds: int_attr(op, "num_rounds")?, + degree: int_attr(op, "degree")?, + claim: symbol_attr(op, "claim")?, + kernel: None, + relation: Some(symbol_attr(op, "relation")?), + claim_value: operand_symbol(op, 0)?, + input_openings: operand_symbols(op, 1)?, + }); + } + "cpu.sumcheck_batch" => { + batches.push(Stage6SumcheckBatchPlan { + symbol: string_attr(op, "sym_name")?, + stage: symbol_attr(op, "stage")?, + proof_slot: symbol_attr(op, "proof_slot")?, + policy: string_attr(op, "policy")?, + count: int_attr(op, "count")?, + ordered_claims: symbol_array_attr(op, "ordered_claims")?, + claim_operands: operand_symbols(op, 0)?, + claim_label: string_attr(op, "claim_label")?, + round_label: string_attr(op, "round_label")?, + round_schedule: int_array_attr(op, "round_schedule")?, + }); + } + "cpu.sumcheck_driver" => { + let symbol = string_attr(op, "sym_name")?; + steps.push(Stage6ProgramStepPlan { + kind: "sumcheck_driver".to_owned(), + symbol: symbol.clone(), + }); + drivers.push(Stage6SumcheckDriverPlan { + symbol, + stage: symbol_attr(op, "stage")?, + proof_slot: symbol_attr(op, "proof_slot")?, + kernel: Some(symbol_attr(op, "kernel")?), + relation: None, + batch: operand_symbol(op, 1)?, + policy: string_attr(op, "policy")?, + round_schedule: int_array_attr(op, "round_schedule")?, + claim_label: string_attr(op, "claim_label")?, + round_label: string_attr(op, "round_label")?, + num_rounds: int_attr(op, "num_rounds")?, + degree: int_attr(op, "degree")?, + }); + } + "cpu.sumcheck_verify" => { + let symbol = string_attr(op, "sym_name")?; + steps.push(Stage6ProgramStepPlan { + kind: "sumcheck_driver".to_owned(), + symbol: symbol.clone(), + }); + drivers.push(Stage6SumcheckDriverPlan { + symbol, + stage: symbol_attr(op, "stage")?, + proof_slot: symbol_attr(op, "proof_slot")?, + kernel: None, + relation: Some(symbol_attr(op, "relation")?), + batch: operand_symbol(op, 1)?, + policy: string_attr(op, "policy")?, + round_schedule: int_array_attr(op, "round_schedule")?, + claim_label: string_attr(op, "claim_label")?, + round_label: string_attr(op, "round_label")?, + num_rounds: int_attr(op, "num_rounds")?, + degree: int_attr(op, "degree")?, + }); + } + "cpu.sumcheck_instance_result" => { + instance_results.push(Stage6SumcheckInstanceResultPlan { + symbol: string_attr(op, "sym_name")?, + source: symbol_attr(op, "source")?, + claim: symbol_attr(op, "claim")?, + relation: symbol_attr(op, "relation")?, + index: int_attr(op, "index")?, + point_arity: int_attr(op, "point_arity")?, + num_rounds: int_attr(op, "num_rounds")?, + round_offset: int_attr(op, "round_offset")?, + point_order: string_attr(op, "point_order")?, + degree: int_attr(op, "degree")?, + }); + } + "cpu.sumcheck_eval" => { + evals.push(Stage6SumcheckEvalPlan { + symbol: string_attr(op, "sym_name")?, + source: symbol_attr(op, "source")?, + name: symbol_attr(op, "name")?, + index: int_attr(op, "index")?, + oracle: symbol_attr(op, "oracle")?, + }); + } + "cpu.point_zero" => { + point_zeros.push(Stage6PointZeroPlan { + symbol: string_attr(op, "sym_name")?, + field: symbol_attr(op, "field")?, + arity: int_attr(op, "arity")?, + }); + } + "cpu.point_slice" => { + point_slices.push(Stage6PointSlicePlan { + symbol: string_attr(op, "sym_name")?, + source: symbol_attr(op, "source")?, + offset: int_attr(op, "offset")?, + length: int_attr(op, "length")?, + input: operand_symbol(op, 0)?, + }); + } + "cpu.point_concat" => { + point_concats.push(Stage6PointConcatPlan { + symbol: string_attr(op, "sym_name")?, + layout: string_attr(op, "layout")?, + arity: int_attr(op, "arity")?, + inputs: operand_symbols(op, 0)?, + }); + } + "cpu.opening_claim" => { + opening_claims.push(Stage6OpeningClaimPlan { + symbol: string_attr(op, "sym_name")?, + oracle: symbol_attr(op, "oracle")?, + domain: symbol_attr(op, "domain")?, + point_arity: int_attr(op, "point_arity")?, + claim_kind: string_attr(op, "claim_kind")?, + point_source: operand_symbol(op, 0)?, + eval_source: operand_symbol(op, 1)?, + }); + } + "cpu.opening_claim_equal" => { + opening_equalities.push(Stage6OpeningClaimEqualityPlan { + symbol: string_attr(op, "sym_name")?, + mode: string_attr(op, "mode")?, + lhs: operand_symbol(op, 0)?, + rhs: operand_symbol(op, 1)?, + }); + } + "cpu.opening_batch" => { + opening_batches.push(Stage6OpeningBatchPlan { + symbol: string_attr(op, "sym_name")?, + stage: symbol_attr(op, "stage")?, + proof_slot: symbol_attr(op, "proof_slot")?, + policy: string_attr(op, "policy")?, + count: int_attr(op, "count")?, + ordered_claims: symbol_array_attr(op, "ordered_claims")?, + claim_operands: operand_symbols(op, 0)?, + }); + } + _ => {} + } + } + + Ok(Self { + params: params.ok_or_else(|| EmitError::new("missing cpu.params"))?, + role: module + .role() + .ok_or_else(|| EmitError::new("missing cpu party role"))?, + steps, + transcript_squeezes, + transcript_absorb_bytes, + opening_inputs, + field_constants, + field_exprs, + kernels, + claims, + batches, + drivers, + instance_results, + evals, + point_zeros, + point_slices, + point_concats, + opening_claims, + opening_equalities, + opening_batches, + }) + } + + fn verify_supported_target(&self) -> Result<(), EmitError> { + require_supported_symbol("field", &self.params.field, "bn254_fr")?; + require_supported_symbol("pcs", &self.params.pcs, "dory")?; + require_supported_symbol("transcript", &self.params.transcript, "blake2b_transcript")?; + self.verify_transcript_steps()?; + self.verify_field_flow()?; + self.verify_claim_batches()?; + match self.role { + Role::Prover => { + self.verify_kernel_definitions()?; + self.verify_prover_driver_bindings()?; + } + Role::Verifier => self.verify_verifier_driver_bindings()?, + } + self.verify_opening_flow() + } + + fn verify_transcript_steps(&self) -> Result<(), EmitError> { + for squeeze in &self.transcript_squeezes { + if !matches!( + squeeze.kind.as_str(), + "challenge_scalar" | "challenge_vector" + ) { + return Err(EmitError::new(format!( + "stage6 transcript squeeze @{} has unsupported kind `{}`", + squeeze.symbol, squeeze.kind + ))); + } + if squeeze.count == 0 { + return Err(EmitError::new(format!( + "stage6 transcript squeeze @{} has zero count", + squeeze.symbol + ))); + } + } + for absorb in &self.transcript_absorb_bytes { + if absorb.label.is_empty() { + return Err(EmitError::new(format!( + "stage6 transcript byte absorb @{} has empty label", + absorb.symbol + ))); + } + } + Ok(()) + } + + fn verify_field_flow(&self) -> Result<(), EmitError> { + for constant in &self.field_constants { + require_supported_symbol("field constant field", &constant.field, "bn254_fr")?; + } + let field_values = self.field_value_symbols(); + for expr in &self.field_exprs { + verify_count( + "field expr operands", + &expr.symbol, + expr.operand_names.len(), + expr.operands.len(), + )?; + for operand in &expr.operands { + if !field_values.contains(operand) { + return Err(EmitError::new(format!( + "field expr @{} references missing field value @{operand}", + expr.symbol + ))); + } + } + } + for claim in &self.claims { + if !field_values.contains(&claim.claim_value) { + return Err(EmitError::new(format!( + "sumcheck claim @{} uses missing claim value @{}", + claim.symbol, claim.claim_value + ))); + } + } + Ok(()) + } + + fn field_value_symbols(&self) -> BTreeSet { + let mut values = symbols(self.opening_inputs.iter().map(|input| &input.symbol)); + values.extend(symbols( + self.field_constants.iter().map(|constant| &constant.symbol), + )); + values.extend(symbols( + self.transcript_squeezes + .iter() + .filter(|squeeze| matches!(squeeze.kind.as_str(), "challenge_scalar" | "scalar")) + .map(|squeeze| &squeeze.symbol), + )); + values.extend(symbols(self.field_exprs.iter().map(|expr| &expr.symbol))); + values.extend(symbols(self.evals.iter().map(|eval| &eval.symbol))); + values + } + + fn verify_kernel_definitions(&self) -> Result<(), EmitError> { + for kernel in &self.kernels { + if kernel.backend != "cpu" { + return Err(EmitError::new(format!( + "stage6 kernel @{} targets unsupported backend `{}`", + kernel.symbol, kernel.backend + ))); + } + if kernel.kind != "sumcheck" { + return Err(EmitError::new(format!( + "stage6 kernel @{} has unsupported kind `{}`", + kernel.symbol, kernel.kind + ))); + } + let expected_abi = match kernel.relation.as_str() { + "jolt.stage6.bytecode_read_raf" => "jolt_stage6_bytecode_read_raf", + "jolt.stage6.booleanity" => "jolt_stage6_booleanity", + "jolt.stage6.hamming_booleanity" => "jolt_stage6_hamming_booleanity", + "jolt.stage6.ram_ra_virtual" => "jolt_stage6_ram_ra_virtual", + "jolt.stage6.instruction_ra_virtual" => "jolt_stage6_instruction_ra_virtual", + "jolt.stage6.inc_claim_reduction" => "jolt_stage6_inc_claim_reduction", + "jolt.stage6.batched" => "jolt_stage6_batched", + _ => { + return Err(EmitError::new(format!( + "unsupported stage6 kernel relation @{}", + kernel.relation + ))); + } + }; + if kernel.abi != expected_abi { + return Err(EmitError::new(format!( + "stage6 kernel @{} ABI `{}` does not match relation @{}", + kernel.symbol, kernel.abi, kernel.relation + ))); + } + } + Ok(()) + } + + fn verify_claim_batches(&self) -> Result<(), EmitError> { + let claims = symbols(self.claims.iter().map(|claim| &claim.symbol)); + for batch in &self.batches { + verify_count( + "sumcheck batch", + &batch.symbol, + batch.count, + batch.ordered_claims.len(), + )?; + verify_count( + "sumcheck batch operands", + &batch.symbol, + batch.count, + batch.claim_operands.len(), + )?; + if batch.ordered_claims != batch.claim_operands { + return Err(EmitError::new(format!( + "sumcheck batch @{} operand order does not match ordered_claims", + batch.symbol + ))); + } + for claim in &batch.ordered_claims { + if !claims.contains(claim) { + return Err(EmitError::new(format!( + "sumcheck batch @{} references missing claim @{claim}", + batch.symbol + ))); + } + } + } + Ok(()) + } + + fn verify_prover_driver_bindings(&self) -> Result<(), EmitError> { + let kernels = symbols(self.kernels.iter().map(|kernel| &kernel.symbol)); + let batches: BTreeMap<_, _> = self + .batches + .iter() + .map(|batch| (batch.symbol.as_str(), batch)) + .collect(); + for claim in &self.claims { + let Some(kernel) = claim.kernel.as_deref() else { + return Err(EmitError::new(format!( + "prover sumcheck claim @{} is missing kernel", + claim.symbol + ))); + }; + if !kernels.contains(kernel) { + return Err(EmitError::new(format!( + "sumcheck claim @{} references missing kernel @{kernel}", + claim.symbol + ))); + } + } + for driver in &self.drivers { + let Some(kernel) = driver.kernel.as_deref() else { + return Err(EmitError::new(format!( + "prover sumcheck driver @{} is missing kernel", + driver.symbol + ))); + }; + if !kernels.contains(kernel) { + return Err(EmitError::new(format!( + "sumcheck driver @{} references missing kernel @{kernel}", + driver.symbol + ))); + } + let batch = batches.get(driver.batch.as_str()).ok_or_else(|| { + EmitError::new(format!( + "sumcheck driver @{} references missing batch @{}", + driver.symbol, driver.batch + )) + })?; + verify_count( + "sumcheck driver round_schedule", + &driver.symbol, + driver.num_rounds, + driver.round_schedule.iter().sum(), + )?; + if driver.round_schedule != batch.round_schedule { + return Err(EmitError::new(format!( + "sumcheck driver @{} round_schedule differs from batch @{}", + driver.symbol, batch.symbol + ))); + } + } + Ok(()) + } + + fn verify_verifier_driver_bindings(&self) -> Result<(), EmitError> { + if !self.kernels.is_empty() { + return Err(EmitError::new( + "verifier stage6 program must not contain kernels", + )); + } + let batches: BTreeMap<_, _> = self + .batches + .iter() + .map(|batch| (batch.symbol.as_str(), batch)) + .collect(); + for claim in &self.claims { + if claim.kernel.is_some() || claim.relation.is_none() { + return Err(EmitError::new(format!( + "verifier sumcheck claim @{} must carry relation and no kernel", + claim.symbol + ))); + } + } + for driver in &self.drivers { + if driver.kernel.is_some() || driver.relation.is_none() { + return Err(EmitError::new(format!( + "verifier sumcheck driver @{} must carry relation and no kernel", + driver.symbol + ))); + } + let batch = batches.get(driver.batch.as_str()).ok_or_else(|| { + EmitError::new(format!( + "sumcheck driver @{} references missing batch @{}", + driver.symbol, driver.batch + )) + })?; + verify_count( + "sumcheck driver round_schedule", + &driver.symbol, + driver.num_rounds, + driver.round_schedule.iter().sum(), + )?; + if driver.round_schedule != batch.round_schedule { + return Err(EmitError::new(format!( + "sumcheck driver @{} round_schedule differs from batch @{}", + driver.symbol, batch.symbol + ))); + } + } + Ok(()) + } + + fn verify_opening_flow(&self) -> Result<(), EmitError> { + let mut point_sources = symbols(self.drivers.iter().map(|driver| &driver.symbol)); + point_sources.extend(symbols( + self.instance_results + .iter() + .map(|instance| &instance.symbol), + )); + point_sources.extend(symbols( + self.opening_inputs.iter().map(|input| &input.symbol), + )); + point_sources.extend(symbols(self.point_zeros.iter().map(|zero| &zero.symbol))); + point_sources.extend(symbols(self.point_slices.iter().map(|slice| &slice.symbol))); + point_sources.extend(symbols( + self.point_concats.iter().map(|concat| &concat.symbol), + )); + for zero in &self.point_zeros { + require_supported_symbol("point zero field", &zero.field, "bn254_fr")?; + } + for slice in &self.point_slices { + if !point_sources.contains(&slice.input) { + return Err(EmitError::new(format!( + "point slice @{} uses missing point source @{}", + slice.symbol, slice.input + ))); + } + } + for concat in &self.point_concats { + for input in &concat.inputs { + if !point_sources.contains(input) { + return Err(EmitError::new(format!( + "point concat @{} uses missing point source @{input}", + concat.symbol + ))); + } + } + } + let eval_sources = self.field_value_symbols(); + let mut opening_sources = symbols(self.opening_inputs.iter().map(|input| &input.symbol)); + opening_sources.extend(symbols( + self.opening_claims.iter().map(|claim| &claim.symbol), + )); + for equality in &self.opening_equalities { + if !opening_sources.contains(&equality.lhs) { + return Err(EmitError::new(format!( + "opening equality @{} uses missing lhs opening @{}", + equality.symbol, equality.lhs + ))); + } + if !opening_sources.contains(&equality.rhs) { + return Err(EmitError::new(format!( + "opening equality @{} uses missing rhs opening @{}", + equality.symbol, equality.rhs + ))); + } + } + for claim in &self.claims { + for input in &claim.input_openings { + if !opening_sources.contains(input) { + return Err(EmitError::new(format!( + "sumcheck claim @{} uses missing opening @{input}", + claim.symbol + ))); + } + } + } + let drivers = symbols(self.drivers.iter().map(|driver| &driver.symbol)); + for instance in &self.instance_results { + if !drivers.contains(&instance.source) { + return Err(EmitError::new(format!( + "sumcheck instance result @{} references missing driver @{}", + instance.symbol, instance.source + ))); + } + } + for eval in &self.evals { + if !drivers.contains(&eval.source) { + return Err(EmitError::new(format!( + "sumcheck eval @{} references missing driver @{}", + eval.symbol, eval.source + ))); + } + } + for claim in &self.opening_claims { + if !point_sources.contains(&claim.point_source) { + return Err(EmitError::new(format!( + "opening claim @{} uses missing point source @{}", + claim.symbol, claim.point_source + ))); + } + if !eval_sources.contains(&claim.eval_source) { + return Err(EmitError::new(format!( + "opening claim @{} uses missing eval source @{}", + claim.symbol, claim.eval_source + ))); + } + } + let openings = symbols(self.opening_claims.iter().map(|claim| &claim.symbol)); + for batch in &self.opening_batches { + verify_count( + "opening batch", + &batch.symbol, + batch.count, + batch.ordered_claims.len(), + )?; + verify_count( + "opening batch operands", + &batch.symbol, + batch.count, + batch.claim_operands.len(), + )?; + if batch.ordered_claims != batch.claim_operands { + return Err(EmitError::new(format!( + "opening batch @{} operand order does not match ordered_claims", + batch.symbol + ))); + } + for claim in &batch.ordered_claims { + if !openings.contains(claim) { + return Err(EmitError::new(format!( + "opening batch @{} references missing opening @{claim}", + batch.symbol + ))); + } + } + } + Ok(()) + } + + fn filename(&self) -> &'static str { + match self.role { + Role::Prover => "prove_stage6.rs", + Role::Verifier => "verify_stage6.rs", + } + } + + fn emit_source(&self) -> String { + let mut source = String::new(); + source.push_str("#![allow(dead_code)]\n\n"); + match self.role { + Role::Prover => { + source.push_str(Self::emit_prover_imports()); + source.push_str("\n\n"); + source.push_str(Self::emit_prover_types()); + } + Role::Verifier => { + source.push_str(Self::emit_verifier_imports()); + source.push_str("\n\n"); + source.push_str(&Self::emit_verifier_types()); + } + } + source.push('\n'); + source.push_str(&self.emit_constants()); + source.push('\n'); + source.push_str(self.emit_entrypoint()); + source + } + + fn emit_prover_imports() -> &'static str { + "use jolt_field::Fr;\n\ + use jolt_kernels::stage6::{execute_stage6_program, Stage6CpuProgramPlan, Stage6ExecutionArtifacts, Stage6ExecutionMode, Stage6FieldConstantPlan, Stage6FieldExprPlan, Stage6KernelError, Stage6KernelExecutor, Stage6KernelPlan, Stage6OpeningBatchPlan, Stage6OpeningClaimEqualityPlan, Stage6OpeningClaimPlan, Stage6OpeningInputPlan, Stage6Params, Stage6PointConcatPlan, Stage6PointSlicePlan, Stage6PointZeroPlan, Stage6ProgramStepPlan, Stage6SumcheckBatchPlan, Stage6SumcheckClaimPlan, Stage6SumcheckDriverPlan, Stage6SumcheckEvalPlan, Stage6SumcheckInstanceResultPlan, Stage6TranscriptAbsorbBytesPlan, Stage6TranscriptSqueezePlan};\n\ + use jolt_transcript::{Blake2bTranscript, Transcript};" + } + + fn emit_prover_types() -> &'static str { + "pub type DefaultStage6Transcript = Blake2bTranscript;\n" + } + + fn emit_verifier_imports() -> &'static str { + "use super::common::{batch_claims, expected_stage67_booleanity, expected_stage67_bytecode_read_raf, expected_stage67_hamming_booleanity, expected_stage67_inc_claim_reduction, expected_stage67_instruction_ra_virtual, expected_stage67_ram_ra_virtual, find_batch, find_plan, normalize_bytecode_read_raf_point, normalize_instruction_read_raf_point, stage67_trace_rounds, Stage67BytecodeEntry, Stage67BytecodeSymbols, Stage67RelationSymbols};\n\ + use jolt_field::{Field, Fr};\n\ + use jolt_sumcheck::SumcheckError;\n\ + use jolt_transcript::{Blake2bTranscript, LabelWithCount, Transcript};" + } + + #[expect(dead_code)] + fn emit_types() -> &'static str { + r#"#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage6Params { + pub field: &'static str, + pub pcs: &'static str, + pub transcript: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage6KernelPlan { + pub symbol: &'static str, + pub relation: &'static str, + pub kind: &'static str, + pub backend: &'static str, + pub abi: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage6TranscriptSqueezePlan { + pub symbol: &'static str, + pub label: &'static str, + pub kind: &'static str, + pub count: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage6TranscriptAbsorbBytesPlan { + pub symbol: &'static str, + pub label: &'static str, + pub payload: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage6ProgramStepPlan { + pub kind: &'static str, + pub symbol: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage6OpeningInputPlan { + pub symbol: &'static str, + pub source_stage: &'static str, + pub source_claim: &'static str, + pub oracle: &'static str, + pub domain: &'static str, + pub point_arity: usize, + pub claim_kind: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage6FieldConstantPlan { + pub symbol: &'static str, + pub field: &'static str, + pub value: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage6FieldExprPlan { + pub symbol: &'static str, + pub kind: &'static str, + pub formula: &'static str, + pub operand_names: &'static [&'static str], + pub operands: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage6SumcheckClaimPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub domain: &'static str, + pub num_rounds: usize, + pub degree: usize, + pub claim: &'static str, + pub kernel: Option<&'static str>, + pub relation: Option<&'static str>, + pub claim_value: &'static str, + pub input_openings: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage6SumcheckBatchPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub proof_slot: &'static str, + pub policy: &'static str, + pub count: usize, + pub ordered_claims: &'static [&'static str], + pub claim_operands: &'static [&'static str], + pub claim_label: &'static str, + pub round_label: &'static str, + pub round_schedule: &'static [usize], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage6SumcheckDriverPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub proof_slot: &'static str, + pub kernel: Option<&'static str>, + pub relation: Option<&'static str>, + pub batch: &'static str, + pub policy: &'static str, + pub round_schedule: &'static [usize], + pub claim_label: &'static str, + pub round_label: &'static str, + pub num_rounds: usize, + pub degree: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage6SumcheckInstanceResultPlan { + pub symbol: &'static str, + pub source: &'static str, + pub claim: &'static str, + pub relation: &'static str, + pub index: usize, + pub point_arity: usize, + pub num_rounds: usize, + pub round_offset: usize, + pub point_order: &'static str, + pub degree: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage6SumcheckEvalPlan { + pub symbol: &'static str, + pub source: &'static str, + pub name: &'static str, + pub index: usize, + pub oracle: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage6PointZeroPlan { + pub symbol: &'static str, + pub field: &'static str, + pub arity: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage6PointSlicePlan { + pub symbol: &'static str, + pub source: &'static str, + pub offset: usize, + pub length: usize, + pub input: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage6PointConcatPlan { + pub symbol: &'static str, + pub layout: &'static str, + pub arity: usize, + pub inputs: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage6OpeningClaimPlan { + pub symbol: &'static str, + pub oracle: &'static str, + pub domain: &'static str, + pub point_arity: usize, + pub claim_kind: &'static str, + pub point_source: &'static str, + pub eval_source: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage6OpeningClaimEqualityPlan { + pub symbol: &'static str, + pub mode: &'static str, + pub lhs: &'static str, + pub rhs: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage6OpeningBatchPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub proof_slot: &'static str, + pub policy: &'static str, + pub count: usize, + pub ordered_claims: &'static [&'static str], + pub claim_operands: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage6CpuProgramPlan { + pub role: &'static str, + pub params: Stage6Params, + pub steps: &'static [Stage6ProgramStepPlan], + pub transcript_squeezes: &'static [Stage6TranscriptSqueezePlan], + pub transcript_absorb_bytes: &'static [Stage6TranscriptAbsorbBytesPlan], + pub opening_inputs: &'static [Stage6OpeningInputPlan], + pub field_constants: &'static [Stage6FieldConstantPlan], + pub field_exprs: &'static [Stage6FieldExprPlan], + pub kernels: &'static [Stage6KernelPlan], + pub claims: &'static [Stage6SumcheckClaimPlan], + pub batches: &'static [Stage6SumcheckBatchPlan], + pub drivers: &'static [Stage6SumcheckDriverPlan], + pub instance_results: &'static [Stage6SumcheckInstanceResultPlan], + pub evals: &'static [Stage6SumcheckEvalPlan], + pub point_zeros: &'static [Stage6PointZeroPlan], + pub point_slices: &'static [Stage6PointSlicePlan], + pub point_concats: &'static [Stage6PointConcatPlan], + pub opening_claims: &'static [Stage6OpeningClaimPlan], + pub opening_equalities: &'static [Stage6OpeningClaimEqualityPlan], + pub opening_batches: &'static [Stage6OpeningBatchPlan], +} +"# + } + + fn emit_verifier_type_aliases() -> &'static str { + r#"pub type Stage6NamedEval = super::common::StageNamedEval; +pub type Stage6SumcheckOutput = super::common::StageSumcheckOutput; +pub type Stage6ChallengeVector = super::common::StageChallengeVector; +pub type Stage6ExecutionArtifacts = super::common::StageExecutionArtifacts; +pub type Stage6Proof = super::common::StageProof; +pub type Stage6OpeningInputValue = super::common::StageOpeningInputValue; + +pub use super::common::{ + FieldConstantPlan as Stage6FieldConstantPlan, FieldExprPlan as Stage6FieldExprPlan, + KernelPlan as Stage6KernelPlan, OpeningBatchPlan as Stage6OpeningBatchPlan, + OpeningClaimEqualityPlan as Stage6OpeningClaimEqualityPlan, + OpeningClaimPlan as Stage6OpeningClaimPlan, OpeningInputPlan as Stage6OpeningInputPlan, + PointConcatPlan as Stage6PointConcatPlan, PointSlicePlan as Stage6PointSlicePlan, + PointZeroPlan as Stage6PointZeroPlan, ProgramStepPlan as Stage6ProgramStepPlan, + StageParams as Stage6Params, StageProgramPlan as Stage6CpuProgramPlan, + SumcheckBatchPlan as Stage6SumcheckBatchPlan, + SumcheckClaimPlan as Stage6SumcheckClaimPlan, SumcheckDriverPlan as Stage6SumcheckDriverPlan, + SumcheckEvalPlan as Stage6SumcheckEvalPlan, + SumcheckInstanceResultPlan as Stage6SumcheckInstanceResultPlan, + TranscriptAbsorbBytesPlan as Stage6TranscriptAbsorbBytesPlan, + TranscriptSqueezePlan as Stage6TranscriptSqueezePlan, +}; +"# + } + + fn emit_verifier_types() -> String { + let mut source = Self::emit_verifier_type_aliases().to_owned(); + source.push_str( + r#" +pub type DefaultStage6Transcript = Blake2bTranscript; +pub type Stage6VerifierProgramPlan = Stage6CpuProgramPlan; + +#[derive(Clone, Debug)] +pub struct Stage6BytecodeEntry { + pub address: Fr, + pub imm: Fr, + pub circuit_flags: [bool; 14], + pub rd: Option, + pub rs1: Option, + pub rs2: Option, + pub lookup_table: Option, + pub is_interleaved: bool, + pub is_branch: bool, + pub left_is_rs1: bool, + pub left_is_pc: bool, + pub right_is_rs2: bool, + pub right_is_imm: bool, + pub is_noop: bool, +} + +impl Stage67BytecodeEntry for Stage6BytecodeEntry { + fn address(&self) -> Fr { self.address } + fn imm(&self) -> Fr { self.imm } + fn circuit_flags(&self) -> &[bool; 14] { &self.circuit_flags } + fn rd(&self) -> Option { self.rd } + fn rs1(&self) -> Option { self.rs1 } + fn rs2(&self) -> Option { self.rs2 } + fn lookup_table(&self) -> Option { self.lookup_table } + fn is_interleaved(&self) -> bool { self.is_interleaved } + fn is_branch(&self) -> bool { self.is_branch } + fn left_is_rs1(&self) -> bool { self.left_is_rs1 } + fn left_is_pc(&self) -> bool { self.left_is_pc } + fn right_is_rs2(&self) -> bool { self.right_is_rs2 } + fn right_is_imm(&self) -> bool { self.right_is_imm } + fn is_noop(&self) -> bool { self.is_noop } +} + + +#[derive(Clone, Debug)] +pub struct Stage6BytecodeReadRafData { + pub entries: Vec, + pub entry_bytecode_index: usize, + pub num_lookup_tables: usize, +} + +#[derive(Clone, Debug)] +pub struct Stage6VerifierData { + pub bytecode_read_raf: Option, +} + +const STAGE6_RELATION_SYMBOLS: Stage67RelationSymbols = Stage67RelationSymbols { + hamming_booleanity_relation: "jolt.stage6.hamming_booleanity", + hamming_booleanity_instance: "stage6.hamming_booleanity.instance", + booleanity_point: "stage6.booleanity.point", + stage5_instruction_ra0: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", + booleanity_combined_point: "stage6.booleanity.combined_point", + booleanity_gamma: "stage6.booleanity.gamma", + booleanity_instruction_ra_prefix: "stage6.booleanity.eval.InstructionRa_", + booleanity_bytecode_ra_prefix: "stage6.booleanity.eval.BytecodeRa_", + booleanity_ram_ra_prefix: "stage6.booleanity.eval.RamRa_", + hamming_weight_eval: "stage6.hamming_booleanity.eval.HammingWeight", + hamming_lookup_output: "stage6.input.stage1.LookupOutput", + ram_ra_virtual_cycle: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", + ram_ra_virtual_eval_prefix: "stage6.ram_ra_virtual.eval.RamRa_", + instruction_ra_virtual_cycle: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", + instruction_ra_virtual_eval_prefix: "stage6.instruction_ra_virtual.eval.InstructionRa_", + instruction_ra_virtual_input_prefix: "stage6.input.stage5.instruction_read_raf.InstructionRa_", + instruction_ra_virtual_gamma: "stage6.instruction_ra_virtual.gamma", + inc_ram_stage2: "stage6.input.stage2.ram_read_write.RamInc", + inc_ram_stage4: "stage6.input.stage4.ram_val_check.RamInc", + inc_rd_stage4: "stage6.input.stage4.registers_read_write.RdInc", + inc_rd_stage5: "stage6.input.stage5.registers_val_evaluation.RdInc", + inc_gamma: "stage6.inc_claim_reduction.gamma", + inc_ram_eval: "stage6.inc_claim_reduction.eval.RamInc", + inc_rd_eval: "stage6.inc_claim_reduction.eval.RdInc", +}; + +const STAGE6_BYTECODE_SYMBOLS: Stage67BytecodeSymbols = Stage67BytecodeSymbols { + point: "stage6.bytecode_read_raf.point", + gamma: "stage6.bytecode_read_raf.gamma", + bytecode_ra_eval_prefix: "stage6.bytecode_read_raf.eval.BytecodeRa_", + entries: "stage6.bytecode_read_raf.entries", + entry_bytecode_index: "stage6.bytecode_read_raf.entry_bytecode_index", + stage_gammas: [ + "stage6.bytecode_read_raf.stage1_gamma", + "stage6.bytecode_read_raf.stage2_gamma", + "stage6.bytecode_read_raf.stage3_gamma", + "stage6.bytecode_read_raf.stage4_gamma", + "stage6.bytecode_read_raf.stage5_gamma", + ], + stage_cycle_points: [ + "stage6.input.stage1.Imm", + "stage6.input.stage2.OpFlagJump", + "stage6.input.stage3.spartan_shift.UnexpandedPC", + "stage6.input.stage4.Rs1Ra", + "stage6.input.stage5.registers_val_evaluation.RdWa", + ], + stage4_register_point: "stage6.input.stage4.Rs1Ra", + stage5_register_point: "stage6.input.stage5.registers_val_evaluation.RdWa", + entry_rd: "stage6.bytecode.entry.rd", + entry_rs1: "stage6.bytecode.entry.rs1", + entry_rs2: "stage6.bytecode.entry.rs2", + entry_lookup_table: "stage6.bytecode.entry.lookup_table", +}; + +#[derive(Debug)] +pub enum VerifyStage6Error { + UnexpectedProofCount { expected: usize, got: usize }, + MissingProof { driver: &'static str }, + MissingBatch { driver: &'static str, batch: &'static str }, + MissingClaim { batch: &'static str, claim: &'static str }, + MissingValue { symbol: &'static str }, + InvalidInputLength { input: &'static str, expected: usize, actual: usize }, + InvalidProof { driver: &'static str, reason: &'static str }, + UnsupportedFieldExpr { symbol: &'static str, formula: &'static str }, + UnsupportedRelation { relation: &'static str }, + Sumcheck { driver: &'static str, error: SumcheckError }, +} + +super::common::impl_runtime_plan_error_conversion!(VerifyStage6Error); +"#, + ); + source + } + + fn emit_constants(&self) -> String { + let mut source = self.emit_shared_constants(); + source.push_str(&self.emit_kernel_constants()); + source.push_str(&self.emit_sumcheck_claim_constants()); + source.push_str(&self.emit_sumcheck_batch_constants()); + source.push_str(&self.emit_sumcheck_driver_constants()); + source.push_str(&self.emit_tail_constants()); + push_format( + &mut source, + format_args!( + "pub const STAGE6_PROGRAM: {} = Stage6CpuProgramPlan {{\n\ + \x20 role: {},\n\ + \x20 params: STAGE6_PARAMS,\n\ + \x20 steps: STAGE6_PROGRAM_STEPS,\n\ + \x20 transcript_squeezes: STAGE6_TRANSCRIPT_SQUEEZES,\n\ + \x20 transcript_absorb_bytes: STAGE6_TRANSCRIPT_ABSORB_BYTES,\n\ + \x20 opening_inputs: STAGE6_OPENING_INPUTS,\n\ + \x20 field_constants: STAGE6_FIELD_CONSTANTS,\n\ + \x20 field_exprs: STAGE6_FIELD_EXPRS,\n\ + \x20 kernels: STAGE6_KERNELS,\n\ + \x20 claims: STAGE6_SUMCHECK_CLAIMS,\n\ + \x20 batches: STAGE6_SUMCHECK_BATCHES,\n\ + \x20 drivers: STAGE6_SUMCHECK_DRIVERS,\n\ + \x20 instance_results: STAGE6_SUMCHECK_INSTANCE_RESULTS,\n\ + \x20 evals: STAGE6_SUMCHECK_EVALS,\n\ + \x20 point_zeros: STAGE6_POINT_ZEROS,\n\ + \x20 point_slices: STAGE6_POINT_SLICES,\n\ + \x20 point_concats: STAGE6_POINT_CONCATS,\n\ + \x20 opening_claims: STAGE6_OPENING_CLAIMS,\n\ + \x20 opening_equalities: STAGE6_OPENING_EQUALITIES,\n\ + \x20 opening_batches: STAGE6_OPENING_BATCHES,\n\ + }};\n", + self.program_plan_type(), + rust_str(self.role_label()) + ), + ); + source + } + + fn emit_shared_constants(&self) -> String { + let mut source = String::new(); + push_format( + &mut source, + format_args!( + "pub const STAGE6_PARAMS: Stage6Params = Stage6Params {{\n\ + \x20 field: {},\n\ + \x20 pcs: {},\n\ + \x20 transcript: {},\n\ + }};\n", + rust_str(&self.params.field), + rust_str(&self.params.pcs), + rust_str(&self.params.transcript) + ), + ); + source.push_str(&self.emit_program_step_constants()); + source.push_str(&self.emit_transcript_squeeze_constants()); + source.push_str(&self.emit_transcript_absorb_bytes_constants()); + source.push_str(&self.emit_opening_input_constants()); + source.push_str(&self.emit_field_constant_constants()); + source.push_str(&self.emit_field_expr_constants()); + source + } + + fn emit_program_step_constants(&self) -> String { + let steps = self + .steps + .iter() + .map(|step| { + format!( + " Stage6ProgramStepPlan {{ kind: {}, symbol: {} }},", + rust_str(&step.kind), + rust_str(&step.symbol), + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE6_PROGRAM_STEPS: &[Stage6ProgramStepPlan] = &[\n{steps}\n];\n\n") + } + + fn emit_transcript_squeeze_constants(&self) -> String { + let squeezes = self + .transcript_squeezes + .iter() + .map(|squeeze| { + format!( + " Stage6TranscriptSqueezePlan {{ symbol: {}, label: {}, kind: {}, count: {} }},", + rust_str(&squeeze.symbol), + rust_str(&squeeze.label), + rust_str(&squeeze.kind), + squeeze.count, + ) + }) + .collect::>() + .join("\n"); + format!( + "pub const STAGE6_TRANSCRIPT_SQUEEZES: &[Stage6TranscriptSqueezePlan] = &[\n{squeezes}\n];\n\n" + ) + } + + fn emit_transcript_absorb_bytes_constants(&self) -> String { + let absorbs = self + .transcript_absorb_bytes + .iter() + .map(|absorb| { + format!( + " Stage6TranscriptAbsorbBytesPlan {{ symbol: {}, label: {}, payload: {} }},", + rust_str(&absorb.symbol), + rust_str(&absorb.label), + rust_str(&absorb.payload), + ) + }) + .collect::>() + .join("\n"); + format!( + "pub const STAGE6_TRANSCRIPT_ABSORB_BYTES: &[Stage6TranscriptAbsorbBytesPlan] = &[\n{absorbs}\n];\n\n" + ) + } + + fn emit_opening_input_constants(&self) -> String { + let inputs = self + .opening_inputs + .iter() + .map(|input| { + format!( + " Stage6OpeningInputPlan {{ symbol: {}, source_stage: {}, source_claim: {}, oracle: {}, domain: {}, point_arity: {}, claim_kind: {} }},", + rust_str(&input.symbol), + rust_str(&input.source_stage), + rust_str(&input.source_claim), + rust_str(&input.oracle), + rust_str(&input.domain), + input.point_arity, + rust_str(&input.claim_kind) + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE6_OPENING_INPUTS: &[Stage6OpeningInputPlan] = &[\n{inputs}\n];\n\n") + } + + fn emit_field_constant_constants(&self) -> String { + let constants = self + .field_constants + .iter() + .map(|constant| { + format!( + " Stage6FieldConstantPlan {{ symbol: {}, field: {}, value: {} }},", + rust_str(&constant.symbol), + rust_str(&constant.field), + constant.value + ) + }) + .collect::>() + .join("\n"); + format!( + "pub const STAGE6_FIELD_CONSTANTS: &[Stage6FieldConstantPlan] = &[\n{constants}\n];\n\n" + ) + } + + fn emit_field_expr_constants(&self) -> String { + if self.role == Role::Verifier { + let rows = self + .field_exprs + .chunks(8) + .map(|chunk| { + let exprs = chunk + .iter() + .map(|expr| { + format!( + "stage6_field_expr!({}, {}, {})", + rust_str(&expr.symbol), + rust_str(&expr.formula), + rust_str(&expr.operands.join("|")) + ) + }) + .collect::>() + .join(", "); + format!(" {exprs},") + }) + .collect::>() + .join("\n"); + return format!( + "macro_rules! stage6_field_expr {{\n ($symbol:literal, $formula:literal, $operands:literal) => {{\n Stage6FieldExprPlan {{ symbol: $symbol, kind: \"op\", formula: $formula, operands: $operands }}\n }};\n}}\n\n#[rustfmt::skip]\npub const STAGE6_FIELD_EXPRS: &[Stage6FieldExprPlan] = &[\n{rows}\n];\n" + ); + } + + let mut source = String::new(); + let mut arrays = Vec::new(); + let mut array_refs = Vec::new(); + for (index, expr) in self.field_exprs.iter().enumerate() { + let operands = intern_str_array( + &mut source, + &mut arrays, + "STAGE6_FIELD_EXPR_OPERANDS", + &expr.operands, + ); + let operand_names = intern_str_array( + &mut source, + &mut arrays, + "STAGE6_FIELD_EXPR_OPERANDS", + &expr.operand_names, + ); + array_refs.push((index, operand_names, operands)); + } + let exprs = self + .field_exprs + .iter() + .enumerate() + .map(|(index, expr)| { + let (_, operand_names, operands) = &array_refs[index]; + format!( + " Stage6FieldExprPlan {{ symbol: {}, kind: {}, formula: {}, operand_names: {operand_names}, operands: {operands} }},", + rust_str(&expr.symbol), + rust_str(&expr.kind), + rust_str(&expr.formula) + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE6_FIELD_EXPRS: &[Stage6FieldExprPlan] = &[\n{exprs}\n];\n" + ), + ); + source + } + + fn emit_kernel_constants(&self) -> String { + let kernels = self + .kernels + .iter() + .map(|kernel| { + format!( + " Stage6KernelPlan {{ symbol: {}, relation: {}, kind: {}, backend: {}, abi: {} }},", + rust_str(&kernel.symbol), + rust_str(&kernel.relation), + rust_str(&kernel.kind), + rust_str(&kernel.backend), + rust_str(&kernel.abi) + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE6_KERNELS: &[Stage6KernelPlan] = &[\n{kernels}\n];\n\n") + } + + fn emit_sumcheck_claim_constants(&self) -> String { + if self.role == Role::Verifier { + let claims = self + .claims + .iter() + .map(|claim| { + format!( + " Stage6SumcheckClaimPlan {{ symbol: {}, stage: {}, domain: {}, num_rounds: {}, degree: {}, claim: {}, kernel: {}, relation: {}, claim_value: {}, input_openings: {} }},", + rust_str(&claim.symbol), + rust_str(&claim.stage), + rust_str(&claim.domain), + claim.num_rounds, + claim.degree, + rust_str(&claim.claim), + rust_option_str(claim.kernel.as_deref()), + rust_option_str(claim.relation.as_deref()), + rust_str(&claim.claim_value), + rust_str(&claim.input_openings.join("|")) + ) + }) + .collect::>() + .join("\n"); + return format!( + "pub const STAGE6_SUMCHECK_CLAIMS: &[Stage6SumcheckClaimPlan] = &[\n{claims}\n];\n" + ); + } + + let mut source = String::new(); + for (index, claim) in self.claims.iter().enumerate() { + source.push_str(&emit_str_array( + &format!("STAGE6_SUMCHECK_CLAIM_{index}_INPUT_OPENINGS"), + &claim.input_openings, + )); + } + let claims = self + .claims + .iter() + .enumerate() + .map(|(index, claim)| { + format!( + " Stage6SumcheckClaimPlan {{ symbol: {}, stage: {}, domain: {}, num_rounds: {}, degree: {}, claim: {}, kernel: {}, relation: {}, claim_value: {}, input_openings: STAGE6_SUMCHECK_CLAIM_{index}_INPUT_OPENINGS }},", + rust_str(&claim.symbol), + rust_str(&claim.stage), + rust_str(&claim.domain), + claim.num_rounds, + claim.degree, + rust_str(&claim.claim), + rust_option_str(claim.kernel.as_deref()), + rust_option_str(claim.relation.as_deref()), + rust_str(&claim.claim_value) + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE6_SUMCHECK_CLAIMS: &[Stage6SumcheckClaimPlan] = &[\n{claims}\n];\n" + ), + ); + source + } + + fn emit_sumcheck_batch_constants(&self) -> String { + if self.role == Role::Verifier { + let mut source = String::new(); + for (index, batch) in self.batches.iter().enumerate() { + source.push_str(&emit_usize_array( + &format!("STAGE6_SUMCHECK_BATCH_{index}_ROUND_SCHEDULE"), + &batch.round_schedule, + )); + } + let batches = self + .batches + .iter() + .enumerate() + .map(|(index, batch)| { + format!( + " Stage6SumcheckBatchPlan {{ symbol: {}, stage: {}, proof_slot: {}, policy: {}, count: {}, ordered_claims: {}, claim_operands: {}, claim_label: {}, round_label: {}, round_schedule: STAGE6_SUMCHECK_BATCH_{index}_ROUND_SCHEDULE }},", + rust_str(&batch.symbol), + rust_str(&batch.stage), + rust_str(&batch.proof_slot), + rust_str(&batch.policy), + batch.count, + rust_str(&batch.ordered_claims.join("|")), + rust_str(&batch.claim_operands.join("|")), + rust_str(&batch.claim_label), + rust_str(&batch.round_label) + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE6_SUMCHECK_BATCHES: &[Stage6SumcheckBatchPlan] = &[\n{batches}\n];\n" + ), + ); + return source; + } + + let mut source = String::new(); + for (index, batch) in self.batches.iter().enumerate() { + source.push_str(&emit_str_array( + &format!("STAGE6_SUMCHECK_BATCH_{index}_ORDERED_CLAIMS"), + &batch.ordered_claims, + )); + source.push_str(&emit_str_array( + &format!("STAGE6_SUMCHECK_BATCH_{index}_CLAIM_OPERANDS"), + &batch.claim_operands, + )); + source.push_str(&emit_usize_array( + &format!("STAGE6_SUMCHECK_BATCH_{index}_ROUND_SCHEDULE"), + &batch.round_schedule, + )); + } + let batches = self + .batches + .iter() + .enumerate() + .map(|(index, batch)| { + format!( + " Stage6SumcheckBatchPlan {{ symbol: {}, stage: {}, proof_slot: {}, policy: {}, count: {}, ordered_claims: STAGE6_SUMCHECK_BATCH_{index}_ORDERED_CLAIMS, claim_operands: STAGE6_SUMCHECK_BATCH_{index}_CLAIM_OPERANDS, claim_label: {}, round_label: {}, round_schedule: STAGE6_SUMCHECK_BATCH_{index}_ROUND_SCHEDULE }},", + rust_str(&batch.symbol), + rust_str(&batch.stage), + rust_str(&batch.proof_slot), + rust_str(&batch.policy), + batch.count, + rust_str(&batch.claim_label), + rust_str(&batch.round_label) + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE6_SUMCHECK_BATCHES: &[Stage6SumcheckBatchPlan] = &[\n{batches}\n];\n" + ), + ); + source + } + + fn emit_sumcheck_driver_constants(&self) -> String { + let mut source = String::new(); + for (index, driver) in self.drivers.iter().enumerate() { + source.push_str(&emit_usize_array( + &format!("STAGE6_SUMCHECK_DRIVER_{index}_ROUND_SCHEDULE"), + &driver.round_schedule, + )); + } + let drivers = self + .drivers + .iter() + .enumerate() + .map(|(index, driver)| { + format!( + " Stage6SumcheckDriverPlan {{ symbol: {}, stage: {}, proof_slot: {}, kernel: {}, relation: {}, batch: {}, policy: {}, round_schedule: STAGE6_SUMCHECK_DRIVER_{index}_ROUND_SCHEDULE, claim_label: {}, round_label: {}, num_rounds: {}, degree: {} }},", + rust_str(&driver.symbol), + rust_str(&driver.stage), + rust_str(&driver.proof_slot), + rust_option_str(driver.kernel.as_deref()), + rust_option_str(driver.relation.as_deref()), + rust_str(&driver.batch), + rust_str(&driver.policy), + rust_str(&driver.claim_label), + rust_str(&driver.round_label), + driver.num_rounds, + driver.degree + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE6_SUMCHECK_DRIVERS: &[Stage6SumcheckDriverPlan] = &[\n{drivers}\n];\n" + ), + ); + source + } + + fn emit_tail_constants(&self) -> String { + let mut source = String::new(); + source.push_str(&self.emit_sumcheck_instance_result_constants()); + source.push_str(&self.emit_sumcheck_eval_constants()); + source.push_str(&self.emit_point_zero_constants()); + source.push_str(&self.emit_point_slice_constants()); + source.push_str(&self.emit_point_concat_constants()); + source.push_str(&self.emit_opening_claim_constants()); + source.push_str(&self.emit_opening_claim_equality_constants()); + source.push_str(&self.emit_opening_batch_constants()); + source + } + + fn emit_sumcheck_instance_result_constants(&self) -> String { + let instances = self + .instance_results + .iter() + .map(|instance| { + format!( + " Stage6SumcheckInstanceResultPlan {{ symbol: {}, source: {}, claim: {}, relation: {}, index: {}, point_arity: {}, num_rounds: {}, round_offset: {}, point_order: {}, degree: {} }},", + rust_str(&instance.symbol), + rust_str(&instance.source), + rust_str(&instance.claim), + rust_str(&instance.relation), + instance.index, + instance.point_arity, + instance.num_rounds, + instance.round_offset, + rust_str(&instance.point_order), + instance.degree + ) + }) + .collect::>() + .join("\n"); + format!( + "pub const STAGE6_SUMCHECK_INSTANCE_RESULTS: &[Stage6SumcheckInstanceResultPlan] = &[\n{instances}\n];\n\n" + ) + } + + fn emit_sumcheck_eval_constants(&self) -> String { + let rows = self + .evals + .chunks(4) + .map(|chunk| { + let evals = chunk + .iter() + .map(|eval| { + format!( + "stage6_sumcheck_eval!({}, {}, {}, {}, {})", + rust_str(&eval.symbol), + rust_str(&eval.source), + rust_str(&eval.name), + eval.index, + rust_str(&eval.oracle) + ) + }) + .collect::>() + .join(", "); + format!(" {evals},") + }) + .collect::>() + .join("\n"); + format!( + "macro_rules! stage6_sumcheck_eval {{\n ($symbol:literal, $source:literal, $name:literal, $index:literal, $oracle:literal) => {{\n Stage6SumcheckEvalPlan {{ symbol: $symbol, source: $source, name: $name, index: $index, oracle: $oracle }}\n }};\n}}\n\n#[rustfmt::skip]\npub const STAGE6_SUMCHECK_EVALS: &[Stage6SumcheckEvalPlan] = &[\n{rows}\n];\n\n" + ) + } + + fn emit_point_zero_constants(&self) -> String { + let zeros = self + .point_zeros + .iter() + .map(|zero| { + format!( + " Stage6PointZeroPlan {{ symbol: {}, field: {}, arity: {} }},", + rust_str(&zero.symbol), + rust_str(&zero.field), + zero.arity + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE6_POINT_ZEROS: &[Stage6PointZeroPlan] = &[\n{zeros}\n];\n\n") + } + + fn emit_point_slice_constants(&self) -> String { + let slices = self + .point_slices + .iter() + .map(|slice| { + format!( + " Stage6PointSlicePlan {{ symbol: {}, source: {}, offset: {}, length: {}, input: {} }},", + rust_str(&slice.symbol), + rust_str(&slice.source), + slice.offset, + slice.length, + rust_str(&slice.input) + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE6_POINT_SLICES: &[Stage6PointSlicePlan] = &[\n{slices}\n];\n\n") + } + + fn emit_point_concat_constants(&self) -> String { + if self.role == Role::Verifier { + let concats = self + .point_concats + .iter() + .map(|concat| { + format!( + " Stage6PointConcatPlan {{ symbol: {}, layout: {}, arity: {}, inputs: {} }},", + rust_str(&concat.symbol), + rust_str(&concat.layout), + concat.arity, + rust_str(&concat.inputs.join("|")) + ) + }) + .collect::>() + .join("\n"); + return format!( + "pub const STAGE6_POINT_CONCATS: &[Stage6PointConcatPlan] = &[\n{concats}\n];\n" + ); + } + + let mut source = String::new(); + for (index, concat) in self.point_concats.iter().enumerate() { + source.push_str(&emit_str_array( + &format!("STAGE6_POINT_CONCAT_{index}_INPUTS"), + &concat.inputs, + )); + } + let concats = self + .point_concats + .iter() + .enumerate() + .map(|(index, concat)| { + format!( + " Stage6PointConcatPlan {{ symbol: {}, layout: {}, arity: {}, inputs: STAGE6_POINT_CONCAT_{index}_INPUTS }},", + rust_str(&concat.symbol), + rust_str(&concat.layout), + concat.arity + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE6_POINT_CONCATS: &[Stage6PointConcatPlan] = &[\n{concats}\n];\n" + ), + ); + source + } + + fn emit_opening_claim_constants(&self) -> String { + let claims = self + .opening_claims + .iter() + .map(|claim| { + format!( + " Stage6OpeningClaimPlan {{ symbol: {}, oracle: {}, domain: {}, point_arity: {}, claim_kind: {}, point_source: {}, eval_source: {} }},", + rust_str(&claim.symbol), + rust_str(&claim.oracle), + rust_str(&claim.domain), + claim.point_arity, + rust_str(&claim.claim_kind), + rust_str(&claim.point_source), + rust_str(&claim.eval_source) + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE6_OPENING_CLAIMS: &[Stage6OpeningClaimPlan] = &[\n{claims}\n];\n\n") + } + + fn emit_opening_claim_equality_constants(&self) -> String { + let equalities = self + .opening_equalities + .iter() + .map(|equality| { + format!( + " Stage6OpeningClaimEqualityPlan {{ symbol: {}, mode: {}, lhs: {}, rhs: {} }},", + rust_str(&equality.symbol), + rust_str(&equality.mode), + rust_str(&equality.lhs), + rust_str(&equality.rhs) + ) + }) + .collect::>() + .join("\n"); + format!( + "pub const STAGE6_OPENING_EQUALITIES: &[Stage6OpeningClaimEqualityPlan] = &[\n{equalities}\n];\n\n" + ) + } + + fn emit_opening_batch_constants(&self) -> String { + if self.role == Role::Verifier { + let batches = self + .opening_batches + .iter() + .map(|batch| { + format!( + " Stage6OpeningBatchPlan {{ symbol: {}, stage: {}, proof_slot: {}, policy: {}, count: {}, ordered_claims: {}, claim_operands: {} }},", + rust_str(&batch.symbol), + rust_str(&batch.stage), + rust_str(&batch.proof_slot), + rust_str(&batch.policy), + batch.count, + rust_str(&batch.ordered_claims.join("|")), + rust_str(&batch.claim_operands.join("|")) + ) + }) + .collect::>() + .join("\n"); + return format!( + "pub const STAGE6_OPENING_BATCHES: &[Stage6OpeningBatchPlan] = &[\n{batches}\n];\n" + ); + } + + let mut source = String::new(); + for (index, batch) in self.opening_batches.iter().enumerate() { + source.push_str(&emit_str_array( + &format!("STAGE6_OPENING_BATCH_{index}_ORDERED_CLAIMS"), + &batch.ordered_claims, + )); + source.push_str(&emit_str_array( + &format!("STAGE6_OPENING_BATCH_{index}_CLAIM_OPERANDS"), + &batch.claim_operands, + )); + } + let batches = self + .opening_batches + .iter() + .enumerate() + .map(|(index, batch)| { + format!( + " Stage6OpeningBatchPlan {{ symbol: {}, stage: {}, proof_slot: {}, policy: {}, count: {}, ordered_claims: STAGE6_OPENING_BATCH_{index}_ORDERED_CLAIMS, claim_operands: STAGE6_OPENING_BATCH_{index}_CLAIM_OPERANDS }},", + rust_str(&batch.symbol), + rust_str(&batch.stage), + rust_str(&batch.proof_slot), + rust_str(&batch.policy), + batch.count + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE6_OPENING_BATCHES: &[Stage6OpeningBatchPlan] = &[\n{batches}\n];\n" + ), + ); + source + } + + fn emit_entrypoint(&self) -> &'static str { + match self.role { + Role::Prover => { + "pub fn execute_stage6_prover(\n\ + \x20 executor: &mut E,\n\ + \x20 transcript: &mut T,\n\ + ) -> Result, Stage6KernelError>\n\ + where\n\ + \x20 E: Stage6KernelExecutor,\n\ + \x20 T: Transcript,\n\ + {\n\ + \x20 execute_stage6_prover_with_program(&STAGE6_PROGRAM, executor, transcript)\n\ + }\n\ + \n\ + pub fn execute_stage6_prover_with_program(\n\ + \x20 program: &'static Stage6CpuProgramPlan,\n\ + \x20 executor: &mut E,\n\ + \x20 transcript: &mut T,\n\ + ) -> Result, Stage6KernelError>\n\ + where\n\ + \x20 E: Stage6KernelExecutor,\n\ + \x20 T: Transcript,\n\ + {\n\ + \x20 execute_stage6_program(program, Stage6ExecutionMode::Prover, executor, transcript)\n\ + }\n" + } + Role::Verifier => { + r#"pub fn verify_stage6( + proof: &Stage6Proof, + opening_inputs: &[Stage6OpeningInputValue], + verifier_data: Option<&Stage6VerifierData>, + transcript: &mut T, +) -> Result, VerifyStage6Error> +where + T: Transcript, +{ + verify_stage6_with_program(&STAGE6_PROGRAM, proof, opening_inputs, verifier_data, transcript) +} + +pub fn verify_stage6_with_program( + program: &'static Stage6VerifierProgramPlan, + proof: &Stage6Proof, + opening_inputs: &[Stage6OpeningInputValue], + verifier_data: Option<&Stage6VerifierData>, + transcript: &mut T, +) -> Result, VerifyStage6Error> +where + T: Transcript, +{ + if proof.sumchecks.len() != program.drivers.len() { + return Err(VerifyStage6Error::UnexpectedProofCount { + expected: program.drivers.len(), + got: proof.sumchecks.len(), + }); + } + let mut store = + super::common::ValueStore::with_opening_inputs(opening_inputs, program.opening_inputs)?; + store.seed_constants(program.field_constants); + store.seed_point_zeros(program.point_zeros); + let mut artifacts = Stage6ExecutionArtifacts::default(); + for step in program.steps { + match step.kind { + "transcript_squeeze" => { + let squeeze = + find_plan(program.transcript_squeezes, step.symbol).ok_or(VerifyStage6Error::MissingValue { + symbol: step.symbol, + })?; + verify_stage6_squeeze(program, squeeze, &mut store, transcript, &mut artifacts)?; + } + "transcript_absorb_bytes" => { + let absorb = find_plan(program.transcript_absorb_bytes, step.symbol).ok_or( + VerifyStage6Error::MissingValue { + symbol: step.symbol, + }, + )?; + absorb_stage6_bytes(absorb, transcript); + } + "sumcheck_driver" => { + let driver = + find_plan(program.drivers, step.symbol).ok_or(VerifyStage6Error::MissingProof { + driver: step.symbol, + })?; + verify_stage6_driver( + program, + driver, + proof, + verifier_data, + &mut store, + transcript, + &mut artifacts, + )?; + } + _ => { + return Err(VerifyStage6Error::InvalidProof { + driver: step.symbol, + reason: "unsupported stage6 program step", + }); + } + } + } + artifacts + .opening_batches + .extend(program.opening_batches.iter()); + Ok(artifacts) +} + +pub fn stage6_verifier_program() -> &'static Stage6VerifierProgramPlan { + &STAGE6_PROGRAM +} + +fn verify_stage6_squeeze( + program: &'static Stage6VerifierProgramPlan, + squeeze: &'static Stage6TranscriptSqueezePlan, + store: &mut super::common::ValueStore, + transcript: &mut T, + artifacts: &mut Stage6ExecutionArtifacts, +) -> Result<(), VerifyStage6Error> +where + T: Transcript, +{ + let values = transcript.challenge_vector(squeeze.count); + store.observe_challenge_vector(squeeze, &values, |input, expected, actual| { + VerifyStage6Error::InvalidInputLength { + input, + expected, + actual, + } + })?; + store + .evaluate_available_field_exprs(program.field_exprs, super::common::evaluate_field_expr) + .map_err(VerifyStage6Error::from)?; + artifacts.challenge_vectors.push(Stage6ChallengeVector { + symbol: squeeze.symbol, + values, + }); + Ok(()) +} + +fn absorb_stage6_bytes(absorb: &'static Stage6TranscriptAbsorbBytesPlan, transcript: &mut T) +where + T: Transcript, +{ + transcript.append(&LabelWithCount( + absorb.label.as_bytes(), + absorb.payload.len() as u64, + )); + transcript.append_bytes(absorb.payload.as_bytes()); +} + +fn verify_stage6_driver( + program: &'static Stage6VerifierProgramPlan, + driver: &'static Stage6SumcheckDriverPlan, + proof: &Stage6Proof, + verifier_data: Option<&Stage6VerifierData>, + store: &mut super::common::ValueStore, + transcript: &mut T, + artifacts: &mut Stage6ExecutionArtifacts, +) -> Result<(), VerifyStage6Error> +where + T: Transcript, +{ + let proof = proof + .sumchecks + .get(artifacts.sumchecks.len()) + .ok_or(VerifyStage6Error::MissingProof { + driver: driver.symbol, + })?; + let relation = driver.relation.unwrap_or(""); + let output = match relation { + "jolt.stage6.batched" => { + verify_batched_stage6(program, driver, proof, verifier_data, store, transcript)? + } + _ => return Err(VerifyStage6Error::UnsupportedRelation { relation }), + }; + artifacts.sumchecks.push(output); + Ok(()) +} + +fn verify_batched_stage6( + program: &'static Stage6VerifierProgramPlan, + driver: &'static Stage6SumcheckDriverPlan, + proof: &Stage6SumcheckOutput, + verifier_data: Option<&Stage6VerifierData>, + store: &mut super::common::ValueStore, + transcript: &mut T, +) -> Result, VerifyStage6Error> +where + T: Transcript, +{ + super::common::verify_batched_sumcheck( + driver, + proof, + program.claims, + program.batches, + program.field_exprs, + program.opening_inputs, + program.opening_claims, + program.opening_batches, + store, + transcript, + |store, evals, point, batching_coeffs| { + expected_batched_output_claim( + program, + driver, + verifier_data, + store, + evals, + point, + batching_coeffs, + ) + }, + |store, verified| observe_stage6_sumcheck_output(program, store, verified), + |driver, error| VerifyStage6Error::Sumcheck { driver, error }, + ) +} + +fn observe_stage6_sumcheck_output( + program: &'static Stage6VerifierProgramPlan, + store: &mut super::common::ValueStore, + output: &Stage6SumcheckOutput, +) -> Result<(), VerifyStage6Error> { + store.observe_sumcheck_output( + program.instance_results, + program.evals, + output, + |instance, mut point| { + match instance.point_order { + "as_is" => {} + "reverse" => point.reverse(), + "bytecode_read_raf" => point = normalize_bytecode_read_raf_point(&point, stage6_trace_rounds(program)?, "stage6.bytecode_read_raf.point")?, + "stage6_booleanity" => {} + "instruction_read_raf" => point = normalize_instruction_read_raf_point(&point, "stage6.instruction_read_raf.point")?, + _ => { + return Err(VerifyStage6Error::InvalidProof { + driver: output.driver, + reason: "unsupported point order", + }); + } + } + Ok(point) + }, + |input, expected, actual| VerifyStage6Error::InvalidInputLength { + input, + expected, + actual, + }, + |symbol| VerifyStage6Error::MissingValue { symbol }, + )?; + store.evaluate_available_points( + program.point_slices, + program.point_concats, + |input, expected, actual| VerifyStage6Error::InvalidInputLength { + input, + expected, + actual, + }, + )?; + store + .evaluate_available_field_exprs(program.field_exprs, super::common::evaluate_field_expr) + .map_err(VerifyStage6Error::from)?; + store.verify_opening_equalities( + program.opening_equalities, + |driver, reason| VerifyStage6Error::InvalidProof { driver, reason }, + |symbol| VerifyStage6Error::MissingValue { symbol }, + ) +} + +fn expected_batched_output_claim( + program: &'static Stage6VerifierProgramPlan, + driver: &'static Stage6SumcheckDriverPlan, + verifier_data: Option<&Stage6VerifierData>, + store: &super::common::ValueStore, + evals: &[Stage6NamedEval], + point: &[Fr], + batching_coeffs: &[Fr], +) -> Result { + let batch = find_batch(program.batches, driver.symbol, driver.batch)?; + let claims = batch_claims(program.claims, batch)?; + let mut expected = Fr::from_u64(0); + for (claim, coefficient) in claims.iter().zip(batching_coeffs) { + let instance = program + .instance_results + .iter() + .find(|instance| instance.claim == claim.symbol && instance.source == driver.symbol) + .ok_or(VerifyStage6Error::MissingClaim { + batch: batch.symbol, + claim: claim.symbol, + })?; + let local_point = point + .get(instance.round_offset..instance.round_offset + instance.num_rounds) + .ok_or(VerifyStage6Error::InvalidInputLength { + input: instance.symbol, + expected: instance.round_offset + instance.num_rounds, + actual: point.len(), + })?; + let relation = claim.relation.unwrap_or(""); + let value = match relation { + "jolt.stage6.bytecode_read_raf" => { + let data = verifier_data + .and_then(|data| data.bytecode_read_raf.as_ref()) + .ok_or(VerifyStage6Error::MissingValue { + symbol: "stage6.bytecode_read_raf.data", + })?; + expected_bytecode_read_raf(program, data, store, evals, local_point)? + } + "jolt.stage6.booleanity" => { + expected_booleanity(program, store, evals, local_point)? + } + "jolt.stage6.hamming_booleanity" => { + expected_hamming_booleanity(store, evals, local_point)? + } + "jolt.stage6.ram_ra_virtual" => { + expected_ram_ra_virtual(store, evals, local_point)? + } + "jolt.stage6.instruction_ra_virtual" => { + expected_instruction_ra_virtual(program, store, evals, local_point)? + } + "jolt.stage6.inc_claim_reduction" => { + expected_inc_claim_reduction(store, evals, local_point)? + } + _ => return Err(VerifyStage6Error::UnsupportedRelation { relation }), + }; + expected += *coefficient * value; + } + Ok(expected) +} + +fn expected_bytecode_read_raf( + program: &'static Stage6VerifierProgramPlan, + data: &Stage6BytecodeReadRafData, + store: &super::common::ValueStore, + evals: &[Stage6NamedEval], + local_point: &[Fr], +) -> Result { + let log_t = stage6_trace_rounds(program)?; + Ok(expected_stage67_bytecode_read_raf( + &data.entries, + data.entry_bytecode_index, + data.num_lookup_tables, + store, + evals, + local_point, + log_t, + &STAGE6_BYTECODE_SYMBOLS, + )?) +} + +fn expected_booleanity( + program: &'static Stage6VerifierProgramPlan, + store: &super::common::ValueStore, + evals: &[Stage6NamedEval], + local_point: &[Fr], +) -> Result { + let log_t = stage6_trace_rounds(program)?; + Ok(expected_stage67_booleanity(store, evals, local_point, log_t, &STAGE6_RELATION_SYMBOLS)?) +} + +fn expected_hamming_booleanity( + store: &super::common::ValueStore, + evals: &[Stage6NamedEval], + local_point: &[Fr], +) -> Result { + Ok(expected_stage67_hamming_booleanity(store, evals, local_point, &STAGE6_RELATION_SYMBOLS)?) +} + +fn expected_ram_ra_virtual( + store: &super::common::ValueStore, + evals: &[Stage6NamedEval], + local_point: &[Fr], +) -> Result { + Ok(expected_stage67_ram_ra_virtual(store, evals, local_point, &STAGE6_RELATION_SYMBOLS)?) +} + +fn expected_instruction_ra_virtual( + program: &'static Stage6VerifierProgramPlan, + store: &super::common::ValueStore, + evals: &[Stage6NamedEval], + local_point: &[Fr], +) -> Result { + Ok(expected_stage67_instruction_ra_virtual(program.opening_inputs, store, evals, local_point, &STAGE6_RELATION_SYMBOLS)?) +} + +fn expected_inc_claim_reduction( + store: &super::common::ValueStore, + evals: &[Stage6NamedEval], + local_point: &[Fr], +) -> Result { + Ok(expected_stage67_inc_claim_reduction(store, evals, local_point, &STAGE6_RELATION_SYMBOLS)?) +} + +fn stage6_trace_rounds( + program: &'static Stage6VerifierProgramPlan, +) -> Result { + Ok(stage67_trace_rounds(program.instance_results, &STAGE6_RELATION_SYMBOLS)?) +} +"# + } + } + } + + fn role_label(&self) -> &'static str { + match self.role { + Role::Prover => "prover", + Role::Verifier => "verifier", + } + } + + fn program_plan_type(&self) -> &'static str { + match self.role { + Role::Prover => "Stage6CpuProgramPlan", + Role::Verifier => "Stage6VerifierProgramPlan", + } + } +} + +fn require_supported_symbol(kind: &str, actual: &str, expected: &str) -> Result<(), EmitError> { + if actual == expected { + Ok(()) + } else { + Err(EmitError::new(format!( + "unsupported {kind} @{actual}; expected @{expected}" + ))) + } +} + +fn emit_str_array(name: &str, values: &[String]) -> String { + if values.is_empty() { + return format!("pub const {name}: &[&str] = &[];\n\n"); + } + if let [value] = values { + return format!("pub const {name}: &[&str] = &[{}];\n\n", rust_str(value)); + } + let entries = values + .iter() + .map(|value| format!(" {},", rust_str(value))) + .collect::>() + .join("\n"); + format!("pub const {name}: &[&str] = &[\n{entries}\n];\n\n") +} + +fn emit_usize_array(name: &str, values: &[usize]) -> String { + let entries = values + .iter() + .map(|value| format!(" {value},")) + .collect::>() + .join("\n"); + format!("pub const {name}: &[usize] = &[\n{entries}\n];\n\n") +} + +fn intern_str_array( + source: &mut String, + arrays: &mut Vec<(Vec, String)>, + name_prefix: &str, + values: &[String], +) -> String { + if let Some((_, name)) = arrays + .iter() + .find(|(existing, _)| existing.as_slice() == values) + { + return name.clone(); + } + let name = format!("{name_prefix}_{}", arrays.len()); + source.push_str(&emit_str_array(&name, values)); + arrays.push((values.to_vec(), name.clone())); + name +} + +fn rust_str(value: &str) -> String { + format!("{value:?}") +} + +fn rust_option_str(value: Option<&str>) -> String { + value.map_or_else( + || "None".to_owned(), + |value| format!("Some({})", rust_str(value)), + ) +} + +fn verify_count(kind: &str, symbol: &str, expected: usize, actual: usize) -> Result<(), EmitError> { + if expected == actual { + Ok(()) + } else { + Err(EmitError::new(format!( + "{kind} @{symbol} count mismatch: expected {expected}, got {actual}" + ))) + } +} + +fn symbols<'a>(values: impl Iterator) -> BTreeSet { + values.cloned().collect() +} + +fn string_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .ok() + .and_then(string_attribute_value) + .ok_or_else(|| attr_error(operation, attr, "string")) +} + +fn symbol_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .ok() + .and_then(symbol_attribute_value) + .ok_or_else(|| attr_error(operation, attr, "symbol")) +} + +fn symbol_array_attr( + operation: OperationRef<'_, '_>, + attr: &str, +) -> Result, EmitError> { + let attribute = operation + .attribute(attr) + .map(|attribute| attribute.to_string()) + .ok() + .ok_or_else(|| attr_error(operation, attr, "symbol array"))?; + parse_symbol_array(&attribute).ok_or_else(|| attr_error(operation, attr, "symbol array")) +} + +fn parse_symbol_array(attribute: &str) -> Option> { + let inner = attribute.strip_prefix('[')?.strip_suffix(']')?.trim(); + if inner.is_empty() { + return Some(Vec::new()); + } + inner + .split(',') + .map(|item| item.trim().strip_prefix('@').map(ToOwned::to_owned)) + .collect() +} + +fn int_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .map(parse_integer_attr) + .ok() + .flatten() + .ok_or_else(|| attr_error(operation, attr, "integer")) +} + +fn parse_integer_attr(attribute: Attribute<'_>) -> Option { + attribute + .to_string() + .split_whitespace() + .next() + .and_then(|value| value.parse().ok()) +} + +fn int_array_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result, EmitError> { + let attribute = operation + .attribute(attr) + .map(|attribute| attribute.to_string()) + .ok() + .ok_or_else(|| attr_error(operation, attr, "integer array"))?; + parse_int_array(&attribute).ok_or_else(|| attr_error(operation, attr, "integer array")) +} + +fn parse_int_array(attribute: &str) -> Option> { + let inner = attribute.strip_prefix('[')?.strip_suffix(']')?.trim(); + if inner.is_empty() { + return Some(Vec::new()); + } + inner + .split(',') + .map(|item| item.trim().parse().ok()) + .collect() +} + +fn operand_symbols( + operation: OperationRef<'_, '_>, + start_index: usize, +) -> Result, EmitError> { + (start_index..operation.operand_count()) + .map(|index| operand_symbol(operation, index)) + .collect() +} + +fn operand_symbol(operation: OperationRef<'_, '_>, index: usize) -> Result { + let operand = operation.operand(index).map_err(|_| { + EmitError::new(format!( + "{} requires operand {index}", + operation_name(operation) + )) + })?; + let owner = OperationResult::try_from(operand).map_err(|_| { + EmitError::new(format!( + "{} operand {index} must be an op result", + operation_name(operation) + )) + })?; + string_attr(owner.owner(), "sym_name") +} + +fn attr_error(operation: OperationRef<'_, '_>, attr: &str, expected: &str) -> EmitError { + EmitError::new(format!( + "{} attr `{attr}` is not a {expected}", + operation_name(operation) + )) +} + +fn operation_name<'c: 'a, 'a>(operation: impl OperationLike<'c, 'a>) -> String { + operation + .name() + .as_string_ref() + .as_str() + .unwrap_or("") + .to_owned() +} diff --git a/crates/bolt/src/protocols/jolt/emit/rust/stage7.rs b/crates/bolt/src/protocols/jolt/emit/rust/stage7.rs new file mode 100644 index 0000000000..afc274ff7f --- /dev/null +++ b/crates/bolt/src/protocols/jolt/emit/rust/stage7.rs @@ -0,0 +1,2529 @@ +#![expect( + clippy::needless_raw_string_hashes, + reason = "generated Rust templates are kept as raw string blocks for copyable output" +)] + +use std::collections::{BTreeMap, BTreeSet}; + +use melior::ir::block::BlockLike; +use melior::ir::operation::{OperationLike, OperationResult}; +use melior::ir::{Attribute, OperationRef}; + +use crate::emit::rust::{push_format, EmitError, RustSourceFile}; +use crate::ir::{string_attribute_value, symbol_attribute_value, BoltModule, Cpu, Role}; +use crate::schema::verify_cpu_schema; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage7CpuProgram { + pub role: Role, + pub params: Stage7Params, + pub steps: Vec, + pub transcript_squeezes: Vec, + pub transcript_absorb_bytes: Vec, + pub opening_inputs: Vec, + pub field_constants: Vec, + pub field_exprs: Vec, + pub kernels: Vec, + pub claims: Vec, + pub batches: Vec, + pub drivers: Vec, + pub instance_results: Vec, + pub evals: Vec, + pub point_zeros: Vec, + pub point_slices: Vec, + pub point_concats: Vec, + pub opening_claims: Vec, + pub opening_equalities: Vec, + pub opening_batches: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage7Params { + pub field: String, + pub pcs: String, + pub transcript: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage7KernelPlan { + pub symbol: String, + pub relation: String, + pub kind: String, + pub backend: String, + pub abi: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage7TranscriptSqueezePlan { + pub symbol: String, + pub label: String, + pub kind: String, + pub count: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage7TranscriptAbsorbBytesPlan { + pub symbol: String, + pub label: String, + pub payload: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage7ProgramStepPlan { + pub kind: String, + pub symbol: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage7OpeningInputPlan { + pub symbol: String, + pub source_stage: String, + pub source_claim: String, + pub oracle: String, + pub domain: String, + pub point_arity: usize, + pub claim_kind: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage7FieldConstantPlan { + pub symbol: String, + pub field: String, + pub value: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage7FieldExprPlan { + pub symbol: String, + pub kind: String, + pub formula: String, + pub operand_names: Vec, + pub operands: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage7SumcheckClaimPlan { + pub symbol: String, + pub stage: String, + pub domain: String, + pub num_rounds: usize, + pub degree: usize, + pub claim: String, + pub kernel: Option, + pub relation: Option, + pub claim_value: String, + pub input_openings: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage7SumcheckBatchPlan { + pub symbol: String, + pub stage: String, + pub proof_slot: String, + pub policy: String, + pub count: usize, + pub ordered_claims: Vec, + pub claim_operands: Vec, + pub claim_label: String, + pub round_label: String, + pub round_schedule: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage7SumcheckDriverPlan { + pub symbol: String, + pub stage: String, + pub proof_slot: String, + pub kernel: Option, + pub relation: Option, + pub batch: String, + pub policy: String, + pub round_schedule: Vec, + pub claim_label: String, + pub round_label: String, + pub num_rounds: usize, + pub degree: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage7SumcheckInstanceResultPlan { + pub symbol: String, + pub source: String, + pub claim: String, + pub relation: String, + pub index: usize, + pub point_arity: usize, + pub num_rounds: usize, + pub round_offset: usize, + pub point_order: String, + pub degree: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage7SumcheckEvalPlan { + pub symbol: String, + pub source: String, + pub name: String, + pub index: usize, + pub oracle: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage7PointZeroPlan { + pub symbol: String, + pub field: String, + pub arity: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage7PointSlicePlan { + pub symbol: String, + pub source: String, + pub offset: usize, + pub length: usize, + pub input: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage7PointConcatPlan { + pub symbol: String, + pub layout: String, + pub arity: usize, + pub inputs: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage7OpeningClaimPlan { + pub symbol: String, + pub oracle: String, + pub domain: String, + pub point_arity: usize, + pub claim_kind: String, + pub point_source: String, + pub eval_source: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage7OpeningClaimEqualityPlan { + pub symbol: String, + pub mode: String, + pub lhs: String, + pub rhs: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage7OpeningBatchPlan { + pub symbol: String, + pub stage: String, + pub proof_slot: String, + pub policy: String, + pub count: usize, + pub ordered_claims: Vec, + pub claim_operands: Vec, +} + +pub fn stage7_cpu_program(module: &BoltModule<'_, Cpu>) -> Result { + verify_cpu_schema(module)?; + let program = Stage7CpuProgram::from_module(module)?; + program.verify_supported_target()?; + Ok(program) +} + +pub fn emit_stage7_rust(module: &BoltModule<'_, Cpu>) -> Result { + let program = stage7_cpu_program(module)?; + + Ok(RustSourceFile { + filename: program.filename().to_owned(), + source: program.emit_source(), + }) +} + +impl Stage7CpuProgram { + fn from_module(module: &BoltModule<'_, Cpu>) -> Result { + let mut params = None; + let mut steps = Vec::new(); + let mut transcript_squeezes = Vec::new(); + let mut transcript_absorb_bytes = Vec::new(); + let mut opening_inputs = Vec::new(); + let mut field_constants = Vec::new(); + let mut field_exprs = Vec::new(); + let mut kernels = Vec::new(); + let mut claims = Vec::new(); + let mut batches = Vec::new(); + let mut drivers = Vec::new(); + let mut instance_results = Vec::new(); + let mut evals = Vec::new(); + let mut point_zeros = Vec::new(); + let mut point_slices = Vec::new(); + let mut point_concats = Vec::new(); + let mut opening_claims = Vec::new(); + let mut opening_equalities = Vec::new(); + let mut opening_batches = Vec::new(); + + let mut operation = module.as_mlir_module().body().first_operation(); + while let Some(op) = operation { + operation = op.next_in_block(); + match operation_name(op).as_str() { + "cpu.params" => { + params = Some(Stage7Params { + field: symbol_attr(op, "field")?, + pcs: symbol_attr(op, "pcs")?, + transcript: symbol_attr(op, "transcript")?, + }); + } + "cpu.kernel" => { + kernels.push(Stage7KernelPlan { + symbol: string_attr(op, "sym_name")?, + relation: symbol_attr(op, "relation")?, + kind: string_attr(op, "kind")?, + backend: string_attr(op, "backend")?, + abi: string_attr(op, "abi")?, + }); + } + "cpu.transcript_squeeze" => { + let symbol = string_attr(op, "sym_name")?; + steps.push(Stage7ProgramStepPlan { + kind: "transcript_squeeze".to_owned(), + symbol: symbol.clone(), + }); + transcript_squeezes.push(Stage7TranscriptSqueezePlan { + symbol, + label: string_attr(op, "label")?, + kind: string_attr(op, "kind")?, + count: int_attr(op, "count")?, + }); + } + "cpu.transcript_absorb_bytes" => { + let symbol = string_attr(op, "sym_name")?; + steps.push(Stage7ProgramStepPlan { + kind: "transcript_absorb_bytes".to_owned(), + symbol: symbol.clone(), + }); + transcript_absorb_bytes.push(Stage7TranscriptAbsorbBytesPlan { + symbol, + label: string_attr(op, "label")?, + payload: string_attr(op, "payload")?, + }); + } + "cpu.opening_input" => { + opening_inputs.push(Stage7OpeningInputPlan { + symbol: string_attr(op, "sym_name")?, + source_stage: symbol_attr(op, "source_stage")?, + source_claim: symbol_attr(op, "source_claim")?, + oracle: symbol_attr(op, "oracle")?, + domain: symbol_attr(op, "domain")?, + point_arity: int_attr(op, "point_arity")?, + claim_kind: string_attr(op, "claim_kind")?, + }); + } + "cpu.field_const" => { + field_constants.push(Stage7FieldConstantPlan { + symbol: string_attr(op, "sym_name")?, + field: symbol_attr(op, "field")?, + value: int_attr(op, "value")?, + }); + } + "cpu.field_zero" => { + field_constants.push(Stage7FieldConstantPlan { + symbol: string_attr(op, "sym_name")?, + field: symbol_attr(op, "field")?, + value: 0, + }); + } + "cpu.field_one" => { + field_constants.push(Stage7FieldConstantPlan { + symbol: string_attr(op, "sym_name")?, + field: symbol_attr(op, "field")?, + value: 1, + }); + } + "cpu.field_add" | "cpu.field_sub" | "cpu.field_mul" | "cpu.field_neg" => { + let operands = operand_symbols(op, 0)?; + field_exprs.push(Stage7FieldExprPlan { + symbol: string_attr(op, "sym_name")?, + kind: "op".to_owned(), + formula: operation_name(op).replace("cpu.field_", "field."), + operand_names: operands.clone(), + operands, + }); + } + "cpu.field_pow" => { + let exponent = int_attr(op, "exponent")?; + let operands = operand_symbols(op, 0)?; + field_exprs.push(Stage7FieldExprPlan { + symbol: string_attr(op, "sym_name")?, + kind: "op".to_owned(), + formula: format!("field.pow:{exponent}"), + operand_names: operands.clone(), + operands, + }); + } + "cpu.sumcheck_claim" => { + claims.push(Stage7SumcheckClaimPlan { + symbol: string_attr(op, "sym_name")?, + stage: symbol_attr(op, "stage")?, + domain: symbol_attr(op, "domain")?, + num_rounds: int_attr(op, "num_rounds")?, + degree: int_attr(op, "degree")?, + claim: symbol_attr(op, "claim")?, + kernel: Some(symbol_attr(op, "kernel")?), + relation: None, + claim_value: operand_symbol(op, 0)?, + input_openings: operand_symbols(op, 1)?, + }); + } + "cpu.sumcheck_verify_claim" => { + claims.push(Stage7SumcheckClaimPlan { + symbol: string_attr(op, "sym_name")?, + stage: symbol_attr(op, "stage")?, + domain: symbol_attr(op, "domain")?, + num_rounds: int_attr(op, "num_rounds")?, + degree: int_attr(op, "degree")?, + claim: symbol_attr(op, "claim")?, + kernel: None, + relation: Some(symbol_attr(op, "relation")?), + claim_value: operand_symbol(op, 0)?, + input_openings: operand_symbols(op, 1)?, + }); + } + "cpu.sumcheck_batch" => { + batches.push(Stage7SumcheckBatchPlan { + symbol: string_attr(op, "sym_name")?, + stage: symbol_attr(op, "stage")?, + proof_slot: symbol_attr(op, "proof_slot")?, + policy: string_attr(op, "policy")?, + count: int_attr(op, "count")?, + ordered_claims: symbol_array_attr(op, "ordered_claims")?, + claim_operands: operand_symbols(op, 0)?, + claim_label: string_attr(op, "claim_label")?, + round_label: string_attr(op, "round_label")?, + round_schedule: int_array_attr(op, "round_schedule")?, + }); + } + "cpu.sumcheck_driver" => { + let symbol = string_attr(op, "sym_name")?; + steps.push(Stage7ProgramStepPlan { + kind: "sumcheck_driver".to_owned(), + symbol: symbol.clone(), + }); + drivers.push(Stage7SumcheckDriverPlan { + symbol, + stage: symbol_attr(op, "stage")?, + proof_slot: symbol_attr(op, "proof_slot")?, + kernel: Some(symbol_attr(op, "kernel")?), + relation: None, + batch: operand_symbol(op, 1)?, + policy: string_attr(op, "policy")?, + round_schedule: int_array_attr(op, "round_schedule")?, + claim_label: string_attr(op, "claim_label")?, + round_label: string_attr(op, "round_label")?, + num_rounds: int_attr(op, "num_rounds")?, + degree: int_attr(op, "degree")?, + }); + } + "cpu.sumcheck_verify" => { + let symbol = string_attr(op, "sym_name")?; + steps.push(Stage7ProgramStepPlan { + kind: "sumcheck_driver".to_owned(), + symbol: symbol.clone(), + }); + drivers.push(Stage7SumcheckDriverPlan { + symbol, + stage: symbol_attr(op, "stage")?, + proof_slot: symbol_attr(op, "proof_slot")?, + kernel: None, + relation: Some(symbol_attr(op, "relation")?), + batch: operand_symbol(op, 1)?, + policy: string_attr(op, "policy")?, + round_schedule: int_array_attr(op, "round_schedule")?, + claim_label: string_attr(op, "claim_label")?, + round_label: string_attr(op, "round_label")?, + num_rounds: int_attr(op, "num_rounds")?, + degree: int_attr(op, "degree")?, + }); + } + "cpu.sumcheck_instance_result" => { + instance_results.push(Stage7SumcheckInstanceResultPlan { + symbol: string_attr(op, "sym_name")?, + source: symbol_attr(op, "source")?, + claim: symbol_attr(op, "claim")?, + relation: symbol_attr(op, "relation")?, + index: int_attr(op, "index")?, + point_arity: int_attr(op, "point_arity")?, + num_rounds: int_attr(op, "num_rounds")?, + round_offset: int_attr(op, "round_offset")?, + point_order: string_attr(op, "point_order")?, + degree: int_attr(op, "degree")?, + }); + } + "cpu.sumcheck_eval" => { + evals.push(Stage7SumcheckEvalPlan { + symbol: string_attr(op, "sym_name")?, + source: symbol_attr(op, "source")?, + name: symbol_attr(op, "name")?, + index: int_attr(op, "index")?, + oracle: symbol_attr(op, "oracle")?, + }); + } + "cpu.point_zero" => { + point_zeros.push(Stage7PointZeroPlan { + symbol: string_attr(op, "sym_name")?, + field: symbol_attr(op, "field")?, + arity: int_attr(op, "arity")?, + }); + } + "cpu.point_slice" => { + point_slices.push(Stage7PointSlicePlan { + symbol: string_attr(op, "sym_name")?, + source: symbol_attr(op, "source")?, + offset: int_attr(op, "offset")?, + length: int_attr(op, "length")?, + input: operand_symbol(op, 0)?, + }); + } + "cpu.point_concat" => { + point_concats.push(Stage7PointConcatPlan { + symbol: string_attr(op, "sym_name")?, + layout: string_attr(op, "layout")?, + arity: int_attr(op, "arity")?, + inputs: operand_symbols(op, 0)?, + }); + } + "cpu.opening_claim" => { + opening_claims.push(Stage7OpeningClaimPlan { + symbol: string_attr(op, "sym_name")?, + oracle: symbol_attr(op, "oracle")?, + domain: symbol_attr(op, "domain")?, + point_arity: int_attr(op, "point_arity")?, + claim_kind: string_attr(op, "claim_kind")?, + point_source: operand_symbol(op, 0)?, + eval_source: operand_symbol(op, 1)?, + }); + } + "cpu.opening_claim_equal" => { + opening_equalities.push(Stage7OpeningClaimEqualityPlan { + symbol: string_attr(op, "sym_name")?, + mode: string_attr(op, "mode")?, + lhs: operand_symbol(op, 0)?, + rhs: operand_symbol(op, 1)?, + }); + } + "cpu.opening_batch" => { + opening_batches.push(Stage7OpeningBatchPlan { + symbol: string_attr(op, "sym_name")?, + stage: symbol_attr(op, "stage")?, + proof_slot: symbol_attr(op, "proof_slot")?, + policy: string_attr(op, "policy")?, + count: int_attr(op, "count")?, + ordered_claims: symbol_array_attr(op, "ordered_claims")?, + claim_operands: operand_symbols(op, 0)?, + }); + } + _ => {} + } + } + + Ok(Self { + params: params.ok_or_else(|| EmitError::new("missing cpu.params"))?, + role: module + .role() + .ok_or_else(|| EmitError::new("missing cpu party role"))?, + steps, + transcript_squeezes, + transcript_absorb_bytes, + opening_inputs, + field_constants, + field_exprs, + kernels, + claims, + batches, + drivers, + instance_results, + evals, + point_zeros, + point_slices, + point_concats, + opening_claims, + opening_equalities, + opening_batches, + }) + } + + fn verify_supported_target(&self) -> Result<(), EmitError> { + require_supported_symbol("field", &self.params.field, "bn254_fr")?; + require_supported_symbol("pcs", &self.params.pcs, "dory")?; + require_supported_symbol("transcript", &self.params.transcript, "blake2b_transcript")?; + self.verify_transcript_steps()?; + self.verify_field_flow()?; + self.verify_claim_batches()?; + match self.role { + Role::Prover => { + self.verify_kernel_definitions()?; + self.verify_prover_driver_bindings()?; + } + Role::Verifier => self.verify_verifier_driver_bindings()?, + } + self.verify_opening_flow() + } + + fn verify_transcript_steps(&self) -> Result<(), EmitError> { + for squeeze in &self.transcript_squeezes { + if !matches!( + squeeze.kind.as_str(), + "challenge_scalar" | "challenge_vector" + ) { + return Err(EmitError::new(format!( + "stage7 transcript squeeze @{} has unsupported kind `{}`", + squeeze.symbol, squeeze.kind + ))); + } + if squeeze.count == 0 { + return Err(EmitError::new(format!( + "stage7 transcript squeeze @{} has zero count", + squeeze.symbol + ))); + } + } + for absorb in &self.transcript_absorb_bytes { + if absorb.label.is_empty() { + return Err(EmitError::new(format!( + "stage7 transcript byte absorb @{} has empty label", + absorb.symbol + ))); + } + } + Ok(()) + } + + fn verify_field_flow(&self) -> Result<(), EmitError> { + for constant in &self.field_constants { + require_supported_symbol("field constant field", &constant.field, "bn254_fr")?; + } + let field_values = self.field_value_symbols(); + for expr in &self.field_exprs { + verify_count( + "field expr operands", + &expr.symbol, + expr.operand_names.len(), + expr.operands.len(), + )?; + for operand in &expr.operands { + if !field_values.contains(operand) { + return Err(EmitError::new(format!( + "field expr @{} references missing field value @{operand}", + expr.symbol + ))); + } + } + } + for claim in &self.claims { + if !field_values.contains(&claim.claim_value) { + return Err(EmitError::new(format!( + "sumcheck claim @{} uses missing claim value @{}", + claim.symbol, claim.claim_value + ))); + } + } + Ok(()) + } + + fn field_value_symbols(&self) -> BTreeSet { + let mut values = symbols(self.opening_inputs.iter().map(|input| &input.symbol)); + values.extend(symbols( + self.field_constants.iter().map(|constant| &constant.symbol), + )); + values.extend(symbols( + self.transcript_squeezes + .iter() + .filter(|squeeze| matches!(squeeze.kind.as_str(), "challenge_scalar" | "scalar")) + .map(|squeeze| &squeeze.symbol), + )); + values.extend(symbols(self.field_exprs.iter().map(|expr| &expr.symbol))); + values.extend(symbols(self.evals.iter().map(|eval| &eval.symbol))); + values + } + + fn verify_kernel_definitions(&self) -> Result<(), EmitError> { + for kernel in &self.kernels { + if kernel.backend != "cpu" { + return Err(EmitError::new(format!( + "stage7 kernel @{} targets unsupported backend `{}`", + kernel.symbol, kernel.backend + ))); + } + if kernel.kind != "sumcheck" { + return Err(EmitError::new(format!( + "stage7 kernel @{} has unsupported kind `{}`", + kernel.symbol, kernel.kind + ))); + } + let expected_abi = match kernel.relation.as_str() { + "jolt.stage7.hamming_weight_claim_reduction" => { + "jolt_stage7_hamming_weight_claim_reduction" + } + "jolt.stage7.batched" => "jolt_stage7_batched", + _ => { + return Err(EmitError::new(format!( + "unsupported stage7 kernel relation @{}", + kernel.relation + ))); + } + }; + if kernel.abi != expected_abi { + return Err(EmitError::new(format!( + "stage7 kernel @{} ABI `{}` does not match relation @{}", + kernel.symbol, kernel.abi, kernel.relation + ))); + } + } + Ok(()) + } + + fn verify_claim_batches(&self) -> Result<(), EmitError> { + let claims = symbols(self.claims.iter().map(|claim| &claim.symbol)); + for batch in &self.batches { + verify_count( + "sumcheck batch", + &batch.symbol, + batch.count, + batch.ordered_claims.len(), + )?; + verify_count( + "sumcheck batch operands", + &batch.symbol, + batch.count, + batch.claim_operands.len(), + )?; + if batch.ordered_claims != batch.claim_operands { + return Err(EmitError::new(format!( + "sumcheck batch @{} operand order does not match ordered_claims", + batch.symbol + ))); + } + for claim in &batch.ordered_claims { + if !claims.contains(claim) { + return Err(EmitError::new(format!( + "sumcheck batch @{} references missing claim @{claim}", + batch.symbol + ))); + } + } + } + Ok(()) + } + + fn verify_prover_driver_bindings(&self) -> Result<(), EmitError> { + let kernels = symbols(self.kernels.iter().map(|kernel| &kernel.symbol)); + let batches: BTreeMap<_, _> = self + .batches + .iter() + .map(|batch| (batch.symbol.as_str(), batch)) + .collect(); + for claim in &self.claims { + let Some(kernel) = claim.kernel.as_deref() else { + return Err(EmitError::new(format!( + "prover sumcheck claim @{} is missing kernel", + claim.symbol + ))); + }; + if !kernels.contains(kernel) { + return Err(EmitError::new(format!( + "sumcheck claim @{} references missing kernel @{kernel}", + claim.symbol + ))); + } + } + for driver in &self.drivers { + let Some(kernel) = driver.kernel.as_deref() else { + return Err(EmitError::new(format!( + "prover sumcheck driver @{} is missing kernel", + driver.symbol + ))); + }; + if !kernels.contains(kernel) { + return Err(EmitError::new(format!( + "sumcheck driver @{} references missing kernel @{kernel}", + driver.symbol + ))); + } + let batch = batches.get(driver.batch.as_str()).ok_or_else(|| { + EmitError::new(format!( + "sumcheck driver @{} references missing batch @{}", + driver.symbol, driver.batch + )) + })?; + verify_count( + "sumcheck driver round_schedule", + &driver.symbol, + driver.num_rounds, + driver.round_schedule.iter().sum(), + )?; + if driver.round_schedule != batch.round_schedule { + return Err(EmitError::new(format!( + "sumcheck driver @{} round_schedule differs from batch @{}", + driver.symbol, batch.symbol + ))); + } + } + Ok(()) + } + + fn verify_verifier_driver_bindings(&self) -> Result<(), EmitError> { + if !self.kernels.is_empty() { + return Err(EmitError::new( + "verifier stage7 program must not contain kernels", + )); + } + let batches: BTreeMap<_, _> = self + .batches + .iter() + .map(|batch| (batch.symbol.as_str(), batch)) + .collect(); + for claim in &self.claims { + if claim.kernel.is_some() || claim.relation.is_none() { + return Err(EmitError::new(format!( + "verifier sumcheck claim @{} must carry relation and no kernel", + claim.symbol + ))); + } + } + for driver in &self.drivers { + if driver.kernel.is_some() || driver.relation.is_none() { + return Err(EmitError::new(format!( + "verifier sumcheck driver @{} must carry relation and no kernel", + driver.symbol + ))); + } + let batch = batches.get(driver.batch.as_str()).ok_or_else(|| { + EmitError::new(format!( + "sumcheck driver @{} references missing batch @{}", + driver.symbol, driver.batch + )) + })?; + verify_count( + "sumcheck driver round_schedule", + &driver.symbol, + driver.num_rounds, + driver.round_schedule.iter().sum(), + )?; + if driver.round_schedule != batch.round_schedule { + return Err(EmitError::new(format!( + "sumcheck driver @{} round_schedule differs from batch @{}", + driver.symbol, batch.symbol + ))); + } + } + Ok(()) + } + + fn verify_opening_flow(&self) -> Result<(), EmitError> { + let mut point_sources = symbols(self.drivers.iter().map(|driver| &driver.symbol)); + point_sources.extend(symbols( + self.instance_results + .iter() + .map(|instance| &instance.symbol), + )); + point_sources.extend(symbols( + self.opening_inputs.iter().map(|input| &input.symbol), + )); + point_sources.extend(symbols(self.point_zeros.iter().map(|zero| &zero.symbol))); + point_sources.extend(symbols(self.point_slices.iter().map(|slice| &slice.symbol))); + point_sources.extend(symbols( + self.point_concats.iter().map(|concat| &concat.symbol), + )); + for zero in &self.point_zeros { + require_supported_symbol("point zero field", &zero.field, "bn254_fr")?; + } + for slice in &self.point_slices { + if !point_sources.contains(&slice.input) { + return Err(EmitError::new(format!( + "point slice @{} uses missing point source @{}", + slice.symbol, slice.input + ))); + } + } + for concat in &self.point_concats { + for input in &concat.inputs { + if !point_sources.contains(input) { + return Err(EmitError::new(format!( + "point concat @{} uses missing point source @{input}", + concat.symbol + ))); + } + } + } + let eval_sources = self.field_value_symbols(); + let mut opening_sources = symbols(self.opening_inputs.iter().map(|input| &input.symbol)); + opening_sources.extend(symbols( + self.opening_claims.iter().map(|claim| &claim.symbol), + )); + for equality in &self.opening_equalities { + if !opening_sources.contains(&equality.lhs) { + return Err(EmitError::new(format!( + "opening equality @{} uses missing lhs opening @{}", + equality.symbol, equality.lhs + ))); + } + if !opening_sources.contains(&equality.rhs) { + return Err(EmitError::new(format!( + "opening equality @{} uses missing rhs opening @{}", + equality.symbol, equality.rhs + ))); + } + } + for claim in &self.claims { + for input in &claim.input_openings { + if !opening_sources.contains(input) { + return Err(EmitError::new(format!( + "sumcheck claim @{} uses missing opening @{input}", + claim.symbol + ))); + } + } + } + let drivers = symbols(self.drivers.iter().map(|driver| &driver.symbol)); + for instance in &self.instance_results { + if !drivers.contains(&instance.source) { + return Err(EmitError::new(format!( + "sumcheck instance result @{} references missing driver @{}", + instance.symbol, instance.source + ))); + } + } + for eval in &self.evals { + if !drivers.contains(&eval.source) { + return Err(EmitError::new(format!( + "sumcheck eval @{} references missing driver @{}", + eval.symbol, eval.source + ))); + } + } + for claim in &self.opening_claims { + if !point_sources.contains(&claim.point_source) { + return Err(EmitError::new(format!( + "opening claim @{} uses missing point source @{}", + claim.symbol, claim.point_source + ))); + } + if !eval_sources.contains(&claim.eval_source) { + return Err(EmitError::new(format!( + "opening claim @{} uses missing eval source @{}", + claim.symbol, claim.eval_source + ))); + } + } + let openings = symbols(self.opening_claims.iter().map(|claim| &claim.symbol)); + for batch in &self.opening_batches { + verify_count( + "opening batch", + &batch.symbol, + batch.count, + batch.ordered_claims.len(), + )?; + verify_count( + "opening batch operands", + &batch.symbol, + batch.count, + batch.claim_operands.len(), + )?; + if batch.ordered_claims != batch.claim_operands { + return Err(EmitError::new(format!( + "opening batch @{} operand order does not match ordered_claims", + batch.symbol + ))); + } + for claim in &batch.ordered_claims { + if !openings.contains(claim) { + return Err(EmitError::new(format!( + "opening batch @{} references missing opening @{claim}", + batch.symbol + ))); + } + } + } + Ok(()) + } + + fn filename(&self) -> &'static str { + match self.role { + Role::Prover => "prove_stage7.rs", + Role::Verifier => "verify_stage7.rs", + } + } + + fn emit_source(&self) -> String { + let mut source = String::new(); + source.push_str("#![allow(dead_code)]\n\n"); + match self.role { + Role::Prover => { + source.push_str(Self::emit_prover_imports()); + source.push_str("\n\n"); + source.push_str(Self::emit_prover_types()); + } + Role::Verifier => { + source.push_str(Self::emit_verifier_imports()); + source.push_str("\n\n"); + source.push_str(&Self::emit_verifier_types()); + } + } + source.push('\n'); + source.push_str(&self.emit_constants()); + source.push('\n'); + source.push_str(self.emit_entrypoint()); + source + } + + fn emit_prover_imports() -> &'static str { + "use jolt_field::Fr;\n\ + use jolt_kernels::stage7::{execute_stage7_program, Stage7CpuProgramPlan, Stage7ExecutionArtifacts, Stage7ExecutionMode, Stage7FieldConstantPlan, Stage7FieldExprPlan, Stage7KernelError, Stage7KernelExecutor, Stage7KernelPlan, Stage7OpeningBatchPlan, Stage7OpeningClaimEqualityPlan, Stage7OpeningClaimPlan, Stage7OpeningInputPlan, Stage7Params, Stage7PointConcatPlan, Stage7PointSlicePlan, Stage7PointZeroPlan, Stage7ProgramStepPlan, Stage7SumcheckBatchPlan, Stage7SumcheckClaimPlan, Stage7SumcheckDriverPlan, Stage7SumcheckEvalPlan, Stage7SumcheckInstanceResultPlan, Stage7TranscriptAbsorbBytesPlan, Stage7TranscriptSqueezePlan};\n\ + use jolt_transcript::{Blake2bTranscript, Transcript};" + } + + fn emit_prover_types() -> &'static str { + "pub type DefaultStage7Transcript = Blake2bTranscript;\n" + } + + fn emit_verifier_imports() -> &'static str { + "use super::common::{batch_claims, eval_by_name, find_batch, find_plan, normalize_bytecode_read_raf_point, normalize_instruction_read_raf_point, reverse_slice};\n\ + use jolt_field::{Field, Fr};\n\ + use jolt_poly::EqPolynomial;\n\ + use jolt_sumcheck::SumcheckError;\n\ + use jolt_transcript::{Blake2bTranscript, LabelWithCount, Transcript};" + } + + #[expect(dead_code)] + fn emit_types() -> &'static str { + r#"#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage7Params { + pub field: &'static str, + pub pcs: &'static str, + pub transcript: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage7KernelPlan { + pub symbol: &'static str, + pub relation: &'static str, + pub kind: &'static str, + pub backend: &'static str, + pub abi: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage7TranscriptSqueezePlan { + pub symbol: &'static str, + pub label: &'static str, + pub kind: &'static str, + pub count: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage7TranscriptAbsorbBytesPlan { + pub symbol: &'static str, + pub label: &'static str, + pub payload: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage7ProgramStepPlan { + pub kind: &'static str, + pub symbol: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage7OpeningInputPlan { + pub symbol: &'static str, + pub source_stage: &'static str, + pub source_claim: &'static str, + pub oracle: &'static str, + pub domain: &'static str, + pub point_arity: usize, + pub claim_kind: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage7FieldConstantPlan { + pub symbol: &'static str, + pub field: &'static str, + pub value: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage7FieldExprPlan { + pub symbol: &'static str, + pub kind: &'static str, + pub formula: &'static str, + pub operand_names: &'static [&'static str], + pub operands: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage7SumcheckClaimPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub domain: &'static str, + pub num_rounds: usize, + pub degree: usize, + pub claim: &'static str, + pub kernel: Option<&'static str>, + pub relation: Option<&'static str>, + pub claim_value: &'static str, + pub input_openings: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage7SumcheckBatchPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub proof_slot: &'static str, + pub policy: &'static str, + pub count: usize, + pub ordered_claims: &'static [&'static str], + pub claim_operands: &'static [&'static str], + pub claim_label: &'static str, + pub round_label: &'static str, + pub round_schedule: &'static [usize], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage7SumcheckDriverPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub proof_slot: &'static str, + pub kernel: Option<&'static str>, + pub relation: Option<&'static str>, + pub batch: &'static str, + pub policy: &'static str, + pub round_schedule: &'static [usize], + pub claim_label: &'static str, + pub round_label: &'static str, + pub num_rounds: usize, + pub degree: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage7SumcheckInstanceResultPlan { + pub symbol: &'static str, + pub source: &'static str, + pub claim: &'static str, + pub relation: &'static str, + pub index: usize, + pub point_arity: usize, + pub num_rounds: usize, + pub round_offset: usize, + pub point_order: &'static str, + pub degree: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage7SumcheckEvalPlan { + pub symbol: &'static str, + pub source: &'static str, + pub name: &'static str, + pub index: usize, + pub oracle: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage7PointZeroPlan { + pub symbol: &'static str, + pub field: &'static str, + pub arity: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage7PointSlicePlan { + pub symbol: &'static str, + pub source: &'static str, + pub offset: usize, + pub length: usize, + pub input: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage7PointConcatPlan { + pub symbol: &'static str, + pub layout: &'static str, + pub arity: usize, + pub inputs: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage7OpeningClaimPlan { + pub symbol: &'static str, + pub oracle: &'static str, + pub domain: &'static str, + pub point_arity: usize, + pub claim_kind: &'static str, + pub point_source: &'static str, + pub eval_source: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage7OpeningClaimEqualityPlan { + pub symbol: &'static str, + pub mode: &'static str, + pub lhs: &'static str, + pub rhs: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage7OpeningBatchPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub proof_slot: &'static str, + pub policy: &'static str, + pub count: usize, + pub ordered_claims: &'static [&'static str], + pub claim_operands: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage7CpuProgramPlan { + pub role: &'static str, + pub params: Stage7Params, + pub steps: &'static [Stage7ProgramStepPlan], + pub transcript_squeezes: &'static [Stage7TranscriptSqueezePlan], + pub transcript_absorb_bytes: &'static [Stage7TranscriptAbsorbBytesPlan], + pub opening_inputs: &'static [Stage7OpeningInputPlan], + pub field_constants: &'static [Stage7FieldConstantPlan], + pub field_exprs: &'static [Stage7FieldExprPlan], + pub kernels: &'static [Stage7KernelPlan], + pub claims: &'static [Stage7SumcheckClaimPlan], + pub batches: &'static [Stage7SumcheckBatchPlan], + pub drivers: &'static [Stage7SumcheckDriverPlan], + pub instance_results: &'static [Stage7SumcheckInstanceResultPlan], + pub evals: &'static [Stage7SumcheckEvalPlan], + pub point_zeros: &'static [Stage7PointZeroPlan], + pub point_slices: &'static [Stage7PointSlicePlan], + pub point_concats: &'static [Stage7PointConcatPlan], + pub opening_claims: &'static [Stage7OpeningClaimPlan], + pub opening_equalities: &'static [Stage7OpeningClaimEqualityPlan], + pub opening_batches: &'static [Stage7OpeningBatchPlan], +} +"# + } + + fn emit_verifier_type_aliases() -> &'static str { + r#"pub type Stage7NamedEval = super::common::StageNamedEval; +pub type Stage7SumcheckOutput = super::common::StageSumcheckOutput; +pub type Stage7ChallengeVector = super::common::StageChallengeVector; +pub type Stage7ExecutionArtifacts = super::common::StageExecutionArtifacts; +pub type Stage7Proof = super::common::StageProof; +pub type Stage7OpeningInputValue = super::common::StageOpeningInputValue; + +pub use super::common::{ + FieldConstantPlan as Stage7FieldConstantPlan, FieldExprPlan as Stage7FieldExprPlan, + KernelPlan as Stage7KernelPlan, OpeningBatchPlan as Stage7OpeningBatchPlan, + OpeningClaimEqualityPlan as Stage7OpeningClaimEqualityPlan, + OpeningClaimPlan as Stage7OpeningClaimPlan, OpeningInputPlan as Stage7OpeningInputPlan, + PointConcatPlan as Stage7PointConcatPlan, PointSlicePlan as Stage7PointSlicePlan, + PointZeroPlan as Stage7PointZeroPlan, ProgramStepPlan as Stage7ProgramStepPlan, + StageParams as Stage7Params, StageProgramPlan as Stage7CpuProgramPlan, + SumcheckBatchPlan as Stage7SumcheckBatchPlan, + SumcheckClaimPlan as Stage7SumcheckClaimPlan, SumcheckDriverPlan as Stage7SumcheckDriverPlan, + SumcheckEvalPlan as Stage7SumcheckEvalPlan, + SumcheckInstanceResultPlan as Stage7SumcheckInstanceResultPlan, + TranscriptAbsorbBytesPlan as Stage7TranscriptAbsorbBytesPlan, + TranscriptSqueezePlan as Stage7TranscriptSqueezePlan, +}; +"# + } + + fn emit_verifier_types() -> String { + let mut source = Self::emit_verifier_type_aliases().to_owned(); + source.push_str( + r#" +pub type DefaultStage7Transcript = Blake2bTranscript; +pub type Stage7VerifierProgramPlan = Stage7CpuProgramPlan; + +#[derive(Debug)] +pub enum VerifyStage7Error { + UnexpectedProofCount { expected: usize, got: usize }, + MissingProof { driver: &'static str }, + MissingBatch { driver: &'static str, batch: &'static str }, + MissingClaim { batch: &'static str, claim: &'static str }, + MissingValue { symbol: &'static str }, + InvalidInputLength { input: &'static str, expected: usize, actual: usize }, + InvalidProof { driver: &'static str, reason: &'static str }, + UnsupportedFieldExpr { symbol: &'static str, formula: &'static str }, + UnsupportedRelation { relation: &'static str }, + Sumcheck { driver: &'static str, error: SumcheckError }, +} + +super::common::impl_runtime_plan_error_conversion!(VerifyStage7Error); +"#, + ); + source + } + + fn emit_constants(&self) -> String { + let mut source = self.emit_shared_constants(); + source.push_str(&self.emit_kernel_constants()); + source.push_str(&self.emit_sumcheck_claim_constants()); + source.push_str(&self.emit_sumcheck_batch_constants()); + source.push_str(&self.emit_sumcheck_driver_constants()); + source.push_str(&self.emit_tail_constants()); + push_format( + &mut source, + format_args!( + "pub const STAGE7_PROGRAM: {} = Stage7CpuProgramPlan {{\n\ + \x20 role: {},\n\ + \x20 params: STAGE7_PARAMS,\n\ + \x20 steps: STAGE7_PROGRAM_STEPS,\n\ + \x20 transcript_squeezes: STAGE7_TRANSCRIPT_SQUEEZES,\n\ + \x20 transcript_absorb_bytes: STAGE7_TRANSCRIPT_ABSORB_BYTES,\n\ + \x20 opening_inputs: STAGE7_OPENING_INPUTS,\n\ + \x20 field_constants: STAGE7_FIELD_CONSTANTS,\n\ + \x20 field_exprs: STAGE7_FIELD_EXPRS,\n\ + \x20 kernels: STAGE7_KERNELS,\n\ + \x20 claims: STAGE7_SUMCHECK_CLAIMS,\n\ + \x20 batches: STAGE7_SUMCHECK_BATCHES,\n\ + \x20 drivers: STAGE7_SUMCHECK_DRIVERS,\n\ + \x20 instance_results: STAGE7_SUMCHECK_INSTANCE_RESULTS,\n\ + \x20 evals: STAGE7_SUMCHECK_EVALS,\n\ + \x20 point_zeros: STAGE7_POINT_ZEROS,\n\ + \x20 point_slices: STAGE7_POINT_SLICES,\n\ + \x20 point_concats: STAGE7_POINT_CONCATS,\n\ + \x20 opening_claims: STAGE7_OPENING_CLAIMS,\n\ + \x20 opening_equalities: STAGE7_OPENING_EQUALITIES,\n\ + \x20 opening_batches: STAGE7_OPENING_BATCHES,\n\ + }};\n", + self.program_plan_type(), + rust_str(self.role_label()) + ), + ); + source + } + + fn emit_shared_constants(&self) -> String { + let mut source = String::new(); + push_format( + &mut source, + format_args!( + "pub const STAGE7_PARAMS: Stage7Params = Stage7Params {{\n\ + \x20 field: {},\n\ + \x20 pcs: {},\n\ + \x20 transcript: {},\n\ + }};\n", + rust_str(&self.params.field), + rust_str(&self.params.pcs), + rust_str(&self.params.transcript) + ), + ); + source.push_str(&self.emit_program_step_constants()); + source.push_str(&self.emit_transcript_squeeze_constants()); + source.push_str(&self.emit_transcript_absorb_bytes_constants()); + source.push_str(&self.emit_opening_input_constants()); + source.push_str(&self.emit_field_constant_constants()); + source.push_str(&self.emit_field_expr_constants()); + source + } + + fn emit_program_step_constants(&self) -> String { + let steps = self + .steps + .iter() + .map(|step| { + format!( + " Stage7ProgramStepPlan {{ kind: {}, symbol: {} }},", + rust_str(&step.kind), + rust_str(&step.symbol), + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE7_PROGRAM_STEPS: &[Stage7ProgramStepPlan] = &[\n{steps}\n];\n\n") + } + + fn emit_transcript_squeeze_constants(&self) -> String { + let squeezes = self + .transcript_squeezes + .iter() + .map(|squeeze| { + format!( + " Stage7TranscriptSqueezePlan {{ symbol: {}, label: {}, kind: {}, count: {} }},", + rust_str(&squeeze.symbol), + rust_str(&squeeze.label), + rust_str(&squeeze.kind), + squeeze.count, + ) + }) + .collect::>() + .join("\n"); + format!( + "pub const STAGE7_TRANSCRIPT_SQUEEZES: &[Stage7TranscriptSqueezePlan] = &[\n{squeezes}\n];\n\n" + ) + } + + fn emit_transcript_absorb_bytes_constants(&self) -> String { + let absorbs = self + .transcript_absorb_bytes + .iter() + .map(|absorb| { + format!( + " Stage7TranscriptAbsorbBytesPlan {{ symbol: {}, label: {}, payload: {} }},", + rust_str(&absorb.symbol), + rust_str(&absorb.label), + rust_str(&absorb.payload), + ) + }) + .collect::>() + .join("\n"); + format!( + "pub const STAGE7_TRANSCRIPT_ABSORB_BYTES: &[Stage7TranscriptAbsorbBytesPlan] = &[\n{absorbs}\n];\n\n" + ) + } + + fn emit_opening_input_constants(&self) -> String { + let inputs = self + .opening_inputs + .iter() + .map(|input| { + format!( + " Stage7OpeningInputPlan {{ symbol: {}, source_stage: {}, source_claim: {}, oracle: {}, domain: {}, point_arity: {}, claim_kind: {} }},", + rust_str(&input.symbol), + rust_str(&input.source_stage), + rust_str(&input.source_claim), + rust_str(&input.oracle), + rust_str(&input.domain), + input.point_arity, + rust_str(&input.claim_kind) + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE7_OPENING_INPUTS: &[Stage7OpeningInputPlan] = &[\n{inputs}\n];\n\n") + } + + fn emit_field_constant_constants(&self) -> String { + let constants = self + .field_constants + .iter() + .map(|constant| { + format!( + " Stage7FieldConstantPlan {{ symbol: {}, field: {}, value: {} }},", + rust_str(&constant.symbol), + rust_str(&constant.field), + constant.value + ) + }) + .collect::>() + .join("\n"); + format!( + "pub const STAGE7_FIELD_CONSTANTS: &[Stage7FieldConstantPlan] = &[\n{constants}\n];\n\n" + ) + } + + fn emit_field_expr_constants(&self) -> String { + if self.role == Role::Verifier { + let rows = self + .field_exprs + .chunks(8) + .map(|chunk| { + let exprs = chunk + .iter() + .map(|expr| { + format!( + "stage7_field_expr!({}, {}, {})", + rust_str(&expr.symbol), + rust_str(&expr.formula), + rust_str(&expr.operands.join("|")) + ) + }) + .collect::>() + .join(", "); + format!(" {exprs},") + }) + .collect::>() + .join("\n"); + return format!( + "macro_rules! stage7_field_expr {{\n ($symbol:literal, $formula:literal, $operands:literal) => {{\n Stage7FieldExprPlan {{ symbol: $symbol, kind: \"op\", formula: $formula, operands: $operands }}\n }};\n}}\n\n#[rustfmt::skip]\npub const STAGE7_FIELD_EXPRS: &[Stage7FieldExprPlan] = &[\n{rows}\n];\n" + ); + } + + let mut source = String::new(); + let mut arrays = Vec::new(); + let mut array_refs = Vec::new(); + for (index, expr) in self.field_exprs.iter().enumerate() { + let operands = intern_str_array( + &mut source, + &mut arrays, + "STAGE7_FIELD_EXPR_OPERANDS", + &expr.operands, + ); + let operand_names = intern_str_array( + &mut source, + &mut arrays, + "STAGE7_FIELD_EXPR_OPERANDS", + &expr.operand_names, + ); + array_refs.push((index, operand_names, operands)); + } + let exprs = self + .field_exprs + .iter() + .enumerate() + .map(|(index, expr)| { + let (_, operand_names, operands) = &array_refs[index]; + format!( + " Stage7FieldExprPlan {{ symbol: {}, kind: {}, formula: {}, operand_names: {operand_names}, operands: {operands} }},", + rust_str(&expr.symbol), + rust_str(&expr.kind), + rust_str(&expr.formula) + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE7_FIELD_EXPRS: &[Stage7FieldExprPlan] = &[\n{exprs}\n];\n" + ), + ); + source + } + + fn emit_kernel_constants(&self) -> String { + let kernels = self + .kernels + .iter() + .map(|kernel| { + format!( + " Stage7KernelPlan {{ symbol: {}, relation: {}, kind: {}, backend: {}, abi: {} }},", + rust_str(&kernel.symbol), + rust_str(&kernel.relation), + rust_str(&kernel.kind), + rust_str(&kernel.backend), + rust_str(&kernel.abi) + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE7_KERNELS: &[Stage7KernelPlan] = &[\n{kernels}\n];\n\n") + } + + fn emit_sumcheck_claim_constants(&self) -> String { + if self.role == Role::Verifier { + let claims = self + .claims + .iter() + .map(|claim| { + format!( + " Stage7SumcheckClaimPlan {{ symbol: {}, stage: {}, domain: {}, num_rounds: {}, degree: {}, claim: {}, kernel: {}, relation: {}, claim_value: {}, input_openings: {} }},", + rust_str(&claim.symbol), + rust_str(&claim.stage), + rust_str(&claim.domain), + claim.num_rounds, + claim.degree, + rust_str(&claim.claim), + rust_option_str(claim.kernel.as_deref()), + rust_option_str(claim.relation.as_deref()), + rust_str(&claim.claim_value), + rust_str(&claim.input_openings.join("|")) + ) + }) + .collect::>() + .join("\n"); + return format!( + "pub const STAGE7_SUMCHECK_CLAIMS: &[Stage7SumcheckClaimPlan] = &[\n{claims}\n];\n" + ); + } + + let mut source = String::new(); + for (index, claim) in self.claims.iter().enumerate() { + source.push_str(&emit_str_array( + &format!("STAGE7_SUMCHECK_CLAIM_{index}_INPUT_OPENINGS"), + &claim.input_openings, + )); + } + let claims = self + .claims + .iter() + .enumerate() + .map(|(index, claim)| { + format!( + " Stage7SumcheckClaimPlan {{ symbol: {}, stage: {}, domain: {}, num_rounds: {}, degree: {}, claim: {}, kernel: {}, relation: {}, claim_value: {}, input_openings: STAGE7_SUMCHECK_CLAIM_{index}_INPUT_OPENINGS }},", + rust_str(&claim.symbol), + rust_str(&claim.stage), + rust_str(&claim.domain), + claim.num_rounds, + claim.degree, + rust_str(&claim.claim), + rust_option_str(claim.kernel.as_deref()), + rust_option_str(claim.relation.as_deref()), + rust_str(&claim.claim_value) + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE7_SUMCHECK_CLAIMS: &[Stage7SumcheckClaimPlan] = &[\n{claims}\n];\n" + ), + ); + source + } + + fn emit_sumcheck_batch_constants(&self) -> String { + if self.role == Role::Verifier { + let mut source = String::new(); + for (index, batch) in self.batches.iter().enumerate() { + source.push_str(&emit_usize_array( + &format!("STAGE7_SUMCHECK_BATCH_{index}_ROUND_SCHEDULE"), + &batch.round_schedule, + )); + } + let batches = self + .batches + .iter() + .enumerate() + .map(|(index, batch)| { + format!( + " Stage7SumcheckBatchPlan {{ symbol: {}, stage: {}, proof_slot: {}, policy: {}, count: {}, ordered_claims: {}, claim_operands: {}, claim_label: {}, round_label: {}, round_schedule: STAGE7_SUMCHECK_BATCH_{index}_ROUND_SCHEDULE }},", + rust_str(&batch.symbol), + rust_str(&batch.stage), + rust_str(&batch.proof_slot), + rust_str(&batch.policy), + batch.count, + rust_str(&batch.ordered_claims.join("|")), + rust_str(&batch.claim_operands.join("|")), + rust_str(&batch.claim_label), + rust_str(&batch.round_label) + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE7_SUMCHECK_BATCHES: &[Stage7SumcheckBatchPlan] = &[\n{batches}\n];\n" + ), + ); + return source; + } + + let mut source = String::new(); + for (index, batch) in self.batches.iter().enumerate() { + source.push_str(&emit_str_array( + &format!("STAGE7_SUMCHECK_BATCH_{index}_ORDERED_CLAIMS"), + &batch.ordered_claims, + )); + source.push_str(&emit_str_array( + &format!("STAGE7_SUMCHECK_BATCH_{index}_CLAIM_OPERANDS"), + &batch.claim_operands, + )); + source.push_str(&emit_usize_array( + &format!("STAGE7_SUMCHECK_BATCH_{index}_ROUND_SCHEDULE"), + &batch.round_schedule, + )); + } + let batches = self + .batches + .iter() + .enumerate() + .map(|(index, batch)| { + format!( + " Stage7SumcheckBatchPlan {{ symbol: {}, stage: {}, proof_slot: {}, policy: {}, count: {}, ordered_claims: STAGE7_SUMCHECK_BATCH_{index}_ORDERED_CLAIMS, claim_operands: STAGE7_SUMCHECK_BATCH_{index}_CLAIM_OPERANDS, claim_label: {}, round_label: {}, round_schedule: STAGE7_SUMCHECK_BATCH_{index}_ROUND_SCHEDULE }},", + rust_str(&batch.symbol), + rust_str(&batch.stage), + rust_str(&batch.proof_slot), + rust_str(&batch.policy), + batch.count, + rust_str(&batch.claim_label), + rust_str(&batch.round_label) + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE7_SUMCHECK_BATCHES: &[Stage7SumcheckBatchPlan] = &[\n{batches}\n];\n" + ), + ); + source + } + + fn emit_sumcheck_driver_constants(&self) -> String { + let mut source = String::new(); + for (index, driver) in self.drivers.iter().enumerate() { + source.push_str(&emit_usize_array( + &format!("STAGE7_SUMCHECK_DRIVER_{index}_ROUND_SCHEDULE"), + &driver.round_schedule, + )); + } + let drivers = self + .drivers + .iter() + .enumerate() + .map(|(index, driver)| { + format!( + " Stage7SumcheckDriverPlan {{ symbol: {}, stage: {}, proof_slot: {}, kernel: {}, relation: {}, batch: {}, policy: {}, round_schedule: STAGE7_SUMCHECK_DRIVER_{index}_ROUND_SCHEDULE, claim_label: {}, round_label: {}, num_rounds: {}, degree: {} }},", + rust_str(&driver.symbol), + rust_str(&driver.stage), + rust_str(&driver.proof_slot), + rust_option_str(driver.kernel.as_deref()), + rust_option_str(driver.relation.as_deref()), + rust_str(&driver.batch), + rust_str(&driver.policy), + rust_str(&driver.claim_label), + rust_str(&driver.round_label), + driver.num_rounds, + driver.degree + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE7_SUMCHECK_DRIVERS: &[Stage7SumcheckDriverPlan] = &[\n{drivers}\n];\n" + ), + ); + source + } + + fn emit_tail_constants(&self) -> String { + let mut source = String::new(); + source.push_str(&self.emit_sumcheck_instance_result_constants()); + source.push_str(&self.emit_sumcheck_eval_constants()); + source.push_str(&self.emit_point_zero_constants()); + source.push_str(&self.emit_point_slice_constants()); + source.push_str(&self.emit_point_concat_constants()); + source.push_str(&self.emit_opening_claim_constants()); + source.push_str(&self.emit_opening_claim_equality_constants()); + source.push_str(&self.emit_opening_batch_constants()); + source + } + + fn emit_sumcheck_instance_result_constants(&self) -> String { + let instances = self + .instance_results + .iter() + .map(|instance| { + format!( + " Stage7SumcheckInstanceResultPlan {{ symbol: {}, source: {}, claim: {}, relation: {}, index: {}, point_arity: {}, num_rounds: {}, round_offset: {}, point_order: {}, degree: {} }},", + rust_str(&instance.symbol), + rust_str(&instance.source), + rust_str(&instance.claim), + rust_str(&instance.relation), + instance.index, + instance.point_arity, + instance.num_rounds, + instance.round_offset, + rust_str(&instance.point_order), + instance.degree + ) + }) + .collect::>() + .join("\n"); + format!( + "pub const STAGE7_SUMCHECK_INSTANCE_RESULTS: &[Stage7SumcheckInstanceResultPlan] = &[\n{instances}\n];\n\n" + ) + } + + fn emit_sumcheck_eval_constants(&self) -> String { + let rows = self + .evals + .chunks(4) + .map(|chunk| { + let evals = chunk + .iter() + .map(|eval| { + format!( + "stage7_sumcheck_eval!({}, {}, {}, {}, {})", + rust_str(&eval.symbol), + rust_str(&eval.source), + rust_str(&eval.name), + eval.index, + rust_str(&eval.oracle) + ) + }) + .collect::>() + .join(", "); + format!(" {evals},") + }) + .collect::>() + .join("\n"); + format!( + "macro_rules! stage7_sumcheck_eval {{\n ($symbol:literal, $source:literal, $name:literal, $index:literal, $oracle:literal) => {{\n Stage7SumcheckEvalPlan {{ symbol: $symbol, source: $source, name: $name, index: $index, oracle: $oracle }}\n }};\n}}\n\n#[rustfmt::skip]\npub const STAGE7_SUMCHECK_EVALS: &[Stage7SumcheckEvalPlan] = &[\n{rows}\n];\n\n" + ) + } + + fn emit_point_zero_constants(&self) -> String { + let zeros = self + .point_zeros + .iter() + .map(|zero| { + format!( + " Stage7PointZeroPlan {{ symbol: {}, field: {}, arity: {} }},", + rust_str(&zero.symbol), + rust_str(&zero.field), + zero.arity + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE7_POINT_ZEROS: &[Stage7PointZeroPlan] = &[\n{zeros}\n];\n\n") + } + + fn emit_point_slice_constants(&self) -> String { + let slices = self + .point_slices + .iter() + .map(|slice| { + format!( + " Stage7PointSlicePlan {{ symbol: {}, source: {}, offset: {}, length: {}, input: {} }},", + rust_str(&slice.symbol), + rust_str(&slice.source), + slice.offset, + slice.length, + rust_str(&slice.input) + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE7_POINT_SLICES: &[Stage7PointSlicePlan] = &[\n{slices}\n];\n\n") + } + + fn emit_point_concat_constants(&self) -> String { + if self.role == Role::Verifier { + let concats = self + .point_concats + .iter() + .map(|concat| { + format!( + " Stage7PointConcatPlan {{ symbol: {}, layout: {}, arity: {}, inputs: {} }},", + rust_str(&concat.symbol), + rust_str(&concat.layout), + concat.arity, + rust_str(&concat.inputs.join("|")) + ) + }) + .collect::>() + .join("\n"); + return format!( + "pub const STAGE7_POINT_CONCATS: &[Stage7PointConcatPlan] = &[\n{concats}\n];\n" + ); + } + + let mut source = String::new(); + for (index, concat) in self.point_concats.iter().enumerate() { + source.push_str(&emit_str_array( + &format!("STAGE7_POINT_CONCAT_{index}_INPUTS"), + &concat.inputs, + )); + } + let concats = self + .point_concats + .iter() + .enumerate() + .map(|(index, concat)| { + format!( + " Stage7PointConcatPlan {{ symbol: {}, layout: {}, arity: {}, inputs: STAGE7_POINT_CONCAT_{index}_INPUTS }},", + rust_str(&concat.symbol), + rust_str(&concat.layout), + concat.arity + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE7_POINT_CONCATS: &[Stage7PointConcatPlan] = &[\n{concats}\n];\n" + ), + ); + source + } + + fn emit_opening_claim_constants(&self) -> String { + let claims = self + .opening_claims + .iter() + .map(|claim| { + format!( + " Stage7OpeningClaimPlan {{ symbol: {}, oracle: {}, domain: {}, point_arity: {}, claim_kind: {}, point_source: {}, eval_source: {} }},", + rust_str(&claim.symbol), + rust_str(&claim.oracle), + rust_str(&claim.domain), + claim.point_arity, + rust_str(&claim.claim_kind), + rust_str(&claim.point_source), + rust_str(&claim.eval_source) + ) + }) + .collect::>() + .join("\n"); + format!("pub const STAGE7_OPENING_CLAIMS: &[Stage7OpeningClaimPlan] = &[\n{claims}\n];\n\n") + } + + fn emit_opening_claim_equality_constants(&self) -> String { + let equalities = self + .opening_equalities + .iter() + .map(|equality| { + format!( + " Stage7OpeningClaimEqualityPlan {{ symbol: {}, mode: {}, lhs: {}, rhs: {} }},", + rust_str(&equality.symbol), + rust_str(&equality.mode), + rust_str(&equality.lhs), + rust_str(&equality.rhs) + ) + }) + .collect::>() + .join("\n"); + format!( + "pub const STAGE7_OPENING_EQUALITIES: &[Stage7OpeningClaimEqualityPlan] = &[\n{equalities}\n];\n\n" + ) + } + + fn emit_opening_batch_constants(&self) -> String { + if self.role == Role::Verifier { + let batches = self + .opening_batches + .iter() + .map(|batch| { + format!( + " Stage7OpeningBatchPlan {{ symbol: {}, stage: {}, proof_slot: {}, policy: {}, count: {}, ordered_claims: {}, claim_operands: {} }},", + rust_str(&batch.symbol), + rust_str(&batch.stage), + rust_str(&batch.proof_slot), + rust_str(&batch.policy), + batch.count, + rust_str(&batch.ordered_claims.join("|")), + rust_str(&batch.claim_operands.join("|")) + ) + }) + .collect::>() + .join("\n"); + return format!( + "pub const STAGE7_OPENING_BATCHES: &[Stage7OpeningBatchPlan] = &[\n{batches}\n];\n" + ); + } + + let mut source = String::new(); + for (index, batch) in self.opening_batches.iter().enumerate() { + source.push_str(&emit_str_array( + &format!("STAGE7_OPENING_BATCH_{index}_ORDERED_CLAIMS"), + &batch.ordered_claims, + )); + source.push_str(&emit_str_array( + &format!("STAGE7_OPENING_BATCH_{index}_CLAIM_OPERANDS"), + &batch.claim_operands, + )); + } + let batches = self + .opening_batches + .iter() + .enumerate() + .map(|(index, batch)| { + format!( + " Stage7OpeningBatchPlan {{ symbol: {}, stage: {}, proof_slot: {}, policy: {}, count: {}, ordered_claims: STAGE7_OPENING_BATCH_{index}_ORDERED_CLAIMS, claim_operands: STAGE7_OPENING_BATCH_{index}_CLAIM_OPERANDS }},", + rust_str(&batch.symbol), + rust_str(&batch.stage), + rust_str(&batch.proof_slot), + rust_str(&batch.policy), + batch.count + ) + }) + .collect::>() + .join("\n"); + push_format( + &mut source, + format_args!( + "pub const STAGE7_OPENING_BATCHES: &[Stage7OpeningBatchPlan] = &[\n{batches}\n];\n" + ), + ); + source + } + + fn emit_entrypoint(&self) -> &'static str { + match self.role { + Role::Prover => { + "pub fn execute_stage7_prover(\n\ + \x20 executor: &mut E,\n\ + \x20 transcript: &mut T,\n\ + ) -> Result, Stage7KernelError>\n\ + where\n\ + \x20 E: Stage7KernelExecutor,\n\ + \x20 T: Transcript,\n\ + {\n\ + \x20 execute_stage7_prover_with_program(&STAGE7_PROGRAM, executor, transcript)\n\ + }\n\ + \n\ + pub fn execute_stage7_prover_with_program(\n\ + \x20 program: &'static Stage7CpuProgramPlan,\n\ + \x20 executor: &mut E,\n\ + \x20 transcript: &mut T,\n\ + ) -> Result, Stage7KernelError>\n\ + where\n\ + \x20 E: Stage7KernelExecutor,\n\ + \x20 T: Transcript,\n\ + {\n\ + \x20 execute_stage7_program(program, Stage7ExecutionMode::Prover, executor, transcript)\n\ + }\n" + } + Role::Verifier => { + r#"pub fn verify_stage7( + proof: &Stage7Proof, + opening_inputs: &[Stage7OpeningInputValue], + transcript: &mut T, +) -> Result, VerifyStage7Error> +where + T: Transcript, +{ + verify_stage7_with_program(&STAGE7_PROGRAM, proof, opening_inputs, transcript) +} + +pub fn verify_stage7_with_program( + program: &'static Stage7VerifierProgramPlan, + proof: &Stage7Proof, + opening_inputs: &[Stage7OpeningInputValue], + transcript: &mut T, +) -> Result, VerifyStage7Error> +where + T: Transcript, +{ + if proof.sumchecks.len() != program.drivers.len() { + return Err(VerifyStage7Error::UnexpectedProofCount { + expected: program.drivers.len(), + got: proof.sumchecks.len(), + }); + } + let mut store = + super::common::ValueStore::with_opening_inputs(opening_inputs, program.opening_inputs)?; + store.seed_constants(program.field_constants); + store.seed_point_zeros(program.point_zeros); + let mut artifacts = Stage7ExecutionArtifacts::default(); + for step in program.steps { + match step.kind { + "transcript_squeeze" => { + let squeeze = + find_plan(program.transcript_squeezes, step.symbol).ok_or(VerifyStage7Error::MissingValue { + symbol: step.symbol, + })?; + verify_stage7_squeeze(program, squeeze, &mut store, transcript, &mut artifacts)?; + } + "transcript_absorb_bytes" => { + let absorb = find_plan(program.transcript_absorb_bytes, step.symbol).ok_or( + VerifyStage7Error::MissingValue { + symbol: step.symbol, + }, + )?; + absorb_stage7_bytes(absorb, transcript); + } + "sumcheck_driver" => { + let driver = + find_plan(program.drivers, step.symbol).ok_or(VerifyStage7Error::MissingProof { + driver: step.symbol, + })?; + verify_stage7_driver( + program, + driver, + proof, + &mut store, + transcript, + &mut artifacts, + )?; + } + _ => { + return Err(VerifyStage7Error::InvalidProof { + driver: step.symbol, + reason: "unsupported stage7 program step", + }); + } + } + } + artifacts + .opening_batches + .extend(program.opening_batches.iter()); + Ok(artifacts) +} + +pub fn stage7_verifier_program() -> &'static Stage7VerifierProgramPlan { + &STAGE7_PROGRAM +} + +fn verify_stage7_squeeze( + program: &'static Stage7VerifierProgramPlan, + squeeze: &'static Stage7TranscriptSqueezePlan, + store: &mut super::common::ValueStore, + transcript: &mut T, + artifacts: &mut Stage7ExecutionArtifacts, +) -> Result<(), VerifyStage7Error> +where + T: Transcript, +{ + let values = transcript.challenge_vector(squeeze.count); + store.observe_challenge_vector(squeeze, &values, |input, expected, actual| { + VerifyStage7Error::InvalidInputLength { + input, + expected, + actual, + } + })?; + store + .evaluate_available_field_exprs(program.field_exprs, super::common::evaluate_field_expr) + .map_err(VerifyStage7Error::from)?; + artifacts.challenge_vectors.push(Stage7ChallengeVector { + symbol: squeeze.symbol, + values, + }); + Ok(()) +} + +fn absorb_stage7_bytes(absorb: &'static Stage7TranscriptAbsorbBytesPlan, transcript: &mut T) +where + T: Transcript, +{ + transcript.append(&LabelWithCount( + absorb.label.as_bytes(), + absorb.payload.len() as u64, + )); + transcript.append_bytes(absorb.payload.as_bytes()); +} + +fn verify_stage7_driver( + program: &'static Stage7VerifierProgramPlan, + driver: &'static Stage7SumcheckDriverPlan, + proof: &Stage7Proof, + store: &mut super::common::ValueStore, + transcript: &mut T, + artifacts: &mut Stage7ExecutionArtifacts, +) -> Result<(), VerifyStage7Error> +where + T: Transcript, +{ + let proof = proof + .sumchecks + .get(artifacts.sumchecks.len()) + .ok_or(VerifyStage7Error::MissingProof { + driver: driver.symbol, + })?; + let relation = driver.relation.unwrap_or(""); + let output = match relation { + "jolt.stage7.batched" => { + verify_batched_stage7(program, driver, proof, store, transcript)? + } + _ => return Err(VerifyStage7Error::UnsupportedRelation { relation }), + }; + artifacts.sumchecks.push(output); + Ok(()) +} + +fn verify_batched_stage7( + program: &'static Stage7VerifierProgramPlan, + driver: &'static Stage7SumcheckDriverPlan, + proof: &Stage7SumcheckOutput, + store: &mut super::common::ValueStore, + transcript: &mut T, +) -> Result, VerifyStage7Error> +where + T: Transcript, +{ + super::common::verify_batched_sumcheck( + driver, + proof, + program.claims, + program.batches, + program.field_exprs, + program.opening_inputs, + program.opening_claims, + program.opening_batches, + store, + transcript, + |store, evals, point, batching_coeffs| { + expected_batched_output_claim(program, driver, store, evals, point, batching_coeffs) + }, + |store, verified| observe_stage7_sumcheck_output(program, store, verified), + |driver, error| VerifyStage7Error::Sumcheck { driver, error }, + ) +} + +fn observe_stage7_sumcheck_output( + program: &'static Stage7VerifierProgramPlan, + store: &mut super::common::ValueStore, + output: &Stage7SumcheckOutput, +) -> Result<(), VerifyStage7Error> { + store.observe_sumcheck_output( + program.instance_results, + program.evals, + output, + |instance, mut point| { + match instance.point_order { + "as_is" => {} + "reverse" => point.reverse(), + "bytecode_read_raf" => point = normalize_bytecode_read_raf_point(&point, stage7_trace_rounds(program)?, "stage7.bytecode_read_raf.point")?, + "stage7_booleanity" => {} + "instruction_read_raf" => point = normalize_instruction_read_raf_point(&point, "stage7.instruction_read_raf.point")?, + _ => { + return Err(VerifyStage7Error::InvalidProof { + driver: output.driver, + reason: "unsupported point order", + }); + } + } + Ok(point) + }, + |input, expected, actual| VerifyStage7Error::InvalidInputLength { + input, + expected, + actual, + }, + |symbol| VerifyStage7Error::MissingValue { symbol }, + )?; + store.evaluate_available_points( + program.point_slices, + program.point_concats, + |input, expected, actual| VerifyStage7Error::InvalidInputLength { + input, + expected, + actual, + }, + )?; + store + .evaluate_available_field_exprs(program.field_exprs, super::common::evaluate_field_expr) + .map_err(VerifyStage7Error::from)?; + store.verify_opening_equalities( + program.opening_equalities, + |driver, reason| VerifyStage7Error::InvalidProof { driver, reason }, + |symbol| VerifyStage7Error::MissingValue { symbol }, + ) +} + +fn expected_batched_output_claim( + program: &'static Stage7VerifierProgramPlan, + driver: &'static Stage7SumcheckDriverPlan, + store: &super::common::ValueStore, + evals: &[Stage7NamedEval], + point: &[Fr], + batching_coeffs: &[Fr], +) -> Result { + let batch = find_batch(program.batches, driver.symbol, driver.batch)?; + let claims = batch_claims(program.claims, batch)?; + let mut expected = Fr::from_u64(0); + for (claim, coefficient) in claims.iter().zip(batching_coeffs) { + let instance = program + .instance_results + .iter() + .find(|instance| instance.claim == claim.symbol && instance.source == driver.symbol) + .ok_or(VerifyStage7Error::MissingClaim { + batch: batch.symbol, + claim: claim.symbol, + })?; + let local_point = point + .get(instance.round_offset..instance.round_offset + instance.num_rounds) + .ok_or(VerifyStage7Error::InvalidInputLength { + input: instance.symbol, + expected: instance.round_offset + instance.num_rounds, + actual: point.len(), + })?; + let relation = claim.relation.unwrap_or(""); + let value = match relation { + "jolt.stage7.hamming_weight_claim_reduction" => { + expected_hamming_weight_claim_reduction(program, driver, store, evals, local_point)? + } + _ => return Err(VerifyStage7Error::UnsupportedRelation { relation }), + }; + expected += *coefficient * value; + } + Ok(expected) +} + +fn expected_hamming_weight_claim_reduction( + program: &'static Stage7VerifierProgramPlan, + driver: &'static Stage7SumcheckDriverPlan, + store: &super::common::ValueStore, + evals: &[Stage7NamedEval], + local_point: &[Fr], +) -> Result { + let rho_rev = reverse_slice(local_point); + let booleanity_point = super::common::store_point(store, "stage7.input.stage6.booleanity.InstructionRa_0")?; + let r_addr_bool = + booleanity_point + .get(..local_point.len()) + .ok_or(VerifyStage7Error::InvalidInputLength { + input: "stage7.input.stage6.booleanity.InstructionRa_0", + expected: local_point.len(), + actual: booleanity_point.len(), + })?; + let eq_bool = EqPolynomial::::mle(&rho_rev, r_addr_bool); + let gamma = super::common::store_scalar(store, "stage7.hamming_weight_claim_reduction.gamma")?; + let mut gamma_power = Fr::from_u64(1); + let mut expected = Fr::from_u64(0); + let mut eval_plans = program + .evals + .iter() + .filter(|eval| eval.source == driver.symbol) + .collect::>(); + eval_plans.sort_by_key(|eval| eval.index); + for eval_plan in eval_plans { + let g_i = eval_by_name(evals, eval_plan.name)?; + let virt_point = + stage7_virtualization_point(store, eval_plan.oracle, local_point.len())?; + let eq_virt = EqPolynomial::::mle(&rho_rev, virt_point); + expected += g_i * (gamma_power + gamma_power * gamma * eq_bool + + gamma_power * gamma.square() * eq_virt); + gamma_power *= gamma; + gamma_power *= gamma; + gamma_power *= gamma; + } + Ok(expected) +} + +fn stage7_virtualization_point<'a>( + store: &'a super::common::ValueStore, + oracle: &str, + log_k_chunk: usize, +) -> Result<&'a [Fr], VerifyStage7Error> { + let symbol = if oracle.starts_with("InstructionRa_") { + format!("stage7.input.stage6.instruction_ra_virtual.{oracle}") + } else if oracle.starts_with("BytecodeRa_") { + format!("stage7.input.stage6.bytecode_read_raf.{oracle}") + } else if oracle.starts_with("RamRa_") { + format!("stage7.input.stage6.ram_ra_virtual.{oracle}") + } else { + return Err(VerifyStage7Error::MissingValue { + symbol: "stage7.hamming_weight_claim_reduction.oracle", + }); + }; + let point = store.try_point(&symbol).ok_or(VerifyStage7Error::MissingValue { + symbol: "stage7.hamming_weight_claim_reduction.virtualization_point", + })?; + point + .get(..log_k_chunk) + .ok_or(VerifyStage7Error::InvalidInputLength { + input: "stage7.hamming_weight_claim_reduction.virtualization_point", + expected: log_k_chunk, + actual: point.len(), + }) +} + +fn stage7_trace_rounds( + program: &'static Stage7VerifierProgramPlan, +) -> Result { + program + .instance_results + .iter() + .find(|instance| instance.relation == "jolt.stage7.hamming_booleanity") + .map(|instance| instance.num_rounds) + .ok_or(VerifyStage7Error::MissingValue { + symbol: "stage7.hamming_booleanity.instance", + }) +} +"# + } + } + } + + fn role_label(&self) -> &'static str { + match self.role { + Role::Prover => "prover", + Role::Verifier => "verifier", + } + } + + fn program_plan_type(&self) -> &'static str { + match self.role { + Role::Prover => "Stage7CpuProgramPlan", + Role::Verifier => "Stage7VerifierProgramPlan", + } + } +} + +fn require_supported_symbol(kind: &str, actual: &str, expected: &str) -> Result<(), EmitError> { + if actual == expected { + Ok(()) + } else { + Err(EmitError::new(format!( + "unsupported {kind} @{actual}; expected @{expected}" + ))) + } +} + +fn emit_str_array(name: &str, values: &[String]) -> String { + if values.is_empty() { + return format!("pub const {name}: &[&str] = &[];\n\n"); + } + if let [value] = values { + return format!("pub const {name}: &[&str] = &[{}];\n\n", rust_str(value)); + } + let entries = values + .iter() + .map(|value| format!(" {},", rust_str(value))) + .collect::>() + .join("\n"); + format!("pub const {name}: &[&str] = &[\n{entries}\n];\n\n") +} + +fn emit_usize_array(name: &str, values: &[usize]) -> String { + let entries = values + .iter() + .map(|value| format!(" {value},")) + .collect::>() + .join("\n"); + format!("pub const {name}: &[usize] = &[\n{entries}\n];\n\n") +} + +fn intern_str_array( + source: &mut String, + arrays: &mut Vec<(Vec, String)>, + name_prefix: &str, + values: &[String], +) -> String { + if let Some((_, name)) = arrays + .iter() + .find(|(existing, _)| existing.as_slice() == values) + { + return name.clone(); + } + let name = format!("{name_prefix}_{}", arrays.len()); + source.push_str(&emit_str_array(&name, values)); + arrays.push((values.to_vec(), name.clone())); + name +} + +fn rust_str(value: &str) -> String { + format!("{value:?}") +} + +fn rust_option_str(value: Option<&str>) -> String { + value.map_or_else( + || "None".to_owned(), + |value| format!("Some({})", rust_str(value)), + ) +} + +fn verify_count(kind: &str, symbol: &str, expected: usize, actual: usize) -> Result<(), EmitError> { + if expected == actual { + Ok(()) + } else { + Err(EmitError::new(format!( + "{kind} @{symbol} count mismatch: expected {expected}, got {actual}" + ))) + } +} + +fn symbols<'a>(values: impl Iterator) -> BTreeSet { + values.cloned().collect() +} + +fn string_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .ok() + .and_then(string_attribute_value) + .ok_or_else(|| attr_error(operation, attr, "string")) +} + +fn symbol_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .ok() + .and_then(symbol_attribute_value) + .ok_or_else(|| attr_error(operation, attr, "symbol")) +} + +fn symbol_array_attr( + operation: OperationRef<'_, '_>, + attr: &str, +) -> Result, EmitError> { + let attribute = operation + .attribute(attr) + .map(|attribute| attribute.to_string()) + .ok() + .ok_or_else(|| attr_error(operation, attr, "symbol array"))?; + parse_symbol_array(&attribute).ok_or_else(|| attr_error(operation, attr, "symbol array")) +} + +fn parse_symbol_array(attribute: &str) -> Option> { + let inner = attribute.strip_prefix('[')?.strip_suffix(']')?.trim(); + if inner.is_empty() { + return Some(Vec::new()); + } + inner + .split(',') + .map(|item| item.trim().strip_prefix('@').map(ToOwned::to_owned)) + .collect() +} + +fn int_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .map(parse_integer_attr) + .ok() + .flatten() + .ok_or_else(|| attr_error(operation, attr, "integer")) +} + +fn parse_integer_attr(attribute: Attribute<'_>) -> Option { + attribute + .to_string() + .split_whitespace() + .next() + .and_then(|value| value.parse().ok()) +} + +fn int_array_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result, EmitError> { + let attribute = operation + .attribute(attr) + .map(|attribute| attribute.to_string()) + .ok() + .ok_or_else(|| attr_error(operation, attr, "integer array"))?; + parse_int_array(&attribute).ok_or_else(|| attr_error(operation, attr, "integer array")) +} + +fn parse_int_array(attribute: &str) -> Option> { + let inner = attribute.strip_prefix('[')?.strip_suffix(']')?.trim(); + if inner.is_empty() { + return Some(Vec::new()); + } + inner + .split(',') + .map(|item| item.trim().parse().ok()) + .collect() +} + +fn operand_symbols( + operation: OperationRef<'_, '_>, + start_index: usize, +) -> Result, EmitError> { + (start_index..operation.operand_count()) + .map(|index| operand_symbol(operation, index)) + .collect() +} + +fn operand_symbol(operation: OperationRef<'_, '_>, index: usize) -> Result { + let operand = operation.operand(index).map_err(|_| { + EmitError::new(format!( + "{} requires operand {index}", + operation_name(operation) + )) + })?; + let owner = OperationResult::try_from(operand).map_err(|_| { + EmitError::new(format!( + "{} operand {index} must be an op result", + operation_name(operation) + )) + })?; + string_attr(owner.owner(), "sym_name") +} + +fn attr_error(operation: OperationRef<'_, '_>, attr: &str, expected: &str) -> EmitError { + EmitError::new(format!( + "{} attr `{attr}` is not a {expected}", + operation_name(operation) + )) +} + +fn operation_name<'c: 'a, 'a>(operation: impl OperationLike<'c, 'a>) -> String { + operation + .name() + .as_string_ref() + .as_str() + .unwrap_or("") + .to_owned() +} diff --git a/crates/bolt/src/protocols/jolt/emit/rust/stage8.rs b/crates/bolt/src/protocols/jolt/emit/rust/stage8.rs new file mode 100644 index 0000000000..9914b4b4cf --- /dev/null +++ b/crates/bolt/src/protocols/jolt/emit/rust/stage8.rs @@ -0,0 +1,516 @@ +use std::collections::{BTreeMap, BTreeSet}; + +use melior::ir::block::BlockLike; +use melior::ir::operation::{OperationLike, OperationResult}; +use melior::ir::OperationRef; + +use crate::emit::rust::{push_format, EmitError, RustSourceFile}; +use crate::ir::{string_attribute_value, symbol_attribute_value, BoltModule, Cpu, Role}; +use crate::schema::verify_cpu_schema; + +const EVALUATION_POINT_SOURCE_SYMBOL: &str = "stage8.evaluation.point_source"; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage8CpuProgram { + pub role: Role, + pub params: Stage8Params, + pub function: String, + pub opening_inputs: Vec, + pub opening_claims: Vec, + pub opening_batches: Vec, + pub pcs_proofs: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage8Params { + pub field: String, + pub pcs: String, + pub transcript: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage8OpeningInputPlan { + pub symbol: String, + pub source_stage: String, + pub source_claim: String, + pub oracle: String, + pub domain: String, + pub point_arity: usize, + pub claim_kind: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage8OpeningClaimPlan { + pub symbol: String, + pub oracle: String, + pub family: String, + pub domain: String, + pub point_arity: usize, + pub point_source: String, + pub eval_source: String, + pub source_stage: String, + pub source_claim: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage8OpeningBatchPlan { + pub symbol: String, + pub proof_slot: String, + pub policy: String, + pub count: usize, + pub ordered_claims: Vec, + pub claim_operands: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage8PcsProofPlan { + pub symbol: String, + pub mode: String, + pub pcs: String, + pub proof_slot: String, + pub transcript_label: String, + pub batch: String, +} + +pub fn stage8_cpu_program(module: &BoltModule<'_, Cpu>) -> Result { + verify_cpu_schema(module)?; + let program = Stage8CpuProgram::from_module(module)?; + program.verify_supported_target()?; + Ok(program) +} + +pub fn emit_stage8_rust(module: &BoltModule<'_, Cpu>) -> Result { + let program = stage8_cpu_program(module)?; + Ok(RustSourceFile { + filename: program.filename().to_owned(), + source: program.emit_source()?, + }) +} + +impl Stage8CpuProgram { + fn from_module(module: &BoltModule<'_, Cpu>) -> Result { + let role = module + .role() + .ok_or_else(|| EmitError::new("stage8 CPU module missing role"))?; + let mut params = None; + let mut function = None; + let mut opening_inputs = Vec::new(); + let mut opening_claims = Vec::new(); + let mut opening_batches = Vec::new(); + let mut pcs_proofs = Vec::new(); + + let mut operation = module.as_mlir_module().body().first_operation(); + while let Some(op) = operation { + operation = op.next_in_block(); + match operation_name(op).as_str() { + "cpu.params" => { + params = Some(Stage8Params { + field: symbol_attr(op, "field")?, + pcs: symbol_attr(op, "pcs")?, + transcript: symbol_attr(op, "transcript")?, + }); + } + "cpu.function" => { + function = Some(string_attr(op, "sym_name")?); + } + "cpu.opening_input" => { + opening_inputs.push(Stage8OpeningInputPlan { + symbol: string_attr(op, "sym_name")?, + source_stage: symbol_attr(op, "source_stage")?, + source_claim: symbol_attr(op, "source_claim")?, + oracle: symbol_attr(op, "oracle")?, + domain: symbol_attr(op, "domain")?, + point_arity: int_attr(op, "point_arity")?, + claim_kind: string_attr(op, "claim_kind")?, + }); + } + "cpu.pcs_opening_claim" => { + opening_claims.push(Stage8OpeningClaimPlan { + symbol: string_attr(op, "sym_name")?, + oracle: symbol_attr(op, "oracle")?, + family: symbol_attr(op, "family")?, + domain: symbol_attr(op, "domain")?, + point_arity: int_attr(op, "point_arity")?, + point_source: operand_symbol(op, 0)?, + eval_source: operand_symbol(op, 1)?, + source_stage: String::new(), + source_claim: String::new(), + }); + } + "cpu.pcs_opening_batch" => { + opening_batches.push(Stage8OpeningBatchPlan { + symbol: string_attr(op, "sym_name")?, + proof_slot: symbol_attr(op, "proof_slot")?, + policy: string_attr(op, "policy")?, + count: int_attr(op, "count")?, + ordered_claims: symbol_array_attr(op, "ordered_claims")?, + claim_operands: operand_symbols(op, 0)?, + }); + } + "cpu.pcs_batch_open" | "cpu.pcs_batch_verify" => { + let mode = match operation_name(op).as_str() { + "cpu.pcs_batch_open" => "open", + "cpu.pcs_batch_verify" => "verify", + _ => unreachable!(), + }; + pcs_proofs.push(Stage8PcsProofPlan { + symbol: string_attr(op, "sym_name")?, + mode: mode.to_owned(), + pcs: symbol_attr(op, "pcs")?, + proof_slot: symbol_attr(op, "proof_slot")?, + transcript_label: string_attr(op, "transcript_label")?, + batch: operand_symbol(op, 1)?, + }); + } + _ => {} + } + } + + let input_by_symbol = opening_inputs + .iter() + .map(|input| (input.symbol.as_str(), input)) + .collect::>(); + for claim in &mut opening_claims { + let input = input_by_symbol + .get(claim.point_source.as_str()) + .ok_or_else(|| { + EmitError::new(format!( + "stage8 opening claim `{}` references missing point source `{}`", + claim.symbol, claim.point_source + )) + })?; + claim.source_stage = input.source_stage.clone(); + claim.source_claim = input.source_claim.clone(); + } + + Ok(Self { + role, + params: params.ok_or_else(|| EmitError::new("stage8 program missing cpu.params"))?, + function: function + .ok_or_else(|| EmitError::new("stage8 program missing cpu.function"))?, + opening_inputs, + opening_claims, + opening_batches, + pcs_proofs, + }) + } + + fn verify_supported_target(&self) -> Result<(), EmitError> { + if self.function != "jolt.stage8" { + return Err(EmitError::new(format!( + "stage8 emitter expected function `jolt.stage8`, got `{}`", + self.function + ))); + } + if self.opening_batches.len() != 1 { + return Err(EmitError::new(format!( + "stage8 emitter expects one PCS opening batch, got {}", + self.opening_batches.len() + ))); + } + if self.pcs_proofs.len() != 1 { + return Err(EmitError::new(format!( + "stage8 emitter expects one PCS proof op, got {}", + self.pcs_proofs.len() + ))); + } + let expected_mode = match self.role { + Role::Prover => "open", + Role::Verifier => "verify", + }; + if self.pcs_proofs[0].mode != expected_mode { + return Err(EmitError::new(format!( + "stage8 {} artifact expected PCS mode `{expected_mode}`, got `{}`", + self.role, self.pcs_proofs[0].mode + ))); + } + let batch = &self.opening_batches[0]; + if batch.count != self.opening_claims.len() { + return Err(EmitError::new(format!( + "stage8 opening batch count {} does not match {} opening claims", + batch.count, + self.opening_claims.len() + ))); + } + if batch.ordered_claims != batch.claim_operands { + return Err(EmitError::new( + "stage8 opening batch ordered claims do not match SSA operands", + )); + } + if !self + .opening_inputs + .iter() + .any(|input| input.symbol == EVALUATION_POINT_SOURCE_SYMBOL) + { + return Err(EmitError::new(format!( + "stage8 program missing `{EVALUATION_POINT_SOURCE_SYMBOL}` opening-point source" + ))); + } + let input_symbols = self + .opening_inputs + .iter() + .map(|input| input.symbol.as_str()) + .collect::>(); + for claim in &self.opening_claims { + if !input_symbols.contains(claim.point_source.as_str()) { + return Err(EmitError::new(format!( + "stage8 claim `{}` point source `{}` is not an opening input", + claim.symbol, claim.point_source + ))); + } + if claim.point_source != claim.eval_source { + return Err(EmitError::new(format!( + "stage8 claim `{}` must take point and eval from the same opening input", + claim.symbol + ))); + } + } + Ok(()) + } + + fn filename(&self) -> &'static str { + match self.role { + Role::Prover => "prove_stage8.rs", + Role::Verifier => "verify_stage8.rs", + } + } + + fn emit_source(&self) -> Result { + let mut source = String::new(); + source.push_str("#![allow(clippy::too_many_lines)]\n\n"); + source.push_str("#[derive(Clone, Copy, Debug, PartialEq, Eq)]\n"); + source.push_str( + "pub struct Stage8Params {\n pub field: &'static str,\n pub pcs: &'static str,\n pub transcript: &'static str,\n}\n\n", + ); + source.push_str("#[derive(Clone, Copy, Debug, PartialEq, Eq)]\n"); + source.push_str( + "pub struct Stage8OpeningInputPlan {\n pub symbol: &'static str,\n pub source_stage: &'static str,\n pub source_claim: &'static str,\n pub oracle: &'static str,\n pub domain: &'static str,\n pub point_arity: usize,\n pub claim_kind: &'static str,\n}\n\n", + ); + source.push_str("#[derive(Clone, Copy, Debug, PartialEq, Eq)]\n"); + source.push_str( + "pub struct Stage8OpeningClaimPlan {\n pub symbol: &'static str,\n pub oracle: &'static str,\n pub family: &'static str,\n pub domain: &'static str,\n pub point_arity: usize,\n pub point_source: &'static str,\n pub eval_source: &'static str,\n pub source_stage: &'static str,\n pub source_claim: &'static str,\n}\n\n", + ); + source.push_str("#[derive(Clone, Copy, Debug, PartialEq, Eq)]\n"); + source.push_str( + "pub struct Stage8OpeningBatchPlan {\n pub symbol: &'static str,\n pub proof_slot: &'static str,\n pub policy: &'static str,\n pub count: usize,\n pub ordered_claims: &'static [&'static str],\n}\n\n", + ); + source.push_str("#[derive(Clone, Copy, Debug, PartialEq, Eq)]\n"); + source.push_str( + "pub struct Stage8PcsProofPlan {\n pub symbol: &'static str,\n pub mode: &'static str,\n pub pcs: &'static str,\n pub proof_slot: &'static str,\n pub transcript_label: &'static str,\n pub batch: &'static str,\n}\n\n", + ); + source.push_str("#[derive(Clone, Copy, Debug, PartialEq, Eq)]\n"); + source.push_str( + "pub struct Stage8EvaluationProgramPlan {\n pub role: &'static str,\n pub function: &'static str,\n pub params: Stage8Params,\n pub evaluation_point_source: Stage8OpeningInputPlan,\n pub opening_inputs: &'static [Stage8OpeningInputPlan],\n pub opening_claims: &'static [Stage8OpeningClaimPlan],\n pub opening_batch: Stage8OpeningBatchPlan,\n pub pcs_proof: Stage8PcsProofPlan,\n}\n\n", + ); + + push_format( + &mut source, + format_args!( + "pub const STAGE8_PARAMS: Stage8Params = Stage8Params {{ field: {}, pcs: {}, transcript: {} }};\n\n", + rust_str(&self.params.field), + rust_str(&self.params.pcs), + rust_str(&self.params.transcript), + ), + ); + let point_source = self + .opening_inputs + .iter() + .find(|input| input.symbol == EVALUATION_POINT_SOURCE_SYMBOL) + .ok_or_else(|| { + EmitError::new(format!( + "evaluation program missing `{EVALUATION_POINT_SOURCE_SYMBOL}` opening-point source" + )) + })?; + push_format( + &mut source, + format_args!( + "pub const STAGE8_EVALUATION_POINT_SOURCE: Stage8OpeningInputPlan = {};\n\n", + opening_input_literal(point_source), + ), + ); + source.push_str("pub const STAGE8_OPENING_INPUTS: &[Stage8OpeningInputPlan] = &[\n"); + for input in &self.opening_inputs { + push_format( + &mut source, + format_args!(" {},\n", opening_input_literal(input)), + ); + } + source.push_str("];\n\n"); + source.push_str("pub const STAGE8_OPENING_CLAIMS: &[Stage8OpeningClaimPlan] = &[\n"); + for claim in &self.opening_claims { + push_format( + &mut source, + format_args!( + " Stage8OpeningClaimPlan {{ symbol: {}, oracle: {}, family: {}, domain: {}, point_arity: {}, point_source: {}, eval_source: {}, source_stage: {}, source_claim: {} }},\n", + rust_str(&claim.symbol), + rust_str(&claim.oracle), + rust_str(&claim.family), + rust_str(&claim.domain), + claim.point_arity, + rust_str(&claim.point_source), + rust_str(&claim.eval_source), + rust_str(&claim.source_stage), + rust_str(&claim.source_claim), + ), + ); + } + source.push_str("];\n\n"); + let batch = &self.opening_batches[0]; + push_format( + &mut source, + format_args!( + "pub const STAGE8_OPENING_BATCH_ORDERED_CLAIMS: &[&str] = &{};\n\n", + rust_str_array(&batch.ordered_claims), + ), + ); + push_format( + &mut source, + format_args!( + "pub const STAGE8_OPENING_BATCH: Stage8OpeningBatchPlan = Stage8OpeningBatchPlan {{ symbol: {}, proof_slot: {}, policy: {}, count: {}, ordered_claims: STAGE8_OPENING_BATCH_ORDERED_CLAIMS }};\n\n", + rust_str(&batch.symbol), + rust_str(&batch.proof_slot), + rust_str(&batch.policy), + batch.count, + ), + ); + let proof = &self.pcs_proofs[0]; + push_format( + &mut source, + format_args!( + "pub const STAGE8_PCS_PROOF: Stage8PcsProofPlan = Stage8PcsProofPlan {{ symbol: {}, mode: {}, pcs: {}, proof_slot: {}, transcript_label: {}, batch: {} }};\n\n", + rust_str(&proof.symbol), + rust_str(&proof.mode), + rust_str(&proof.pcs), + rust_str(&proof.proof_slot), + rust_str(&proof.transcript_label), + rust_str(&proof.batch), + ), + ); + push_format( + &mut source, + format_args!( + "pub const STAGE8_PROGRAM: Stage8EvaluationProgramPlan = Stage8EvaluationProgramPlan {{\n role: {},\n function: {},\n params: STAGE8_PARAMS,\n evaluation_point_source: STAGE8_EVALUATION_POINT_SOURCE,\n opening_inputs: STAGE8_OPENING_INPUTS,\n opening_claims: STAGE8_OPENING_CLAIMS,\n opening_batch: STAGE8_OPENING_BATCH,\n pcs_proof: STAGE8_PCS_PROOF,\n}};\n", + rust_str(self.role.as_str()), + rust_str(&self.function), + ), + ); + Ok(source) + } +} + +fn opening_input_literal(input: &Stage8OpeningInputPlan) -> String { + format!( + "Stage8OpeningInputPlan {{ symbol: {}, source_stage: {}, source_claim: {}, oracle: {}, domain: {}, point_arity: {}, claim_kind: {} }}", + rust_str(&input.symbol), + rust_str(&input.source_stage), + rust_str(&input.source_claim), + rust_str(&input.oracle), + rust_str(&input.domain), + input.point_arity, + rust_str(&input.claim_kind), + ) +} + +fn rust_str(value: &str) -> String { + format!("{value:?}") +} + +fn rust_str_array(values: &[String]) -> String { + let values = values + .iter() + .map(|value| rust_str(value)) + .collect::>() + .join(", "); + format!("[{values}]") +} + +fn string_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .ok() + .and_then(string_attribute_value) + .ok_or_else(|| attr_error(operation, attr, "string")) +} + +fn symbol_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .ok() + .and_then(symbol_attribute_value) + .ok_or_else(|| attr_error(operation, attr, "symbol reference")) +} + +fn int_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + let value = operation + .attribute(attr) + .ok() + .and_then(|attr| attr.to_string().strip_suffix(" : i64").map(str::to_owned)) + .ok_or_else(|| attr_error(operation, attr, "integer"))?; + value + .parse() + .map_err(|_| attr_error(operation, attr, "integer")) +} + +fn symbol_array_attr( + operation: OperationRef<'_, '_>, + attr: &str, +) -> Result, EmitError> { + let value = operation + .attribute(attr) + .ok() + .map(|attr| attr.to_string()) + .ok_or_else(|| attr_error(operation, attr, "symbol array"))?; + parse_symbol_array(&value).ok_or_else(|| attr_error(operation, attr, "symbol array")) +} + +fn parse_symbol_array(attribute: &str) -> Option> { + let inner = attribute.strip_prefix('[')?.strip_suffix(']')?.trim(); + if inner.is_empty() { + return Some(Vec::new()); + } + inner + .split(',') + .map(|item| item.trim().strip_prefix('@').map(str::to_owned)) + .collect() +} + +fn operand_symbols( + operation: OperationRef<'_, '_>, + start_index: usize, +) -> Result, EmitError> { + (start_index..operation.operand_count()) + .map(|index| operand_symbol(operation, index)) + .collect() +} + +fn operand_symbol(operation: OperationRef<'_, '_>, index: usize) -> Result { + let operand = operation.operand(index).map_err(|_| { + EmitError::new(format!( + "{} requires operand {index}", + operation_name(operation) + )) + })?; + let owner = OperationResult::try_from(operand).map_err(|_| { + EmitError::new(format!( + "{} operand {index} must be an op result", + operation_name(operation) + )) + })?; + string_attr(owner.owner(), "sym_name") +} + +fn attr_error(operation: OperationRef<'_, '_>, attr: &str, expected: &str) -> EmitError { + EmitError::new(format!( + "{} attr `{attr}` is not a {expected}", + operation_name(operation) + )) +} + +fn operation_name<'c: 'a, 'a>(operation: impl OperationLike<'c, 'a>) -> String { + operation + .name() + .as_string_ref() + .as_str() + .unwrap_or("") + .to_owned() +} diff --git a/crates/bolt/src/protocols/jolt/mod.rs b/crates/bolt/src/protocols/jolt/mod.rs new file mode 100644 index 0000000000..91da996a0e --- /dev/null +++ b/crates/bolt/src/protocols/jolt/mod.rs @@ -0,0 +1,41 @@ +pub mod artifacts; +pub mod emit; +pub mod oracles; +pub mod params; +pub mod phases; +pub mod validate; + +pub use artifacts::{ + assemble_jolt_generated_crates, assemble_jolt_workspace_generated_crates, jolt_artifact_config, + jolt_rust_artifact, validate_jolt_rust_artifact_imports, write_jolt_generated_crates, + JoltArtifactCrate, JoltGeneratedCrate, JoltGeneratedFile, JoltProtocolStage, JoltRustArtifact, +}; +pub use emit::rust::{ + commitment_cpu_program, emit_commitment_rust, emit_stage1_rust, emit_stage2_rust, + emit_stage3_rust, emit_stage4_rust, emit_stage5_rust, emit_stage6_rust, emit_stage7_rust, + emit_stage8_rust, stage1_cpu_program, stage2_cpu_program, stage3_cpu_program, + stage4_cpu_program, stage5_cpu_program, stage6_cpu_program, stage7_cpu_program, + stage8_cpu_program, CommitmentBatchPlan, CommitmentCpuProgram, CommitmentParams, + OptionalCommitmentPlan, OptionalSkipPolicy, OracleGeneration, OraclePlan, Stage1CpuProgram, + Stage1KernelPlan, Stage1OpeningBatchPlan, Stage1OpeningClaimPlan, Stage1Params, + Stage1SumcheckBatchPlan, Stage1SumcheckClaimPlan, Stage1SumcheckDriverPlan, + Stage1SumcheckEvalPlan, Stage2CpuProgram, Stage3CpuProgram, Stage4CpuProgram, Stage5CpuProgram, + Stage6CpuProgram, Stage7CpuProgram, Stage8CpuProgram, TranscriptStep, +}; +pub use params::JoltProtocolParams; +pub use phases::commitment::{ + build_commitment_protocol, lower_commitment_to_compute, lower_compute_to_cpu, +}; +pub use phases::stage1::{ + build_stage1_outer_protocol, lower_stage1_to_compute, resolve_compute_kernels, +}; +pub use phases::stage2::{build_stage2_protocol, lower_stage2_to_compute}; +pub use phases::stage3::{build_stage3_protocol, lower_stage3_to_compute}; +pub use phases::stage4::{build_stage4_protocol, lower_stage4_to_compute}; +pub use phases::stage5::{build_stage5_protocol, lower_stage5_to_compute}; +pub use phases::stage6::{build_stage6_protocol, lower_stage6_to_compute}; +pub use phases::stage7::{build_stage7_protocol, lower_stage7_to_compute}; +pub use phases::stage8::{build_stage8_protocol, lower_stage8_to_compute}; +pub use validate::{ + verify_jolt_concrete_schema, verify_jolt_party_schema, verify_jolt_protocol_schema, +}; diff --git a/crates/bolt/src/protocols/jolt/oracles.rs b/crates/bolt/src/protocols/jolt/oracles.rs new file mode 100644 index 0000000000..46e66304b2 --- /dev/null +++ b/crates/bolt/src/protocols/jolt/oracles.rs @@ -0,0 +1,227 @@ +use crate::ir::{BoltModule, Protocol}; +use crate::mlir::{MeliorContext, MlirError}; + +use super::params::JoltProtocolParams; + +pub const FIELD_SYMBOL: &str = "bn254_fr"; +pub const HASH_SYMBOL: &str = "blake2b"; +pub const TRANSCRIPT_SYMBOL: &str = "blake2b_transcript"; +pub const PCS_SYMBOL: &str = "dory"; +pub const TRACE_DOMAIN_SYMBOL: &str = "jolt.trace_domain"; +pub const MAIN_WITNESS_COMMIT_DOMAIN_SYMBOL: &str = "jolt.main_witness_commit_domain"; +pub const MAIN_WITNESS_FAMILY_SYMBOL: &str = "jolt.main_witness_polys"; +pub const ADVICE_FAMILY_SYMBOL: &str = "jolt.advice_polys"; + +pub fn main_witness_oracles(params: &JoltProtocolParams) -> Vec { + let mut oracles = vec!["RdInc".to_owned(), "RamInc".to_owned()]; + oracles.extend((0..params.instruction_d).map(|index| format!("InstructionRa_{index}"))); + oracles.extend((0..params.ram_d).map(|index| format!("RamRa_{index}"))); + oracles.extend((0..params.bytecode_d).map(|index| format!("BytecodeRa_{index}"))); + oracles +} + +pub fn main_witness_oracle_attr(params: &JoltProtocolParams) -> String { + symbol_array_attr(&main_witness_oracles(params)) +} + +pub fn append_foundation_ops<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + params: &JoltProtocolParams, +) -> Result<(), MlirError> { + context.append_op( + module, + "field.define", + Some(FIELD_SYMBOL), + &[("modulus_bits", "254 : i64"), ("role", r#""scalar""#)], + )?; + context.append_op( + module, + "hash.function", + Some(HASH_SYMBOL), + &[("algorithm", r#""blake2b""#)], + )?; + context.append_op( + module, + "transcript.scheme", + Some(TRANSCRIPT_SYMBOL), + &[("hash", "@blake2b")], + )?; + context.append_op( + module, + "pcs.scheme", + Some(PCS_SYMBOL), + &[("field", "@bn254_fr")], + )?; + context.append_op( + module, + "poly.domain", + Some(TRACE_DOMAIN_SYMBOL), + &[ + ("field", "@bn254_fr"), + ("log_size", &format!("{} : i64", params.log_t)), + ], + )?; + context.append_op( + module, + "poly.domain", + Some(MAIN_WITNESS_COMMIT_DOMAIN_SYMBOL), + &[ + ("field", "@bn254_fr"), + ( + "log_size", + &format!("{} : i64", params.log_t + params.log_k_chunk), + ), + ], + )?; + Ok(()) +} + +pub fn append_committed_oracles<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + params: &JoltProtocolParams, +) -> Result<(), MlirError> { + append_oracle( + context, + module, + OracleSpec { + symbol: "RdInc".to_owned(), + domain: "@jolt.trace_domain", + commit_domain: "@jolt.main_witness_commit_domain", + layout: "dense_trace", + visibility: "committed", + extra_attrs: Vec::new(), + }, + )?; + append_oracle( + context, + module, + OracleSpec { + symbol: "RamInc".to_owned(), + domain: "@jolt.trace_domain", + commit_domain: "@jolt.main_witness_commit_domain", + layout: "dense_trace", + visibility: "committed", + extra_attrs: Vec::new(), + }, + )?; + for index in 0..params.instruction_d { + append_indexed_oracle( + context, + module, + "InstructionRa", + index, + "@jolt.main_witness_commit_domain", + )?; + } + for index in 0..params.ram_d { + append_indexed_oracle( + context, + module, + "RamRa", + index, + "@jolt.main_witness_commit_domain", + )?; + } + for index in 0..params.bytecode_d { + append_indexed_oracle( + context, + module, + "BytecodeRa", + index, + "@jolt.main_witness_commit_domain", + )?; + } + append_oracle( + context, + module, + OracleSpec { + symbol: "UntrustedAdvice".to_owned(), + domain: "@jolt.trace_domain", + commit_domain: "@jolt.trace_domain", + layout: "dense_trace", + visibility: "optional_committed", + extra_attrs: Vec::new(), + }, + )?; + append_oracle( + context, + module, + OracleSpec { + symbol: "TrustedAdvice".to_owned(), + domain: "@jolt.trace_domain", + commit_domain: "@jolt.trace_domain", + layout: "dense_trace", + visibility: "optional_committed", + extra_attrs: Vec::new(), + }, + )?; + Ok(()) +} + +fn append_indexed_oracle<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + family: &str, + index: usize, + domain: &str, +) -> Result<(), MlirError> { + append_oracle( + context, + module, + OracleSpec { + symbol: format!("{family}_{index}"), + domain, + commit_domain: "@jolt.main_witness_commit_domain", + layout: "onehot_expanded", + visibility: "committed", + extra_attrs: vec![ + ("family", format!("@{family}")), + ("index", format!("{index} : i64")), + ], + }, + ) +} + +struct OracleSpec<'a> { + symbol: String, + domain: &'a str, + commit_domain: &'a str, + layout: &'a str, + visibility: &'a str, + extra_attrs: Vec<(&'a str, String)>, +} + +fn append_oracle<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + spec: OracleSpec<'_>, +) -> Result<(), MlirError> { + let mut attrs = vec![ + ("field", "@bn254_fr".to_owned()), + ("domain", spec.domain.to_owned()), + ("commit_domain", spec.commit_domain.to_owned()), + ("visibility", format!("\"{}\"", spec.visibility)), + ("layout", format!("\"{}\"", spec.layout)), + ]; + attrs.extend(spec.extra_attrs); + context.append_op_with_owned_attrs( + module, + "piop.oracle", + Some(&spec.symbol), + &attrs + .into_iter() + .map(|(name, value)| (name.to_owned(), value)) + .collect::>(), + ) +} + +fn symbol_array_attr(values: &[String]) -> String { + let values = values + .iter() + .map(|value| format!("@{value}")) + .collect::>() + .join(", "); + format!("[{values}]") +} diff --git a/crates/bolt/src/protocols/jolt/params.rs b/crates/bolt/src/protocols/jolt/params.rs new file mode 100644 index 0000000000..5dd94687dd --- /dev/null +++ b/crates/bolt/src/protocols/jolt/params.rs @@ -0,0 +1,305 @@ +use melior::ir::OperationRef; + +use crate::schema::{ + int_attr as mlir_int_attr, require_attrs, symbol_attr as mlir_symbol_attr, SchemaError, +}; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct JoltProtocolParams { + pub field: &'static str, + pub pcs: &'static str, + pub transcript: &'static str, + pub xlen: usize, + pub log_t: usize, + pub trace_length: usize, + pub log_k_bytecode: usize, + pub bytecode_k: usize, + pub log_k_ram: usize, + pub ram_k: usize, + pub log_k_chunk: usize, + pub k_chunk: usize, + pub lookups_ra_virtual_log_k_chunk: usize, + pub instruction_log_k: usize, + pub register_log_k: usize, + pub lookup_table_count: usize, + pub instruction_d: usize, + pub instruction_ra_virtual_d: usize, + pub bytecode_d: usize, + pub ram_d: usize, + pub num_committed: usize, + pub num_r1cs_constraints: usize, + pub num_r1cs_inputs: usize, + pub num_vars_padded: usize, +} + +impl JoltProtocolParams { + pub fn new(log_t: usize, log_k_bytecode: usize, log_k_ram: usize) -> Self { + let log_k_chunk = if log_t < 25 { 4 } else { 8 }; + let instruction_log_k = 128; + let lookups_ra_virtual_log_k_chunk = if log_t < 25 { + instruction_log_k / 8 + } else { + instruction_log_k / 4 + }; + let instruction_d = instruction_log_k / log_k_chunk; + let instruction_ra_virtual_d = instruction_log_k / lookups_ra_virtual_log_k_chunk; + let bytecode_d = log_k_bytecode.div_ceil(log_k_chunk); + let ram_d = log_k_ram.div_ceil(log_k_chunk); + Self { + field: "bn254_fr", + pcs: "dory", + transcript: "blake2b_transcript", + xlen: 64, + log_t, + trace_length: 1usize << log_t, + log_k_bytecode, + bytecode_k: 1usize << log_k_bytecode, + log_k_ram, + ram_k: 1usize << log_k_ram, + log_k_chunk, + k_chunk: 1usize << log_k_chunk, + lookups_ra_virtual_log_k_chunk, + instruction_log_k, + register_log_k: 7, + lookup_table_count: 40, + instruction_d, + instruction_ra_virtual_d, + bytecode_d, + ram_d, + num_committed: 2 + instruction_d + bytecode_d + ram_d, + num_r1cs_constraints: 19, + num_r1cs_inputs: 35, + num_vars_padded: 64, + } + } + + pub fn fixture() -> Self { + Self::new(16, 10, 16) + } + + pub fn attrs(&self) -> Vec<(String, String)> { + vec![ + symbol_attr("field", self.field), + symbol_attr("pcs", self.pcs), + symbol_attr("transcript", self.transcript), + int_attr("xlen", self.xlen), + int_attr("log_t", self.log_t), + int_attr("trace_length", self.trace_length), + int_attr("log_k_bytecode", self.log_k_bytecode), + int_attr("bytecode_k", self.bytecode_k), + int_attr("log_k_ram", self.log_k_ram), + int_attr("ram_k", self.ram_k), + int_attr("log_k_chunk", self.log_k_chunk), + int_attr("k_chunk", self.k_chunk), + int_attr( + "lookups_ra_virtual_log_k_chunk", + self.lookups_ra_virtual_log_k_chunk, + ), + int_attr("instruction_log_k", self.instruction_log_k), + int_attr("register_log_k", self.register_log_k), + int_attr("lookup_table_count", self.lookup_table_count), + int_attr("instruction_d", self.instruction_d), + int_attr("instruction_ra_virtual_d", self.instruction_ra_virtual_d), + int_attr("bytecode_d", self.bytecode_d), + int_attr("ram_d", self.ram_d), + int_attr("num_committed", self.num_committed), + int_attr("num_r1cs_constraints", self.num_r1cs_constraints), + int_attr("num_r1cs_inputs", self.num_r1cs_inputs), + int_attr("num_vars_padded", self.num_vars_padded), + ] + } +} + +fn symbol_attr(name: &str, value: &str) -> (String, String) { + (name.to_owned(), format!("@{value}")) +} + +fn int_attr(name: &str, value: usize) -> (String, String) { + (name.to_owned(), format!("{value} : i64")) +} + +#[derive(Clone, Debug)] +pub(crate) struct ParsedJoltProtocolParams { + pub(crate) field: String, + pub(crate) pcs: String, + pub(crate) transcript: String, + pub(crate) log_t: usize, + pub(crate) trace_length: usize, + pub(crate) log_k_bytecode: usize, + pub(crate) bytecode_k: usize, + pub(crate) log_k_ram: usize, + pub(crate) ram_k: usize, + pub(crate) log_k_chunk: usize, + pub(crate) k_chunk: usize, + pub(crate) lookups_ra_virtual_log_k_chunk: usize, + pub(crate) instruction_log_k: usize, + pub(crate) instruction_d: usize, + pub(crate) instruction_ra_virtual_d: usize, + pub(crate) bytecode_d: usize, + pub(crate) ram_d: usize, + pub(crate) num_committed: usize, +} + +impl ParsedJoltProtocolParams { + pub(crate) fn from_op(operation: OperationRef<'_, '_>) -> Result { + require_jolt_params_attrs(operation)?; + Ok(Self { + field: mlir_symbol_attr(operation, "field")?, + pcs: mlir_symbol_attr(operation, "pcs")?, + transcript: mlir_symbol_attr(operation, "transcript")?, + log_t: mlir_int_attr(operation, "log_t")?, + trace_length: mlir_int_attr(operation, "trace_length")?, + log_k_bytecode: mlir_int_attr(operation, "log_k_bytecode")?, + bytecode_k: mlir_int_attr(operation, "bytecode_k")?, + log_k_ram: mlir_int_attr(operation, "log_k_ram")?, + ram_k: mlir_int_attr(operation, "ram_k")?, + log_k_chunk: mlir_int_attr(operation, "log_k_chunk")?, + k_chunk: mlir_int_attr(operation, "k_chunk")?, + lookups_ra_virtual_log_k_chunk: mlir_int_attr( + operation, + "lookups_ra_virtual_log_k_chunk", + )?, + instruction_log_k: mlir_int_attr(operation, "instruction_log_k")?, + instruction_d: mlir_int_attr(operation, "instruction_d")?, + instruction_ra_virtual_d: mlir_int_attr(operation, "instruction_ra_virtual_d")?, + bytecode_d: mlir_int_attr(operation, "bytecode_d")?, + ram_d: mlir_int_attr(operation, "ram_d")?, + num_committed: mlir_int_attr(operation, "num_committed")?, + }) + } + + pub(crate) fn validate(&self) -> Result<(), SchemaError> { + require_power_relation("trace_length", self.trace_length, "log_t", self.log_t)?; + require_power_relation( + "bytecode_k", + self.bytecode_k, + "log_k_bytecode", + self.log_k_bytecode, + )?; + require_power_relation("ram_k", self.ram_k, "log_k_ram", self.log_k_ram)?; + require_power_relation("k_chunk", self.k_chunk, "log_k_chunk", self.log_k_chunk)?; + + if self.log_k_chunk != 4 && self.log_k_chunk != 8 { + return Err(SchemaError::new(format!( + "log_k_chunk must be 4 or 8, got {}", + self.log_k_chunk + ))); + } + if self.instruction_log_k != 128 { + return Err(SchemaError::new(format!( + "instruction_log_k must be 128, got {}", + self.instruction_log_k + ))); + } + if self.lookups_ra_virtual_log_k_chunk < self.log_k_chunk { + return Err(SchemaError::new(format!( + "lookups_ra_virtual_log_k_chunk must be >= log_k_chunk; got {} < {}", + self.lookups_ra_virtual_log_k_chunk, self.log_k_chunk + ))); + } + if !self + .lookups_ra_virtual_log_k_chunk + .is_multiple_of(self.log_k_chunk) + { + return Err(SchemaError::new(format!( + "lookups_ra_virtual_log_k_chunk must be a multiple of log_k_chunk; got {} and {}", + self.lookups_ra_virtual_log_k_chunk, self.log_k_chunk + ))); + } + if !self + .instruction_log_k + .is_multiple_of(self.lookups_ra_virtual_log_k_chunk) + { + return Err(SchemaError::new(format!( + "instruction_log_k must be divisible by lookups_ra_virtual_log_k_chunk; got {} and {}", + self.instruction_log_k, self.lookups_ra_virtual_log_k_chunk + ))); + } + + let instruction_d = self.instruction_log_k / self.log_k_chunk; + let instruction_ra_virtual_d = self.instruction_log_k / self.lookups_ra_virtual_log_k_chunk; + let bytecode_d = self.log_k_bytecode.div_ceil(self.log_k_chunk); + let ram_d = self.log_k_ram.div_ceil(self.log_k_chunk); + require_eq("instruction_d", self.instruction_d, instruction_d)?; + require_eq( + "instruction_ra_virtual_d", + self.instruction_ra_virtual_d, + instruction_ra_virtual_d, + )?; + require_eq("bytecode_d", self.bytecode_d, bytecode_d)?; + require_eq("ram_d", self.ram_d, ram_d)?; + require_eq( + "num_committed", + self.num_committed, + 2 + instruction_d + bytecode_d + ram_d, + )?; + Ok(()) + } + + pub(crate) fn main_witness_oracles(&self) -> Vec { + let mut oracles = vec!["RdInc".to_owned(), "RamInc".to_owned()]; + oracles.extend((0..self.instruction_d).map(|index| format!("InstructionRa_{index}"))); + oracles.extend((0..self.ram_d).map(|index| format!("RamRa_{index}"))); + oracles.extend((0..self.bytecode_d).map(|index| format!("BytecodeRa_{index}"))); + oracles + } +} + +fn require_jolt_params_attrs(operation: OperationRef<'_, '_>) -> Result<(), SchemaError> { + require_attrs( + operation, + &[ + "sym_name", + "field", + "pcs", + "transcript", + "xlen", + "log_t", + "trace_length", + "log_k_bytecode", + "bytecode_k", + "log_k_ram", + "ram_k", + "log_k_chunk", + "k_chunk", + "lookups_ra_virtual_log_k_chunk", + "instruction_log_k", + "register_log_k", + "lookup_table_count", + "instruction_d", + "instruction_ra_virtual_d", + "bytecode_d", + "ram_d", + "num_committed", + "num_r1cs_constraints", + "num_r1cs_inputs", + "num_vars_padded", + ], + ) +} + +fn require_power_relation( + value_name: &str, + value: usize, + log_name: &str, + log_value: usize, +) -> Result<(), SchemaError> { + let expected = 1usize << log_value; + if value == expected { + Ok(()) + } else { + Err(SchemaError::new(format!( + "{value_name} must equal 2^{log_name}; got {value}, expected {expected}" + ))) + } +} + +fn require_eq(name: &str, actual: usize, expected: usize) -> Result<(), SchemaError> { + if actual == expected { + Ok(()) + } else { + Err(SchemaError::new(format!( + "{name} must be {expected}, got {actual}" + ))) + } +} diff --git a/crates/bolt/src/protocols/jolt/phases/commitment.rs b/crates/bolt/src/protocols/jolt/phases/commitment.rs new file mode 100644 index 0000000000..10327884cd --- /dev/null +++ b/crates/bolt/src/protocols/jolt/phases/commitment.rs @@ -0,0 +1,1663 @@ +use std::collections::BTreeMap; + +use melior::ir::block::BlockLike; +use melior::ir::operation::{OperationLike, OperationResult}; +use melior::ir::{OperationRef, Value}; + +use crate::ir::{BoltModule, Compute, Cpu, Party, Protocol, Role}; +use crate::mlir::{verify_module, MeliorContext, MlirError}; +use crate::schema::{ + int_attr, operation_name, symbol_array_attr, symbol_attr, verify_compute_schema, + verify_cpu_schema, SchemaError, +}; + +use super::super::oracles::{self, ADVICE_FAMILY_SYMBOL, MAIN_WITNESS_FAMILY_SYMBOL, PCS_SYMBOL}; +use super::super::params::JoltProtocolParams; +use super::super::validate::{verify_jolt_party_schema, verify_jolt_protocol_schema}; +use super::lowering::{ + copy_attrs, field_lowering_attrs as compute_field_attrs, string_attr, + transcript_squeeze_cpu_result_types, +}; + +pub fn build_commitment_protocol<'c>( + context: &'c MeliorContext, + params: &JoltProtocolParams, +) -> Result, MlirError> { + let module = context.new_module::("jolt.commitment_phase", None); + oracles::append_foundation_ops(context, &module, params)?; + context.append_op_with_owned_attrs( + &module, + "protocol.params", + Some("jolt.params"), + ¶ms.attrs(), + )?; + context.append_op( + &module, + "protocol.boundary", + Some("jolt.commitment_phase"), + &[("roles", r#"["prover", "verifier"]"#)], + )?; + oracles::append_committed_oracles(context, &module, params)?; + context.append_op( + &module, + "piop.oracle_family", + Some(MAIN_WITNESS_FAMILY_SYMBOL), + &[ + ( + "ordered_oracles", + &oracles::main_witness_oracle_attr(params), + ), + ("count", &format!("{} : i64", params.num_committed)), + ("domain", "@jolt.main_witness_commit_domain"), + ("visibility", r#""committed""#), + ], + )?; + context.append_op( + &module, + "piop.oracle_family", + Some(ADVICE_FAMILY_SYMBOL), + &[ + ("ordered_oracles", "[@UntrustedAdvice, @TrustedAdvice]"), + ("count", "2 : i64"), + ("domain", "@jolt.trace_domain"), + ("visibility", r#""optional_committed""#), + ], + )?; + let state = context.append_typed_op( + &module, + "transcript.state", + Some("fs0"), + &[("scheme", "@blake2b_transcript")], + &[], + &["!transcript.state_type"], + )?; + let mut state = state + .result(0) + .map_err(|_| schema_error("transcript.state requires one result"))? + .into(); + let main_commitments = context.append_typed_op( + &module, + "commit.publish_batch", + Some("jolt.main_witness_commitments"), + &[ + ("oracle_family", "@jolt.main_witness_polys"), + ("label", r#""commitment""#), + ], + &[], + &["!commit.artifact"], + )?; + let main_commitments = main_commitments + .result(0) + .map_err(|_| schema_error("commit.publish_batch requires one result"))? + .into(); + let _pcs_commit = context.append_typed_op( + &module, + "pcs.commit_batch", + Some("jolt.dory_main_witness_commit"), + &[("scheme", &format!("@{PCS_SYMBOL}"))], + &[main_commitments], + &[], + )?; + let untrusted_advice = context.append_typed_op( + &module, + "commit.publish_optional", + Some("jolt.untrusted_advice_commitment"), + &[ + ("oracle", "@UntrustedAdvice"), + ("label", r#""untrusted_advice""#), + ("skip_policy", r#""missing_or_zero""#), + ], + &[], + &["!commit.artifact"], + )?; + let untrusted_advice = untrusted_advice + .result(0) + .map_err(|_| schema_error("commit.publish_optional requires one result"))? + .into(); + let trusted_advice = context.append_typed_op( + &module, + "commit.publish_optional", + Some("jolt.trusted_advice_commitment"), + &[ + ("oracle", "@TrustedAdvice"), + ("label", r#""trusted_advice""#), + ("skip_policy", r#""missing_or_zero""#), + ], + &[], + &["!commit.artifact"], + )?; + let trusted_advice = trusted_advice + .result(0) + .map_err(|_| schema_error("commit.publish_optional requires one result"))? + .into(); + let absorb = context.append_typed_op( + &module, + "transcript.absorb", + Some("jolt.absorb_main_witness_commitments"), + &[("label", r#""commitment""#)], + &[state, main_commitments], + &["!transcript.state_type"], + )?; + state = absorb + .result(0) + .map_err(|_| schema_error("transcript.absorb requires one result"))? + .into(); + let absorb = context.append_typed_op( + &module, + "transcript.absorb_optional", + Some("jolt.absorb_untrusted_advice"), + &[("label", r#""untrusted_advice""#)], + &[state, untrusted_advice], + &["!transcript.state_type"], + )?; + state = absorb + .result(0) + .map_err(|_| schema_error("transcript.absorb_optional requires one result"))? + .into(); + let _absorb = context.append_typed_op( + &module, + "transcript.absorb_optional", + Some("jolt.absorb_trusted_advice"), + &[("label", r#""trusted_advice""#)], + &[state, trusted_advice], + &["!transcript.state_type"], + )?; + verify_module(&module)?; + verify_jolt_protocol_schema(&module)?; + Ok(module) +} + +pub fn lower_commitment_to_compute<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Party>, +) -> Result, MlirError> { + verify_jolt_party_schema(module)?; + let role = module + .role() + .ok_or_else(|| schema_error("commitment lowering requires party role"))?; + let concrete = analyze_concrete(module)?; + let (batch_op, optional_op) = match role { + Role::Prover => ("compute.pcs_commit_batch", "compute.pcs_commit_optional"), + Role::Verifier => ("compute.pcs_receive_batch", "compute.pcs_receive_optional"), + }; + let module_name = module.name(); + let compute = context.new_module::(&module_name, Some(role.clone())); + context.append_op_with_owned_attrs( + &compute, + "compute.params", + Some("jolt.compute_params"), + &[ + ("field".to_owned(), symbol_ref(&concrete.params.field)), + ("pcs".to_owned(), symbol_ref(&concrete.params.pcs)), + ( + "transcript".to_owned(), + symbol_ref(&concrete.params.transcript), + ), + ], + )?; + context.append_op( + &compute, + "compute.function", + Some("jolt.commitment_phase"), + &[("source", "@jolt.commitment_phase")], + )?; + + let mut artifact_values = BTreeMap::new(); + let transcript_scheme = symbol_ref(&concrete.params.transcript); + let transcript_init = context.append_typed_op( + &compute, + "compute.transcript_init", + Some("fs0"), + &[("scheme", transcript_scheme.as_str())], + &[], + &["!compute.transcript_state"], + )?; + let mut transcript_value = first_result(transcript_init, "compute.transcript_init")?; + + for plan in &concrete.batch_plans { + let family_symbol = format!("{}.oracle_family.compute", plan.oracle_family); + let family_init = context.append_typed_op_with_owned_attrs( + &compute, + "compute.oracle_family_init", + Some(&family_symbol), + &[ + ("family".to_owned(), symbol_ref(&plan.oracle_family)), + ("count".to_owned(), int_attr_source(plan.count)), + ], + &[], + &["!compute.oracle_family"], + )?; + let mut family_value = first_result(family_init, "compute.oracle_family_init")?; + for (index, oracle) in plan.oracles.iter().enumerate() { + let oracle_buffer = concrete.oracle_buffers.get(oracle).ok_or_else(|| { + schema_error(format!( + "batch commitment references missing oracle buffer @{oracle}" + )) + })?; + let oracle_value = append_oracle_buffer( + context, + &compute, + &role, + &concrete.params, + oracle, + &oracle_buffer.domain, + oracle_buffer.num_vars, + )?; + let append_symbol = format!("{}.append_{index}.compute", plan.oracle_family); + let append = context.append_typed_op_with_owned_attrs( + &compute, + "compute.oracle_family_append", + Some(&append_symbol), + &[ + ("family".to_owned(), symbol_ref(&plan.oracle_family)), + ("oracle".to_owned(), symbol_ref(oracle)), + ("index".to_owned(), int_attr_source(index)), + ], + &[family_value, oracle_value], + &["!compute.oracle_family"], + )?; + family_value = first_result(append, "compute.oracle_family_append")?; + } + let symbol = format!("{}.compute", plan.artifact); + let attrs = vec![ + ("artifact".to_owned(), symbol_ref(&plan.artifact)), + ("count".to_owned(), int_attr_source(plan.count)), + ("domain".to_owned(), symbol_ref(&plan.domain)), + ("label".to_owned(), string_attr_source(&plan.label)), + ("num_vars".to_owned(), int_attr_source(plan.num_vars)), + ("oracle_family".to_owned(), symbol_ref(&plan.oracle_family)), + ( + "ordered_oracles".to_owned(), + symbol_array_attr_source(&plan.oracles), + ), + ("pcs".to_owned(), symbol_ref(&plan.pcs)), + ]; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + batch_op, + Some(&symbol), + &attrs, + &[family_value], + &["!compute.commitment_artifact"], + )?; + let value = first_result(operation, batch_op)?; + let inserted = artifact_values.insert(plan.artifact.clone(), value); + debug_assert!(inserted.is_none()); + } + for plan in &concrete.optional_plans { + let oracle_value = append_optional_oracle_buffer( + context, + &compute, + &role, + &plan.oracle, + &plan.domain, + plan.num_vars, + &plan.skip_policy, + )?; + let symbol = format!("{}.compute", plan.artifact); + let attrs = vec![ + ("artifact".to_owned(), symbol_ref(&plan.artifact)), + ("domain".to_owned(), symbol_ref(&plan.domain)), + ("label".to_owned(), string_attr_source(&plan.label)), + ("num_vars".to_owned(), int_attr_source(plan.num_vars)), + ("oracle".to_owned(), symbol_ref(&plan.oracle)), + ("pcs".to_owned(), symbol_ref(&plan.pcs)), + ( + "skip_policy".to_owned(), + string_attr_source(&plan.skip_policy), + ), + ]; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + optional_op, + Some(&symbol), + &attrs, + &[oracle_value], + &["!compute.commitment_artifact"], + )?; + let value = first_result(operation, optional_op)?; + let inserted = artifact_values.insert(plan.artifact.clone(), value); + debug_assert!(inserted.is_none()); + } + for step in &concrete.transcript_steps { + let artifact = artifact_values.get(&step.source).copied().ok_or_else(|| { + schema_error(format!( + "transcript absorb @{} references missing commitment artifact @{}", + step.symbol, step.source + )) + })?; + let symbol = format!("{}.compute", step.symbol); + let attrs = vec![ + ("label".to_owned(), string_attr_source(&step.label)), + ( + "optional".to_owned(), + bool_attr_source(step.optional).to_owned(), + ), + ]; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.transcript_absorb", + Some(&symbol), + &attrs, + &[transcript_value, artifact], + &["!compute.transcript_state"], + )?; + transcript_value = first_result(operation, "compute.transcript_absorb")?; + } + verify_module(&compute)?; + verify_compute_schema(&compute)?; + Ok(compute) +} + +pub fn lower_compute_to_cpu<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Compute>, +) -> Result, MlirError> { + verify_compute_schema(module)?; + let role = module + .role() + .ok_or_else(|| schema_error("CPU lowering requires compute party role"))?; + let module_name = module.name(); + let cpu = context.new_module::(&module_name, Some(role)); + let mut value_map = BTreeMap::new(); + let mut operation = module.as_mlir_module().body().first_operation(); + while let Some(op) = operation { + operation = op.next_in_block(); + match operation_name(op).as_str() { + "compute.function" => { + let source = symbol_ref(&symbol_attr(op, "source")?); + let symbol = string_attr(op, "sym_name")?; + context.append_op(&cpu, "cpu.function", Some(&symbol), &[("source", &source)])?; + } + "compute.params" => { + let symbol = string_attr(op, "sym_name")?; + context.append_op_with_owned_attrs( + &cpu, + "cpu.params", + Some(&symbol), + &[ + ("field".to_owned(), symbol_ref(&symbol_attr(op, "field")?)), + ("pcs".to_owned(), symbol_ref(&symbol_attr(op, "pcs")?)), + ( + "transcript".to_owned(), + symbol_ref(&symbol_attr(op, "transcript")?), + ), + ], + )?; + } + "compute.kernel" => { + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["relation", "kind", "backend", "abi"])?; + context.append_op_with_owned_attrs(&cpu, "cpu.kernel", Some(&symbol), &attrs)?; + } + "compute.transcript_init" => { + let attrs = vec![("scheme".to_owned(), symbol_ref(&symbol_attr(op, "scheme")?))]; + let symbol = string_attr(op, "sym_name")?; + let operation = context.append_typed_op_with_owned_attrs( + &cpu, + "cpu.transcript_init", + Some(&symbol), + &attrs, + &[], + &["!cpu.transcript_state"], + )?; + let value = first_result(operation, "cpu.transcript_init")?; + let inserted = value_map.insert(operation_result_key(op)?, value); + debug_assert!(inserted.is_none()); + } + "compute.oracle_dense_trace" + | "compute.oracle_one_hot_chunk" + | "compute.oracle_optional_advice" + | "compute.oracle_ref" => { + let target_op = operation_name(op).replacen("compute.", "cpu.", 1); + let attrs = copy_attrs( + op, + &[ + "oracle", + "source", + "domain", + "num_vars", + "trace_num_vars", + "chunk", + "num_chunks", + "chunk_bits", + "padding", + "layout", + "skip_policy", + ], + )?; + let symbol = string_attr(op, "sym_name")?; + let operation = context.append_typed_op_with_owned_attrs( + &cpu, + &target_op, + Some(&symbol), + &attrs, + &[], + &["!cpu.oracle_buffer"], + )?; + let value = first_result(operation, &target_op)?; + let inserted = value_map.insert(operation_result_key(op)?, value); + debug_assert!(inserted.is_none()); + } + "compute.oracle_family_init" => { + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["family", "count"])?; + let operation = context.append_typed_op_with_owned_attrs( + &cpu, + "cpu.oracle_family_init", + Some(&symbol), + &attrs, + &[], + &["!cpu.oracle_family"], + )?; + let value = first_result(operation, "cpu.oracle_family_init")?; + let inserted = value_map.insert(operation_result_key(op)?, value); + debug_assert!(inserted.is_none()); + } + "compute.oracle_family_append" => { + let input = operand_key(op, 0)?; + let oracle = operand_key(op, 1)?; + let input = value_map.get(&input).copied().ok_or_else(|| { + schema_error("compute.oracle_family_append input operand was not lowered") + })?; + let oracle = value_map.get(&oracle).copied().ok_or_else(|| { + schema_error("compute.oracle_family_append oracle operand was not lowered") + })?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["family", "oracle", "index"])?; + let operation = context.append_typed_op_with_owned_attrs( + &cpu, + "cpu.oracle_family_append", + Some(&symbol), + &attrs, + &[input, oracle], + &["!cpu.oracle_family"], + )?; + let value = first_result(operation, "cpu.oracle_family_append")?; + let inserted = value_map.insert(operation_result_key(op)?, value); + debug_assert!(inserted.is_none()); + } + "compute.pcs_commit_batch" | "compute.pcs_receive_batch" => { + let target_op = match operation_name(op).as_str() { + "compute.pcs_commit_batch" => "cpu.pcs_commit_batch", + "compute.pcs_receive_batch" => "cpu.pcs_receive_batch", + _ => unreachable!(), + }; + let attrs = vec![ + ( + "artifact".to_owned(), + symbol_ref(&symbol_attr(op, "artifact")?), + ), + ("count".to_owned(), int_attr_source(int_attr(op, "count")?)), + ("domain".to_owned(), symbol_ref(&symbol_attr(op, "domain")?)), + ( + "label".to_owned(), + string_attr_source(&string_attr(op, "label")?), + ), + ( + "num_vars".to_owned(), + int_attr_source(int_attr(op, "num_vars")?), + ), + ( + "oracle_family".to_owned(), + symbol_ref(&symbol_attr(op, "oracle_family")?), + ), + ( + "ordered_oracles".to_owned(), + symbol_array_attr_source(&symbol_array_attr(op, "ordered_oracles")?), + ), + ("pcs".to_owned(), symbol_ref(&symbol_attr(op, "pcs")?)), + ]; + let oracles = operand_key(op, 0)?; + let oracles = value_map.get(&oracles).copied().ok_or_else(|| { + schema_error("compute.pcs batch oracle family was not lowered") + })?; + let symbol = string_attr(op, "sym_name")?; + let operation = context.append_typed_op_with_owned_attrs( + &cpu, + target_op, + Some(&symbol), + &attrs, + &[oracles], + &["!cpu.commitment_artifact"], + )?; + let value = first_result(operation, target_op)?; + let inserted = value_map.insert(operation_result_key(op)?, value); + debug_assert!(inserted.is_none()); + } + "compute.pcs_commit_optional" | "compute.pcs_receive_optional" => { + let target_op = match operation_name(op).as_str() { + "compute.pcs_commit_optional" => "cpu.pcs_commit_optional", + "compute.pcs_receive_optional" => "cpu.pcs_receive_optional", + _ => unreachable!(), + }; + let attrs = vec![ + ( + "artifact".to_owned(), + symbol_ref(&symbol_attr(op, "artifact")?), + ), + ("domain".to_owned(), symbol_ref(&symbol_attr(op, "domain")?)), + ( + "label".to_owned(), + string_attr_source(&string_attr(op, "label")?), + ), + ( + "num_vars".to_owned(), + int_attr_source(int_attr(op, "num_vars")?), + ), + ("oracle".to_owned(), symbol_ref(&symbol_attr(op, "oracle")?)), + ("pcs".to_owned(), symbol_ref(&symbol_attr(op, "pcs")?)), + ( + "skip_policy".to_owned(), + string_attr_source(&string_attr(op, "skip_policy")?), + ), + ]; + let oracle = operand_key(op, 0)?; + let oracle = value_map + .get(&oracle) + .copied() + .ok_or_else(|| schema_error("compute.pcs optional oracle was not lowered"))?; + let symbol = string_attr(op, "sym_name")?; + let operation = context.append_typed_op_with_owned_attrs( + &cpu, + target_op, + Some(&symbol), + &attrs, + &[oracle], + &["!cpu.commitment_artifact"], + )?; + let value = first_result(operation, target_op)?; + let inserted = value_map.insert(operation_result_key(op)?, value); + debug_assert!(inserted.is_none()); + } + "compute.transcript_absorb" => { + let input = operand_key(op, 0)?; + let artifact = operand_key(op, 1)?; + let input = value_map.get(&input).copied().ok_or_else(|| { + schema_error("compute.transcript_absorb input operand was not lowered") + })?; + let artifact = value_map.get(&artifact).copied().ok_or_else(|| { + schema_error("compute.transcript_absorb artifact operand was not lowered") + })?; + let attrs = vec![ + ( + "label".to_owned(), + string_attr_source(&string_attr(op, "label")?), + ), + ( + "optional".to_owned(), + bool_attr_source(bool_attr(op, "optional")?).to_owned(), + ), + ]; + let symbol = string_attr(op, "sym_name")?; + let operation = context.append_typed_op_with_owned_attrs( + &cpu, + "cpu.transcript_absorb", + Some(&symbol), + &attrs, + &[input, artifact], + &["!cpu.transcript_state"], + )?; + let output = first_result(operation, "cpu.transcript_absorb")?; + let inserted = value_map.insert(operation_result_key(op)?, output); + debug_assert!(inserted.is_none()); + } + "compute.transcript_absorb_bytes" => { + let operands = lowered_operands(op, &value_map)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["label", "payload"])?; + let operation = context.append_typed_op_with_owned_attrs( + &cpu, + "cpu.transcript_absorb_bytes", + Some(&symbol), + &attrs, + &operands, + &["!cpu.transcript_state"], + )?; + let output = first_result(operation, "cpu.transcript_absorb_bytes")?; + let inserted = value_map.insert(operation_result_key(op)?, output); + debug_assert!(inserted.is_none()); + } + "compute.transcript_squeeze" => { + let operands = lowered_operands(op, &value_map)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["label", "kind", "count"])?; + let result_types = transcript_squeeze_cpu_result_types(op)?; + let operation = context.append_typed_op_with_owned_attrs( + &cpu, + "cpu.transcript_squeeze", + Some(&symbol), + &attrs, + &operands, + &result_types, + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + insert_result_mapping(&mut value_map, op, operation, 1, 1)?; + } + "compute.opening_input" => { + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs( + op, + &[ + "source_stage", + "source_claim", + "oracle", + "domain", + "point_arity", + "claim_kind", + ], + )?; + let operation = context.append_typed_op_with_owned_attrs( + &cpu, + "cpu.opening_input", + Some(&symbol), + &attrs, + &[], + &["!cpu.point", "!cpu.field_value", "!cpu.opening_claim_type"], + )?; + for index in 0..3 { + insert_result_mapping(&mut value_map, op, operation, index, index)?; + } + } + "compute.point_slice" => { + let operands = lowered_operands(op, &value_map)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["source", "offset", "length"])?; + let operation = context.append_typed_op_with_owned_attrs( + &cpu, + "cpu.point_slice", + Some(&symbol), + &attrs, + &operands, + &["!cpu.point"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "compute.point_zero" => { + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["field", "arity"])?; + let operation = context.append_typed_op_with_owned_attrs( + &cpu, + "cpu.point_zero", + Some(&symbol), + &attrs, + &[], + &["!cpu.point"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "compute.point_concat" => { + let operands = lowered_operands(op, &value_map)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["layout", "arity"])?; + let operation = context.append_typed_op_with_owned_attrs( + &cpu, + "cpu.point_concat", + Some(&symbol), + &attrs, + &operands, + &["!cpu.point"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "compute.field_const" => { + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["field", "value"])?; + let operation = context.append_typed_op_with_owned_attrs( + &cpu, + "cpu.field_const", + Some(&symbol), + &attrs, + &[], + &["!cpu.field_value"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "compute.field_zero" | "compute.field_one" => { + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["field"])?; + let operation = context.append_typed_op_with_owned_attrs( + &cpu, + &operation_name(op).replace("compute.", "cpu."), + Some(&symbol), + &attrs, + &[], + &["!cpu.field_value"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "compute.field_add" + | "compute.field_sub" + | "compute.field_mul" + | "compute.field_neg" + | "compute.field_pow" + | "compute.poly_lagrange_basis_eval" => { + let operands = lowered_operands(op, &value_map)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = compute_field_attrs(op)?; + let operation = context.append_typed_op_with_owned_attrs( + &cpu, + &operation_name(op).replace("compute.", "cpu."), + Some(&symbol), + &attrs, + &operands, + &["!cpu.field_value"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "compute.sumcheck_kernel_claim" => { + let operands = lowered_operands(op, &value_map)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs( + op, + &["stage", "domain", "num_rounds", "degree", "claim", "kernel"], + )?; + let operation = context.append_typed_op_with_owned_attrs( + &cpu, + "cpu.sumcheck_claim", + Some(&symbol), + &attrs, + &operands, + &["!cpu.sumcheck_claim_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "compute.sumcheck_verify_claim" => { + let operands = lowered_operands(op, &value_map)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs( + op, + &[ + "stage", + "domain", + "num_rounds", + "degree", + "claim", + "relation", + ], + )?; + let operation = context.append_typed_op_with_owned_attrs( + &cpu, + "cpu.sumcheck_verify_claim", + Some(&symbol), + &attrs, + &operands, + &["!cpu.sumcheck_claim_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "compute.sumcheck_batch" => { + let operands = lowered_operands(op, &value_map)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs( + op, + &[ + "stage", + "proof_slot", + "policy", + "count", + "ordered_claims", + "claim_label", + "round_label", + "round_schedule", + ], + )?; + let operation = context.append_typed_op_with_owned_attrs( + &cpu, + "cpu.sumcheck_batch", + Some(&symbol), + &attrs, + &operands, + &["!cpu.sumcheck_batch_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "compute.sumcheck_kernel_driver" => { + let operands = lowered_operands(op, &value_map)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs( + op, + &[ + "stage", + "proof_slot", + "kernel", + "policy", + "round_schedule", + "claim_label", + "round_label", + "num_rounds", + "degree", + ], + )?; + let operation = context.append_typed_op_with_owned_attrs( + &cpu, + "cpu.sumcheck_driver", + Some(&symbol), + &attrs, + &operands, + &[ + "!cpu.transcript_state", + "!cpu.point", + "!cpu.sumcheck_result_type", + "!cpu.sumcheck_proof_type", + ], + )?; + for index in 0..4 { + insert_result_mapping(&mut value_map, op, operation, index, index)?; + } + } + "compute.sumcheck_verify" => { + let operands = lowered_operands(op, &value_map)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs( + op, + &[ + "stage", + "proof_slot", + "relation", + "policy", + "round_schedule", + "claim_label", + "round_label", + "num_rounds", + "degree", + ], + )?; + let operation = context.append_typed_op_with_owned_attrs( + &cpu, + "cpu.sumcheck_verify", + Some(&symbol), + &attrs, + &operands, + &[ + "!cpu.transcript_state", + "!cpu.point", + "!cpu.sumcheck_result_type", + "!cpu.sumcheck_proof_type", + ], + )?; + for index in 0..4 { + insert_result_mapping(&mut value_map, op, operation, index, index)?; + } + } + "compute.sumcheck_eval" => { + let operands = lowered_operands(op, &value_map)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["source", "name", "index", "oracle"])?; + let operation = context.append_typed_op_with_owned_attrs( + &cpu, + "cpu.sumcheck_eval", + Some(&symbol), + &attrs, + &operands, + &["!cpu.field_value"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "compute.sumcheck_instance_result" => { + let operands = lowered_operands(op, &value_map)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs( + op, + &[ + "source", + "claim", + "relation", + "index", + "point_arity", + "num_rounds", + "round_offset", + "point_order", + "degree", + ], + )?; + let operation = context.append_typed_op_with_owned_attrs( + &cpu, + "cpu.sumcheck_instance_result", + Some(&symbol), + &attrs, + &operands, + &["!cpu.point", "!cpu.sumcheck_result_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + insert_result_mapping(&mut value_map, op, operation, 1, 1)?; + } + "compute.opening_claim" => { + let operands = lowered_operands(op, &value_map)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["oracle", "domain", "point_arity", "claim_kind"])?; + let operation = context.append_typed_op_with_owned_attrs( + &cpu, + "cpu.opening_claim", + Some(&symbol), + &attrs, + &operands, + &["!cpu.opening_claim_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "compute.opening_claim_equal" => { + let operands = lowered_operands(op, &value_map)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["mode"])?; + let _operation = context.append_typed_op_with_owned_attrs( + &cpu, + "cpu.opening_claim_equal", + Some(&symbol), + &attrs, + &operands, + &[], + )?; + } + "compute.opening_batch" => { + let operands = lowered_operands(op, &value_map)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs( + op, + &["stage", "proof_slot", "policy", "count", "ordered_claims"], + )?; + let operation = context.append_typed_op_with_owned_attrs( + &cpu, + "cpu.opening_batch", + Some(&symbol), + &attrs, + &operands, + &["!cpu.opening_batch_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "compute.pcs_opening_claim" => { + let operands = lowered_operands(op, &value_map)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["oracle", "family", "domain", "point_arity"])?; + let operation = context.append_typed_op_with_owned_attrs( + &cpu, + "cpu.pcs_opening_claim", + Some(&symbol), + &attrs, + &operands, + &["!cpu.opening_claim_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "compute.pcs_opening_batch" => { + let operands = lowered_operands(op, &value_map)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["proof_slot", "policy", "count", "ordered_claims"])?; + let operation = context.append_typed_op_with_owned_attrs( + &cpu, + "cpu.pcs_opening_batch", + Some(&symbol), + &attrs, + &operands, + &["!cpu.opening_batch_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "compute.pcs_batch_open" | "compute.pcs_batch_verify" => { + let target_op = match operation_name(op).as_str() { + "compute.pcs_batch_open" => "cpu.pcs_batch_open", + "compute.pcs_batch_verify" => "cpu.pcs_batch_verify", + _ => unreachable!(), + }; + let operands = lowered_operands(op, &value_map)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["pcs", "proof_slot", "transcript_label"])?; + let operation = context.append_typed_op_with_owned_attrs( + &cpu, + target_op, + Some(&symbol), + &attrs, + &operands, + &["!cpu.transcript_state", "!cpu.opening_proof_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + insert_result_mapping(&mut value_map, op, operation, 1, 1)?; + } + _ => {} + } + } + verify_module(&cpu)?; + verify_cpu_schema(&cpu)?; + Ok(cpu) +} + +#[derive(Clone, Debug)] +struct ConcreteCommitmentAst { + params: ParamsAst, + oracle_buffers: BTreeMap, + batch_plans: Vec, + optional_plans: Vec, + transcript_steps: Vec, +} + +#[derive(Clone, Debug)] +struct ParamsAst { + field: String, + pcs: String, + transcript: String, + log_t: usize, + log_k_chunk: usize, + instruction_d: usize, + bytecode_d: usize, + ram_d: usize, +} + +#[derive(Clone, Debug)] +struct DomainAst { + num_vars: usize, +} + +#[derive(Clone, Debug)] +struct OracleAst { + domain: String, + commit_domain: String, + layout: String, +} + +#[derive(Clone, Debug)] +struct OracleBufferAst { + domain: String, + num_vars: usize, +} + +#[derive(Clone, Debug)] +struct OracleFamilyAst { + oracles: Vec, + count: usize, + domain: String, +} + +#[derive(Clone, Debug)] +struct PublishedBatchAst { + artifact: String, + oracle_family: String, + label: String, +} + +#[derive(Clone, Debug)] +struct PublishedOptionalAst { + artifact: String, + oracle: String, + label: String, + skip_policy: String, +} + +#[derive(Clone, Debug)] +struct BatchPlanAst { + artifact: String, + pcs: String, + oracle_family: String, + oracles: Vec, + label: String, + domain: String, + num_vars: usize, + count: usize, +} + +#[derive(Clone, Debug)] +struct OptionalPlanAst { + artifact: String, + pcs: String, + oracle: String, + label: String, + domain: String, + num_vars: usize, + skip_policy: String, +} + +#[derive(Clone, Debug)] +struct TranscriptStepAst { + symbol: String, + label: String, + source: String, + optional: bool, +} + +fn analyze_concrete

(module: &BoltModule<'_, P>) -> Result +where + P: crate::ir::Phase, +{ + let mut params = None; + let mut domains = BTreeMap::new(); + let mut oracles = BTreeMap::new(); + let mut families = BTreeMap::new(); + let mut published_batches = Vec::new(); + let mut published_optional = Vec::new(); + let mut pcs_by_artifact = BTreeMap::new(); + let mut transcript_steps = Vec::new(); + + let mut operation = module.as_mlir_module().body().first_operation(); + while let Some(op) = operation { + operation = op.next_in_block(); + match operation_name(op).as_str() { + "protocol.params" => { + params = Some(ParamsAst { + field: symbol_attr(op, "field")?, + pcs: symbol_attr(op, "pcs")?, + transcript: symbol_attr(op, "transcript")?, + log_t: int_attr(op, "log_t")?, + log_k_chunk: int_attr(op, "log_k_chunk")?, + instruction_d: int_attr(op, "instruction_d")?, + bytecode_d: int_attr(op, "bytecode_d")?, + ram_d: int_attr(op, "ram_d")?, + }); + } + "poly.domain" => { + let _ = domains.insert( + string_attr(op, "sym_name")?, + DomainAst { + num_vars: int_attr(op, "log_size")?, + }, + ); + } + "piop.oracle" => { + let _ = oracles.insert( + string_attr(op, "sym_name")?, + OracleAst { + domain: symbol_attr(op, "domain")?, + commit_domain: symbol_attr(op, "commit_domain")?, + layout: string_attr(op, "layout")?, + }, + ); + } + "piop.oracle_family" => { + let _ = families.insert( + string_attr(op, "sym_name")?, + OracleFamilyAst { + oracles: symbol_array_attr(op, "ordered_oracles")?, + count: int_attr(op, "count")?, + domain: symbol_attr(op, "domain")?, + }, + ); + } + "commit.publish_batch" => published_batches.push(PublishedBatchAst { + artifact: string_attr(op, "sym_name")?, + oracle_family: symbol_attr(op, "oracle_family")?, + label: string_attr(op, "label")?, + }), + "commit.publish_optional" => published_optional.push(PublishedOptionalAst { + artifact: string_attr(op, "sym_name")?, + oracle: symbol_attr(op, "oracle")?, + label: string_attr(op, "label")?, + skip_policy: string_attr(op, "skip_policy")?, + }), + "pcs.commit_batch" => { + let _ = pcs_by_artifact + .insert(pcs_commitment_artifact(op)?, symbol_attr(op, "scheme")?); + } + "transcript.absorb" | "transcript.absorb_optional" => { + transcript_steps.push(TranscriptStepAst { + symbol: string_attr(op, "sym_name")?, + label: string_attr(op, "label")?, + source: transcript_artifact_source(op)?, + optional: operation_name(op) == "transcript.absorb_optional", + }); + } + _ => {} + } + } + + let params = params.ok_or_else(|| schema_error("missing protocol.params"))?; + let mut oracle_buffers = BTreeMap::new(); + for (symbol, oracle) in &oracles { + let buffer_domain = oracle_buffer_domain(oracle); + let domain = domains.get(buffer_domain).ok_or_else(|| { + schema_error(format!( + "oracle @{symbol} references missing buffer domain @{buffer_domain}" + )) + })?; + let _ = oracle_buffers.insert( + symbol.clone(), + OracleBufferAst { + domain: buffer_domain.to_owned(), + num_vars: domain.num_vars, + }, + ); + } + + let mut batch_plans = Vec::new(); + for batch in published_batches { + let family = families.get(&batch.oracle_family).ok_or_else(|| { + schema_error(format!( + "commitment artifact @{} references missing oracle family @{}", + batch.artifact, batch.oracle_family + )) + })?; + let domain = domains.get(&family.domain).ok_or_else(|| { + schema_error(format!( + "oracle family @{} references missing domain @{}", + batch.oracle_family, family.domain + )) + })?; + batch_plans.push(BatchPlanAst { + pcs: pcs_by_artifact + .get(&batch.artifact) + .cloned() + .unwrap_or_else(|| params.pcs.clone()), + artifact: batch.artifact, + oracle_family: batch.oracle_family, + oracles: family.oracles.clone(), + label: batch.label, + domain: family.domain.clone(), + num_vars: domain.num_vars, + count: family.count, + }); + } + + let mut optional_plans = Vec::new(); + for optional in published_optional { + let oracle = oracles.get(&optional.oracle).ok_or_else(|| { + schema_error(format!( + "commitment artifact @{} references missing oracle @{}", + optional.artifact, optional.oracle + )) + })?; + let domain = domains.get(&oracle.commit_domain).ok_or_else(|| { + schema_error(format!( + "oracle @{} references missing commit domain @{}", + optional.oracle, oracle.commit_domain + )) + })?; + optional_plans.push(OptionalPlanAst { + pcs: params.pcs.clone(), + artifact: optional.artifact, + oracle: optional.oracle, + label: optional.label, + domain: oracle.commit_domain.clone(), + num_vars: domain.num_vars, + skip_policy: optional.skip_policy, + }); + } + + Ok(ConcreteCommitmentAst { + params, + oracle_buffers, + batch_plans, + optional_plans, + transcript_steps, + }) +} + +fn oracle_buffer_domain(oracle: &OracleAst) -> &str { + if oracle.layout == "onehot_expanded" { + &oracle.commit_domain + } else { + &oracle.domain + } +} + +fn append_oracle_buffer<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Compute>, + role: &Role, + params: &ParamsAst, + oracle: &str, + domain: &str, + num_vars: usize, +) -> Result, MlirError> { + let symbol = format!("jolt.oracle.{oracle}.compute"); + match role { + Role::Verifier => append_oracle_ref(context, module, &symbol, oracle, domain, num_vars), + Role::Prover => { + let recipe = oracle_recipe(oracle, params)?; + let attrs = recipe.attrs(oracle, domain, num_vars, params); + let operation = context.append_typed_op_with_owned_attrs( + module, + recipe.op_name(), + Some(&symbol), + &attrs, + &[], + &["!compute.oracle_buffer"], + )?; + first_result(operation, recipe.op_name()) + } + } +} + +fn append_optional_oracle_buffer<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Compute>, + role: &Role, + oracle: &str, + domain: &str, + num_vars: usize, + skip_policy: &str, +) -> Result, MlirError> { + let symbol = format!("jolt.oracle.{oracle}.compute"); + match role { + Role::Verifier => append_oracle_ref(context, module, &symbol, oracle, domain, num_vars), + Role::Prover => { + let operation = context.append_typed_op_with_owned_attrs( + module, + "compute.oracle_optional_advice", + Some(&symbol), + &[ + ("oracle".to_owned(), symbol_ref(oracle)), + ( + "source".to_owned(), + symbol_ref(&optional_advice_source(oracle)?), + ), + ("domain".to_owned(), symbol_ref(domain)), + ("num_vars".to_owned(), int_attr_source(num_vars)), + ("skip_policy".to_owned(), string_attr_source(skip_policy)), + ], + &[], + &["!compute.oracle_buffer"], + )?; + first_result(operation, "compute.oracle_optional_advice") + } + } +} + +fn append_oracle_ref<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Compute>, + symbol: &str, + oracle: &str, + domain: &str, + num_vars: usize, +) -> Result, MlirError> { + let operation = context.append_typed_op_with_owned_attrs( + module, + "compute.oracle_ref", + Some(symbol), + &[ + ("oracle".to_owned(), symbol_ref(oracle)), + ("domain".to_owned(), symbol_ref(domain)), + ("num_vars".to_owned(), int_attr_source(num_vars)), + ], + &[], + &["!compute.oracle_buffer"], + )?; + first_result(operation, "compute.oracle_ref") +} + +#[derive(Clone, Debug)] +enum OracleRecipe { + DenseTrace { + source: &'static str, + }, + OneHotChunk { + source: &'static str, + chunk: usize, + num_chunks: usize, + padding: &'static str, + }, +} + +impl OracleRecipe { + fn op_name(&self) -> &'static str { + match self { + Self::DenseTrace { .. } => "compute.oracle_dense_trace", + Self::OneHotChunk { .. } => "compute.oracle_one_hot_chunk", + } + } + + fn attrs( + &self, + oracle: &str, + domain: &str, + num_vars: usize, + params: &ParamsAst, + ) -> Vec<(String, String)> { + let mut attrs = vec![ + ("oracle".to_owned(), symbol_ref(oracle)), + ("domain".to_owned(), symbol_ref(domain)), + ("num_vars".to_owned(), int_attr_source(num_vars)), + ]; + match self { + Self::DenseTrace { source } => { + attrs.push(("source".to_owned(), symbol_ref(source))); + attrs.push(("padding".to_owned(), string_attr_source("zero"))); + } + Self::OneHotChunk { + source, + chunk, + num_chunks, + padding, + } => { + attrs.push(("source".to_owned(), symbol_ref(source))); + attrs.push(("trace_num_vars".to_owned(), int_attr_source(params.log_t))); + attrs.push(("chunk".to_owned(), int_attr_source(*chunk))); + attrs.push(("num_chunks".to_owned(), int_attr_source(*num_chunks))); + attrs.push(("chunk_bits".to_owned(), int_attr_source(params.log_k_chunk))); + attrs.push(("padding".to_owned(), string_attr_source(padding))); + attrs.push(("layout".to_owned(), string_attr_source("address_major"))); + } + } + attrs + } +} + +fn oracle_recipe(oracle: &str, params: &ParamsAst) -> Result { + if oracle == "RdInc" { + return Ok(OracleRecipe::DenseTrace { + source: "trace.rd_inc", + }); + } + if oracle == "RamInc" { + return Ok(OracleRecipe::DenseTrace { + source: "trace.ram_inc", + }); + } + if let Some(index) = parse_indexed_oracle(oracle, "InstructionRa") { + return Ok(OracleRecipe::OneHotChunk { + source: "trace.instruction_keys", + chunk: index, + num_chunks: params.instruction_d, + padding: "zero", + }); + } + if let Some(index) = parse_indexed_oracle(oracle, "RamRa") { + return Ok(OracleRecipe::OneHotChunk { + source: "trace.ram_addresses", + chunk: index, + num_chunks: params.ram_d, + padding: "none", + }); + } + if let Some(index) = parse_indexed_oracle(oracle, "BytecodeRa") { + return Ok(OracleRecipe::OneHotChunk { + source: "trace.bytecode_indices", + chunk: index, + num_chunks: params.bytecode_d, + padding: "zero", + }); + } + Err(schema_error(format!( + "unsupported commitment oracle @{oracle}" + ))) +} + +fn parse_indexed_oracle(oracle: &str, prefix: &str) -> Option { + oracle.strip_prefix(prefix)?.strip_prefix('_')?.parse().ok() +} + +fn optional_advice_source(oracle: &str) -> Result { + match oracle { + "UntrustedAdvice" => Ok("advice.untrusted".to_owned()), + "TrustedAdvice" => Ok("advice.trusted".to_owned()), + _ => Err(schema_error(format!( + "unsupported optional advice oracle @{oracle}" + ))), + } +} + +fn bool_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .map(|attribute| match attribute.to_string().as_str() { + "true" => Some(true), + "false" => Some(false), + _ => None, + }) + .ok() + .flatten() + .ok_or_else(|| { + schema_error(format!( + "{} attr `{attr}` is not a bool", + operation_name(operation) + )) + }) +} + +fn operation_result_key(operation: OperationRef<'_, '_>) -> Result { + operation_result_key_at(operation, 0) +} + +fn operation_result_key_at( + operation: OperationRef<'_, '_>, + index: usize, +) -> Result { + let result = operation.result(index).map_err(|_| { + schema_error(format!( + "{} requires result {index}", + operation_name(operation) + )) + })?; + result_key(result.owner(), result.result_number()) +} + +fn result_key(operation: OperationRef<'_, '_>, result_number: usize) -> Result { + Ok(format!( + "{}#{result_number}", + string_attr(operation, "sym_name")? + )) +} + +fn operand_key(operation: OperationRef<'_, '_>, index: usize) -> Result { + let operand = operation.operand(index).map_err(|_| { + schema_error(format!( + "{} requires operand {index}", + operation_name(operation) + )) + })?; + let owner = OperationResult::try_from(operand).map_err(|_| { + schema_error(format!( + "{} operand {index} must be an op result", + operation_name(operation) + )) + })?; + result_key(owner.owner(), owner.result_number()).map_err(|_| { + schema_error(format!( + "{} operand {index} owner missing sym_name", + operation_name(operation) + )) + }) +} + +fn lowered_operands<'c, 'a>( + operation: OperationRef<'_, '_>, + value_map: &BTreeMap>, +) -> Result>, MlirError> { + (0..operation.operand_count()) + .map(|index| { + let key = operand_key(operation, index)?; + value_map.get(&key).copied().ok_or_else(|| { + schema_error(format!( + "{} operand {index} was not lowered", + operation_name(operation) + )) + }) + }) + .collect() +} + +fn insert_result_mapping<'c, 'a>( + value_map: &mut BTreeMap>, + source: OperationRef<'_, '_>, + target: OperationRef<'c, 'a>, + source_index: usize, + target_index: usize, +) -> Result<(), MlirError> { + let key = operation_result_key_at(source, source_index)?; + let value = target.result(target_index).map(Into::into).map_err(|_| { + schema_error(format!( + "{} requires result {target_index}", + operation_name(target) + )) + })?; + let inserted = value_map.insert(key, value); + debug_assert!(inserted.is_none()); + Ok(()) +} + +fn first_result<'c, 'a>( + operation: OperationRef<'c, 'a>, + operation_name: &str, +) -> Result, MlirError> { + operation + .result(0) + .map(Into::into) + .map_err(|_| schema_error(format!("{operation_name} requires one result"))) +} + +fn pcs_commitment_artifact(operation: OperationRef<'_, '_>) -> Result { + let artifact = operation.operand(0).map_err(|_| { + schema_error(format!( + "{} requires commitment artifact operand 0", + operation_name(operation) + )) + })?; + let owner = OperationResult::try_from(artifact).map_err(|_| { + schema_error(format!( + "{} commitment operand must be an op result", + operation_name(operation) + )) + })?; + string_attr(owner.owner(), "sym_name") +} + +fn transcript_artifact_source(operation: OperationRef<'_, '_>) -> Result { + if let Ok(source) = symbol_attr(operation, "source") { + return Ok(source); + } + let artifact = operation.operand(1).map_err(|_| { + schema_error(format!( + "{} requires commitment artifact operand 1", + operation_name(operation) + )) + })?; + let owner = OperationResult::try_from(artifact).map_err(|_| { + schema_error(format!( + "{} artifact operand must be an op result", + operation_name(operation) + )) + })?; + string_attr(owner.owner(), "sym_name") +} + +fn schema_error(message: impl Into) -> MlirError { + let error = SchemaError::new(message); + error.into() +} + +fn symbol_ref(value: &str) -> String { + format!("@{value}") +} + +fn string_attr_source(value: &str) -> String { + format!("{value:?}") +} + +fn symbol_array_attr_source(values: &[String]) -> String { + let values = values + .iter() + .map(|value| format!("@{value}")) + .collect::>() + .join(", "); + format!("[{values}]") +} + +fn int_attr_source(value: usize) -> String { + format!("{value} : i64") +} + +fn bool_attr_source(value: bool) -> &'static str { + if value { + "true" + } else { + "false" + } +} diff --git a/crates/bolt/src/protocols/jolt/phases/lowering.rs b/crates/bolt/src/protocols/jolt/phases/lowering.rs new file mode 100644 index 0000000000..ed50ed20db --- /dev/null +++ b/crates/bolt/src/protocols/jolt/phases/lowering.rs @@ -0,0 +1,641 @@ +use std::collections::BTreeMap; + +use melior::ir::block::BlockLike; +use melior::ir::operation::OperationResult; +use melior::ir::operation::{OperationLike, OperationRef}; +use melior::ir::Value; + +use crate::ir::{string_attribute_value, BoltModule, Compute, Party, Role}; +use crate::mlir::{verify_module, MeliorContext, MlirError}; +use crate::schema::{operation_name, verify_compute_schema, verify_party_schema, SchemaError}; + +pub(super) fn copy_attrs( + operation: OperationRef<'_, '_>, + attrs: &[&str], +) -> Result, MlirError> { + attrs + .iter() + .filter_map(|attr| { + operation + .attribute(attr) + .ok() + .map(|value| Ok(((*attr).to_owned(), value.to_string()))) + }) + .collect() +} + +pub(super) fn string_attr( + operation: OperationRef<'_, '_>, + attr: &str, +) -> Result { + operation + .attribute(attr) + .ok() + .and_then(string_attribute_value) + .ok_or_else(|| { + schema_error(format!( + "{} attr `{attr}` is not a string", + operation_name(operation) + )) + }) +} + +pub(super) fn transcript_squeeze_protocol_result_type( + kind: &str, +) -> Result<&'static str, MlirError> { + transcript_squeeze_value_type(kind, "!poly.point", "!field.scalar") +} + +pub(super) fn transcript_squeeze_compute_result_types( + operation: OperationRef<'_, '_>, +) -> Result<[&'static str; 2], MlirError> { + Ok([ + "!compute.transcript_state", + transcript_squeeze_value_type( + string_attr(operation, "kind")?.as_str(), + "!compute.point", + "!compute.field_value", + )?, + ]) +} + +pub(super) fn transcript_squeeze_cpu_result_types( + operation: OperationRef<'_, '_>, +) -> Result<[&'static str; 2], MlirError> { + Ok([ + "!cpu.transcript_state", + transcript_squeeze_value_type( + string_attr(operation, "kind")?.as_str(), + "!cpu.point", + "!cpu.field_value", + )?, + ]) +} + +pub(super) fn field_lowering_attrs( + operation: OperationRef<'_, '_>, +) -> Result, MlirError> { + match operation_name(operation).as_str() { + "field.pow" | "compute.field_pow" => copy_attrs(operation, &["exponent"]), + "poly.lagrange_basis_eval" | "compute.poly_lagrange_basis_eval" => { + copy_attrs(operation, &["domain_start", "domain_size", "index"]) + } + _ => Ok(Vec::new()), + } +} + +pub(super) fn lower_party_to_compute<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Party>, + function_symbol: &str, + source_symbol: &str, + stage_label: &str, +) -> Result, MlirError> { + verify_party_schema(module)?; + let role = module + .role() + .ok_or_else(|| schema_error(format!("{stage_label} lowering requires party role")))?; + let compute = context.new_module::(&module.name(), Some(role.clone())); + let params_attrs = compute_params_attrs(module)?; + context.append_op_with_owned_attrs( + &compute, + "compute.params", + Some("jolt.compute_params"), + ¶ms_attrs, + )?; + context.append_op( + &compute, + "compute.function", + Some(function_symbol), + &[("source", &format!("@{source_symbol}"))], + )?; + + let mut value_map = BTreeMap::new(); + let mut operation = module.as_mlir_module().body().first_operation(); + while let Some(op) = operation { + operation = op.next_in_block(); + match operation_name(op).as_str() { + "piop.relation" => { + let attrs = copy_attrs( + op, + &["kind", "domain", "num_rounds", "degree", "output_count"], + )?; + let symbol = string_attr(op, "sym_name")?; + context.append_op_with_owned_attrs( + &compute, + "compute.relation", + Some(&symbol), + &attrs, + )?; + } + "transcript.state" => { + let attrs = copy_attrs(op, &["scheme"])?; + let symbol = string_attr(op, "sym_name")?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.transcript_init", + Some(&symbol), + &attrs, + &[], + &["!compute.transcript_state"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "transcript.absorb_bytes" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["label", "payload"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.transcript_absorb_bytes", + Some(&symbol), + &attrs, + &operands, + &["!compute.transcript_state"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "transcript.squeeze" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["label", "kind", "count"])?; + let result_types = transcript_squeeze_compute_result_types(op)?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.transcript_squeeze", + Some(&symbol), + &attrs, + &operands, + &result_types, + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + insert_result_mapping(&mut value_map, op, operation, 1, 1)?; + } + "field.const" => { + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["field", "value"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.field_const", + Some(&symbol), + &attrs, + &[], + &["!compute.field_value"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "field.zero" | "field.one" => { + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["field"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + &format!("compute.{}", operation_name(op).replace('.', "_")), + Some(&symbol), + &attrs, + &[], + &["!compute.field_value"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "field.add" | "field.sub" | "field.mul" | "field.neg" | "field.pow" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = field_lowering_attrs(op)?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + &format!("compute.{}", operation_name(op).replace('.', "_")), + Some(&symbol), + &attrs, + &operands, + &["!compute.field_value"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "poly.lagrange_basis_eval" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["domain_start", "domain_size", "index"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.poly_lagrange_basis_eval", + Some(&symbol), + &attrs, + &operands, + &["!compute.field_value"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "piop.opening_input" => { + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs( + op, + &[ + "source_stage", + "source_claim", + "oracle", + "domain", + "point_arity", + "claim_kind", + ], + )?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.opening_input", + Some(&symbol), + &attrs, + &[], + &[ + "!compute.point", + "!compute.field_value", + "!compute.opening_claim_type", + ], + )?; + for index in 0..3 { + insert_result_mapping(&mut value_map, op, operation, index, index)?; + } + } + "poly.point_slice" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["source", "offset", "length"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.point_slice", + Some(&symbol), + &attrs, + &operands, + &["!compute.point"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "poly.point_zero" => { + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["field", "arity"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.point_zero", + Some(&symbol), + &attrs, + &[], + &["!compute.point"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "poly.point_concat" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["layout", "arity"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.point_concat", + Some(&symbol), + &attrs, + &operands, + &["!compute.point"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "piop.sumcheck_claim" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs( + op, + &[ + "stage", + "domain", + "num_rounds", + "degree", + "claim", + "relation", + ], + )?; + let target_op = match &role { + Role::Prover => "compute.sumcheck_claim", + Role::Verifier => "compute.sumcheck_verify_claim", + }; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + target_op, + Some(&symbol), + &attrs, + &operands, + &["!compute.sumcheck_claim_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "piop.sumcheck_batch" => { + let operands = lowered_operands(op, &value_map, 1)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs( + op, + &[ + "stage", + "proof_slot", + "policy", + "count", + "ordered_claims", + "claim_label", + "round_label", + "round_schedule", + ], + )?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.sumcheck_batch", + Some(&symbol), + &attrs, + &operands, + &["!compute.sumcheck_batch_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "piop.sumcheck" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs( + op, + &[ + "stage", + "proof_slot", + "relation", + "policy", + "round_schedule", + "claim_label", + "round_label", + "num_rounds", + "degree", + ], + )?; + let target_op = match &role { + Role::Prover => "compute.sumcheck_driver", + Role::Verifier => "compute.sumcheck_verify", + }; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + target_op, + Some(&symbol), + &attrs, + &operands, + &[ + "!compute.transcript_state", + "!compute.point", + "!compute.sumcheck_result_type", + "!compute.sumcheck_proof_type", + ], + )?; + for index in 0..4 { + insert_result_mapping(&mut value_map, op, operation, index, index)?; + } + } + "piop.sumcheck_eval" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["source", "name", "index", "oracle"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.sumcheck_eval", + Some(&symbol), + &attrs, + &operands, + &["!compute.field_value"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "piop.sumcheck_instance_result" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs( + op, + &[ + "source", + "claim", + "relation", + "index", + "point_arity", + "num_rounds", + "round_offset", + "point_order", + "degree", + ], + )?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.sumcheck_instance_result", + Some(&symbol), + &attrs, + &operands, + &["!compute.point", "!compute.sumcheck_result_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + insert_result_mapping(&mut value_map, op, operation, 1, 1)?; + } + "piop.opening_claim" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["oracle", "domain", "point_arity", "claim_kind"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.opening_claim", + Some(&symbol), + &attrs, + &operands, + &["!compute.opening_claim_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "piop.opening_claim_equal" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["mode"])?; + let _operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.opening_claim_equal", + Some(&symbol), + &attrs, + &operands, + &[], + )?; + } + "piop.opening_batch" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs( + op, + &["stage", "proof_slot", "policy", "count", "ordered_claims"], + )?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.opening_batch", + Some(&symbol), + &attrs, + &operands, + &["!compute.opening_batch_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "pcs.opening_claim" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["oracle", "family", "domain", "point_arity"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.pcs_opening_claim", + Some(&symbol), + &attrs, + &operands, + &["!compute.opening_claim_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "pcs.opening_batch" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["proof_slot", "policy", "count", "ordered_claims"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.pcs_opening_batch", + Some(&symbol), + &attrs, + &operands, + &["!compute.opening_batch_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "pcs.batch_open" | "pcs.batch_verify" => { + let target_op = match &role { + Role::Prover => "compute.pcs_batch_open", + Role::Verifier => "compute.pcs_batch_verify", + }; + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["pcs", "proof_slot", "transcript_label"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + target_op, + Some(&symbol), + &attrs, + &operands, + &["!compute.transcript_state", "!compute.opening_proof_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + insert_result_mapping(&mut value_map, op, operation, 1, 1)?; + } + _ => {} + } + } + + verify_module(&compute)?; + verify_compute_schema(&compute)?; + Ok(compute) +} + +fn compute_params_attrs( + module: &BoltModule<'_, P>, +) -> Result, MlirError> { + let mut operation = module.as_mlir_module().body().first_operation(); + while let Some(op) = operation { + operation = op.next_in_block(); + if operation_name(op) == "protocol.params" { + return copy_attrs(op, &["field", "pcs", "transcript"]); + } + } + Err(schema_error("module missing protocol.params")) +} + +fn transcript_squeeze_value_type( + kind: &str, + point_type: &'static str, + scalar_type: &'static str, +) -> Result<&'static str, MlirError> { + match kind { + "challenge_vector" => Ok(point_type), + "challenge_scalar" | "scalar" => Ok(scalar_type), + kind => Err(schema_error(format!( + "unsupported transcript squeeze kind `{kind}`" + ))), + } +} + +fn schema_error(message: impl Into) -> MlirError { + SchemaError::new(message).into() +} + +fn operation_result_key_at( + operation: OperationRef<'_, '_>, + index: usize, +) -> Result { + let result = operation.result(index).map_err(|_| { + schema_error(format!( + "{} requires result {index}", + operation_name(operation) + )) + })?; + result_key(operation, result.result_number()).map_err(|_| { + schema_error(format!( + "{} result {index} owner missing sym_name", + operation_name(operation) + )) + }) +} + +fn result_key(operation: OperationRef<'_, '_>, result_number: usize) -> Result { + let symbol = string_attr(operation, "sym_name")?; + Ok(format!("{symbol}#{result_number}")) +} + +fn operand_key(operation: OperationRef<'_, '_>, index: usize) -> Result { + let operand = operation.operand(index).map_err(|_| { + schema_error(format!( + "{} requires operand {index}", + operation_name(operation) + )) + })?; + let owner = OperationResult::try_from(operand).map_err(|_| { + schema_error(format!( + "{} operand {index} must be an op result", + operation_name(operation) + )) + })?; + result_key(owner.owner(), owner.result_number()).map_err(|_| { + schema_error(format!( + "{} operand {index} owner missing sym_name", + operation_name(operation) + )) + }) +} + +fn lowered_operands<'c, 'a>( + operation: OperationRef<'_, '_>, + value_map: &BTreeMap>, + start_index: usize, +) -> Result>, MlirError> { + (start_index..operation.operand_count()) + .map(|index| { + let key = operand_key(operation, index)?; + value_map.get(&key).copied().ok_or_else(|| { + schema_error(format!( + "{} operand {index} was not lowered", + operation_name(operation) + )) + }) + }) + .collect() +} + +fn insert_result_mapping<'c, 'a>( + value_map: &mut BTreeMap>, + source: OperationRef<'_, '_>, + target: OperationRef<'c, 'a>, + source_index: usize, + target_index: usize, +) -> Result<(), MlirError> { + let key = operation_result_key_at(source, source_index)?; + let value = target.result(target_index).map(Into::into).map_err(|_| { + schema_error(format!( + "{} requires result {target_index}", + operation_name(target) + )) + })?; + let _ = value_map.insert(key, value); + Ok(()) +} diff --git a/crates/bolt/src/protocols/jolt/phases/mod.rs b/crates/bolt/src/protocols/jolt/phases/mod.rs new file mode 100644 index 0000000000..19f9646db3 --- /dev/null +++ b/crates/bolt/src/protocols/jolt/phases/mod.rs @@ -0,0 +1,11 @@ +mod lowering; + +pub mod commitment; +pub mod stage1; +pub mod stage2; +pub mod stage3; +pub mod stage4; +pub mod stage5; +pub mod stage6; +pub mod stage7; +pub mod stage8; diff --git a/crates/bolt/src/protocols/jolt/phases/stage1.rs b/crates/bolt/src/protocols/jolt/phases/stage1.rs new file mode 100644 index 0000000000..7501e62768 --- /dev/null +++ b/crates/bolt/src/protocols/jolt/phases/stage1.rs @@ -0,0 +1,1723 @@ +use std::collections::BTreeMap; + +use melior::ir::block::BlockLike; +use melior::ir::operation::OperationRef; +use melior::ir::operation::{OperationLike, OperationResult}; +use melior::ir::Value; + +use crate::ir::{BoltModule, Compute, Party, Protocol, Role}; +use crate::mlir::{verify_module, MeliorContext, MlirError}; +use crate::schema::{ + operation_name, symbol_attr, verify_compute_schema, verify_party_schema, + verify_protocol_schema, SchemaError, +}; + +use super::super::oracles; +use super::super::params::JoltProtocolParams; +use super::lowering::{ + copy_attrs, field_lowering_attrs as field_compute_attrs, string_attr, + transcript_squeeze_compute_result_types, +}; + +const R1CS_INPUT_ORACLES: [&str; 35] = [ + "LeftInstructionInput", + "RightInstructionInput", + "Product", + "ShouldBranch", + "PC", + "UnexpandedPC", + "Imm", + "RamAddress", + "Rs1Value", + "Rs2Value", + "RdWriteValue", + "RamReadValue", + "RamWriteValue", + "LeftLookupOperand", + "RightLookupOperand", + "NextUnexpandedPC", + "NextPC", + "NextIsVirtual", + "NextIsFirstInSequence", + "LookupOutput", + "ShouldJump", + "OpFlagAddOperands", + "OpFlagSubtractOperands", + "OpFlagMultiplyOperands", + "OpFlagLoad", + "OpFlagStore", + "OpFlagJump", + "OpFlagWriteLookupOutputToRD", + "OpFlagVirtualInstruction", + "OpFlagAssert", + "OpFlagDoNotUpdateUnexpandedPC", + "OpFlagAdvice", + "OpFlagIsCompressed", + "OpFlagIsFirstInSequence", + "OpFlagIsLastInSequence", +]; +const OUTER_UNISKIP_FIRST_ROUND_DEGREE_BOUND: usize = 27; + +pub fn build_stage1_outer_protocol<'c>( + context: &'c MeliorContext, + params: &JoltProtocolParams, +) -> Result, MlirError> { + let module = context.new_module::("jolt.stage1_outer", None); + oracles::append_foundation_ops(context, &module, params)?; + context.append_op_with_owned_attrs( + &module, + "protocol.params", + Some("jolt.params"), + ¶ms.attrs(), + )?; + context.append_op( + &module, + "protocol.boundary", + Some("jolt.stage1_outer"), + &[("roles", r#"["prover", "verifier"]"#)], + )?; + append_stage1_virtual_oracles(context, &module, params)?; + append_stage1_relations(context, &module, params)?; + + let fs0 = context.append_typed_op( + &module, + "transcript.state", + Some("fs0"), + &[("scheme", "@blake2b_transcript")], + &[], + &["!transcript.state_type"], + )?; + let state = first_result(fs0, "transcript.state")?; + let tau = context.append_typed_op( + &module, + "transcript.squeeze", + Some("stage1.tau"), + &[ + ("label", r#""outer_tau""#), + ("kind", r#""challenge_vector""#), + ("count", &int_attr(params.log_t + 2)), + ], + &[state], + &["!transcript.state_type", "!poly.point"], + )?; + let state = first_result(tau, "transcript.squeeze")?; + + let stage = context.append_typed_op( + &module, + "piop.stage", + Some("stage1"), + &[ + ("name", r#""spartan_outer""#), + ("order", "1 : i64"), + ("roles", r#"["prover", "verifier"]"#), + ], + &[], + &["!piop.stage_type"], + )?; + let stage = first_result(stage, "piop.stage")?; + let zero_claim = append_field_zero(context, &module, "stage1.zero")?; + + let (state, uniskip_opening, uniskip_eval) = + append_uniskip_sumcheck(context, &module, params, state, stage, zero_claim)?; + let _state = append_remaining_sumcheck( + context, + &module, + params, + state, + stage, + uniskip_eval, + uniskip_opening, + )?; + + verify_module(&module)?; + verify_protocol_schema(&module)?; + Ok(module) +} + +pub fn lower_stage1_to_compute<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Party>, +) -> Result, MlirError> { + verify_party_schema(module)?; + let role = module + .role() + .ok_or_else(|| schema_error("stage1 lowering requires party role"))?; + let params = stage_params(module)?; + let compute = context.new_module::(&module.name(), Some(role.clone())); + context.append_op_with_owned_attrs( + &compute, + "compute.params", + Some("jolt.compute_params"), + &[ + ("field".to_owned(), symbol_ref(¶ms.field)), + ("pcs".to_owned(), symbol_ref(¶ms.pcs)), + ("transcript".to_owned(), symbol_ref(¶ms.transcript)), + ], + )?; + context.append_op( + &compute, + "compute.function", + Some("jolt.stage1_outer"), + &[("source", "@jolt.stage1_outer")], + )?; + + let mut value_map = BTreeMap::new(); + let mut operation = module.as_mlir_module().body().first_operation(); + while let Some(op) = operation { + operation = op.next_in_block(); + match operation_name(op).as_str() { + "piop.relation" => { + let attrs = copy_attrs( + op, + &["kind", "domain", "num_rounds", "degree", "output_count"], + )?; + let symbol = string_attr(op, "sym_name")?; + context.append_op_with_owned_attrs( + &compute, + "compute.relation", + Some(&symbol), + &attrs, + )?; + } + "transcript.state" => { + let attrs = copy_attrs(op, &["scheme"])?; + let symbol = string_attr(op, "sym_name")?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.transcript_init", + Some(&symbol), + &attrs, + &[], + &["!compute.transcript_state"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "transcript.absorb_bytes" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["label", "payload"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.transcript_absorb_bytes", + Some(&symbol), + &attrs, + &operands, + &["!compute.transcript_state"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "transcript.squeeze" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["label", "kind", "count"])?; + let result_types = transcript_squeeze_compute_result_types(op)?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.transcript_squeeze", + Some(&symbol), + &attrs, + &operands, + &result_types, + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + insert_result_mapping(&mut value_map, op, operation, 1, 1)?; + } + "field.const" => { + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["field", "value"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.field_const", + Some(&symbol), + &attrs, + &[], + &["!compute.field_value"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "field.zero" | "field.one" => { + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["field"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + &format!("compute.{}", operation_name(op).replace('.', "_")), + Some(&symbol), + &attrs, + &[], + &["!compute.field_value"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "field.add" | "field.sub" | "field.mul" | "field.neg" | "field.pow" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = field_compute_attrs(op)?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + &format!("compute.{}", operation_name(op).replace('.', "_")), + Some(&symbol), + &attrs, + &operands, + &["!compute.field_value"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "poly.lagrange_basis_eval" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["domain_start", "domain_size", "index"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.poly_lagrange_basis_eval", + Some(&symbol), + &attrs, + &operands, + &["!compute.field_value"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "piop.sumcheck_claim" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs( + op, + &[ + "stage", + "domain", + "num_rounds", + "degree", + "claim", + "relation", + ], + )?; + let target_op = match &role { + Role::Prover => "compute.sumcheck_claim", + Role::Verifier => "compute.sumcheck_verify_claim", + }; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + target_op, + Some(&symbol), + &attrs, + &operands, + &["!compute.sumcheck_claim_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "piop.sumcheck_batch" => { + let operands = lowered_operands(op, &value_map, 1)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs( + op, + &[ + "stage", + "proof_slot", + "policy", + "count", + "ordered_claims", + "claim_label", + "round_label", + "round_schedule", + ], + )?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.sumcheck_batch", + Some(&symbol), + &attrs, + &operands, + &["!compute.sumcheck_batch_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "piop.sumcheck" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs( + op, + &[ + "stage", + "proof_slot", + "relation", + "policy", + "round_schedule", + "claim_label", + "round_label", + "num_rounds", + "degree", + ], + )?; + let target_op = match &role { + Role::Prover => "compute.sumcheck_driver", + Role::Verifier => "compute.sumcheck_verify", + }; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + target_op, + Some(&symbol), + &attrs, + &operands, + &[ + "!compute.transcript_state", + "!compute.point", + "!compute.sumcheck_result_type", + "!compute.sumcheck_proof_type", + ], + )?; + for index in 0..4 { + insert_result_mapping(&mut value_map, op, operation, index, index)?; + } + } + "piop.sumcheck_eval" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["source", "name", "index", "oracle"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.sumcheck_eval", + Some(&symbol), + &attrs, + &operands, + &["!compute.field_value"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "piop.sumcheck_instance_result" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs( + op, + &[ + "source", + "claim", + "relation", + "index", + "point_arity", + "num_rounds", + "round_offset", + "point_order", + "degree", + ], + )?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.sumcheck_instance_result", + Some(&symbol), + &attrs, + &operands, + &["!compute.point", "!compute.sumcheck_result_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + insert_result_mapping(&mut value_map, op, operation, 1, 1)?; + } + "piop.opening_claim" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["oracle", "domain", "point_arity", "claim_kind"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.opening_claim", + Some(&symbol), + &attrs, + &operands, + &["!compute.opening_claim_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "piop.opening_claim_equal" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["mode"])?; + let _operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.opening_claim_equal", + Some(&symbol), + &attrs, + &operands, + &[], + )?; + } + "piop.opening_batch" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs( + op, + &["stage", "proof_slot", "policy", "count", "ordered_claims"], + )?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.opening_batch", + Some(&symbol), + &attrs, + &operands, + &["!compute.opening_batch_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + _ => {} + } + } + + verify_module(&compute)?; + verify_compute_schema(&compute)?; + Ok(compute) +} + +pub fn resolve_compute_kernels<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Compute>, +) -> Result, MlirError> { + verify_compute_schema(module)?; + let role = module + .role() + .ok_or_else(|| schema_error("kernel resolution requires compute party role"))?; + let kernelized = context.new_module::(&module.name(), Some(role)); + let mut value_map = BTreeMap::new(); + let mut kernels = BTreeMap::new(); + let mut operation = module.as_mlir_module().body().first_operation(); + while let Some(op) = operation { + operation = op.next_in_block(); + match operation_name(op).as_str() { + "compute.params" => { + let attrs = copy_attrs(op, &["field", "pcs", "transcript"])?; + let symbol = string_attr(op, "sym_name")?; + context.append_op_with_owned_attrs( + &kernelized, + "compute.params", + Some(&symbol), + &attrs, + )?; + } + "compute.function" => { + let attrs = copy_attrs(op, &["source"])?; + let symbol = string_attr(op, "sym_name")?; + context.append_op_with_owned_attrs( + &kernelized, + "compute.function", + Some(&symbol), + &attrs, + )?; + } + "compute.relation" => { + let attrs = copy_attrs( + op, + &["kind", "domain", "num_rounds", "degree", "output_count"], + )?; + let symbol = string_attr(op, "sym_name")?; + context.append_op_with_owned_attrs( + &kernelized, + "compute.relation", + Some(&symbol), + &attrs, + )?; + } + "compute.transcript_init" => { + let attrs = copy_attrs(op, &["scheme"])?; + let symbol = string_attr(op, "sym_name")?; + let operation = context.append_typed_op_with_owned_attrs( + &kernelized, + "compute.transcript_init", + Some(&symbol), + &attrs, + &[], + &["!compute.transcript_state"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "compute.transcript_absorb_bytes" => { + let operands = lowered_operands(op, &value_map, 0)?; + let attrs = copy_attrs(op, &["label", "payload"])?; + let symbol = string_attr(op, "sym_name")?; + let operation = context.append_typed_op_with_owned_attrs( + &kernelized, + "compute.transcript_absorb_bytes", + Some(&symbol), + &attrs, + &operands, + &["!compute.transcript_state"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "compute.transcript_squeeze" => { + let operands = lowered_operands(op, &value_map, 0)?; + let attrs = copy_attrs(op, &["label", "kind", "count"])?; + let symbol = string_attr(op, "sym_name")?; + let result_types = transcript_squeeze_compute_result_types(op)?; + let operation = context.append_typed_op_with_owned_attrs( + &kernelized, + "compute.transcript_squeeze", + Some(&symbol), + &attrs, + &operands, + &result_types, + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + insert_result_mapping(&mut value_map, op, operation, 1, 1)?; + } + "compute.opening_input" => { + let attrs = copy_attrs( + op, + &[ + "source_stage", + "source_claim", + "oracle", + "domain", + "point_arity", + "claim_kind", + ], + )?; + let symbol = string_attr(op, "sym_name")?; + let operation = context.append_typed_op_with_owned_attrs( + &kernelized, + "compute.opening_input", + Some(&symbol), + &attrs, + &[], + &[ + "!compute.point", + "!compute.field_value", + "!compute.opening_claim_type", + ], + )?; + for index in 0..3 { + insert_result_mapping(&mut value_map, op, operation, index, index)?; + } + } + "compute.point_slice" => { + let operands = lowered_operands(op, &value_map, 0)?; + let attrs = copy_attrs(op, &["source", "offset", "length"])?; + let symbol = string_attr(op, "sym_name")?; + let operation = context.append_typed_op_with_owned_attrs( + &kernelized, + "compute.point_slice", + Some(&symbol), + &attrs, + &operands, + &["!compute.point"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "compute.point_zero" => { + let attrs = copy_attrs(op, &["field", "arity"])?; + let symbol = string_attr(op, "sym_name")?; + let operation = context.append_typed_op_with_owned_attrs( + &kernelized, + "compute.point_zero", + Some(&symbol), + &attrs, + &[], + &["!compute.point"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "compute.point_concat" => { + let operands = lowered_operands(op, &value_map, 0)?; + let attrs = copy_attrs(op, &["layout", "arity"])?; + let symbol = string_attr(op, "sym_name")?; + let operation = context.append_typed_op_with_owned_attrs( + &kernelized, + "compute.point_concat", + Some(&symbol), + &attrs, + &operands, + &["!compute.point"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "compute.field_const" => { + let attrs = copy_attrs(op, &["field", "value"])?; + let symbol = string_attr(op, "sym_name")?; + let operation = context.append_typed_op_with_owned_attrs( + &kernelized, + "compute.field_const", + Some(&symbol), + &attrs, + &[], + &["!compute.field_value"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "compute.field_zero" | "compute.field_one" => { + let attrs = copy_attrs(op, &["field"])?; + let symbol = string_attr(op, "sym_name")?; + let operation = context.append_typed_op_with_owned_attrs( + &kernelized, + &operation_name(op), + Some(&symbol), + &attrs, + &[], + &["!compute.field_value"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "compute.field_add" + | "compute.field_sub" + | "compute.field_mul" + | "compute.field_neg" + | "compute.field_pow" + | "compute.poly_lagrange_basis_eval" => { + let operands = lowered_operands(op, &value_map, 0)?; + let attrs = field_compute_attrs(op)?; + let symbol = string_attr(op, "sym_name")?; + let operation = context.append_typed_op_with_owned_attrs( + &kernelized, + &operation_name(op), + Some(&symbol), + &attrs, + &operands, + &["!compute.field_value"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "compute.sumcheck_claim" => { + let relation = symbol_attr(op, "relation")?; + let kernel = ensure_kernel(context, &kernelized, &mut kernels, &relation)?; + let operands = lowered_operands(op, &value_map, 0)?; + let mut attrs = + copy_attrs(op, &["stage", "domain", "num_rounds", "degree", "claim"])?; + attrs.push(("kernel".to_owned(), symbol_ref(&kernel))); + let symbol = string_attr(op, "sym_name")?; + let operation = context.append_typed_op_with_owned_attrs( + &kernelized, + "compute.sumcheck_kernel_claim", + Some(&symbol), + &attrs, + &operands, + &["!compute.sumcheck_claim_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "compute.sumcheck_verify_claim" => { + let operands = lowered_operands(op, &value_map, 0)?; + let attrs = copy_attrs( + op, + &[ + "stage", + "domain", + "num_rounds", + "degree", + "claim", + "relation", + ], + )?; + let symbol = string_attr(op, "sym_name")?; + let operation = context.append_typed_op_with_owned_attrs( + &kernelized, + "compute.sumcheck_verify_claim", + Some(&symbol), + &attrs, + &operands, + &["!compute.sumcheck_claim_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "compute.sumcheck_batch" => { + let operands = lowered_operands(op, &value_map, 0)?; + let attrs = copy_attrs( + op, + &[ + "stage", + "proof_slot", + "policy", + "count", + "ordered_claims", + "claim_label", + "round_label", + "round_schedule", + ], + )?; + let symbol = string_attr(op, "sym_name")?; + let operation = context.append_typed_op_with_owned_attrs( + &kernelized, + "compute.sumcheck_batch", + Some(&symbol), + &attrs, + &operands, + &["!compute.sumcheck_batch_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "compute.sumcheck_driver" => { + let relation = symbol_attr(op, "relation")?; + let kernel = ensure_kernel(context, &kernelized, &mut kernels, &relation)?; + let operands = lowered_operands(op, &value_map, 0)?; + let mut attrs = copy_attrs( + op, + &[ + "stage", + "proof_slot", + "policy", + "round_schedule", + "claim_label", + "round_label", + "num_rounds", + "degree", + ], + )?; + attrs.push(("kernel".to_owned(), symbol_ref(&kernel))); + let symbol = string_attr(op, "sym_name")?; + let operation = context.append_typed_op_with_owned_attrs( + &kernelized, + "compute.sumcheck_kernel_driver", + Some(&symbol), + &attrs, + &operands, + &[ + "!compute.transcript_state", + "!compute.point", + "!compute.sumcheck_result_type", + "!compute.sumcheck_proof_type", + ], + )?; + for index in 0..4 { + insert_result_mapping(&mut value_map, op, operation, index, index)?; + } + } + "compute.sumcheck_verify" => { + let operands = lowered_operands(op, &value_map, 0)?; + let attrs = copy_attrs( + op, + &[ + "stage", + "proof_slot", + "relation", + "policy", + "round_schedule", + "claim_label", + "round_label", + "num_rounds", + "degree", + ], + )?; + let symbol = string_attr(op, "sym_name")?; + let operation = context.append_typed_op_with_owned_attrs( + &kernelized, + "compute.sumcheck_verify", + Some(&symbol), + &attrs, + &operands, + &[ + "!compute.transcript_state", + "!compute.point", + "!compute.sumcheck_result_type", + "!compute.sumcheck_proof_type", + ], + )?; + for index in 0..4 { + insert_result_mapping(&mut value_map, op, operation, index, index)?; + } + } + "compute.sumcheck_eval" => { + let operands = lowered_operands(op, &value_map, 0)?; + let attrs = copy_attrs(op, &["source", "name", "index", "oracle"])?; + let symbol = string_attr(op, "sym_name")?; + let operation = context.append_typed_op_with_owned_attrs( + &kernelized, + "compute.sumcheck_eval", + Some(&symbol), + &attrs, + &operands, + &["!compute.field_value"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "compute.sumcheck_instance_result" => { + let operands = lowered_operands(op, &value_map, 0)?; + let attrs = copy_attrs( + op, + &[ + "source", + "claim", + "relation", + "index", + "point_arity", + "num_rounds", + "round_offset", + "point_order", + "degree", + ], + )?; + let symbol = string_attr(op, "sym_name")?; + let operation = context.append_typed_op_with_owned_attrs( + &kernelized, + "compute.sumcheck_instance_result", + Some(&symbol), + &attrs, + &operands, + &["!compute.point", "!compute.sumcheck_result_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + insert_result_mapping(&mut value_map, op, operation, 1, 1)?; + } + "compute.opening_claim" => { + let operands = lowered_operands(op, &value_map, 0)?; + let attrs = copy_attrs(op, &["oracle", "domain", "point_arity", "claim_kind"])?; + let symbol = string_attr(op, "sym_name")?; + let operation = context.append_typed_op_with_owned_attrs( + &kernelized, + "compute.opening_claim", + Some(&symbol), + &attrs, + &operands, + &["!compute.opening_claim_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "compute.opening_claim_equal" => { + let operands = lowered_operands(op, &value_map, 0)?; + let attrs = copy_attrs(op, &["mode"])?; + let symbol = string_attr(op, "sym_name")?; + let _operation = context.append_typed_op_with_owned_attrs( + &kernelized, + "compute.opening_claim_equal", + Some(&symbol), + &attrs, + &operands, + &[], + )?; + } + "compute.opening_batch" => { + let operands = lowered_operands(op, &value_map, 0)?; + let attrs = copy_attrs( + op, + &["stage", "proof_slot", "policy", "count", "ordered_claims"], + )?; + let symbol = string_attr(op, "sym_name")?; + let operation = context.append_typed_op_with_owned_attrs( + &kernelized, + "compute.opening_batch", + Some(&symbol), + &attrs, + &operands, + &["!compute.opening_batch_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "compute.pcs_opening_claim" => { + let operands = lowered_operands(op, &value_map, 0)?; + let attrs = copy_attrs(op, &["oracle", "family", "domain", "point_arity"])?; + let symbol = string_attr(op, "sym_name")?; + let operation = context.append_typed_op_with_owned_attrs( + &kernelized, + "compute.pcs_opening_claim", + Some(&symbol), + &attrs, + &operands, + &["!compute.opening_claim_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "compute.pcs_opening_batch" => { + let operands = lowered_operands(op, &value_map, 0)?; + let attrs = copy_attrs(op, &["proof_slot", "policy", "count", "ordered_claims"])?; + let symbol = string_attr(op, "sym_name")?; + let operation = context.append_typed_op_with_owned_attrs( + &kernelized, + "compute.pcs_opening_batch", + Some(&symbol), + &attrs, + &operands, + &["!compute.opening_batch_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "compute.pcs_batch_open" | "compute.pcs_batch_verify" => { + let operands = lowered_operands(op, &value_map, 0)?; + let attrs = copy_attrs(op, &["pcs", "proof_slot", "transcript_label"])?; + let symbol = string_attr(op, "sym_name")?; + let operation = context.append_typed_op_with_owned_attrs( + &kernelized, + &operation_name(op), + Some(&symbol), + &attrs, + &operands, + &["!compute.transcript_state", "!compute.opening_proof_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + insert_result_mapping(&mut value_map, op, operation, 1, 1)?; + } + _ => {} + } + } + + verify_module(&kernelized)?; + verify_compute_schema(&kernelized)?; + Ok(kernelized) +} + +fn append_stage1_virtual_oracles<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + params: &JoltProtocolParams, +) -> Result<(), MlirError> { + context.append_op( + module, + "poly.domain", + Some("jolt.stage1_uniskip_domain"), + &[("field", "@bn254_fr"), ("log_size", "1 : i64")], + )?; + append_virtual_oracle( + context, + module, + "UnivariateSkip", + "jolt.stage1_uniskip_domain", + )?; + for oracle in R1CS_INPUT_ORACLES { + append_virtual_oracle(context, module, oracle, "jolt.trace_domain")?; + } + context.append_op( + module, + "piop.oracle_family", + Some("jolt.stage1_r1cs_virtuals"), + &[ + ("ordered_oracles", &symbol_array_attr(&R1CS_INPUT_ORACLES)), + ("count", &int_attr(params.num_r1cs_inputs)), + ("domain", "@jolt.trace_domain"), + ("visibility", r#""virtual""#), + ], + ) +} + +fn append_virtual_oracle<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + symbol: &str, + domain: &str, +) -> Result<(), MlirError> { + context.append_op( + module, + "piop.oracle", + Some(symbol), + &[ + ("field", "@bn254_fr"), + ("domain", &format!("@{domain}")), + ("commit_domain", &format!("@{domain}")), + ("visibility", r#""virtual""#), + ("layout", r#""virtual""#), + ], + ) +} + +fn append_stage1_relations<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + params: &JoltProtocolParams, +) -> Result<(), MlirError> { + context.append_op( + module, + "piop.relation", + Some("jolt.stage1.outer.uniskip"), + &[ + ("kind", r#""sumcheck""#), + ("domain", "@jolt.stage1_uniskip_domain"), + ("num_rounds", "1 : i64"), + ("degree", &int_attr(OUTER_UNISKIP_FIRST_ROUND_DEGREE_BOUND)), + ("output_count", "1 : i64"), + ], + )?; + context.append_op( + module, + "piop.relation", + Some("jolt.stage1.outer.remaining"), + &[ + ("kind", r#""sumcheck""#), + ("domain", "@jolt.trace_domain"), + ("num_rounds", &int_attr(params.log_t + 1)), + ("degree", "3 : i64"), + ("output_count", &int_attr(R1CS_INPUT_ORACLES.len())), + ], + ) +} + +fn append_field_zero<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "field.zero", + Some(symbol), + &[("field", "@bn254_fr")], + &[], + &["!field.scalar"], + )?; + first_result(op, "field.zero") +} + +fn append_uniskip_sumcheck<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + params: &JoltProtocolParams, + state: Value<'c, 'a>, + stage: Value<'c, 'a>, + zero_claim: Value<'c, 'a>, +) -> Result<(Value<'c, 'a>, Value<'c, 'a>, Value<'c, 'a>), MlirError> { + let claim = context.append_typed_op( + module, + "piop.sumcheck_claim", + Some("stage1.uniskip.input"), + &[ + ("stage", "@stage1"), + ("domain", "@jolt.stage1_uniskip_domain"), + ("num_rounds", "1 : i64"), + ("degree", &int_attr(OUTER_UNISKIP_FIRST_ROUND_DEGREE_BOUND)), + ("claim", "@stage1.zero"), + ("relation", "@jolt.stage1.outer.uniskip"), + ], + &[zero_claim], + &["!piop.sumcheck_claim_type"], + )?; + let claim = first_result(claim, "piop.sumcheck_claim")?; + let batch = context.append_typed_op( + module, + "piop.sumcheck_batch", + Some("stage1.uniskip.batch"), + &[ + ("stage", "@stage1"), + ("proof_slot", "@stage1.uni_skip_first_round"), + ("policy", r#""single_instance""#), + ("count", "1 : i64"), + ("ordered_claims", "[@stage1.uniskip.input]"), + ("claim_label", r#""uniskip_claim""#), + ("round_label", r#""uniskip_poly""#), + ("round_schedule", "[1]"), + ], + &[stage, claim], + &["!piop.sumcheck_batch_type"], + )?; + let batch = first_result(batch, "piop.sumcheck_batch")?; + let sumcheck = context.append_typed_op( + module, + "piop.sumcheck", + Some("stage1.uniskip.sumcheck"), + &[ + ("stage", "@stage1"), + ("proof_slot", "@stage1.uni_skip_first_round"), + ("relation", "@jolt.stage1.outer.uniskip"), + ("policy", r#""univariate_skip""#), + ("round_schedule", "[1]"), + ("claim_label", r#""uniskip_claim""#), + ("round_label", r#""uniskip_poly""#), + ("num_rounds", "1 : i64"), + ("degree", &int_attr(OUTER_UNISKIP_FIRST_ROUND_DEGREE_BOUND)), + ], + &[state, batch], + &[ + "!transcript.state_type", + "!poly.point", + "!piop.sumcheck_result_type", + "!piop.sumcheck_proof_type", + ], + )?; + let state = result(sumcheck, 0, "piop.sumcheck")?; + let point = result(sumcheck, 1, "piop.sumcheck")?; + let result_value = result(sumcheck, 2, "piop.sumcheck")?; + let (point, result_value) = append_sumcheck_instance_result( + context, + module, + SumcheckInstanceResultSpec { + symbol: "stage1.uniskip.instance", + source: "stage1.uniskip.sumcheck", + claim: "stage1.uniskip.input", + relation: "jolt.stage1.outer.uniskip", + index: 0, + point_arity: 1, + num_rounds: 1, + round_offset: 0, + point_order: "as_is", + degree: OUTER_UNISKIP_FIRST_ROUND_DEGREE_BOUND, + }, + point, + result_value, + )?; + let eval = append_sumcheck_eval( + context, + module, + "stage1.uniskip.eval", + "stage1.uniskip.sumcheck", + "UnivariateSkip", + 0, + result_value, + )?; + let opening = append_piop_opening_claim( + context, + module, + point, + eval, + OpeningClaimSpec { + symbol: "stage1.uniskip.opening", + oracle: "UnivariateSkip", + domain: "jolt.stage1_uniskip_domain", + point_arity: 1, + }, + )?; + let _ = params; + Ok((state, opening, eval)) +} + +fn append_remaining_sumcheck<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + params: &JoltProtocolParams, + state: Value<'c, 'a>, + stage: Value<'c, 'a>, + input_claim: Value<'c, 'a>, + uniskip_opening: Value<'c, 'a>, +) -> Result, MlirError> { + let num_rounds = params.log_t + 1; + let claim = context.append_typed_op( + module, + "piop.sumcheck_claim", + Some("stage1.outer_remaining.input"), + &[ + ("stage", "@stage1"), + ("domain", "@jolt.trace_domain"), + ("num_rounds", &int_attr(num_rounds)), + ("degree", "3 : i64"), + ("claim", "@stage1.uniskip.eval"), + ("relation", "@jolt.stage1.outer.remaining"), + ], + &[input_claim, uniskip_opening], + &["!piop.sumcheck_claim_type"], + )?; + let claim = first_result(claim, "piop.sumcheck_claim")?; + let batch = context.append_typed_op( + module, + "piop.sumcheck_batch", + Some("stage1.outer_remaining.batch"), + &[ + ("stage", "@stage1"), + ("proof_slot", "@stage1.sumcheck"), + ("policy", r#""jolt_core_front_loaded""#), + ("count", "1 : i64"), + ("ordered_claims", "[@stage1.outer_remaining.input]"), + ("claim_label", r#""sumcheck_claim""#), + ("round_label", r#""sumcheck_poly""#), + ("round_schedule", &format!("[{}]", num_rounds)), + ], + &[stage, claim], + &["!piop.sumcheck_batch_type"], + )?; + let batch = first_result(batch, "piop.sumcheck_batch")?; + let sumcheck = context.append_typed_op( + module, + "piop.sumcheck", + Some("stage1.outer_remaining.sumcheck"), + &[ + ("stage", "@stage1"), + ("proof_slot", "@stage1.sumcheck"), + ("relation", "@jolt.stage1.outer.remaining"), + ("policy", r#""jolt_core_front_loaded""#), + ("round_schedule", &format!("[{}]", num_rounds)), + ("claim_label", r#""sumcheck_claim""#), + ("round_label", r#""sumcheck_poly""#), + ("num_rounds", &int_attr(num_rounds)), + ("degree", "3 : i64"), + ], + &[state, batch], + &[ + "!transcript.state_type", + "!poly.point", + "!piop.sumcheck_result_type", + "!piop.sumcheck_proof_type", + ], + )?; + let state = result(sumcheck, 0, "piop.sumcheck")?; + let point = result(sumcheck, 1, "piop.sumcheck")?; + let result_value = result(sumcheck, 2, "piop.sumcheck")?; + let (point, result_value) = append_sumcheck_instance_result( + context, + module, + SumcheckInstanceResultSpec { + symbol: "stage1.outer_remaining.instance", + source: "stage1.outer_remaining.sumcheck", + claim: "stage1.outer_remaining.input", + relation: "jolt.stage1.outer.remaining", + index: 0, + point_arity: params.log_t, + num_rounds, + round_offset: 1, + point_order: "reverse", + degree: 3, + }, + point, + result_value, + )?; + let mut claims = Vec::with_capacity(R1CS_INPUT_ORACLES.len()); + for (index, oracle) in R1CS_INPUT_ORACLES.iter().enumerate() { + let eval = append_sumcheck_eval( + context, + module, + &format!("stage1.outer_remaining.eval.{oracle}"), + "stage1.outer_remaining.sumcheck", + oracle, + index, + result_value, + )?; + claims.push(append_piop_opening_claim( + context, + module, + point, + eval, + OpeningClaimSpec { + symbol: &format!("stage1.outer_remaining.opening.{oracle}"), + oracle, + domain: "jolt.trace_domain", + point_arity: params.log_t, + }, + )?); + } + let _batch = context.append_typed_op( + module, + "piop.opening_batch", + Some("stage1.outer_remaining.openings"), + &[ + ("stage", "@stage1"), + ("proof_slot", "@stage1.virtual_openings"), + ("policy", r#""jolt_r1cs_input_order""#), + ("count", &int_attr(R1CS_INPUT_ORACLES.len())), + ("ordered_claims", &opening_claim_attr()), + ], + &claims, + &["!piop.opening_batch_type"], + )?; + Ok(state) +} + +fn append_sumcheck_eval<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + source: &str, + oracle: &str, + index: usize, + result_value: Value<'c, 'a>, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "piop.sumcheck_eval", + Some(symbol), + &[ + ("source", &format!("@{source}")), + ("name", &format!("@{symbol}")), + ("index", &int_attr(index)), + ("oracle", &format!("@{oracle}")), + ], + &[result_value], + &["!field.scalar"], + )?; + first_result(op, "piop.sumcheck_eval") +} + +fn append_sumcheck_instance_result<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + spec: SumcheckInstanceResultSpec<'_>, + point: Value<'c, 'a>, + result_value: Value<'c, 'a>, +) -> Result<(Value<'c, 'a>, Value<'c, 'a>), MlirError> { + let op = context.append_typed_op( + module, + "piop.sumcheck_instance_result", + Some(spec.symbol), + &[ + ("source", &format!("@{}", spec.source)), + ("claim", &format!("@{}", spec.claim)), + ("relation", &format!("@{}", spec.relation)), + ("index", &int_attr(spec.index)), + ("point_arity", &int_attr(spec.point_arity)), + ("num_rounds", &int_attr(spec.num_rounds)), + ("round_offset", &int_attr(spec.round_offset)), + ("point_order", &format!("\"{}\"", spec.point_order)), + ("degree", &int_attr(spec.degree)), + ], + &[point, result_value], + &["!poly.point", "!piop.sumcheck_result_type"], + )?; + Ok(( + result(op, 0, "piop.sumcheck_instance_result")?, + result(op, 1, "piop.sumcheck_instance_result")?, + )) +} + +fn append_piop_opening_claim<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + point: Value<'c, 'a>, + eval: Value<'c, 'a>, + spec: OpeningClaimSpec<'_>, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "piop.opening_claim", + Some(spec.symbol), + &[ + ("oracle", &format!("@{}", spec.oracle)), + ("domain", &format!("@{}", spec.domain)), + ("point_arity", &int_attr(spec.point_arity)), + ("claim_kind", r#""virtual""#), + ], + &[point, eval], + &["!piop.opening_claim_type"], + )?; + first_result(op, "piop.opening_claim") +} + +struct OpeningClaimSpec<'a> { + symbol: &'a str, + oracle: &'a str, + domain: &'a str, + point_arity: usize, +} + +struct SumcheckInstanceResultSpec<'a> { + symbol: &'a str, + source: &'a str, + claim: &'a str, + relation: &'a str, + index: usize, + point_arity: usize, + num_rounds: usize, + round_offset: usize, + point_order: &'a str, + degree: usize, +} + +fn first_result<'c, 'a>( + operation: OperationRef<'c, 'a>, + operation_name: &str, +) -> Result, MlirError> { + result(operation, 0, operation_name) +} + +fn result<'c, 'a>( + operation: OperationRef<'c, 'a>, + index: usize, + operation_name: &str, +) -> Result, MlirError> { + operation + .result(index) + .map(Into::into) + .map_err(|_| schema_error(format!("{operation_name} requires result {index}"))) +} + +#[derive(Clone, Debug)] +struct StageParamsAst { + field: String, + pcs: String, + transcript: String, +} + +fn stage_params(module: &BoltModule<'_, Party>) -> Result { + let mut operation = module.as_mlir_module().body().first_operation(); + while let Some(op) = operation { + operation = op.next_in_block(); + if operation_name(op) == "protocol.params" { + return Ok(StageParamsAst { + field: symbol_attr(op, "field")?, + pcs: symbol_attr(op, "pcs")?, + transcript: symbol_attr(op, "transcript")?, + }); + } + } + Err(schema_error("stage1 lowering requires protocol.params")) +} + +fn operation_result_key_at( + operation: OperationRef<'_, '_>, + index: usize, +) -> Result { + let result = operation.result(index).map_err(|_| { + schema_error(format!( + "{} requires result {index}", + operation_name(operation) + )) + })?; + result_key(result.owner(), result.result_number()) +} + +fn result_key(operation: OperationRef<'_, '_>, result_number: usize) -> Result { + Ok(format!( + "{}#{result_number}", + string_attr(operation, "sym_name")? + )) +} + +fn operand_key(operation: OperationRef<'_, '_>, index: usize) -> Result { + let operand = operation.operand(index).map_err(|_| { + schema_error(format!( + "{} requires operand {index}", + operation_name(operation) + )) + })?; + let owner = OperationResult::try_from(operand).map_err(|_| { + schema_error(format!( + "{} operand {index} must be an op result", + operation_name(operation) + )) + })?; + result_key(owner.owner(), owner.result_number()).map_err(|_| { + schema_error(format!( + "{} operand {index} owner missing sym_name", + operation_name(operation) + )) + }) +} + +fn lowered_operands<'c, 'a>( + operation: OperationRef<'_, '_>, + value_map: &BTreeMap>, + start_index: usize, +) -> Result>, MlirError> { + (start_index..operation.operand_count()) + .map(|index| { + let key = operand_key(operation, index)?; + value_map.get(&key).copied().ok_or_else(|| { + schema_error(format!( + "{} operand {index} was not lowered", + operation_name(operation) + )) + }) + }) + .collect() +} + +fn insert_result_mapping<'c, 'a>( + value_map: &mut BTreeMap>, + source: OperationRef<'_, '_>, + target: OperationRef<'c, 'a>, + source_index: usize, + target_index: usize, +) -> Result<(), MlirError> { + let key = operation_result_key_at(source, source_index)?; + let value = target.result(target_index).map(Into::into).map_err(|_| { + schema_error(format!( + "{} requires result {target_index}", + operation_name(target) + )) + })?; + let inserted = value_map.insert(key, value); + debug_assert!(inserted.is_none()); + Ok(()) +} + +fn ensure_kernel<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Compute>, + kernels: &mut BTreeMap, + relation: &str, +) -> Result { + if let Some(kernel) = kernels.get(relation) { + return Ok(kernel.clone()); + } + let spec = kernel_spec(relation)?; + context.append_op_with_owned_attrs( + module, + "compute.kernel", + Some(spec.symbol), + &[ + ("relation".to_owned(), symbol_ref(relation)), + ("kind".to_owned(), string_literal(spec.kind)), + ("backend".to_owned(), string_literal("cpu")), + ("abi".to_owned(), string_literal(spec.abi)), + ], + )?; + let inserted = kernels.insert(relation.to_owned(), spec.symbol.to_owned()); + debug_assert!(inserted.is_none()); + Ok(spec.symbol.to_owned()) +} + +fn kernel_spec(relation: &str) -> Result { + match relation { + "jolt.stage1.outer.uniskip" => Ok(KernelSpec { + symbol: "jolt.cpu.stage1.outer.uniskip", + kind: "sumcheck", + abi: "jolt_stage1_outer_uniskip", + }), + "jolt.stage1.outer.remaining" => Ok(KernelSpec { + symbol: "jolt.cpu.stage1.outer.remaining", + kind: "sumcheck", + abi: "jolt_stage1_outer_remaining", + }), + "jolt.stage2.product_virtual.uniskip" => Ok(KernelSpec { + symbol: "jolt.cpu.stage2.product_virtual.uniskip", + kind: "sumcheck", + abi: "jolt_stage2_product_virtual_uniskip", + }), + "jolt.stage2.ram.read_write" => Ok(KernelSpec { + symbol: "jolt.cpu.stage2.ram.read_write", + kind: "sumcheck", + abi: "jolt_stage2_ram_read_write", + }), + "jolt.stage2.product_virtual.remainder" => Ok(KernelSpec { + symbol: "jolt.cpu.stage2.product_virtual.remainder", + kind: "sumcheck", + abi: "jolt_stage2_product_virtual_remainder", + }), + "jolt.stage2.instruction_lookup.claim_reduction" => Ok(KernelSpec { + symbol: "jolt.cpu.stage2.instruction_lookup.claim_reduction", + kind: "sumcheck", + abi: "jolt_stage2_instruction_lookup_claim_reduction", + }), + "jolt.stage2.ram.raf_evaluation" => Ok(KernelSpec { + symbol: "jolt.cpu.stage2.ram.raf_evaluation", + kind: "sumcheck", + abi: "jolt_stage2_ram_raf_evaluation", + }), + "jolt.stage2.ram.output_check" => Ok(KernelSpec { + symbol: "jolt.cpu.stage2.ram.output_check", + kind: "sumcheck", + abi: "jolt_stage2_ram_output_check", + }), + "jolt.stage2.batched" => Ok(KernelSpec { + symbol: "jolt.cpu.stage2.batched", + kind: "sumcheck", + abi: "jolt_stage2_batched", + }), + "jolt.stage3.spartan_shift" => Ok(KernelSpec { + symbol: "jolt.cpu.stage3.spartan_shift", + kind: "sumcheck", + abi: "jolt_stage3_spartan_shift", + }), + "jolt.stage3.instruction_input" => Ok(KernelSpec { + symbol: "jolt.cpu.stage3.instruction_input", + kind: "sumcheck", + abi: "jolt_stage3_instruction_input", + }), + "jolt.stage3.registers_claim_reduction" => Ok(KernelSpec { + symbol: "jolt.cpu.stage3.registers_claim_reduction", + kind: "sumcheck", + abi: "jolt_stage3_registers_claim_reduction", + }), + "jolt.stage3.batched" => Ok(KernelSpec { + symbol: "jolt.cpu.stage3.batched", + kind: "sumcheck", + abi: "jolt_stage3_batched", + }), + "jolt.stage4.registers_read_write" => Ok(KernelSpec { + symbol: "jolt.cpu.stage4.registers_read_write", + kind: "sumcheck", + abi: "jolt_stage4_registers_read_write", + }), + "jolt.stage4.ram_val_check" => Ok(KernelSpec { + symbol: "jolt.cpu.stage4.ram_val_check", + kind: "sumcheck", + abi: "jolt_stage4_ram_val_check", + }), + "jolt.stage4.batched" => Ok(KernelSpec { + symbol: "jolt.cpu.stage4.batched", + kind: "sumcheck", + abi: "jolt_stage4_batched", + }), + "jolt.stage5.instruction_read_raf" => Ok(KernelSpec { + symbol: "jolt.cpu.stage5.instruction_read_raf", + kind: "sumcheck", + abi: "jolt_stage5_instruction_read_raf", + }), + "jolt.stage5.ram_ra_claim_reduction" => Ok(KernelSpec { + symbol: "jolt.cpu.stage5.ram_ra_claim_reduction", + kind: "sumcheck", + abi: "jolt_stage5_ram_ra_claim_reduction", + }), + "jolt.stage5.registers_val_evaluation" => Ok(KernelSpec { + symbol: "jolt.cpu.stage5.registers_val_evaluation", + kind: "sumcheck", + abi: "jolt_stage5_registers_val_evaluation", + }), + "jolt.stage5.batched" => Ok(KernelSpec { + symbol: "jolt.cpu.stage5.batched", + kind: "sumcheck", + abi: "jolt_stage5_batched", + }), + "jolt.stage6.bytecode_read_raf" => Ok(KernelSpec { + symbol: "jolt.cpu.stage6.bytecode_read_raf", + kind: "sumcheck", + abi: "jolt_stage6_bytecode_read_raf", + }), + "jolt.stage6.booleanity" => Ok(KernelSpec { + symbol: "jolt.cpu.stage6.booleanity", + kind: "sumcheck", + abi: "jolt_stage6_booleanity", + }), + "jolt.stage6.hamming_booleanity" => Ok(KernelSpec { + symbol: "jolt.cpu.stage6.hamming_booleanity", + kind: "sumcheck", + abi: "jolt_stage6_hamming_booleanity", + }), + "jolt.stage6.ram_ra_virtual" => Ok(KernelSpec { + symbol: "jolt.cpu.stage6.ram_ra_virtual", + kind: "sumcheck", + abi: "jolt_stage6_ram_ra_virtual", + }), + "jolt.stage6.instruction_ra_virtual" => Ok(KernelSpec { + symbol: "jolt.cpu.stage6.instruction_ra_virtual", + kind: "sumcheck", + abi: "jolt_stage6_instruction_ra_virtual", + }), + "jolt.stage6.inc_claim_reduction" => Ok(KernelSpec { + symbol: "jolt.cpu.stage6.inc_claim_reduction", + kind: "sumcheck", + abi: "jolt_stage6_inc_claim_reduction", + }), + "jolt.stage6.batched" => Ok(KernelSpec { + symbol: "jolt.cpu.stage6.batched", + kind: "sumcheck", + abi: "jolt_stage6_batched", + }), + "jolt.stage7.hamming_weight_claim_reduction" => Ok(KernelSpec { + symbol: "jolt.cpu.stage7.hamming_weight_claim_reduction", + kind: "sumcheck", + abi: "jolt_stage7_hamming_weight_claim_reduction", + }), + "jolt.stage7.batched" => Ok(KernelSpec { + symbol: "jolt.cpu.stage7.batched", + kind: "sumcheck", + abi: "jolt_stage7_batched", + }), + _ => Err(schema_error(format!( + "unsupported compute relation @{relation}" + ))), + } +} + +struct KernelSpec { + symbol: &'static str, + kind: &'static str, + abi: &'static str, +} + +fn int_attr(value: usize) -> String { + format!("{value} : i64") +} + +fn symbol_array_attr(values: &[&str]) -> String { + let values = values + .iter() + .map(|value| format!("@{value}")) + .collect::>() + .join(", "); + format!("[{values}]") +} + +fn opening_claim_attr() -> String { + let values = R1CS_INPUT_ORACLES + .iter() + .map(|oracle| format!("@stage1.outer_remaining.opening.{oracle}")) + .collect::>() + .join(", "); + format!("[{values}]") +} + +fn schema_error(message: impl Into) -> MlirError { + let error = SchemaError::new(message); + error.into() +} + +fn symbol_ref(value: &str) -> String { + format!("@{value}") +} + +fn string_literal(value: &str) -> String { + format!("{value:?}") +} diff --git a/crates/bolt/src/protocols/jolt/phases/stage2.rs b/crates/bolt/src/protocols/jolt/phases/stage2.rs new file mode 100644 index 0000000000..2c67e00a81 --- /dev/null +++ b/crates/bolt/src/protocols/jolt/phases/stage2.rs @@ -0,0 +1,2082 @@ +use std::collections::{BTreeMap, BTreeSet}; + +use melior::ir::block::BlockLike; +use melior::ir::operation::OperationRef; +use melior::ir::operation::{OperationLike, OperationResult}; +use melior::ir::Value; + +use crate::ir::{BoltModule, Compute, Party, Protocol, Role}; +use crate::mlir::{verify_module, MeliorContext, MlirError}; +use crate::schema::{ + operation_name, symbol_attr, verify_compute_schema, verify_party_schema, + verify_protocol_schema, SchemaError, +}; + +use super::super::oracles; +use super::super::params::JoltProtocolParams; +use super::lowering::{ + copy_attrs, field_lowering_attrs as field_compute_attrs, string_attr, + transcript_squeeze_compute_result_types, transcript_squeeze_protocol_result_type, +}; + +const PRODUCT_UNISKIP_DEGREE_BOUND: usize = 6; +const PRODUCT_UNISKIP_DOMAIN_START: isize = -1; +const PRODUCT_UNISKIP_DOMAIN_SIZE: usize = 3; +const RAM_RW_DEGREE: usize = 3; +const PRODUCT_REMAINDER_DEGREE: usize = 3; +const INSTRUCTION_CLAIM_REDUCTION_DEGREE: usize = 2; +const RAM_RAF_DEGREE: usize = 2; +const RAM_OUTPUT_DEGREE: usize = 3; + +const STAGE1_PRODUCT_OPENINGS: [&str; 3] = ["Product", "ShouldBranch", "ShouldJump"]; +const STAGE2_RAM_RW_INPUTS: [&str; 2] = ["RamReadValue", "RamWriteValue"]; +const STAGE2_INSTRUCTION_INPUTS: [&str; 5] = [ + "LookupOutput", + "LeftLookupOperand", + "RightLookupOperand", + "LeftInstructionInput", + "RightInstructionInput", +]; +const PRODUCT_REMAINDER_OUTPUTS: [&str; 8] = [ + "LeftInstructionInput", + "RightInstructionInput", + "OpFlagJump", + "OpFlagWriteLookupOutputToRD", + "LookupOutput", + "InstructionFlagBranch", + "NextIsNoop", + "OpFlagVirtualInstruction", +]; + +pub fn build_stage2_protocol<'c>( + context: &'c MeliorContext, + params: &JoltProtocolParams, +) -> Result, MlirError> { + let module = context.new_module::("jolt.stage2", None); + oracles::append_foundation_ops(context, &module, params)?; + context.append_op_with_owned_attrs( + &module, + "protocol.params", + Some("jolt.params"), + ¶ms.attrs(), + )?; + context.append_op( + &module, + "protocol.boundary", + Some("jolt.stage2"), + &[("roles", r#"["prover", "verifier"]"#)], + )?; + append_stage2_domains(context, &module, params)?; + append_stage2_oracles(context, &module)?; + append_stage2_relations(context, &module, params)?; + let inputs = append_stage2_opening_inputs(context, &module, params)?; + + let fs = context.append_typed_op( + &module, + "transcript.state", + Some("fs_after_stage1"), + &[("scheme", "@blake2b_transcript")], + &[], + &["!transcript.state_type"], + )?; + let state = first_result(fs, "transcript.state")?; + let stage = context.append_typed_op( + &module, + "piop.stage", + Some("stage2"), + &[ + ("name", r#""product_virtual_and_ram""#), + ("order", "2 : i64"), + ("roles", r#"["prover", "verifier"]"#), + ], + &[], + &["!piop.stage_type"], + )?; + let stage = first_result(stage, "piop.stage")?; + let (state, tau_high) = append_transcript_squeeze( + context, + &module, + state, + "stage2.product_virtual.tau_high", + "product_virtual_tau_high", + "challenge_scalar", + 1, + )?; + let (state, uniskip) = + append_product_uniskip(context, &module, params, state, stage, &inputs, tau_high)?; + let (state, ram_read_write_gamma) = append_transcript_squeeze( + context, + &module, + state, + "stage2.ram_read_write.gamma", + "ram_read_write_gamma", + "challenge_scalar", + 1, + )?; + let (state, instruction_lookup_gamma) = append_transcript_squeeze( + context, + &module, + state, + "stage2.instruction_lookup.gamma", + "instruction_lookup_gamma", + "challenge_scalar", + 1, + )?; + let (state, _ram_output_address) = append_transcript_squeeze( + context, + &module, + state, + "stage2.ram_output.r_address", + "ram_output_r_address", + "challenge_vector", + params.log_k_ram, + )?; + let _state = append_stage2_batched_sumcheck( + context, + &module, + params, + Stage2BatchedSumcheckInputs { + state, + stage, + openings: &inputs, + uniskip, + ram_read_write_gamma, + instruction_lookup_gamma, + }, + )?; + + verify_module(&module)?; + verify_protocol_schema(&module)?; + Ok(module) +} + +pub fn lower_stage2_to_compute<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Party>, +) -> Result, MlirError> { + verify_party_schema(module)?; + let role = module + .role() + .ok_or_else(|| schema_error("stage2 lowering requires party role"))?; + let params = stage_params(module)?; + let compute = context.new_module::(&module.name(), Some(role.clone())); + context.append_op_with_owned_attrs( + &compute, + "compute.params", + Some("jolt.compute_params"), + &[ + ("field".to_owned(), symbol_ref(¶ms.field)), + ("pcs".to_owned(), symbol_ref(¶ms.pcs)), + ("transcript".to_owned(), symbol_ref(¶ms.transcript)), + ], + )?; + context.append_op( + &compute, + "compute.function", + Some("jolt.stage2"), + &[("source", "@jolt.stage2")], + )?; + + let mut value_map = BTreeMap::new(); + let mut operation = module.as_mlir_module().body().first_operation(); + while let Some(op) = operation { + operation = op.next_in_block(); + match operation_name(op).as_str() { + "piop.relation" => { + let attrs = copy_attrs( + op, + &["kind", "domain", "num_rounds", "degree", "output_count"], + )?; + let symbol = string_attr(op, "sym_name")?; + context.append_op_with_owned_attrs( + &compute, + "compute.relation", + Some(&symbol), + &attrs, + )?; + } + "transcript.state" => { + let attrs = copy_attrs(op, &["scheme"])?; + let symbol = string_attr(op, "sym_name")?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.transcript_init", + Some(&symbol), + &attrs, + &[], + &["!compute.transcript_state"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "transcript.absorb_bytes" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["label", "payload"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.transcript_absorb_bytes", + Some(&symbol), + &attrs, + &operands, + &["!compute.transcript_state"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "transcript.squeeze" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["label", "kind", "count"])?; + let result_types = transcript_squeeze_compute_result_types(op)?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.transcript_squeeze", + Some(&symbol), + &attrs, + &operands, + &result_types, + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + insert_result_mapping(&mut value_map, op, operation, 1, 1)?; + } + "field.const" => { + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["field", "value"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.field_const", + Some(&symbol), + &attrs, + &[], + &["!compute.field_value"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "field.zero" | "field.one" => { + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["field"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + &format!("compute.{}", operation_name(op).replace('.', "_")), + Some(&symbol), + &attrs, + &[], + &["!compute.field_value"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "field.add" | "field.sub" | "field.mul" | "field.neg" | "field.pow" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = field_compute_attrs(op)?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + &format!("compute.{}", operation_name(op).replace('.', "_")), + Some(&symbol), + &attrs, + &operands, + &["!compute.field_value"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "poly.lagrange_basis_eval" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["domain_start", "domain_size", "index"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.poly_lagrange_basis_eval", + Some(&symbol), + &attrs, + &operands, + &["!compute.field_value"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "piop.opening_input" => { + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs( + op, + &[ + "source_stage", + "source_claim", + "oracle", + "domain", + "point_arity", + "claim_kind", + ], + )?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.opening_input", + Some(&symbol), + &attrs, + &[], + &[ + "!compute.point", + "!compute.field_value", + "!compute.opening_claim_type", + ], + )?; + for index in 0..3 { + insert_result_mapping(&mut value_map, op, operation, index, index)?; + } + } + "poly.point_slice" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["source", "offset", "length"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.point_slice", + Some(&symbol), + &attrs, + &operands, + &["!compute.point"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "poly.point_concat" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["layout", "arity"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.point_concat", + Some(&symbol), + &attrs, + &operands, + &["!compute.point"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "piop.sumcheck_claim" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs( + op, + &[ + "stage", + "domain", + "num_rounds", + "degree", + "claim", + "relation", + ], + )?; + let target_op = match &role { + Role::Prover => "compute.sumcheck_claim", + Role::Verifier => "compute.sumcheck_verify_claim", + }; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + target_op, + Some(&symbol), + &attrs, + &operands, + &["!compute.sumcheck_claim_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "piop.sumcheck_batch" => { + let operands = lowered_operands(op, &value_map, 1)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs( + op, + &[ + "stage", + "proof_slot", + "policy", + "count", + "ordered_claims", + "claim_label", + "round_label", + "round_schedule", + ], + )?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.sumcheck_batch", + Some(&symbol), + &attrs, + &operands, + &["!compute.sumcheck_batch_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "piop.sumcheck" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs( + op, + &[ + "stage", + "proof_slot", + "relation", + "policy", + "round_schedule", + "claim_label", + "round_label", + "num_rounds", + "degree", + ], + )?; + let target_op = match &role { + Role::Prover => "compute.sumcheck_driver", + Role::Verifier => "compute.sumcheck_verify", + }; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + target_op, + Some(&symbol), + &attrs, + &operands, + &[ + "!compute.transcript_state", + "!compute.point", + "!compute.sumcheck_result_type", + "!compute.sumcheck_proof_type", + ], + )?; + for index in 0..4 { + insert_result_mapping(&mut value_map, op, operation, index, index)?; + } + } + "piop.sumcheck_eval" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["source", "name", "index", "oracle"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.sumcheck_eval", + Some(&symbol), + &attrs, + &operands, + &["!compute.field_value"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "piop.sumcheck_instance_result" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs( + op, + &[ + "source", + "claim", + "relation", + "index", + "point_arity", + "num_rounds", + "round_offset", + "point_order", + "degree", + ], + )?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.sumcheck_instance_result", + Some(&symbol), + &attrs, + &operands, + &["!compute.point", "!compute.sumcheck_result_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + insert_result_mapping(&mut value_map, op, operation, 1, 1)?; + } + "piop.opening_claim" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["oracle", "domain", "point_arity", "claim_kind"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.opening_claim", + Some(&symbol), + &attrs, + &operands, + &["!compute.opening_claim_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "piop.opening_claim_equal" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["mode"])?; + let _operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.opening_claim_equal", + Some(&symbol), + &attrs, + &operands, + &[], + )?; + } + "piop.opening_batch" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs( + op, + &["stage", "proof_slot", "policy", "count", "ordered_claims"], + )?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.opening_batch", + Some(&symbol), + &attrs, + &operands, + &["!compute.opening_batch_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + _ => {} + } + } + + verify_module(&compute)?; + verify_compute_schema(&compute)?; + Ok(compute) +} + +fn append_stage2_domains<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + params: &JoltProtocolParams, +) -> Result<(), MlirError> { + context.append_op( + module, + "poly.domain", + Some("jolt.stage2_uniskip_domain"), + &[("field", "@bn254_fr"), ("log_size", "1 : i64")], + )?; + context.append_op( + module, + "poly.domain", + Some("jolt.stage2_ram_rw_domain"), + &[ + ("field", "@bn254_fr"), + ("log_size", &int_attr(stage2_max_rounds(params))), + ], + )?; + context.append_op( + module, + "poly.domain", + Some("jolt.ram_address_domain"), + &[ + ("field", "@bn254_fr"), + ("log_size", &int_attr(params.log_k_ram)), + ], + ) +} + +fn append_stage2_oracles<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, +) -> Result<(), MlirError> { + let mut trace_oracles = BTreeSet::new(); + trace_oracles.extend(STAGE1_PRODUCT_OPENINGS); + trace_oracles.extend(STAGE2_RAM_RW_INPUTS); + trace_oracles.extend(STAGE2_INSTRUCTION_INPUTS); + trace_oracles.extend(PRODUCT_REMAINDER_OUTPUTS); + let _ = trace_oracles.insert("RamAddress"); + for oracle in trace_oracles { + append_virtual_oracle(context, module, oracle, "jolt.trace_domain")?; + } + append_virtual_oracle( + context, + module, + "UnivariateSkip", + "jolt.stage2_uniskip_domain", + )?; + append_virtual_oracle(context, module, "RamVal", "jolt.stage2_ram_rw_domain")?; + append_virtual_oracle(context, module, "RamRa", "jolt.stage2_ram_rw_domain")?; + append_virtual_oracle(context, module, "RamValFinal", "jolt.ram_address_domain")?; + context.append_op( + module, + "piop.oracle", + Some("RamInc"), + &[ + ("field", "@bn254_fr"), + ("domain", "@jolt.trace_domain"), + ("commit_domain", "@jolt.main_witness_commit_domain"), + ("visibility", r#""committed""#), + ("layout", r#""dense_trace""#), + ], + ) +} + +fn append_virtual_oracle<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + symbol: &str, + domain: &str, +) -> Result<(), MlirError> { + context.append_op( + module, + "piop.oracle", + Some(symbol), + &[ + ("field", "@bn254_fr"), + ("domain", &format!("@{domain}")), + ("commit_domain", &format!("@{domain}")), + ("visibility", r#""virtual""#), + ("layout", r#""virtual""#), + ], + ) +} + +fn append_stage2_relations<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + params: &JoltProtocolParams, +) -> Result<(), MlirError> { + let max_rounds = stage2_max_rounds(params); + append_relation( + context, + module, + RelationSpec { + symbol: "jolt.stage2.product_virtual.uniskip", + kind: "sumcheck", + domain: "jolt.stage2_uniskip_domain", + num_rounds: 1, + degree: PRODUCT_UNISKIP_DEGREE_BOUND, + output_count: 1, + }, + )?; + append_relation( + context, + module, + RelationSpec { + symbol: "jolt.stage2.ram.read_write", + kind: "sumcheck", + domain: "jolt.stage2_ram_rw_domain", + num_rounds: max_rounds, + degree: RAM_RW_DEGREE, + output_count: 3, + }, + )?; + append_relation( + context, + module, + RelationSpec { + symbol: "jolt.stage2.product_virtual.remainder", + kind: "sumcheck", + domain: "jolt.trace_domain", + num_rounds: params.log_t, + degree: PRODUCT_REMAINDER_DEGREE, + output_count: PRODUCT_REMAINDER_OUTPUTS.len(), + }, + )?; + append_relation( + context, + module, + RelationSpec { + symbol: "jolt.stage2.instruction_lookup.claim_reduction", + kind: "sumcheck", + domain: "jolt.trace_domain", + num_rounds: params.log_t, + degree: INSTRUCTION_CLAIM_REDUCTION_DEGREE, + output_count: STAGE2_INSTRUCTION_INPUTS.len(), + }, + )?; + append_relation( + context, + module, + RelationSpec { + symbol: "jolt.stage2.ram.raf_evaluation", + kind: "sumcheck", + domain: "jolt.ram_address_domain", + num_rounds: params.log_k_ram, + degree: RAM_RAF_DEGREE, + output_count: 1, + }, + )?; + append_relation( + context, + module, + RelationSpec { + symbol: "jolt.stage2.ram.output_check", + kind: "sumcheck", + domain: "jolt.ram_address_domain", + num_rounds: params.log_k_ram, + degree: RAM_OUTPUT_DEGREE, + output_count: 1, + }, + )?; + append_relation( + context, + module, + RelationSpec { + symbol: "jolt.stage2.batched", + kind: "batched_sumcheck", + domain: "jolt.stage2_ram_rw_domain", + num_rounds: max_rounds, + degree: RAM_RW_DEGREE, + output_count: 18, + }, + ) +} + +fn append_relation<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + spec: RelationSpec<'_>, +) -> Result<(), MlirError> { + context.append_op( + module, + "piop.relation", + Some(spec.symbol), + &[ + ("kind", &format!("\"{}\"", spec.kind)), + ("domain", &format!("@{}", spec.domain)), + ("num_rounds", &int_attr(spec.num_rounds)), + ("degree", &int_attr(spec.degree)), + ("output_count", &int_attr(spec.output_count)), + ], + ) +} + +fn append_stage2_opening_inputs<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + params: &JoltProtocolParams, +) -> Result, MlirError> { + let product = append_stage1_opening_input(context, module, params, "Product")?; + let should_branch = append_stage1_opening_input(context, module, params, "ShouldBranch")?; + let should_jump = append_stage1_opening_input(context, module, params, "ShouldJump")?; + let ram_read_value = append_stage1_opening_input(context, module, params, "RamReadValue")?; + let ram_write_value = append_stage1_opening_input(context, module, params, "RamWriteValue")?; + let lookup_output = append_stage1_opening_input(context, module, params, "LookupOutput")?; + let left_lookup_operand = + append_stage1_opening_input(context, module, params, "LeftLookupOperand")?; + let right_lookup_operand = + append_stage1_opening_input(context, module, params, "RightLookupOperand")?; + let left_instruction_input = + append_stage1_opening_input(context, module, params, "LeftInstructionInput")?; + let right_instruction_input = + append_stage1_opening_input(context, module, params, "RightInstructionInput")?; + let ram_address = append_stage1_opening_input(context, module, params, "RamAddress")?; + + Ok(Stage2OpeningInputs { + product, + should_branch, + should_jump, + ram_read_value, + ram_write_value, + lookup_output, + left_lookup_operand, + right_lookup_operand, + left_instruction_input, + right_instruction_input, + ram_address, + }) +} + +fn append_stage1_opening_input<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + params: &JoltProtocolParams, + oracle: &str, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "piop.opening_input", + Some(&format!("stage2.input.stage1.{oracle}")), + &[ + ("source_stage", "@stage1"), + ( + "source_claim", + &format!("@stage1.outer_remaining.opening.{oracle}"), + ), + ("oracle", &format!("@{oracle}")), + ("domain", "@jolt.trace_domain"), + ("point_arity", &int_attr(params.log_t)), + ("claim_kind", r#""virtual""#), + ], + &[], + &["!poly.point", "!field.scalar", "!piop.opening_claim_type"], + )?; + Ok(Stage2OpeningInput { + point: result(op, 0, "piop.opening_input")?, + eval: result(op, 1, "piop.opening_input")?, + claim: result(op, 2, "piop.opening_input")?, + }) +} + +fn append_transcript_squeeze<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + state: Value<'c, 'a>, + symbol: &str, + label: &str, + kind: &str, + count: usize, +) -> Result<(Value<'c, 'a>, Value<'c, 'a>), MlirError> { + let op = context.append_typed_op( + module, + "transcript.squeeze", + Some(symbol), + &[ + ("label", &format!("\"{label}\"")), + ("kind", &format!("\"{kind}\"")), + ("count", &int_attr(count)), + ], + &[state], + &[ + "!transcript.state_type", + transcript_squeeze_protocol_result_type(kind)?, + ], + )?; + Ok(( + result(op, 0, "transcript.squeeze")?, + result(op, 1, "transcript.squeeze")?, + )) +} + +fn append_field_const<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + value: usize, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "field.const", + Some(symbol), + &[("field", "@bn254_fr"), ("value", &int_attr(value))], + &[], + &["!field.scalar"], + )?; + first_result(op, "field.const") +} + +fn append_field_binary<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + op_name: &str, + symbol: &str, + lhs: Value<'c, 'a>, + rhs: Value<'c, 'a>, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + op_name, + Some(symbol), + &[], + &[lhs, rhs], + &["!field.scalar"], + )?; + first_result(op, op_name) +} + +fn append_field_add<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + lhs: Value<'c, 'a>, + rhs: Value<'c, 'a>, +) -> Result, MlirError> { + append_field_binary(context, module, "field.add", symbol, lhs, rhs) +} + +fn append_field_mul<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + lhs: Value<'c, 'a>, + rhs: Value<'c, 'a>, +) -> Result, MlirError> { + append_field_binary(context, module, "field.mul", symbol, lhs, rhs) +} + +fn append_lagrange_basis_eval<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + point: Value<'c, 'a>, + index: usize, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "poly.lagrange_basis_eval", + Some(symbol), + &[ + ( + "domain_start", + &int_attr_signed(PRODUCT_UNISKIP_DOMAIN_START), + ), + ("domain_size", &int_attr(PRODUCT_UNISKIP_DOMAIN_SIZE)), + ("index", &int_attr(index)), + ], + &[point], + &["!field.scalar"], + )?; + first_result(op, "poly.lagrange_basis_eval") +} + +fn append_product_uniskip<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + _params: &JoltProtocolParams, + state: Value<'c, 'a>, + stage: Value<'c, 'a>, + inputs: &Stage2OpeningInputs<'c, 'a>, + tau_high: Value<'c, 'a>, +) -> Result<(Value<'c, 'a>, Stage2UniskipOutput<'c, 'a>), MlirError> { + let product_weight = append_lagrange_basis_eval( + context, + module, + "stage2.product_virtual.uniskip.weight.Product", + tau_high, + 0, + )?; + let branch_weight = append_lagrange_basis_eval( + context, + module, + "stage2.product_virtual.uniskip.weight.ShouldBranch", + tau_high, + 1, + )?; + let jump_weight = append_lagrange_basis_eval( + context, + module, + "stage2.product_virtual.uniskip.weight.ShouldJump", + tau_high, + 2, + )?; + let product_term = append_field_mul( + context, + module, + "stage2.product_virtual.uniskip.term.Product", + product_weight, + inputs.product.eval, + )?; + let branch_term = append_field_mul( + context, + module, + "stage2.product_virtual.uniskip.term.ShouldBranch", + branch_weight, + inputs.should_branch.eval, + )?; + let jump_term = append_field_mul( + context, + module, + "stage2.product_virtual.uniskip.term.ShouldJump", + jump_weight, + inputs.should_jump.eval, + )?; + let product_branch_sum = append_field_add( + context, + module, + "stage2.product_virtual.uniskip.partial.ProductShouldBranch", + product_term, + branch_term, + )?; + let input_claim = append_field_add( + context, + module, + "stage2.product_virtual.uniskip.claim_expr", + product_branch_sum, + jump_term, + )?; + let claim = append_sumcheck_claim( + context, + module, + SumcheckClaimSpec { + symbol: "stage2.product_virtual.uniskip.input", + stage: "stage2", + domain: "jolt.stage2_uniskip_domain", + num_rounds: 1, + degree: PRODUCT_UNISKIP_DEGREE_BOUND, + claim: "stage2.product_virtual.weighted_stage1_outputs", + relation: "jolt.stage2.product_virtual.uniskip", + }, + input_claim, + &[ + inputs.product.claim, + inputs.should_branch.claim, + inputs.should_jump.claim, + ], + )?; + let batch = append_sumcheck_batch( + context, + module, + stage, + &[claim], + SumcheckBatchSpec { + symbol: "stage2.product_virtual.uniskip.batch", + stage: "stage2", + proof_slot: "stage2.product_virtual.uni_skip_first_round", + policy: "single_instance", + ordered_claims: &["stage2.product_virtual.uniskip.input"], + claim_label: "uniskip_claim", + round_label: "uniskip_poly", + round_schedule: "[1]".to_owned(), + }, + )?; + let (state, point, result_value) = append_sumcheck( + context, + module, + state, + batch, + SumcheckDriverSpec { + symbol: "stage2.product_virtual.uniskip.sumcheck", + stage: "stage2", + proof_slot: "stage2.product_virtual.uni_skip_first_round", + relation: "jolt.stage2.product_virtual.uniskip", + policy: "univariate_skip", + round_schedule: "[1]".to_owned(), + claim_label: "uniskip_claim", + round_label: "uniskip_poly", + num_rounds: 1, + degree: PRODUCT_UNISKIP_DEGREE_BOUND, + }, + )?; + let (point, result_value) = append_sumcheck_instance_result( + context, + module, + SumcheckInstanceResultSpec { + symbol: "stage2.product_virtual.uniskip.instance", + source: "stage2.product_virtual.uniskip.sumcheck", + claim: "stage2.product_virtual.uniskip.input", + relation: "jolt.stage2.product_virtual.uniskip", + index: 0, + point_arity: 1, + num_rounds: 1, + round_offset: 0, + point_order: "as_is", + degree: PRODUCT_UNISKIP_DEGREE_BOUND, + }, + point, + result_value, + )?; + let eval = append_sumcheck_eval( + context, + module, + "stage2.product_virtual.uniskip.eval.UnivariateSkip", + "stage2.product_virtual.uniskip.sumcheck", + "UnivariateSkip", + 0, + result_value, + )?; + let opening = append_opening_claim( + context, + module, + point, + eval, + OpeningClaimSpec { + symbol: "stage2.product_virtual.uniskip.opening.UnivariateSkip", + oracle: "UnivariateSkip", + domain: "jolt.stage2_uniskip_domain", + point_arity: 1, + claim_kind: "virtual", + }, + )?; + Ok((state, Stage2UniskipOutput { opening, eval })) +} + +fn append_stage2_batched_sumcheck<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + params: &JoltProtocolParams, + spec: Stage2BatchedSumcheckInputs<'c, 'a, '_>, +) -> Result, MlirError> { + let inputs = spec.openings; + let uniskip = spec.uniskip; + let max_rounds = stage2_max_rounds(params); + let product_offset = max_rounds - params.log_t; + let ram_offset = params.log_t; + let ram_write_term = append_field_mul( + context, + module, + "stage2.ram_read_write.term.RamWriteValue", + spec.ram_read_write_gamma, + inputs.ram_write_value.eval, + )?; + let ram_read_write_claim = append_field_add( + context, + module, + "stage2.ram_read_write.claim_expr", + inputs.ram_read_value.eval, + ram_write_term, + )?; + let product_remainder_claim = uniskip.eval; + let gamma2 = append_field_mul( + context, + module, + "stage2.instruction_lookup.gamma2", + spec.instruction_lookup_gamma, + spec.instruction_lookup_gamma, + )?; + let gamma3 = append_field_mul( + context, + module, + "stage2.instruction_lookup.gamma3", + gamma2, + spec.instruction_lookup_gamma, + )?; + let gamma4 = append_field_mul( + context, + module, + "stage2.instruction_lookup.gamma4", + gamma2, + gamma2, + )?; + let left_lookup_term = append_field_mul( + context, + module, + "stage2.instruction_lookup.term.LeftLookupOperand", + spec.instruction_lookup_gamma, + inputs.left_lookup_operand.eval, + )?; + let right_lookup_term = append_field_mul( + context, + module, + "stage2.instruction_lookup.term.RightLookupOperand", + gamma2, + inputs.right_lookup_operand.eval, + )?; + let left_input_term = append_field_mul( + context, + module, + "stage2.instruction_lookup.term.LeftInstructionInput", + gamma3, + inputs.left_instruction_input.eval, + )?; + let right_input_term = append_field_mul( + context, + module, + "stage2.instruction_lookup.term.RightInstructionInput", + gamma4, + inputs.right_instruction_input.eval, + )?; + let instruction_sum_0 = append_field_add( + context, + module, + "stage2.instruction_lookup.partial.LookupOutputLeftOperand", + inputs.lookup_output.eval, + left_lookup_term, + )?; + let instruction_sum_1 = append_field_add( + context, + module, + "stage2.instruction_lookup.partial.RightOperand", + instruction_sum_0, + right_lookup_term, + )?; + let instruction_sum_2 = append_field_add( + context, + module, + "stage2.instruction_lookup.partial.LeftInstructionInput", + instruction_sum_1, + left_input_term, + )?; + let instruction_claim = append_field_add( + context, + module, + "stage2.instruction_lookup.claim_reduction.claim_expr", + instruction_sum_2, + right_input_term, + )?; + let ram_raf_claim = inputs.ram_address.eval; + let ram_output_claim = append_field_const(context, module, "stage2.ram_output.zero", 0)?; + let claims = [ + append_sumcheck_claim( + context, + module, + SumcheckClaimSpec { + symbol: "stage2.ram_read_write.input", + stage: "stage2", + domain: "jolt.stage2_ram_rw_domain", + num_rounds: max_rounds, + degree: RAM_RW_DEGREE, + claim: "stage2.ram_read_write.weighted_values", + relation: "jolt.stage2.ram.read_write", + }, + ram_read_write_claim, + &[inputs.ram_read_value.claim, inputs.ram_write_value.claim], + )?, + append_sumcheck_claim( + context, + module, + SumcheckClaimSpec { + symbol: "stage2.product_virtual.remainder.input", + stage: "stage2", + domain: "jolt.trace_domain", + num_rounds: params.log_t, + degree: PRODUCT_REMAINDER_DEGREE, + claim: "stage2.product_virtual.uniskip.opening", + relation: "jolt.stage2.product_virtual.remainder", + }, + product_remainder_claim, + &[uniskip.opening], + )?, + append_sumcheck_claim( + context, + module, + SumcheckClaimSpec { + symbol: "stage2.instruction_lookup.claim_reduction.input", + stage: "stage2", + domain: "jolt.trace_domain", + num_rounds: params.log_t, + degree: INSTRUCTION_CLAIM_REDUCTION_DEGREE, + claim: "stage2.instruction_lookup.weighted_operands", + relation: "jolt.stage2.instruction_lookup.claim_reduction", + }, + instruction_claim, + &[ + inputs.lookup_output.claim, + inputs.left_lookup_operand.claim, + inputs.right_lookup_operand.claim, + inputs.left_instruction_input.claim, + inputs.right_instruction_input.claim, + ], + )?, + append_sumcheck_claim( + context, + module, + SumcheckClaimSpec { + symbol: "stage2.ram_raf.input", + stage: "stage2", + domain: "jolt.ram_address_domain", + num_rounds: params.log_k_ram, + degree: RAM_RAF_DEGREE, + claim: "stage2.ram_raf.ram_address", + relation: "jolt.stage2.ram.raf_evaluation", + }, + ram_raf_claim, + &[inputs.ram_address.claim], + )?, + append_sumcheck_claim( + context, + module, + SumcheckClaimSpec { + symbol: "stage2.ram_output.input", + stage: "stage2", + domain: "jolt.ram_address_domain", + num_rounds: params.log_k_ram, + degree: RAM_OUTPUT_DEGREE, + claim: "zero", + relation: "jolt.stage2.ram.output_check", + }, + ram_output_claim, + &[], + )?, + ]; + let batch = append_sumcheck_batch( + context, + module, + spec.stage, + &claims, + SumcheckBatchSpec { + symbol: "stage2.batch", + stage: "stage2", + proof_slot: "stage2.sumcheck", + policy: "jolt_core_stage2_aligned", + ordered_claims: &[ + "stage2.ram_read_write.input", + "stage2.product_virtual.remainder.input", + "stage2.instruction_lookup.claim_reduction.input", + "stage2.ram_raf.input", + "stage2.ram_output.input", + ], + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + round_schedule: format!("[{}, {}]", params.log_t, params.log_k_ram), + }, + )?; + let (state, point, result_value) = append_sumcheck( + context, + module, + spec.state, + batch, + SumcheckDriverSpec { + symbol: "stage2.sumcheck", + stage: "stage2", + proof_slot: "stage2.sumcheck", + relation: "jolt.stage2.batched", + policy: "jolt_core_stage2_aligned", + round_schedule: format!("[{}, {}]", params.log_t, params.log_k_ram), + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + num_rounds: max_rounds, + degree: RAM_RW_DEGREE, + }, + )?; + let ram_rw = append_sumcheck_instance_result( + context, + module, + SumcheckInstanceResultSpec { + symbol: "stage2.ram_read_write.instance", + source: "stage2.sumcheck", + claim: "stage2.ram_read_write.input", + relation: "jolt.stage2.ram.read_write", + index: 0, + point_arity: max_rounds, + num_rounds: max_rounds, + round_offset: 0, + point_order: "reverse", + degree: RAM_RW_DEGREE, + }, + point, + result_value, + )?; + let product = append_sumcheck_instance_result( + context, + module, + SumcheckInstanceResultSpec { + symbol: "stage2.product_virtual.remainder.instance", + source: "stage2.sumcheck", + claim: "stage2.product_virtual.remainder.input", + relation: "jolt.stage2.product_virtual.remainder", + index: 1, + point_arity: params.log_t, + num_rounds: params.log_t, + round_offset: product_offset, + point_order: "reverse", + degree: PRODUCT_REMAINDER_DEGREE, + }, + point, + result_value, + )?; + let instruction = append_sumcheck_instance_result( + context, + module, + SumcheckInstanceResultSpec { + symbol: "stage2.instruction_lookup.claim_reduction.instance", + source: "stage2.sumcheck", + claim: "stage2.instruction_lookup.claim_reduction.input", + relation: "jolt.stage2.instruction_lookup.claim_reduction", + index: 2, + point_arity: params.log_t, + num_rounds: params.log_t, + round_offset: product_offset, + point_order: "reverse", + degree: INSTRUCTION_CLAIM_REDUCTION_DEGREE, + }, + point, + result_value, + )?; + let ram_raf = append_sumcheck_instance_result( + context, + module, + SumcheckInstanceResultSpec { + symbol: "stage2.ram_raf.instance", + source: "stage2.sumcheck", + claim: "stage2.ram_raf.input", + relation: "jolt.stage2.ram.raf_evaluation", + index: 3, + point_arity: params.log_k_ram, + num_rounds: params.log_k_ram, + round_offset: ram_offset, + point_order: "reverse", + degree: RAM_RAF_DEGREE, + }, + point, + result_value, + )?; + let ram_output = append_sumcheck_instance_result( + context, + module, + SumcheckInstanceResultSpec { + symbol: "stage2.ram_output.instance", + source: "stage2.sumcheck", + claim: "stage2.ram_output.input", + relation: "jolt.stage2.ram.output_check", + index: 4, + point_arity: params.log_k_ram, + num_rounds: params.log_k_ram, + round_offset: ram_offset, + point_order: "reverse", + degree: RAM_OUTPUT_DEGREE, + }, + point, + result_value, + )?; + append_stage2_output_openings( + context, + module, + params, + Stage2OutputOpeningSpec { + outputs: &[ + InstanceOutput { + prefix: "stage2.product_virtual.remainder", + instance: product, + eval_source: "stage2.sumcheck", + outputs: &PRODUCT_REMAINDER_OUTPUTS, + domain: "jolt.trace_domain", + point_arity: params.log_t, + claim_kind: "virtual", + }, + InstanceOutput { + prefix: "stage2.instruction_lookup.claim_reduction", + instance: instruction, + eval_source: "stage2.sumcheck", + outputs: &STAGE2_INSTRUCTION_INPUTS, + domain: "jolt.trace_domain", + point_arity: params.log_t, + claim_kind: "virtual", + }, + ], + ram_rw, + ram_raf, + ram_output, + stage1_ram_address_point: inputs.ram_address.point, + }, + )?; + Ok(state) +} + +fn append_stage2_output_openings<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + params: &JoltProtocolParams, + spec: Stage2OutputOpeningSpec<'c, 'a, '_>, +) -> Result<(), MlirError> { + let mut claims = Vec::new(); + let mut claim_symbols = Vec::new(); + + for (index, &oracle) in ["RamVal", "RamRa"].iter().enumerate() { + let symbol = format!("stage2.ram_read_write.opening.{oracle}"); + let eval = append_sumcheck_eval( + context, + module, + &format!("stage2.ram_read_write.eval.{oracle}"), + "stage2.sumcheck", + oracle, + index, + spec.ram_rw.1, + )?; + claim_symbols.push(symbol.clone()); + claims.push(append_opening_claim( + context, + module, + spec.ram_rw.0, + eval, + OpeningClaimSpec { + symbol: &symbol, + oracle, + domain: "jolt.stage2_ram_rw_domain", + point_arity: stage2_max_rounds(params), + claim_kind: "virtual", + }, + )?); + } + let ram_inc_point = append_point_slice( + context, + module, + "stage2.ram_read_write.point.RamInc", + "stage2.ram_read_write.instance", + params.log_k_ram, + params.log_t, + spec.ram_rw.0, + )?; + let ram_inc_eval = append_sumcheck_eval( + context, + module, + "stage2.ram_read_write.eval.RamInc", + "stage2.sumcheck", + "RamInc", + 2, + spec.ram_rw.1, + )?; + claim_symbols.push("stage2.ram_read_write.opening.RamInc".to_owned()); + claims.push(append_opening_claim( + context, + module, + ram_inc_point, + ram_inc_eval, + OpeningClaimSpec { + symbol: "stage2.ram_read_write.opening.RamInc", + oracle: "RamInc", + domain: "jolt.trace_domain", + point_arity: params.log_t, + claim_kind: "committed", + }, + )?); + + for output in spec.outputs { + for (index, &oracle) in output.outputs.iter().enumerate() { + let symbol = format!("{}.opening.{oracle}", output.prefix); + let eval = append_sumcheck_eval( + context, + module, + &format!("{}.eval.{oracle}", output.prefix), + output.eval_source, + oracle, + index, + output.instance.1, + )?; + claim_symbols.push(symbol.clone()); + claims.push(append_opening_claim( + context, + module, + output.instance.0, + eval, + OpeningClaimSpec { + symbol: &symbol, + oracle, + domain: output.domain, + point_arity: output.point_arity, + claim_kind: output.claim_kind, + }, + )?); + } + } + + let ram_raf_point = append_point_concat( + context, + module, + "stage2.ram_raf.point.RamRa", + "address_then_cycle", + params.log_k_ram + params.log_t, + &[spec.ram_raf.0, spec.stage1_ram_address_point], + )?; + let ram_raf_eval = append_sumcheck_eval( + context, + module, + "stage2.ram_raf.eval.RamRa", + "stage2.sumcheck", + "RamRa", + 0, + spec.ram_raf.1, + )?; + claim_symbols.push("stage2.ram_raf.opening.RamRa".to_owned()); + claims.push(append_opening_claim( + context, + module, + ram_raf_point, + ram_raf_eval, + OpeningClaimSpec { + symbol: "stage2.ram_raf.opening.RamRa", + oracle: "RamRa", + domain: "jolt.stage2_ram_rw_domain", + point_arity: params.log_k_ram + params.log_t, + claim_kind: "virtual", + }, + )?); + + let ram_output_eval = append_sumcheck_eval( + context, + module, + "stage2.ram_output.eval.RamValFinal", + "stage2.sumcheck", + "RamValFinal", + 0, + spec.ram_output.1, + )?; + claim_symbols.push("stage2.ram_output.opening.RamValFinal".to_owned()); + claims.push(append_opening_claim( + context, + module, + spec.ram_output.0, + ram_output_eval, + OpeningClaimSpec { + symbol: "stage2.ram_output.opening.RamValFinal", + oracle: "RamValFinal", + domain: "jolt.ram_address_domain", + point_arity: params.log_k_ram, + claim_kind: "virtual", + }, + )?); + + let claim_names = claim_symbols.iter().map(String::as_str).collect::>(); + let _batch = context.append_typed_op( + module, + "piop.opening_batch", + Some("stage2.openings"), + &[ + ("stage", "@stage2"), + ("proof_slot", "@stage2.openings"), + ("policy", r#""jolt_stage2_output_order""#), + ("count", &int_attr(claims.len())), + ("ordered_claims", &symbol_array_attr(&claim_names)), + ], + &claims, + &["!piop.opening_batch_type"], + )?; + Ok(()) +} + +fn append_sumcheck_claim<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + spec: SumcheckClaimSpec<'_>, + input_claim: Value<'c, 'a>, + inputs: &[Value<'c, 'a>], +) -> Result, MlirError> { + let mut operands = Vec::with_capacity(inputs.len() + 1); + operands.push(input_claim); + operands.extend_from_slice(inputs); + let op = context.append_typed_op( + module, + "piop.sumcheck_claim", + Some(spec.symbol), + &[ + ("stage", &format!("@{}", spec.stage)), + ("domain", &format!("@{}", spec.domain)), + ("num_rounds", &int_attr(spec.num_rounds)), + ("degree", &int_attr(spec.degree)), + ("claim", &format!("@{}", spec.claim)), + ("relation", &format!("@{}", spec.relation)), + ], + &operands, + &["!piop.sumcheck_claim_type"], + )?; + first_result(op, "piop.sumcheck_claim") +} + +fn append_sumcheck_batch<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + stage: Value<'c, 'a>, + claims: &[Value<'c, 'a>], + spec: SumcheckBatchSpec<'_>, +) -> Result, MlirError> { + let mut operands = Vec::with_capacity(claims.len() + 1); + operands.push(stage); + operands.extend_from_slice(claims); + let op = context.append_typed_op( + module, + "piop.sumcheck_batch", + Some(spec.symbol), + &[ + ("stage", &format!("@{}", spec.stage)), + ("proof_slot", &format!("@{}", spec.proof_slot)), + ("policy", &format!("\"{}\"", spec.policy)), + ("count", &int_attr(spec.ordered_claims.len())), + ("ordered_claims", &symbol_array_attr(spec.ordered_claims)), + ("claim_label", &format!("\"{}\"", spec.claim_label)), + ("round_label", &format!("\"{}\"", spec.round_label)), + ("round_schedule", &spec.round_schedule), + ], + &operands, + &["!piop.sumcheck_batch_type"], + )?; + first_result(op, "piop.sumcheck_batch") +} + +fn append_sumcheck<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + state: Value<'c, 'a>, + batch: Value<'c, 'a>, + spec: SumcheckDriverSpec<'_>, +) -> Result<(Value<'c, 'a>, Value<'c, 'a>, Value<'c, 'a>), MlirError> { + let op = context.append_typed_op( + module, + "piop.sumcheck", + Some(spec.symbol), + &[ + ("stage", &format!("@{}", spec.stage)), + ("proof_slot", &format!("@{}", spec.proof_slot)), + ("relation", &format!("@{}", spec.relation)), + ("policy", &format!("\"{}\"", spec.policy)), + ("round_schedule", &spec.round_schedule), + ("claim_label", &format!("\"{}\"", spec.claim_label)), + ("round_label", &format!("\"{}\"", spec.round_label)), + ("num_rounds", &int_attr(spec.num_rounds)), + ("degree", &int_attr(spec.degree)), + ], + &[state, batch], + &[ + "!transcript.state_type", + "!poly.point", + "!piop.sumcheck_result_type", + "!piop.sumcheck_proof_type", + ], + )?; + Ok(( + result(op, 0, "piop.sumcheck")?, + result(op, 1, "piop.sumcheck")?, + result(op, 2, "piop.sumcheck")?, + )) +} + +fn append_sumcheck_instance_result<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + spec: SumcheckInstanceResultSpec<'_>, + point: Value<'c, 'a>, + result_value: Value<'c, 'a>, +) -> Result<(Value<'c, 'a>, Value<'c, 'a>), MlirError> { + let op = context.append_typed_op( + module, + "piop.sumcheck_instance_result", + Some(spec.symbol), + &[ + ("source", &format!("@{}", spec.source)), + ("claim", &format!("@{}", spec.claim)), + ("relation", &format!("@{}", spec.relation)), + ("index", &int_attr(spec.index)), + ("point_arity", &int_attr(spec.point_arity)), + ("num_rounds", &int_attr(spec.num_rounds)), + ("round_offset", &int_attr(spec.round_offset)), + ("point_order", &format!("\"{}\"", spec.point_order)), + ("degree", &int_attr(spec.degree)), + ], + &[point, result_value], + &["!poly.point", "!piop.sumcheck_result_type"], + )?; + Ok(( + result(op, 0, "piop.sumcheck_instance_result")?, + result(op, 1, "piop.sumcheck_instance_result")?, + )) +} + +fn append_sumcheck_eval<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + source: &str, + oracle: &str, + index: usize, + result_value: Value<'c, 'a>, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "piop.sumcheck_eval", + Some(symbol), + &[ + ("source", &format!("@{source}")), + ("name", &format!("@{symbol}")), + ("index", &int_attr(index)), + ("oracle", &format!("@{oracle}")), + ], + &[result_value], + &["!field.scalar"], + )?; + first_result(op, "piop.sumcheck_eval") +} + +fn append_opening_claim<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + point: Value<'c, 'a>, + eval: Value<'c, 'a>, + spec: OpeningClaimSpec<'_>, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "piop.opening_claim", + Some(spec.symbol), + &[ + ("oracle", &format!("@{}", spec.oracle)), + ("domain", &format!("@{}", spec.domain)), + ("point_arity", &int_attr(spec.point_arity)), + ("claim_kind", &format!("\"{}\"", spec.claim_kind)), + ], + &[point, eval], + &["!piop.opening_claim_type"], + )?; + first_result(op, "piop.opening_claim") +} + +fn append_point_slice<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + source: &str, + offset: usize, + length: usize, + point: Value<'c, 'a>, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "poly.point_slice", + Some(symbol), + &[ + ("source", &format!("@{source}")), + ("offset", &int_attr(offset)), + ("length", &int_attr(length)), + ], + &[point], + &["!poly.point"], + )?; + first_result(op, "poly.point_slice") +} + +fn append_point_concat<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + layout: &str, + arity: usize, + points: &[Value<'c, 'a>], +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "poly.point_concat", + Some(symbol), + &[ + ("layout", &format!("\"{layout}\"")), + ("arity", &int_attr(arity)), + ], + points, + &["!poly.point"], + )?; + first_result(op, "poly.point_concat") +} + +fn first_result<'c, 'a>( + operation: OperationRef<'c, 'a>, + operation_name: &str, +) -> Result, MlirError> { + result(operation, 0, operation_name) +} + +fn result<'c, 'a>( + operation: OperationRef<'c, 'a>, + index: usize, + operation_name: &str, +) -> Result, MlirError> { + operation + .result(index) + .map(Into::into) + .map_err(|_| schema_error(format!("{operation_name} requires result {index}"))) +} + +#[derive(Clone, Debug)] +struct StageParamsAst { + field: String, + pcs: String, + transcript: String, +} + +fn stage_params(module: &BoltModule<'_, Party>) -> Result { + let mut operation = module.as_mlir_module().body().first_operation(); + while let Some(op) = operation { + operation = op.next_in_block(); + if operation_name(op) == "protocol.params" { + return Ok(StageParamsAst { + field: symbol_attr(op, "field")?, + pcs: symbol_attr(op, "pcs")?, + transcript: symbol_attr(op, "transcript")?, + }); + } + } + Err(schema_error("stage2 lowering requires protocol.params")) +} + +fn operation_result_key_at( + operation: OperationRef<'_, '_>, + index: usize, +) -> Result { + let result = operation.result(index).map_err(|_| { + schema_error(format!( + "{} requires result {index}", + operation_name(operation) + )) + })?; + result_key(result.owner(), result.result_number()) +} + +fn result_key(operation: OperationRef<'_, '_>, result_number: usize) -> Result { + Ok(format!( + "{}#{result_number}", + string_attr(operation, "sym_name")? + )) +} + +fn operand_key(operation: OperationRef<'_, '_>, index: usize) -> Result { + let operand = operation.operand(index).map_err(|_| { + schema_error(format!( + "{} requires operand {index}", + operation_name(operation) + )) + })?; + let owner = OperationResult::try_from(operand).map_err(|_| { + schema_error(format!( + "{} operand {index} must be an op result", + operation_name(operation) + )) + })?; + result_key(owner.owner(), owner.result_number()).map_err(|_| { + schema_error(format!( + "{} operand {index} owner missing sym_name", + operation_name(operation) + )) + }) +} + +fn lowered_operands<'c, 'a>( + operation: OperationRef<'_, '_>, + value_map: &BTreeMap>, + start_index: usize, +) -> Result>, MlirError> { + (start_index..operation.operand_count()) + .map(|index| { + let key = operand_key(operation, index)?; + value_map.get(&key).copied().ok_or_else(|| { + schema_error(format!( + "{} operand {index} was not lowered", + operation_name(operation) + )) + }) + }) + .collect() +} + +fn insert_result_mapping<'c, 'a>( + value_map: &mut BTreeMap>, + source: OperationRef<'_, '_>, + target: OperationRef<'c, 'a>, + source_index: usize, + target_index: usize, +) -> Result<(), MlirError> { + let key = operation_result_key_at(source, source_index)?; + let value = target.result(target_index).map(Into::into).map_err(|_| { + schema_error(format!( + "{} requires result {target_index}", + operation_name(target) + )) + })?; + let inserted = value_map.insert(key, value); + debug_assert!(inserted.is_none()); + Ok(()) +} + +fn symbol_ref(symbol: &str) -> String { + format!("@{symbol}") +} + +fn stage2_max_rounds(params: &JoltProtocolParams) -> usize { + params.log_t + params.log_k_ram +} + +fn int_attr(value: usize) -> String { + format!("{value} : i64") +} + +fn int_attr_signed(value: isize) -> String { + format!("{value} : i64") +} + +fn symbol_array_attr(values: &[&str]) -> String { + let values = values + .iter() + .map(|value| format!("@{value}")) + .collect::>() + .join(", "); + format!("[{values}]") +} + +fn schema_error(message: impl Into) -> MlirError { + SchemaError::new(message).into() +} + +#[derive(Clone, Copy)] +struct Stage2OpeningInput<'c, 'a> { + point: Value<'c, 'a>, + eval: Value<'c, 'a>, + claim: Value<'c, 'a>, +} + +struct Stage2OpeningInputs<'c, 'a> { + product: Stage2OpeningInput<'c, 'a>, + should_branch: Stage2OpeningInput<'c, 'a>, + should_jump: Stage2OpeningInput<'c, 'a>, + ram_read_value: Stage2OpeningInput<'c, 'a>, + ram_write_value: Stage2OpeningInput<'c, 'a>, + lookup_output: Stage2OpeningInput<'c, 'a>, + left_lookup_operand: Stage2OpeningInput<'c, 'a>, + right_lookup_operand: Stage2OpeningInput<'c, 'a>, + left_instruction_input: Stage2OpeningInput<'c, 'a>, + right_instruction_input: Stage2OpeningInput<'c, 'a>, + ram_address: Stage2OpeningInput<'c, 'a>, +} + +#[derive(Clone, Copy)] +struct Stage2UniskipOutput<'c, 'a> { + opening: Value<'c, 'a>, + eval: Value<'c, 'a>, +} + +struct Stage2BatchedSumcheckInputs<'c, 'a, 'b> { + state: Value<'c, 'a>, + stage: Value<'c, 'a>, + openings: &'b Stage2OpeningInputs<'c, 'a>, + uniskip: Stage2UniskipOutput<'c, 'a>, + ram_read_write_gamma: Value<'c, 'a>, + instruction_lookup_gamma: Value<'c, 'a>, +} + +struct RelationSpec<'a> { + symbol: &'a str, + kind: &'a str, + domain: &'a str, + num_rounds: usize, + degree: usize, + output_count: usize, +} + +struct SumcheckClaimSpec<'a> { + symbol: &'a str, + stage: &'a str, + domain: &'a str, + num_rounds: usize, + degree: usize, + claim: &'a str, + relation: &'a str, +} + +struct SumcheckBatchSpec<'a> { + symbol: &'a str, + stage: &'a str, + proof_slot: &'a str, + policy: &'a str, + ordered_claims: &'a [&'a str], + claim_label: &'a str, + round_label: &'a str, + round_schedule: String, +} + +struct SumcheckDriverSpec<'a> { + symbol: &'a str, + stage: &'a str, + proof_slot: &'a str, + relation: &'a str, + policy: &'a str, + round_schedule: String, + claim_label: &'a str, + round_label: &'a str, + num_rounds: usize, + degree: usize, +} + +struct SumcheckInstanceResultSpec<'a> { + symbol: &'a str, + source: &'a str, + claim: &'a str, + relation: &'a str, + index: usize, + point_arity: usize, + num_rounds: usize, + round_offset: usize, + point_order: &'a str, + degree: usize, +} + +struct OpeningClaimSpec<'a> { + symbol: &'a str, + oracle: &'a str, + domain: &'a str, + point_arity: usize, + claim_kind: &'a str, +} + +struct Stage2OutputOpeningSpec<'c, 'a, 'b> { + outputs: &'b [InstanceOutput<'c, 'a, 'b>], + ram_rw: (Value<'c, 'a>, Value<'c, 'a>), + ram_raf: (Value<'c, 'a>, Value<'c, 'a>), + ram_output: (Value<'c, 'a>, Value<'c, 'a>), + stage1_ram_address_point: Value<'c, 'a>, +} + +struct InstanceOutput<'c, 'a, 'b> { + prefix: &'b str, + instance: (Value<'c, 'a>, Value<'c, 'a>), + eval_source: &'b str, + outputs: &'b [&'b str], + domain: &'b str, + point_arity: usize, + claim_kind: &'b str, +} diff --git a/crates/bolt/src/protocols/jolt/phases/stage3.rs b/crates/bolt/src/protocols/jolt/phases/stage3.rs new file mode 100644 index 0000000000..b0e3c1513d --- /dev/null +++ b/crates/bolt/src/protocols/jolt/phases/stage3.rs @@ -0,0 +1,1762 @@ +use std::collections::{BTreeMap, BTreeSet}; + +use melior::ir::block::BlockLike; +use melior::ir::operation::OperationRef; +use melior::ir::operation::{OperationLike, OperationResult}; +use melior::ir::Value; + +use crate::ir::{BoltModule, Compute, Party, Protocol, Role}; +use crate::mlir::{verify_module, MeliorContext, MlirError}; +use crate::schema::{ + operation_name, symbol_attr, verify_compute_schema, verify_party_schema, + verify_protocol_schema, SchemaError, +}; + +use super::super::oracles; +use super::super::params::JoltProtocolParams; +use super::lowering::{ + copy_attrs, field_lowering_attrs as field_compute_attrs, string_attr, + transcript_squeeze_compute_result_types, transcript_squeeze_protocol_result_type, +}; + +const SPARTAN_SHIFT_DEGREE: usize = 2; +const INSTRUCTION_INPUT_DEGREE: usize = 3; +const REGISTERS_CLAIM_REDUCTION_DEGREE: usize = 2; +const STAGE3_BATCHED_DEGREE: usize = 3; + +const STAGE3_SHIFT_INPUTS: [&str; 4] = [ + "NextUnexpandedPC", + "NextPC", + "NextIsVirtual", + "NextIsFirstInSequence", +]; +const STAGE3_SHIFT_OUTPUTS: [&str; 5] = [ + "UnexpandedPC", + "PC", + "OpFlagVirtualInstruction", + "OpFlagIsFirstInSequence", + "InstructionFlagIsNoop", +]; +const STAGE3_INSTRUCTION_INPUT_OUTPUTS: [&str; 8] = [ + "InstructionFlagLeftOperandIsRs1Value", + "Rs1Value", + "InstructionFlagLeftOperandIsPC", + "UnexpandedPC", + "InstructionFlagRightOperandIsRs2Value", + "Rs2Value", + "InstructionFlagRightOperandIsImm", + "Imm", +]; +const STAGE3_REGISTER_INPUTS: [&str; 3] = ["RdWriteValue", "Rs1Value", "Rs2Value"]; + +pub fn build_stage3_protocol<'c>( + context: &'c MeliorContext, + params: &JoltProtocolParams, +) -> Result, MlirError> { + let module = context.new_module::("jolt.stage3", None); + oracles::append_foundation_ops(context, &module, params)?; + context.append_op_with_owned_attrs( + &module, + "protocol.params", + Some("jolt.params"), + ¶ms.attrs(), + )?; + context.append_op( + &module, + "protocol.boundary", + Some("jolt.stage3"), + &[("roles", r#"["prover", "verifier"]"#)], + )?; + append_stage3_oracles(context, &module)?; + append_stage3_relations(context, &module, params)?; + let inputs = append_stage3_opening_inputs(context, &module, params)?; + + let fs = context.append_typed_op( + &module, + "transcript.state", + Some("fs_after_stage2"), + &[("scheme", "@blake2b_transcript")], + &[], + &["!transcript.state_type"], + )?; + let state = first_result(fs, "transcript.state")?; + let stage = context.append_typed_op( + &module, + "piop.stage", + Some("stage3"), + &[ + ("name", r#""shift_instruction_input_and_registers""#), + ("order", "3 : i64"), + ("roles", r#"["prover", "verifier"]"#), + ], + &[], + &["!piop.stage_type"], + )?; + let stage = first_result(stage, "piop.stage")?; + + let (state, shift_gamma) = append_transcript_squeeze( + context, + &module, + state, + "stage3.spartan_shift.gamma", + "spartan_shift_gamma", + "challenge_scalar", + 1, + )?; + let (state, instruction_gamma) = append_transcript_squeeze( + context, + &module, + state, + "stage3.instruction_input.gamma", + "instruction_input_gamma", + "challenge_scalar", + 1, + )?; + let (state, registers_gamma) = append_transcript_squeeze( + context, + &module, + state, + "stage3.registers.gamma", + "registers_gamma", + "challenge_scalar", + 1, + )?; + let _state = append_stage3_batched_sumcheck( + context, + &module, + params, + Stage3BatchedSumcheckInputs { + state, + stage, + openings: &inputs, + shift_gamma, + instruction_gamma, + registers_gamma, + }, + )?; + + verify_module(&module)?; + verify_protocol_schema(&module)?; + Ok(module) +} + +pub fn lower_stage3_to_compute<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Party>, +) -> Result, MlirError> { + verify_party_schema(module)?; + let role = module + .role() + .ok_or_else(|| schema_error("stage3 lowering requires party role"))?; + let params = stage_params(module)?; + let compute = context.new_module::(&module.name(), Some(role.clone())); + context.append_op_with_owned_attrs( + &compute, + "compute.params", + Some("jolt.compute_params"), + &[ + ("field".to_owned(), symbol_ref(¶ms.field)), + ("pcs".to_owned(), symbol_ref(¶ms.pcs)), + ("transcript".to_owned(), symbol_ref(¶ms.transcript)), + ], + )?; + context.append_op( + &compute, + "compute.function", + Some("jolt.stage3"), + &[("source", "@jolt.stage3")], + )?; + + let mut value_map = BTreeMap::new(); + let mut operation = module.as_mlir_module().body().first_operation(); + while let Some(op) = operation { + operation = op.next_in_block(); + match operation_name(op).as_str() { + "piop.relation" => { + let attrs = copy_attrs( + op, + &["kind", "domain", "num_rounds", "degree", "output_count"], + )?; + let symbol = string_attr(op, "sym_name")?; + context.append_op_with_owned_attrs( + &compute, + "compute.relation", + Some(&symbol), + &attrs, + )?; + } + "transcript.state" => { + let attrs = copy_attrs(op, &["scheme"])?; + let symbol = string_attr(op, "sym_name")?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.transcript_init", + Some(&symbol), + &attrs, + &[], + &["!compute.transcript_state"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "transcript.absorb_bytes" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["label", "payload"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.transcript_absorb_bytes", + Some(&symbol), + &attrs, + &operands, + &["!compute.transcript_state"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "transcript.squeeze" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["label", "kind", "count"])?; + let result_types = transcript_squeeze_compute_result_types(op)?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.transcript_squeeze", + Some(&symbol), + &attrs, + &operands, + &result_types, + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + insert_result_mapping(&mut value_map, op, operation, 1, 1)?; + } + "field.const" => { + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["field", "value"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.field_const", + Some(&symbol), + &attrs, + &[], + &["!compute.field_value"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "field.zero" | "field.one" => { + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["field"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + &format!("compute.{}", operation_name(op).replace('.', "_")), + Some(&symbol), + &attrs, + &[], + &["!compute.field_value"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "field.add" | "field.sub" | "field.mul" | "field.neg" | "field.pow" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = field_compute_attrs(op)?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + &format!("compute.{}", operation_name(op).replace('.', "_")), + Some(&symbol), + &attrs, + &operands, + &["!compute.field_value"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "poly.lagrange_basis_eval" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["domain_start", "domain_size", "index"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.poly_lagrange_basis_eval", + Some(&symbol), + &attrs, + &operands, + &["!compute.field_value"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "piop.opening_input" => { + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs( + op, + &[ + "source_stage", + "source_claim", + "oracle", + "domain", + "point_arity", + "claim_kind", + ], + )?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.opening_input", + Some(&symbol), + &attrs, + &[], + &[ + "!compute.point", + "!compute.field_value", + "!compute.opening_claim_type", + ], + )?; + for index in 0..3 { + insert_result_mapping(&mut value_map, op, operation, index, index)?; + } + } + "poly.point_slice" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["source", "offset", "length"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.point_slice", + Some(&symbol), + &attrs, + &operands, + &["!compute.point"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "poly.point_concat" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["layout", "arity"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.point_concat", + Some(&symbol), + &attrs, + &operands, + &["!compute.point"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "piop.sumcheck_claim" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs( + op, + &[ + "stage", + "domain", + "num_rounds", + "degree", + "claim", + "relation", + ], + )?; + let target_op = match &role { + Role::Prover => "compute.sumcheck_claim", + Role::Verifier => "compute.sumcheck_verify_claim", + }; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + target_op, + Some(&symbol), + &attrs, + &operands, + &["!compute.sumcheck_claim_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "piop.sumcheck_batch" => { + let operands = lowered_operands(op, &value_map, 1)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs( + op, + &[ + "stage", + "proof_slot", + "policy", + "count", + "ordered_claims", + "claim_label", + "round_label", + "round_schedule", + ], + )?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.sumcheck_batch", + Some(&symbol), + &attrs, + &operands, + &["!compute.sumcheck_batch_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "piop.sumcheck" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs( + op, + &[ + "stage", + "proof_slot", + "relation", + "policy", + "round_schedule", + "claim_label", + "round_label", + "num_rounds", + "degree", + ], + )?; + let target_op = match &role { + Role::Prover => "compute.sumcheck_driver", + Role::Verifier => "compute.sumcheck_verify", + }; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + target_op, + Some(&symbol), + &attrs, + &operands, + &[ + "!compute.transcript_state", + "!compute.point", + "!compute.sumcheck_result_type", + "!compute.sumcheck_proof_type", + ], + )?; + for index in 0..4 { + insert_result_mapping(&mut value_map, op, operation, index, index)?; + } + } + "piop.sumcheck_eval" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["source", "name", "index", "oracle"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.sumcheck_eval", + Some(&symbol), + &attrs, + &operands, + &["!compute.field_value"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "piop.sumcheck_instance_result" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs( + op, + &[ + "source", + "claim", + "relation", + "index", + "point_arity", + "num_rounds", + "round_offset", + "point_order", + "degree", + ], + )?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.sumcheck_instance_result", + Some(&symbol), + &attrs, + &operands, + &["!compute.point", "!compute.sumcheck_result_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + insert_result_mapping(&mut value_map, op, operation, 1, 1)?; + } + "piop.opening_claim" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["oracle", "domain", "point_arity", "claim_kind"])?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.opening_claim", + Some(&symbol), + &attrs, + &operands, + &["!compute.opening_claim_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + "piop.opening_claim_equal" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs(op, &["mode"])?; + let _operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.opening_claim_equal", + Some(&symbol), + &attrs, + &operands, + &[], + )?; + } + "piop.opening_batch" => { + let operands = lowered_operands(op, &value_map, 0)?; + let symbol = string_attr(op, "sym_name")?; + let attrs = copy_attrs( + op, + &["stage", "proof_slot", "policy", "count", "ordered_claims"], + )?; + let operation = context.append_typed_op_with_owned_attrs( + &compute, + "compute.opening_batch", + Some(&symbol), + &attrs, + &operands, + &["!compute.opening_batch_type"], + )?; + insert_result_mapping(&mut value_map, op, operation, 0, 0)?; + } + _ => {} + } + } + + verify_module(&compute)?; + verify_compute_schema(&compute)?; + Ok(compute) +} + +fn append_stage3_oracles<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, +) -> Result<(), MlirError> { + let mut trace_oracles = BTreeSet::new(); + trace_oracles.extend(STAGE3_SHIFT_INPUTS); + trace_oracles.extend(STAGE3_SHIFT_OUTPUTS); + trace_oracles.extend(STAGE3_INSTRUCTION_INPUT_OUTPUTS); + trace_oracles.extend(STAGE3_REGISTER_INPUTS); + trace_oracles.extend([ + "LeftInstructionInput", + "RightInstructionInput", + "NextIsNoop", + ]); + for oracle in trace_oracles { + append_virtual_oracle(context, module, oracle, "jolt.trace_domain")?; + } + Ok(()) +} + +fn append_virtual_oracle<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + symbol: &str, + domain: &str, +) -> Result<(), MlirError> { + context.append_op( + module, + "piop.oracle", + Some(symbol), + &[ + ("field", "@bn254_fr"), + ("domain", &format!("@{domain}")), + ("commit_domain", &format!("@{domain}")), + ("visibility", r#""virtual""#), + ("layout", r#""virtual""#), + ], + ) +} + +fn append_stage3_relations<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + params: &JoltProtocolParams, +) -> Result<(), MlirError> { + append_relation( + context, + module, + RelationSpec { + symbol: "jolt.stage3.spartan_shift", + kind: "sumcheck", + domain: "jolt.trace_domain", + num_rounds: params.log_t, + degree: SPARTAN_SHIFT_DEGREE, + output_count: STAGE3_SHIFT_OUTPUTS.len(), + }, + )?; + append_relation( + context, + module, + RelationSpec { + symbol: "jolt.stage3.instruction_input", + kind: "sumcheck", + domain: "jolt.trace_domain", + num_rounds: params.log_t, + degree: INSTRUCTION_INPUT_DEGREE, + output_count: STAGE3_INSTRUCTION_INPUT_OUTPUTS.len(), + }, + )?; + append_relation( + context, + module, + RelationSpec { + symbol: "jolt.stage3.registers_claim_reduction", + kind: "sumcheck", + domain: "jolt.trace_domain", + num_rounds: params.log_t, + degree: REGISTERS_CLAIM_REDUCTION_DEGREE, + output_count: STAGE3_REGISTER_INPUTS.len(), + }, + )?; + append_relation( + context, + module, + RelationSpec { + symbol: "jolt.stage3.batched", + kind: "batched_sumcheck", + domain: "jolt.trace_domain", + num_rounds: params.log_t, + degree: STAGE3_BATCHED_DEGREE, + output_count: stage3_output_count(), + }, + ) +} + +fn append_relation<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + spec: RelationSpec<'_>, +) -> Result<(), MlirError> { + context.append_op( + module, + "piop.relation", + Some(spec.symbol), + &[ + ("kind", &format!("\"{}\"", spec.kind)), + ("domain", &format!("@{}", spec.domain)), + ("num_rounds", &int_attr(spec.num_rounds)), + ("degree", &int_attr(spec.degree)), + ("output_count", &int_attr(spec.output_count)), + ], + ) +} + +fn append_stage3_opening_inputs<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + params: &JoltProtocolParams, +) -> Result, MlirError> { + Ok(Stage3OpeningInputs { + next_unexpanded_pc: append_stage_input( + context, + module, + params, + StageOpeningInputSpec { + symbol: "stage3.input.stage1.NextUnexpandedPC", + source_stage: "stage1", + source_claim: "stage1.outer_remaining.opening.NextUnexpandedPC", + oracle: "NextUnexpandedPC", + }, + )?, + next_pc: append_stage_input( + context, + module, + params, + StageOpeningInputSpec { + symbol: "stage3.input.stage1.NextPC", + source_stage: "stage1", + source_claim: "stage1.outer_remaining.opening.NextPC", + oracle: "NextPC", + }, + )?, + next_is_virtual: append_stage_input( + context, + module, + params, + StageOpeningInputSpec { + symbol: "stage3.input.stage1.NextIsVirtual", + source_stage: "stage1", + source_claim: "stage1.outer_remaining.opening.NextIsVirtual", + oracle: "NextIsVirtual", + }, + )?, + next_is_first_in_sequence: append_stage_input( + context, + module, + params, + StageOpeningInputSpec { + symbol: "stage3.input.stage1.NextIsFirstInSequence", + source_stage: "stage1", + source_claim: "stage1.outer_remaining.opening.NextIsFirstInSequence", + oracle: "NextIsFirstInSequence", + }, + )?, + product_next_is_noop: append_stage_input( + context, + module, + params, + StageOpeningInputSpec { + symbol: "stage3.input.stage2.product_virtual.NextIsNoop", + source_stage: "stage2", + source_claim: "stage2.product_virtual.remainder.opening.NextIsNoop", + oracle: "NextIsNoop", + }, + )?, + product_left_instruction_input: append_stage_input( + context, + module, + params, + StageOpeningInputSpec { + symbol: "stage3.input.stage2.product_virtual.LeftInstructionInput", + source_stage: "stage2", + source_claim: "stage2.product_virtual.remainder.opening.LeftInstructionInput", + oracle: "LeftInstructionInput", + }, + )?, + product_right_instruction_input: append_stage_input( + context, + module, + params, + StageOpeningInputSpec { + symbol: "stage3.input.stage2.product_virtual.RightInstructionInput", + source_stage: "stage2", + source_claim: "stage2.product_virtual.remainder.opening.RightInstructionInput", + oracle: "RightInstructionInput", + }, + )?, + instruction_left_instruction_input: append_stage_input( + context, + module, + params, + StageOpeningInputSpec { + symbol: "stage3.input.stage2.instruction_lookup.LeftInstructionInput", + source_stage: "stage2", + source_claim: + "stage2.instruction_lookup.claim_reduction.opening.LeftInstructionInput", + oracle: "LeftInstructionInput", + }, + )?, + instruction_right_instruction_input: append_stage_input( + context, + module, + params, + StageOpeningInputSpec { + symbol: "stage3.input.stage2.instruction_lookup.RightInstructionInput", + source_stage: "stage2", + source_claim: + "stage2.instruction_lookup.claim_reduction.opening.RightInstructionInput", + oracle: "RightInstructionInput", + }, + )?, + rd_write_value: append_stage_input( + context, + module, + params, + StageOpeningInputSpec { + symbol: "stage3.input.stage1.RdWriteValue", + source_stage: "stage1", + source_claim: "stage1.outer_remaining.opening.RdWriteValue", + oracle: "RdWriteValue", + }, + )?, + rs1_value: append_stage_input( + context, + module, + params, + StageOpeningInputSpec { + symbol: "stage3.input.stage1.Rs1Value", + source_stage: "stage1", + source_claim: "stage1.outer_remaining.opening.Rs1Value", + oracle: "Rs1Value", + }, + )?, + rs2_value: append_stage_input( + context, + module, + params, + StageOpeningInputSpec { + symbol: "stage3.input.stage1.Rs2Value", + source_stage: "stage1", + source_claim: "stage1.outer_remaining.opening.Rs2Value", + oracle: "Rs2Value", + }, + )?, + }) +} + +fn append_stage_input<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + params: &JoltProtocolParams, + spec: StageOpeningInputSpec<'_>, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "piop.opening_input", + Some(spec.symbol), + &[ + ("source_stage", &format!("@{}", spec.source_stage)), + ("source_claim", &format!("@{}", spec.source_claim)), + ("oracle", &format!("@{}", spec.oracle)), + ("domain", "@jolt.trace_domain"), + ("point_arity", &int_attr(params.log_t)), + ("claim_kind", r#""virtual""#), + ], + &[], + &["!poly.point", "!field.scalar", "!piop.opening_claim_type"], + )?; + Ok(Stage3OpeningInput { + eval: result(op, 1, "piop.opening_input")?, + claim: result(op, 2, "piop.opening_input")?, + }) +} + +fn append_transcript_squeeze<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + state: Value<'c, 'a>, + symbol: &str, + label: &str, + kind: &str, + count: usize, +) -> Result<(Value<'c, 'a>, Value<'c, 'a>), MlirError> { + let op = context.append_typed_op( + module, + "transcript.squeeze", + Some(symbol), + &[ + ("label", &format!("\"{label}\"")), + ("kind", &format!("\"{kind}\"")), + ("count", &int_attr(count)), + ], + &[state], + &[ + "!transcript.state_type", + transcript_squeeze_protocol_result_type(kind)?, + ], + )?; + Ok(( + result(op, 0, "transcript.squeeze")?, + result(op, 1, "transcript.squeeze")?, + )) +} + +fn append_field_one<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "field.one", + Some(symbol), + &[("field", "@bn254_fr")], + &[], + &["!field.scalar"], + )?; + first_result(op, "field.one") +} + +fn append_field_binary<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + op_name: &str, + symbol: &str, + lhs: Value<'c, 'a>, + rhs: Value<'c, 'a>, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + op_name, + Some(symbol), + &[], + &[lhs, rhs], + &["!field.scalar"], + )?; + first_result(op, op_name) +} + +fn append_field_add<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + lhs: Value<'c, 'a>, + rhs: Value<'c, 'a>, +) -> Result, MlirError> { + append_field_binary(context, module, "field.add", symbol, lhs, rhs) +} + +fn append_field_sub<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + lhs: Value<'c, 'a>, + rhs: Value<'c, 'a>, +) -> Result, MlirError> { + append_field_binary(context, module, "field.sub", symbol, lhs, rhs) +} + +fn append_field_mul<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + lhs: Value<'c, 'a>, + rhs: Value<'c, 'a>, +) -> Result, MlirError> { + append_field_binary(context, module, "field.mul", symbol, lhs, rhs) +} + +fn append_field_pow<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + base: Value<'c, 'a>, + exponent: usize, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "field.pow", + Some(symbol), + &[("exponent", &int_attr(exponent))], + &[base], + &["!field.scalar"], + )?; + first_result(op, "field.pow") +} + +fn append_opening_claim_equal<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + symbol: &str, + left: Value<'c, '_>, + right: Value<'c, '_>, +) -> Result<(), MlirError> { + let _operation = context.append_typed_op( + module, + "piop.opening_claim_equal", + Some(symbol), + &[("mode", r#""point_and_eval""#)], + &[left, right], + &[], + )?; + Ok(()) +} + +fn append_stage3_batched_sumcheck<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + params: &JoltProtocolParams, + spec: Stage3BatchedSumcheckInputs<'c, 'a, '_>, +) -> Result, MlirError> { + let inputs = spec.openings; + let shift_gamma2 = append_field_pow( + context, + module, + "stage3.spartan_shift.gamma2", + spec.shift_gamma, + 2, + )?; + let shift_gamma3 = append_field_mul( + context, + module, + "stage3.spartan_shift.gamma3", + shift_gamma2, + spec.shift_gamma, + )?; + let shift_gamma4 = append_field_mul( + context, + module, + "stage3.spartan_shift.gamma4", + shift_gamma2, + shift_gamma2, + )?; + let one = append_field_one(context, module, "stage3.field.one")?; + let next_pc_term = append_field_mul( + context, + module, + "stage3.spartan_shift.term.NextPC", + spec.shift_gamma, + inputs.next_pc.eval, + )?; + let next_virtual_term = append_field_mul( + context, + module, + "stage3.spartan_shift.term.NextIsVirtual", + shift_gamma2, + inputs.next_is_virtual.eval, + )?; + let next_first_term = append_field_mul( + context, + module, + "stage3.spartan_shift.term.NextIsFirstInSequence", + shift_gamma3, + inputs.next_is_first_in_sequence.eval, + )?; + let one_minus_noop = append_field_sub( + context, + module, + "stage3.spartan_shift.one_minus.NextIsNoop", + one, + inputs.product_next_is_noop.eval, + )?; + let next_noop_term = append_field_mul( + context, + module, + "stage3.spartan_shift.term.NextIsNoop", + shift_gamma4, + one_minus_noop, + )?; + let shift_sum0 = append_field_add( + context, + module, + "stage3.spartan_shift.partial.NextUnexpandedPCNextPC", + inputs.next_unexpanded_pc.eval, + next_pc_term, + )?; + let shift_sum1 = append_field_add( + context, + module, + "stage3.spartan_shift.partial.NextIsVirtual", + shift_sum0, + next_virtual_term, + )?; + let shift_sum2 = append_field_add( + context, + module, + "stage3.spartan_shift.partial.NextIsFirstInSequence", + shift_sum1, + next_first_term, + )?; + let shift_claim = append_field_add( + context, + module, + "stage3.spartan_shift.claim_expr", + shift_sum2, + next_noop_term, + )?; + append_opening_claim_equal( + context, + module, + "stage3.instruction_input.left_claim_consistency", + inputs.product_left_instruction_input.claim, + inputs.instruction_left_instruction_input.claim, + )?; + append_opening_claim_equal( + context, + module, + "stage3.instruction_input.right_claim_consistency", + inputs.product_right_instruction_input.claim, + inputs.instruction_right_instruction_input.claim, + )?; + let instruction_left_term = append_field_mul( + context, + module, + "stage3.instruction_input.term.LeftInstructionInput", + spec.instruction_gamma, + inputs.product_left_instruction_input.eval, + )?; + let instruction_claim = append_field_add( + context, + module, + "stage3.instruction_input.claim_expr", + inputs.product_right_instruction_input.eval, + instruction_left_term, + )?; + let registers_gamma2 = append_field_pow( + context, + module, + "stage3.registers.gamma2", + spec.registers_gamma, + 2, + )?; + let rs1_term = append_field_mul( + context, + module, + "stage3.registers.term.Rs1Value", + spec.registers_gamma, + inputs.rs1_value.eval, + )?; + let rs2_term = append_field_mul( + context, + module, + "stage3.registers.term.Rs2Value", + registers_gamma2, + inputs.rs2_value.eval, + )?; + let registers_sum = append_field_add( + context, + module, + "stage3.registers.partial.RdWriteValueRs1Value", + inputs.rd_write_value.eval, + rs1_term, + )?; + let registers_claim = append_field_add( + context, + module, + "stage3.registers.claim_expr", + registers_sum, + rs2_term, + )?; + + let claims = [ + append_sumcheck_claim( + context, + module, + SumcheckClaimSpec { + symbol: "stage3.spartan_shift.input", + stage: "stage3", + domain: "jolt.trace_domain", + num_rounds: params.log_t, + degree: SPARTAN_SHIFT_DEGREE, + claim: "stage3.spartan_shift.weighted_next_values", + relation: "jolt.stage3.spartan_shift", + }, + shift_claim, + &[ + inputs.next_unexpanded_pc.claim, + inputs.next_pc.claim, + inputs.next_is_virtual.claim, + inputs.next_is_first_in_sequence.claim, + inputs.product_next_is_noop.claim, + ], + )?, + append_sumcheck_claim( + context, + module, + SumcheckClaimSpec { + symbol: "stage3.instruction_input.input", + stage: "stage3", + domain: "jolt.trace_domain", + num_rounds: params.log_t, + degree: INSTRUCTION_INPUT_DEGREE, + claim: "stage3.instruction_input.weighted_inputs", + relation: "jolt.stage3.instruction_input", + }, + instruction_claim, + &[ + inputs.product_right_instruction_input.claim, + inputs.product_left_instruction_input.claim, + ], + )?, + append_sumcheck_claim( + context, + module, + SumcheckClaimSpec { + symbol: "stage3.registers_claim_reduction.input", + stage: "stage3", + domain: "jolt.trace_domain", + num_rounds: params.log_t, + degree: REGISTERS_CLAIM_REDUCTION_DEGREE, + claim: "stage3.registers.weighted_register_values", + relation: "jolt.stage3.registers_claim_reduction", + }, + registers_claim, + &[ + inputs.rd_write_value.claim, + inputs.rs1_value.claim, + inputs.rs2_value.claim, + ], + )?, + ]; + let batch = append_sumcheck_batch( + context, + module, + spec.stage, + &claims, + SumcheckBatchSpec { + symbol: "stage3.batch", + stage: "stage3", + proof_slot: "stage3.sumcheck", + policy: "jolt_core_stage3_aligned", + ordered_claims: &[ + "stage3.spartan_shift.input", + "stage3.instruction_input.input", + "stage3.registers_claim_reduction.input", + ], + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + round_schedule: format!("[{}]", params.log_t), + }, + )?; + let (state, point, result_value) = append_sumcheck( + context, + module, + spec.state, + batch, + SumcheckDriverSpec { + symbol: "stage3.sumcheck", + stage: "stage3", + proof_slot: "stage3.sumcheck", + relation: "jolt.stage3.batched", + policy: "jolt_core_stage3_aligned", + round_schedule: format!("[{}]", params.log_t), + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + num_rounds: params.log_t, + degree: STAGE3_BATCHED_DEGREE, + }, + )?; + + let shift = append_sumcheck_instance_result( + context, + module, + SumcheckInstanceResultSpec { + symbol: "stage3.spartan_shift.instance", + source: "stage3.sumcheck", + claim: "stage3.spartan_shift.input", + relation: "jolt.stage3.spartan_shift", + index: 0, + point_arity: params.log_t, + num_rounds: params.log_t, + round_offset: 0, + point_order: "reverse", + degree: SPARTAN_SHIFT_DEGREE, + }, + point, + result_value, + )?; + let instruction = append_sumcheck_instance_result( + context, + module, + SumcheckInstanceResultSpec { + symbol: "stage3.instruction_input.instance", + source: "stage3.sumcheck", + claim: "stage3.instruction_input.input", + relation: "jolt.stage3.instruction_input", + index: 1, + point_arity: params.log_t, + num_rounds: params.log_t, + round_offset: 0, + point_order: "reverse", + degree: INSTRUCTION_INPUT_DEGREE, + }, + point, + result_value, + )?; + let registers = append_sumcheck_instance_result( + context, + module, + SumcheckInstanceResultSpec { + symbol: "stage3.registers_claim_reduction.instance", + source: "stage3.sumcheck", + claim: "stage3.registers_claim_reduction.input", + relation: "jolt.stage3.registers_claim_reduction", + index: 2, + point_arity: params.log_t, + num_rounds: params.log_t, + round_offset: 0, + point_order: "reverse", + degree: REGISTERS_CLAIM_REDUCTION_DEGREE, + }, + point, + result_value, + )?; + append_stage3_output_openings( + context, + module, + &[ + InstanceOutput { + prefix: "stage3.spartan_shift", + instance: shift, + outputs: &STAGE3_SHIFT_OUTPUTS, + degree_offset: 0, + }, + InstanceOutput { + prefix: "stage3.instruction_input", + instance: instruction, + outputs: &STAGE3_INSTRUCTION_INPUT_OUTPUTS, + degree_offset: STAGE3_SHIFT_OUTPUTS.len(), + }, + InstanceOutput { + prefix: "stage3.registers_claim_reduction", + instance: registers, + outputs: &STAGE3_REGISTER_INPUTS, + degree_offset: STAGE3_SHIFT_OUTPUTS.len() + STAGE3_INSTRUCTION_INPUT_OUTPUTS.len(), + }, + ], + params.log_t, + )?; + Ok(state) +} + +fn append_stage3_output_openings<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + outputs: &[InstanceOutput<'c, 'a, '_>], + point_arity: usize, +) -> Result<(), MlirError> { + let mut claims = Vec::new(); + let mut claim_symbols = Vec::new(); + + for output in outputs { + for (index, &oracle) in output.outputs.iter().enumerate() { + let symbol = format!("{}.opening.{oracle}", output.prefix); + let eval = append_sumcheck_eval( + context, + module, + &format!("{}.eval.{oracle}", output.prefix), + "stage3.sumcheck", + oracle, + output.degree_offset + index, + output.instance.1, + )?; + claim_symbols.push(symbol.clone()); + claims.push(append_opening_claim( + context, + module, + output.instance.0, + eval, + OpeningClaimSpec { + symbol: &symbol, + oracle, + domain: "jolt.trace_domain", + point_arity, + claim_kind: "virtual", + }, + )?); + } + } + + let claim_names = claim_symbols.iter().map(String::as_str).collect::>(); + let _batch = context.append_typed_op( + module, + "piop.opening_batch", + Some("stage3.openings"), + &[ + ("stage", "@stage3"), + ("proof_slot", "@stage3.openings"), + ("policy", r#""jolt_stage3_output_order""#), + ("count", &int_attr(claims.len())), + ("ordered_claims", &symbol_array_attr(&claim_names)), + ], + &claims, + &["!piop.opening_batch_type"], + )?; + Ok(()) +} + +fn append_sumcheck_claim<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + spec: SumcheckClaimSpec<'_>, + input_claim: Value<'c, 'a>, + inputs: &[Value<'c, 'a>], +) -> Result, MlirError> { + let mut operands = Vec::with_capacity(inputs.len() + 1); + operands.push(input_claim); + operands.extend_from_slice(inputs); + let op = context.append_typed_op( + module, + "piop.sumcheck_claim", + Some(spec.symbol), + &[ + ("stage", &format!("@{}", spec.stage)), + ("domain", &format!("@{}", spec.domain)), + ("num_rounds", &int_attr(spec.num_rounds)), + ("degree", &int_attr(spec.degree)), + ("claim", &format!("@{}", spec.claim)), + ("relation", &format!("@{}", spec.relation)), + ], + &operands, + &["!piop.sumcheck_claim_type"], + )?; + first_result(op, "piop.sumcheck_claim") +} + +fn append_sumcheck_batch<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + stage: Value<'c, 'a>, + claims: &[Value<'c, 'a>], + spec: SumcheckBatchSpec<'_>, +) -> Result, MlirError> { + let mut operands = Vec::with_capacity(claims.len() + 1); + operands.push(stage); + operands.extend_from_slice(claims); + let op = context.append_typed_op( + module, + "piop.sumcheck_batch", + Some(spec.symbol), + &[ + ("stage", &format!("@{}", spec.stage)), + ("proof_slot", &format!("@{}", spec.proof_slot)), + ("policy", &format!("\"{}\"", spec.policy)), + ("count", &int_attr(spec.ordered_claims.len())), + ("ordered_claims", &symbol_array_attr(spec.ordered_claims)), + ("claim_label", &format!("\"{}\"", spec.claim_label)), + ("round_label", &format!("\"{}\"", spec.round_label)), + ("round_schedule", &spec.round_schedule), + ], + &operands, + &["!piop.sumcheck_batch_type"], + )?; + first_result(op, "piop.sumcheck_batch") +} + +fn append_sumcheck<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + state: Value<'c, 'a>, + batch: Value<'c, 'a>, + spec: SumcheckDriverSpec<'_>, +) -> Result<(Value<'c, 'a>, Value<'c, 'a>, Value<'c, 'a>), MlirError> { + let op = context.append_typed_op( + module, + "piop.sumcheck", + Some(spec.symbol), + &[ + ("stage", &format!("@{}", spec.stage)), + ("proof_slot", &format!("@{}", spec.proof_slot)), + ("relation", &format!("@{}", spec.relation)), + ("policy", &format!("\"{}\"", spec.policy)), + ("round_schedule", &spec.round_schedule), + ("claim_label", &format!("\"{}\"", spec.claim_label)), + ("round_label", &format!("\"{}\"", spec.round_label)), + ("num_rounds", &int_attr(spec.num_rounds)), + ("degree", &int_attr(spec.degree)), + ], + &[state, batch], + &[ + "!transcript.state_type", + "!poly.point", + "!piop.sumcheck_result_type", + "!piop.sumcheck_proof_type", + ], + )?; + Ok(( + result(op, 0, "piop.sumcheck")?, + result(op, 1, "piop.sumcheck")?, + result(op, 2, "piop.sumcheck")?, + )) +} + +fn append_sumcheck_instance_result<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + spec: SumcheckInstanceResultSpec<'_>, + point: Value<'c, 'a>, + result_value: Value<'c, 'a>, +) -> Result<(Value<'c, 'a>, Value<'c, 'a>), MlirError> { + let op = context.append_typed_op( + module, + "piop.sumcheck_instance_result", + Some(spec.symbol), + &[ + ("source", &format!("@{}", spec.source)), + ("claim", &format!("@{}", spec.claim)), + ("relation", &format!("@{}", spec.relation)), + ("index", &int_attr(spec.index)), + ("point_arity", &int_attr(spec.point_arity)), + ("num_rounds", &int_attr(spec.num_rounds)), + ("round_offset", &int_attr(spec.round_offset)), + ("point_order", &format!("\"{}\"", spec.point_order)), + ("degree", &int_attr(spec.degree)), + ], + &[point, result_value], + &["!poly.point", "!piop.sumcheck_result_type"], + )?; + Ok(( + result(op, 0, "piop.sumcheck_instance_result")?, + result(op, 1, "piop.sumcheck_instance_result")?, + )) +} + +fn append_sumcheck_eval<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + source: &str, + oracle: &str, + index: usize, + result_value: Value<'c, 'a>, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "piop.sumcheck_eval", + Some(symbol), + &[ + ("source", &format!("@{source}")), + ("name", &format!("@{symbol}")), + ("index", &int_attr(index)), + ("oracle", &format!("@{oracle}")), + ], + &[result_value], + &["!field.scalar"], + )?; + first_result(op, "piop.sumcheck_eval") +} + +fn append_opening_claim<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + point: Value<'c, 'a>, + eval: Value<'c, 'a>, + spec: OpeningClaimSpec<'_>, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "piop.opening_claim", + Some(spec.symbol), + &[ + ("oracle", &format!("@{}", spec.oracle)), + ("domain", &format!("@{}", spec.domain)), + ("point_arity", &int_attr(spec.point_arity)), + ("claim_kind", &format!("\"{}\"", spec.claim_kind)), + ], + &[point, eval], + &["!piop.opening_claim_type"], + )?; + first_result(op, "piop.opening_claim") +} + +fn first_result<'c, 'a>( + operation: OperationRef<'c, 'a>, + operation_name: &str, +) -> Result, MlirError> { + result(operation, 0, operation_name) +} + +fn result<'c, 'a>( + operation: OperationRef<'c, 'a>, + index: usize, + operation_name: &str, +) -> Result, MlirError> { + operation + .result(index) + .map(Into::into) + .map_err(|_| schema_error(format!("{operation_name} requires result {index}"))) +} + +#[derive(Clone, Debug)] +struct StageParamsAst { + field: String, + pcs: String, + transcript: String, +} + +fn stage_params(module: &BoltModule<'_, Party>) -> Result { + let mut operation = module.as_mlir_module().body().first_operation(); + while let Some(op) = operation { + operation = op.next_in_block(); + if operation_name(op) == "protocol.params" { + return Ok(StageParamsAst { + field: symbol_attr(op, "field")?, + pcs: symbol_attr(op, "pcs")?, + transcript: symbol_attr(op, "transcript")?, + }); + } + } + Err(schema_error("stage3 lowering requires protocol.params")) +} + +fn operation_result_key_at( + operation: OperationRef<'_, '_>, + index: usize, +) -> Result { + let result = operation.result(index).map_err(|_| { + schema_error(format!( + "{} requires result {index}", + operation_name(operation) + )) + })?; + result_key(result.owner(), result.result_number()) +} + +fn result_key(operation: OperationRef<'_, '_>, result_number: usize) -> Result { + Ok(format!( + "{}#{result_number}", + string_attr(operation, "sym_name")? + )) +} + +fn operand_key(operation: OperationRef<'_, '_>, index: usize) -> Result { + let operand = operation.operand(index).map_err(|_| { + schema_error(format!( + "{} requires operand {index}", + operation_name(operation) + )) + })?; + let owner = OperationResult::try_from(operand).map_err(|_| { + schema_error(format!( + "{} operand {index} must be an op result", + operation_name(operation) + )) + })?; + result_key(owner.owner(), owner.result_number()).map_err(|_| { + schema_error(format!( + "{} operand {index} owner missing sym_name", + operation_name(operation) + )) + }) +} + +fn lowered_operands<'c, 'a>( + operation: OperationRef<'_, '_>, + value_map: &BTreeMap>, + start_index: usize, +) -> Result>, MlirError> { + (start_index..operation.operand_count()) + .map(|index| { + let key = operand_key(operation, index)?; + value_map.get(&key).copied().ok_or_else(|| { + schema_error(format!( + "{} operand {index} was not lowered", + operation_name(operation) + )) + }) + }) + .collect() +} + +fn insert_result_mapping<'c, 'a>( + value_map: &mut BTreeMap>, + source: OperationRef<'_, '_>, + target: OperationRef<'c, 'a>, + source_index: usize, + target_index: usize, +) -> Result<(), MlirError> { + let key = operation_result_key_at(source, source_index)?; + let value = target.result(target_index).map(Into::into).map_err(|_| { + schema_error(format!( + "{} requires result {target_index}", + operation_name(target) + )) + })?; + let inserted = value_map.insert(key, value); + debug_assert!(inserted.is_none()); + Ok(()) +} + +fn symbol_ref(symbol: &str) -> String { + format!("@{symbol}") +} + +fn stage3_output_count() -> usize { + STAGE3_SHIFT_OUTPUTS.len() + + STAGE3_INSTRUCTION_INPUT_OUTPUTS.len() + + STAGE3_REGISTER_INPUTS.len() +} + +fn int_attr(value: usize) -> String { + format!("{value} : i64") +} + +fn symbol_array_attr(values: &[&str]) -> String { + let values = values + .iter() + .map(|value| format!("@{value}")) + .collect::>() + .join(", "); + format!("[{values}]") +} + +fn schema_error(message: impl Into) -> MlirError { + SchemaError::new(message).into() +} + +#[derive(Clone, Copy)] +struct Stage3OpeningInput<'c, 'a> { + eval: Value<'c, 'a>, + claim: Value<'c, 'a>, +} + +struct Stage3OpeningInputs<'c, 'a> { + next_unexpanded_pc: Stage3OpeningInput<'c, 'a>, + next_pc: Stage3OpeningInput<'c, 'a>, + next_is_virtual: Stage3OpeningInput<'c, 'a>, + next_is_first_in_sequence: Stage3OpeningInput<'c, 'a>, + product_next_is_noop: Stage3OpeningInput<'c, 'a>, + product_left_instruction_input: Stage3OpeningInput<'c, 'a>, + product_right_instruction_input: Stage3OpeningInput<'c, 'a>, + instruction_left_instruction_input: Stage3OpeningInput<'c, 'a>, + instruction_right_instruction_input: Stage3OpeningInput<'c, 'a>, + rd_write_value: Stage3OpeningInput<'c, 'a>, + rs1_value: Stage3OpeningInput<'c, 'a>, + rs2_value: Stage3OpeningInput<'c, 'a>, +} + +struct StageOpeningInputSpec<'a> { + symbol: &'a str, + source_stage: &'a str, + source_claim: &'a str, + oracle: &'a str, +} + +struct Stage3BatchedSumcheckInputs<'c, 'a, 'b> { + state: Value<'c, 'a>, + stage: Value<'c, 'a>, + openings: &'b Stage3OpeningInputs<'c, 'a>, + shift_gamma: Value<'c, 'a>, + instruction_gamma: Value<'c, 'a>, + registers_gamma: Value<'c, 'a>, +} + +struct RelationSpec<'a> { + symbol: &'a str, + kind: &'a str, + domain: &'a str, + num_rounds: usize, + degree: usize, + output_count: usize, +} + +struct SumcheckClaimSpec<'a> { + symbol: &'a str, + stage: &'a str, + domain: &'a str, + num_rounds: usize, + degree: usize, + claim: &'a str, + relation: &'a str, +} + +struct SumcheckBatchSpec<'a> { + symbol: &'a str, + stage: &'a str, + proof_slot: &'a str, + policy: &'a str, + ordered_claims: &'a [&'a str], + claim_label: &'a str, + round_label: &'a str, + round_schedule: String, +} + +struct SumcheckDriverSpec<'a> { + symbol: &'a str, + stage: &'a str, + proof_slot: &'a str, + relation: &'a str, + policy: &'a str, + round_schedule: String, + claim_label: &'a str, + round_label: &'a str, + num_rounds: usize, + degree: usize, +} + +struct SumcheckInstanceResultSpec<'a> { + symbol: &'a str, + source: &'a str, + claim: &'a str, + relation: &'a str, + index: usize, + point_arity: usize, + num_rounds: usize, + round_offset: usize, + point_order: &'a str, + degree: usize, +} + +struct OpeningClaimSpec<'a> { + symbol: &'a str, + oracle: &'a str, + domain: &'a str, + point_arity: usize, + claim_kind: &'a str, +} + +struct InstanceOutput<'c, 'a, 'b> { + prefix: &'b str, + instance: (Value<'c, 'a>, Value<'c, 'a>), + outputs: &'b [&'b str], + degree_offset: usize, +} diff --git a/crates/bolt/src/protocols/jolt/phases/stage4.rs b/crates/bolt/src/protocols/jolt/phases/stage4.rs new file mode 100644 index 0000000000..adf6bc080a --- /dev/null +++ b/crates/bolt/src/protocols/jolt/phases/stage4.rs @@ -0,0 +1,1264 @@ +use melior::ir::operation::OperationRef; +use melior::ir::Value; + +use crate::ir::{BoltModule, Compute, Party, Protocol}; +use crate::mlir::{verify_module, MeliorContext, MlirError}; +use crate::schema::{verify_protocol_schema, SchemaError}; + +use super::super::oracles; +use super::super::params::JoltProtocolParams; +use super::lowering::{lower_party_to_compute, transcript_squeeze_protocol_result_type}; + +const REGISTERS_RW_DEGREE: usize = 3; +const RAM_VAL_CHECK_DEGREE: usize = 3; +const STAGE4_BATCHED_DEGREE: usize = 3; + +const STAGE4_REGISTER_INPUTS: [&str; 3] = ["RdWriteValue", "Rs1Value", "Rs2Value"]; +const STAGE4_REGISTER_OUTPUTS: [&str; 5] = ["RegistersVal", "Rs1Ra", "Rs2Ra", "RdWa", "RdInc"]; +const STAGE4_RAM_VAL_OUTPUTS: [&str; 2] = ["RamRa", "RamInc"]; + +pub fn build_stage4_protocol<'c>( + context: &'c MeliorContext, + params: &JoltProtocolParams, +) -> Result, MlirError> { + let module = context.new_module::("jolt.stage4", None); + oracles::append_foundation_ops(context, &module, params)?; + context.append_op_with_owned_attrs( + &module, + "protocol.params", + Some("jolt.params"), + ¶ms.attrs(), + )?; + context.append_op( + &module, + "protocol.boundary", + Some("jolt.stage4"), + &[("roles", r#"["prover", "verifier"]"#)], + )?; + append_stage4_domains(context, &module, params)?; + append_stage4_oracles(context, &module)?; + append_stage4_relations(context, &module, params)?; + let inputs = append_stage4_opening_inputs(context, &module, params)?; + + let fs = context.append_typed_op( + &module, + "transcript.state", + Some("fs_after_stage3"), + &[("scheme", "@blake2b_transcript")], + &[], + &["!transcript.state_type"], + )?; + let state = first_result(fs, "transcript.state")?; + let stage = context.append_typed_op( + &module, + "piop.stage", + Some("stage4"), + &[ + ("name", r#""registers_rw_and_ram_val_check""#), + ("order", "4 : i64"), + ("roles", r#"["prover", "verifier"]"#), + ], + &[], + &["!piop.stage_type"], + )?; + let stage = first_result(stage, "piop.stage")?; + + let (state, registers_gamma) = append_transcript_squeeze( + context, + &module, + state, + "stage4.registers_read_write.gamma", + "registers_read_write_gamma", + "challenge_scalar", + 1, + )?; + let state = append_transcript_absorb_bytes( + context, + &module, + state, + "stage4.ram_val_check.domain_separator", + "ram_val_check_gamma", + "", + )?; + let (state, ram_val_check_gamma) = append_transcript_squeeze( + context, + &module, + state, + "stage4.ram_val_check.gamma", + "ram_val_check_gamma", + "challenge_scalar", + 1, + )?; + let _state = append_stage4_batched_sumcheck( + context, + &module, + params, + Stage4BatchedSumcheckInputs { + state, + stage, + openings: &inputs, + registers_gamma, + ram_val_check_gamma, + }, + )?; + + verify_module(&module)?; + verify_protocol_schema(&module)?; + Ok(module) +} + +pub fn lower_stage4_to_compute<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Party>, +) -> Result, MlirError> { + lower_party_to_compute(context, module, "jolt.stage4", "jolt.stage4", "stage4") +} + +fn append_stage4_domains<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + params: &JoltProtocolParams, +) -> Result<(), MlirError> { + context.append_op( + module, + "poly.domain", + Some("jolt.stage4_registers_rw_domain"), + &[ + ("field", "@bn254_fr"), + ("log_size", &int_attr(stage4_registers_rw_rounds(params))), + ], + )?; + context.append_op( + module, + "poly.domain", + Some("jolt.stage2_ram_rw_domain"), + &[ + ("field", "@bn254_fr"), + ("log_size", &int_attr(params.log_k_ram + params.log_t)), + ], + )?; + context.append_op( + module, + "poly.domain", + Some("jolt.ram_address_domain"), + &[ + ("field", "@bn254_fr"), + ("log_size", &int_attr(params.log_k_ram)), + ], + ) +} + +fn append_stage4_oracles<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, +) -> Result<(), MlirError> { + for oracle in STAGE4_REGISTER_INPUTS { + append_virtual_oracle(context, module, oracle, "jolt.trace_domain")?; + } + append_virtual_oracle( + context, + module, + "RegistersVal", + "jolt.stage4_registers_rw_domain", + )?; + append_virtual_oracle(context, module, "Rs1Ra", "jolt.stage4_registers_rw_domain")?; + append_virtual_oracle(context, module, "Rs2Ra", "jolt.stage4_registers_rw_domain")?; + append_virtual_oracle(context, module, "RdWa", "jolt.stage4_registers_rw_domain")?; + append_virtual_oracle(context, module, "RamVal", "jolt.stage2_ram_rw_domain")?; + append_virtual_oracle(context, module, "RamRa", "jolt.stage2_ram_rw_domain")?; + append_virtual_oracle(context, module, "RamValFinal", "jolt.ram_address_domain")?; + append_virtual_oracle(context, module, "RamValInit", "jolt.ram_address_domain")?; + append_committed_trace_oracle(context, module, "RdInc")?; + append_committed_trace_oracle(context, module, "RamInc") +} + +fn append_virtual_oracle<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + symbol: &str, + domain: &str, +) -> Result<(), MlirError> { + context.append_op( + module, + "piop.oracle", + Some(symbol), + &[ + ("field", "@bn254_fr"), + ("domain", &format!("@{domain}")), + ("commit_domain", &format!("@{domain}")), + ("visibility", r#""virtual""#), + ("layout", r#""virtual""#), + ], + ) +} + +fn append_committed_trace_oracle<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + symbol: &str, +) -> Result<(), MlirError> { + context.append_op( + module, + "piop.oracle", + Some(symbol), + &[ + ("field", "@bn254_fr"), + ("domain", "@jolt.trace_domain"), + ("commit_domain", "@jolt.main_witness_commit_domain"), + ("visibility", r#""committed""#), + ("layout", r#""dense_trace""#), + ], + ) +} + +fn append_stage4_relations<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + params: &JoltProtocolParams, +) -> Result<(), MlirError> { + append_relation( + context, + module, + RelationSpec { + symbol: "jolt.stage4.registers_read_write", + kind: "sumcheck", + domain: "jolt.stage4_registers_rw_domain", + num_rounds: stage4_registers_rw_rounds(params), + degree: REGISTERS_RW_DEGREE, + output_count: STAGE4_REGISTER_OUTPUTS.len(), + }, + )?; + append_relation( + context, + module, + RelationSpec { + symbol: "jolt.stage4.ram_val_check", + kind: "sumcheck", + domain: "jolt.trace_domain", + num_rounds: params.log_t, + degree: RAM_VAL_CHECK_DEGREE, + output_count: STAGE4_RAM_VAL_OUTPUTS.len(), + }, + )?; + append_relation( + context, + module, + RelationSpec { + symbol: "jolt.stage4.batched", + kind: "batched_sumcheck", + domain: "jolt.stage4_registers_rw_domain", + num_rounds: stage4_registers_rw_rounds(params), + degree: STAGE4_BATCHED_DEGREE, + output_count: stage4_output_count(), + }, + ) +} + +fn append_relation<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + spec: RelationSpec<'_>, +) -> Result<(), MlirError> { + context.append_op( + module, + "piop.relation", + Some(spec.symbol), + &[ + ("kind", &format!("\"{}\"", spec.kind)), + ("domain", &format!("@{}", spec.domain)), + ("num_rounds", &int_attr(spec.num_rounds)), + ("degree", &int_attr(spec.degree)), + ("output_count", &int_attr(spec.output_count)), + ], + ) +} + +fn append_stage4_opening_inputs<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + params: &JoltProtocolParams, +) -> Result, MlirError> { + Ok(Stage4OpeningInputs { + rd_write_value: append_stage_input( + context, + module, + StageOpeningInputSpec { + symbol: "stage4.input.stage3.registers.RdWriteValue", + source_stage: "stage3", + source_claim: "stage3.registers_claim_reduction.opening.RdWriteValue", + oracle: "RdWriteValue", + domain: "jolt.trace_domain", + point_arity: params.log_t, + }, + )?, + rs1_registers: append_stage_input( + context, + module, + StageOpeningInputSpec { + symbol: "stage4.input.stage3.registers.Rs1Value", + source_stage: "stage3", + source_claim: "stage3.registers_claim_reduction.opening.Rs1Value", + oracle: "Rs1Value", + domain: "jolt.trace_domain", + point_arity: params.log_t, + }, + )?, + rs2_registers: append_stage_input( + context, + module, + StageOpeningInputSpec { + symbol: "stage4.input.stage3.registers.Rs2Value", + source_stage: "stage3", + source_claim: "stage3.registers_claim_reduction.opening.Rs2Value", + oracle: "Rs2Value", + domain: "jolt.trace_domain", + point_arity: params.log_t, + }, + )?, + rs1_instruction: append_stage_input( + context, + module, + StageOpeningInputSpec { + symbol: "stage4.input.stage3.instruction.Rs1Value", + source_stage: "stage3", + source_claim: "stage3.instruction_input.opening.Rs1Value", + oracle: "Rs1Value", + domain: "jolt.trace_domain", + point_arity: params.log_t, + }, + )?, + rs2_instruction: append_stage_input( + context, + module, + StageOpeningInputSpec { + symbol: "stage4.input.stage3.instruction.Rs2Value", + source_stage: "stage3", + source_claim: "stage3.instruction_input.opening.Rs2Value", + oracle: "Rs2Value", + domain: "jolt.trace_domain", + point_arity: params.log_t, + }, + )?, + ram_val: append_stage_input( + context, + module, + StageOpeningInputSpec { + symbol: "stage4.input.stage2.RamVal", + source_stage: "stage2", + source_claim: "stage2.ram_read_write.opening.RamVal", + oracle: "RamVal", + domain: "jolt.stage2_ram_rw_domain", + point_arity: params.log_k_ram + params.log_t, + }, + )?, + ram_val_final: append_stage_input( + context, + module, + StageOpeningInputSpec { + symbol: "stage4.input.stage2.RamValFinal", + source_stage: "stage2", + source_claim: "stage2.ram_output.opening.RamValFinal", + oracle: "RamValFinal", + domain: "jolt.ram_address_domain", + point_arity: params.log_k_ram, + }, + )?, + ram_val_init: append_stage_input( + context, + module, + StageOpeningInputSpec { + symbol: "stage4.input.initial_ram.RamValInit", + source_stage: "stage4_precomputed", + source_claim: "stage4.ram_val_check.initial_ram_eval", + oracle: "RamValInit", + domain: "jolt.ram_address_domain", + point_arity: params.log_k_ram, + }, + )?, + }) +} + +fn append_stage_input<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + spec: StageOpeningInputSpec<'_>, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "piop.opening_input", + Some(spec.symbol), + &[ + ("source_stage", &format!("@{}", spec.source_stage)), + ("source_claim", &format!("@{}", spec.source_claim)), + ("oracle", &format!("@{}", spec.oracle)), + ("domain", &format!("@{}", spec.domain)), + ("point_arity", &int_attr(spec.point_arity)), + ("claim_kind", r#""virtual""#), + ], + &[], + &["!poly.point", "!field.scalar", "!piop.opening_claim_type"], + )?; + Ok(Stage4OpeningInput { + point: result(op, 0, "piop.opening_input")?, + eval: result(op, 1, "piop.opening_input")?, + claim: result(op, 2, "piop.opening_input")?, + }) +} + +fn append_transcript_squeeze<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + state: Value<'c, 'a>, + symbol: &str, + label: &str, + kind: &str, + count: usize, +) -> Result<(Value<'c, 'a>, Value<'c, 'a>), MlirError> { + let op = context.append_typed_op( + module, + "transcript.squeeze", + Some(symbol), + &[ + ("label", &format!("\"{label}\"")), + ("kind", &format!("\"{kind}\"")), + ("count", &int_attr(count)), + ], + &[state], + &[ + "!transcript.state_type", + transcript_squeeze_protocol_result_type(kind)?, + ], + )?; + Ok(( + result(op, 0, "transcript.squeeze")?, + result(op, 1, "transcript.squeeze")?, + )) +} + +fn append_transcript_absorb_bytes<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + state: Value<'c, 'a>, + symbol: &str, + label: &str, + payload: &str, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "transcript.absorb_bytes", + Some(symbol), + &[ + ("label", &format!("\"{label}\"")), + ("payload", &format!("\"{payload}\"")), + ], + &[state], + &["!transcript.state_type"], + )?; + first_result(op, "transcript.absorb_bytes") +} + +fn append_stage4_batched_sumcheck<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + params: &JoltProtocolParams, + spec: Stage4BatchedSumcheckInputs<'c, 'a, '_>, +) -> Result, MlirError> { + let inputs = spec.openings; + append_opening_claim_equal( + context, + module, + "stage4.registers.rs1_claim_consistency", + inputs.rs1_registers.claim, + inputs.rs1_instruction.claim, + )?; + append_opening_claim_equal( + context, + module, + "stage4.registers.rs2_claim_consistency", + inputs.rs2_registers.claim, + inputs.rs2_instruction.claim, + )?; + let registers_gamma2 = append_field_pow( + context, + module, + "stage4.registers_read_write.gamma2", + spec.registers_gamma, + 2, + )?; + let rs1_term = append_field_mul( + context, + module, + "stage4.registers_read_write.term.Rs1Value", + spec.registers_gamma, + inputs.rs1_registers.eval, + )?; + let rs2_term = append_field_mul( + context, + module, + "stage4.registers_read_write.term.Rs2Value", + registers_gamma2, + inputs.rs2_registers.eval, + )?; + let registers_sum = append_field_add( + context, + module, + "stage4.registers_read_write.partial.RdWriteValueRs1Value", + inputs.rd_write_value.eval, + rs1_term, + )?; + let registers_claim = append_field_add( + context, + module, + "stage4.registers_read_write.claim_expr", + registers_sum, + rs2_term, + )?; + + let ram_val_delta = append_field_sub( + context, + module, + "stage4.ram_val_check.delta.RamVal", + inputs.ram_val.eval, + inputs.ram_val_init.eval, + )?; + let ram_final_delta = append_field_sub( + context, + module, + "stage4.ram_val_check.delta.RamValFinal", + inputs.ram_val_final.eval, + inputs.ram_val_init.eval, + )?; + let ram_final_term = append_field_mul( + context, + module, + "stage4.ram_val_check.term.RamValFinal", + spec.ram_val_check_gamma, + ram_final_delta, + )?; + let ram_val_claim = append_field_add( + context, + module, + "stage4.ram_val_check.claim_expr", + ram_val_delta, + ram_final_term, + )?; + + let claims = [ + append_sumcheck_claim( + context, + module, + SumcheckClaimSpec { + symbol: "stage4.registers_read_write.input", + stage: "stage4", + domain: "jolt.stage4_registers_rw_domain", + num_rounds: stage4_registers_rw_rounds(params), + degree: REGISTERS_RW_DEGREE, + claim: "stage4.registers_read_write.weighted_values", + relation: "jolt.stage4.registers_read_write", + }, + registers_claim, + &[ + inputs.rd_write_value.claim, + inputs.rs1_registers.claim, + inputs.rs2_registers.claim, + ], + )?, + append_sumcheck_claim( + context, + module, + SumcheckClaimSpec { + symbol: "stage4.ram_val_check.input", + stage: "stage4", + domain: "jolt.trace_domain", + num_rounds: params.log_t, + degree: RAM_VAL_CHECK_DEGREE, + claim: "stage4.ram_val_check.weighted_values", + relation: "jolt.stage4.ram_val_check", + }, + ram_val_claim, + &[ + inputs.ram_val.claim, + inputs.ram_val_final.claim, + inputs.ram_val_init.claim, + ], + )?, + ]; + let batch = append_sumcheck_batch( + context, + module, + spec.stage, + &claims, + SumcheckBatchSpec { + symbol: "stage4.batch", + stage: "stage4", + proof_slot: "stage4.sumcheck", + policy: "jolt_core_stage4_aligned", + ordered_claims: &[ + "stage4.registers_read_write.input", + "stage4.ram_val_check.input", + ], + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + round_schedule: format!("[{}, {}]", params.log_t, params.register_log_k), + }, + )?; + let (state, point, result_value) = append_sumcheck( + context, + module, + spec.state, + batch, + SumcheckDriverSpec { + symbol: "stage4.sumcheck", + stage: "stage4", + proof_slot: "stage4.sumcheck", + relation: "jolt.stage4.batched", + policy: "jolt_core_stage4_aligned", + round_schedule: format!("[{}, {}]", params.log_t, params.register_log_k), + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + num_rounds: stage4_registers_rw_rounds(params), + degree: STAGE4_BATCHED_DEGREE, + }, + )?; + let registers = append_sumcheck_instance_result( + context, + module, + SumcheckInstanceResultSpec { + symbol: "stage4.registers_read_write.instance", + source: "stage4.sumcheck", + claim: "stage4.registers_read_write.input", + relation: "jolt.stage4.registers_read_write", + index: 0, + point_arity: stage4_registers_rw_rounds(params), + num_rounds: stage4_registers_rw_rounds(params), + round_offset: 0, + point_order: "stage4_registers_rw", + degree: REGISTERS_RW_DEGREE, + }, + point, + result_value, + )?; + let ram_val_check = append_sumcheck_instance_result( + context, + module, + SumcheckInstanceResultSpec { + symbol: "stage4.ram_val_check.instance", + source: "stage4.sumcheck", + claim: "stage4.ram_val_check.input", + relation: "jolt.stage4.ram_val_check", + index: 1, + point_arity: params.log_t, + num_rounds: params.log_t, + round_offset: params.register_log_k, + point_order: "reverse", + degree: RAM_VAL_CHECK_DEGREE, + }, + point, + result_value, + )?; + append_stage4_output_openings(context, module, params, inputs, registers, ram_val_check)?; + Ok(state) +} + +fn append_stage4_output_openings<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + params: &JoltProtocolParams, + inputs: &Stage4OpeningInputs<'c, 'a>, + registers: (Value<'c, 'a>, Value<'c, 'a>), + ram_val_check: (Value<'c, 'a>, Value<'c, 'a>), +) -> Result<(), MlirError> { + let mut claims = Vec::new(); + let mut claim_symbols = Vec::new(); + + for (index, &oracle) in ["RegistersVal", "Rs1Ra", "Rs2Ra", "RdWa"] + .iter() + .enumerate() + { + let symbol = format!("stage4.registers_read_write.opening.{oracle}"); + let eval = append_sumcheck_eval( + context, + module, + &format!("stage4.registers_read_write.eval.{oracle}"), + "stage4.sumcheck", + oracle, + index, + registers.1, + )?; + claim_symbols.push(symbol.clone()); + claims.push(append_opening_claim( + context, + module, + registers.0, + eval, + OpeningClaimSpec { + symbol: &symbol, + oracle, + domain: "jolt.stage4_registers_rw_domain", + point_arity: stage4_registers_rw_rounds(params), + claim_kind: "virtual", + }, + )?); + } + + let rd_inc_point = append_point_slice( + context, + module, + "stage4.registers_read_write.point.RdInc", + "stage4.registers_read_write.instance", + params.register_log_k, + params.log_t, + registers.0, + )?; + let rd_inc_eval = append_sumcheck_eval( + context, + module, + "stage4.registers_read_write.eval.RdInc", + "stage4.sumcheck", + "RdInc", + 4, + registers.1, + )?; + claim_symbols.push("stage4.registers_read_write.opening.RdInc".to_owned()); + claims.push(append_opening_claim( + context, + module, + rd_inc_point, + rd_inc_eval, + OpeningClaimSpec { + symbol: "stage4.registers_read_write.opening.RdInc", + oracle: "RdInc", + domain: "jolt.trace_domain", + point_arity: params.log_t, + claim_kind: "committed", + }, + )?); + + let ram_address_point = append_point_slice( + context, + module, + "stage4.ram_val_check.point.RamAddress", + "stage4.input.stage2.RamVal", + 0, + params.log_k_ram, + inputs.ram_val.point, + )?; + let ram_ra_point = append_point_concat( + context, + module, + "stage4.ram_val_check.point.RamRa", + "address_then_cycle", + params.log_k_ram + params.log_t, + &[ram_address_point, ram_val_check.0], + )?; + let ram_ra_eval = append_sumcheck_eval( + context, + module, + "stage4.ram_val_check.eval.RamRa", + "stage4.sumcheck", + "RamRa", + 0, + ram_val_check.1, + )?; + claim_symbols.push("stage4.ram_val_check.opening.RamRa".to_owned()); + claims.push(append_opening_claim( + context, + module, + ram_ra_point, + ram_ra_eval, + OpeningClaimSpec { + symbol: "stage4.ram_val_check.opening.RamRa", + oracle: "RamRa", + domain: "jolt.stage2_ram_rw_domain", + point_arity: params.log_k_ram + params.log_t, + claim_kind: "virtual", + }, + )?); + + let ram_inc_eval = append_sumcheck_eval( + context, + module, + "stage4.ram_val_check.eval.RamInc", + "stage4.sumcheck", + "RamInc", + 1, + ram_val_check.1, + )?; + claim_symbols.push("stage4.ram_val_check.opening.RamInc".to_owned()); + claims.push(append_opening_claim( + context, + module, + ram_val_check.0, + ram_inc_eval, + OpeningClaimSpec { + symbol: "stage4.ram_val_check.opening.RamInc", + oracle: "RamInc", + domain: "jolt.trace_domain", + point_arity: params.log_t, + claim_kind: "committed", + }, + )?); + + let claim_names = claim_symbols.iter().map(String::as_str).collect::>(); + let _batch = context.append_typed_op( + module, + "piop.opening_batch", + Some("stage4.openings"), + &[ + ("stage", "@stage4"), + ("proof_slot", "@stage4.openings"), + ("policy", r#""jolt_stage4_output_order""#), + ("count", &int_attr(claims.len())), + ("ordered_claims", &symbol_array_attr(&claim_names)), + ], + &claims, + &["!piop.opening_batch_type"], + )?; + Ok(()) +} + +fn append_opening_claim_equal<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + symbol: &str, + left: Value<'c, '_>, + right: Value<'c, '_>, +) -> Result<(), MlirError> { + let _operation = context.append_typed_op( + module, + "piop.opening_claim_equal", + Some(symbol), + &[("mode", r#""point_and_eval""#)], + &[left, right], + &[], + )?; + Ok(()) +} + +fn append_field_binary<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + op_name: &str, + symbol: &str, + lhs: Value<'c, 'a>, + rhs: Value<'c, 'a>, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + op_name, + Some(symbol), + &[], + &[lhs, rhs], + &["!field.scalar"], + )?; + first_result(op, op_name) +} + +fn append_field_add<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + lhs: Value<'c, 'a>, + rhs: Value<'c, 'a>, +) -> Result, MlirError> { + append_field_binary(context, module, "field.add", symbol, lhs, rhs) +} + +fn append_field_sub<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + lhs: Value<'c, 'a>, + rhs: Value<'c, 'a>, +) -> Result, MlirError> { + append_field_binary(context, module, "field.sub", symbol, lhs, rhs) +} + +fn append_field_mul<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + lhs: Value<'c, 'a>, + rhs: Value<'c, 'a>, +) -> Result, MlirError> { + append_field_binary(context, module, "field.mul", symbol, lhs, rhs) +} + +fn append_field_pow<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + base: Value<'c, 'a>, + exponent: usize, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "field.pow", + Some(symbol), + &[("exponent", &int_attr(exponent))], + &[base], + &["!field.scalar"], + )?; + first_result(op, "field.pow") +} + +fn append_sumcheck_claim<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + spec: SumcheckClaimSpec<'_>, + input_claim: Value<'c, 'a>, + inputs: &[Value<'c, 'a>], +) -> Result, MlirError> { + let mut operands = Vec::with_capacity(inputs.len() + 1); + operands.push(input_claim); + operands.extend_from_slice(inputs); + let op = context.append_typed_op( + module, + "piop.sumcheck_claim", + Some(spec.symbol), + &[ + ("stage", &format!("@{}", spec.stage)), + ("domain", &format!("@{}", spec.domain)), + ("num_rounds", &int_attr(spec.num_rounds)), + ("degree", &int_attr(spec.degree)), + ("claim", &format!("@{}", spec.claim)), + ("relation", &format!("@{}", spec.relation)), + ], + &operands, + &["!piop.sumcheck_claim_type"], + )?; + first_result(op, "piop.sumcheck_claim") +} + +fn append_sumcheck_batch<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + stage: Value<'c, 'a>, + claims: &[Value<'c, 'a>], + spec: SumcheckBatchSpec<'_>, +) -> Result, MlirError> { + let mut operands = Vec::with_capacity(claims.len() + 1); + operands.push(stage); + operands.extend_from_slice(claims); + let op = context.append_typed_op( + module, + "piop.sumcheck_batch", + Some(spec.symbol), + &[ + ("stage", &format!("@{}", spec.stage)), + ("proof_slot", &format!("@{}", spec.proof_slot)), + ("policy", &format!("\"{}\"", spec.policy)), + ("count", &int_attr(spec.ordered_claims.len())), + ("ordered_claims", &symbol_array_attr(spec.ordered_claims)), + ("claim_label", &format!("\"{}\"", spec.claim_label)), + ("round_label", &format!("\"{}\"", spec.round_label)), + ("round_schedule", &spec.round_schedule), + ], + &operands, + &["!piop.sumcheck_batch_type"], + )?; + first_result(op, "piop.sumcheck_batch") +} + +fn append_sumcheck<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + state: Value<'c, 'a>, + batch: Value<'c, 'a>, + spec: SumcheckDriverSpec<'_>, +) -> Result<(Value<'c, 'a>, Value<'c, 'a>, Value<'c, 'a>), MlirError> { + let op = context.append_typed_op( + module, + "piop.sumcheck", + Some(spec.symbol), + &[ + ("stage", &format!("@{}", spec.stage)), + ("proof_slot", &format!("@{}", spec.proof_slot)), + ("relation", &format!("@{}", spec.relation)), + ("policy", &format!("\"{}\"", spec.policy)), + ("round_schedule", &spec.round_schedule), + ("claim_label", &format!("\"{}\"", spec.claim_label)), + ("round_label", &format!("\"{}\"", spec.round_label)), + ("num_rounds", &int_attr(spec.num_rounds)), + ("degree", &int_attr(spec.degree)), + ], + &[state, batch], + &[ + "!transcript.state_type", + "!poly.point", + "!piop.sumcheck_result_type", + "!piop.sumcheck_proof_type", + ], + )?; + Ok(( + result(op, 0, "piop.sumcheck")?, + result(op, 1, "piop.sumcheck")?, + result(op, 2, "piop.sumcheck")?, + )) +} + +fn append_sumcheck_instance_result<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + spec: SumcheckInstanceResultSpec<'_>, + point: Value<'c, 'a>, + result_value: Value<'c, 'a>, +) -> Result<(Value<'c, 'a>, Value<'c, 'a>), MlirError> { + let op = context.append_typed_op( + module, + "piop.sumcheck_instance_result", + Some(spec.symbol), + &[ + ("source", &format!("@{}", spec.source)), + ("claim", &format!("@{}", spec.claim)), + ("relation", &format!("@{}", spec.relation)), + ("index", &int_attr(spec.index)), + ("point_arity", &int_attr(spec.point_arity)), + ("num_rounds", &int_attr(spec.num_rounds)), + ("round_offset", &int_attr(spec.round_offset)), + ("point_order", &format!("\"{}\"", spec.point_order)), + ("degree", &int_attr(spec.degree)), + ], + &[point, result_value], + &["!poly.point", "!piop.sumcheck_result_type"], + )?; + Ok(( + result(op, 0, "piop.sumcheck_instance_result")?, + result(op, 1, "piop.sumcheck_instance_result")?, + )) +} + +fn append_sumcheck_eval<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + source: &str, + oracle: &str, + index: usize, + result_value: Value<'c, 'a>, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "piop.sumcheck_eval", + Some(symbol), + &[ + ("source", &format!("@{source}")), + ("name", &format!("@{symbol}")), + ("index", &int_attr(index)), + ("oracle", &format!("@{oracle}")), + ], + &[result_value], + &["!field.scalar"], + )?; + first_result(op, "piop.sumcheck_eval") +} + +fn append_opening_claim<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + point: Value<'c, 'a>, + eval: Value<'c, 'a>, + spec: OpeningClaimSpec<'_>, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "piop.opening_claim", + Some(spec.symbol), + &[ + ("oracle", &format!("@{}", spec.oracle)), + ("domain", &format!("@{}", spec.domain)), + ("point_arity", &int_attr(spec.point_arity)), + ("claim_kind", &format!("\"{}\"", spec.claim_kind)), + ], + &[point, eval], + &["!piop.opening_claim_type"], + )?; + first_result(op, "piop.opening_claim") +} + +fn append_point_slice<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + source: &str, + offset: usize, + length: usize, + point: Value<'c, 'a>, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "poly.point_slice", + Some(symbol), + &[ + ("source", &format!("@{source}")), + ("offset", &int_attr(offset)), + ("length", &int_attr(length)), + ], + &[point], + &["!poly.point"], + )?; + first_result(op, "poly.point_slice") +} + +fn append_point_concat<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + layout: &str, + arity: usize, + points: &[Value<'c, 'a>], +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "poly.point_concat", + Some(symbol), + &[ + ("layout", &format!("\"{layout}\"")), + ("arity", &int_attr(arity)), + ], + points, + &["!poly.point"], + )?; + first_result(op, "poly.point_concat") +} + +fn first_result<'c, 'a>( + operation: OperationRef<'c, 'a>, + operation_name: &str, +) -> Result, MlirError> { + result(operation, 0, operation_name) +} + +fn result<'c, 'a>( + operation: OperationRef<'c, 'a>, + index: usize, + operation_name: &str, +) -> Result, MlirError> { + operation + .result(index) + .map(Into::into) + .map_err(|_| schema_error(format!("{operation_name} requires result {index}"))) +} + +struct RelationSpec<'a> { + symbol: &'a str, + kind: &'a str, + domain: &'a str, + num_rounds: usize, + degree: usize, + output_count: usize, +} + +struct Stage4OpeningInputs<'c, 'a> { + rd_write_value: Stage4OpeningInput<'c, 'a>, + rs1_registers: Stage4OpeningInput<'c, 'a>, + rs2_registers: Stage4OpeningInput<'c, 'a>, + rs1_instruction: Stage4OpeningInput<'c, 'a>, + rs2_instruction: Stage4OpeningInput<'c, 'a>, + ram_val: Stage4OpeningInput<'c, 'a>, + ram_val_final: Stage4OpeningInput<'c, 'a>, + ram_val_init: Stage4OpeningInput<'c, 'a>, +} + +struct Stage4OpeningInput<'c, 'a> { + point: Value<'c, 'a>, + eval: Value<'c, 'a>, + claim: Value<'c, 'a>, +} + +struct StageOpeningInputSpec<'a> { + symbol: &'a str, + source_stage: &'a str, + source_claim: &'a str, + oracle: &'a str, + domain: &'a str, + point_arity: usize, +} + +struct Stage4BatchedSumcheckInputs<'c, 'a, 'b> { + state: Value<'c, 'a>, + stage: Value<'c, 'a>, + openings: &'b Stage4OpeningInputs<'c, 'a>, + registers_gamma: Value<'c, 'a>, + ram_val_check_gamma: Value<'c, 'a>, +} + +struct SumcheckClaimSpec<'a> { + symbol: &'a str, + stage: &'a str, + domain: &'a str, + num_rounds: usize, + degree: usize, + claim: &'a str, + relation: &'a str, +} + +struct SumcheckBatchSpec<'a> { + symbol: &'a str, + stage: &'a str, + proof_slot: &'a str, + policy: &'a str, + ordered_claims: &'a [&'a str], + claim_label: &'a str, + round_label: &'a str, + round_schedule: String, +} + +struct SumcheckDriverSpec<'a> { + symbol: &'a str, + stage: &'a str, + proof_slot: &'a str, + relation: &'a str, + policy: &'a str, + round_schedule: String, + claim_label: &'a str, + round_label: &'a str, + num_rounds: usize, + degree: usize, +} + +struct SumcheckInstanceResultSpec<'a> { + symbol: &'a str, + source: &'a str, + claim: &'a str, + relation: &'a str, + index: usize, + point_arity: usize, + num_rounds: usize, + round_offset: usize, + point_order: &'a str, + degree: usize, +} + +struct OpeningClaimSpec<'a> { + symbol: &'a str, + oracle: &'a str, + domain: &'a str, + point_arity: usize, + claim_kind: &'a str, +} + +fn stage4_registers_rw_rounds(params: &JoltProtocolParams) -> usize { + params.log_t + params.register_log_k +} + +fn stage4_output_count() -> usize { + STAGE4_REGISTER_OUTPUTS.len() + STAGE4_RAM_VAL_OUTPUTS.len() +} + +fn int_attr(value: usize) -> String { + format!("{value} : i64") +} + +fn symbol_array_attr(values: &[&str]) -> String { + let values = values + .iter() + .map(|value| format!("@{value}")) + .collect::>() + .join(", "); + format!("[{values}]") +} + +fn schema_error(message: impl Into) -> MlirError { + SchemaError::new(message).into() +} diff --git a/crates/bolt/src/protocols/jolt/phases/stage5.rs b/crates/bolt/src/protocols/jolt/phases/stage5.rs new file mode 100644 index 0000000000..3a7b1171e8 --- /dev/null +++ b/crates/bolt/src/protocols/jolt/phases/stage5.rs @@ -0,0 +1,1387 @@ +use melior::ir::operation::OperationRef; +use melior::ir::Value; + +use crate::ir::{BoltModule, Compute, Party, Protocol}; +use crate::mlir::{verify_module, MeliorContext, MlirError}; +use crate::schema::{verify_protocol_schema, SchemaError}; + +use super::super::oracles; +use super::super::params::JoltProtocolParams; +use super::lowering::{lower_party_to_compute, transcript_squeeze_protocol_result_type}; + +const RAM_RA_CLAIM_REDUCTION_DEGREE: usize = 2; +const REGISTERS_VAL_EVALUATION_DEGREE: usize = 3; + +pub fn build_stage5_protocol<'c>( + context: &'c MeliorContext, + params: &JoltProtocolParams, +) -> Result, MlirError> { + let module = context.new_module::("jolt.stage5", None); + oracles::append_foundation_ops(context, &module, params)?; + context.append_op_with_owned_attrs( + &module, + "protocol.params", + Some("jolt.params"), + ¶ms.attrs(), + )?; + context.append_op( + &module, + "protocol.boundary", + Some("jolt.stage5"), + &[("roles", r#"["prover", "verifier"]"#)], + )?; + append_stage5_domains(context, &module, params)?; + append_stage5_oracles(context, &module, params)?; + append_stage5_relations(context, &module, params)?; + let inputs = append_stage5_opening_inputs(context, &module, params)?; + + let fs = context.append_typed_op( + &module, + "transcript.state", + Some("fs_after_stage4"), + &[("scheme", "@blake2b_transcript")], + &[], + &["!transcript.state_type"], + )?; + let state = first_result(fs, "transcript.state")?; + let stage = context.append_typed_op( + &module, + "piop.stage", + Some("stage5"), + &[ + ("name", r#""instruction_ram_and_register_value_reductions""#), + ("order", "5 : i64"), + ("roles", r#"["prover", "verifier"]"#), + ], + &[], + &["!piop.stage_type"], + )?; + let stage = first_result(stage, "piop.stage")?; + + let (state, instruction_gamma) = append_transcript_squeeze( + context, + &module, + state, + "stage5.instruction_read_raf.gamma", + "instruction_read_raf_gamma", + "challenge_scalar", + 1, + )?; + let (state, ram_gamma) = append_transcript_squeeze( + context, + &module, + state, + "stage5.ram_ra_claim_reduction.gamma", + "ram_ra_claim_reduction_gamma", + "challenge_scalar", + 1, + )?; + let _state = append_stage5_batched_sumcheck( + context, + &module, + params, + Stage5BatchedSumcheckInputs { + state, + stage, + openings: &inputs, + instruction_gamma, + ram_gamma, + }, + )?; + + verify_module(&module)?; + verify_protocol_schema(&module)?; + Ok(module) +} + +pub fn lower_stage5_to_compute<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Party>, +) -> Result, MlirError> { + lower_party_to_compute(context, module, "jolt.stage5", "jolt.stage5", "stage5") +} + +fn append_stage5_domains<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + params: &JoltProtocolParams, +) -> Result<(), MlirError> { + append_domain( + context, + module, + "jolt.stage2_ram_rw_domain", + params.log_k_ram + params.log_t, + )?; + append_domain( + context, + module, + "jolt.stage4_registers_rw_domain", + params.register_log_k + params.log_t, + )?; + append_domain( + context, + module, + "jolt.stage5_instruction_read_raf_domain", + params.instruction_log_k + params.log_t, + )?; + append_domain( + context, + module, + "jolt.stage5_instruction_ra_chunk_domain", + params.lookups_ra_virtual_log_k_chunk + params.log_t, + ) +} + +fn append_domain<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + symbol: &str, + log_size: usize, +) -> Result<(), MlirError> { + context.append_op( + module, + "poly.domain", + Some(symbol), + &[("field", "@bn254_fr"), ("log_size", &int_attr(log_size))], + ) +} + +fn append_stage5_oracles<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + params: &JoltProtocolParams, +) -> Result<(), MlirError> { + append_virtual_oracle(context, module, "LookupOutput", "jolt.trace_domain")?; + append_virtual_oracle(context, module, "LeftLookupOperand", "jolt.trace_domain")?; + append_virtual_oracle(context, module, "RightLookupOperand", "jolt.trace_domain")?; + append_virtual_oracle(context, module, "RamRa", "jolt.stage2_ram_rw_domain")?; + append_virtual_oracle( + context, + module, + "RegistersVal", + "jolt.stage4_registers_rw_domain", + )?; + append_virtual_oracle(context, module, "RdWa", "jolt.stage4_registers_rw_domain")?; + append_committed_trace_oracle(context, module, "RdInc")?; + append_virtual_oracle(context, module, "InstructionRafFlag", "jolt.trace_domain")?; + for index in 0..params.lookup_table_count { + append_virtual_oracle( + context, + module, + &format!("LookupTableFlag_{index}"), + "jolt.trace_domain", + )?; + } + for index in 0..params.instruction_ra_virtual_d { + append_virtual_oracle( + context, + module, + &format!("InstructionRa_{index}"), + "jolt.stage5_instruction_ra_chunk_domain", + )?; + } + Ok(()) +} + +fn append_virtual_oracle<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + symbol: &str, + domain: &str, +) -> Result<(), MlirError> { + context.append_op( + module, + "piop.oracle", + Some(symbol), + &[ + ("field", "@bn254_fr"), + ("domain", &format!("@{domain}")), + ("commit_domain", &format!("@{domain}")), + ("visibility", r#""virtual""#), + ("layout", r#""virtual""#), + ], + ) +} + +fn append_committed_trace_oracle<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + symbol: &str, +) -> Result<(), MlirError> { + context.append_op( + module, + "piop.oracle", + Some(symbol), + &[ + ("field", "@bn254_fr"), + ("domain", "@jolt.trace_domain"), + ("commit_domain", "@jolt.main_witness_commit_domain"), + ("visibility", r#""committed""#), + ("layout", r#""dense_trace""#), + ], + ) +} + +fn append_stage5_relations<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + params: &JoltProtocolParams, +) -> Result<(), MlirError> { + append_relation( + context, + module, + RelationSpec { + symbol: "jolt.stage5.instruction_read_raf", + kind: "sumcheck", + domain: "jolt.stage5_instruction_read_raf_domain", + num_rounds: stage5_instruction_rounds(params), + degree: instruction_read_raf_degree(params), + output_count: instruction_read_raf_output_count(params), + }, + )?; + append_relation( + context, + module, + RelationSpec { + symbol: "jolt.stage5.ram_ra_claim_reduction", + kind: "sumcheck", + domain: "jolt.trace_domain", + num_rounds: params.log_t, + degree: RAM_RA_CLAIM_REDUCTION_DEGREE, + output_count: 1, + }, + )?; + append_relation( + context, + module, + RelationSpec { + symbol: "jolt.stage5.registers_val_evaluation", + kind: "sumcheck", + domain: "jolt.trace_domain", + num_rounds: params.log_t, + degree: REGISTERS_VAL_EVALUATION_DEGREE, + output_count: 2, + }, + )?; + append_relation( + context, + module, + RelationSpec { + symbol: "jolt.stage5.batched", + kind: "batched_sumcheck", + domain: "jolt.stage5_instruction_read_raf_domain", + num_rounds: stage5_instruction_rounds(params), + degree: instruction_read_raf_degree(params), + output_count: stage5_output_count(params), + }, + ) +} + +fn append_relation<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + spec: RelationSpec<'_>, +) -> Result<(), MlirError> { + context.append_op( + module, + "piop.relation", + Some(spec.symbol), + &[ + ("kind", &format!("\"{}\"", spec.kind)), + ("domain", &format!("@{}", spec.domain)), + ("num_rounds", &int_attr(spec.num_rounds)), + ("degree", &int_attr(spec.degree)), + ("output_count", &int_attr(spec.output_count)), + ], + ) +} + +fn append_stage5_opening_inputs<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + params: &JoltProtocolParams, +) -> Result, MlirError> { + Ok(Stage5OpeningInputs { + lookup_output_instruction: append_stage_input( + context, + module, + StageOpeningInputSpec { + symbol: "stage5.input.stage2.instruction.LookupOutput", + source_stage: "stage2", + source_claim: "stage2.instruction_lookup.claim_reduction.opening.LookupOutput", + oracle: "LookupOutput", + domain: "jolt.trace_domain", + point_arity: params.log_t, + }, + )?, + lookup_output_product: append_stage_input( + context, + module, + StageOpeningInputSpec { + symbol: "stage5.input.stage2.product_virtual.LookupOutput", + source_stage: "stage2", + source_claim: "stage2.product_virtual.remainder.opening.LookupOutput", + oracle: "LookupOutput", + domain: "jolt.trace_domain", + point_arity: params.log_t, + }, + )?, + left_lookup_operand: append_stage_input( + context, + module, + StageOpeningInputSpec { + symbol: "stage5.input.stage2.instruction.LeftLookupOperand", + source_stage: "stage2", + source_claim: "stage2.instruction_lookup.claim_reduction.opening.LeftLookupOperand", + oracle: "LeftLookupOperand", + domain: "jolt.trace_domain", + point_arity: params.log_t, + }, + )?, + right_lookup_operand: append_stage_input( + context, + module, + StageOpeningInputSpec { + symbol: "stage5.input.stage2.instruction.RightLookupOperand", + source_stage: "stage2", + source_claim: + "stage2.instruction_lookup.claim_reduction.opening.RightLookupOperand", + oracle: "RightLookupOperand", + domain: "jolt.trace_domain", + point_arity: params.log_t, + }, + )?, + ram_ra_raf: append_stage_input( + context, + module, + StageOpeningInputSpec { + symbol: "stage5.input.stage2.ram_raf.RamRa", + source_stage: "stage2", + source_claim: "stage2.ram_raf.opening.RamRa", + oracle: "RamRa", + domain: "jolt.stage2_ram_rw_domain", + point_arity: params.log_k_ram + params.log_t, + }, + )?, + ram_ra_rw: append_stage_input( + context, + module, + StageOpeningInputSpec { + symbol: "stage5.input.stage2.ram_read_write.RamRa", + source_stage: "stage2", + source_claim: "stage2.ram_read_write.opening.RamRa", + oracle: "RamRa", + domain: "jolt.stage2_ram_rw_domain", + point_arity: params.log_k_ram + params.log_t, + }, + )?, + ram_ra_val: append_stage_input( + context, + module, + StageOpeningInputSpec { + symbol: "stage5.input.stage4.ram_val_check.RamRa", + source_stage: "stage4", + source_claim: "stage4.ram_val_check.opening.RamRa", + oracle: "RamRa", + domain: "jolt.stage2_ram_rw_domain", + point_arity: params.log_k_ram + params.log_t, + }, + )?, + registers_val: append_stage_input( + context, + module, + StageOpeningInputSpec { + symbol: "stage5.input.stage4.registers.RegistersVal", + source_stage: "stage4", + source_claim: "stage4.registers_read_write.opening.RegistersVal", + oracle: "RegistersVal", + domain: "jolt.stage4_registers_rw_domain", + point_arity: params.register_log_k + params.log_t, + }, + )?, + }) +} + +fn append_stage_input<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + spec: StageOpeningInputSpec<'_>, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "piop.opening_input", + Some(spec.symbol), + &[ + ("source_stage", &format!("@{}", spec.source_stage)), + ("source_claim", &format!("@{}", spec.source_claim)), + ("oracle", &format!("@{}", spec.oracle)), + ("domain", &format!("@{}", spec.domain)), + ("point_arity", &int_attr(spec.point_arity)), + ("claim_kind", r#""virtual""#), + ], + &[], + &["!poly.point", "!field.scalar", "!piop.opening_claim_type"], + )?; + Ok(Stage5OpeningInput { + point: result(op, 0, "piop.opening_input")?, + eval: result(op, 1, "piop.opening_input")?, + claim: result(op, 2, "piop.opening_input")?, + }) +} + +fn append_transcript_squeeze<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + state: Value<'c, 'a>, + symbol: &str, + label: &str, + kind: &str, + count: usize, +) -> Result<(Value<'c, 'a>, Value<'c, 'a>), MlirError> { + let op = context.append_typed_op( + module, + "transcript.squeeze", + Some(symbol), + &[ + ("label", &format!("\"{label}\"")), + ("kind", &format!("\"{kind}\"")), + ("count", &int_attr(count)), + ], + &[state], + &[ + "!transcript.state_type", + transcript_squeeze_protocol_result_type(kind)?, + ], + )?; + Ok(( + result(op, 0, "transcript.squeeze")?, + result(op, 1, "transcript.squeeze")?, + )) +} + +fn append_stage5_batched_sumcheck<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + params: &JoltProtocolParams, + spec: Stage5BatchedSumcheckInputs<'c, 'a, '_>, +) -> Result, MlirError> { + let inputs = spec.openings; + append_opening_claim_equal( + context, + module, + "stage5.instruction.lookup_output_claim_consistency", + inputs.lookup_output_instruction.claim, + inputs.lookup_output_product.claim, + )?; + + let instruction_gamma2 = append_field_pow( + context, + module, + "stage5.instruction_read_raf.gamma2", + spec.instruction_gamma, + 2, + )?; + let left_term = append_field_mul( + context, + module, + "stage5.instruction_read_raf.term.LeftLookupOperand", + spec.instruction_gamma, + inputs.left_lookup_operand.eval, + )?; + let right_term = append_field_mul( + context, + module, + "stage5.instruction_read_raf.term.RightLookupOperand", + instruction_gamma2, + inputs.right_lookup_operand.eval, + )?; + let lookup_left_sum = append_field_add( + context, + module, + "stage5.instruction_read_raf.partial.LookupOutputLeftOperand", + inputs.lookup_output_instruction.eval, + left_term, + )?; + let instruction_claim = append_field_add( + context, + module, + "stage5.instruction_read_raf.claim_expr", + lookup_left_sum, + right_term, + )?; + + let ram_gamma2 = append_field_pow( + context, + module, + "stage5.ram_ra_claim_reduction.gamma2", + spec.ram_gamma, + 2, + )?; + let ram_rw_term = append_field_mul( + context, + module, + "stage5.ram_ra_claim_reduction.term.RamRaReadWrite", + spec.ram_gamma, + inputs.ram_ra_rw.eval, + )?; + let ram_val_term = append_field_mul( + context, + module, + "stage5.ram_ra_claim_reduction.term.RamRaValCheck", + ram_gamma2, + inputs.ram_ra_val.eval, + )?; + let ram_raf_rw_sum = append_field_add( + context, + module, + "stage5.ram_ra_claim_reduction.partial.RafReadWrite", + inputs.ram_ra_raf.eval, + ram_rw_term, + )?; + let ram_claim = append_field_add( + context, + module, + "stage5.ram_ra_claim_reduction.claim_expr", + ram_raf_rw_sum, + ram_val_term, + )?; + + let claims = [ + append_sumcheck_claim( + context, + module, + SumcheckClaimSpec { + symbol: "stage5.instruction_read_raf.input", + stage: "stage5", + domain: "jolt.stage5_instruction_read_raf_domain", + num_rounds: stage5_instruction_rounds(params), + degree: instruction_read_raf_degree(params), + claim: "stage5.instruction_read_raf.weighted_lookup_values", + relation: "jolt.stage5.instruction_read_raf", + }, + instruction_claim, + &[ + inputs.lookup_output_instruction.claim, + inputs.left_lookup_operand.claim, + inputs.right_lookup_operand.claim, + ], + )?, + append_sumcheck_claim( + context, + module, + SumcheckClaimSpec { + symbol: "stage5.ram_ra_claim_reduction.input", + stage: "stage5", + domain: "jolt.trace_domain", + num_rounds: params.log_t, + degree: RAM_RA_CLAIM_REDUCTION_DEGREE, + claim: "stage5.ram_ra_claim_reduction.weighted_ram_ra", + relation: "jolt.stage5.ram_ra_claim_reduction", + }, + ram_claim, + &[ + inputs.ram_ra_raf.claim, + inputs.ram_ra_rw.claim, + inputs.ram_ra_val.claim, + ], + )?, + append_sumcheck_claim( + context, + module, + SumcheckClaimSpec { + symbol: "stage5.registers_val_evaluation.input", + stage: "stage5", + domain: "jolt.trace_domain", + num_rounds: params.log_t, + degree: REGISTERS_VAL_EVALUATION_DEGREE, + claim: "stage5.registers_val_evaluation.registers_val", + relation: "jolt.stage5.registers_val_evaluation", + }, + inputs.registers_val.eval, + &[inputs.registers_val.claim], + )?, + ]; + let round_schedule = format!("[{}, {}]", params.instruction_log_k, params.log_t); + let batch = append_sumcheck_batch( + context, + module, + spec.stage, + &claims, + SumcheckBatchSpec { + symbol: "stage5.batch", + stage: "stage5", + proof_slot: "stage5.sumcheck", + policy: "jolt_core_stage5_aligned", + ordered_claims: &[ + "stage5.instruction_read_raf.input", + "stage5.ram_ra_claim_reduction.input", + "stage5.registers_val_evaluation.input", + ], + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + round_schedule: &round_schedule, + }, + )?; + let (state, point, result_value) = append_sumcheck( + context, + module, + spec.state, + batch, + SumcheckDriverSpec { + symbol: "stage5.sumcheck", + stage: "stage5", + proof_slot: "stage5.sumcheck", + relation: "jolt.stage5.batched", + policy: "jolt_core_stage5_aligned", + round_schedule: &round_schedule, + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + num_rounds: stage5_instruction_rounds(params), + degree: instruction_read_raf_degree(params), + }, + )?; + let instruction = append_sumcheck_instance_result( + context, + module, + SumcheckInstanceResultSpec { + symbol: "stage5.instruction_read_raf.instance", + source: "stage5.sumcheck", + claim: "stage5.instruction_read_raf.input", + relation: "jolt.stage5.instruction_read_raf", + index: 0, + point_arity: stage5_instruction_rounds(params), + num_rounds: stage5_instruction_rounds(params), + round_offset: 0, + point_order: "instruction_read_raf", + degree: instruction_read_raf_degree(params), + }, + point, + result_value, + )?; + let ram = append_sumcheck_instance_result( + context, + module, + SumcheckInstanceResultSpec { + symbol: "stage5.ram_ra_claim_reduction.instance", + source: "stage5.sumcheck", + claim: "stage5.ram_ra_claim_reduction.input", + relation: "jolt.stage5.ram_ra_claim_reduction", + index: 1, + point_arity: params.log_t, + num_rounds: params.log_t, + round_offset: params.instruction_log_k, + point_order: "reverse", + degree: RAM_RA_CLAIM_REDUCTION_DEGREE, + }, + point, + result_value, + )?; + let registers = append_sumcheck_instance_result( + context, + module, + SumcheckInstanceResultSpec { + symbol: "stage5.registers_val_evaluation.instance", + source: "stage5.sumcheck", + claim: "stage5.registers_val_evaluation.input", + relation: "jolt.stage5.registers_val_evaluation", + index: 2, + point_arity: params.log_t, + num_rounds: params.log_t, + round_offset: params.instruction_log_k, + point_order: "reverse", + degree: REGISTERS_VAL_EVALUATION_DEGREE, + }, + point, + result_value, + )?; + append_stage5_output_openings(context, module, params, inputs, instruction, ram, registers)?; + Ok(state) +} + +fn append_stage5_output_openings<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + params: &JoltProtocolParams, + inputs: &Stage5OpeningInputs<'c, 'a>, + instruction: (Value<'c, 'a>, Value<'c, 'a>), + ram: (Value<'c, 'a>, Value<'c, 'a>), + registers: (Value<'c, 'a>, Value<'c, 'a>), +) -> Result<(), MlirError> { + let mut claims = Vec::new(); + let mut claim_symbols = Vec::new(); + + let instruction_cycle = append_point_slice( + context, + module, + "stage5.instruction_read_raf.point.Cycle", + "stage5.instruction_read_raf.instance", + params.instruction_log_k, + params.log_t, + instruction.0, + )?; + for index in 0..params.lookup_table_count { + let oracle = format!("LookupTableFlag_{index}"); + let symbol = format!("stage5.instruction_read_raf.opening.{oracle}"); + let eval_symbol = format!("stage5.instruction_read_raf.eval.{oracle}"); + let eval = append_sumcheck_eval( + context, + module, + &eval_symbol, + "stage5.sumcheck", + &oracle, + index, + instruction.1, + )?; + claim_symbols.push(symbol.clone()); + claims.push(append_opening_claim( + context, + module, + instruction_cycle, + eval, + OpeningClaimSpec { + symbol: &symbol, + oracle: &oracle, + domain: "jolt.trace_domain", + point_arity: params.log_t, + claim_kind: "virtual", + }, + )?); + } + + for index in 0..params.instruction_ra_virtual_d { + let oracle = format!("InstructionRa_{index}"); + let symbol = format!("stage5.instruction_read_raf.opening.{oracle}"); + let address_chunk = append_point_slice( + context, + module, + &format!("stage5.instruction_read_raf.point.{oracle}.address"), + "stage5.instruction_read_raf.instance", + index * params.lookups_ra_virtual_log_k_chunk, + params.lookups_ra_virtual_log_k_chunk, + instruction.0, + )?; + let ra_point = append_point_concat( + context, + module, + &format!("stage5.instruction_read_raf.point.{oracle}"), + "address_chunk_then_cycle", + params.lookups_ra_virtual_log_k_chunk + params.log_t, + &[address_chunk, instruction_cycle], + )?; + let eval_symbol = format!("stage5.instruction_read_raf.eval.{oracle}"); + let eval = append_sumcheck_eval( + context, + module, + &eval_symbol, + "stage5.sumcheck", + &oracle, + params.lookup_table_count + index, + instruction.1, + )?; + claim_symbols.push(symbol.clone()); + claims.push(append_opening_claim( + context, + module, + ra_point, + eval, + OpeningClaimSpec { + symbol: &symbol, + oracle: &oracle, + domain: "jolt.stage5_instruction_ra_chunk_domain", + point_arity: params.lookups_ra_virtual_log_k_chunk + params.log_t, + claim_kind: "virtual", + }, + )?); + } + + let raf_flag_eval_index = params.lookup_table_count + params.instruction_ra_virtual_d; + let raf_flag_eval = append_sumcheck_eval( + context, + module, + "stage5.instruction_read_raf.eval.InstructionRafFlag", + "stage5.sumcheck", + "InstructionRafFlag", + raf_flag_eval_index, + instruction.1, + )?; + claim_symbols.push("stage5.instruction_read_raf.opening.InstructionRafFlag".to_owned()); + claims.push(append_opening_claim( + context, + module, + instruction_cycle, + raf_flag_eval, + OpeningClaimSpec { + symbol: "stage5.instruction_read_raf.opening.InstructionRafFlag", + oracle: "InstructionRafFlag", + domain: "jolt.trace_domain", + point_arity: params.log_t, + claim_kind: "virtual", + }, + )?); + + let ram_address = append_point_slice( + context, + module, + "stage5.ram_ra_claim_reduction.point.RamAddress", + "stage5.input.stage2.ram_raf.RamRa", + 0, + params.log_k_ram, + inputs.ram_ra_raf.point, + )?; + let ram_ra_point = append_point_concat( + context, + module, + "stage5.ram_ra_claim_reduction.point.RamRa", + "address_then_cycle", + params.log_k_ram + params.log_t, + &[ram_address, ram.0], + )?; + let ram_ra_eval = append_sumcheck_eval( + context, + module, + "stage5.ram_ra_claim_reduction.eval.RamRa", + "stage5.sumcheck", + "RamRa", + 0, + ram.1, + )?; + claim_symbols.push("stage5.ram_ra_claim_reduction.opening.RamRa".to_owned()); + claims.push(append_opening_claim( + context, + module, + ram_ra_point, + ram_ra_eval, + OpeningClaimSpec { + symbol: "stage5.ram_ra_claim_reduction.opening.RamRa", + oracle: "RamRa", + domain: "jolt.stage2_ram_rw_domain", + point_arity: params.log_k_ram + params.log_t, + claim_kind: "virtual", + }, + )?); + + let rd_inc_eval = append_sumcheck_eval( + context, + module, + "stage5.registers_val_evaluation.eval.RdInc", + "stage5.sumcheck", + "RdInc", + 0, + registers.1, + )?; + claim_symbols.push("stage5.registers_val_evaluation.opening.RdInc".to_owned()); + claims.push(append_opening_claim( + context, + module, + registers.0, + rd_inc_eval, + OpeningClaimSpec { + symbol: "stage5.registers_val_evaluation.opening.RdInc", + oracle: "RdInc", + domain: "jolt.trace_domain", + point_arity: params.log_t, + claim_kind: "committed", + }, + )?); + + let register_address = append_point_slice( + context, + module, + "stage5.registers_val_evaluation.point.RegisterAddress", + "stage5.input.stage4.registers.RegistersVal", + 0, + params.register_log_k, + inputs.registers_val.point, + )?; + let rd_wa_point = append_point_concat( + context, + module, + "stage5.registers_val_evaluation.point.RdWa", + "register_address_then_cycle", + params.register_log_k + params.log_t, + &[register_address, registers.0], + )?; + let rd_wa_eval = append_sumcheck_eval( + context, + module, + "stage5.registers_val_evaluation.eval.RdWa", + "stage5.sumcheck", + "RdWa", + 1, + registers.1, + )?; + claim_symbols.push("stage5.registers_val_evaluation.opening.RdWa".to_owned()); + claims.push(append_opening_claim( + context, + module, + rd_wa_point, + rd_wa_eval, + OpeningClaimSpec { + symbol: "stage5.registers_val_evaluation.opening.RdWa", + oracle: "RdWa", + domain: "jolt.stage4_registers_rw_domain", + point_arity: params.register_log_k + params.log_t, + claim_kind: "virtual", + }, + )?); + + let claim_names = claim_symbols.iter().map(String::as_str).collect::>(); + let _batch = context.append_typed_op( + module, + "piop.opening_batch", + Some("stage5.openings"), + &[ + ("stage", "@stage5"), + ("proof_slot", "@stage5.openings"), + ("policy", r#""jolt_stage5_output_order""#), + ("count", &int_attr(claims.len())), + ("ordered_claims", &symbol_array_attr(&claim_names)), + ], + &claims, + &["!piop.opening_batch_type"], + )?; + Ok(()) +} + +fn append_opening_claim_equal<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + symbol: &str, + left: Value<'c, '_>, + right: Value<'c, '_>, +) -> Result<(), MlirError> { + let _operation = context.append_typed_op( + module, + "piop.opening_claim_equal", + Some(symbol), + &[("mode", r#""point_and_eval""#)], + &[left, right], + &[], + )?; + Ok(()) +} + +fn append_field_binary<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + op_name: &str, + symbol: &str, + lhs: Value<'c, 'a>, + rhs: Value<'c, 'a>, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + op_name, + Some(symbol), + &[], + &[lhs, rhs], + &["!field.scalar"], + )?; + first_result(op, op_name) +} + +fn append_field_add<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + lhs: Value<'c, 'a>, + rhs: Value<'c, 'a>, +) -> Result, MlirError> { + append_field_binary(context, module, "field.add", symbol, lhs, rhs) +} + +fn append_field_mul<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + lhs: Value<'c, 'a>, + rhs: Value<'c, 'a>, +) -> Result, MlirError> { + append_field_binary(context, module, "field.mul", symbol, lhs, rhs) +} + +fn append_field_pow<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + base: Value<'c, 'a>, + exponent: usize, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "field.pow", + Some(symbol), + &[("exponent", &int_attr(exponent))], + &[base], + &["!field.scalar"], + )?; + first_result(op, "field.pow") +} + +fn append_sumcheck_claim<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + spec: SumcheckClaimSpec<'_>, + input_claim: Value<'c, 'a>, + inputs: &[Value<'c, 'a>], +) -> Result, MlirError> { + let mut operands = Vec::with_capacity(inputs.len() + 1); + operands.push(input_claim); + operands.extend_from_slice(inputs); + let op = context.append_typed_op( + module, + "piop.sumcheck_claim", + Some(spec.symbol), + &[ + ("stage", &format!("@{}", spec.stage)), + ("domain", &format!("@{}", spec.domain)), + ("num_rounds", &int_attr(spec.num_rounds)), + ("degree", &int_attr(spec.degree)), + ("claim", &format!("@{}", spec.claim)), + ("relation", &format!("@{}", spec.relation)), + ], + &operands, + &["!piop.sumcheck_claim_type"], + )?; + first_result(op, "piop.sumcheck_claim") +} + +fn append_sumcheck_batch<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + stage: Value<'c, 'a>, + claims: &[Value<'c, 'a>], + spec: SumcheckBatchSpec<'_>, +) -> Result, MlirError> { + let mut operands = Vec::with_capacity(claims.len() + 1); + operands.push(stage); + operands.extend_from_slice(claims); + let op = context.append_typed_op( + module, + "piop.sumcheck_batch", + Some(spec.symbol), + &[ + ("stage", &format!("@{}", spec.stage)), + ("proof_slot", &format!("@{}", spec.proof_slot)), + ("policy", &format!("\"{}\"", spec.policy)), + ("count", &int_attr(spec.ordered_claims.len())), + ("ordered_claims", &symbol_array_attr(spec.ordered_claims)), + ("claim_label", &format!("\"{}\"", spec.claim_label)), + ("round_label", &format!("\"{}\"", spec.round_label)), + ("round_schedule", spec.round_schedule), + ], + &operands, + &["!piop.sumcheck_batch_type"], + )?; + first_result(op, "piop.sumcheck_batch") +} + +fn append_sumcheck<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + state: Value<'c, 'a>, + batch: Value<'c, 'a>, + spec: SumcheckDriverSpec<'_>, +) -> Result<(Value<'c, 'a>, Value<'c, 'a>, Value<'c, 'a>), MlirError> { + let op = context.append_typed_op( + module, + "piop.sumcheck", + Some(spec.symbol), + &[ + ("stage", &format!("@{}", spec.stage)), + ("proof_slot", &format!("@{}", spec.proof_slot)), + ("relation", &format!("@{}", spec.relation)), + ("policy", &format!("\"{}\"", spec.policy)), + ("round_schedule", spec.round_schedule), + ("claim_label", &format!("\"{}\"", spec.claim_label)), + ("round_label", &format!("\"{}\"", spec.round_label)), + ("num_rounds", &int_attr(spec.num_rounds)), + ("degree", &int_attr(spec.degree)), + ], + &[state, batch], + &[ + "!transcript.state_type", + "!poly.point", + "!piop.sumcheck_result_type", + "!piop.sumcheck_proof_type", + ], + )?; + Ok(( + result(op, 0, "piop.sumcheck")?, + result(op, 1, "piop.sumcheck")?, + result(op, 2, "piop.sumcheck")?, + )) +} + +fn append_sumcheck_instance_result<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + spec: SumcheckInstanceResultSpec<'_>, + point: Value<'c, 'a>, + result_value: Value<'c, 'a>, +) -> Result<(Value<'c, 'a>, Value<'c, 'a>), MlirError> { + let op = context.append_typed_op( + module, + "piop.sumcheck_instance_result", + Some(spec.symbol), + &[ + ("source", &format!("@{}", spec.source)), + ("claim", &format!("@{}", spec.claim)), + ("relation", &format!("@{}", spec.relation)), + ("index", &int_attr(spec.index)), + ("point_arity", &int_attr(spec.point_arity)), + ("num_rounds", &int_attr(spec.num_rounds)), + ("round_offset", &int_attr(spec.round_offset)), + ("point_order", &format!("\"{}\"", spec.point_order)), + ("degree", &int_attr(spec.degree)), + ], + &[point, result_value], + &["!poly.point", "!piop.sumcheck_result_type"], + )?; + Ok(( + result(op, 0, "piop.sumcheck_instance_result")?, + result(op, 1, "piop.sumcheck_instance_result")?, + )) +} + +fn append_sumcheck_eval<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + source: &str, + oracle: &str, + index: usize, + result_value: Value<'c, 'a>, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "piop.sumcheck_eval", + Some(symbol), + &[ + ("source", &format!("@{}", source)), + ("name", &format!("@{}", symbol)), + ("index", &int_attr(index)), + ("oracle", &format!("@{}", oracle)), + ], + &[result_value], + &["!field.scalar"], + )?; + first_result(op, "piop.sumcheck_eval") +} + +fn append_point_slice<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + source: &str, + offset: usize, + length: usize, + input: Value<'c, 'a>, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "poly.point_slice", + Some(symbol), + &[ + ("source", &format!("@{}", source)), + ("offset", &int_attr(offset)), + ("length", &int_attr(length)), + ], + &[input], + &["!poly.point"], + )?; + first_result(op, "poly.point_slice") +} + +fn append_point_concat<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + layout: &str, + arity: usize, + inputs: &[Value<'c, 'a>], +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "poly.point_concat", + Some(symbol), + &[ + ("layout", &format!("\"{}\"", layout)), + ("arity", &int_attr(arity)), + ], + inputs, + &["!poly.point"], + )?; + first_result(op, "poly.point_concat") +} + +fn append_opening_claim<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + point: Value<'c, 'a>, + eval: Value<'c, 'a>, + spec: OpeningClaimSpec<'_>, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "piop.opening_claim", + Some(spec.symbol), + &[ + ("oracle", &format!("@{}", spec.oracle)), + ("domain", &format!("@{}", spec.domain)), + ("point_arity", &int_attr(spec.point_arity)), + ("claim_kind", &format!("\"{}\"", spec.claim_kind)), + ], + &[point, eval], + &["!piop.opening_claim_type"], + )?; + first_result(op, "piop.opening_claim") +} + +fn stage5_instruction_rounds(params: &JoltProtocolParams) -> usize { + params.instruction_log_k + params.log_t +} + +fn instruction_read_raf_degree(params: &JoltProtocolParams) -> usize { + params.instruction_ra_virtual_d + 2 +} + +fn instruction_read_raf_output_count(params: &JoltProtocolParams) -> usize { + params.lookup_table_count + params.instruction_ra_virtual_d + 1 +} + +fn stage5_output_count(params: &JoltProtocolParams) -> usize { + instruction_read_raf_output_count(params) + 3 +} + +fn int_attr(value: usize) -> String { + format!("{value} : i64") +} + +fn symbol_array_attr(values: &[&str]) -> String { + let values = values + .iter() + .map(|value| format!("@{value}")) + .collect::>() + .join(", "); + format!("[{values}]") +} + +fn first_result<'c, 'a>( + op: OperationRef<'c, 'a>, + context: &str, +) -> Result, MlirError> { + result(op, 0, context) +} + +fn result<'c, 'a>( + op: OperationRef<'c, 'a>, + index: usize, + context: &str, +) -> Result, MlirError> { + op.result(index) + .map(Into::into) + .map_err(|_| schema_error(format!("{context} expected result {index}"))) +} + +fn schema_error(message: impl Into) -> MlirError { + SchemaError::new(message).into() +} + +struct Stage5OpeningInput<'c, 'a> { + point: Value<'c, 'a>, + eval: Value<'c, 'a>, + claim: Value<'c, 'a>, +} + +struct Stage5OpeningInputs<'c, 'a> { + lookup_output_instruction: Stage5OpeningInput<'c, 'a>, + lookup_output_product: Stage5OpeningInput<'c, 'a>, + left_lookup_operand: Stage5OpeningInput<'c, 'a>, + right_lookup_operand: Stage5OpeningInput<'c, 'a>, + ram_ra_raf: Stage5OpeningInput<'c, 'a>, + ram_ra_rw: Stage5OpeningInput<'c, 'a>, + ram_ra_val: Stage5OpeningInput<'c, 'a>, + registers_val: Stage5OpeningInput<'c, 'a>, +} + +struct StageOpeningInputSpec<'a> { + symbol: &'a str, + source_stage: &'a str, + source_claim: &'a str, + oracle: &'a str, + domain: &'a str, + point_arity: usize, +} + +struct Stage5BatchedSumcheckInputs<'c, 'a, 'b> { + state: Value<'c, 'a>, + stage: Value<'c, 'a>, + openings: &'b Stage5OpeningInputs<'c, 'a>, + instruction_gamma: Value<'c, 'a>, + ram_gamma: Value<'c, 'a>, +} + +struct RelationSpec<'a> { + symbol: &'a str, + kind: &'a str, + domain: &'a str, + num_rounds: usize, + degree: usize, + output_count: usize, +} + +struct SumcheckClaimSpec<'a> { + symbol: &'a str, + stage: &'a str, + domain: &'a str, + num_rounds: usize, + degree: usize, + claim: &'a str, + relation: &'a str, +} + +struct SumcheckBatchSpec<'a> { + symbol: &'a str, + stage: &'a str, + proof_slot: &'a str, + policy: &'a str, + ordered_claims: &'a [&'a str], + claim_label: &'a str, + round_label: &'a str, + round_schedule: &'a str, +} + +struct SumcheckDriverSpec<'a> { + symbol: &'a str, + stage: &'a str, + proof_slot: &'a str, + relation: &'a str, + policy: &'a str, + round_schedule: &'a str, + claim_label: &'a str, + round_label: &'a str, + num_rounds: usize, + degree: usize, +} + +struct SumcheckInstanceResultSpec<'a> { + symbol: &'a str, + source: &'a str, + claim: &'a str, + relation: &'a str, + index: usize, + point_arity: usize, + num_rounds: usize, + round_offset: usize, + point_order: &'a str, + degree: usize, +} + +struct OpeningClaimSpec<'a> { + symbol: &'a str, + oracle: &'a str, + domain: &'a str, + point_arity: usize, + claim_kind: &'a str, +} diff --git a/crates/bolt/src/protocols/jolt/phases/stage6.rs b/crates/bolt/src/protocols/jolt/phases/stage6.rs new file mode 100644 index 0000000000..2e474f42c5 --- /dev/null +++ b/crates/bolt/src/protocols/jolt/phases/stage6.rs @@ -0,0 +1,2365 @@ +use std::collections::BTreeSet; + +use melior::ir::operation::OperationRef; +use melior::ir::Value; + +use crate::ir::{BoltModule, Compute, Party, Protocol}; +use crate::mlir::{verify_module, MeliorContext, MlirError}; +use crate::schema::{verify_protocol_schema, SchemaError}; + +use super::super::oracles; +use super::super::params::JoltProtocolParams; +use super::lowering::{lower_party_to_compute, transcript_squeeze_protocol_result_type}; + +const BOOLEANITY_DEGREE: usize = 3; +const HAMMING_BOOLEANITY_DEGREE: usize = 3; +const INC_CLAIM_REDUCTION_DEGREE: usize = 2; + +#[derive(Clone, Copy)] +enum BytecodeStageGamma { + Stage1, + Stage2, + Stage3, + Stage4, + Stage5, +} + +pub fn build_stage6_protocol<'c>( + context: &'c MeliorContext, + params: &JoltProtocolParams, +) -> Result, MlirError> { + let module = context.new_module::("jolt.stage6", None); + oracles::append_foundation_ops(context, &module, params)?; + context.append_op_with_owned_attrs( + &module, + "protocol.params", + Some("jolt.params"), + ¶ms.attrs(), + )?; + context.append_op( + &module, + "protocol.boundary", + Some("jolt.stage6"), + &[("roles", r#"["prover", "verifier"]"#)], + )?; + append_stage6_domains(context, &module, params)?; + append_stage6_oracles(context, &module, params)?; + append_stage6_relations(context, &module, params)?; + let inputs = append_stage6_opening_inputs(context, &module, params)?; + + let fs = context.append_typed_op( + &module, + "transcript.state", + Some("fs_after_stage5"), + &[("scheme", "@blake2b_transcript")], + &[], + &["!transcript.state_type"], + )?; + let state = first_result(fs, "transcript.state")?; + let stage = context.append_typed_op( + &module, + "piop.stage", + Some("stage6"), + &[ + ( + "name", + r#""bytecode_booleanity_and_virtual_address_reductions""#, + ), + ("order", "6 : i64"), + ("roles", r#"["prover", "verifier"]"#), + ], + &[], + &["!piop.stage_type"], + )?; + let stage = first_result(stage, "piop.stage")?; + + let (state, bc_gamma) = append_transcript_squeeze( + context, + &module, + state, + "stage6.bytecode_read_raf.gamma", + "bc_raf_gamma", + "challenge_scalar", + 1, + )?; + let (state, bc_stage1_gamma) = append_transcript_squeeze( + context, + &module, + state, + "stage6.bytecode_read_raf.stage1_gamma", + "bc_raf_stage1_gamma", + "challenge_scalar", + 1, + )?; + let (state, bc_stage2_gamma) = append_transcript_squeeze( + context, + &module, + state, + "stage6.bytecode_read_raf.stage2_gamma", + "bc_raf_stage2_gamma", + "challenge_scalar", + 1, + )?; + let (state, bc_stage3_gamma) = append_transcript_squeeze( + context, + &module, + state, + "stage6.bytecode_read_raf.stage3_gamma", + "bc_raf_stage3_gamma", + "challenge_scalar", + 1, + )?; + let (state, bc_stage4_gamma) = append_transcript_squeeze( + context, + &module, + state, + "stage6.bytecode_read_raf.stage4_gamma", + "bc_raf_stage4_gamma", + "challenge_scalar", + 1, + )?; + let (state, bc_stage5_gamma) = append_transcript_squeeze( + context, + &module, + state, + "stage6.bytecode_read_raf.stage5_gamma", + "bc_raf_stage5_gamma", + "challenge_scalar", + 1, + )?; + let (state, booleanity_gamma) = append_transcript_squeeze( + context, + &module, + state, + "stage6.booleanity.gamma", + "booleanity_gamma", + "challenge_scalar", + 1, + )?; + append_booleanity_power_placeholders(context, &module, params, booleanity_gamma)?; + let (state, inst_ra_gamma) = append_transcript_squeeze( + context, + &module, + state, + "stage6.instruction_ra_virtual.gamma", + "inst_ra_virtual_gamma", + "challenge_scalar", + 1, + )?; + let (state, inc_gamma) = append_transcript_squeeze( + context, + &module, + state, + "stage6.inc_claim_reduction.gamma", + "inc_reduction_gamma", + "challenge_scalar", + 1, + )?; + + let _state = append_stage6_batched_sumcheck( + context, + &module, + params, + Stage6BatchedSumcheckInputs { + state, + stage, + openings: &inputs, + bc_gamma, + bc_stage1_gamma, + bc_stage2_gamma, + bc_stage3_gamma, + bc_stage4_gamma, + bc_stage5_gamma, + inst_ra_gamma, + inc_gamma, + }, + )?; + + verify_module(&module)?; + verify_protocol_schema(&module)?; + Ok(module) +} + +pub fn lower_stage6_to_compute<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Party>, +) -> Result, MlirError> { + lower_party_to_compute(context, module, "jolt.stage6", "jolt.stage6", "stage6") +} + +fn append_stage6_domains<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + params: &JoltProtocolParams, +) -> Result<(), MlirError> { + append_domain( + context, + module, + "jolt.stage2_ram_rw_domain", + params.log_k_ram + params.log_t, + )?; + append_domain( + context, + module, + "jolt.stage4_registers_rw_domain", + params.register_log_k + params.log_t, + )?; + append_domain( + context, + module, + "jolt.stage5_instruction_ra_chunk_domain", + params.lookups_ra_virtual_log_k_chunk + params.log_t, + )?; + append_domain( + context, + module, + "jolt.stage6_bytecode_read_raf_domain", + stage6_max_rounds(params), + )?; + append_domain( + context, + module, + "jolt.stage6_booleanity_domain", + booleanity_rounds(params), + ) +} + +fn append_domain<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + symbol: &str, + log_size: usize, +) -> Result<(), MlirError> { + context.append_op( + module, + "poly.domain", + Some(symbol), + &[("field", "@bn254_fr"), ("log_size", &int_attr(log_size))], + ) +} + +fn append_stage6_oracles<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + params: &JoltProtocolParams, +) -> Result<(), MlirError> { + let mut trace_oracles = BTreeSet::new(); + trace_oracles.extend( + [ + "HammingWeight", + "Imm", + "InstructionFlagBranch", + "InstructionFlagIsNoop", + "InstructionFlagLeftOperandIsPC", + "InstructionFlagLeftOperandIsRs1Value", + "InstructionFlagRightOperandIsImm", + "InstructionFlagRightOperandIsRs2Value", + "InstructionRafFlag", + "LookupOutput", + "OpFlagAddOperands", + "OpFlagAdvice", + "OpFlagAssert", + "OpFlagDoNotUpdateUnexpandedPC", + "OpFlagIsCompressed", + "OpFlagIsFirstInSequence", + "OpFlagIsLastInSequence", + "OpFlagJump", + "OpFlagLoad", + "OpFlagMultiplyOperands", + "OpFlagStore", + "OpFlagSubtractOperands", + "OpFlagVirtualInstruction", + "OpFlagWriteLookupOutputToRD", + "PC", + "UnexpandedPC", + ] + .into_iter() + .map(str::to_owned), + ); + for index in 0..params.lookup_table_count { + let _inserted = trace_oracles.insert(format!("LookupTableFlag_{index}")); + } + for oracle in trace_oracles { + append_virtual_oracle(context, module, &oracle, "jolt.trace_domain")?; + } + + append_virtual_oracle(context, module, "RamRa", "jolt.stage2_ram_rw_domain")?; + for oracle in ["RdWa", "Rs1Ra", "Rs2Ra"] { + append_virtual_oracle(context, module, oracle, "jolt.stage4_registers_rw_domain")?; + } + + append_committed_trace_oracle(context, module, "RamInc")?; + append_committed_trace_oracle(context, module, "RdInc")?; + for index in 0..params.instruction_d { + append_committed_main_witness_oracle(context, module, &format!("InstructionRa_{index}"))?; + } + for index in 0..params.bytecode_d { + append_committed_main_witness_oracle(context, module, &format!("BytecodeRa_{index}"))?; + } + for index in 0..params.ram_d { + append_committed_main_witness_oracle(context, module, &format!("RamRa_{index}"))?; + } + Ok(()) +} + +fn append_virtual_oracle<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + symbol: &str, + domain: &str, +) -> Result<(), MlirError> { + context.append_op( + module, + "piop.oracle", + Some(symbol), + &[ + ("field", "@bn254_fr"), + ("domain", &format!("@{domain}")), + ("commit_domain", &format!("@{domain}")), + ("visibility", r#""virtual""#), + ("layout", r#""virtual""#), + ], + ) +} + +fn append_committed_trace_oracle<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + symbol: &str, +) -> Result<(), MlirError> { + context.append_op( + module, + "piop.oracle", + Some(symbol), + &[ + ("field", "@bn254_fr"), + ("domain", "@jolt.trace_domain"), + ("commit_domain", "@jolt.main_witness_commit_domain"), + ("visibility", r#""committed""#), + ("layout", r#""dense_trace""#), + ], + ) +} + +fn append_committed_main_witness_oracle<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + symbol: &str, +) -> Result<(), MlirError> { + context.append_op( + module, + "piop.oracle", + Some(symbol), + &[ + ("field", "@bn254_fr"), + ("domain", "@jolt.main_witness_commit_domain"), + ("commit_domain", "@jolt.main_witness_commit_domain"), + ("visibility", r#""committed""#), + ("layout", r#""onehot_expanded""#), + ], + ) +} + +fn append_stage6_relations<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + params: &JoltProtocolParams, +) -> Result<(), MlirError> { + append_relation( + context, + module, + RelationSpec { + symbol: "jolt.stage6.bytecode_read_raf", + kind: "sumcheck", + domain: "jolt.stage6_bytecode_read_raf_domain", + num_rounds: stage6_max_rounds(params), + degree: params.bytecode_d + 1, + output_count: params.bytecode_d, + }, + )?; + append_relation( + context, + module, + RelationSpec { + symbol: "jolt.stage6.booleanity", + kind: "sumcheck", + domain: "jolt.stage6_booleanity_domain", + num_rounds: booleanity_rounds(params), + degree: BOOLEANITY_DEGREE, + output_count: total_ra_oracles(params), + }, + )?; + append_relation( + context, + module, + RelationSpec { + symbol: "jolt.stage6.hamming_booleanity", + kind: "sumcheck", + domain: "jolt.trace_domain", + num_rounds: params.log_t, + degree: HAMMING_BOOLEANITY_DEGREE, + output_count: 1, + }, + )?; + append_relation( + context, + module, + RelationSpec { + symbol: "jolt.stage6.ram_ra_virtual", + kind: "sumcheck", + domain: "jolt.trace_domain", + num_rounds: params.log_t, + degree: params.ram_d + 1, + output_count: params.ram_d, + }, + )?; + append_relation( + context, + module, + RelationSpec { + symbol: "jolt.stage6.instruction_ra_virtual", + kind: "sumcheck", + domain: "jolt.trace_domain", + num_rounds: params.log_t, + degree: n_committed_per_virtual(params) + 1, + output_count: params.instruction_d, + }, + )?; + append_relation( + context, + module, + RelationSpec { + symbol: "jolt.stage6.inc_claim_reduction", + kind: "sumcheck", + domain: "jolt.trace_domain", + num_rounds: params.log_t, + degree: INC_CLAIM_REDUCTION_DEGREE, + output_count: 2, + }, + )?; + append_relation( + context, + module, + RelationSpec { + symbol: "jolt.stage6.batched", + kind: "batched_sumcheck", + domain: "jolt.stage6_bytecode_read_raf_domain", + num_rounds: stage6_max_rounds(params), + degree: stage6_batched_degree(params), + output_count: stage6_output_count(params), + }, + ) +} + +fn append_relation<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + spec: RelationSpec<'_>, +) -> Result<(), MlirError> { + context.append_op( + module, + "piop.relation", + Some(spec.symbol), + &[ + ("kind", &format!("\"{}\"", spec.kind)), + ("domain", &format!("@{}", spec.domain)), + ("num_rounds", &int_attr(spec.num_rounds)), + ("degree", &int_attr(spec.degree)), + ("output_count", &int_attr(spec.output_count)), + ], + ) +} + +fn append_stage6_opening_inputs<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + params: &JoltProtocolParams, +) -> Result, MlirError> { + let mut bytecode_terms = Vec::new(); + append_bytecode_term( + context, + module, + params, + &mut bytecode_terms, + BytecodeTermSpec::trace( + "stage6.input.stage1.UnexpandedPC", + "stage1", + "stage1.outer_remaining.opening.UnexpandedPC", + "UnexpandedPC", + 0, + Some(BytecodeStageGamma::Stage1), + 0, + ), + )?; + append_bytecode_term( + context, + module, + params, + &mut bytecode_terms, + BytecodeTermSpec::trace( + "stage6.input.stage1.Imm", + "stage1", + "stage1.outer_remaining.opening.Imm", + "Imm", + 0, + Some(BytecodeStageGamma::Stage1), + 1, + ), + )?; + for (index, oracle) in STAGE1_OP_FLAGS.iter().enumerate() { + append_bytecode_term( + context, + module, + params, + &mut bytecode_terms, + BytecodeTermSpec::trace( + &format!("stage6.input.stage1.{oracle}"), + "stage1", + &format!("stage1.outer_remaining.opening.{oracle}"), + oracle, + 0, + Some(BytecodeStageGamma::Stage1), + 2 + index, + ), + )?; + } + for (oracle, stage_gamma_power) in [ + ("OpFlagJump", 0), + ("InstructionFlagBranch", 1), + ("OpFlagWriteLookupOutputToRD", 2), + ("OpFlagVirtualInstruction", 3), + ] { + append_bytecode_term( + context, + module, + params, + &mut bytecode_terms, + BytecodeTermSpec::trace( + &format!("stage6.input.stage2.{oracle}"), + "stage2", + &format!("stage2.product_virtual.remainder.opening.{oracle}"), + oracle, + 1, + Some(BytecodeStageGamma::Stage2), + stage_gamma_power, + ), + )?; + } + for (symbol, source_claim, oracle, stage_gamma_power) in [ + ( + "stage6.input.stage3.instruction_input.Imm", + "stage3.instruction_input.opening.Imm", + "Imm", + 0, + ), + ( + "stage6.input.stage3.spartan_shift.UnexpandedPC", + "stage3.spartan_shift.opening.UnexpandedPC", + "UnexpandedPC", + 1, + ), + ( + "stage6.input.stage3.instruction_input.InstructionFlagLeftOperandIsRs1Value", + "stage3.instruction_input.opening.InstructionFlagLeftOperandIsRs1Value", + "InstructionFlagLeftOperandIsRs1Value", + 2, + ), + ( + "stage6.input.stage3.instruction_input.InstructionFlagLeftOperandIsPC", + "stage3.instruction_input.opening.InstructionFlagLeftOperandIsPC", + "InstructionFlagLeftOperandIsPC", + 3, + ), + ( + "stage6.input.stage3.instruction_input.InstructionFlagRightOperandIsRs2Value", + "stage3.instruction_input.opening.InstructionFlagRightOperandIsRs2Value", + "InstructionFlagRightOperandIsRs2Value", + 4, + ), + ( + "stage6.input.stage3.instruction_input.InstructionFlagRightOperandIsImm", + "stage3.instruction_input.opening.InstructionFlagRightOperandIsImm", + "InstructionFlagRightOperandIsImm", + 5, + ), + ( + "stage6.input.stage3.spartan_shift.InstructionFlagIsNoop", + "stage3.spartan_shift.opening.InstructionFlagIsNoop", + "InstructionFlagIsNoop", + 6, + ), + ( + "stage6.input.stage3.spartan_shift.OpFlagVirtualInstruction", + "stage3.spartan_shift.opening.OpFlagVirtualInstruction", + "OpFlagVirtualInstruction", + 7, + ), + ( + "stage6.input.stage3.spartan_shift.OpFlagIsFirstInSequence", + "stage3.spartan_shift.opening.OpFlagIsFirstInSequence", + "OpFlagIsFirstInSequence", + 8, + ), + ] { + append_bytecode_term( + context, + module, + params, + &mut bytecode_terms, + BytecodeTermSpec::trace( + symbol, + "stage3", + source_claim, + oracle, + 2, + Some(BytecodeStageGamma::Stage3), + stage_gamma_power, + ), + )?; + } + for (oracle, stage_gamma_power) in [("RdWa", 0), ("Rs1Ra", 1), ("Rs2Ra", 2)] { + append_bytecode_term( + context, + module, + params, + &mut bytecode_terms, + BytecodeTermSpec { + input: StageOpeningInputSpec { + symbol: &format!("stage6.input.stage4.{oracle}"), + source_stage: "stage4", + source_claim: &format!("stage4.registers_read_write.opening.{oracle}"), + oracle, + domain: "jolt.stage4_registers_rw_domain", + point_arity: params.register_log_k + params.log_t, + claim_kind: "virtual", + }, + gamma_power: 3, + stage_gamma: Some(BytecodeStageGamma::Stage4), + stage_gamma_power, + }, + )?; + } + append_bytecode_term( + context, + module, + params, + &mut bytecode_terms, + BytecodeTermSpec { + input: StageOpeningInputSpec { + symbol: "stage6.input.stage5.registers_val_evaluation.RdWa", + source_stage: "stage5", + source_claim: "stage5.registers_val_evaluation.opening.RdWa", + oracle: "RdWa", + domain: "jolt.stage4_registers_rw_domain", + point_arity: params.register_log_k + params.log_t, + claim_kind: "virtual", + }, + gamma_power: 4, + stage_gamma: Some(BytecodeStageGamma::Stage5), + stage_gamma_power: 0, + }, + )?; + append_bytecode_term( + context, + module, + params, + &mut bytecode_terms, + BytecodeTermSpec::trace( + "stage6.input.stage5.InstructionRafFlag", + "stage5", + "stage5.instruction_read_raf.opening.InstructionRafFlag", + "InstructionRafFlag", + 4, + Some(BytecodeStageGamma::Stage5), + 1, + ), + )?; + for index in 0..params.lookup_table_count { + let oracle = format!("LookupTableFlag_{index}"); + append_bytecode_term( + context, + module, + params, + &mut bytecode_terms, + BytecodeTermSpec::trace( + &format!("stage6.input.stage5.{oracle}"), + "stage5", + &format!("stage5.instruction_read_raf.opening.{oracle}"), + &oracle, + 4, + Some(BytecodeStageGamma::Stage5), + 2 + index, + ), + )?; + } + append_bytecode_term( + context, + module, + params, + &mut bytecode_terms, + BytecodeTermSpec::trace( + "stage6.input.stage1.PC", + "stage1", + "stage1.outer_remaining.opening.PC", + "PC", + 5, + None, + 0, + ), + )?; + append_bytecode_term( + context, + module, + params, + &mut bytecode_terms, + BytecodeTermSpec::trace( + "stage6.input.stage3.spartan_shift.PC", + "stage3", + "stage3.spartan_shift.opening.PC", + "PC", + 6, + None, + 0, + ), + )?; + + let ram_ra_virtual = append_stage_input( + context, + module, + StageOpeningInputSpec { + symbol: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", + source_stage: "stage5", + source_claim: "stage5.ram_ra_claim_reduction.opening.RamRa", + oracle: "RamRa", + domain: "jolt.stage2_ram_rw_domain", + point_arity: params.log_k_ram + params.log_t, + claim_kind: "virtual", + }, + )?; + + let mut instruction_ra_virtual = Vec::with_capacity(params.instruction_ra_virtual_d); + for index in 0..params.instruction_ra_virtual_d { + instruction_ra_virtual.push(append_stage_input( + context, + module, + StageOpeningInputSpec { + symbol: &format!("stage6.input.stage5.instruction_read_raf.InstructionRa_{index}"), + source_stage: "stage5", + source_claim: &format!("stage5.instruction_read_raf.opening.InstructionRa_{index}"), + oracle: &format!("InstructionRa_{index}"), + domain: "jolt.stage5_instruction_ra_chunk_domain", + point_arity: params.lookups_ra_virtual_log_k_chunk + params.log_t, + claim_kind: "virtual", + }, + )?); + } + + Ok(Stage6OpeningInputs { + bytecode_terms, + hamming_lookup_output: append_stage_input( + context, + module, + StageOpeningInputSpec { + symbol: "stage6.input.stage1.LookupOutput", + source_stage: "stage1", + source_claim: "stage1.outer_remaining.opening.LookupOutput", + oracle: "LookupOutput", + domain: "jolt.trace_domain", + point_arity: params.log_t, + claim_kind: "virtual", + }, + )?, + ram_ra_virtual, + instruction_ra_virtual, + ram_inc_stage2: append_stage_input( + context, + module, + StageOpeningInputSpec { + symbol: "stage6.input.stage2.ram_read_write.RamInc", + source_stage: "stage2", + source_claim: "stage2.ram_read_write.opening.RamInc", + oracle: "RamInc", + domain: "jolt.trace_domain", + point_arity: params.log_t, + claim_kind: "committed", + }, + )?, + ram_inc_stage4: append_stage_input( + context, + module, + StageOpeningInputSpec { + symbol: "stage6.input.stage4.ram_val_check.RamInc", + source_stage: "stage4", + source_claim: "stage4.ram_val_check.opening.RamInc", + oracle: "RamInc", + domain: "jolt.trace_domain", + point_arity: params.log_t, + claim_kind: "committed", + }, + )?, + rd_inc_stage4: append_stage_input( + context, + module, + StageOpeningInputSpec { + symbol: "stage6.input.stage4.registers_read_write.RdInc", + source_stage: "stage4", + source_claim: "stage4.registers_read_write.opening.RdInc", + oracle: "RdInc", + domain: "jolt.trace_domain", + point_arity: params.log_t, + claim_kind: "committed", + }, + )?, + rd_inc_stage5: append_stage_input( + context, + module, + StageOpeningInputSpec { + symbol: "stage6.input.stage5.registers_val_evaluation.RdInc", + source_stage: "stage5", + source_claim: "stage5.registers_val_evaluation.opening.RdInc", + oracle: "RdInc", + domain: "jolt.trace_domain", + point_arity: params.log_t, + claim_kind: "committed", + }, + )?, + }) +} + +fn append_bytecode_term<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + params: &JoltProtocolParams, + terms: &mut Vec>, + mut spec: BytecodeTermSpec<'_>, +) -> Result<(), MlirError> { + if spec.input.point_arity == 0 { + spec.input.point_arity = params.log_t; + } + let input = append_stage_input(context, module, spec.input)?; + terms.push(Stage6BytecodeTerm { + eval: input.eval, + claim: input.claim, + gamma_power: spec.gamma_power, + stage_gamma: spec.stage_gamma, + stage_gamma_power: spec.stage_gamma_power, + }); + Ok(()) +} + +fn append_stage_input<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + spec: StageOpeningInputSpec<'_>, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "piop.opening_input", + Some(spec.symbol), + &[ + ("source_stage", &format!("@{}", spec.source_stage)), + ("source_claim", &format!("@{}", spec.source_claim)), + ("oracle", &format!("@{}", spec.oracle)), + ("domain", &format!("@{}", spec.domain)), + ("point_arity", &int_attr(spec.point_arity)), + ("claim_kind", &format!("\"{}\"", spec.claim_kind)), + ], + &[], + &["!poly.point", "!field.scalar", "!piop.opening_claim_type"], + )?; + Ok(Stage6OpeningInput { + point: result(op, 0, "piop.opening_input")?, + eval: result(op, 1, "piop.opening_input")?, + claim: result(op, 2, "piop.opening_input")?, + }) +} + +fn append_transcript_squeeze<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + state: Value<'c, 'a>, + symbol: &str, + label: &str, + kind: &str, + count: usize, +) -> Result<(Value<'c, 'a>, Value<'c, 'a>), MlirError> { + let op = context.append_typed_op( + module, + "transcript.squeeze", + Some(symbol), + &[ + ("label", &format!("\"{label}\"")), + ("kind", &format!("\"{kind}\"")), + ("count", &int_attr(count)), + ], + &[state], + &[ + "!transcript.state_type", + transcript_squeeze_protocol_result_type(kind)?, + ], + )?; + Ok(( + result(op, 0, "transcript.squeeze")?, + result(op, 1, "transcript.squeeze")?, + )) +} + +fn append_booleanity_power_placeholders<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + params: &JoltProtocolParams, + booleanity_gamma: Value<'c, 'a>, +) -> Result<(), MlirError> { + let total = total_ra_oracles(params); + for index in 0..total { + let _ = append_field_pow( + context, + module, + &format!("stage6.booleanity.gamma_sq_{index}"), + booleanity_gamma, + 2 * index, + )?; + } + for index in 0..total { + let _ = append_field_pow( + context, + module, + &format!("stage6.booleanity.gamma_pow_{index}"), + booleanity_gamma, + index, + )?; + } + Ok(()) +} + +fn append_stage6_batched_sumcheck<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + params: &JoltProtocolParams, + spec: Stage6BatchedSumcheckInputs<'c, 'a, '_>, +) -> Result, MlirError> { + let inputs = spec.openings; + let bytecode_claim = append_bytecode_read_raf_claim(context, module, inputs, &spec)?; + let zero = append_field_zero(context, module, "stage6.zero")?; + let ram_ra_virtual_claim = inputs.ram_ra_virtual.eval; + let inst_ra_virtual_claim = + append_instruction_ra_virtual_claim(context, module, inputs, spec.inst_ra_gamma)?; + let inc_claim = append_inc_claim_reduction_claim(context, module, inputs, spec.inc_gamma)?; + + let bytecode_inputs = inputs + .bytecode_terms + .iter() + .map(|term| term.claim) + .collect::>(); + let instruction_inputs = inputs + .instruction_ra_virtual + .iter() + .map(|input| input.claim) + .collect::>(); + let inc_inputs = [ + inputs.ram_inc_stage2.claim, + inputs.ram_inc_stage4.claim, + inputs.rd_inc_stage4.claim, + inputs.rd_inc_stage5.claim, + ]; + let claims = [ + append_sumcheck_claim( + context, + module, + SumcheckClaimSpec { + symbol: "stage6.bytecode_read_raf.input", + stage: "stage6", + domain: "jolt.stage6_bytecode_read_raf_domain", + num_rounds: stage6_max_rounds(params), + degree: params.bytecode_d + 1, + claim: "stage6.bytecode_read_raf.weighted_prior_stage_values", + relation: "jolt.stage6.bytecode_read_raf", + }, + bytecode_claim, + &bytecode_inputs, + )?, + append_sumcheck_claim( + context, + module, + SumcheckClaimSpec { + symbol: "stage6.booleanity.input", + stage: "stage6", + domain: "jolt.stage6_booleanity_domain", + num_rounds: booleanity_rounds(params), + degree: BOOLEANITY_DEGREE, + claim: "stage6.booleanity.zero", + relation: "jolt.stage6.booleanity", + }, + zero, + &[], + )?, + append_sumcheck_claim( + context, + module, + SumcheckClaimSpec { + symbol: "stage6.hamming_booleanity.input", + stage: "stage6", + domain: "jolt.trace_domain", + num_rounds: params.log_t, + degree: HAMMING_BOOLEANITY_DEGREE, + claim: "stage6.hamming_booleanity.zero", + relation: "jolt.stage6.hamming_booleanity", + }, + zero, + &[inputs.hamming_lookup_output.claim], + )?, + append_sumcheck_claim( + context, + module, + SumcheckClaimSpec { + symbol: "stage6.ram_ra_virtual.input", + stage: "stage6", + domain: "jolt.trace_domain", + num_rounds: params.log_t, + degree: params.ram_d + 1, + claim: "stage6.ram_ra_virtual.weighted_ram_ra", + relation: "jolt.stage6.ram_ra_virtual", + }, + ram_ra_virtual_claim, + &[inputs.ram_ra_virtual.claim], + )?, + append_sumcheck_claim( + context, + module, + SumcheckClaimSpec { + symbol: "stage6.instruction_ra_virtual.input", + stage: "stage6", + domain: "jolt.trace_domain", + num_rounds: params.log_t, + degree: n_committed_per_virtual(params) + 1, + claim: "stage6.instruction_ra_virtual.weighted_instruction_ra", + relation: "jolt.stage6.instruction_ra_virtual", + }, + inst_ra_virtual_claim, + &instruction_inputs, + )?, + append_sumcheck_claim( + context, + module, + SumcheckClaimSpec { + symbol: "stage6.inc_claim_reduction.input", + stage: "stage6", + domain: "jolt.trace_domain", + num_rounds: params.log_t, + degree: INC_CLAIM_REDUCTION_DEGREE, + claim: "stage6.inc_claim_reduction.weighted_increments", + relation: "jolt.stage6.inc_claim_reduction", + }, + inc_claim, + &inc_inputs, + )?, + ]; + let round_schedule = format!("[{}, {}]", params.log_k_bytecode, params.log_t); + let batch = append_sumcheck_batch( + context, + module, + spec.stage, + &claims, + SumcheckBatchSpec { + symbol: "stage6.batch", + stage: "stage6", + proof_slot: "stage6.sumcheck", + policy: "jolt_core_stage6_aligned", + ordered_claims: &[ + "stage6.bytecode_read_raf.input", + "stage6.booleanity.input", + "stage6.hamming_booleanity.input", + "stage6.ram_ra_virtual.input", + "stage6.instruction_ra_virtual.input", + "stage6.inc_claim_reduction.input", + ], + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + round_schedule: &round_schedule, + }, + )?; + let (state, point, result_value) = append_sumcheck( + context, + module, + spec.state, + batch, + SumcheckDriverSpec { + symbol: "stage6.sumcheck", + stage: "stage6", + proof_slot: "stage6.sumcheck", + relation: "jolt.stage6.batched", + policy: "jolt_core_stage6_aligned", + round_schedule: &round_schedule, + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + num_rounds: stage6_max_rounds(params), + degree: stage6_batched_degree(params), + }, + )?; + let bytecode = append_sumcheck_instance_result( + context, + module, + SumcheckInstanceResultSpec { + symbol: "stage6.bytecode_read_raf.instance", + source: "stage6.sumcheck", + claim: "stage6.bytecode_read_raf.input", + relation: "jolt.stage6.bytecode_read_raf", + index: 0, + point_arity: stage6_max_rounds(params), + num_rounds: stage6_max_rounds(params), + round_offset: 0, + point_order: "bytecode_read_raf", + degree: params.bytecode_d + 1, + }, + point, + result_value, + )?; + let booleanity = append_sumcheck_instance_result( + context, + module, + SumcheckInstanceResultSpec { + symbol: "stage6.booleanity.instance", + source: "stage6.sumcheck", + claim: "stage6.booleanity.input", + relation: "jolt.stage6.booleanity", + index: 1, + point_arity: booleanity_rounds(params), + num_rounds: booleanity_rounds(params), + round_offset: params.log_k_bytecode.saturating_sub(params.log_k_chunk), + point_order: "stage6_booleanity", + degree: BOOLEANITY_DEGREE, + }, + point, + result_value, + )?; + let hamming = append_stage6_trace_instance_result( + context, + module, + params, + point, + result_value, + Stage6TraceInstanceSpec { + symbol: "stage6.hamming_booleanity.instance", + claim: "stage6.hamming_booleanity.input", + relation: "jolt.stage6.hamming_booleanity", + index: 2, + degree: HAMMING_BOOLEANITY_DEGREE, + }, + )?; + let ram = append_stage6_trace_instance_result( + context, + module, + params, + point, + result_value, + Stage6TraceInstanceSpec { + symbol: "stage6.ram_ra_virtual.instance", + claim: "stage6.ram_ra_virtual.input", + relation: "jolt.stage6.ram_ra_virtual", + index: 3, + degree: params.ram_d + 1, + }, + )?; + let instruction = append_stage6_trace_instance_result( + context, + module, + params, + point, + result_value, + Stage6TraceInstanceSpec { + symbol: "stage6.instruction_ra_virtual.instance", + claim: "stage6.instruction_ra_virtual.input", + relation: "jolt.stage6.instruction_ra_virtual", + index: 4, + degree: n_committed_per_virtual(params) + 1, + }, + )?; + let inc = append_stage6_trace_instance_result( + context, + module, + params, + point, + result_value, + Stage6TraceInstanceSpec { + symbol: "stage6.inc_claim_reduction.instance", + claim: "stage6.inc_claim_reduction.input", + relation: "jolt.stage6.inc_claim_reduction", + index: 5, + degree: INC_CLAIM_REDUCTION_DEGREE, + }, + )?; + append_stage6_output_openings( + context, + module, + params, + inputs, + bytecode, + booleanity, + hamming, + ram, + instruction, + inc, + )?; + Ok(state) +} + +fn append_bytecode_read_raf_claim<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + inputs: &Stage6OpeningInputs<'c, 'a>, + spec: &Stage6BatchedSumcheckInputs<'c, 'a, '_>, +) -> Result, MlirError> { + let mut terms = Vec::with_capacity(inputs.bytecode_terms.len() + 1); + for (index, term) in inputs.bytecode_terms.iter().enumerate() { + terms.push(append_weighted_eval( + context, + module, + &format!("stage6.bytecode_read_raf.claim.term{index}"), + term.eval, + WeightedEvalSpec { + gamma: spec.bc_gamma, + gamma_power: term.gamma_power, + stage_gamma: term.stage_gamma.map(|gamma| stage_gamma_value(gamma, spec)), + stage_gamma_power: term.stage_gamma_power, + }, + )?); + } + terms.push(append_field_pow( + context, + module, + "stage6.bytecode_read_raf.claim.entry_constant", + spec.bc_gamma, + 7, + )?); + append_field_sum( + context, + module, + "stage6.bytecode_read_raf.claim_expr", + &terms, + ) +} + +fn append_instruction_ra_virtual_claim<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + inputs: &Stage6OpeningInputs<'c, 'a>, + gamma: Value<'c, 'a>, +) -> Result, MlirError> { + let mut terms = Vec::with_capacity(inputs.instruction_ra_virtual.len()); + for (index, input) in inputs.instruction_ra_virtual.iter().enumerate() { + terms.push(append_weighted_eval( + context, + module, + &format!("stage6.instruction_ra_virtual.claim.term{index}"), + input.eval, + WeightedEvalSpec { + gamma, + gamma_power: index, + stage_gamma: None, + stage_gamma_power: 0, + }, + )?); + } + append_field_sum( + context, + module, + "stage6.instruction_ra_virtual.claim_expr", + &terms, + ) +} + +fn append_inc_claim_reduction_claim<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + inputs: &Stage6OpeningInputs<'c, 'a>, + gamma: Value<'c, 'a>, +) -> Result, MlirError> { + let terms = [ + inputs.ram_inc_stage2.eval, + append_weighted_eval( + context, + module, + "stage6.inc_claim_reduction.claim.ram_inc_stage4", + inputs.ram_inc_stage4.eval, + WeightedEvalSpec { + gamma, + gamma_power: 1, + stage_gamma: None, + stage_gamma_power: 0, + }, + )?, + append_weighted_eval( + context, + module, + "stage6.inc_claim_reduction.claim.rd_inc_stage4", + inputs.rd_inc_stage4.eval, + WeightedEvalSpec { + gamma, + gamma_power: 2, + stage_gamma: None, + stage_gamma_power: 0, + }, + )?, + append_weighted_eval( + context, + module, + "stage6.inc_claim_reduction.claim.rd_inc_stage5", + inputs.rd_inc_stage5.eval, + WeightedEvalSpec { + gamma, + gamma_power: 3, + stage_gamma: None, + stage_gamma_power: 0, + }, + )?, + ]; + append_field_sum( + context, + module, + "stage6.inc_claim_reduction.claim_expr", + &terms, + ) +} + +fn append_weighted_eval<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol_prefix: &str, + eval: Value<'c, 'a>, + spec: WeightedEvalSpec<'c, 'a>, +) -> Result, MlirError> { + let mut value = eval; + if spec.stage_gamma_power > 0 { + let power = append_field_pow( + context, + module, + &format!("{symbol_prefix}.stage_gamma_pow"), + spec.stage_gamma.ok_or_else(|| MlirError::Schema { + message: format!( + "{symbol_prefix} requires stage gamma when stage_gamma_power is non-zero" + ), + })?, + spec.stage_gamma_power, + )?; + value = append_field_mul( + context, + module, + &format!("{symbol_prefix}.stage_gamma_term"), + power, + value, + )?; + } + if spec.gamma_power > 0 { + let power = append_field_pow( + context, + module, + &format!("{symbol_prefix}.gamma_pow"), + spec.gamma, + spec.gamma_power, + )?; + value = append_field_mul( + context, + module, + &format!("{symbol_prefix}.gamma_term"), + power, + value, + )?; + } + Ok(value) +} + +fn stage_gamma_value<'c, 'a>( + gamma: BytecodeStageGamma, + spec: &Stage6BatchedSumcheckInputs<'c, 'a, '_>, +) -> Value<'c, 'a> { + match gamma { + BytecodeStageGamma::Stage1 => spec.bc_stage1_gamma, + BytecodeStageGamma::Stage2 => spec.bc_stage2_gamma, + BytecodeStageGamma::Stage3 => spec.bc_stage3_gamma, + BytecodeStageGamma::Stage4 => spec.bc_stage4_gamma, + BytecodeStageGamma::Stage5 => spec.bc_stage5_gamma, + } +} + +fn append_stage6_trace_instance_result<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + params: &JoltProtocolParams, + point: Value<'c, 'a>, + result_value: Value<'c, 'a>, + spec: Stage6TraceInstanceSpec<'_>, +) -> Result<(Value<'c, 'a>, Value<'c, 'a>), MlirError> { + append_sumcheck_instance_result( + context, + module, + SumcheckInstanceResultSpec { + symbol: spec.symbol, + source: "stage6.sumcheck", + claim: spec.claim, + relation: spec.relation, + index: spec.index, + point_arity: params.log_t, + num_rounds: params.log_t, + round_offset: params.log_k_bytecode, + point_order: "reverse", + degree: spec.degree, + }, + point, + result_value, + ) +} + +#[expect(clippy::too_many_arguments)] +fn append_stage6_output_openings<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + params: &JoltProtocolParams, + inputs: &Stage6OpeningInputs<'c, 'a>, + bytecode: (Value<'c, 'a>, Value<'c, 'a>), + booleanity: (Value<'c, 'a>, Value<'c, 'a>), + hamming: (Value<'c, 'a>, Value<'c, 'a>), + ram: (Value<'c, 'a>, Value<'c, 'a>), + instruction: (Value<'c, 'a>, Value<'c, 'a>), + inc: (Value<'c, 'a>, Value<'c, 'a>), +) -> Result<(), MlirError> { + let mut claims = Vec::new(); + let mut claim_symbols = Vec::new(); + + let bytecode_cycle = append_point_slice( + context, + module, + "stage6.bytecode_read_raf.point.Cycle", + "stage6.bytecode_read_raf.instance", + params.log_k_bytecode, + params.log_t, + bytecode.0, + )?; + for index in 0..params.bytecode_d { + let oracle = format!("BytecodeRa_{index}"); + let eval_symbol = format!("stage6.bytecode_read_raf.eval.{oracle}"); + let eval = append_sumcheck_eval( + context, + module, + &eval_symbol, + "stage6.sumcheck", + &oracle, + index, + bytecode.1, + )?; + let address = append_padded_address_chunk( + context, + module, + &format!("stage6.bytecode_read_raf.point.{oracle}.address"), + "stage6.bytecode_read_raf.instance", + params.log_k_bytecode, + index, + params.log_k_chunk, + bytecode.0, + )?; + let point = append_point_concat( + context, + module, + &format!("stage6.bytecode_read_raf.point.{oracle}"), + "address_chunk_then_cycle", + params.log_k_chunk + params.log_t, + &[address, bytecode_cycle], + )?; + let symbol = format!("stage6.bytecode_read_raf.opening.{oracle}"); + claim_symbols.push(symbol.clone()); + claims.push(append_opening_claim( + context, + module, + point, + eval, + OpeningClaimSpec { + symbol: &symbol, + oracle: &oracle, + domain: "jolt.main_witness_commit_domain", + point_arity: params.log_k_chunk + params.log_t, + claim_kind: "committed", + }, + )?); + } + + let mut eval_index = 0; + for index in 0..params.instruction_d { + append_booleanity_output_opening( + context, + module, + params, + &mut claims, + &mut claim_symbols, + booleanity, + &format!("InstructionRa_{index}"), + eval_index, + )?; + eval_index += 1; + } + for index in 0..params.bytecode_d { + append_booleanity_output_opening( + context, + module, + params, + &mut claims, + &mut claim_symbols, + booleanity, + &format!("BytecodeRa_{index}"), + eval_index, + )?; + eval_index += 1; + } + for index in 0..params.ram_d { + append_booleanity_output_opening( + context, + module, + params, + &mut claims, + &mut claim_symbols, + booleanity, + &format!("RamRa_{index}"), + eval_index, + )?; + eval_index += 1; + } + + let hamming_eval = append_sumcheck_eval( + context, + module, + "stage6.hamming_booleanity.eval.HammingWeight", + "stage6.sumcheck", + "HammingWeight", + 0, + hamming.1, + )?; + claim_symbols.push("stage6.hamming_booleanity.opening.HammingWeight".to_owned()); + claims.push(append_opening_claim( + context, + module, + hamming.0, + hamming_eval, + OpeningClaimSpec { + symbol: "stage6.hamming_booleanity.opening.HammingWeight", + oracle: "HammingWeight", + domain: "jolt.trace_domain", + point_arity: params.log_t, + claim_kind: "virtual", + }, + )?); + + for index in 0..params.ram_d { + let oracle = format!("RamRa_{index}"); + let symbol = format!("stage6.ram_ra_virtual.opening.{oracle}"); + let address = append_padded_address_chunk( + context, + module, + &format!("stage6.ram_ra_virtual.point.{oracle}.address"), + "stage6.input.stage5.ram_ra_claim_reduction.RamRa", + params.log_k_ram, + index, + params.log_k_chunk, + inputs.ram_ra_virtual.point, + )?; + let point = append_point_concat( + context, + module, + &format!("stage6.ram_ra_virtual.point.{oracle}"), + "address_chunk_then_cycle", + params.log_k_chunk + params.log_t, + &[address, ram.0], + )?; + let eval = append_sumcheck_eval( + context, + module, + &format!("stage6.ram_ra_virtual.eval.{oracle}"), + "stage6.sumcheck", + &oracle, + index, + ram.1, + )?; + claim_symbols.push(symbol.clone()); + claims.push(append_opening_claim( + context, + module, + point, + eval, + OpeningClaimSpec { + symbol: &symbol, + oracle: &oracle, + domain: "jolt.main_witness_commit_domain", + point_arity: params.log_k_chunk + params.log_t, + claim_kind: "committed", + }, + )?); + } + for index in 0..params.instruction_d { + let oracle = format!("InstructionRa_{index}"); + let symbol = format!("stage6.instruction_ra_virtual.opening.{oracle}"); + let virtual_index = index / n_committed_per_virtual(params); + let chunk_index = index % n_committed_per_virtual(params); + let virtual_input = inputs.instruction_ra_virtual[virtual_index].point; + let address = append_padded_address_chunk( + context, + module, + &format!("stage6.instruction_ra_virtual.point.{oracle}.address"), + &format!("stage6.input.stage5.instruction_read_raf.InstructionRa_{virtual_index}"), + params.lookups_ra_virtual_log_k_chunk, + chunk_index, + params.log_k_chunk, + virtual_input, + )?; + let point = append_point_concat( + context, + module, + &format!("stage6.instruction_ra_virtual.point.{oracle}"), + "address_chunk_then_cycle", + params.log_k_chunk + params.log_t, + &[address, instruction.0], + )?; + let eval = append_sumcheck_eval( + context, + module, + &format!("stage6.instruction_ra_virtual.eval.{oracle}"), + "stage6.sumcheck", + &oracle, + index, + instruction.1, + )?; + claim_symbols.push(symbol.clone()); + claims.push(append_opening_claim( + context, + module, + point, + eval, + OpeningClaimSpec { + symbol: &symbol, + oracle: &oracle, + domain: "jolt.main_witness_commit_domain", + point_arity: params.log_k_chunk + params.log_t, + claim_kind: "committed", + }, + )?); + } + + for (index, oracle) in ["RamInc", "RdInc"].iter().enumerate() { + let symbol = format!("stage6.inc_claim_reduction.opening.{oracle}"); + let eval = append_sumcheck_eval( + context, + module, + &format!("stage6.inc_claim_reduction.eval.{oracle}"), + "stage6.sumcheck", + oracle, + index, + inc.1, + )?; + claim_symbols.push(symbol.clone()); + claims.push(append_opening_claim( + context, + module, + inc.0, + eval, + OpeningClaimSpec { + symbol: &symbol, + oracle, + domain: "jolt.trace_domain", + point_arity: params.log_t, + claim_kind: "committed", + }, + )?); + } + + let claim_names = claim_symbols.iter().map(String::as_str).collect::>(); + let _batch = context.append_typed_op( + module, + "piop.opening_batch", + Some("stage6.openings"), + &[ + ("stage", "@stage6"), + ("proof_slot", "@stage6.openings"), + ("policy", r#""jolt_stage6_output_order""#), + ("count", &int_attr(claims.len())), + ("ordered_claims", &symbol_array_attr(&claim_names)), + ], + &claims, + &["!piop.opening_batch_type"], + )?; + Ok(()) +} + +#[expect(clippy::too_many_arguments)] +fn append_booleanity_output_opening<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + params: &JoltProtocolParams, + claims: &mut Vec>, + claim_symbols: &mut Vec, + booleanity: (Value<'c, 'a>, Value<'c, 'a>), + oracle: &str, + eval_index: usize, +) -> Result<(), MlirError> { + let symbol = format!("stage6.booleanity.opening.{oracle}"); + let eval = append_sumcheck_eval( + context, + module, + &format!("stage6.booleanity.eval.{oracle}"), + "stage6.sumcheck", + oracle, + eval_index, + booleanity.1, + )?; + claim_symbols.push(symbol.clone()); + claims.push(append_opening_claim( + context, + module, + booleanity.0, + eval, + OpeningClaimSpec { + symbol: &symbol, + oracle, + domain: "jolt.main_witness_commit_domain", + point_arity: booleanity_rounds(params), + claim_kind: "committed", + }, + )?); + Ok(()) +} + +fn append_field_zero<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "field.zero", + Some(symbol), + &[("field", "@bn254_fr")], + &[], + &["!field.scalar"], + )?; + first_result(op, "field.zero") +} + +fn append_field_binary<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + op_name: &str, + symbol: &str, + lhs: Value<'c, 'a>, + rhs: Value<'c, 'a>, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + op_name, + Some(symbol), + &[], + &[lhs, rhs], + &["!field.scalar"], + )?; + first_result(op, op_name) +} + +fn append_field_add<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + lhs: Value<'c, 'a>, + rhs: Value<'c, 'a>, +) -> Result, MlirError> { + append_field_binary(context, module, "field.add", symbol, lhs, rhs) +} + +fn append_field_mul<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + lhs: Value<'c, 'a>, + rhs: Value<'c, 'a>, +) -> Result, MlirError> { + append_field_binary(context, module, "field.mul", symbol, lhs, rhs) +} + +fn append_field_pow<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + base: Value<'c, 'a>, + exponent: usize, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "field.pow", + Some(symbol), + &[("exponent", &int_attr(exponent))], + &[base], + &["!field.scalar"], + )?; + first_result(op, "field.pow") +} + +fn append_field_sum<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol_prefix: &str, + terms: &[Value<'c, 'a>], +) -> Result, MlirError> { + let Some((&first, rest)) = terms.split_first() else { + return append_field_zero(context, module, symbol_prefix); + }; + let mut value = first; + for (index, &term) in rest.iter().enumerate() { + value = append_field_add( + context, + module, + &format!("{symbol_prefix}.partial{index}"), + value, + term, + )?; + } + Ok(value) +} + +fn append_sumcheck_claim<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + spec: SumcheckClaimSpec<'_>, + input_claim: Value<'c, 'a>, + inputs: &[Value<'c, 'a>], +) -> Result, MlirError> { + let mut operands = Vec::with_capacity(inputs.len() + 1); + operands.push(input_claim); + operands.extend_from_slice(inputs); + let op = context.append_typed_op( + module, + "piop.sumcheck_claim", + Some(spec.symbol), + &[ + ("stage", &format!("@{}", spec.stage)), + ("domain", &format!("@{}", spec.domain)), + ("num_rounds", &int_attr(spec.num_rounds)), + ("degree", &int_attr(spec.degree)), + ("claim", &format!("@{}", spec.claim)), + ("relation", &format!("@{}", spec.relation)), + ], + &operands, + &["!piop.sumcheck_claim_type"], + )?; + first_result(op, "piop.sumcheck_claim") +} + +fn append_sumcheck_batch<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + stage: Value<'c, 'a>, + claims: &[Value<'c, 'a>], + spec: SumcheckBatchSpec<'_>, +) -> Result, MlirError> { + let mut operands = Vec::with_capacity(claims.len() + 1); + operands.push(stage); + operands.extend_from_slice(claims); + let op = context.append_typed_op( + module, + "piop.sumcheck_batch", + Some(spec.symbol), + &[ + ("stage", &format!("@{}", spec.stage)), + ("proof_slot", &format!("@{}", spec.proof_slot)), + ("policy", &format!("\"{}\"", spec.policy)), + ("count", &int_attr(spec.ordered_claims.len())), + ("ordered_claims", &symbol_array_attr(spec.ordered_claims)), + ("claim_label", &format!("\"{}\"", spec.claim_label)), + ("round_label", &format!("\"{}\"", spec.round_label)), + ("round_schedule", spec.round_schedule), + ], + &operands, + &["!piop.sumcheck_batch_type"], + )?; + first_result(op, "piop.sumcheck_batch") +} + +fn append_sumcheck<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + state: Value<'c, 'a>, + batch: Value<'c, 'a>, + spec: SumcheckDriverSpec<'_>, +) -> Result<(Value<'c, 'a>, Value<'c, 'a>, Value<'c, 'a>), MlirError> { + let op = context.append_typed_op( + module, + "piop.sumcheck", + Some(spec.symbol), + &[ + ("stage", &format!("@{}", spec.stage)), + ("proof_slot", &format!("@{}", spec.proof_slot)), + ("relation", &format!("@{}", spec.relation)), + ("policy", &format!("\"{}\"", spec.policy)), + ("round_schedule", spec.round_schedule), + ("claim_label", &format!("\"{}\"", spec.claim_label)), + ("round_label", &format!("\"{}\"", spec.round_label)), + ("num_rounds", &int_attr(spec.num_rounds)), + ("degree", &int_attr(spec.degree)), + ], + &[state, batch], + &[ + "!transcript.state_type", + "!poly.point", + "!piop.sumcheck_result_type", + "!piop.sumcheck_proof_type", + ], + )?; + Ok(( + result(op, 0, "piop.sumcheck")?, + result(op, 1, "piop.sumcheck")?, + result(op, 2, "piop.sumcheck")?, + )) +} + +fn append_sumcheck_instance_result<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + spec: SumcheckInstanceResultSpec<'_>, + point: Value<'c, 'a>, + result_value: Value<'c, 'a>, +) -> Result<(Value<'c, 'a>, Value<'c, 'a>), MlirError> { + let op = context.append_typed_op( + module, + "piop.sumcheck_instance_result", + Some(spec.symbol), + &[ + ("source", &format!("@{}", spec.source)), + ("claim", &format!("@{}", spec.claim)), + ("relation", &format!("@{}", spec.relation)), + ("index", &int_attr(spec.index)), + ("point_arity", &int_attr(spec.point_arity)), + ("num_rounds", &int_attr(spec.num_rounds)), + ("round_offset", &int_attr(spec.round_offset)), + ("point_order", &format!("\"{}\"", spec.point_order)), + ("degree", &int_attr(spec.degree)), + ], + &[point, result_value], + &["!poly.point", "!piop.sumcheck_result_type"], + )?; + Ok(( + result(op, 0, "piop.sumcheck_instance_result")?, + result(op, 1, "piop.sumcheck_instance_result")?, + )) +} + +fn append_sumcheck_eval<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + source: &str, + oracle: &str, + index: usize, + result_value: Value<'c, 'a>, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "piop.sumcheck_eval", + Some(symbol), + &[ + ("source", &format!("@{}", source)), + ("name", &format!("@{}", symbol)), + ("index", &int_attr(index)), + ("oracle", &format!("@{}", oracle)), + ], + &[result_value], + &["!field.scalar"], + )?; + first_result(op, "piop.sumcheck_eval") +} + +fn append_point_slice<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + source: &str, + offset: usize, + length: usize, + input: Value<'c, 'a>, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "poly.point_slice", + Some(symbol), + &[ + ("source", &format!("@{}", source)), + ("offset", &int_attr(offset)), + ("length", &int_attr(length)), + ], + &[input], + &["!poly.point"], + )?; + first_result(op, "poly.point_slice") +} + +#[expect(clippy::too_many_arguments)] +fn append_padded_address_chunk<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + source: &str, + address_len: usize, + chunk_index: usize, + chunk_len: usize, + input: Value<'c, 'a>, +) -> Result, MlirError> { + let pad_len = (chunk_len - (address_len % chunk_len)) % chunk_len; + let padded_offset = chunk_index * chunk_len; + let zero_len = pad_len.saturating_sub(padded_offset).min(chunk_len); + let source_offset = padded_offset.saturating_sub(pad_len); + let source_len = chunk_len - zero_len; + if source_offset + source_len > address_len { + return Err(schema_error(format!( + "address chunk {chunk_index} exceeds source point @{source}" + ))); + } + + let source_chunk = if source_len == 0 { + None + } else { + let source_symbol = if zero_len == 0 { + symbol.to_owned() + } else { + format!("{symbol}.source") + }; + Some(append_point_slice( + context, + module, + &source_symbol, + source, + source_offset, + source_len, + input, + )?) + }; + + if zero_len == 0 { + return source_chunk.ok_or_else(|| { + schema_error(format!("address chunk {chunk_index} has no source point")) + }); + } + + let zero = append_point_zero(context, module, &format!("{symbol}.zero_pad"), zero_len)?; + let inputs = match source_chunk { + Some(source_chunk) => vec![zero, source_chunk], + None => vec![zero], + }; + append_point_concat( + context, + module, + symbol, + "left_zero_padded_address_chunk", + chunk_len, + &inputs, + ) +} + +fn append_point_zero<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + arity: usize, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "poly.point_zero", + Some(symbol), + &[("field", "@bn254_fr"), ("arity", &int_attr(arity))], + &[], + &["!poly.point"], + )?; + first_result(op, "poly.point_zero") +} + +fn append_point_concat<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + layout: &str, + arity: usize, + inputs: &[Value<'c, 'a>], +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "poly.point_concat", + Some(symbol), + &[ + ("layout", &format!("\"{}\"", layout)), + ("arity", &int_attr(arity)), + ], + inputs, + &["!poly.point"], + )?; + first_result(op, "poly.point_concat") +} + +fn append_opening_claim<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + point: Value<'c, 'a>, + eval: Value<'c, 'a>, + spec: OpeningClaimSpec<'_>, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "piop.opening_claim", + Some(spec.symbol), + &[ + ("oracle", &format!("@{}", spec.oracle)), + ("domain", &format!("@{}", spec.domain)), + ("point_arity", &int_attr(spec.point_arity)), + ("claim_kind", &format!("\"{}\"", spec.claim_kind)), + ], + &[point, eval], + &["!piop.opening_claim_type"], + )?; + first_result(op, "piop.opening_claim") +} + +fn stage6_max_rounds(params: &JoltProtocolParams) -> usize { + params.log_k_bytecode + params.log_t +} + +fn booleanity_rounds(params: &JoltProtocolParams) -> usize { + params.log_k_chunk + params.log_t +} + +fn n_committed_per_virtual(params: &JoltProtocolParams) -> usize { + params.lookups_ra_virtual_log_k_chunk / params.log_k_chunk +} + +fn total_ra_oracles(params: &JoltProtocolParams) -> usize { + params.instruction_d + params.bytecode_d + params.ram_d +} + +fn stage6_batched_degree(params: &JoltProtocolParams) -> usize { + [ + params.bytecode_d + 1, + BOOLEANITY_DEGREE, + HAMMING_BOOLEANITY_DEGREE, + params.ram_d + 1, + n_committed_per_virtual(params) + 1, + INC_CLAIM_REDUCTION_DEGREE, + ] + .into_iter() + .max() + .unwrap_or(INC_CLAIM_REDUCTION_DEGREE) +} + +fn stage6_output_count(params: &JoltProtocolParams) -> usize { + params.bytecode_d + total_ra_oracles(params) + 1 + params.ram_d + params.instruction_d + 2 +} + +fn int_attr(value: usize) -> String { + format!("{value} : i64") +} + +fn symbol_array_attr(values: &[&str]) -> String { + let values = values + .iter() + .map(|value| format!("@{value}")) + .collect::>() + .join(", "); + format!("[{values}]") +} + +fn first_result<'c, 'a>( + op: OperationRef<'c, 'a>, + context: &str, +) -> Result, MlirError> { + result(op, 0, context) +} + +fn result<'c, 'a>( + op: OperationRef<'c, 'a>, + index: usize, + context: &str, +) -> Result, MlirError> { + op.result(index) + .map(Into::into) + .map_err(|_| schema_error(format!("{context} missing result {index}"))) +} + +fn schema_error(message: impl Into) -> MlirError { + SchemaError::new(message).into() +} + +const STAGE1_OP_FLAGS: [&str; 14] = [ + "OpFlagAddOperands", + "OpFlagSubtractOperands", + "OpFlagMultiplyOperands", + "OpFlagLoad", + "OpFlagStore", + "OpFlagJump", + "OpFlagWriteLookupOutputToRD", + "OpFlagVirtualInstruction", + "OpFlagAssert", + "OpFlagDoNotUpdateUnexpandedPC", + "OpFlagAdvice", + "OpFlagIsCompressed", + "OpFlagIsFirstInSequence", + "OpFlagIsLastInSequence", +]; + +struct Stage6BatchedSumcheckInputs<'c, 'a, 'b> { + state: Value<'c, 'a>, + stage: Value<'c, 'a>, + openings: &'b Stage6OpeningInputs<'c, 'a>, + bc_gamma: Value<'c, 'a>, + bc_stage1_gamma: Value<'c, 'a>, + bc_stage2_gamma: Value<'c, 'a>, + bc_stage3_gamma: Value<'c, 'a>, + bc_stage4_gamma: Value<'c, 'a>, + bc_stage5_gamma: Value<'c, 'a>, + inst_ra_gamma: Value<'c, 'a>, + inc_gamma: Value<'c, 'a>, +} + +struct Stage6OpeningInputs<'c, 'a> { + bytecode_terms: Vec>, + hamming_lookup_output: Stage6OpeningInput<'c, 'a>, + ram_ra_virtual: Stage6OpeningInput<'c, 'a>, + instruction_ra_virtual: Vec>, + ram_inc_stage2: Stage6OpeningInput<'c, 'a>, + ram_inc_stage4: Stage6OpeningInput<'c, 'a>, + rd_inc_stage4: Stage6OpeningInput<'c, 'a>, + rd_inc_stage5: Stage6OpeningInput<'c, 'a>, +} + +struct Stage6OpeningInput<'c, 'a> { + point: Value<'c, 'a>, + eval: Value<'c, 'a>, + claim: Value<'c, 'a>, +} + +struct Stage6BytecodeTerm<'c, 'a> { + eval: Value<'c, 'a>, + claim: Value<'c, 'a>, + gamma_power: usize, + stage_gamma: Option, + stage_gamma_power: usize, +} + +struct BytecodeTermSpec<'a> { + input: StageOpeningInputSpec<'a>, + gamma_power: usize, + stage_gamma: Option, + stage_gamma_power: usize, +} + +impl<'a> BytecodeTermSpec<'a> { + fn trace( + symbol: &'a str, + source_stage: &'a str, + source_claim: &'a str, + oracle: &'a str, + gamma_power: usize, + stage_gamma: Option, + stage_gamma_power: usize, + ) -> Self { + Self { + input: StageOpeningInputSpec { + symbol, + source_stage, + source_claim, + oracle, + domain: "jolt.trace_domain", + point_arity: 0, + claim_kind: "virtual", + }, + gamma_power, + stage_gamma, + stage_gamma_power, + } + } +} + +struct WeightedEvalSpec<'c, 'a> { + gamma: Value<'c, 'a>, + gamma_power: usize, + stage_gamma: Option>, + stage_gamma_power: usize, +} + +struct StageOpeningInputSpec<'a> { + symbol: &'a str, + source_stage: &'a str, + source_claim: &'a str, + oracle: &'a str, + domain: &'a str, + point_arity: usize, + claim_kind: &'a str, +} + +struct RelationSpec<'a> { + symbol: &'a str, + kind: &'a str, + domain: &'a str, + num_rounds: usize, + degree: usize, + output_count: usize, +} + +struct SumcheckClaimSpec<'a> { + symbol: &'a str, + stage: &'a str, + domain: &'a str, + num_rounds: usize, + degree: usize, + claim: &'a str, + relation: &'a str, +} + +struct SumcheckBatchSpec<'a> { + symbol: &'a str, + stage: &'a str, + proof_slot: &'a str, + policy: &'a str, + ordered_claims: &'a [&'a str], + claim_label: &'a str, + round_label: &'a str, + round_schedule: &'a str, +} + +struct SumcheckDriverSpec<'a> { + symbol: &'a str, + stage: &'a str, + proof_slot: &'a str, + relation: &'a str, + policy: &'a str, + round_schedule: &'a str, + claim_label: &'a str, + round_label: &'a str, + num_rounds: usize, + degree: usize, +} + +struct SumcheckInstanceResultSpec<'a> { + symbol: &'a str, + source: &'a str, + claim: &'a str, + relation: &'a str, + index: usize, + point_arity: usize, + num_rounds: usize, + round_offset: usize, + point_order: &'a str, + degree: usize, +} + +struct Stage6TraceInstanceSpec<'a> { + symbol: &'a str, + claim: &'a str, + relation: &'a str, + index: usize, + degree: usize, +} + +struct OpeningClaimSpec<'a> { + symbol: &'a str, + oracle: &'a str, + domain: &'a str, + point_arity: usize, + claim_kind: &'a str, +} diff --git a/crates/bolt/src/protocols/jolt/phases/stage7.rs b/crates/bolt/src/protocols/jolt/phases/stage7.rs new file mode 100644 index 0000000000..c37568c3d3 --- /dev/null +++ b/crates/bolt/src/protocols/jolt/phases/stage7.rs @@ -0,0 +1,1095 @@ +use melior::ir::operation::OperationRef; +use melior::ir::Value; + +use crate::ir::{BoltModule, Compute, Party, Protocol}; +use crate::mlir::{verify_module, MeliorContext, MlirError}; +use crate::schema::{verify_protocol_schema, SchemaError}; + +use super::super::oracles; +use super::super::params::JoltProtocolParams; +use super::lowering::{lower_party_to_compute, transcript_squeeze_protocol_result_type}; + +const HAMMING_WEIGHT_CLAIM_REDUCTION_DEGREE: usize = 2; + +pub fn build_stage7_protocol<'c>( + context: &'c MeliorContext, + params: &JoltProtocolParams, +) -> Result, MlirError> { + let module = context.new_module::("jolt.stage7", None); + oracles::append_foundation_ops(context, &module, params)?; + context.append_op_with_owned_attrs( + &module, + "protocol.params", + Some("jolt.params"), + ¶ms.attrs(), + )?; + context.append_op( + &module, + "protocol.boundary", + Some("jolt.stage7"), + &[("roles", r#"["prover", "verifier"]"#)], + )?; + append_stage7_domains(context, &module, params)?; + append_stage7_oracles(context, &module, params)?; + append_stage7_relations(context, &module, params)?; + let inputs = append_stage7_opening_inputs(context, &module, params)?; + + let fs = context.append_typed_op( + &module, + "transcript.state", + Some("fs_after_stage6"), + &[("scheme", "@blake2b_transcript")], + &[], + &["!transcript.state_type"], + )?; + let state = first_result(fs, "transcript.state")?; + let stage = context.append_typed_op( + &module, + "piop.stage", + Some("stage7"), + &[ + ("name", r#""hamming_weight_claim_reduction""#), + ("order", "7 : i64"), + ("roles", r#"["prover", "verifier"]"#), + ], + &[], + &["!piop.stage_type"], + )?; + let stage = first_result(stage, "piop.stage")?; + + let (state, gamma) = append_transcript_squeeze( + context, + &module, + state, + "stage7.hamming_weight_claim_reduction.gamma", + "hamming_weight_claim_reduction_gamma", + "challenge_scalar", + 1, + )?; + let _state = append_stage7_sumcheck( + context, + &module, + params, + Stage7SumcheckInputs { + state, + stage, + openings: &inputs, + gamma, + }, + )?; + + verify_module(&module)?; + verify_protocol_schema(&module)?; + Ok(module) +} + +pub fn lower_stage7_to_compute<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Party>, +) -> Result, MlirError> { + lower_party_to_compute(context, module, "jolt.stage7", "jolt.stage7", "stage7") +} + +fn append_stage7_domains<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + params: &JoltProtocolParams, +) -> Result<(), MlirError> { + append_domain( + context, + module, + "jolt.stage7_hamming_weight_claim_reduction_domain", + params.log_k_chunk, + ) +} + +fn append_domain<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + symbol: &str, + log_size: usize, +) -> Result<(), MlirError> { + context.append_op( + module, + "poly.domain", + Some(symbol), + &[("field", "@bn254_fr"), ("log_size", &int_attr(log_size))], + ) +} + +fn append_stage7_oracles<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + params: &JoltProtocolParams, +) -> Result<(), MlirError> { + append_virtual_oracle(context, module, "HammingWeight", "jolt.trace_domain")?; + for index in 0..params.instruction_d { + append_committed_main_witness_oracle(context, module, &format!("InstructionRa_{index}"))?; + } + for index in 0..params.bytecode_d { + append_committed_main_witness_oracle(context, module, &format!("BytecodeRa_{index}"))?; + } + for index in 0..params.ram_d { + append_committed_main_witness_oracle(context, module, &format!("RamRa_{index}"))?; + } + Ok(()) +} + +fn append_virtual_oracle<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + symbol: &str, + domain: &str, +) -> Result<(), MlirError> { + context.append_op( + module, + "piop.oracle", + Some(symbol), + &[ + ("field", "@bn254_fr"), + ("domain", &format!("@{domain}")), + ("commit_domain", &format!("@{domain}")), + ("visibility", r#""virtual""#), + ("layout", r#""virtual""#), + ], + ) +} + +fn append_committed_main_witness_oracle<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + symbol: &str, +) -> Result<(), MlirError> { + context.append_op( + module, + "piop.oracle", + Some(symbol), + &[ + ("field", "@bn254_fr"), + ("domain", "@jolt.main_witness_commit_domain"), + ("commit_domain", "@jolt.main_witness_commit_domain"), + ("visibility", r#""committed""#), + ("layout", r#""onehot_expanded""#), + ], + ) +} + +fn append_stage7_relations<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + params: &JoltProtocolParams, +) -> Result<(), MlirError> { + append_relation( + context, + module, + RelationSpec { + symbol: "jolt.stage7.hamming_weight_claim_reduction", + kind: "sumcheck", + domain: "jolt.stage7_hamming_weight_claim_reduction_domain", + num_rounds: params.log_k_chunk, + degree: HAMMING_WEIGHT_CLAIM_REDUCTION_DEGREE, + output_count: total_ra_oracles(params), + }, + )?; + append_relation( + context, + module, + RelationSpec { + symbol: "jolt.stage7.batched", + kind: "batched_sumcheck", + domain: "jolt.stage7_hamming_weight_claim_reduction_domain", + num_rounds: params.log_k_chunk, + degree: HAMMING_WEIGHT_CLAIM_REDUCTION_DEGREE, + output_count: total_ra_oracles(params), + }, + ) +} + +fn append_relation<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Protocol>, + spec: RelationSpec<'_>, +) -> Result<(), MlirError> { + context.append_op( + module, + "piop.relation", + Some(spec.symbol), + &[ + ("kind", &format!("\"{}\"", spec.kind)), + ("domain", &format!("@{}", spec.domain)), + ("num_rounds", &int_attr(spec.num_rounds)), + ("degree", &int_attr(spec.degree)), + ("output_count", &int_attr(spec.output_count)), + ], + ) +} + +fn append_stage7_opening_inputs<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + params: &JoltProtocolParams, +) -> Result, MlirError> { + let ram_hamming = append_stage_input( + context, + module, + StageOpeningInputSpec { + symbol: "stage7.input.stage6.hamming_booleanity.HammingWeight", + source_stage: "stage6", + source_claim: "stage6.hamming_booleanity.opening.HammingWeight", + oracle: "HammingWeight", + domain: "jolt.trace_domain", + point_arity: params.log_t, + claim_kind: "virtual", + }, + )?; + + let mut ra_inputs = Vec::with_capacity(total_ra_oracles(params)); + for index in 0..params.instruction_d { + let oracle = format!("InstructionRa_{index}"); + ra_inputs.push(append_ra_inputs( + context, + module, + params, + &oracle, + Stage7RaKind::Instruction, + &format!("stage6.instruction_ra_virtual.opening.{oracle}"), + &format!("stage7.input.stage6.instruction_ra_virtual.{oracle}"), + )?); + } + for index in 0..params.bytecode_d { + let oracle = format!("BytecodeRa_{index}"); + ra_inputs.push(append_ra_inputs( + context, + module, + params, + &oracle, + Stage7RaKind::Bytecode, + &format!("stage6.bytecode_read_raf.opening.{oracle}"), + &format!("stage7.input.stage6.bytecode_read_raf.{oracle}"), + )?); + } + for index in 0..params.ram_d { + let oracle = format!("RamRa_{index}"); + ra_inputs.push(append_ra_inputs( + context, + module, + params, + &oracle, + Stage7RaKind::Ram, + &format!("stage6.ram_ra_virtual.opening.{oracle}"), + &format!("stage7.input.stage6.ram_ra_virtual.{oracle}"), + )?); + } + + let booleanity_point = ra_inputs + .first() + .ok_or_else(|| schema_error("Stage 7 requires at least one RA oracle"))? + .booleanity + .point; + + Ok(Stage7OpeningInputs { + ra_inputs, + ram_hamming, + booleanity_point, + }) +} + +fn append_ra_inputs<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + params: &JoltProtocolParams, + oracle: &str, + kind: Stage7RaKind, + source_virtual_claim: &str, + virtual_input_symbol: &str, +) -> Result, MlirError> { + let booleanity = append_stage_input( + context, + module, + StageOpeningInputSpec { + symbol: &format!("stage7.input.stage6.booleanity.{oracle}"), + source_stage: "stage6", + source_claim: &format!("stage6.booleanity.opening.{oracle}"), + oracle, + domain: "jolt.main_witness_commit_domain", + point_arity: params.log_k_chunk + params.log_t, + claim_kind: "committed", + }, + )?; + let virtualization = append_stage_input( + context, + module, + StageOpeningInputSpec { + symbol: virtual_input_symbol, + source_stage: "stage6", + source_claim: source_virtual_claim, + oracle, + domain: "jolt.main_witness_commit_domain", + point_arity: params.log_k_chunk + params.log_t, + claim_kind: "committed", + }, + )?; + Ok(Stage7RaInput { + oracle: oracle.to_owned(), + kind, + booleanity, + virtualization, + }) +} + +fn append_stage_input<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + spec: StageOpeningInputSpec<'_>, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "piop.opening_input", + Some(spec.symbol), + &[ + ("source_stage", &format!("@{}", spec.source_stage)), + ("source_claim", &format!("@{}", spec.source_claim)), + ("oracle", &format!("@{}", spec.oracle)), + ("domain", &format!("@{}", spec.domain)), + ("point_arity", &int_attr(spec.point_arity)), + ("claim_kind", &format!("\"{}\"", spec.claim_kind)), + ], + &[], + &["!poly.point", "!field.scalar", "!piop.opening_claim_type"], + )?; + Ok(Stage7OpeningInput { + point: result(op, 0, "piop.opening_input")?, + eval: result(op, 1, "piop.opening_input")?, + claim: result(op, 2, "piop.opening_input")?, + }) +} + +fn append_stage7_sumcheck<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + params: &JoltProtocolParams, + spec: Stage7SumcheckInputs<'c, 'a, '_>, +) -> Result, MlirError> { + let input_claim = append_hamming_weight_claim_reduction_input_claim( + context, + module, + spec.openings, + spec.gamma, + )?; + let mut input_openings = Vec::with_capacity(2 * spec.openings.ra_inputs.len() + 1); + input_openings.push(spec.openings.ram_hamming.claim); + for input in &spec.openings.ra_inputs { + input_openings.push(input.booleanity.claim); + input_openings.push(input.virtualization.claim); + } + let claim = append_sumcheck_claim( + context, + module, + SumcheckClaimSpec { + symbol: "stage7.hamming_weight_claim_reduction.input", + stage: "stage7", + domain: "jolt.stage7_hamming_weight_claim_reduction_domain", + num_rounds: params.log_k_chunk, + degree: HAMMING_WEIGHT_CLAIM_REDUCTION_DEGREE, + claim: "stage7.hamming_weight_claim_reduction.weighted_stage6_claims", + relation: "jolt.stage7.hamming_weight_claim_reduction", + }, + input_claim, + &input_openings, + )?; + let round_schedule = format!("[{}]", params.log_k_chunk); + let batch = append_sumcheck_batch( + context, + module, + spec.stage, + &[claim], + SumcheckBatchSpec { + symbol: "stage7.batch", + stage: "stage7", + proof_slot: "stage7.sumcheck", + policy: "jolt_core_stage7_aligned", + ordered_claims: &["stage7.hamming_weight_claim_reduction.input"], + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + round_schedule: &round_schedule, + }, + )?; + let (state, point, result_value) = append_sumcheck( + context, + module, + spec.state, + batch, + SumcheckDriverSpec { + symbol: "stage7.sumcheck", + stage: "stage7", + proof_slot: "stage7.sumcheck", + relation: "jolt.stage7.batched", + policy: "jolt_core_stage7_aligned", + round_schedule: &round_schedule, + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + num_rounds: params.log_k_chunk, + degree: HAMMING_WEIGHT_CLAIM_REDUCTION_DEGREE, + }, + )?; + let instance = append_sumcheck_instance_result( + context, + module, + SumcheckInstanceResultSpec { + symbol: "stage7.hamming_weight_claim_reduction.instance", + source: "stage7.sumcheck", + claim: "stage7.hamming_weight_claim_reduction.input", + relation: "jolt.stage7.hamming_weight_claim_reduction", + index: 0, + point_arity: params.log_k_chunk, + num_rounds: params.log_k_chunk, + round_offset: 0, + point_order: "reverse", + degree: HAMMING_WEIGHT_CLAIM_REDUCTION_DEGREE, + }, + point, + result_value, + )?; + append_stage7_output_openings(context, module, params, spec.openings, instance)?; + Ok(state) +} + +fn append_hamming_weight_claim_reduction_input_claim<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + inputs: &Stage7OpeningInputs<'c, 'a>, + gamma: Value<'c, 'a>, +) -> Result, MlirError> { + let one = append_field_one(context, module, "stage7.field.one")?; + let mut terms = Vec::with_capacity(3 * inputs.ra_inputs.len()); + for (index, input) in inputs.ra_inputs.iter().enumerate() { + let hamming_eval = match input.kind { + Stage7RaKind::Instruction | Stage7RaKind::Bytecode => one, + Stage7RaKind::Ram => inputs.ram_hamming.eval, + }; + terms.push(append_weighted_eval( + context, + module, + &format!("stage7.hamming_weight_claim_reduction.claim.{index}.hw"), + hamming_eval, + gamma, + 3 * index, + )?); + terms.push(append_weighted_eval( + context, + module, + &format!("stage7.hamming_weight_claim_reduction.claim.{index}.booleanity"), + input.booleanity.eval, + gamma, + 3 * index + 1, + )?); + terms.push(append_weighted_eval( + context, + module, + &format!("stage7.hamming_weight_claim_reduction.claim.{index}.virtualization"), + input.virtualization.eval, + gamma, + 3 * index + 2, + )?); + } + append_field_sum( + context, + module, + "stage7.hamming_weight_claim_reduction.claim_expr", + &terms, + ) +} + +fn append_weighted_eval<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol_prefix: &str, + eval: Value<'c, 'a>, + gamma: Value<'c, 'a>, + gamma_power: usize, +) -> Result, MlirError> { + if gamma_power == 0 { + return Ok(eval); + } + let power = append_field_pow( + context, + module, + &format!("{symbol_prefix}.gamma_pow"), + gamma, + gamma_power, + )?; + append_field_mul( + context, + module, + &format!("{symbol_prefix}.gamma_term"), + power, + eval, + ) +} + +fn append_stage7_output_openings<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + params: &JoltProtocolParams, + inputs: &Stage7OpeningInputs<'c, 'a>, + instance: (Value<'c, 'a>, Value<'c, 'a>), +) -> Result<(), MlirError> { + let cycle = append_point_slice( + context, + module, + "stage7.hamming_weight_claim_reduction.point.cycle", + "stage7.input.stage6.booleanity.InstructionRa_0", + params.log_k_chunk, + params.log_t, + inputs.booleanity_point, + )?; + let full_point = append_point_concat( + context, + module, + "stage7.hamming_weight_claim_reduction.point", + "address_chunk_then_cycle", + params.log_k_chunk + params.log_t, + &[instance.0, cycle], + )?; + + let mut claims = Vec::with_capacity(inputs.ra_inputs.len()); + let mut claim_symbols = Vec::with_capacity(inputs.ra_inputs.len()); + for (index, input) in inputs.ra_inputs.iter().enumerate() { + let eval = append_sumcheck_eval( + context, + module, + &format!( + "stage7.hamming_weight_claim_reduction.eval.{}", + input.oracle + ), + "stage7.sumcheck", + &input.oracle, + index, + instance.1, + )?; + let symbol = format!( + "stage7.hamming_weight_claim_reduction.opening.{}", + input.oracle + ); + claim_symbols.push(symbol.clone()); + claims.push(append_opening_claim( + context, + module, + full_point, + eval, + OpeningClaimSpec { + symbol: &symbol, + oracle: &input.oracle, + domain: "jolt.main_witness_commit_domain", + point_arity: params.log_k_chunk + params.log_t, + claim_kind: "committed", + }, + )?); + } + let claim_names = claim_symbols.iter().map(String::as_str).collect::>(); + let _batch = context.append_typed_op( + module, + "piop.opening_batch", + Some("stage7.openings"), + &[ + ("stage", "@stage7"), + ("proof_slot", "@stage7.openings"), + ("policy", r#""jolt_stage7_output_order""#), + ("count", &int_attr(claims.len())), + ("ordered_claims", &symbol_array_attr(&claim_names)), + ], + &claims, + &["!piop.opening_batch_type"], + )?; + Ok(()) +} + +fn append_transcript_squeeze<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + state: Value<'c, 'a>, + symbol: &str, + label: &str, + kind: &str, + count: usize, +) -> Result<(Value<'c, 'a>, Value<'c, 'a>), MlirError> { + let op = context.append_typed_op( + module, + "transcript.squeeze", + Some(symbol), + &[ + ("label", &format!("\"{label}\"")), + ("kind", &format!("\"{kind}\"")), + ("count", &int_attr(count)), + ], + &[state], + &[ + "!transcript.state_type", + transcript_squeeze_protocol_result_type(kind)?, + ], + )?; + Ok(( + result(op, 0, "transcript.squeeze")?, + result(op, 1, "transcript.squeeze")?, + )) +} + +fn append_field_one<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "field.one", + Some(symbol), + &[("field", "@bn254_fr")], + &[], + &["!field.scalar"], + )?; + first_result(op, "field.one") +} + +fn append_field_binary<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + op_name: &str, + symbol: &str, + lhs: Value<'c, 'a>, + rhs: Value<'c, 'a>, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + op_name, + Some(symbol), + &[], + &[lhs, rhs], + &["!field.scalar"], + )?; + first_result(op, op_name) +} + +fn append_field_add<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + lhs: Value<'c, 'a>, + rhs: Value<'c, 'a>, +) -> Result, MlirError> { + append_field_binary(context, module, "field.add", symbol, lhs, rhs) +} + +fn append_field_mul<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + lhs: Value<'c, 'a>, + rhs: Value<'c, 'a>, +) -> Result, MlirError> { + append_field_binary(context, module, "field.mul", symbol, lhs, rhs) +} + +fn append_field_pow<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + base: Value<'c, 'a>, + exponent: usize, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "field.pow", + Some(symbol), + &[("exponent", &int_attr(exponent))], + &[base], + &["!field.scalar"], + )?; + first_result(op, "field.pow") +} + +fn append_field_sum<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol_prefix: &str, + terms: &[Value<'c, 'a>], +) -> Result, MlirError> { + let Some((&first, rest)) = terms.split_first() else { + return append_field_one(context, module, symbol_prefix); + }; + let mut value = first; + for (index, &term) in rest.iter().enumerate() { + value = append_field_add( + context, + module, + &format!("{symbol_prefix}.partial{index}"), + value, + term, + )?; + } + Ok(value) +} + +fn append_sumcheck_claim<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + spec: SumcheckClaimSpec<'_>, + input_claim: Value<'c, 'a>, + inputs: &[Value<'c, 'a>], +) -> Result, MlirError> { + let mut operands = Vec::with_capacity(inputs.len() + 1); + operands.push(input_claim); + operands.extend_from_slice(inputs); + let op = context.append_typed_op( + module, + "piop.sumcheck_claim", + Some(spec.symbol), + &[ + ("stage", &format!("@{}", spec.stage)), + ("domain", &format!("@{}", spec.domain)), + ("num_rounds", &int_attr(spec.num_rounds)), + ("degree", &int_attr(spec.degree)), + ("claim", &format!("@{}", spec.claim)), + ("relation", &format!("@{}", spec.relation)), + ], + &operands, + &["!piop.sumcheck_claim_type"], + )?; + first_result(op, "piop.sumcheck_claim") +} + +fn append_sumcheck_batch<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + stage: Value<'c, 'a>, + claims: &[Value<'c, 'a>], + spec: SumcheckBatchSpec<'_>, +) -> Result, MlirError> { + let mut operands = Vec::with_capacity(claims.len() + 1); + operands.push(stage); + operands.extend_from_slice(claims); + let op = context.append_typed_op( + module, + "piop.sumcheck_batch", + Some(spec.symbol), + &[ + ("stage", &format!("@{}", spec.stage)), + ("proof_slot", &format!("@{}", spec.proof_slot)), + ("policy", &format!("\"{}\"", spec.policy)), + ("count", &int_attr(spec.ordered_claims.len())), + ("ordered_claims", &symbol_array_attr(spec.ordered_claims)), + ("claim_label", &format!("\"{}\"", spec.claim_label)), + ("round_label", &format!("\"{}\"", spec.round_label)), + ("round_schedule", spec.round_schedule), + ], + &operands, + &["!piop.sumcheck_batch_type"], + )?; + first_result(op, "piop.sumcheck_batch") +} + +fn append_sumcheck<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + state: Value<'c, 'a>, + batch: Value<'c, 'a>, + spec: SumcheckDriverSpec<'_>, +) -> Result<(Value<'c, 'a>, Value<'c, 'a>, Value<'c, 'a>), MlirError> { + let op = context.append_typed_op( + module, + "piop.sumcheck", + Some(spec.symbol), + &[ + ("stage", &format!("@{}", spec.stage)), + ("proof_slot", &format!("@{}", spec.proof_slot)), + ("relation", &format!("@{}", spec.relation)), + ("policy", &format!("\"{}\"", spec.policy)), + ("round_schedule", spec.round_schedule), + ("claim_label", &format!("\"{}\"", spec.claim_label)), + ("round_label", &format!("\"{}\"", spec.round_label)), + ("num_rounds", &int_attr(spec.num_rounds)), + ("degree", &int_attr(spec.degree)), + ], + &[state, batch], + &[ + "!transcript.state_type", + "!poly.point", + "!piop.sumcheck_result_type", + "!piop.sumcheck_proof_type", + ], + )?; + Ok(( + result(op, 0, "piop.sumcheck")?, + result(op, 1, "piop.sumcheck")?, + result(op, 2, "piop.sumcheck")?, + )) +} + +fn append_sumcheck_instance_result<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + spec: SumcheckInstanceResultSpec<'_>, + point: Value<'c, 'a>, + result_value: Value<'c, 'a>, +) -> Result<(Value<'c, 'a>, Value<'c, 'a>), MlirError> { + let op = context.append_typed_op( + module, + "piop.sumcheck_instance_result", + Some(spec.symbol), + &[ + ("source", &format!("@{}", spec.source)), + ("claim", &format!("@{}", spec.claim)), + ("relation", &format!("@{}", spec.relation)), + ("index", &int_attr(spec.index)), + ("point_arity", &int_attr(spec.point_arity)), + ("num_rounds", &int_attr(spec.num_rounds)), + ("round_offset", &int_attr(spec.round_offset)), + ("point_order", &format!("\"{}\"", spec.point_order)), + ("degree", &int_attr(spec.degree)), + ], + &[point, result_value], + &["!poly.point", "!piop.sumcheck_result_type"], + )?; + Ok(( + result(op, 0, "piop.sumcheck_instance_result")?, + result(op, 1, "piop.sumcheck_instance_result")?, + )) +} + +fn append_sumcheck_eval<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + source: &str, + oracle: &str, + index: usize, + result_value: Value<'c, 'a>, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "piop.sumcheck_eval", + Some(symbol), + &[ + ("source", &format!("@{}", source)), + ("name", &format!("@{}", symbol)), + ("index", &int_attr(index)), + ("oracle", &format!("@{}", oracle)), + ], + &[result_value], + &["!field.scalar"], + )?; + first_result(op, "piop.sumcheck_eval") +} + +fn append_point_slice<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + source: &str, + offset: usize, + length: usize, + input: Value<'c, 'a>, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "poly.point_slice", + Some(symbol), + &[ + ("source", &format!("@{}", source)), + ("offset", &int_attr(offset)), + ("length", &int_attr(length)), + ], + &[input], + &["!poly.point"], + )?; + first_result(op, "poly.point_slice") +} + +fn append_point_concat<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + symbol: &str, + layout: &str, + arity: usize, + inputs: &[Value<'c, 'a>], +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "poly.point_concat", + Some(symbol), + &[ + ("layout", &format!("\"{}\"", layout)), + ("arity", &int_attr(arity)), + ], + inputs, + &["!poly.point"], + )?; + first_result(op, "poly.point_concat") +} + +fn append_opening_claim<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + point: Value<'c, 'a>, + eval: Value<'c, 'a>, + spec: OpeningClaimSpec<'_>, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "piop.opening_claim", + Some(spec.symbol), + &[ + ("oracle", &format!("@{}", spec.oracle)), + ("domain", &format!("@{}", spec.domain)), + ("point_arity", &int_attr(spec.point_arity)), + ("claim_kind", &format!("\"{}\"", spec.claim_kind)), + ], + &[point, eval], + &["!piop.opening_claim_type"], + )?; + first_result(op, "piop.opening_claim") +} + +fn total_ra_oracles(params: &JoltProtocolParams) -> usize { + params.instruction_d + params.bytecode_d + params.ram_d +} + +fn int_attr(value: usize) -> String { + format!("{value} : i64") +} + +fn symbol_array_attr(values: &[&str]) -> String { + let values = values + .iter() + .map(|value| format!("@{value}")) + .collect::>() + .join(", "); + format!("[{values}]") +} + +fn first_result<'c, 'a>( + op: OperationRef<'c, 'a>, + context: &str, +) -> Result, MlirError> { + result(op, 0, context) +} + +fn result<'c, 'a>( + op: OperationRef<'c, 'a>, + index: usize, + context: &str, +) -> Result, MlirError> { + op.result(index) + .map(Into::into) + .map_err(|_| schema_error(format!("{context} missing result {index}"))) +} + +fn schema_error(message: impl Into) -> MlirError { + SchemaError::new(message).into() +} + +#[derive(Clone, Copy)] +enum Stage7RaKind { + Instruction, + Bytecode, + Ram, +} + +struct Stage7SumcheckInputs<'c, 'a, 'b> { + state: Value<'c, 'a>, + stage: Value<'c, 'a>, + openings: &'b Stage7OpeningInputs<'c, 'a>, + gamma: Value<'c, 'a>, +} + +struct Stage7OpeningInputs<'c, 'a> { + ra_inputs: Vec>, + ram_hamming: Stage7OpeningInput<'c, 'a>, + booleanity_point: Value<'c, 'a>, +} + +struct Stage7RaInput<'c, 'a> { + oracle: String, + kind: Stage7RaKind, + booleanity: Stage7OpeningInput<'c, 'a>, + virtualization: Stage7OpeningInput<'c, 'a>, +} + +struct Stage7OpeningInput<'c, 'a> { + point: Value<'c, 'a>, + eval: Value<'c, 'a>, + claim: Value<'c, 'a>, +} + +struct StageOpeningInputSpec<'a> { + symbol: &'a str, + source_stage: &'a str, + source_claim: &'a str, + oracle: &'a str, + domain: &'a str, + point_arity: usize, + claim_kind: &'a str, +} + +struct RelationSpec<'a> { + symbol: &'a str, + kind: &'a str, + domain: &'a str, + num_rounds: usize, + degree: usize, + output_count: usize, +} + +struct SumcheckClaimSpec<'a> { + symbol: &'a str, + stage: &'a str, + domain: &'a str, + num_rounds: usize, + degree: usize, + claim: &'a str, + relation: &'a str, +} + +struct SumcheckBatchSpec<'a> { + symbol: &'a str, + stage: &'a str, + proof_slot: &'a str, + policy: &'a str, + ordered_claims: &'a [&'a str], + claim_label: &'a str, + round_label: &'a str, + round_schedule: &'a str, +} + +struct SumcheckDriverSpec<'a> { + symbol: &'a str, + stage: &'a str, + proof_slot: &'a str, + relation: &'a str, + policy: &'a str, + round_schedule: &'a str, + claim_label: &'a str, + round_label: &'a str, + num_rounds: usize, + degree: usize, +} + +struct SumcheckInstanceResultSpec<'a> { + symbol: &'a str, + source: &'a str, + claim: &'a str, + relation: &'a str, + index: usize, + point_arity: usize, + num_rounds: usize, + round_offset: usize, + point_order: &'a str, + degree: usize, +} + +struct OpeningClaimSpec<'a> { + symbol: &'a str, + oracle: &'a str, + domain: &'a str, + point_arity: usize, + claim_kind: &'a str, +} diff --git a/crates/bolt/src/protocols/jolt/phases/stage8.rs b/crates/bolt/src/protocols/jolt/phases/stage8.rs new file mode 100644 index 0000000000..97ed373918 --- /dev/null +++ b/crates/bolt/src/protocols/jolt/phases/stage8.rs @@ -0,0 +1,293 @@ +use melior::ir::operation::{OperationLike, OperationRef}; +use melior::ir::Value; + +use crate::ir::{BoltModule, Compute, Party, Protocol}; +use crate::mlir::{verify_module, MeliorContext, MlirError}; +use crate::schema::{verify_protocol_schema, SchemaError}; + +use super::super::oracles; +use super::super::params::JoltProtocolParams; +use super::lowering::lower_party_to_compute; + +const EVALUATION_POINT_SOURCE_SYMBOL: &str = "stage8.evaluation.point_source"; + +pub fn build_stage8_protocol<'c>( + context: &'c MeliorContext, + params: &JoltProtocolParams, +) -> Result, MlirError> { + let module = context.new_module::("jolt.stage8", None); + oracles::append_foundation_ops(context, &module, params)?; + oracles::append_committed_oracles(context, &module, params)?; + context.append_op_with_owned_attrs( + &module, + "protocol.params", + Some("jolt.params"), + ¶ms.attrs(), + )?; + context.append_op( + &module, + "protocol.boundary", + Some("jolt.stage8"), + &[("roles", r#"["prover", "verifier"]"#)], + )?; + + let fs = context.append_typed_op( + &module, + "transcript.state", + Some("fs_after_stage7"), + &[("scheme", "@blake2b_transcript")], + &[], + &["!transcript.state_type"], + )?; + let state = result(fs, 0, "transcript.state")?; + let _stage = context.append_typed_op( + &module, + "piop.stage", + Some("stage8"), + &[ + ("name", r#""evaluation_proof""#), + ("order", "8 : i64"), + ("roles", r#"["prover", "verifier"]"#), + ], + &[], + &["!piop.stage_type"], + )?; + + let _point_source = append_opening_input( + context, + &module, + Stage8OpeningInputSpec { + symbol: EVALUATION_POINT_SOURCE_SYMBOL, + source_stage: "stage7", + source_claim: "stage7.input.stage6.booleanity.InstructionRa_0", + oracle: "InstructionRa_0", + point_arity: params.log_t + params.log_k_chunk, + }, + )?; + let mut claims = Vec::new(); + let mut claim_symbols = Vec::new(); + append_evaluation_claim( + context, + &module, + params, + &mut claims, + &mut claim_symbols, + Stage8EvaluationClaimSpec { + oracle: "RamInc", + source_stage: "stage6", + source_claim: "stage6.inc_claim_reduction.eval.RamInc", + }, + )?; + append_evaluation_claim( + context, + &module, + params, + &mut claims, + &mut claim_symbols, + Stage8EvaluationClaimSpec { + oracle: "RdInc", + source_stage: "stage6", + source_claim: "stage6.inc_claim_reduction.eval.RdInc", + }, + )?; + for index in 0..params.instruction_d { + append_evaluation_claim( + context, + &module, + params, + &mut claims, + &mut claim_symbols, + Stage8EvaluationClaimSpec { + oracle: &format!("InstructionRa_{index}"), + source_stage: "stage7", + source_claim: &format!( + "stage7.hamming_weight_claim_reduction.eval.InstructionRa_{index}" + ), + }, + )?; + } + for index in 0..params.bytecode_d { + append_evaluation_claim( + context, + &module, + params, + &mut claims, + &mut claim_symbols, + Stage8EvaluationClaimSpec { + oracle: &format!("BytecodeRa_{index}"), + source_stage: "stage7", + source_claim: &format!( + "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_{index}" + ), + }, + )?; + } + for index in 0..params.ram_d { + append_evaluation_claim( + context, + &module, + params, + &mut claims, + &mut claim_symbols, + Stage8EvaluationClaimSpec { + oracle: &format!("RamRa_{index}"), + source_stage: "stage7", + source_claim: &format!("stage7.hamming_weight_claim_reduction.eval.RamRa_{index}"), + }, + )?; + } + + let opening_batch = context.append_typed_op( + &module, + "pcs.opening_batch", + Some("stage8.evaluation.openings"), + &[ + ("proof_slot", "@stage8.evaluation"), + ("policy", r#""jolt_stage8_joint_rlc""#), + ("count", &int_attr(claims.len())), + ("ordered_claims", &symbol_array_attr(&claim_symbols)), + ], + &claims, + &["!pcs.opening_batch_type"], + )?; + let opening_batch = result(opening_batch, 0, "pcs.opening_batch")?; + let _state = context.append_typed_op( + &module, + "pcs.batch_open", + Some("stage8.evaluation.proof"), + &[ + ("pcs", "@dory"), + ("proof_slot", "@stage8.evaluation"), + ("transcript_label", r#""rlc_claims""#), + ], + &[state, opening_batch], + &["!transcript.state_type", "!pcs.opening_proof_type"], + )?; + + verify_module(&module)?; + verify_protocol_schema(&module)?; + Ok(module) +} + +pub fn lower_stage8_to_compute<'c>( + context: &'c MeliorContext, + module: &BoltModule<'c, Party>, +) -> Result, MlirError> { + lower_party_to_compute(context, module, "jolt.stage8", "jolt.stage8", "stage8") +} + +fn append_evaluation_claim<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + params: &JoltProtocolParams, + claims: &mut Vec>, + claim_symbols: &mut Vec, + spec: Stage8EvaluationClaimSpec<'_>, +) -> Result<(), MlirError> { + let input_symbol = format!("stage8.input.{}.{}", spec.source_stage, spec.oracle); + let opening_input = append_opening_input( + context, + module, + Stage8OpeningInputSpec { + symbol: &input_symbol, + source_stage: spec.source_stage, + source_claim: spec.source_claim, + oracle: spec.oracle, + point_arity: params.log_t + params.log_k_chunk, + }, + )?; + let opening_symbol = format!("stage8.evaluation.opening.{}", spec.oracle); + let opening = context.append_typed_op( + module, + "pcs.opening_claim", + Some(&opening_symbol), + &[ + ("oracle", &format!("@{}", spec.oracle)), + ("family", "@jolt.main_witness_polys"), + ("domain", "@jolt.main_witness_commit_domain"), + ("point_arity", &int_attr(params.log_t + params.log_k_chunk)), + ], + &[opening_input.point, opening_input.eval], + &["!pcs.opening_claim_type"], + )?; + claims.push(result(opening, 0, "pcs.opening_claim")?); + claim_symbols.push(opening_symbol); + Ok(()) +} + +fn append_opening_input<'c, 'a>( + context: &'c MeliorContext, + module: &'a BoltModule<'c, Protocol>, + spec: Stage8OpeningInputSpec<'_>, +) -> Result, MlirError> { + let op = context.append_typed_op( + module, + "piop.opening_input", + Some(spec.symbol), + &[ + ("source_stage", &format!("@{}", spec.source_stage)), + ("source_claim", &format!("@{}", spec.source_claim)), + ("oracle", &format!("@{}", spec.oracle)), + ("domain", "@jolt.main_witness_commit_domain"), + ("point_arity", &int_attr(spec.point_arity)), + ("claim_kind", r#""committed""#), + ], + &[], + &["!poly.point", "!field.scalar", "!piop.opening_claim_type"], + )?; + Ok(Stage8OpeningInput { + point: result(op, 0, "piop.opening_input")?, + eval: result(op, 1, "piop.opening_input")?, + }) +} + +#[derive(Clone, Copy)] +struct Stage8OpeningInputSpec<'a> { + symbol: &'a str, + source_stage: &'a str, + source_claim: &'a str, + oracle: &'a str, + point_arity: usize, +} + +#[derive(Clone, Copy)] +struct Stage8EvaluationClaimSpec<'a> { + oracle: &'a str, + source_stage: &'a str, + source_claim: &'a str, +} + +struct Stage8OpeningInput<'c, 'a> { + point: Value<'c, 'a>, + eval: Value<'c, 'a>, +} + +fn result<'c, 'a>( + operation: OperationRef<'c, 'a>, + index: usize, + op_name: &str, +) -> Result, MlirError> { + operation.result(index).map(Into::into).map_err(|_| { + schema_error(format!( + "{op_name} requires result {index}, got {} results", + operation.result_count() + )) + }) +} + +fn symbol_array_attr(symbols: &[String]) -> String { + let symbols = symbols + .iter() + .map(|symbol| format!("@{symbol}")) + .collect::>() + .join(", "); + format!("[{symbols}]") +} + +fn int_attr(value: usize) -> String { + format!("{value} : i64") +} + +fn schema_error(message: impl Into) -> MlirError { + SchemaError::new(message).into() +} diff --git a/crates/bolt/src/protocols/jolt/validate.rs b/crates/bolt/src/protocols/jolt/validate.rs new file mode 100644 index 0000000000..8070f5ba3a --- /dev/null +++ b/crates/bolt/src/protocols/jolt/validate.rs @@ -0,0 +1,134 @@ +use melior::ir::operation::{OperationLike, OperationResult}; +use melior::ir::OperationRef; + +use crate::ir::{string_attribute_value, BoltModule, Concrete, Party, Protocol}; +use crate::schema::{ + find_symbol, int_attr, missing_module_op, missing_symbol, require_symbol_attr_eq, + symbol_array_attr, symbol_attr, verify_concrete_schema, verify_party_schema, + verify_protocol_schema, SchemaError, +}; + +use super::oracles::{MAIN_WITNESS_FAMILY_SYMBOL, PCS_SYMBOL}; +use super::params::ParsedJoltProtocolParams; + +pub fn verify_jolt_protocol_schema(module: &BoltModule<'_, Protocol>) -> Result<(), SchemaError> { + verify_protocol_schema(module)?; + validate_jolt_shape(module) +} + +pub fn verify_jolt_concrete_schema(module: &BoltModule<'_, Concrete>) -> Result<(), SchemaError> { + verify_concrete_schema(module)?; + validate_jolt_shape(module) +} + +pub fn verify_jolt_party_schema(module: &BoltModule<'_, Party>) -> Result<(), SchemaError> { + verify_party_schema(module)?; + validate_jolt_shape(module) +} + +fn validate_jolt_shape

(module: &BoltModule<'_, P>) -> Result<(), SchemaError> +where + P: crate::ir::Phase, +{ + let params_op = + find_symbol(module, "jolt.params").ok_or_else(|| missing_module_op("protocol.params"))?; + let params = ParsedJoltProtocolParams::from_op(params_op)?; + params.validate()?; + + require_symbol(module, ¶ms.field)?; + require_symbol(module, ¶ms.pcs)?; + require_symbol(module, ¶ms.transcript)?; + + let witness_family = find_symbol(module, MAIN_WITNESS_FAMILY_SYMBOL) + .ok_or_else(|| missing_symbol(MAIN_WITNESS_FAMILY_SYMBOL))?; + let witness_count = int_attr(witness_family, "count")?; + if witness_count != params.num_committed { + return Err(SchemaError::new(format!( + "main witness count {witness_count} does not match num_committed {}", + params.num_committed + ))); + } + let ordered_oracles = symbol_array_attr(witness_family, "ordered_oracles")?; + let expected_oracles = params.main_witness_oracles(); + if ordered_oracles != expected_oracles { + return Err(SchemaError::new(format!( + "main witness ordered_oracles mismatch: expected [{}], got [{}]", + expected_oracles.join(", "), + ordered_oracles.join(", ") + ))); + } + if ordered_oracles.len() != witness_count { + return Err(SchemaError::new(format!( + "main witness ordered_oracles length {} does not match count {witness_count}", + ordered_oracles.len() + ))); + } + for oracle in &ordered_oracles { + let oracle_op = find_symbol(module, oracle).ok_or_else(|| missing_symbol(oracle))?; + require_symbol_attr_eq(oracle_op, "field", ¶ms.field)?; + } + + let commit = find_symbol(module, "jolt.main_witness_commitments") + .ok_or_else(|| missing_symbol("jolt.main_witness_commitments"))?; + require_symbol_attr_eq(commit, "oracle_family", MAIN_WITNESS_FAMILY_SYMBOL)?; + + let pcs = find_symbol(module, "jolt.dory_main_witness_commit") + .ok_or_else(|| missing_symbol("jolt.dory_main_witness_commit"))?; + require_operand_owner_symbol_eq(pcs, 0, "jolt.main_witness_commitments")?; + let scheme = symbol_attr(pcs, "scheme")?; + if scheme != PCS_SYMBOL || scheme != params.pcs { + return Err(SchemaError::new(format!( + "PCS scheme `{scheme}` does not match params pcs `{}`", + params.pcs + ))); + } + + Ok(()) +} + +fn require_operand_owner_symbol_eq( + operation: OperationRef<'_, '_>, + index: usize, + expected: &str, +) -> Result<(), SchemaError> { + let operand = operation.operand(index).map_err(|_| { + SchemaError::new(format!( + "{} missing required operand {index}", + crate::schema::operation_name(operation) + )) + })?; + let owner = OperationResult::try_from(operand).map_err(|_| { + SchemaError::new(format!( + "{} operand {index} must be an op result", + crate::schema::operation_name(operation) + )) + })?; + let actual = owner + .owner() + .attribute("sym_name") + .ok() + .and_then(string_attribute_value) + .ok_or_else(|| { + SchemaError::new(format!( + "{} operand {index} owner missing sym_name", + crate::schema::operation_name(operation) + )) + })?; + if actual == expected { + Ok(()) + } else { + Err(SchemaError::new(format!( + "{} operand {index} expected @{expected}, got @{actual}", + crate::schema::operation_name(operation) + ))) + } +} + +fn require_symbol

(module: &BoltModule<'_, P>, symbol: &str) -> Result<(), SchemaError> +where + P: crate::ir::Phase, +{ + find_symbol(module, symbol) + .map(|_| ()) + .ok_or_else(|| missing_symbol(symbol)) +} diff --git a/crates/bolt/src/protocols/jolt/verifier_common.rs.template b/crates/bolt/src/protocols/jolt/verifier_common.rs.template new file mode 100644 index 0000000000..5c31bfa6ef --- /dev/null +++ b/crates/bolt/src/protocols/jolt/verifier_common.rs.template @@ -0,0 +1,1789 @@ +#![expect( + clippy::too_many_arguments, + reason = "generated verifier helpers mirror staged protocol ABIs" +)] + +use jolt_field::{Field, Fr}; +use jolt_poly::EqPolynomial; +use jolt_sumcheck::{ + CompressedLabeledRoundPoly, SumcheckClaim, SumcheckError, SumcheckProof, SumcheckVerifier, +}; +use jolt_transcript::{Label, Transcript}; +use serde::Serialize; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct StageParams { + pub field: &'static str, + pub pcs: &'static str, + pub transcript: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct KernelPlan { + pub symbol: &'static str, + pub relation: &'static str, + pub kind: &'static str, + pub backend: &'static str, + pub abi: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct TranscriptSqueezePlan { + pub symbol: &'static str, + pub label: &'static str, + pub kind: &'static str, + pub count: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct TranscriptAbsorbBytesPlan { + pub symbol: &'static str, + pub label: &'static str, + pub payload: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct ProgramStepPlan { + pub kind: &'static str, + pub symbol: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct OpeningInputPlan { + pub symbol: &'static str, + pub source_stage: &'static str, + pub source_claim: &'static str, + pub oracle: &'static str, + pub domain: &'static str, + pub point_arity: usize, + pub claim_kind: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct FieldConstantPlan { + pub symbol: &'static str, + pub field: &'static str, + pub value: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct FieldExprPlan { + pub symbol: &'static str, + pub kind: &'static str, + pub formula: &'static str, + pub operands: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct SumcheckClaimPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub domain: &'static str, + pub num_rounds: usize, + pub degree: usize, + pub claim: &'static str, + pub kernel: Option<&'static str>, + pub relation: Option<&'static str>, + pub claim_value: &'static str, + pub input_openings: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct SumcheckBatchPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub proof_slot: &'static str, + pub policy: &'static str, + pub count: usize, + pub ordered_claims: &'static str, + pub claim_operands: &'static str, + pub claim_label: &'static str, + pub round_label: &'static str, + pub round_schedule: &'static [usize], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct SumcheckDriverPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub proof_slot: &'static str, + pub kernel: Option<&'static str>, + pub relation: Option<&'static str>, + pub batch: &'static str, + pub policy: &'static str, + pub round_schedule: &'static [usize], + pub claim_label: &'static str, + pub round_label: &'static str, + pub num_rounds: usize, + pub degree: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct SumcheckInstanceResultPlan { + pub symbol: &'static str, + pub source: &'static str, + pub claim: &'static str, + pub relation: &'static str, + pub index: usize, + pub point_arity: usize, + pub num_rounds: usize, + pub round_offset: usize, + pub point_order: &'static str, + pub degree: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct SumcheckEvalPlan { + pub symbol: &'static str, + pub source: &'static str, + pub name: &'static str, + pub index: usize, + pub oracle: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct PointZeroPlan { + pub symbol: &'static str, + pub field: &'static str, + pub arity: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct PointSlicePlan { + pub symbol: &'static str, + pub source: &'static str, + pub offset: usize, + pub length: usize, + pub input: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct PointConcatPlan { + pub symbol: &'static str, + pub layout: &'static str, + pub arity: usize, + pub inputs: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct OpeningClaimPlan { + pub symbol: &'static str, + pub oracle: &'static str, + pub domain: &'static str, + pub point_arity: usize, + pub claim_kind: &'static str, + pub point_source: &'static str, + pub eval_source: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct OpeningClaimEqualityPlan { + pub symbol: &'static str, + pub mode: &'static str, + pub lhs: &'static str, + pub rhs: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct OpeningBatchPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub proof_slot: &'static str, + pub policy: &'static str, + pub count: usize, + pub ordered_claims: &'static str, + pub claim_operands: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct StageProgramPlan { + pub role: &'static str, + pub params: StageParams, + pub steps: &'static [ProgramStepPlan], + pub transcript_squeezes: &'static [TranscriptSqueezePlan], + pub transcript_absorb_bytes: &'static [TranscriptAbsorbBytesPlan], + pub opening_inputs: &'static [OpeningInputPlan], + pub field_constants: &'static [FieldConstantPlan], + pub field_exprs: &'static [FieldExprPlan], + pub kernels: &'static [KernelPlan], + pub claims: &'static [SumcheckClaimPlan], + pub batches: &'static [SumcheckBatchPlan], + pub drivers: &'static [SumcheckDriverPlan], + pub instance_results: &'static [SumcheckInstanceResultPlan], + pub evals: &'static [SumcheckEvalPlan], + pub point_zeros: &'static [PointZeroPlan], + pub point_slices: &'static [PointSlicePlan], + pub point_concats: &'static [PointConcatPlan], + pub opening_claims: &'static [OpeningClaimPlan], + pub opening_equalities: &'static [OpeningClaimEqualityPlan], + pub opening_batches: &'static [OpeningBatchPlan], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct StageProgramPlanNoPointZeros { + pub role: &'static str, + pub params: StageParams, + pub steps: &'static [ProgramStepPlan], + pub transcript_squeezes: &'static [TranscriptSqueezePlan], + pub transcript_absorb_bytes: &'static [TranscriptAbsorbBytesPlan], + pub opening_inputs: &'static [OpeningInputPlan], + pub field_constants: &'static [FieldConstantPlan], + pub field_exprs: &'static [FieldExprPlan], + pub kernels: &'static [KernelPlan], + pub claims: &'static [SumcheckClaimPlan], + pub batches: &'static [SumcheckBatchPlan], + pub drivers: &'static [SumcheckDriverPlan], + pub instance_results: &'static [SumcheckInstanceResultPlan], + pub evals: &'static [SumcheckEvalPlan], + pub point_slices: &'static [PointSlicePlan], + pub point_concats: &'static [PointConcatPlan], + pub opening_claims: &'static [OpeningClaimPlan], + pub opening_equalities: &'static [OpeningClaimEqualityPlan], + pub opening_batches: &'static [OpeningBatchPlan], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct StageVerifierProgramPlan { + pub params: StageParams, + pub steps: &'static [ProgramStepPlan], + pub transcript_squeezes: &'static [TranscriptSqueezePlan], + pub opening_inputs: &'static [OpeningInputPlan], + pub field_constants: &'static [FieldConstantPlan], + pub field_exprs: &'static [FieldExprPlan], + pub claims: &'static [SumcheckClaimPlan], + pub batches: &'static [SumcheckBatchPlan], + pub drivers: &'static [SumcheckDriverPlan], + pub instance_results: &'static [SumcheckInstanceResultPlan], + pub evals: &'static [SumcheckEvalPlan], + pub point_slices: &'static [PointSlicePlan], + pub point_concats: &'static [PointConcatPlan], + pub opening_claims: &'static [OpeningClaimPlan], + pub opening_equalities: &'static [OpeningClaimEqualityPlan], + pub opening_batches: &'static [OpeningBatchPlan], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct StageVerifierProgramPlanNoEqualities { + pub params: StageParams, + pub steps: &'static [ProgramStepPlan], + pub transcript_squeezes: &'static [TranscriptSqueezePlan], + pub opening_inputs: &'static [OpeningInputPlan], + pub field_constants: &'static [FieldConstantPlan], + pub field_exprs: &'static [FieldExprPlan], + pub claims: &'static [SumcheckClaimPlan], + pub batches: &'static [SumcheckBatchPlan], + pub drivers: &'static [SumcheckDriverPlan], + pub instance_results: &'static [SumcheckInstanceResultPlan], + pub evals: &'static [SumcheckEvalPlan], + pub point_slices: &'static [PointSlicePlan], + pub point_concats: &'static [PointConcatPlan], + pub opening_claims: &'static [OpeningClaimPlan], + pub opening_batches: &'static [OpeningBatchPlan], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct VerifierProgramPlanMinimal { + pub params: StageParams, + pub transcript_squeezes: &'static [TranscriptSqueezePlan], + pub claims: &'static [SumcheckClaimPlan], + pub batches: &'static [SumcheckBatchPlan], + pub drivers: &'static [SumcheckDriverPlan], + pub instance_results: &'static [SumcheckInstanceResultPlan], + pub evals: &'static [SumcheckEvalPlan], + pub opening_claims: &'static [OpeningClaimPlan], + pub opening_batches: &'static [OpeningBatchPlan], +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize)] +pub struct StageNamedEval { + pub name: &'static str, + pub oracle: &'static str, + pub value: F, +} + +#[derive(Clone, Debug, Serialize)] +pub struct StageSumcheckOutput { + pub driver: &'static str, + pub point: Vec, + pub evals: Vec>, + pub proof: SumcheckProof, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct StageChallengeVector { + pub symbol: &'static str, + pub values: Vec, +} + +#[derive(Clone, Debug)] +pub struct StageExecutionArtifacts { + pub challenge_vectors: Vec>, + pub sumchecks: Vec>, + pub opening_batches: Vec<&'static OpeningBatchPlan>, +} + +impl Default for StageExecutionArtifacts { + fn default() -> Self { + Self { + challenge_vectors: Vec::new(), + sumchecks: Vec::new(), + opening_batches: Vec::new(), + } + } +} + +#[derive(Clone, Debug, Default, Serialize)] +pub struct StageProof { + pub sumchecks: Vec>, +} + +#[derive(Clone, Debug)] +pub struct StageOpeningInputValue { + pub symbol: &'static str, + pub point: Vec, + pub eval: F, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum RuntimePlanError { + MissingBatch { + driver: &'static str, + batch: &'static str, + }, + MissingClaim { + batch: &'static str, + claim: &'static str, + }, + MissingValue { + symbol: &'static str, + }, + InvalidInputLength { + input: &'static str, + expected: usize, + actual: usize, + }, + InvalidProof { + driver: &'static str, + reason: &'static str, + }, + UnsupportedFieldExpr { + symbol: &'static str, + formula: &'static str, + }, +} + +macro_rules! impl_runtime_plan_error_conversion { + ($error:ident) => { + impl From for $error { + fn from(error: super::common::RuntimePlanError) -> Self { + match error { + super::common::RuntimePlanError::MissingBatch { driver, batch } => { + Self::MissingBatch { driver, batch } + } + super::common::RuntimePlanError::MissingClaim { batch, claim } => { + Self::MissingClaim { batch, claim } + } + super::common::RuntimePlanError::MissingValue { symbol } => { + Self::MissingValue { symbol } + } + super::common::RuntimePlanError::InvalidInputLength { + input, + expected, + actual, + } => Self::InvalidInputLength { + input, + expected, + actual, + }, + super::common::RuntimePlanError::InvalidProof { driver, reason } => { + Self::InvalidProof { driver, reason } + } + super::common::RuntimePlanError::UnsupportedFieldExpr { symbol, formula } => { + Self::UnsupportedFieldExpr { symbol, formula } + } + } + } + } + }; +} + +pub(crate) use impl_runtime_plan_error_conversion; + +pub trait SymbolPlan { + fn symbol(&self) -> &'static str; +} + +impl SymbolPlan for TranscriptSqueezePlan { + fn symbol(&self) -> &'static str { + self.symbol + } +} + +impl SymbolPlan for TranscriptAbsorbBytesPlan { + fn symbol(&self) -> &'static str { + self.symbol + } +} + +impl SymbolPlan for SumcheckBatchPlan { + fn symbol(&self) -> &'static str { + self.symbol + } +} + +impl SymbolPlan for SumcheckClaimPlan { + fn symbol(&self) -> &'static str { + self.symbol + } +} + +impl SymbolPlan for SumcheckDriverPlan { + fn symbol(&self) -> &'static str { + self.symbol + } +} + +impl SymbolPlan for OpeningClaimPlan { + fn symbol(&self) -> &'static str { + self.symbol + } +} + +pub trait SumcheckClaimInfo: SymbolPlan { + fn num_rounds(&self) -> usize; + fn claim_value(&self) -> &'static str; +} + +impl SumcheckClaimInfo for SumcheckClaimPlan { + fn num_rounds(&self) -> usize { + self.num_rounds + } + + fn claim_value(&self) -> &'static str { + self.claim_value + } +} + +pub trait SumcheckDriverInfo: SymbolPlan { + fn batch(&self) -> &'static str; + fn num_rounds(&self) -> usize; + fn degree(&self) -> usize; + fn round_label(&self) -> &'static str; +} + +impl SumcheckDriverInfo for SumcheckDriverPlan { + fn batch(&self) -> &'static str { + self.batch + } + + fn num_rounds(&self) -> usize { + self.num_rounds + } + + fn degree(&self) -> usize { + self.degree + } + + fn round_label(&self) -> &'static str { + self.round_label + } +} + +#[derive(Clone, Debug, Default)] +pub struct ValueStore { + scalars: Vec<(&'static str, F)>, + points: Vec<(&'static str, Vec)>, +} + +impl ValueStore { + pub fn with_opening_inputs( + inputs: &[StageOpeningInputValue], + expected_inputs: &[OpeningInputPlan], + ) -> Result { + if inputs.len() != expected_inputs.len() { + return Err(RuntimePlanError::InvalidInputLength { + input: "opening_inputs", + expected: expected_inputs.len(), + actual: inputs.len(), + }); + } + for expected in expected_inputs { + let matching_count = inputs + .iter() + .filter(|input| input.symbol == expected.symbol) + .count(); + if matching_count != 1 { + return Err(RuntimePlanError::InvalidInputLength { + input: expected.symbol, + expected: 1, + actual: matching_count, + }); + } + if let Some(input) = inputs.iter().find(|input| input.symbol == expected.symbol) { + if input.point.len() != expected.point_arity { + return Err(RuntimePlanError::InvalidInputLength { + input: expected.symbol, + expected: expected.point_arity, + actual: input.point.len(), + }); + } + } + } + let mut store = Self::default(); + for input in inputs { + store.insert_scalar(input.symbol, input.eval); + store.insert_point(input.symbol, input.point.clone()); + } + Ok(store) + } + + pub fn seed_constants(&mut self, constants: &[FieldConstantPlan]) { + for constant in constants { + self.insert_scalar(constant.symbol, F::from_u64(constant.value as u64)); + } + } + + pub fn seed_point_zeros(&mut self, point_zeros: &[PointZeroPlan]) { + for zero in point_zeros { + self.insert_point(zero.symbol, vec![F::from_u64(0); zero.arity]); + } + } + + pub fn observe_challenge_vector( + &mut self, + plan: &TranscriptSqueezePlan, + values: &[F], + invalid_input_length: impl Fn(&'static str, usize, usize) -> E, + ) -> Result<(), E> { + self.insert_point(plan.symbol, values.to_vec()); + if matches!(plan.kind, "challenge_scalar" | "scalar") { + if values.len() != 1 { + return Err(invalid_input_length(plan.symbol, 1, values.len())); + } + self.insert_scalar(plan.symbol, values[0]); + } + Ok(()) + } + + pub fn observe_sumcheck_output( + &mut self, + instance_results: &[SumcheckInstanceResultPlan], + evals: &[SumcheckEvalPlan], + output: &StageSumcheckOutput, + normalize_point: impl Fn(&SumcheckInstanceResultPlan, Vec) -> Result, E>, + invalid_input_length: impl Fn(&'static str, usize, usize) -> E, + missing_value: impl Fn(&'static str) -> E, + ) -> Result<(), E> { + self.insert_point(output.driver, output.point.clone()); + for instance in instance_results + .iter() + .filter(|instance| instance.source == output.driver) + { + let end = instance.round_offset + instance.point_arity; + let point = output + .point + .get(instance.round_offset..end) + .ok_or_else(|| invalid_input_length(instance.symbol, end, output.point.len()))? + .to_vec(); + self.insert_point(instance.symbol, normalize_point(instance, point)?); + } + for eval in evals.iter().filter(|eval| eval.source == output.driver) { + let value = output + .evals + .iter() + .find(|value| value.name == eval.name) + .or_else(|| output.evals.get(eval.index)) + .ok_or_else(|| missing_value(eval.symbol))? + .value; + self.insert_scalar(eval.symbol, value); + self.insert_scalar(eval.name, value); + } + Ok(()) + } + + pub fn evaluate_available_points( + &mut self, + point_slices: &[PointSlicePlan], + point_concats: &[PointConcatPlan], + invalid_input_length: impl Fn(&'static str, usize, usize) -> E, + ) -> Result<(), E> { + loop { + let mut progress = 0usize; + for slice in point_slices { + if self.try_point(slice.symbol).is_some() { + continue; + } + let Some(input) = self.try_point(slice.input) else { + continue; + }; + let end = slice.offset + slice.length; + let point = input + .get(slice.offset..end) + .ok_or_else(|| invalid_input_length(slice.symbol, end, input.len()))? + .to_vec(); + self.insert_point(slice.symbol, point); + progress += 1; + } + for concat in point_concats { + if self.try_point(concat.symbol).is_some() { + continue; + } + let Some(point) = self.try_concat_point(concat) else { + continue; + }; + if point.len() != concat.arity { + return Err(invalid_input_length( + concat.symbol, + concat.arity, + point.len(), + )); + } + self.insert_point(concat.symbol, point); + progress += 1; + } + if progress == 0 { + return Ok(()); + } + } + } + + pub fn evaluate_available_field_exprs( + &mut self, + field_exprs: &[FieldExprPlan], + evaluate: impl Fn(&FieldExprPlan, &[F]) -> Result, + ) -> Result<(), E> { + loop { + let mut progress = 0usize; + for expr in field_exprs { + if self.try_scalar(expr.symbol).is_some() { + continue; + } + let Some(operands) = self.try_expr_operands(expr) else { + continue; + }; + self.insert_scalar(expr.symbol, evaluate(expr, &operands)?); + progress += 1; + } + if progress == 0 { + return Ok(()); + } + } + } + + pub fn verify_opening_equalities( + &self, + opening_equalities: &[OpeningClaimEqualityPlan], + invalid_proof: impl Fn(&'static str, &'static str) -> E, + missing_value: impl Fn(&'static str) -> E, + ) -> Result<(), E> { + for equality in opening_equalities { + match equality.mode { + "point_and_eval" => { + if self.point_or(equality.lhs, &missing_value)? + != self.point_or(equality.rhs, &missing_value)? + || self.scalar_or(equality.lhs, &missing_value)? + != self.scalar_or(equality.rhs, &missing_value)? + { + return Err(invalid_proof( + equality.symbol, + "opening claim equality failed", + )); + } + } + _ => { + return Err(invalid_proof( + equality.symbol, + "unsupported opening equality mode", + )); + } + } + } + Ok(()) + } + + pub fn insert_scalar(&mut self, symbol: &'static str, value: F) { + if let Some((_, existing)) = self.scalars.iter_mut().find(|(name, _)| *name == symbol) { + *existing = value; + } else { + self.scalars.push((symbol, value)); + } + } + + pub fn insert_point(&mut self, symbol: &'static str, point: Vec) { + if let Some((_, existing)) = self.points.iter_mut().find(|(name, _)| *name == symbol) { + *existing = point; + } else { + self.points.push((symbol, point)); + } + } + + pub fn scalar_or( + &self, + symbol: &'static str, + missing_value: impl FnOnce(&'static str) -> E, + ) -> Result { + self.try_scalar(symbol).ok_or_else(|| missing_value(symbol)) + } + + pub fn try_scalar(&self, symbol: &str) -> Option { + self.scalars + .iter() + .find(|(name, _)| *name == symbol) + .map(|(_, value)| *value) + } + + pub fn point_or( + &self, + symbol: &'static str, + missing_value: impl FnOnce(&'static str) -> E, + ) -> Result<&[F], E> { + self.try_point(symbol).ok_or_else(|| missing_value(symbol)) + } + + pub fn try_point(&self, symbol: &str) -> Option<&[F]> { + self.points + .iter() + .find(|(name, _)| *name == symbol) + .map(|(_, point)| point.as_slice()) + } + + fn try_expr_operands(&self, expr: &FieldExprPlan) -> Option> { + if expr.operands.is_empty() { + return Some(Vec::new()); + } + expr.operands + .split('|') + .map(|operand| self.try_scalar(operand)) + .collect() + } + + fn try_concat_point(&self, concat: &PointConcatPlan) -> Option> { + let mut point = Vec::with_capacity(concat.arity); + for input in symbol_list(concat.inputs) { + point.extend_from_slice(self.try_point(input)?); + } + Some(point) + } +} + +pub fn symbol_list(symbols: &'static str) -> impl Iterator { + symbols.split('|').filter(|symbol| !symbol.is_empty()) +} + +pub fn find_plan<'a, T: SymbolPlan>(plans: &'a [T], symbol: &str) -> Option<&'a T> { + plans.iter().find(|plan| plan.symbol() == symbol) +} + +pub fn find_batch<'a>( + batches: &'a [SumcheckBatchPlan], + driver: &'static str, + batch: &'static str, +) -> Result<&'a SumcheckBatchPlan, RuntimePlanError> { + find_plan(batches, batch).ok_or(RuntimePlanError::MissingBatch { driver, batch }) +} + +pub fn batch_claims<'a, C: SymbolPlan>( + claims: &'a [C], + batch: &SumcheckBatchPlan, +) -> Result, RuntimePlanError> { + symbol_list(batch.claim_operands) + .map(|symbol| { + find_plan(claims, symbol).ok_or(RuntimePlanError::MissingClaim { + batch: batch.symbol, + claim: symbol, + }) + }) + .collect() +} + +pub fn batch_claim_values( + claims: &[&C], + field_exprs: &[FieldExprPlan], + store: &mut ValueStore, +) -> Result, RuntimePlanError> { + claims + .iter() + .map(|claim| { + store.evaluate_available_field_exprs(field_exprs, evaluate_field_expr)?; + store.scalar_or(claim.claim_value(), |symbol| { + RuntimePlanError::MissingValue { symbol } + }) + }) + .collect() +} + +pub fn verify_batched_sumcheck( + driver: &'static D, + proof: &StageSumcheckOutput, + claims: &'static [C], + batches: &'static [SumcheckBatchPlan], + field_exprs: &'static [FieldExprPlan], + opening_inputs: &'static [OpeningInputPlan], + opening_claims: &'static [OpeningClaimPlan], + opening_batches: &'static [OpeningBatchPlan], + store: &mut ValueStore, + transcript: &mut T, + expected_output: Expected, + observe_output: Observe, + map_sumcheck: MapSumcheck, +) -> Result, E> +where + T: Transcript, + E: From, + C: SumcheckClaimInfo, + D: SumcheckDriverInfo, + Expected: FnOnce(&ValueStore, &[StageNamedEval], &[Fr], &[Fr]) -> Result, + Observe: FnOnce(&mut ValueStore, &StageSumcheckOutput) -> Result<(), E>, + MapSumcheck: FnOnce(&'static str, SumcheckError) -> E, +{ + if proof.driver != driver.symbol() { + return Err(RuntimePlanError::InvalidProof { + driver: driver.symbol(), + reason: "driver symbol mismatch", + } + .into()); + } + let batch = find_batch(batches, driver.symbol(), driver.batch())?; + let claims = batch_claims(claims, batch)?; + let input_claims = batch_claim_values(&claims, field_exprs, store)?; + for claim in &input_claims { + append_labeled_scalar(transcript, batch.claim_label, claim); + } + let batching_coeffs = transcript.challenge_vector(claims.len()); + let claimed_sum = input_claims + .iter() + .zip(claims.iter()) + .zip(&batching_coeffs) + .map(|((claim, plan), coefficient)| { + claim.mul_pow_2(driver.num_rounds() - plan.num_rounds()) * *coefficient + }) + .sum::(); + let claim = SumcheckClaim::new(driver.num_rounds(), driver.degree(), claimed_sum); + let round_proofs = proof + .proof + .round_polynomials + .iter() + .map(|poly| CompressedLabeledRoundPoly::new(poly, driver.round_label().as_bytes())) + .collect::>(); + let output = SumcheckVerifier::verify(&claim, &round_proofs, transcript) + .map_err(|error| map_sumcheck(driver.symbol(), error))?; + if !proof.point.is_empty() && proof.point != output.point { + return Err(RuntimePlanError::InvalidProof { + driver: driver.symbol(), + reason: "batched point mismatch", + } + .into()); + } + let expected = expected_output(store, &proof.evals, &output.point, &batching_coeffs)?; + if output.value != expected { + return Err(RuntimePlanError::InvalidProof { + driver: driver.symbol(), + reason: "batched output claim mismatch", + } + .into()); + } + let verified = StageSumcheckOutput { + driver: driver.symbol(), + point: output.point, + evals: proof.evals.clone(), + proof: proof.proof.clone(), + }; + observe_output(store, &verified)?; + append_opening_claims( + opening_inputs, + opening_claims, + opening_batches, + store, + transcript, + &verified.evals, + |batch, claim| RuntimePlanError::MissingClaim { batch, claim }, + |symbol| RuntimePlanError::MissingValue { symbol }, + )?; + Ok(verified) +} + +pub fn eval_by_name( + evals: &[StageNamedEval], + name: &'static str, +) -> Result { + evals + .iter() + .find(|eval| eval.name == name) + .map(|eval| eval.value) + .ok_or(RuntimePlanError::MissingValue { symbol: name }) +} + +pub fn indexed_evals_by_prefix( + evals: &[StageNamedEval], + prefix: &'static str, + count: usize, +) -> Result, RuntimePlanError> { + let mut values = vec![None; count]; + for eval in evals { + let Some(suffix) = eval.name.strip_prefix(prefix) else { + continue; + }; + let index = suffix + .parse::() + .map_err(|_| RuntimePlanError::InvalidProof { + driver: prefix, + reason: "invalid indexed eval suffix", + })?; + if index >= count || values[index].is_some() { + return Err(RuntimePlanError::InvalidProof { + driver: prefix, + reason: "invalid indexed eval", + }); + } + values[index] = Some(eval.value); + } + values + .into_iter() + .map(|value| value.ok_or(RuntimePlanError::MissingValue { symbol: prefix })) + .collect() +} + +pub fn indexed_evals_by_prefix_any( + evals: &[StageNamedEval], + prefix: &'static str, +) -> Result, RuntimePlanError> { + let mut indexed_values = Vec::new(); + for eval in evals { + let Some(suffix) = eval.name.strip_prefix(prefix) else { + continue; + }; + let index = suffix + .parse::() + .map_err(|_| RuntimePlanError::InvalidProof { + driver: prefix, + reason: "invalid indexed eval suffix", + })?; + if indexed_values + .iter() + .any(|(existing_index, _)| *existing_index == index) + { + return Err(RuntimePlanError::InvalidProof { + driver: prefix, + reason: "duplicate indexed eval", + }); + } + indexed_values.push((index, eval.value)); + } + if indexed_values.is_empty() { + return Err(RuntimePlanError::MissingValue { symbol: prefix }); + } + indexed_values.sort_by_key(|(index, _)| *index); + for (expected, (actual, _)) in indexed_values.iter().enumerate() { + if *actual != expected { + return Err(RuntimePlanError::InvalidProof { + driver: prefix, + reason: "non-contiguous indexed eval", + }); + } + } + Ok(indexed_values.into_iter().map(|(_, value)| value).collect()) +} + +pub fn single_operand( + symbol: &'static str, + operands: &[F], +) -> Result { + require_operand_count(symbol, 1, operands.len())?; + Ok(operands[0]) +} + +pub fn require_operand_count( + input: &'static str, + expected: usize, + actual: usize, +) -> Result<(), RuntimePlanError> { + if expected == actual { + Ok(()) + } else { + Err(RuntimePlanError::InvalidInputLength { + input, + expected, + actual, + }) + } +} + +pub fn evaluate_field_expr( + expr: &FieldExprPlan, + operands: &[F], +) -> Result { + match expr.formula { + "opening_eval" => Ok(single_operand(expr.symbol, operands)?), + "field.add" => { + require_operand_count(expr.symbol, 2, operands.len())?; + Ok(operands[0] + operands[1]) + } + "field.sub" => { + require_operand_count(expr.symbol, 2, operands.len())?; + Ok(operands[0] - operands[1]) + } + "field.mul" => { + require_operand_count(expr.symbol, 2, operands.len())?; + Ok(operands[0] * operands[1]) + } + "field.neg" => { + require_operand_count(expr.symbol, 1, operands.len())?; + Ok(-operands[0]) + } + formula => { + if let Some(exponent) = formula.strip_prefix("field.pow:") { + require_operand_count(expr.symbol, 1, operands.len())?; + let exponent = exponent.parse::().map_err(|_| { + RuntimePlanError::UnsupportedFieldExpr { + symbol: expr.symbol, + formula, + } + })?; + return Ok(pow_field(operands[0], exponent)); + } + Err(RuntimePlanError::UnsupportedFieldExpr { + symbol: expr.symbol, + formula, + }) + } + } +} + +pub fn bytecode_gamma_powers(gamma: Fr) -> [Fr; 8] { + let mut powers = [Fr::from_u64(1); 8]; + for index in 1..powers.len() { + powers[index] = powers[index - 1] * gamma; + } + powers +} + +pub fn indexed_boolean_eq(index: usize, point: &[Fr]) -> Fr { + point + .iter() + .enumerate() + .map(|(bit, value)| { + if (index >> (point.len() - 1 - bit)) & 1 == 1 { + *value + } else { + Fr::from_u64(1) - *value + } + }) + .product() +} + +pub fn field_powers(base: Fr, count: usize) -> Vec { + let mut powers = Vec::with_capacity(count); + let mut power = Fr::from_u64(1); + for _ in 0..count { + powers.push(power); + power *= base; + } + powers +} + +pub fn prefix_point<'a, F: Field>( + point: &'a [F], + length: usize, + input: &'static str, +) -> Result<&'a [F], RuntimePlanError> { + point + .get(..length) + .filter(|prefix| prefix.len() == length) + .ok_or(RuntimePlanError::InvalidInputLength { + input, + expected: length, + actual: point.len(), + }) +} + +pub fn suffix_point<'a, F: Field>( + point: &'a [F], + length: usize, + input: &'static str, +) -> Result<&'a [F], RuntimePlanError> { + point + .get(point.len().saturating_sub(length)..) + .filter(|suffix| suffix.len() == length) + .ok_or(RuntimePlanError::InvalidInputLength { + input, + expected: length, + actual: point.len(), + }) +} + +pub fn normalize_bytecode_read_raf_point( + point: &[F], + log_t: usize, + input: &'static str, +) -> Result, RuntimePlanError> { + let log_k = point + .len() + .checked_sub(log_t) + .ok_or(RuntimePlanError::InvalidInputLength { + input, + expected: log_t, + actual: point.len(), + })?; + let mut normalized = point.to_vec(); + normalized[..log_k].reverse(); + normalized[log_k..].reverse(); + Ok(normalized) +} + +pub fn normalize_instruction_read_raf_point( + point: &[F], + input: &'static str, +) -> Result, RuntimePlanError> { + const LOG_K: usize = 128; + if point.len() < LOG_K { + return Err(RuntimePlanError::InvalidInputLength { + input, + expected: LOG_K, + actual: point.len(), + }); + } + let mut normalized = point.to_vec(); + normalized[LOG_K..].reverse(); + Ok(normalized) +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage67RelationSymbols { + pub hamming_booleanity_relation: &'static str, + pub hamming_booleanity_instance: &'static str, + pub booleanity_point: &'static str, + pub stage5_instruction_ra0: &'static str, + pub booleanity_combined_point: &'static str, + pub booleanity_gamma: &'static str, + pub booleanity_instruction_ra_prefix: &'static str, + pub booleanity_bytecode_ra_prefix: &'static str, + pub booleanity_ram_ra_prefix: &'static str, + pub hamming_weight_eval: &'static str, + pub hamming_lookup_output: &'static str, + pub ram_ra_virtual_cycle: &'static str, + pub ram_ra_virtual_eval_prefix: &'static str, + pub instruction_ra_virtual_cycle: &'static str, + pub instruction_ra_virtual_eval_prefix: &'static str, + pub instruction_ra_virtual_input_prefix: &'static str, + pub instruction_ra_virtual_gamma: &'static str, + pub inc_ram_stage2: &'static str, + pub inc_ram_stage4: &'static str, + pub inc_rd_stage4: &'static str, + pub inc_rd_stage5: &'static str, + pub inc_gamma: &'static str, + pub inc_ram_eval: &'static str, + pub inc_rd_eval: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage67BytecodeSymbols { + pub point: &'static str, + pub gamma: &'static str, + pub bytecode_ra_eval_prefix: &'static str, + pub entries: &'static str, + pub entry_bytecode_index: &'static str, + pub stage_gammas: [&'static str; 5], + pub stage_cycle_points: [&'static str; 5], + pub stage4_register_point: &'static str, + pub stage5_register_point: &'static str, + pub entry_rd: &'static str, + pub entry_rs1: &'static str, + pub entry_rs2: &'static str, + pub entry_lookup_table: &'static str, +} + +pub trait Stage67BytecodeEntry { + fn address(&self) -> Fr; + fn imm(&self) -> Fr; + fn circuit_flags(&self) -> &[bool; 14]; + fn rd(&self) -> Option; + fn rs1(&self) -> Option; + fn rs2(&self) -> Option; + fn lookup_table(&self) -> Option; + fn is_interleaved(&self) -> bool; + fn is_branch(&self) -> bool; + fn left_is_rs1(&self) -> bool; + fn left_is_pc(&self) -> bool; + fn right_is_rs2(&self) -> bool; + fn right_is_imm(&self) -> bool; + fn is_noop(&self) -> bool; +} + +pub fn store_scalar(store: &ValueStore, symbol: &'static str) -> Result { + store.scalar_or(symbol, |symbol| RuntimePlanError::MissingValue { symbol }) +} + +pub fn store_point<'a>( + store: &'a ValueStore, + symbol: &'static str, +) -> Result<&'a [Fr], RuntimePlanError> { + store.point_or(symbol, |symbol| RuntimePlanError::MissingValue { symbol }) +} + +pub fn stage67_trace_rounds( + instance_results: &[SumcheckInstanceResultPlan], + symbols: &Stage67RelationSymbols, +) -> Result { + instance_results + .iter() + .find(|instance| instance.relation == symbols.hamming_booleanity_relation) + .map(|instance| instance.num_rounds) + .ok_or(RuntimePlanError::MissingValue { + symbol: symbols.hamming_booleanity_instance, + }) +} + +pub fn expected_stage67_bytecode_read_raf( + entries: &[E], + entry_bytecode_index: usize, + num_lookup_tables: usize, + store: &ValueStore, + evals: &[StageNamedEval], + local_point: &[Fr], + log_t: usize, + symbols: &Stage67BytecodeSymbols, +) -> Result { + let opening_point = normalize_bytecode_read_raf_point(local_point, log_t, symbols.point)?; + let log_k = opening_point.len() - log_t; + let (r_address_prime, r_cycle_prime) = opening_point.split_at(log_k); + + let gamma = store_scalar(store, symbols.gamma)?; + let gamma_powers = bytecode_gamma_powers(gamma); + let int_eval = identity_polynomial_eval(r_address_prime); + let stage_value_evals = stage67_bytecode_stage_value_evals( + entries, + entry_bytecode_index, + num_lookup_tables, + store, + r_address_prime, + r_cycle_prime.len(), + symbols, + )?; + let stage_cycle_points = + stage67_bytecode_stage_cycle_points(store, r_cycle_prime.len(), symbols)?; + let int_contrib = [ + gamma_powers[5] * int_eval, + Fr::from_u64(0), + gamma_powers[4] * int_eval, + Fr::from_u64(0), + Fr::from_u64(0), + ]; + + let mut val = Fr::from_u64(0); + for index in 0..stage_value_evals.len() { + val += (stage_value_evals[index] + int_contrib[index]) + * EqPolynomial::::mle(&stage_cycle_points[index], r_cycle_prime) + * gamma_powers[index]; + } + + let entry_bits = (0..log_k) + .map(|index| Fr::from_u64(((entry_bytecode_index >> (log_k - 1 - index)) & 1) as u64)) + .collect::>(); + let zero_cycle = vec![Fr::from_u64(0); r_cycle_prime.len()]; + let entry_contrib = gamma_powers[7] + * EqPolynomial::::mle(&entry_bits, r_address_prime) + * EqPolynomial::::mle(&zero_cycle, r_cycle_prime); + let bytecode_ra = indexed_evals_by_prefix_any(evals, symbols.bytecode_ra_eval_prefix)? + .into_iter() + .product::(); + Ok((val + entry_contrib) * bytecode_ra) +} + +pub fn expected_stage67_booleanity( + store: &ValueStore, + evals: &[StageNamedEval], + local_point: &[Fr], + log_t: usize, + symbols: &Stage67RelationSymbols, +) -> Result { + let log_k_chunk = + local_point + .len() + .checked_sub(log_t) + .ok_or(RuntimePlanError::InvalidInputLength { + input: symbols.booleanity_point, + expected: log_t, + actual: local_point.len(), + })?; + let stage5_point = store_point(store, symbols.stage5_instruction_ra0)?; + let stage5_address_len = + stage5_point + .len() + .checked_sub(log_t) + .ok_or(RuntimePlanError::InvalidInputLength { + input: symbols.stage5_instruction_ra0, + expected: log_t, + actual: stage5_point.len(), + })?; + if stage5_address_len < log_k_chunk { + return Err(RuntimePlanError::InvalidInputLength { + input: symbols.stage5_instruction_ra0, + expected: log_k_chunk + log_t, + actual: stage5_point.len(), + }); + } + + let mut stage5_addr = stage5_point[..stage5_address_len].to_vec(); + stage5_addr.reverse(); + let mut combined_r = stage5_addr[stage5_address_len - log_k_chunk..].to_vec(); + combined_r.extend(stage5_point[stage5_address_len..].iter().rev().copied()); + if combined_r.len() != local_point.len() { + return Err(RuntimePlanError::InvalidInputLength { + input: symbols.booleanity_combined_point, + expected: local_point.len(), + actual: combined_r.len(), + }); + } + let mut verifier_point = combined_r[..log_k_chunk].to_vec(); + verifier_point.reverse(); + verifier_point.extend(combined_r[log_k_chunk..].iter().rev().copied()); + let eq_eval = EqPolynomial::::mle(local_point, &verifier_point); + + let gamma = store_scalar(store, symbols.booleanity_gamma)?; + let gamma_sq = gamma.square(); + let mut gamma_power = Fr::from_u64(1); + let mut booleanity = Fr::from_u64(0); + for ra in stage67_booleanity_evals(evals, symbols)? { + booleanity += gamma_power * (ra.square() - ra); + gamma_power *= gamma_sq; + } + Ok(eq_eval * booleanity) +} + +pub fn expected_stage67_hamming_booleanity( + store: &ValueStore, + evals: &[StageNamedEval], + local_point: &[Fr], + symbols: &Stage67RelationSymbols, +) -> Result { + let hamming = eval_by_name(evals, symbols.hamming_weight_eval)?; + let lookup_output_point = reverse_slice(store_point(store, symbols.hamming_lookup_output)?); + if lookup_output_point.len() != local_point.len() { + return Err(RuntimePlanError::InvalidInputLength { + input: symbols.hamming_lookup_output, + expected: local_point.len(), + actual: lookup_output_point.len(), + }); + } + let eq_eval = EqPolynomial::::mle(local_point, &lookup_output_point); + Ok((hamming.square() - hamming) * eq_eval) +} + +pub fn expected_stage67_ram_ra_virtual( + store: &ValueStore, + evals: &[StageNamedEval], + local_point: &[Fr], + symbols: &Stage67RelationSymbols, +) -> Result { + let r_cycle_reduced = reverse_slice(local_point); + let r_cycle = suffix_point( + store_point(store, symbols.ram_ra_virtual_cycle)?, + r_cycle_reduced.len(), + symbols.ram_ra_virtual_cycle, + )?; + let eq_eval = EqPolynomial::::mle(r_cycle, &r_cycle_reduced); + let ram_ra = indexed_evals_by_prefix_any(evals, symbols.ram_ra_virtual_eval_prefix)? + .into_iter() + .product::(); + Ok(eq_eval * ram_ra) +} + +pub fn expected_stage67_instruction_ra_virtual( + opening_inputs: &[OpeningInputPlan], + store: &ValueStore, + evals: &[StageNamedEval], + local_point: &[Fr], + symbols: &Stage67RelationSymbols, +) -> Result { + let r_cycle_reduced = reverse_slice(local_point); + let r_cycle = suffix_point( + store_point(store, symbols.instruction_ra_virtual_cycle)?, + r_cycle_reduced.len(), + symbols.instruction_ra_virtual_cycle, + )?; + let eq_eval = EqPolynomial::::mle(r_cycle, &r_cycle_reduced); + let committed_ra = + indexed_evals_by_prefix_any(evals, symbols.instruction_ra_virtual_eval_prefix)?; + let virtual_count = opening_inputs + .iter() + .filter(|input| { + input + .symbol + .starts_with(symbols.instruction_ra_virtual_input_prefix) + }) + .count(); + if virtual_count == 0 || committed_ra.len() % virtual_count != 0 { + return Err(RuntimePlanError::InvalidInputLength { + input: symbols.instruction_ra_virtual_eval_prefix, + expected: virtual_count, + actual: committed_ra.len(), + }); + } + let committed_per_virtual = committed_ra.len() / virtual_count; + let gamma = store_scalar(store, symbols.instruction_ra_virtual_gamma)?; + let mut gamma_power = Fr::from_u64(1); + let mut value = Fr::from_u64(0); + for chunk in committed_ra.chunks(committed_per_virtual) { + value += gamma_power * chunk.iter().copied().product::(); + gamma_power *= gamma; + } + Ok(eq_eval * value) +} + +pub fn expected_stage67_inc_claim_reduction( + store: &ValueStore, + evals: &[StageNamedEval], + local_point: &[Fr], + symbols: &Stage67RelationSymbols, +) -> Result { + let r_cycle_reduced = reverse_slice(local_point); + let ram_inc_stage2 = suffix_point( + store_point(store, symbols.inc_ram_stage2)?, + r_cycle_reduced.len(), + symbols.inc_ram_stage2, + )?; + let ram_inc_stage4 = suffix_point( + store_point(store, symbols.inc_ram_stage4)?, + r_cycle_reduced.len(), + symbols.inc_ram_stage4, + )?; + let rd_inc_stage4 = suffix_point( + store_point(store, symbols.inc_rd_stage4)?, + r_cycle_reduced.len(), + symbols.inc_rd_stage4, + )?; + let rd_inc_stage5 = suffix_point( + store_point(store, symbols.inc_rd_stage5)?, + r_cycle_reduced.len(), + symbols.inc_rd_stage5, + )?; + let gamma = store_scalar(store, symbols.inc_gamma)?; + let eq_ram_combined = EqPolynomial::::mle(ram_inc_stage2, &r_cycle_reduced) + + gamma * EqPolynomial::::mle(ram_inc_stage4, &r_cycle_reduced); + let eq_rd_combined = EqPolynomial::::mle(rd_inc_stage4, &r_cycle_reduced) + + gamma * EqPolynomial::::mle(rd_inc_stage5, &r_cycle_reduced); + let ram_inc = eval_by_name(evals, symbols.inc_ram_eval)?; + let rd_inc = eval_by_name(evals, symbols.inc_rd_eval)?; + Ok(ram_inc * eq_ram_combined + gamma.square() * rd_inc * eq_rd_combined) +} + +fn stage67_booleanity_evals( + evals: &[StageNamedEval], + symbols: &Stage67RelationSymbols, +) -> Result, RuntimePlanError> { + let mut values = indexed_evals_by_prefix_any(evals, symbols.booleanity_instruction_ra_prefix)?; + values.extend(indexed_evals_by_prefix_any( + evals, + symbols.booleanity_bytecode_ra_prefix, + )?); + values.extend(indexed_evals_by_prefix_any( + evals, + symbols.booleanity_ram_ra_prefix, + )?); + Ok(values) +} + +fn stage67_bytecode_stage_cycle_points( + store: &ValueStore, + log_t: usize, + symbols: &Stage67BytecodeSymbols, +) -> Result<[Vec; 5], RuntimePlanError> { + let point = |index| { + let symbol = symbols.stage_cycle_points[index]; + suffix_point(store_point(store, symbol)?, log_t, symbol).map(|point| point.to_vec()) + }; + Ok([point(0)?, point(1)?, point(2)?, point(3)?, point(4)?]) +} + +fn stage67_bytecode_stage_value_evals( + entries: &[E], + entry_bytecode_index: usize, + num_lookup_tables: usize, + store: &ValueStore, + r_address: &[Fr], + log_t: usize, + symbols: &Stage67BytecodeSymbols, +) -> Result<[Fr; 5], RuntimePlanError> { + let expected_len = + 1usize + .checked_shl(r_address.len() as u32) + .ok_or(RuntimePlanError::InvalidInputLength { + input: symbols.entries, + expected: usize::BITS as usize, + actual: r_address.len(), + })?; + if entries.len() != expected_len { + return Err(RuntimePlanError::InvalidInputLength { + input: symbols.entries, + expected: expected_len, + actual: entries.len(), + }); + } + if entry_bytecode_index >= expected_len { + return Err(RuntimePlanError::InvalidInputLength { + input: symbols.entry_bytecode_index, + expected: expected_len, + actual: entry_bytecode_index + 1, + }); + } + + let stage1_gamma_powers = field_powers(store_scalar(store, symbols.stage_gammas[0])?, 16); + let stage2_gamma_powers = field_powers(store_scalar(store, symbols.stage_gammas[1])?, 4); + let stage3_gamma_powers = field_powers(store_scalar(store, symbols.stage_gammas[2])?, 9); + let stage4_gamma_powers = field_powers(store_scalar(store, symbols.stage_gammas[3])?, 3); + let stage5_gamma_powers = field_powers( + store_scalar(store, symbols.stage_gammas[4])?, + num_lookup_tables + 2, + ); + + let stage4_register_point = + stage67_register_prefix_point(store, symbols.stage4_register_point, log_t)?; + let stage5_register_point = + stage67_register_prefix_point(store, symbols.stage5_register_point, log_t)?; + + let mut evals = [Fr::from_u64(0); 5]; + for (index, entry) in entries.iter().enumerate() { + let eq = indexed_boolean_eq(index, r_address); + let values = stage67_bytecode_entry_stage_values( + entry, + num_lookup_tables, + stage4_register_point, + stage5_register_point, + &stage1_gamma_powers, + &stage2_gamma_powers, + &stage3_gamma_powers, + &stage4_gamma_powers, + &stage5_gamma_powers, + symbols, + )?; + for stage in 0..evals.len() { + evals[stage] += eq * values[stage]; + } + } + Ok(evals) +} + +fn stage67_bytecode_entry_stage_values( + entry: &E, + num_lookup_tables: usize, + stage4_register_point: &[Fr], + stage5_register_point: &[Fr], + stage1_gamma_powers: &[Fr], + stage2_gamma_powers: &[Fr], + stage3_gamma_powers: &[Fr], + stage4_gamma_powers: &[Fr], + stage5_gamma_powers: &[Fr], + symbols: &Stage67BytecodeSymbols, +) -> Result<[Fr; 5], RuntimePlanError> { + let flags = entry.circuit_flags(); + let mut stage1 = entry.address() + entry.imm() * stage1_gamma_powers[1]; + for (flag, gamma) in flags.iter().zip(stage1_gamma_powers.iter().skip(2)) { + if *flag { + stage1 += *gamma; + } + } + + let mut stage2 = Fr::from_u64(0); + if flags[5] { + stage2 += stage2_gamma_powers[0]; + } + if entry.is_branch() { + stage2 += stage2_gamma_powers[1]; + } + if flags[6] { + stage2 += stage2_gamma_powers[2]; + } + if flags[7] { + stage2 += stage2_gamma_powers[3]; + } + + let mut stage3 = entry.imm() + entry.address() * stage3_gamma_powers[1]; + if entry.left_is_rs1() { + stage3 += stage3_gamma_powers[2]; + } + if entry.left_is_pc() { + stage3 += stage3_gamma_powers[3]; + } + if entry.right_is_rs2() { + stage3 += stage3_gamma_powers[4]; + } + if entry.right_is_imm() { + stage3 += stage3_gamma_powers[5]; + } + if entry.is_noop() { + stage3 += stage3_gamma_powers[6]; + } + if flags[7] { + stage3 += stage3_gamma_powers[7]; + } + if flags[12] { + stage3 += stage3_gamma_powers[8]; + } + + let stage4 = stage67_register_eq(entry.rd(), stage4_register_point, symbols.entry_rd)? + * stage4_gamma_powers[0] + + stage67_register_eq(entry.rs1(), stage4_register_point, symbols.entry_rs1)? + * stage4_gamma_powers[1] + + stage67_register_eq(entry.rs2(), stage4_register_point, symbols.entry_rs2)? + * stage4_gamma_powers[2]; + + let mut stage5 = stage67_register_eq(entry.rd(), stage5_register_point, symbols.entry_rd)? + * stage5_gamma_powers[0]; + if !entry.is_interleaved() { + stage5 += stage5_gamma_powers[1]; + } + if let Some(table) = entry.lookup_table() { + if table >= num_lookup_tables { + return Err(RuntimePlanError::InvalidInputLength { + input: symbols.entry_lookup_table, + expected: num_lookup_tables, + actual: table + 1, + }); + } + stage5 += stage5_gamma_powers[2 + table]; + } + + Ok([stage1, stage2, stage3, stage4, stage5]) +} + +fn stage67_register_eq( + index: Option, + point: &[Fr], + input: &'static str, +) -> Result { + let Some(index) = index else { + return Ok(Fr::from_u64(0)); + }; + let register_count = + 1usize + .checked_shl(point.len() as u32) + .ok_or(RuntimePlanError::InvalidInputLength { + input, + expected: usize::BITS as usize, + actual: point.len(), + })?; + if index >= register_count { + return Err(RuntimePlanError::InvalidInputLength { + input, + expected: register_count, + actual: index + 1, + }); + } + Ok(indexed_boolean_eq(index, point)) +} + +fn stage67_register_prefix_point<'a>( + store: &'a ValueStore, + symbol: &'static str, + log_t: usize, +) -> Result<&'a [Fr], RuntimePlanError> { + let point = store_point(store, symbol)?; + let register_len = + point + .len() + .checked_sub(log_t) + .ok_or(RuntimePlanError::InvalidInputLength { + input: symbol, + expected: log_t, + actual: point.len(), + })?; + prefix_point(point, register_len, symbol) +} + +pub fn operand_polynomial_eval(point: &[Fr], left: bool) -> Fr { + let stride_offset = usize::from(!left); + let operand_bits = point.len() / 2; + (0..operand_bits) + .map(|index| point[2 * index + stride_offset].mul_pow_2(operand_bits - 1 - index)) + .sum() +} + +pub fn identity_polynomial_eval(point: &[Fr]) -> Fr { + point + .iter() + .enumerate() + .map(|(index, value)| value.mul_pow_2(point.len() - 1 - index)) + .sum() +} + +pub fn append_labeled_scalar(transcript: &mut T, label: &'static str, scalar: &Fr) +where + T: Transcript, +{ + transcript.append(&Label(label.as_bytes())); + transcript.append(scalar); +} + +pub fn append_opening_claims( + opening_inputs: &[OpeningInputPlan], + opening_claims: &[OpeningClaimPlan], + opening_batches: &[OpeningBatchPlan], + store: &mut ValueStore, + transcript: &mut T, + evals: &[StageNamedEval], + missing_claim: impl Fn(&'static str, &'static str) -> E, + missing_value: impl Fn(&'static str) -> E, +) -> Result<(), E> +where + T: Transcript, +{ + if opening_batches.is_empty() { + for eval in evals { + append_labeled_scalar(transcript, "opening_claim", &eval.value); + } + return Ok(()); + } + let mut seen = opening_inputs + .iter() + .filter_map(|input| { + store + .try_point(input.symbol) + .map(|point| (input.claim_kind, input.oracle, point.to_vec())) + }) + .collect::>(); + for batch in opening_batches { + for symbol in symbol_list(batch.claim_operands) { + let claim = opening_claims + .iter() + .find(|claim| claim.symbol == symbol) + .ok_or_else(|| missing_claim(batch.symbol, symbol))?; + let point = store.point_or(claim.point_source, &missing_value)?.to_vec(); + if seen.iter().any(|(kind, oracle, seen_point)| { + *kind == claim.claim_kind && *oracle == claim.oracle && seen_point == &point + }) { + continue; + } + let value = store.scalar_or(claim.eval_source, &missing_value)?; + append_labeled_scalar(transcript, "opening_claim", &value); + seen.push((claim.claim_kind, claim.oracle, point)); + } + } + Ok(()) +} + +pub fn lt_polynomial_eval(x: &[Fr], y: &[Fr]) -> Fr { + let mut lt_eval = Fr::from_u64(0); + let mut eq_term = Fr::from_u64(1); + for (x_i, y_i) in x.iter().zip(y.iter()) { + lt_eval += (Fr::from_u64(1) - *x_i) * *y_i * eq_term; + eq_term *= Fr::from_u64(1) - *x_i - *y_i + *x_i * *y_i + *x_i * *y_i; + } + lt_eval +} + +pub fn pow_field(base: F, mut exponent: usize) -> F { + let mut result = F::one(); + let mut power = base; + while exponent != 0 { + if exponent & 1 == 1 { + result *= power; + } + power = power.square(); + exponent >>= 1; + } + result +} + +pub fn reverse_slice(values: &[Fr]) -> Vec { + values.iter().rev().copied().collect() +} diff --git a/crates/bolt/src/protocols/mod.rs b/crates/bolt/src/protocols/mod.rs new file mode 100644 index 0000000000..5e01eb0c28 --- /dev/null +++ b/crates/bolt/src/protocols/mod.rs @@ -0,0 +1 @@ +pub mod jolt; diff --git a/crates/bolt/src/schema.rs b/crates/bolt/src/schema.rs new file mode 100644 index 0000000000..46e963c4e7 --- /dev/null +++ b/crates/bolt/src/schema.rs @@ -0,0 +1,1466 @@ +use std::collections::BTreeSet; +use std::error::Error; +use std::fmt::{self, Display, Formatter}; + +use melior::ir::block::BlockLike; +use melior::ir::operation::OperationLike; +use melior::ir::operation::OperationResult; +use melior::ir::{Attribute, OperationRef}; + +use crate::ir::{ + string_attribute_value, symbol_attribute_value, BoltModule, Compute, Concrete, Cpu, Party, + Protocol, Role, +}; +use crate::mlir::MlirError; +use crate::pass::{verify_concrete_transcript, VerifyError}; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct SchemaError { + message: String, +} + +impl SchemaError { + pub(crate) fn new(message: impl Into) -> Self { + Self { + message: message.into(), + } + } +} + +impl Display for SchemaError { + fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result { + formatter.write_str(&self.message) + } +} + +impl Error for SchemaError {} + +impl From for MlirError { + fn from(error: SchemaError) -> Self { + Self::Schema { + message: error.to_string(), + } + } +} + +impl From for SchemaError { + fn from(error: VerifyError) -> Self { + Self::new(error.to_string()) + } +} + +pub fn verify_protocol_schema(module: &BoltModule<'_, Protocol>) -> Result<(), SchemaError> { + verify_schema(module, ModulePhase::Protocol) +} + +pub fn verify_concrete_schema(module: &BoltModule<'_, Concrete>) -> Result<(), SchemaError> { + verify_schema(module, ModulePhase::Concrete)?; + verify_concrete_transcript(module)?; + Ok(()) +} + +pub fn verify_party_schema(module: &BoltModule<'_, Party>) -> Result<(), SchemaError> { + verify_schema(module, ModulePhase::Party)?; + verify_concrete_transcript(module)?; + Ok(()) +} + +pub fn verify_compute_schema(module: &BoltModule<'_, Compute>) -> Result<(), SchemaError> { + verify_schema(module, ModulePhase::Compute) +} + +pub fn verify_cpu_schema(module: &BoltModule<'_, Cpu>) -> Result<(), SchemaError> { + verify_schema(module, ModulePhase::Cpu) +} + +#[derive(Clone, Copy)] +enum ModulePhase { + Protocol, + Concrete, + Party, + Compute, + Cpu, +} + +fn verify_schema

(module: &BoltModule<'_, P>, phase: ModulePhase) -> Result<(), SchemaError> +where + P: crate::ir::Phase, +{ + let phase_attr = module + .as_mlir_module() + .as_operation() + .attribute("bolt.phase") + .ok() + .and_then(string_attribute_value) + .ok_or_else(|| SchemaError::new("module missing required attr `bolt.phase`"))?; + if phase_attr != P::NAME { + return Err(SchemaError::new(format!( + "module phase `{phase_attr}` does not match expected `{}`", + P::NAME + ))); + } + + let mut kernel_symbols = BTreeSet::new(); + let mut kernel_refs = Vec::new(); + let role = module.role(); + let mut operation = module.as_mlir_module().body().first_operation(); + while let Some(op) = operation { + operation = op.next_in_block(); + validate_op(op, phase)?; + if matches!(role, Some(Role::Verifier)) + && matches!(phase, ModulePhase::Compute | ModulePhase::Cpu) + { + validate_verifier_lowering_op(op)?; + } + match operation_name(op).as_str() { + "compute.kernel" | "cpu.kernel" => { + let _ = kernel_symbols.insert(string_attr(op, "sym_name")?); + } + "compute.sumcheck_kernel_claim" + | "compute.sumcheck_kernel_driver" + | "cpu.sumcheck_claim" + | "cpu.sumcheck_driver" => { + kernel_refs.push(symbol_attr(op, "kernel")?); + } + _ => {} + } + } + + if matches!(phase, ModulePhase::Compute | ModulePhase::Cpu) { + for kernel in kernel_refs { + if !kernel_symbols.contains(&kernel) { + return Err(SchemaError::new(format!( + "kernel reference @{kernel} has no matching kernel definition" + ))); + } + } + } + + Ok(()) +} + +fn validate_verifier_lowering_op(operation: OperationRef<'_, '_>) -> Result<(), SchemaError> { + let name = operation_name(operation); + match name.as_str() { + "compute.kernel" + | "compute.sumcheck_claim" + | "compute.sumcheck_driver" + | "compute.sumcheck_kernel_claim" + | "compute.sumcheck_kernel_driver" + | "compute.generate_oracle" + | "compute.generate_oracle_family" + | "cpu.kernel" + | "cpu.sumcheck_claim" + | "cpu.sumcheck_driver" => Err(SchemaError::new(format!( + "verifier lowering must use verifier-specific ops, got `{name}`" + ))), + _ => Ok(()), + } +} + +fn validate_op(operation: OperationRef<'_, '_>, _phase: ModulePhase) -> Result<(), SchemaError> { + let name = operation_name(operation); + match name.as_str() { + "field.define" => require_attrs(operation, &["sym_name", "modulus_bits", "role"]), + "field.const" => { + require_attrs(operation, &["sym_name", "field", "value"])?; + require_shape(operation, 0, 1) + } + "field.zero" | "field.one" => { + require_attrs(operation, &["sym_name", "field"])?; + require_shape(operation, 0, 1) + } + "field.add" | "field.sub" | "field.mul" => { + require_attrs(operation, &["sym_name"])?; + require_shape(operation, 2, 1) + } + "field.neg" => { + require_attrs(operation, &["sym_name"])?; + require_shape(operation, 1, 1) + } + "field.pow" => { + require_attrs(operation, &["sym_name", "exponent"])?; + require_shape(operation, 1, 1) + } + "hash.function" => require_attrs(operation, &["sym_name", "algorithm"]), + "transcript.scheme" => require_attrs(operation, &["sym_name", "hash"]), + "pcs.scheme" => require_attrs(operation, &["sym_name", "field"]), + "poly.domain" => require_attrs(operation, &["sym_name", "field", "log_size"]), + "poly.point_slice" => { + require_attrs(operation, &["sym_name", "source", "offset", "length"])?; + require_shape(operation, 1, 1) + } + "poly.point_zero" => { + require_attrs(operation, &["sym_name", "field", "arity"])?; + require_shape(operation, 0, 1) + } + "poly.point_concat" => { + require_attrs(operation, &["sym_name", "layout", "arity"])?; + require_min_shape(operation, 1, 1) + } + "poly.lagrange_basis_eval" => { + require_attrs( + operation, + &["sym_name", "domain_start", "domain_size", "index"], + )?; + require_shape(operation, 1, 1) + } + "protocol.params" => require_attrs(operation, &["sym_name", "field", "pcs", "transcript"]), + "protocol.boundary" => require_attrs(operation, &["sym_name", "roles"]), + "piop.oracle" => require_attrs( + operation, + &[ + "sym_name", + "field", + "domain", + "commit_domain", + "visibility", + "layout", + ], + ), + "piop.oracle_family" => require_attrs( + operation, + &[ + "sym_name", + "ordered_oracles", + "visibility", + "count", + "domain", + ], + ), + "commit.publish_batch" => { + require_attrs(operation, &["sym_name", "oracle_family", "label"])?; + require_shape(operation, 0, 1) + } + "commit.publish_optional" => { + require_attrs(operation, &["sym_name", "oracle", "label", "skip_policy"])?; + require_shape(operation, 0, 1) + } + "pcs.commit_batch" => { + require_attrs(operation, &["sym_name", "scheme"])?; + require_shape(operation, 1, 0) + } + "transcript.absorb" | "transcript.absorb_optional" => { + require_attrs(operation, &["sym_name", "label"])?; + require_shape(operation, 2, 1) + } + "transcript.absorb_bytes" => { + require_attrs(operation, &["sym_name", "label", "payload"])?; + require_shape(operation, 1, 1) + } + "transcript.squeeze" => { + require_attrs(operation, &["sym_name", "label", "kind", "count"])?; + require_shape(operation, 1, 2) + } + "transcript.state" => { + require_attrs(operation, &["sym_name", "scheme"])?; + require_shape(operation, 0, 1) + } + "piop.stage" => { + require_attrs(operation, &["sym_name", "name", "order", "roles"])?; + require_shape(operation, 0, 1) + } + "piop.relation" => require_attrs( + operation, + &[ + "sym_name", + "kind", + "domain", + "num_rounds", + "degree", + "output_count", + ], + ), + "piop.sumcheck_claim" => { + require_attrs( + operation, + &[ + "sym_name", + "stage", + "domain", + "num_rounds", + "degree", + "claim", + "relation", + ], + )?; + require_min_shape(operation, 1, 1) + } + "piop.opening_input" => { + require_attrs( + operation, + &[ + "sym_name", + "source_stage", + "source_claim", + "oracle", + "domain", + "point_arity", + "claim_kind", + ], + )?; + require_shape(operation, 0, 3) + } + "piop.sumcheck_batch" => { + require_attrs( + operation, + &[ + "sym_name", + "stage", + "proof_slot", + "policy", + "count", + "ordered_claims", + "claim_label", + "round_label", + "round_schedule", + ], + )?; + require_min_shape(operation, 1, 1)?; + require_counted_operands(operation, 1, "ordered_claims") + } + "piop.sumcheck" => { + require_attrs( + operation, + &[ + "sym_name", + "stage", + "proof_slot", + "relation", + "policy", + "round_schedule", + "claim_label", + "round_label", + "num_rounds", + "degree", + ], + )?; + require_shape(operation, 2, 4) + } + "piop.sumcheck_eval" => { + require_attrs( + operation, + &["sym_name", "source", "name", "index", "oracle"], + )?; + require_shape(operation, 1, 1) + } + "piop.sumcheck_instance_result" => { + require_attrs( + operation, + &[ + "sym_name", + "source", + "claim", + "relation", + "index", + "point_arity", + "num_rounds", + "round_offset", + "point_order", + "degree", + ], + )?; + require_shape(operation, 2, 2) + } + "piop.opening_claim" => { + require_attrs( + operation, + &["sym_name", "oracle", "domain", "point_arity", "claim_kind"], + )?; + require_shape(operation, 2, 1) + } + "piop.opening_claim_equal" => { + require_attrs(operation, &["sym_name", "mode"])?; + require_shape(operation, 2, 0)?; + require_opening_claim_equality(operation) + } + "piop.opening_batch" => { + require_attrs( + operation, + &[ + "sym_name", + "stage", + "proof_slot", + "policy", + "count", + "ordered_claims", + ], + )?; + require_min_shape(operation, 0, 1)?; + require_counted_operands(operation, 0, "ordered_claims") + } + "party.function" => require_attrs(operation, &["sym_name", "source", "role"]), + "compute.params" => require_attrs(operation, &["sym_name", "field", "pcs", "transcript"]), + "compute.function" => require_attrs(operation, &["sym_name", "source"]), + "compute.relation" => require_attrs( + operation, + &[ + "sym_name", + "kind", + "domain", + "num_rounds", + "degree", + "output_count", + ], + ), + "compute.kernel" => require_attrs( + operation, + &["sym_name", "relation", "kind", "backend", "abi"], + ), + "compute.oracle_dense_trace" => { + require_attrs( + operation, + &[ + "sym_name", "oracle", "source", "domain", "num_vars", "padding", + ], + )?; + require_shape(operation, 0, 1) + } + "compute.oracle_one_hot_chunk" => { + require_attrs( + operation, + &[ + "sym_name", + "oracle", + "source", + "domain", + "num_vars", + "trace_num_vars", + "chunk", + "num_chunks", + "chunk_bits", + "padding", + "layout", + ], + )?; + require_shape(operation, 0, 1) + } + "compute.oracle_optional_advice" => { + require_attrs( + operation, + &[ + "sym_name", + "oracle", + "source", + "domain", + "num_vars", + "skip_policy", + ], + )?; + require_shape(operation, 0, 1) + } + "compute.oracle_ref" => { + require_attrs(operation, &["sym_name", "oracle", "domain", "num_vars"])?; + require_shape(operation, 0, 1) + } + "compute.oracle_family_init" => { + require_attrs(operation, &["sym_name", "family", "count"])?; + require_shape(operation, 0, 1) + } + "compute.oracle_family_append" => { + require_attrs(operation, &["sym_name", "family", "oracle", "index"])?; + require_shape(operation, 2, 1) + } + "compute.pcs_commit_batch" | "compute.pcs_receive_batch" => { + require_attrs( + operation, + &[ + "sym_name", + "artifact", + "pcs", + "oracle_family", + "ordered_oracles", + "label", + "domain", + "num_vars", + "count", + ], + )?; + require_shape(operation, 1, 1) + } + "compute.pcs_commit_optional" | "compute.pcs_receive_optional" => { + require_attrs( + operation, + &[ + "sym_name", + "artifact", + "pcs", + "oracle", + "label", + "domain", + "num_vars", + "skip_policy", + ], + )?; + require_shape(operation, 1, 1) + } + "compute.transcript_init" => { + require_attrs(operation, &["sym_name", "scheme"])?; + require_shape(operation, 0, 1) + } + "compute.transcript_absorb" => { + require_attrs(operation, &["sym_name", "label", "optional"])?; + require_shape(operation, 2, 1) + } + "compute.transcript_absorb_bytes" => { + require_attrs(operation, &["sym_name", "label", "payload"])?; + require_shape(operation, 1, 1) + } + "compute.transcript_squeeze" => { + require_attrs(operation, &["sym_name", "label", "kind", "count"])?; + require_shape(operation, 1, 2) + } + "compute.opening_input" => { + require_attrs( + operation, + &[ + "sym_name", + "source_stage", + "source_claim", + "oracle", + "domain", + "point_arity", + "claim_kind", + ], + )?; + require_shape(operation, 0, 3) + } + "compute.point_slice" => { + require_attrs(operation, &["sym_name", "source", "offset", "length"])?; + require_shape(operation, 1, 1) + } + "compute.point_zero" => { + require_attrs(operation, &["sym_name", "field", "arity"])?; + require_shape(operation, 0, 1) + } + "compute.point_concat" => { + require_attrs(operation, &["sym_name", "layout", "arity"])?; + require_min_shape(operation, 1, 1) + } + "compute.field_const" => { + require_attrs(operation, &["sym_name", "field", "value"])?; + require_shape(operation, 0, 1) + } + "compute.field_zero" | "compute.field_one" => { + require_attrs(operation, &["sym_name", "field"])?; + require_shape(operation, 0, 1) + } + "compute.field_add" | "compute.field_sub" | "compute.field_mul" => { + require_attrs(operation, &["sym_name"])?; + require_shape(operation, 2, 1) + } + "compute.field_neg" => { + require_attrs(operation, &["sym_name"])?; + require_shape(operation, 1, 1) + } + "compute.field_pow" => { + require_attrs(operation, &["sym_name", "exponent"])?; + require_shape(operation, 1, 1) + } + "compute.poly_lagrange_basis_eval" => { + require_attrs( + operation, + &["sym_name", "domain_start", "domain_size", "index"], + )?; + require_shape(operation, 1, 1) + } + "compute.sumcheck_claim" => { + require_attrs( + operation, + &[ + "sym_name", + "stage", + "domain", + "num_rounds", + "degree", + "claim", + "relation", + ], + )?; + require_min_shape(operation, 1, 1) + } + "compute.sumcheck_kernel_claim" => { + require_attrs( + operation, + &[ + "sym_name", + "stage", + "domain", + "num_rounds", + "degree", + "claim", + "kernel", + ], + )?; + require_min_shape(operation, 1, 1) + } + "compute.sumcheck_verify_claim" => { + require_attrs( + operation, + &[ + "sym_name", + "stage", + "domain", + "num_rounds", + "degree", + "claim", + "relation", + ], + )?; + require_min_shape(operation, 1, 1) + } + "compute.sumcheck_batch" => { + require_attrs( + operation, + &[ + "sym_name", + "stage", + "proof_slot", + "policy", + "count", + "ordered_claims", + "claim_label", + "round_label", + "round_schedule", + ], + )?; + require_min_shape(operation, 0, 1)?; + require_counted_operands(operation, 0, "ordered_claims") + } + "compute.sumcheck_driver" => { + require_attrs( + operation, + &[ + "sym_name", + "stage", + "proof_slot", + "relation", + "policy", + "round_schedule", + "claim_label", + "round_label", + "num_rounds", + "degree", + ], + )?; + require_shape(operation, 2, 4) + } + "compute.sumcheck_kernel_driver" => { + require_attrs( + operation, + &[ + "sym_name", + "stage", + "proof_slot", + "kernel", + "policy", + "round_schedule", + "claim_label", + "round_label", + "num_rounds", + "degree", + ], + )?; + require_shape(operation, 2, 4) + } + "compute.sumcheck_verify" => { + require_attrs( + operation, + &[ + "sym_name", + "stage", + "proof_slot", + "relation", + "policy", + "round_schedule", + "claim_label", + "round_label", + "num_rounds", + "degree", + ], + )?; + require_shape(operation, 2, 4) + } + "compute.sumcheck_eval" => { + require_attrs( + operation, + &["sym_name", "source", "name", "index", "oracle"], + )?; + require_shape(operation, 1, 1) + } + "compute.sumcheck_instance_result" => { + require_attrs( + operation, + &[ + "sym_name", + "source", + "claim", + "relation", + "index", + "point_arity", + "num_rounds", + "round_offset", + "point_order", + "degree", + ], + )?; + require_shape(operation, 2, 2) + } + "compute.opening_claim" => { + require_attrs( + operation, + &["sym_name", "oracle", "domain", "point_arity", "claim_kind"], + )?; + require_shape(operation, 2, 1) + } + "compute.opening_claim_equal" => { + require_attrs(operation, &["sym_name", "mode"])?; + require_shape(operation, 2, 0)?; + require_opening_claim_equality(operation) + } + "compute.opening_batch" => { + require_attrs( + operation, + &[ + "sym_name", + "stage", + "proof_slot", + "policy", + "count", + "ordered_claims", + ], + )?; + require_min_shape(operation, 0, 1)?; + require_counted_operands(operation, 0, "ordered_claims") + } + "compute.pcs_opening_claim" => { + require_attrs( + operation, + &["sym_name", "oracle", "family", "domain", "point_arity"], + )?; + require_shape(operation, 2, 1) + } + "compute.pcs_opening_batch" => { + require_attrs( + operation, + &[ + "sym_name", + "proof_slot", + "policy", + "count", + "ordered_claims", + ], + )?; + require_min_shape(operation, 0, 1)?; + require_counted_operands(operation, 0, "ordered_claims") + } + "compute.pcs_batch_open" | "compute.pcs_batch_verify" => { + require_attrs( + operation, + &["sym_name", "pcs", "proof_slot", "transcript_label"], + )?; + require_shape(operation, 2, 2) + } + "cpu.params" => require_attrs(operation, &["sym_name", "field", "pcs", "transcript"]), + "cpu.function" => require_attrs(operation, &["sym_name", "source"]), + "cpu.oracle_dense_trace" => { + require_attrs( + operation, + &[ + "sym_name", "oracle", "source", "domain", "num_vars", "padding", + ], + )?; + require_shape(operation, 0, 1) + } + "cpu.oracle_one_hot_chunk" => { + require_attrs( + operation, + &[ + "sym_name", + "oracle", + "source", + "domain", + "num_vars", + "trace_num_vars", + "chunk", + "num_chunks", + "chunk_bits", + "padding", + "layout", + ], + )?; + require_shape(operation, 0, 1) + } + "cpu.oracle_optional_advice" => { + require_attrs( + operation, + &[ + "sym_name", + "oracle", + "source", + "domain", + "num_vars", + "skip_policy", + ], + )?; + require_shape(operation, 0, 1) + } + "cpu.oracle_ref" => { + require_attrs(operation, &["sym_name", "oracle", "domain", "num_vars"])?; + require_shape(operation, 0, 1) + } + "cpu.oracle_family_init" => { + require_attrs(operation, &["sym_name", "family", "count"])?; + require_shape(operation, 0, 1) + } + "cpu.oracle_family_append" => { + require_attrs(operation, &["sym_name", "family", "oracle", "index"])?; + require_shape(operation, 2, 1) + } + "cpu.pcs_commit_batch" | "cpu.pcs_receive_batch" => { + require_attrs( + operation, + &[ + "sym_name", + "artifact", + "pcs", + "oracle_family", + "ordered_oracles", + "label", + "domain", + "num_vars", + "count", + ], + )?; + require_shape(operation, 1, 1) + } + "cpu.pcs_commit_optional" | "cpu.pcs_receive_optional" => { + require_attrs( + operation, + &[ + "sym_name", + "artifact", + "pcs", + "oracle", + "label", + "domain", + "num_vars", + "skip_policy", + ], + )?; + require_shape(operation, 1, 1) + } + "cpu.transcript_init" => { + require_attrs(operation, &["sym_name", "scheme"])?; + require_shape(operation, 0, 1) + } + "cpu.transcript_absorb" => { + require_attrs(operation, &["sym_name", "label", "optional"])?; + require_shape(operation, 2, 1) + } + "cpu.transcript_absorb_bytes" => { + require_attrs(operation, &["sym_name", "label", "payload"])?; + require_shape(operation, 1, 1) + } + "cpu.transcript_squeeze" => { + require_attrs(operation, &["sym_name", "label", "kind", "count"])?; + require_shape(operation, 1, 2) + } + "cpu.opening_input" => { + require_attrs( + operation, + &[ + "sym_name", + "source_stage", + "source_claim", + "oracle", + "domain", + "point_arity", + "claim_kind", + ], + )?; + require_shape(operation, 0, 3) + } + "cpu.point_slice" => { + require_attrs(operation, &["sym_name", "source", "offset", "length"])?; + require_shape(operation, 1, 1) + } + "cpu.point_zero" => { + require_attrs(operation, &["sym_name", "field", "arity"])?; + require_shape(operation, 0, 1) + } + "cpu.point_concat" => { + require_attrs(operation, &["sym_name", "layout", "arity"])?; + require_min_shape(operation, 1, 1) + } + "cpu.field_const" => { + require_attrs(operation, &["sym_name", "field", "value"])?; + require_shape(operation, 0, 1) + } + "cpu.field_zero" | "cpu.field_one" => { + require_attrs(operation, &["sym_name", "field"])?; + require_shape(operation, 0, 1) + } + "cpu.field_add" | "cpu.field_sub" | "cpu.field_mul" => { + require_attrs(operation, &["sym_name"])?; + require_shape(operation, 2, 1) + } + "cpu.field_neg" => { + require_attrs(operation, &["sym_name"])?; + require_shape(operation, 1, 1) + } + "cpu.field_pow" => { + require_attrs(operation, &["sym_name", "exponent"])?; + require_shape(operation, 1, 1) + } + "cpu.poly_lagrange_basis_eval" => { + require_attrs( + operation, + &["sym_name", "domain_start", "domain_size", "index"], + )?; + require_shape(operation, 1, 1) + } + "cpu.kernel" => require_attrs( + operation, + &["sym_name", "relation", "kind", "backend", "abi"], + ), + "cpu.sumcheck_claim" => { + require_attrs( + operation, + &[ + "sym_name", + "stage", + "domain", + "num_rounds", + "degree", + "claim", + "kernel", + ], + )?; + require_min_shape(operation, 1, 1) + } + "cpu.sumcheck_verify_claim" => { + require_attrs( + operation, + &[ + "sym_name", + "stage", + "domain", + "num_rounds", + "degree", + "claim", + "relation", + ], + )?; + require_min_shape(operation, 1, 1) + } + "cpu.sumcheck_batch" => { + require_attrs( + operation, + &[ + "sym_name", + "stage", + "proof_slot", + "policy", + "count", + "ordered_claims", + "claim_label", + "round_label", + "round_schedule", + ], + )?; + require_min_shape(operation, 0, 1)?; + require_counted_operands(operation, 0, "ordered_claims") + } + "cpu.sumcheck_driver" => { + require_attrs( + operation, + &[ + "sym_name", + "stage", + "proof_slot", + "kernel", + "policy", + "round_schedule", + "claim_label", + "round_label", + "num_rounds", + "degree", + ], + )?; + require_shape(operation, 2, 4) + } + "cpu.sumcheck_verify" => { + require_attrs( + operation, + &[ + "sym_name", + "stage", + "proof_slot", + "relation", + "policy", + "round_schedule", + "claim_label", + "round_label", + "num_rounds", + "degree", + ], + )?; + require_shape(operation, 2, 4) + } + "cpu.sumcheck_eval" => { + require_attrs( + operation, + &["sym_name", "source", "name", "index", "oracle"], + )?; + require_shape(operation, 1, 1) + } + "cpu.sumcheck_instance_result" => { + require_attrs( + operation, + &[ + "sym_name", + "source", + "claim", + "relation", + "index", + "point_arity", + "num_rounds", + "round_offset", + "point_order", + "degree", + ], + )?; + require_shape(operation, 2, 2) + } + "cpu.opening_claim" => { + require_attrs( + operation, + &["sym_name", "oracle", "domain", "point_arity", "claim_kind"], + )?; + require_shape(operation, 2, 1) + } + "cpu.opening_claim_equal" => { + require_attrs(operation, &["sym_name", "mode"])?; + require_shape(operation, 2, 0)?; + require_opening_claim_equality(operation) + } + "cpu.opening_batch" => { + require_attrs( + operation, + &[ + "sym_name", + "stage", + "proof_slot", + "policy", + "count", + "ordered_claims", + ], + )?; + require_min_shape(operation, 0, 1)?; + require_counted_operands(operation, 0, "ordered_claims") + } + "cpu.pcs_opening_claim" => { + require_attrs( + operation, + &["sym_name", "oracle", "family", "domain", "point_arity"], + )?; + require_shape(operation, 2, 1) + } + "cpu.pcs_opening_batch" => { + require_attrs( + operation, + &[ + "sym_name", + "proof_slot", + "policy", + "count", + "ordered_claims", + ], + )?; + require_min_shape(operation, 0, 1)?; + require_counted_operands(operation, 0, "ordered_claims") + } + "cpu.pcs_batch_open" | "cpu.pcs_batch_verify" => { + require_attrs( + operation, + &["sym_name", "pcs", "proof_slot", "transcript_label"], + )?; + require_shape(operation, 2, 2) + } + "pcs.opening_claim" => { + require_attrs( + operation, + &["sym_name", "oracle", "family", "domain", "point_arity"], + )?; + require_shape(operation, 2, 1) + } + "pcs.opening_batch" => { + require_attrs( + operation, + &[ + "sym_name", + "proof_slot", + "policy", + "count", + "ordered_claims", + ], + )?; + require_min_shape(operation, 0, 1)?; + require_counted_operands(operation, 0, "ordered_claims") + } + "pcs.batch_open" | "pcs.batch_verify" => { + require_attrs( + operation, + &["sym_name", "pcs", "proof_slot", "transcript_label"], + )?; + require_shape(operation, 2, 2) + } + _ if is_bolt_dialect_op(&name) => Err(SchemaError::new(format!( + "unknown Bolt op `{name}` in schema verifier" + ))), + _ => Ok(()), + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +struct OpeningClaimMetadata { + owner: String, + oracle: String, + domain: String, + point_arity: usize, + claim_kind: String, +} + +fn require_opening_claim_equality(operation: OperationRef<'_, '_>) -> Result<(), SchemaError> { + let mode = string_attr(operation, "mode")?; + if mode != "point_and_eval" { + return Err(SchemaError::new(format!( + "{} attr `mode` expected \"point_and_eval\", got \"{mode}\"", + operation_name(operation) + ))); + } + + let left = opening_claim_metadata(operation, 0)?; + let right = opening_claim_metadata(operation, 1)?; + if left.oracle != right.oracle + || left.domain != right.domain + || left.point_arity != right.point_arity + || left.claim_kind != right.claim_kind + { + return Err(SchemaError::new(format!( + "{} compares incompatible claims @{} and @{}", + operation_name(operation), + left.owner, + right.owner + ))); + } + Ok(()) +} + +fn opening_claim_metadata( + equality_op: OperationRef<'_, '_>, + operand_index: usize, +) -> Result { + let operand = equality_op.operand(operand_index).map_err(|_| { + SchemaError::new(format!( + "{} missing required operand {operand_index}", + operation_name(equality_op) + )) + })?; + let owner = OperationResult::try_from(operand).map_err(|_| { + SchemaError::new(format!( + "{} operand {operand_index} must be an op result", + operation_name(equality_op) + )) + })?; + let operation = owner.owner(); + let result_number = owner.result_number(); + let expected_result = match operation_name(operation).as_str() { + "piop.opening_input" | "compute.opening_input" | "cpu.opening_input" => 2, + "piop.opening_claim" | "compute.opening_claim" | "cpu.opening_claim" => 0, + name => { + return Err(SchemaError::new(format!( + "{} operand {operand_index} must be an opening claim, got result from `{name}`", + operation_name(equality_op) + ))); + } + }; + if result_number != expected_result { + return Err(SchemaError::new(format!( + "{} operand {operand_index} must use opening claim result {expected_result}, got result {result_number}", + operation_name(equality_op) + ))); + } + + Ok(OpeningClaimMetadata { + owner: string_attr(operation, "sym_name")?, + oracle: symbol_attr(operation, "oracle")?, + domain: symbol_attr(operation, "domain")?, + point_arity: int_attr(operation, "point_arity")?, + claim_kind: string_attr(operation, "claim_kind")?, + }) +} + +fn require_shape( + operation: OperationRef<'_, '_>, + operands: usize, + results: usize, +) -> Result<(), SchemaError> { + if operation.operand_count() != operands { + return Err(SchemaError::new(format!( + "{} expected {operands} operands, got {}", + operation_name(operation), + operation.operand_count() + ))); + } + if operation.result_count() != results { + return Err(SchemaError::new(format!( + "{} expected {results} results, got {}", + operation_name(operation), + operation.result_count() + ))); + } + Ok(()) +} + +fn require_min_shape( + operation: OperationRef<'_, '_>, + min_operands: usize, + results: usize, +) -> Result<(), SchemaError> { + if operation.operand_count() < min_operands { + return Err(SchemaError::new(format!( + "{} expected at least {min_operands} operands, got {}", + operation_name(operation), + operation.operand_count() + ))); + } + if operation.result_count() != results { + return Err(SchemaError::new(format!( + "{} expected {results} results, got {}", + operation_name(operation), + operation.result_count() + ))); + } + Ok(()) +} + +fn require_counted_operands( + operation: OperationRef<'_, '_>, + fixed_operands: usize, + ordered_attr: &str, +) -> Result<(), SchemaError> { + let count = int_attr(operation, "count")?; + let dynamic_count = operation.operand_count().saturating_sub(fixed_operands); + if count != dynamic_count { + return Err(SchemaError::new(format!( + "{} attr `count` expected {dynamic_count}, got {count}", + operation_name(operation) + ))); + } + let ordered = symbol_array_attr(operation, ordered_attr)?; + if ordered.len() != count { + return Err(SchemaError::new(format!( + "{} attr `{ordered_attr}` length {} does not match count {count}", + operation_name(operation), + ordered.len() + ))); + } + for (index, expected) in ordered.iter().enumerate() { + let operand_index = fixed_operands + index; + let actual = operand_owner_symbol(operation, operand_index)?; + if &actual != expected { + return Err(SchemaError::new(format!( + "{} operand {operand_index} expected @{expected}, got @{actual}", + operation_name(operation) + ))); + } + } + Ok(()) +} + +pub(crate) fn require_attrs( + operation: OperationRef<'_, '_>, + attrs: &[&str], +) -> Result<(), SchemaError> { + for attr in attrs { + if !operation.has_attribute(attr) { + return Err(SchemaError::new(format!( + "{} missing required attr `{attr}`", + operation_name(operation) + ))); + } + } + Ok(()) +} + +pub(crate) fn operand_owner_symbol( + operation: OperationRef<'_, '_>, + index: usize, +) -> Result { + let operand = operation.operand(index).map_err(|_| { + SchemaError::new(format!( + "{} missing required operand {index}", + operation_name(operation) + )) + })?; + let owner = OperationResult::try_from(operand).map_err(|_| { + SchemaError::new(format!( + "{} operand {index} must be an op result", + operation_name(operation) + )) + })?; + owner + .owner() + .attribute("sym_name") + .ok() + .and_then(string_attribute_value) + .ok_or_else(|| { + SchemaError::new(format!( + "{} operand {index} owner missing sym_name", + operation_name(operation) + )) + }) +} + +pub(crate) fn require_symbol_attr_eq( + operation: OperationRef<'_, '_>, + attr: &str, + expected: &str, +) -> Result<(), SchemaError> { + let actual = symbol_attr(operation, attr)?; + if actual == expected { + Ok(()) + } else { + Err(SchemaError::new(format!( + "{} attr `{attr}` expected @{expected}, got @{actual}", + operation_name(operation) + ))) + } +} + +pub(crate) fn find_symbol<'c, P>( + module: &'c BoltModule<'_, P>, + symbol: &str, +) -> Option> +where + P: crate::ir::Phase, +{ + let mut operation = module.as_mlir_module().body().first_operation(); + while let Some(op) = operation { + operation = op.next_in_block(); + if op + .attribute("sym_name") + .ok() + .and_then(string_attribute_value) + .as_deref() + == Some(symbol) + { + return Some(op); + } + } + None +} + +pub(crate) fn symbol_attr( + operation: OperationRef<'_, '_>, + attr: &str, +) -> Result { + operation + .attribute(attr) + .ok() + .and_then(symbol_attribute_value) + .ok_or_else(|| attr_error(operation, attr, "symbol")) +} + +fn string_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .ok() + .and_then(string_attribute_value) + .ok_or_else(|| attr_error(operation, attr, "string")) +} + +pub(crate) fn symbol_array_attr( + operation: OperationRef<'_, '_>, + attr: &str, +) -> Result, SchemaError> { + let attribute = operation + .attribute(attr) + .map(|attribute| attribute.to_string()) + .ok() + .ok_or_else(|| attr_error(operation, attr, "symbol array"))?; + parse_symbol_array(&attribute).ok_or_else(|| attr_error(operation, attr, "symbol array")) +} + +fn parse_symbol_array(attribute: &str) -> Option> { + let inner = attribute.strip_prefix('[')?.strip_suffix(']')?.trim(); + if inner.is_empty() { + return Some(Vec::new()); + } + inner + .split(',') + .map(|item| item.trim().strip_prefix('@').map(ToOwned::to_owned)) + .collect() +} + +pub(crate) fn int_attr(operation: OperationRef<'_, '_>, attr: &str) -> Result { + operation + .attribute(attr) + .map(parse_integer_attr) + .ok() + .flatten() + .ok_or_else(|| attr_error(operation, attr, "integer")) +} + +fn parse_integer_attr(attribute: Attribute<'_>) -> Option { + attribute + .to_string() + .split_whitespace() + .next() + .and_then(|value| value.parse().ok()) +} + +fn attr_error(operation: OperationRef<'_, '_>, attr: &str, expected: &str) -> SchemaError { + SchemaError::new(format!( + "{} attr `{attr}` is not a {expected}", + operation_name(operation) + )) +} + +pub(crate) fn operation_name(operation: OperationRef<'_, '_>) -> String { + operation + .name() + .as_string_ref() + .as_str() + .unwrap_or("") + .to_owned() +} + +pub(crate) fn missing_module_op(name: &str) -> SchemaError { + SchemaError::new(format!("module missing required op `{name}`")) +} + +pub(crate) fn missing_symbol(symbol: &str) -> SchemaError { + SchemaError::new(format!("module missing required symbol @{symbol}")) +} + +fn is_bolt_dialect_op(name: &str) -> bool { + matches!( + name.split_once('.').map(|(dialect, _)| dialect), + Some( + "field" + | "poly" + | "hash" + | "transcript" + | "commit" + | "pcs" + | "protocol" + | "piop" + | "party" + | "compute" + | "cpu" + ) + ) +} diff --git a/crates/bolt/tests/commitment_ir.rs b/crates/bolt/tests/commitment_ir.rs new file mode 100644 index 0000000000..64c31d4016 --- /dev/null +++ b/crates/bolt/tests/commitment_ir.rs @@ -0,0 +1,4148 @@ +#![expect( + clippy::expect_used, + clippy::unwrap_used, + reason = "integration tests use explicit panic messages" +)] + +use bolt::protocols::jolt::{ + assemble_jolt_generated_crates, assemble_jolt_workspace_generated_crates, + build_commitment_protocol, build_stage1_outer_protocol, build_stage2_protocol, + build_stage3_protocol, build_stage4_protocol, build_stage5_protocol, build_stage6_protocol, + build_stage7_protocol, build_stage8_protocol, commitment_cpu_program, emit_commitment_rust, + emit_stage1_rust, emit_stage2_rust, emit_stage3_rust, emit_stage4_rust, emit_stage5_rust, + emit_stage6_rust, emit_stage7_rust, emit_stage8_rust, jolt_artifact_config, jolt_rust_artifact, + lower_commitment_to_compute, lower_compute_to_cpu, lower_stage1_to_compute, + lower_stage2_to_compute, lower_stage3_to_compute, lower_stage4_to_compute, + lower_stage5_to_compute, lower_stage6_to_compute, lower_stage7_to_compute, + lower_stage8_to_compute, resolve_compute_kernels, stage1_cpu_program, stage2_cpu_program, + stage3_cpu_program, stage4_cpu_program, stage5_cpu_program, stage6_cpu_program, + stage7_cpu_program, stage8_cpu_program, validate_jolt_rust_artifact_imports, + verify_jolt_protocol_schema, write_jolt_generated_crates, JoltGeneratedCrate, + JoltProtocolParams, JoltProtocolStage, +}; +use bolt::{ + assemble_generated_crates, lower_piop_and_fiat_shamir, project_prover_party, + project_verifier_party, protocol_rust_artifact, validate_rust_artifact_imports, + verify_compute_schema, verify_concrete_transcript, verify_cpu_schema, verify_protocol_schema, + Concrete, Cpu, GeneratedFile, MeliorContext, ProtocolArtifactConfig, ProtocolRuntimeModule, + ProtocolStage, ProtocolStageKind, ProtocolStandaloneDependency, Role, RustSourceFile, + RustTypeRef, TextMlir, +}; +use std::fmt::Write as _; +use std::path::Path; +use std::process::Command; +use std::time::{SystemTime, UNIX_EPOCH}; + +#[test] +fn bolt_irdl_dialects_are_registered() { + let context = MeliorContext::new(); + assert!(!context.context().allow_unregistered_dialects()); + + let registered = r#" +module @registered { + "field.define"() {modulus_bits = 254 : i64, role = "scalar", sym_name = "bn254_fr"} : () -> () +} +"#; + let _ = context + .parse_module::(registered) + .expect("registered dialect op parses"); + + let unknown = r#" +module @unknown { + "unknown.dialect_op"() : () -> () +} +"#; + let _ = context + .parse_module::(unknown) + .expect_err("unknown dialect rejected"); +} + +#[test] +fn commitment_protocol_uses_bolt_semantic_dialects() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let protocol = build_commitment_protocol(&context, ¶ms).expect("build protocol"); + let text = protocol.to_text_mlir(); + + assert!(text.contains("\"protocol.params\"()")); + assert!(text.contains("sym_name = \"jolt.params\"")); + assert!(text.contains("trace_length = 65536")); + assert!(text.contains("num_committed = 41")); + assert!(text.contains("\"field.define\"()")); + assert!(text.contains("sym_name = \"bn254_fr\"")); + assert!(text.contains("\"poly.domain\"()")); + assert!(text.contains("sym_name = \"jolt.main_witness_commit_domain\"")); + assert!(text.contains("\"protocol.boundary\"()")); + assert!(text.contains("sym_name = \"jolt.commitment_phase\"")); + assert!(text.contains("\"piop.oracle\"()")); + assert!(text.contains("sym_name = \"InstructionRa_0\"")); + assert!(text.contains("\"piop.oracle_family\"()")); + assert!(text.contains("sym_name = \"jolt.main_witness_polys\"")); + assert!(text.contains("ordered_oracles = [@RdInc, @RamInc, @InstructionRa_0")); + assert!(text.contains("\"commit.publish_batch\"()")); + assert!(text.contains("\"pcs.commit_batch\"(%")); + assert!(!text.contains("commitment = @jolt.main_witness_commitments")); + assert!(text.contains("\"transcript.absorb\"(%")); + + let parsed = context + .parse_module::(&text) + .expect("parse protocol MLIR"); + assert!(parsed.to_text_mlir().contains("\"protocol.boundary\"")); +} + +#[test] +fn concrete_commitment_phase_threads_transcript_state() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let protocol = build_commitment_protocol(&context, ¶ms).expect("build protocol"); + let concrete = + lower_piop_and_fiat_shamir(&context, &protocol).expect("lower Fiat-Shamir state"); + verify_concrete_transcript(&concrete).expect("valid transcript state threading"); + + let text = concrete.to_text_mlir(); + assert!(text.contains("!transcript.state_type")); + assert!(text.contains("\"transcript.state\"()")); + assert!(text.contains("sym_name = \"fs0\"")); + assert!(text.contains("\"transcript.absorb\"(%")); + assert!(text.contains("\"transcript.absorb_optional\"(%")); + assert!(!text.contains("in = @fs")); + assert!(!text.contains("out = @fs")); +} + +#[test] +fn transcript_absorb_bytes_threads_and_lowers_to_cpu() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let protocol = context + .parse_module::(&transcript_absorb_bytes_protocol(¶ms)) + .expect("parse absorb-bytes protocol"); + verify_protocol_schema(&protocol).expect("absorb-bytes protocol schema is valid"); + + let concrete = + lower_piop_and_fiat_shamir(&context, &protocol).expect("lower absorb-bytes protocol"); + verify_concrete_transcript(&concrete).expect("absorb-bytes threads transcript state"); + + let prover = project_prover_party(&context, &concrete).expect("project prover party"); + // Stage4 does not have its own lowering entrypoint yet; this exercises the + // shared operation mapping that each stage lowering uses. + let compute = lower_stage3_to_compute(&context, &prover).expect("lower to compute"); + verify_compute_schema(&compute).expect("compute schema accepts absorb-bytes"); + assert!(compute + .to_text_mlir() + .contains("\"compute.transcript_absorb_bytes\"(%")); + + let kernelized = resolve_compute_kernels(&context, &compute).expect("kernelize compute"); + assert!(kernelized + .to_text_mlir() + .contains("\"compute.transcript_absorb_bytes\"(%")); + + let cpu = lower_compute_to_cpu(&context, &kernelized).expect("lower to CPU"); + verify_cpu_schema(&cpu).expect("CPU schema accepts absorb-bytes"); + let cpu_text = cpu.to_text_mlir(); + assert!(cpu_text.contains("\"cpu.transcript_absorb_bytes\"(%")); + assert!(cpu_text.contains("label = \"ram_val_check_gamma\"")); + assert!(cpu_text.contains("payload = \"\"")); +} + +#[test] +fn concrete_projects_to_party_ir() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let protocol = build_commitment_protocol(&context, ¶ms).expect("build protocol"); + let concrete = + lower_piop_and_fiat_shamir(&context, &protocol).expect("lower Fiat-Shamir state"); + let prover = project_prover_party(&context, &concrete).expect("project prover party"); + let verifier = project_verifier_party(&context, &concrete).expect("project verifier party"); + let prover_text = prover.to_text_mlir(); + let verifier_text = verifier.to_text_mlir(); + + assert!(prover_text.contains("bolt.phase = \"party\"")); + assert!(prover_text.contains("bolt.role = \"prover\"")); + assert!(prover_text.contains("\"party.function\"()")); + assert!(prover_text.contains("role = \"prover\"")); + assert!(prover_text.contains("\"transcript.absorb\"(%")); + assert!(!prover_text.contains("in = @fs")); + assert!(verifier_text.contains("bolt.phase = \"party\"")); + assert!(verifier_text.contains("bolt.role = \"verifier\"")); + assert!(verifier_text.contains("\"party.function\"()")); + assert!(verifier_text.contains("role = \"verifier\"")); + assert!(verifier_text.contains("\"transcript.absorb\"(%")); + assert!(!verifier_text.contains("in = @fs")); +} + +#[test] +fn commitment_compute_lowers_to_cpu_ir() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let protocol = build_commitment_protocol(&context, ¶ms).expect("build protocol"); + let concrete = + lower_piop_and_fiat_shamir(&context, &protocol).expect("lower Fiat-Shamir state"); + let prover = project_prover_party(&context, &concrete).expect("project prover party"); + let verifier = project_verifier_party(&context, &concrete).expect("project verifier party"); + let prover_compute = lower_commitment_to_compute(&context, &prover).expect("lower compute"); + let verifier_compute = + lower_commitment_to_compute(&context, &verifier).expect("lower verifier compute"); + let prover_cpu = lower_compute_to_cpu(&context, &prover_compute).expect("lower to CPU"); + let verifier_cpu = + lower_compute_to_cpu(&context, &verifier_compute).expect("lower verifier to CPU"); + let compute_text = prover_compute.to_text_mlir(); + let text = prover_cpu.to_text_mlir(); + let verifier_compute_text = verifier_compute.to_text_mlir(); + let verifier_text = verifier_cpu.to_text_mlir(); + + assert!(compute_text.contains("\"compute.oracle_dense_trace\"()")); + assert!(compute_text.contains("\"compute.oracle_one_hot_chunk\"()")); + assert!(compute_text.contains("\"compute.oracle_family_append\"(%")); + assert!(compute_text.contains("\"compute.pcs_commit_batch\"(%")); + assert!(compute_text.contains("artifact = @jolt.main_witness_commitments")); + assert!(compute_text.contains("ordered_oracles = [@RdInc, @RamInc, @InstructionRa_0")); + assert!(compute_text.contains("\"compute.pcs_commit_optional\"(%")); + assert!(compute_text.contains("skip_policy = \"missing_or_zero\"")); + assert!(compute_text.contains("!compute.transcript_state")); + assert!(compute_text.contains("\"compute.transcript_absorb\"(%")); + assert!(!compute_text.contains("in = @fs")); + assert!(text.contains("\"cpu.function\"()")); + assert!(!text.contains("\"compute.function\"()")); + assert!(text.contains("\"cpu.oracle_family_append\"(%")); + assert!(text.contains("\"cpu.pcs_commit_batch\"(%")); + assert!(text.contains("\"cpu.pcs_commit_optional\"(%")); + assert!(text.contains("skip_policy = \"missing_or_zero\"")); + assert!(text.contains("!cpu.transcript_state")); + assert!(text.contains("\"cpu.transcript_absorb\"(%")); + assert!(!text.contains("in = @fs")); + assert!(verifier_compute_text.contains("\"compute.oracle_ref\"()")); + assert!(verifier_compute_text.contains("\"compute.pcs_receive_batch\"(%")); + assert!(verifier_compute_text.contains("\"compute.pcs_receive_optional\"(%")); + assert!(!verifier_compute_text.contains("\"compute.pcs_commit_batch\"(%")); + assert!(verifier_text.contains("\"cpu.pcs_receive_batch\"(%")); + assert!(verifier_text.contains("\"cpu.pcs_receive_optional\"(%")); + assert!(!verifier_text.contains("\"cpu.pcs_commit_batch\"(%")); + + let parsed = context + .parse_module::(&text) + .expect("parse CPU MLIR"); + assert!(parsed.to_text_mlir().contains("\"cpu.pcs_commit_batch\"")); + let parsed = context + .parse_module::(&verifier_text) + .expect("parse verifier CPU MLIR"); + assert!(parsed.to_text_mlir().contains("\"cpu.pcs_receive_batch\"")); +} + +#[test] +fn generic_protocol_schema_accepts_non_jolt_params() { + let context = MeliorContext::new(); + let generic = context.new_module::("generic", None); + context + .append_op( + &generic, + "protocol.params", + Some("generic.params"), + &[ + ("field", "@some_field"), + ("pcs", "@some_pcs"), + ("transcript", "@some_transcript"), + ], + ) + .expect("append generic params"); + + assert!( + generic.verify(), + "generic protocol params pass IRDL verification" + ); + verify_protocol_schema(&generic).expect("generic schema does not require Jolt attrs"); +} + +#[test] +fn protocol_schema_rejects_bad_derived_params() { + let context = MeliorContext::new(); + let bad = context.new_module::("bad", None); + let mut attrs = JoltProtocolParams::fixture().attrs(); + for (name, value) in &mut attrs { + if name == "num_committed" { + *value = "40 : i64".to_owned(); + } + } + context + .append_op_with_owned_attrs(&bad, "protocol.params", Some("jolt.params"), &attrs) + .expect("append params"); + context + .append_op( + &bad, + "piop.oracle_family", + Some("jolt.main_witness_polys"), + &[ + ( + "ordered_oracles", + "[@RdInc, @RamInc, @InstructionRa_0, @RamRa_0, @BytecodeRa_0]", + ), + ("count", "40 : i64"), + ("domain", "@jolt.trace_domain"), + ("visibility", r#""committed""#), + ], + ) + .expect("append family"); + + let error = verify_jolt_protocol_schema(&bad).expect_err("bad derived param rejected"); + assert!(error.to_string().contains("num_committed must be 41")); +} + +#[test] +fn concrete_verifier_rejects_unthreaded_transcript_absorb() { + let context = MeliorContext::new(); + let concrete = context.new_module::("bad", None); + context + .append_op( + &concrete, + "transcript.absorb", + Some("bad_absorb"), + &[ + ("label", r#""commitment""#), + ("source", "@jolt.main_witness_commitments"), + ], + ) + .expect("append bad absorb"); + + let error = verify_concrete_transcript(&concrete).expect_err("missing transcript state"); + assert!(error + .to_string() + .contains("requires a prior transcript.state result")); +} + +#[test] +fn protocol_schema_accepts_explicit_sumcheck_and_opening_flow() { + let context = MeliorContext::new(); + let protocol = context + .parse_module::(explicit_sumcheck_protocol()) + .expect("parse explicit sumcheck protocol"); + + verify_protocol_schema(&protocol).expect("explicit sumcheck protocol schema is valid"); + let concrete = + lower_piop_and_fiat_shamir(&context, &protocol).expect("lower protocol copy to concrete"); + verify_concrete_transcript(&concrete).expect("sumcheck/opening ops thread transcript state"); + + let text = concrete.to_text_mlir(); + assert!(text.contains("\"piop.sumcheck_batch\"(%")); + assert!(text.contains("round_schedule = [2, 1, 1]")); + assert!(text.contains("\"pcs.opening_claim\"(%")); + assert!(text.contains("\"pcs.opening_batch\"(%")); + assert!(text.contains("\"pcs.batch_open\"(%")); +} + +#[test] +fn opening_batch_schema_rejects_hidden_or_reordered_claims() { + let context = MeliorContext::new(); + let protocol = context + .parse_module::(&explicit_sumcheck_protocol().replace( + "ordered_claims = [@stage1.outer.opening]", + "ordered_claims = [@wrong.opening]", + )) + .expect("parse explicit sumcheck protocol"); + + let error = verify_protocol_schema(&protocol).expect_err("opening batch order mismatch"); + assert!(error + .to_string() + .contains("expected @wrong.opening, got @stage1.outer.opening")); +} + +#[test] +fn opening_claim_equal_lowers_through_ssa_pipeline() { + let context = MeliorContext::new(); + let protocol = context + .parse_module::(&opening_claim_equal_protocol( + "LeftInstructionInput", + "LeftInstructionInput", + "point_and_eval", + )) + .expect("parse opening equality protocol"); + verify_protocol_schema(&protocol).expect("opening equality protocol schema is valid"); + let concrete = + lower_piop_and_fiat_shamir(&context, &protocol).expect("lower protocol to concrete"); + let prover = project_prover_party(&context, &concrete).expect("project prover party"); + let compute = lower_stage2_to_compute(&context, &prover).expect("lower equality to compute"); + verify_compute_schema(&compute).expect("compute equality schema is valid"); + let kernelized = + resolve_compute_kernels(&context, &compute).expect("preserve equality through kernels"); + let cpu = lower_compute_to_cpu(&context, &kernelized).expect("lower equality to CPU"); + verify_cpu_schema(&cpu).expect("CPU equality schema is valid"); + + let compute_text = kernelized.to_text_mlir(); + let cpu_text = cpu.to_text_mlir(); + assert!(compute_text.contains("\"compute.opening_claim_equal\"(%")); + assert!(compute_text.contains("mode = \"point_and_eval\"")); + assert!(cpu_text.contains("\"cpu.opening_claim_equal\"(%")); + assert!(cpu_text.contains("mode = \"point_and_eval\"")); +} + +#[test] +fn opening_claim_equal_rejects_incompatible_claim_metadata() { + let context = MeliorContext::new(); + let protocol = context + .parse_module::(&opening_claim_equal_protocol( + "LeftInstructionInput", + "RightInstructionInput", + "point_and_eval", + )) + .expect("parse bad opening equality protocol"); + + let error = verify_protocol_schema(&protocol).expect_err("mismatched claims are rejected"); + assert!(error.to_string().contains("compares incompatible claims")); +} + +#[test] +fn opening_claim_equal_rejects_unsupported_mode() { + let context = MeliorContext::new(); + let protocol = context + .parse_module::(&opening_claim_equal_protocol( + "LeftInstructionInput", + "LeftInstructionInput", + "eval_only", + )) + .expect("parse bad opening equality mode"); + + let error = verify_protocol_schema(&protocol).expect_err("unsupported equality mode rejected"); + assert!(error.to_string().contains("expected \"point_and_eval\"")); +} + +#[test] +fn sumcheck_compute_lowers_to_cpu_kernel_ir() { + let context = MeliorContext::new(); + let compute = context + .parse_module::(explicit_sumcheck_compute()) + .expect("parse explicit sumcheck compute"); + + verify_compute_schema(&compute).expect("compute sumcheck schema is valid"); + let kernelized = + resolve_compute_kernels(&context, &compute).expect("resolve sumcheck compute kernels"); + verify_compute_schema(&kernelized).expect("kernelized sumcheck schema is valid"); + let cpu = lower_compute_to_cpu(&context, &kernelized).expect("lower sumcheck compute to CPU"); + verify_cpu_schema(&cpu).expect("CPU sumcheck schema is valid"); + + let text = cpu.to_text_mlir(); + assert!(text.contains("\"cpu.transcript_squeeze\"(%")); + assert!(text.contains("\"cpu.sumcheck_batch\"(%")); + assert!(text.contains("\"cpu.sumcheck_driver\"(%")); + assert!(text.contains("\"cpu.sumcheck_eval\"(%")); + assert!(text.contains("\"cpu.pcs_opening_claim\"(%")); + assert!(text.contains("\"cpu.pcs_batch_open\"(%")); + assert!(text.contains("!cpu.sumcheck_claim_type")); +} + +#[test] +fn jolt_stage1_outer_protocol_defines_virtual_claim_flow() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let protocol = + build_stage1_outer_protocol(&context, ¶ms).expect("build stage1 outer protocol"); + verify_protocol_schema(&protocol).expect("stage1 protocol schema is valid"); + let concrete = + lower_piop_and_fiat_shamir(&context, &protocol).expect("lower stage1 to concrete"); + verify_concrete_transcript(&concrete).expect("stage1 transcript is threaded"); + + let text = protocol.to_text_mlir(); + assert!(text.contains("sym_name = \"stage1.uniskip.sumcheck\"")); + assert!(text.contains("sym_name = \"stage1.outer_remaining.sumcheck\"")); + assert!(text.contains("relation = @jolt.stage1.outer.uniskip")); + assert!(!text.contains("kernel = @")); + assert!(text.contains("\"piop.sumcheck_claim\"(%")); + assert!(text.contains("\"piop.sumcheck_eval\"(%")); + assert!(text.contains("\"piop.opening_claim\"(%")); + assert!(text.contains("\"piop.opening_batch\"(%")); + assert!(text.contains("count = 35 : i64")); + assert!(text.contains("ordered_claims = [@stage1.outer_remaining.opening.LeftInstructionInput")); + assert!(text.contains("oracle = @OpFlagIsLastInSequence")); + assert!(!text.contains("\"pcs.opening_claim\"")); + assert_or_update_fixture("tests/fixtures/stage1_outer_protocol.mlir", &text); +} + +#[test] +fn jolt_stage2_protocol_defines_product_ram_claim_flow() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let protocol = build_stage2_protocol(&context, ¶ms).expect("build stage2 protocol"); + verify_protocol_schema(&protocol).expect("stage2 protocol schema is valid"); + let concrete = + lower_piop_and_fiat_shamir(&context, &protocol).expect("lower stage2 to concrete"); + verify_concrete_transcript(&concrete).expect("stage2 transcript is threaded"); + + let text = protocol.to_text_mlir(); + assert!(text.contains("sym_name = \"stage2.product_virtual.uniskip.sumcheck\"")); + assert!(text.contains("sym_name = \"stage2.sumcheck\"")); + assert!(text.contains("relation = @jolt.stage2.product_virtual.uniskip")); + assert!(text.contains("relation = @jolt.stage2.batched")); + assert!(text.contains("\"piop.opening_input\"()")); + assert!(text.contains("\"field.add\"(%")); + assert!(text.contains("\"poly.lagrange_basis_eval\"(%")); + assert!(text.contains("sym_name = \"stage2.ram_read_write.claim_expr\"")); + assert!(text.contains("\"piop.sumcheck_instance_result\"(%")); + assert!(text.contains("round_offset = 16 : i64")); + assert!(text.contains("\"poly.point_slice\"(%")); + assert!(text.contains("\"poly.point_concat\"(%")); + assert!(text.contains( + "ordered_claims = [@stage2.ram_read_write.input, @stage2.product_virtual.remainder.input" + )); + assert!(text.contains("ordered_claims = [@stage2.ram_read_write.opening.RamVal, @stage2.ram_read_write.opening.RamRa, @stage2.ram_read_write.opening.RamInc")); + assert!(text.contains("claim_kind = \"committed\"")); + assert!(text.contains("source_claim = @stage1.outer_remaining.opening.RamAddress")); + assert!(!text.contains("kernel = @")); + assert!(!text.contains("\"compute.")); + assert_or_update_fixture("tests/fixtures/stage2_protocol.mlir", &text); +} + +#[test] +fn jolt_stage2_lowers_to_compute_and_cpu_role_ir() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let protocol = build_stage2_protocol(&context, ¶ms).expect("build stage2 protocol"); + let concrete = + lower_piop_and_fiat_shamir(&context, &protocol).expect("lower stage2 to concrete"); + let prover = project_prover_party(&context, &concrete).expect("project prover party"); + let verifier = project_verifier_party(&context, &concrete).expect("project verifier party"); + let prover_compute = lower_stage2_to_compute(&context, &prover).expect("lower prover stage2"); + let verifier_compute = + lower_stage2_to_compute(&context, &verifier).expect("lower verifier stage2"); + verify_compute_schema(&prover_compute).expect("prover stage2 compute schema is valid"); + verify_compute_schema(&verifier_compute).expect("verifier stage2 compute schema is valid"); + + let prover_compute_text = prover_compute.to_text_mlir(); + let verifier_compute_text = verifier_compute.to_text_mlir(); + assert!(prover_compute_text.contains("\"compute.opening_input\"()")); + assert!(prover_compute_text.contains("\"compute.field_add\"(%")); + assert!(prover_compute_text.contains("\"compute.poly_lagrange_basis_eval\"(%")); + assert!(prover_compute_text.contains("\"compute.point_slice\"(%")); + assert!(prover_compute_text.contains("\"compute.point_concat\"(%")); + assert!(prover_compute_text.contains("\"compute.sumcheck_claim\"(%")); + assert!(prover_compute_text.contains("\"compute.sumcheck_driver\"(%")); + assert!(!prover_compute_text.contains("kernel = @")); + assert!(verifier_compute_text.contains("\"compute.sumcheck_verify_claim\"")); + assert!(verifier_compute_text.contains("\"compute.sumcheck_verify\"")); + assert!(!verifier_compute_text.contains("\"compute.kernel\"")); + assert!(!verifier_compute_text.contains("kernel = @")); + + let prover_kernel_compute = + resolve_compute_kernels(&context, &prover_compute).expect("resolve prover kernels"); + let verifier_kernel_compute = + resolve_compute_kernels(&context, &verifier_compute).expect("resolve verifier kernels"); + verify_compute_schema(&prover_kernel_compute) + .expect("prover kernelized stage2 compute schema is valid"); + verify_compute_schema(&verifier_kernel_compute) + .expect("verifier kernelized stage2 compute schema is valid"); + + let prover_cpu = + lower_compute_to_cpu(&context, &prover_kernel_compute).expect("lower prover CPU"); + let verifier_cpu = + lower_compute_to_cpu(&context, &verifier_kernel_compute).expect("lower verifier CPU"); + verify_cpu_schema(&prover_cpu).expect("prover stage2 CPU schema is valid"); + verify_cpu_schema(&verifier_cpu).expect("verifier stage2 CPU schema is valid"); + + let prover_cpu_text = prover_cpu.to_text_mlir(); + let verifier_cpu_text = verifier_cpu.to_text_mlir(); + assert!(prover_cpu_text.contains("\"cpu.opening_input\"()")); + assert!(prover_cpu_text.contains("\"cpu.field_add\"(%")); + assert!(prover_cpu_text.contains("\"cpu.poly_lagrange_basis_eval\"(%")); + assert!(prover_cpu_text.contains("\"cpu.point_slice\"(%")); + assert!(prover_cpu_text.contains("\"cpu.point_concat\"(%")); + assert!(prover_cpu_text.contains("\"cpu.kernel\"()")); + assert!(prover_cpu_text.contains("kernel = @jolt.cpu.stage2.batched")); + assert!(verifier_cpu_text.contains("\"cpu.opening_input\"()")); + assert!(verifier_cpu_text.contains("\"cpu.sumcheck_verify_claim\"")); + assert!(verifier_cpu_text.contains("\"cpu.sumcheck_verify\"")); + assert!(!verifier_cpu_text.contains("\"cpu.kernel\"")); + assert!(!verifier_cpu_text.contains("kernel = @")); + + assert_or_update_fixture( + "tests/fixtures/stage2_prover_compute.mlir", + &prover_compute.to_text_mlir(), + ); + assert_or_update_fixture( + "tests/fixtures/stage2_verifier_compute.mlir", + &verifier_compute.to_text_mlir(), + ); + assert_or_update_fixture( + "tests/fixtures/stage2_prover_kernel_compute.mlir", + &prover_kernel_compute.to_text_mlir(), + ); + assert_or_update_fixture( + "tests/fixtures/stage2_verifier_kernel_compute.mlir", + &verifier_kernel_compute.to_text_mlir(), + ); + assert_or_update_fixture("tests/fixtures/stage2_prover_cpu.mlir", &prover_cpu_text); + assert_or_update_fixture( + "tests/fixtures/stage2_verifier_cpu.mlir", + &verifier_cpu_text, + ); +} + +#[test] +fn jolt_stage3_protocol_defines_shift_instruction_register_flow() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let protocol = build_stage3_protocol(&context, ¶ms).expect("build stage3 protocol"); + verify_protocol_schema(&protocol).expect("stage3 protocol schema is valid"); + let concrete = + lower_piop_and_fiat_shamir(&context, &protocol).expect("lower stage3 to concrete"); + verify_concrete_transcript(&concrete).expect("stage3 transcript is threaded"); + + let text = protocol.to_text_mlir(); + assert!(text.contains("sym_name = \"stage3.spartan_shift.input\"")); + assert!(text.contains("sym_name = \"stage3.instruction_input.input\"")); + assert!(text.contains("sym_name = \"stage3.registers_claim_reduction.input\"")); + assert!(text.contains("\"piop.opening_claim_equal\"(%")); + assert!(text.contains("\"field.add\"(%")); + assert!(text.contains("\"field.mul\"(%")); + assert!(text.contains("\"field.sub\"(%")); + assert!(text.contains("policy = \"jolt_core_stage3_aligned\"")); + assert!(text.contains("point_order = \"reverse\"")); + assert!(text.contains("ordered_claims = [@stage3.spartan_shift.input, @stage3.instruction_input.input, @stage3.registers_claim_reduction.input]")); + assert!(text.contains("ordered_claims = [@stage3.spartan_shift.opening.UnexpandedPC, @stage3.spartan_shift.opening.PC")); + assert!(!text.contains("kernel = @")); + assert!(!text.contains("\"compute.")); + assert_or_update_fixture("tests/fixtures/stage3_protocol.mlir", &text); +} + +#[test] +fn jolt_stage3_lowers_to_compute_and_cpu_role_ir() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let protocol = build_stage3_protocol(&context, ¶ms).expect("build stage3 protocol"); + let concrete = + lower_piop_and_fiat_shamir(&context, &protocol).expect("lower stage3 to concrete"); + let prover = project_prover_party(&context, &concrete).expect("project prover party"); + let verifier = project_verifier_party(&context, &concrete).expect("project verifier party"); + let prover_compute = lower_stage3_to_compute(&context, &prover).expect("lower prover stage3"); + let verifier_compute = + lower_stage3_to_compute(&context, &verifier).expect("lower verifier stage3"); + verify_compute_schema(&prover_compute).expect("prover stage3 compute schema is valid"); + verify_compute_schema(&verifier_compute).expect("verifier stage3 compute schema is valid"); + + let prover_compute_text = prover_compute.to_text_mlir(); + let verifier_compute_text = verifier_compute.to_text_mlir(); + assert!(prover_compute_text.contains("\"compute.opening_input\"()")); + assert!(prover_compute_text.contains("\"compute.opening_claim_equal\"(%")); + assert!(prover_compute_text.contains("\"compute.field_add\"(%")); + assert!(prover_compute_text.contains("\"compute.field_mul\"(%")); + assert!(prover_compute_text.contains("\"compute.sumcheck_claim\"(%")); + assert!(prover_compute_text.contains("\"compute.sumcheck_driver\"(%")); + assert!(!prover_compute_text.contains("kernel = @")); + assert!(verifier_compute_text.contains("\"compute.opening_claim_equal\"(%")); + assert!(verifier_compute_text.contains("\"compute.sumcheck_verify_claim\"")); + assert!(verifier_compute_text.contains("\"compute.sumcheck_verify\"")); + assert!(!verifier_compute_text.contains("\"compute.kernel\"")); + assert!(!verifier_compute_text.contains("kernel = @")); + + let prover_kernel_compute = + resolve_compute_kernels(&context, &prover_compute).expect("resolve prover kernels"); + let verifier_kernel_compute = + resolve_compute_kernels(&context, &verifier_compute).expect("resolve verifier kernels"); + verify_compute_schema(&prover_kernel_compute) + .expect("prover kernelized stage3 compute schema is valid"); + verify_compute_schema(&verifier_kernel_compute) + .expect("verifier kernelized stage3 compute schema is valid"); + + let prover_cpu = + lower_compute_to_cpu(&context, &prover_kernel_compute).expect("lower prover CPU"); + let verifier_cpu = + lower_compute_to_cpu(&context, &verifier_kernel_compute).expect("lower verifier CPU"); + verify_cpu_schema(&prover_cpu).expect("prover stage3 CPU schema is valid"); + verify_cpu_schema(&verifier_cpu).expect("verifier stage3 CPU schema is valid"); + + let prover_kernel_text = prover_kernel_compute.to_text_mlir(); + let verifier_kernel_text = verifier_kernel_compute.to_text_mlir(); + let prover_cpu_text = prover_cpu.to_text_mlir(); + let verifier_cpu_text = verifier_cpu.to_text_mlir(); + assert!(prover_kernel_text.contains("kernel = @jolt.cpu.stage3.batched")); + assert!(!verifier_kernel_text.contains("kernel = @")); + assert!(prover_cpu_text.contains("\"cpu.opening_claim_equal\"(%")); + assert!(prover_cpu_text.contains("\"cpu.kernel\"()")); + assert!(prover_cpu_text.contains("kernel = @jolt.cpu.stage3.batched")); + assert!(verifier_cpu_text.contains("\"cpu.opening_claim_equal\"(%")); + assert!(verifier_cpu_text.contains("\"cpu.sumcheck_verify_claim\"")); + assert!(verifier_cpu_text.contains("\"cpu.sumcheck_verify\"")); + assert!(!verifier_cpu_text.contains("\"cpu.kernel\"")); + assert!(!verifier_cpu_text.contains("kernel = @")); + + assert_or_update_fixture( + "tests/fixtures/stage3_prover_compute.mlir", + &prover_compute_text, + ); + assert_or_update_fixture( + "tests/fixtures/stage3_verifier_compute.mlir", + &verifier_compute_text, + ); + assert_or_update_fixture( + "tests/fixtures/stage3_prover_kernel_compute.mlir", + &prover_kernel_text, + ); + assert_or_update_fixture( + "tests/fixtures/stage3_verifier_kernel_compute.mlir", + &verifier_kernel_text, + ); + assert_or_update_fixture("tests/fixtures/stage3_prover_cpu.mlir", &prover_cpu_text); + assert_or_update_fixture( + "tests/fixtures/stage3_verifier_cpu.mlir", + &verifier_cpu_text, + ); +} + +#[test] +fn jolt_stage4_protocol_defines_registers_and_ram_val_flow() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let protocol = build_stage4_protocol(&context, ¶ms).expect("build stage4 protocol"); + verify_protocol_schema(&protocol).expect("stage4 protocol schema is valid"); + let concrete = + lower_piop_and_fiat_shamir(&context, &protocol).expect("lower stage4 to concrete"); + verify_concrete_transcript(&concrete).expect("stage4 transcript is threaded"); + + let text = protocol.to_text_mlir(); + assert!(text.contains("sym_name = \"stage4.registers_read_write.input\"")); + assert!(text.contains("sym_name = \"stage4.ram_val_check.input\"")); + assert!(text.contains("\"transcript.absorb_bytes\"(%")); + assert!(text.contains("label = \"ram_val_check_gamma\"")); + assert!(text.contains("payload = \"\"")); + assert!(text.contains("sym_name = \"stage4.input.initial_ram.RamValInit\"")); + assert!(text.contains("sym_name = \"stage4.registers.rs1_claim_consistency\"")); + assert!(text.contains("sym_name = \"stage4.registers.rs2_claim_consistency\"")); + assert!(text.contains( + "ordered_claims = [@stage4.registers_read_write.input, @stage4.ram_val_check.input]" + )); + assert!(text.contains("ordered_claims = [@stage4.registers_read_write.opening.RegistersVal")); + assert!(text.contains("@stage4.ram_val_check.opening.RamRa")); + assert!(text.contains("@stage4.ram_val_check.opening.RamInc")); + assert!(!text.contains("kernel = @")); + assert!(!text.contains("\"compute.")); + assert_or_update_fixture("tests/fixtures/stage4_protocol.mlir", &text); +} + +#[test] +fn jolt_stage4_lowers_to_compute_and_cpu_role_ir() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let protocol = build_stage4_protocol(&context, ¶ms).expect("build stage4 protocol"); + let concrete = + lower_piop_and_fiat_shamir(&context, &protocol).expect("lower stage4 to concrete"); + let prover = project_prover_party(&context, &concrete).expect("project prover party"); + let verifier = project_verifier_party(&context, &concrete).expect("project verifier party"); + let prover_compute = lower_stage4_to_compute(&context, &prover).expect("lower prover stage4"); + let verifier_compute = + lower_stage4_to_compute(&context, &verifier).expect("lower verifier stage4"); + verify_compute_schema(&prover_compute).expect("prover stage4 compute schema is valid"); + verify_compute_schema(&verifier_compute).expect("verifier stage4 compute schema is valid"); + + let prover_compute_text = prover_compute.to_text_mlir(); + let verifier_compute_text = verifier_compute.to_text_mlir(); + assert!(prover_compute_text.contains("\"compute.transcript_absorb_bytes\"(%")); + assert!(prover_compute_text.contains("\"compute.opening_claim_equal\"(%")); + assert!(prover_compute_text.contains("\"compute.field_sub\"(%")); + assert!(prover_compute_text.contains("\"compute.sumcheck_claim\"(%")); + assert!(prover_compute_text.contains("\"compute.sumcheck_driver\"(%")); + assert!(verifier_compute_text.contains("\"compute.transcript_absorb_bytes\"(%")); + assert!(verifier_compute_text.contains("\"compute.sumcheck_verify_claim\"")); + assert!(verifier_compute_text.contains("\"compute.sumcheck_verify\"")); + assert!(!verifier_compute_text.contains("kernel = @")); + + let prover_kernel_compute = + resolve_compute_kernels(&context, &prover_compute).expect("resolve prover kernels"); + let verifier_kernel_compute = + resolve_compute_kernels(&context, &verifier_compute).expect("resolve verifier kernels"); + verify_compute_schema(&prover_kernel_compute) + .expect("prover kernelized stage4 compute schema is valid"); + verify_compute_schema(&verifier_kernel_compute) + .expect("verifier kernelized stage4 compute schema is valid"); + + let prover_cpu = + lower_compute_to_cpu(&context, &prover_kernel_compute).expect("lower prover CPU"); + let verifier_cpu = + lower_compute_to_cpu(&context, &verifier_kernel_compute).expect("lower verifier CPU"); + verify_cpu_schema(&prover_cpu).expect("prover stage4 CPU schema is valid"); + verify_cpu_schema(&verifier_cpu).expect("verifier stage4 CPU schema is valid"); + + let prover_kernel_text = prover_kernel_compute.to_text_mlir(); + let verifier_kernel_text = verifier_kernel_compute.to_text_mlir(); + let prover_cpu_text = prover_cpu.to_text_mlir(); + let verifier_cpu_text = verifier_cpu.to_text_mlir(); + assert!(prover_kernel_text.contains("kernel = @jolt.cpu.stage4.batched")); + assert!(prover_cpu_text.contains("\"cpu.transcript_absorb_bytes\"(%")); + assert!(prover_cpu_text.contains("kernel = @jolt.cpu.stage4.batched")); + assert!(verifier_cpu_text.contains("\"cpu.transcript_absorb_bytes\"(%")); + assert!(verifier_cpu_text.contains("\"cpu.sumcheck_verify_claim\"")); + assert!(!verifier_kernel_text.contains("kernel = @")); + assert!(!verifier_cpu_text.contains("kernel = @")); + + assert_or_update_fixture( + "tests/fixtures/stage4_prover_compute.mlir", + &prover_compute_text, + ); + assert_or_update_fixture( + "tests/fixtures/stage4_verifier_compute.mlir", + &verifier_compute_text, + ); + assert_or_update_fixture( + "tests/fixtures/stage4_prover_kernel_compute.mlir", + &prover_kernel_text, + ); + assert_or_update_fixture( + "tests/fixtures/stage4_verifier_kernel_compute.mlir", + &verifier_kernel_text, + ); + assert_or_update_fixture("tests/fixtures/stage4_prover_cpu.mlir", &prover_cpu_text); + assert_or_update_fixture( + "tests/fixtures/stage4_verifier_cpu.mlir", + &verifier_cpu_text, + ); +} + +#[test] +fn jolt_stage5_protocol_defines_value_lookup_reduction_flow() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let protocol = build_stage5_protocol(&context, ¶ms).expect("build stage5 protocol"); + verify_protocol_schema(&protocol).expect("stage5 protocol schema is valid"); + let concrete = + lower_piop_and_fiat_shamir(&context, &protocol).expect("lower stage5 to concrete"); + verify_concrete_transcript(&concrete).expect("stage5 transcript is threaded"); + + let text = protocol.to_text_mlir(); + assert!(text.contains("sym_name = \"stage5.instruction_read_raf.input\"")); + assert!(text.contains("sym_name = \"stage5.ram_ra_claim_reduction.input\"")); + assert!(text.contains("sym_name = \"stage5.registers_val_evaluation.input\"")); + assert!(text.contains("sym_name = \"stage5.instruction_read_raf.gamma\"")); + assert!(text.contains("sym_name = \"stage5.ram_ra_claim_reduction.gamma\"")); + assert!(text.contains("sym_name = \"stage5.instruction.lookup_output_claim_consistency\"")); + assert!(text.contains("round_schedule = [128, 16]")); + assert!(text.contains("ordered_claims = [@stage5.instruction_read_raf.input, @stage5.ram_ra_claim_reduction.input, @stage5.registers_val_evaluation.input]")); + assert!(text.contains("@stage5.instruction_read_raf.opening.LookupTableFlag_0")); + assert!(text.contains("@stage5.instruction_read_raf.opening.InstructionRa_0")); + assert!(text.contains("@stage5.instruction_read_raf.opening.InstructionRafFlag")); + assert!(text.contains("@stage5.ram_ra_claim_reduction.opening.RamRa")); + assert!(text.contains("@stage5.registers_val_evaluation.opening.RdInc")); + assert!(text.contains("@stage5.registers_val_evaluation.opening.RdWa")); + assert!(!text.contains("kernel = @")); + assert!(!text.contains("\"compute.")); +} + +#[test] +fn jolt_stage5_lowers_to_compute_and_cpu_role_ir() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let protocol = build_stage5_protocol(&context, ¶ms).expect("build stage5 protocol"); + let concrete = + lower_piop_and_fiat_shamir(&context, &protocol).expect("lower stage5 to concrete"); + let prover = project_prover_party(&context, &concrete).expect("project prover party"); + let verifier = project_verifier_party(&context, &concrete).expect("project verifier party"); + let prover_compute = lower_stage5_to_compute(&context, &prover).expect("lower prover stage5"); + let verifier_compute = + lower_stage5_to_compute(&context, &verifier).expect("lower verifier stage5"); + verify_compute_schema(&prover_compute).expect("prover stage5 compute schema is valid"); + verify_compute_schema(&verifier_compute).expect("verifier stage5 compute schema is valid"); + + let prover_compute_text = prover_compute.to_text_mlir(); + let verifier_compute_text = verifier_compute.to_text_mlir(); + assert!(prover_compute_text.contains("\"compute.opening_claim_equal\"(%")); + assert!(prover_compute_text.contains("\"compute.field_pow\"(%")); + assert!(prover_compute_text.contains("\"compute.sumcheck_claim\"(%")); + assert!(prover_compute_text.contains("\"compute.sumcheck_driver\"(%")); + assert!(verifier_compute_text.contains("\"compute.sumcheck_verify_claim\"")); + assert!(verifier_compute_text.contains("\"compute.sumcheck_verify\"")); + assert!(!verifier_compute_text.contains("kernel = @")); + + let prover_kernel_compute = + resolve_compute_kernels(&context, &prover_compute).expect("resolve prover kernels"); + let verifier_kernel_compute = + resolve_compute_kernels(&context, &verifier_compute).expect("resolve verifier kernels"); + verify_compute_schema(&prover_kernel_compute) + .expect("prover kernelized stage5 compute schema is valid"); + verify_compute_schema(&verifier_kernel_compute) + .expect("verifier kernelized stage5 compute schema is valid"); + + let prover_cpu = + lower_compute_to_cpu(&context, &prover_kernel_compute).expect("lower prover CPU"); + let verifier_cpu = + lower_compute_to_cpu(&context, &verifier_kernel_compute).expect("lower verifier CPU"); + verify_cpu_schema(&prover_cpu).expect("prover stage5 CPU schema is valid"); + verify_cpu_schema(&verifier_cpu).expect("verifier stage5 CPU schema is valid"); + + let prover_kernel_text = prover_kernel_compute.to_text_mlir(); + let verifier_kernel_text = verifier_kernel_compute.to_text_mlir(); + let prover_cpu_text = prover_cpu.to_text_mlir(); + let verifier_cpu_text = verifier_cpu.to_text_mlir(); + assert!(prover_kernel_text.contains("kernel = @jolt.cpu.stage5.batched")); + assert!(prover_cpu_text.contains("kernel = @jolt.cpu.stage5.batched")); + assert!(prover_cpu_text.contains("point_order = \"instruction_read_raf\"")); + assert!(verifier_cpu_text.contains("\"cpu.sumcheck_verify_claim\"")); + assert!(!verifier_kernel_text.contains("kernel = @")); + assert!(!verifier_cpu_text.contains("kernel = @")); +} + +#[test] +fn jolt_stage6_protocol_defines_bytecode_booleanity_and_virtualization_flow() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let protocol = build_stage6_protocol(&context, ¶ms).expect("build stage6 protocol"); + verify_protocol_schema(&protocol).expect("stage6 protocol schema is valid"); + let concrete = + lower_piop_and_fiat_shamir(&context, &protocol).expect("lower stage6 to concrete"); + verify_concrete_transcript(&concrete).expect("stage6 transcript is threaded"); + + let text = protocol.to_text_mlir(); + assert!(text.contains("sym_name = \"stage6.bytecode_read_raf.input\"")); + assert!(text.contains("sym_name = \"stage6.booleanity.input\"")); + assert!(text.contains("sym_name = \"stage6.hamming_booleanity.input\"")); + assert!(text.contains("sym_name = \"stage6.ram_ra_virtual.input\"")); + assert!(text.contains("sym_name = \"stage6.instruction_ra_virtual.input\"")); + assert!(text.contains("sym_name = \"stage6.inc_claim_reduction.input\"")); + assert!(text.contains("sym_name = \"stage6.bytecode_read_raf.gamma\"")); + assert!(text.contains("sym_name = \"stage6.bytecode_read_raf.stage5_gamma\"")); + assert!(text.contains("sym_name = \"stage6.booleanity.gamma\"")); + assert!(text.contains("sym_name = \"stage6.instruction_ra_virtual.gamma\"")); + assert!(text.contains("sym_name = \"stage6.inc_claim_reduction.gamma\"")); + assert!(text.contains("sym_name = \"stage6.booleanity.gamma_sq_0\"")); + assert!(text.contains("source_claim = @stage2.ram_read_write.opening.RamInc")); + assert!(text.contains("source_claim = @stage4.registers_read_write.opening.RdInc")); + assert!(text.contains("source_claim = @stage5.registers_val_evaluation.opening.RdInc")); + assert!(text.contains("round_schedule = [10, 16]")); + assert!(text.contains("ordered_claims = [@stage6.bytecode_read_raf.input, @stage6.booleanity.input, @stage6.hamming_booleanity.input, @stage6.ram_ra_virtual.input, @stage6.instruction_ra_virtual.input, @stage6.inc_claim_reduction.input]")); + assert!(text.contains("@stage6.bytecode_read_raf.opening.BytecodeRa_0")); + assert!(text.contains("@stage6.booleanity.opening.InstructionRa_0")); + assert!(text.contains("@stage6.hamming_booleanity.opening.HammingWeight")); + assert!(text.contains("@stage6.ram_ra_virtual.opening.RamRa_0")); + assert!(text.contains("@stage6.instruction_ra_virtual.opening.InstructionRa_0")); + assert!(text.contains("@stage6.inc_claim_reduction.opening.RamInc")); + assert!(text.contains("@stage6.inc_claim_reduction.opening.RdInc")); + assert!(!text.contains("kernel = @")); + assert!(!text.contains("\"compute.")); +} + +#[test] +fn jolt_stage6_lowers_to_compute_and_cpu_role_ir() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let protocol = build_stage6_protocol(&context, ¶ms).expect("build stage6 protocol"); + let concrete = + lower_piop_and_fiat_shamir(&context, &protocol).expect("lower stage6 to concrete"); + let prover = project_prover_party(&context, &concrete).expect("project prover party"); + let verifier = project_verifier_party(&context, &concrete).expect("project verifier party"); + let prover_compute = lower_stage6_to_compute(&context, &prover).expect("lower prover stage6"); + let verifier_compute = + lower_stage6_to_compute(&context, &verifier).expect("lower verifier stage6"); + verify_compute_schema(&prover_compute).expect("prover stage6 compute schema is valid"); + verify_compute_schema(&verifier_compute).expect("verifier stage6 compute schema is valid"); + + let prover_compute_text = prover_compute.to_text_mlir(); + let verifier_compute_text = verifier_compute.to_text_mlir(); + assert!(prover_compute_text.contains("\"compute.field_pow\"(%")); + assert!(prover_compute_text.contains("\"compute.field_zero\"()")); + assert!(prover_compute_text.contains("\"compute.sumcheck_claim\"(%")); + assert!(prover_compute_text.contains("\"compute.sumcheck_driver\"(%")); + assert!(verifier_compute_text.contains("\"compute.sumcheck_verify_claim\"")); + assert!(verifier_compute_text.contains("\"compute.sumcheck_verify\"")); + assert!(!verifier_compute_text.contains("kernel = @")); + + let prover_kernel_compute = + resolve_compute_kernels(&context, &prover_compute).expect("resolve prover kernels"); + let verifier_kernel_compute = + resolve_compute_kernels(&context, &verifier_compute).expect("resolve verifier kernels"); + verify_compute_schema(&prover_kernel_compute) + .expect("prover kernelized stage6 compute schema is valid"); + verify_compute_schema(&verifier_kernel_compute) + .expect("verifier kernelized stage6 compute schema is valid"); + + let prover_cpu = + lower_compute_to_cpu(&context, &prover_kernel_compute).expect("lower prover CPU"); + let verifier_cpu = + lower_compute_to_cpu(&context, &verifier_kernel_compute).expect("lower verifier CPU"); + verify_cpu_schema(&prover_cpu).expect("prover stage6 CPU schema is valid"); + verify_cpu_schema(&verifier_cpu).expect("verifier stage6 CPU schema is valid"); + + let prover_kernel_text = prover_kernel_compute.to_text_mlir(); + let verifier_kernel_text = verifier_kernel_compute.to_text_mlir(); + let prover_cpu_text = prover_cpu.to_text_mlir(); + let verifier_cpu_text = verifier_cpu.to_text_mlir(); + assert!(prover_kernel_text.contains("kernel = @jolt.cpu.stage6.batched")); + assert!(prover_cpu_text.contains("kernel = @jolt.cpu.stage6.batched")); + assert!(prover_cpu_text.contains("point_order = \"bytecode_read_raf\"")); + assert!(verifier_cpu_text.contains("\"cpu.sumcheck_verify_claim\"")); + assert!(!verifier_kernel_text.contains("kernel = @")); + assert!(!verifier_cpu_text.contains("kernel = @")); +} + +#[test] +fn jolt_stage7_protocol_defines_hamming_weight_claim_reduction_flow() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let protocol = build_stage7_protocol(&context, ¶ms).expect("build stage7 protocol"); + verify_protocol_schema(&protocol).expect("stage7 protocol schema is valid"); + let concrete = + lower_piop_and_fiat_shamir(&context, &protocol).expect("lower stage7 to concrete"); + verify_concrete_transcript(&concrete).expect("stage7 transcript is threaded"); + + let text = protocol.to_text_mlir(); + assert!(text.contains("sym_name = \"jolt.stage7_hamming_weight_claim_reduction_domain\"")); + assert!(text.contains("sym_name = \"jolt.stage7.hamming_weight_claim_reduction\"")); + assert!(text.contains("sym_name = \"jolt.stage7.batched\"")); + assert!(text.contains("sym_name = \"stage7.hamming_weight_claim_reduction.gamma\"")); + assert!(text.contains("sym_name = \"stage7.field.one\"")); + assert!(text.contains("sym_name = \"stage7.hamming_weight_claim_reduction.input\"")); + assert!(text.contains("round_schedule = [4]")); + assert!(text.contains("ordered_claims = [@stage7.hamming_weight_claim_reduction.input]")); + assert!(text.contains("source_claim = @stage6.booleanity.opening.InstructionRa_0")); + assert!(text.contains("source_claim = @stage6.instruction_ra_virtual.opening.InstructionRa_0")); + assert!(text.contains("source_claim = @stage6.bytecode_read_raf.opening.BytecodeRa_0")); + assert!(text.contains("source_claim = @stage6.ram_ra_virtual.opening.RamRa_0")); + assert!(text.contains("source_claim = @stage6.hamming_booleanity.opening.HammingWeight")); + assert!(text.contains("sym_name = \"stage7.hamming_weight_claim_reduction.point.cycle\"")); + assert!(text.contains("sym_name = \"stage7.hamming_weight_claim_reduction.point\"")); + assert!(text.contains("@stage7.hamming_weight_claim_reduction.opening.InstructionRa_0")); + assert!(text.contains("@stage7.hamming_weight_claim_reduction.opening.BytecodeRa_0")); + assert!(text.contains("@stage7.hamming_weight_claim_reduction.opening.RamRa_0")); + assert!(!text.contains("kernel = @")); + assert!(!text.contains("\"compute.")); +} + +#[test] +fn jolt_stage7_lowers_to_compute_and_cpu_role_ir() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let protocol = build_stage7_protocol(&context, ¶ms).expect("build stage7 protocol"); + let concrete = + lower_piop_and_fiat_shamir(&context, &protocol).expect("lower stage7 to concrete"); + let prover = project_prover_party(&context, &concrete).expect("project prover party"); + let verifier = project_verifier_party(&context, &concrete).expect("project verifier party"); + let prover_compute = lower_stage7_to_compute(&context, &prover).expect("lower prover stage7"); + let verifier_compute = + lower_stage7_to_compute(&context, &verifier).expect("lower verifier stage7"); + verify_compute_schema(&prover_compute).expect("prover stage7 compute schema is valid"); + verify_compute_schema(&verifier_compute).expect("verifier stage7 compute schema is valid"); + + let prover_compute_text = prover_compute.to_text_mlir(); + let verifier_compute_text = verifier_compute.to_text_mlir(); + assert!(prover_compute_text.contains("\"compute.field_one\"()")); + assert!(prover_compute_text.contains("\"compute.field_pow\"(%")); + assert!(prover_compute_text.contains("\"compute.sumcheck_claim\"(%")); + assert!(prover_compute_text.contains("\"compute.sumcheck_driver\"(%")); + assert!(prover_compute_text.contains("\"compute.point_concat\"(%")); + assert!(verifier_compute_text.contains("\"compute.sumcheck_verify_claim\"")); + assert!(verifier_compute_text.contains("\"compute.sumcheck_verify\"")); + assert!(!verifier_compute_text.contains("kernel = @")); + + let prover_kernel_compute = + resolve_compute_kernels(&context, &prover_compute).expect("resolve prover kernels"); + let verifier_kernel_compute = + resolve_compute_kernels(&context, &verifier_compute).expect("resolve verifier kernels"); + verify_compute_schema(&prover_kernel_compute) + .expect("prover kernelized stage7 compute schema is valid"); + verify_compute_schema(&verifier_kernel_compute) + .expect("verifier kernelized stage7 compute schema is valid"); + + let prover_cpu = + lower_compute_to_cpu(&context, &prover_kernel_compute).expect("lower prover CPU"); + let verifier_cpu = + lower_compute_to_cpu(&context, &verifier_kernel_compute).expect("lower verifier CPU"); + verify_cpu_schema(&prover_cpu).expect("prover stage7 CPU schema is valid"); + verify_cpu_schema(&verifier_cpu).expect("verifier stage7 CPU schema is valid"); + + let prover_kernel_text = prover_kernel_compute.to_text_mlir(); + let verifier_kernel_text = verifier_kernel_compute.to_text_mlir(); + let prover_cpu_text = prover_cpu.to_text_mlir(); + let verifier_cpu_text = verifier_cpu.to_text_mlir(); + assert!(prover_kernel_text.contains("kernel = @jolt.cpu.stage7.batched")); + assert!(prover_cpu_text.contains("kernel = @jolt.cpu.stage7.batched")); + assert!(prover_cpu_text.contains("point_order = \"reverse\"")); + assert!(verifier_cpu_text.contains("\"cpu.sumcheck_verify_claim\"")); + assert!(!verifier_kernel_text.contains("kernel = @")); + assert!(!verifier_cpu_text.contains("kernel = @")); +} + +#[test] +fn jolt_stage8_protocol_defines_evaluation_proof_flow() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let protocol = build_stage8_protocol(&context, ¶ms).expect("build stage8 protocol"); + verify_protocol_schema(&protocol).expect("stage8 protocol schema is valid"); + let concrete = + lower_piop_and_fiat_shamir(&context, &protocol).expect("lower stage8 to concrete"); + verify_concrete_transcript(&concrete).expect("stage8 transcript is threaded"); + + let text = protocol.to_text_mlir(); + assert!(text.contains("sym_name = \"jolt.stage8\"")); + assert!(text.contains("name = \"evaluation_proof\"")); + assert!(text.contains("sym_name = \"stage8.evaluation.point_source\"")); + assert!(text.contains("source_claim = @stage7.input.stage6.booleanity.InstructionRa_0")); + assert!(text.contains("sym_name = \"stage8.evaluation.opening.RamInc\"")); + assert!(text.contains("source_claim = @stage6.inc_claim_reduction.eval.RamInc")); + assert!(text.contains("sym_name = \"stage8.evaluation.opening.InstructionRa_0\"")); + assert!( + text.contains("source_claim = @stage7.hamming_weight_claim_reduction.eval.InstructionRa_0") + ); + assert!(text.contains("\"pcs.opening_batch\"(%")); + assert!(text.contains("policy = \"jolt_stage8_joint_rlc\"")); + assert!(text.contains("transcript_label = \"rlc_claims\"")); + assert!(text.contains("ordered_claims = [@stage8.evaluation.opening.RamInc, @stage8.evaluation.opening.RdInc, @stage8.evaluation.opening.InstructionRa_0")); +} + +#[test] +fn jolt_stage8_lowers_to_compute_and_cpu_role_ir() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let protocol = build_stage8_protocol(&context, ¶ms).expect("build stage8 protocol"); + let concrete = + lower_piop_and_fiat_shamir(&context, &protocol).expect("lower stage8 to concrete"); + let prover = project_prover_party(&context, &concrete).expect("project prover party"); + let verifier = project_verifier_party(&context, &concrete).expect("project verifier party"); + let prover_compute = lower_stage8_to_compute(&context, &prover).expect("lower prover stage8"); + let verifier_compute = + lower_stage8_to_compute(&context, &verifier).expect("lower verifier stage8"); + verify_compute_schema(&prover_compute).expect("prover stage8 compute schema is valid"); + verify_compute_schema(&verifier_compute).expect("verifier stage8 compute schema is valid"); + + let prover_compute_text = prover_compute.to_text_mlir(); + let verifier_compute_text = verifier_compute.to_text_mlir(); + assert!(prover_compute_text.contains("\"compute.pcs_opening_claim\"(%")); + assert!(prover_compute_text.contains("\"compute.pcs_opening_batch\"(%")); + assert!(prover_compute_text.contains("\"compute.pcs_batch_open\"(%")); + assert!(!prover_compute_text.contains("\"compute.pcs_batch_verify\"(%")); + assert!(verifier_compute_text.contains("\"compute.pcs_batch_verify\"(%")); + assert!(!verifier_compute_text.contains("\"compute.pcs_batch_open\"(%")); + + let prover_kernel_compute = + resolve_compute_kernels(&context, &prover_compute).expect("resolve prover kernels"); + let verifier_kernel_compute = + resolve_compute_kernels(&context, &verifier_compute).expect("resolve verifier kernels"); + verify_compute_schema(&prover_kernel_compute) + .expect("prover kernelized stage8 compute schema is valid"); + verify_compute_schema(&verifier_kernel_compute) + .expect("verifier kernelized stage8 compute schema is valid"); + + let prover_cpu = + lower_compute_to_cpu(&context, &prover_kernel_compute).expect("lower prover CPU"); + let verifier_cpu = + lower_compute_to_cpu(&context, &verifier_kernel_compute).expect("lower verifier CPU"); + verify_cpu_schema(&prover_cpu).expect("prover stage8 CPU schema is valid"); + verify_cpu_schema(&verifier_cpu).expect("verifier stage8 CPU schema is valid"); + + let prover_cpu_text = prover_cpu.to_text_mlir(); + let verifier_cpu_text = verifier_cpu.to_text_mlir(); + assert!(prover_cpu_text.contains("\"cpu.pcs_batch_open\"(%")); + assert!(verifier_cpu_text.contains("\"cpu.pcs_batch_verify\"(%")); + assert!(!prover_cpu_text.contains("kernel = @")); + assert!(!verifier_cpu_text.contains("kernel = @")); +} + +#[test] +fn stage2_rust_targets_extract_and_compile() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let (prover_cpu, verifier_cpu) = build_stage2_pipeline_cpu(&context, ¶ms); + let prover_program = stage2_cpu_program(&prover_cpu).expect("extract prover stage2 program"); + let verifier_program = + stage2_cpu_program(&verifier_cpu).expect("extract verifier stage2 program"); + + assert_eq!(prover_program.role, Role::Prover); + assert_eq!(verifier_program.role, Role::Verifier); + assert_eq!(prover_program.kernels.len(), 7); + assert!(verifier_program.kernels.is_empty()); + assert_eq!(prover_program.opening_inputs.len(), 11); + assert_eq!(prover_program.field_exprs.len(), 21); + assert_eq!(prover_program.field_constants.len(), 1); + assert_eq!(prover_program.claims.len(), 6); + assert_eq!(prover_program.drivers.len(), 2); + assert_eq!(prover_program.point_slices.len(), 1); + assert_eq!(prover_program.point_concats.len(), 1); + assert!(prover_program + .claims + .iter() + .any(|claim| claim.claim_value == "stage2.ram_read_write.claim_expr")); + assert!(prover_program + .drivers + .iter() + .any(|driver| driver.kernel.as_deref() == Some("jolt.cpu.stage2.batched"))); + assert!(verifier_program + .claims + .iter() + .all(|claim| claim.kernel.is_none() && claim.relation.is_some())); + assert!(verifier_program + .drivers + .iter() + .all(|driver| driver.kernel.is_none() && driver.relation.is_some())); + + let prover_source = emit_stage2_rust(&prover_cpu).expect("emit stage2 prover rust"); + let verifier_source = emit_stage2_rust(&verifier_cpu).expect("emit stage2 verifier rust"); + assert_eq!(prover_source.filename, "prove_stage2.rs"); + assert_eq!(verifier_source.filename, "verify_stage2.rs"); + assert!(prover_source.source.contains("jolt_stage2_ram_read_write")); + assert!(prover_source.source.contains("Stage2KernelExecutor")); + assert!(!verifier_source.source.contains("jolt_kernels")); + assert!(verifier_source.source.contains("Stage2VerifierProgramPlan")); + assert!(verifier_source.source.contains("pub fn verify_stage2")); + assert!(verifier_source.source.contains("SumcheckVerifier::verify")); + assert_or_update_fixture("tests/fixtures/prove_stage2.rs", &prover_source.source); + assert_or_update_fixture("tests/fixtures/verify_stage2.rs", &verifier_source.source); + assert_rust_source_compiles(&prover_source.filename, &prover_source.source); + assert_rust_source_compiles(&verifier_source.filename, &verifier_source.source); +} + +#[test] +fn stage3_rust_targets_extract_and_compile() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let (prover_cpu, verifier_cpu) = build_stage3_pipeline_cpu(&context, ¶ms); + let prover_program = stage3_cpu_program(&prover_cpu).expect("extract prover stage3 program"); + let verifier_program = + stage3_cpu_program(&verifier_cpu).expect("extract verifier stage3 program"); + + assert_eq!(prover_program.role, Role::Prover); + assert_eq!(verifier_program.role, Role::Verifier); + assert_eq!(prover_program.kernels.len(), 4); + assert!(verifier_program.kernels.is_empty()); + assert_eq!(prover_program.opening_inputs.len(), 12); + assert_eq!(prover_program.field_exprs.len(), 19); + assert_eq!(prover_program.field_constants.len(), 1); + assert_eq!(prover_program.opening_equalities.len(), 2); + assert_eq!(prover_program.claims.len(), 3); + assert_eq!(prover_program.drivers.len(), 1); + assert_eq!(prover_program.opening_claims.len(), 16); + assert!(prover_program + .drivers + .iter() + .any(|driver| driver.kernel.as_deref() == Some("jolt.cpu.stage3.batched"))); + assert!(verifier_program + .claims + .iter() + .all(|claim| claim.kernel.is_none() && claim.relation.is_some())); + assert!(verifier_program + .drivers + .iter() + .all(|driver| driver.kernel.is_none() && driver.relation.is_some())); + + let prover_source = emit_stage3_rust(&prover_cpu).expect("emit stage3 prover rust"); + let verifier_source = emit_stage3_rust(&verifier_cpu).expect("emit stage3 verifier rust"); + assert_eq!(prover_source.filename, "prove_stage3.rs"); + assert_eq!(verifier_source.filename, "verify_stage3.rs"); + assert!(prover_source.source.contains("jolt_stage3_spartan_shift")); + assert!(prover_source.source.contains("Stage3KernelExecutor")); + assert!(prover_source + .source + .contains("Stage3OpeningClaimEqualityPlan")); + assert!(!verifier_source.source.contains("jolt_kernels")); + assert!(verifier_source.source.contains("Stage3VerifierProgramPlan")); + assert!(verifier_source.source.contains("pub fn verify_stage3")); + assert!(verifier_source + .source + .contains("super::common::verify_batched_sumcheck")); + assert!(verifier_source + .source + .contains("Stage3OpeningClaimEqualityPlan")); + assert_or_update_fixture("tests/fixtures/prove_stage3.rs", &prover_source.source); + assert_or_update_fixture("tests/fixtures/verify_stage3.rs", &verifier_source.source); + assert_rust_source_compiles(&prover_source.filename, &prover_source.source); + assert_rust_source_compiles(&verifier_source.filename, &verifier_source.source); +} + +#[test] +fn stage4_rust_targets_extract_and_compile() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let (prover_cpu, verifier_cpu) = build_stage4_pipeline_cpu(&context, ¶ms); + let prover_program = stage4_cpu_program(&prover_cpu).expect("extract prover stage4 program"); + let verifier_program = + stage4_cpu_program(&verifier_cpu).expect("extract verifier stage4 program"); + + assert_eq!(prover_program.role, Role::Prover); + assert_eq!(verifier_program.role, Role::Verifier); + assert_eq!(prover_program.kernels.len(), 3); + assert!(verifier_program.kernels.is_empty()); + assert_eq!(prover_program.steps.len(), 4); + assert_eq!(prover_program.transcript_squeezes.len(), 2); + assert_eq!(prover_program.transcript_absorb_bytes.len(), 1); + assert_eq!(prover_program.opening_inputs.len(), 8); + assert_eq!(prover_program.field_exprs.len(), 9); + assert!(prover_program.field_constants.is_empty()); + assert_eq!(prover_program.opening_equalities.len(), 2); + assert_eq!(prover_program.claims.len(), 2); + assert_eq!(prover_program.drivers.len(), 1); + assert_eq!(prover_program.instance_results.len(), 2); + assert_eq!(prover_program.evals.len(), 7); + assert_eq!(prover_program.point_slices.len(), 2); + assert_eq!(prover_program.point_concats.len(), 1); + assert_eq!(prover_program.opening_claims.len(), 7); + assert_eq!(prover_program.opening_batches.len(), 1); + assert!(prover_program + .transcript_absorb_bytes + .iter() + .any( + |absorb| absorb.symbol == "stage4.ram_val_check.domain_separator" + && absorb.label == "ram_val_check_gamma" + && absorb.payload.is_empty() + )); + assert!(prover_program + .drivers + .iter() + .any(|driver| driver.kernel.as_deref() == Some("jolt.cpu.stage4.batched"))); + assert!(verifier_program + .claims + .iter() + .all(|claim| claim.kernel.is_none() && claim.relation.is_some())); + assert!(verifier_program + .drivers + .iter() + .all(|driver| driver.kernel.is_none() && driver.relation.is_some())); + + let prover_source = emit_stage4_rust(&prover_cpu).expect("emit stage4 prover rust"); + let verifier_source = emit_stage4_rust(&verifier_cpu).expect("emit stage4 verifier rust"); + assert_eq!(prover_source.filename, "prove_stage4.rs"); + assert_eq!(verifier_source.filename, "verify_stage4.rs"); + assert!(prover_source.source.contains("jolt_stage4_ram_val_check")); + assert!(prover_source + .source + .contains("Stage4TranscriptAbsorbBytesPlan")); + assert!(prover_source + .source + .contains("STAGE4_TRANSCRIPT_ABSORB_BYTES")); + assert!(prover_source.source.contains("Stage4KernelExecutor")); + assert!(prover_source.source.contains("execute_stage4_program")); + assert!(prover_source.source.contains("execute_stage4_prover")); + assert!(!verifier_source.source.contains("jolt_kernels")); + assert!(verifier_source + .source + .contains("Stage4TranscriptAbsorbBytesPlan")); + assert!(verifier_source + .source + .contains("relation: Some(\"jolt.stage4.batched\")")); + assert!(verifier_source.source.contains("Stage4VerifierProgramPlan")); + assert!(verifier_source.source.contains("pub fn verify_stage4")); + assert!(verifier_source.source.contains("LabelWithCount")); + assert!(verifier_source + .source + .contains("super::common::verify_batched_sumcheck")); + assert!(verifier_source.source.contains("stage4_verifier_program")); + assert_or_update_fixture("tests/fixtures/prove_stage4.rs", &prover_source.source); + assert_or_update_fixture("tests/fixtures/verify_stage4.rs", &verifier_source.source); + assert_rust_source_compiles(&prover_source.filename, &prover_source.source); + assert_rust_source_compiles(&verifier_source.filename, &verifier_source.source); +} + +#[test] +fn stage5_rust_targets_extract_and_compile() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let (prover_cpu, verifier_cpu) = build_stage5_pipeline_cpu(&context, ¶ms); + let prover_program = stage5_cpu_program(&prover_cpu).expect("extract prover stage5 program"); + let verifier_program = + stage5_cpu_program(&verifier_cpu).expect("extract verifier stage5 program"); + + assert_eq!(prover_program.role, Role::Prover); + assert_eq!(verifier_program.role, Role::Verifier); + assert_eq!(prover_program.kernels.len(), 4); + assert!(verifier_program.kernels.is_empty()); + assert_eq!(prover_program.steps.len(), 3); + assert_eq!(prover_program.transcript_squeezes.len(), 2); + assert!(prover_program.transcript_absorb_bytes.is_empty()); + assert_eq!(prover_program.opening_inputs.len(), 8); + assert_eq!(prover_program.field_exprs.len(), 10); + assert!(prover_program.field_constants.is_empty()); + assert_eq!(prover_program.opening_equalities.len(), 1); + assert_eq!(prover_program.claims.len(), 3); + assert_eq!(prover_program.drivers.len(), 1); + assert_eq!(prover_program.instance_results.len(), 3); + assert_eq!( + prover_program.evals.len(), + params.lookup_table_count + params.instruction_ra_virtual_d + 4 + ); + assert_eq!( + prover_program.point_slices.len(), + params.instruction_ra_virtual_d + 3 + ); + assert_eq!( + prover_program.point_concats.len(), + params.instruction_ra_virtual_d + 2 + ); + assert_eq!( + prover_program.opening_claims.len(), + params.lookup_table_count + params.instruction_ra_virtual_d + 4 + ); + assert_eq!(prover_program.opening_batches.len(), 1); + assert!(prover_program + .drivers + .iter() + .any(|driver| driver.kernel.as_deref() == Some("jolt.cpu.stage5.batched"))); + assert!(prover_program.instance_results.iter().any(|instance| { + instance.symbol == "stage5.instruction_read_raf.instance" + && instance.point_order == "instruction_read_raf" + })); + assert!(verifier_program + .claims + .iter() + .all(|claim| claim.kernel.is_none() && claim.relation.is_some())); + assert!(verifier_program + .drivers + .iter() + .all(|driver| driver.kernel.is_none() && driver.relation.is_some())); + + let prover_source = emit_stage5_rust(&prover_cpu).expect("emit stage5 prover rust"); + let verifier_source = emit_stage5_rust(&verifier_cpu).expect("emit stage5 verifier rust"); + assert_eq!(prover_source.filename, "prove_stage5.rs"); + assert_eq!(verifier_source.filename, "verify_stage5.rs"); + assert!(prover_source + .source + .contains("jolt_stage5_instruction_read_raf")); + assert!(prover_source.source.contains("Stage5KernelExecutor")); + assert!(prover_source.source.contains("execute_stage5_program")); + assert!(prover_source.source.contains("execute_stage5_prover")); + assert!(!verifier_source.source.contains("jolt_kernels")); + assert!(verifier_source.source.contains("Stage5VerifierProgramPlan")); + assert!(verifier_source.source.contains("pub fn verify_stage5")); + assert!(verifier_source + .source + .contains("relation: Some(\"jolt.stage5.batched\")")); + assert!(verifier_source + .source + .contains("expected_instruction_read_raf")); + assert!(verifier_source + .source + .contains("jolt.stage5.instruction_read_raf")); + assert!(verifier_source + .source + .contains("LookupTableKind::::all")); + assert!(verifier_source + .source + .contains("use jolt_lookup_tables::LookupTableKind")); + assert!(verifier_source + .source + .contains("expected_ram_ra_claim_reduction")); + assert!(verifier_source + .source + .contains("expected_registers_val_evaluation")); + assert!(verifier_source + .source + .contains("jolt.stage5.ram_ra_claim_reduction")); + assert!(verifier_source + .source + .contains("jolt.stage5.registers_val_evaluation")); + assert!(verifier_source.source.contains("LookupTableFlag_39")); + assert!(!verifier_source.source.contains("LookupTableFlag_40")); + assert!(verifier_source + .source + .contains("stage5.instruction_read_raf.eval.InstructionRa_7")); + assert!(!verifier_source + .source + .contains("stage5.instruction_read_raf.eval.InstructionRa_8")); + assert!(!verifier_source + .source + .contains("jolt.stage5.registers_read_write")); + assert!(!verifier_source.source.contains("jolt.stage5.ram_val_check")); + assert!(verifier_source + .source + .contains("super::common::verify_batched_sumcheck")); + assert!(verifier_source.source.contains("stage5_verifier_program")); + assert_rust_source_compiles(&prover_source.filename, &prover_source.source); + assert_rust_source_compiles(&verifier_source.filename, &verifier_source.source); +} + +#[test] +fn stage6_rust_targets_extract_and_compile() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let (prover_cpu, verifier_cpu) = build_stage6_pipeline_cpu(&context, ¶ms); + let prover_program = stage6_cpu_program(&prover_cpu).expect("extract prover stage6 program"); + let verifier_program = + stage6_cpu_program(&verifier_cpu).expect("extract verifier stage6 program"); + + assert_eq!(prover_program.role, Role::Prover); + assert_eq!(verifier_program.role, Role::Verifier); + assert_eq!(prover_program.kernels.len(), 7); + assert!(verifier_program.kernels.is_empty()); + assert_eq!(prover_program.steps.len(), 10); + assert_eq!(prover_program.transcript_squeezes.len(), 9); + assert!(prover_program.transcript_absorb_bytes.is_empty()); + assert_eq!(prover_program.opening_inputs.len(), 90); + assert!(prover_program.field_exprs.len() > 150); + assert_eq!(prover_program.field_constants.len(), 1); + assert!(prover_program.opening_equalities.is_empty()); + assert_eq!(prover_program.claims.len(), 6); + assert_eq!(prover_program.drivers.len(), 1); + assert_eq!(prover_program.instance_results.len(), 6); + assert_eq!( + prover_program.evals.len(), + params.bytecode_d + + params.instruction_d + + params.bytecode_d + + params.ram_d + + 1 + + params.ram_d + + params.instruction_d + + 2 + ); + assert_eq!(prover_program.point_zeros.len(), 1); + assert_eq!( + prover_program.point_slices.len(), + params.bytecode_d + 1 + params.ram_d + params.instruction_d + ); + assert_eq!( + prover_program.point_concats.len(), + params.bytecode_d + 1 + params.ram_d + params.instruction_d + ); + assert_eq!( + prover_program.opening_claims.len(), + prover_program.evals.len() + ); + assert_eq!(prover_program.opening_batches.len(), 1); + assert!(prover_program + .drivers + .iter() + .any(|driver| driver.kernel.as_deref() == Some("jolt.cpu.stage6.batched"))); + assert!(prover_program.instance_results.iter().any(|instance| { + instance.symbol == "stage6.bytecode_read_raf.instance" + && instance.point_order == "bytecode_read_raf" + })); + assert!(prover_program.instance_results.iter().any(|instance| { + instance.symbol == "stage6.booleanity.instance" + && instance.point_order == "stage6_booleanity" + })); + assert!(verifier_program.opening_inputs.iter().any(|input| { + input.symbol == "stage6.input.stage1.LookupOutput" + && input.source_stage == "stage1" + && input.source_claim == "stage1.outer_remaining.opening.LookupOutput" + })); + assert!(verifier_program.claims.iter().any(|claim| { + claim.symbol == "stage6.hamming_booleanity.input" + && claim + .input_openings + .contains(&"stage6.input.stage1.LookupOutput".to_owned()) + })); + assert!(verifier_program.claims.iter().any(|claim| { + claim.symbol == "stage6.booleanity.input" && claim.input_openings.is_empty() + })); + assert!(verifier_program + .claims + .iter() + .all(|claim| claim.kernel.is_none() && claim.relation.is_some())); + assert!(verifier_program + .drivers + .iter() + .all(|driver| driver.kernel.is_none() && driver.relation.is_some())); + + let prover_source = emit_stage6_rust(&prover_cpu).expect("emit stage6 prover rust"); + let verifier_source = emit_stage6_rust(&verifier_cpu).expect("emit stage6 verifier rust"); + assert_eq!(prover_source.filename, "prove_stage6.rs"); + assert_eq!(verifier_source.filename, "verify_stage6.rs"); + assert!(prover_source + .source + .contains("jolt_stage6_bytecode_read_raf")); + assert!(prover_source.source.contains("Stage6KernelExecutor")); + assert!(prover_source.source.contains("execute_stage6_program")); + assert!(prover_source.source.contains("execute_stage6_prover")); + assert!(!verifier_source.source.contains("jolt_kernels")); + assert!(verifier_source.source.contains("Stage6VerifierProgramPlan")); + assert!(verifier_source.source.contains("pub fn verify_stage6")); + assert!(verifier_source + .source + .contains("relation: Some(\"jolt.stage6.batched\")")); + assert!(verifier_source + .source + .contains("jolt.stage6.bytecode_read_raf")); + assert!(verifier_source.source.contains("Stage6VerifierData")); + assert!(verifier_source.source.contains("Stage6BytecodeReadRafData")); + assert!(verifier_source.source.contains("Stage6BytecodeEntry")); + assert!(verifier_source + .source + .contains("expected_bytecode_read_raf")); + assert!(verifier_source + .source + .contains("stage6.bytecode_read_raf.data")); + assert!(verifier_source.source.contains("expected_booleanity")); + assert!(verifier_source + .source + .contains("expected_hamming_booleanity")); + assert!(verifier_source + .source + .contains("jolt.stage6.inc_claim_reduction")); + assert!(verifier_source + .source + .contains("stage6.input.stage1.LookupOutput")); + assert!(verifier_source.source.contains("expected_ram_ra_virtual")); + assert!(verifier_source + .source + .contains("expected_instruction_ra_virtual")); + assert!(verifier_source + .source + .contains("expected_inc_claim_reduction")); + assert!(verifier_source + .source + .contains("stage6.bytecode_read_raf.eval.BytecodeRa_0")); + assert!(verifier_source + .source + .contains("stage6.booleanity.eval.InstructionRa_31")); + assert!(verifier_source + .source + .contains("stage6.inc_claim_reduction.eval.RdInc")); + assert!(verifier_source + .source + .contains("super::common::verify_batched_sumcheck")); + assert!(verifier_source.source.contains("stage6_verifier_program")); + assert_rust_source_compiles(&prover_source.filename, &prover_source.source); + assert_rust_source_compiles(&verifier_source.filename, &verifier_source.source); +} + +#[test] +fn stage7_rust_targets_extract_and_compile() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let total_ra = params.instruction_d + params.bytecode_d + params.ram_d; + let (prover_cpu, verifier_cpu) = build_stage7_pipeline_cpu(&context, ¶ms); + let prover_program = stage7_cpu_program(&prover_cpu).expect("extract prover stage7 program"); + let verifier_program = + stage7_cpu_program(&verifier_cpu).expect("extract verifier stage7 program"); + + assert_eq!(prover_program.role, Role::Prover); + assert_eq!(verifier_program.role, Role::Verifier); + assert_eq!(prover_program.kernels.len(), 2); + assert!(verifier_program.kernels.is_empty()); + assert_eq!(prover_program.steps.len(), 2); + assert_eq!(prover_program.transcript_squeezes.len(), 1); + assert!(prover_program.transcript_absorb_bytes.is_empty()); + assert_eq!(prover_program.opening_inputs.len(), 1 + 2 * total_ra); + assert_eq!(prover_program.field_constants.len(), 1); + assert!(prover_program.field_exprs.len() >= 3 * total_ra); + assert_eq!(prover_program.claims.len(), 1); + assert_eq!(prover_program.batches.len(), 1); + assert_eq!(prover_program.drivers.len(), 1); + assert_eq!(prover_program.instance_results.len(), 1); + assert_eq!(prover_program.evals.len(), total_ra); + assert!(prover_program.point_zeros.is_empty()); + assert_eq!(prover_program.point_slices.len(), 1); + assert_eq!(prover_program.point_concats.len(), 1); + assert_eq!(prover_program.opening_claims.len(), total_ra); + assert_eq!(prover_program.opening_batches.len(), 1); + assert!(prover_program + .drivers + .iter() + .any(|driver| driver.kernel.as_deref() == Some("jolt.cpu.stage7.batched"))); + assert!(prover_program.claims.iter().any(|claim| { + claim.symbol == "stage7.hamming_weight_claim_reduction.input" + && claim.kernel.as_deref() == Some("jolt.cpu.stage7.hamming_weight_claim_reduction") + })); + assert!(prover_program.opening_claims.iter().any(|claim| { + claim.symbol == "stage7.hamming_weight_claim_reduction.opening.InstructionRa_0" + && claim.point_source == "stage7.hamming_weight_claim_reduction.point" + })); + assert!(verifier_program + .claims + .iter() + .all(|claim| claim.kernel.is_none() && claim.relation.is_some())); + assert!(verifier_program + .drivers + .iter() + .all(|driver| driver.kernel.is_none() && driver.relation.is_some())); + + let prover_source = emit_stage7_rust(&prover_cpu).expect("emit stage7 prover rust"); + let verifier_source = emit_stage7_rust(&verifier_cpu).expect("emit stage7 verifier rust"); + assert_eq!(prover_source.filename, "prove_stage7.rs"); + assert_eq!(verifier_source.filename, "verify_stage7.rs"); + assert!(prover_source + .source + .contains("jolt_stage7_hamming_weight_claim_reduction")); + assert!(prover_source.source.contains("Stage7KernelExecutor")); + assert!(prover_source.source.contains("execute_stage7_program")); + assert!(prover_source.source.contains("execute_stage7_prover")); + assert!(!verifier_source.source.contains("jolt_kernels")); + assert!(verifier_source.source.contains("Stage7VerifierProgramPlan")); + assert!(verifier_source.source.contains("pub fn verify_stage7")); + assert!(verifier_source + .source + .contains("relation: Some(\"jolt.stage7.batched\")")); + assert!(verifier_source + .source + .contains("jolt.stage7.hamming_weight_claim_reduction")); + assert!(verifier_source + .source + .contains("expected_hamming_weight_claim_reduction")); + assert!(verifier_source + .source + .contains("stage7.input.stage6.booleanity.InstructionRa_0")); + assert!(verifier_source + .source + .contains("stage7.hamming_weight_claim_reduction.eval.InstructionRa_0")); + assert!(verifier_source + .source + .contains("super::common::verify_batched_sumcheck")); + assert!(verifier_source.source.contains("stage7_verifier_program")); + assert_rust_source_compiles(&prover_source.filename, &prover_source.source); + assert_rust_source_compiles(&verifier_source.filename, &verifier_source.source); +} + +#[test] +fn stage8_rust_targets_extract_and_compile() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let expected_claims = params.num_committed; + let (prover_cpu, verifier_cpu) = build_stage8_pipeline_cpu(&context, ¶ms); + let prover_program = stage8_cpu_program(&prover_cpu).expect("extract prover stage8 program"); + let verifier_program = + stage8_cpu_program(&verifier_cpu).expect("extract verifier stage8 program"); + + assert_eq!(prover_program.role, Role::Prover); + assert_eq!(verifier_program.role, Role::Verifier); + assert_eq!(prover_program.opening_inputs.len(), expected_claims + 1); + assert_eq!(prover_program.opening_claims.len(), expected_claims); + assert_eq!(prover_program.opening_batches.len(), 1); + assert_eq!(prover_program.pcs_proofs.len(), 1); + assert_eq!(prover_program.pcs_proofs[0].mode, "open"); + assert_eq!(verifier_program.pcs_proofs[0].mode, "verify"); + assert_eq!( + prover_program.opening_batches[0].ordered_claims, + prover_program.opening_batches[0].claim_operands + ); + assert!(prover_program.opening_claims.iter().any(|claim| { + claim.symbol == "stage8.evaluation.opening.RamInc" + && claim.source_claim == "stage6.inc_claim_reduction.eval.RamInc" + })); + assert!(prover_program.opening_claims.iter().any(|claim| { + claim.symbol == "stage8.evaluation.opening.InstructionRa_0" + && claim.source_claim == "stage7.hamming_weight_claim_reduction.eval.InstructionRa_0" + })); + + let prover_source = emit_stage8_rust(&prover_cpu).expect("emit stage8 prover rust"); + let verifier_source = emit_stage8_rust(&verifier_cpu).expect("emit stage8 verifier rust"); + assert_eq!(prover_source.filename, "prove_stage8.rs"); + assert_eq!(verifier_source.filename, "verify_stage8.rs"); + assert!(prover_source.source.contains("pub const STAGE8_PROGRAM")); + assert!(prover_source + .source + .contains("stage8.evaluation.point_source")); + assert!(prover_source.source.contains("jolt_stage8_joint_rlc")); + assert!(prover_source + .source + .contains("stage6.inc_claim_reduction.eval.RamInc")); + assert!(prover_source + .source + .contains("stage7.hamming_weight_claim_reduction.eval.InstructionRa_0")); + assert!(verifier_source.source.contains("mode: \"verify\"")); + assert_rust_source_compiles(&prover_source.filename, &prover_source.source); + assert_rust_source_compiles(&verifier_source.filename, &verifier_source.source); +} + +#[test] +fn stage4_generated_artifact_crates_compile_in_isolation() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let (prover_cpu, verifier_cpu) = build_stage4_pipeline_cpu(&context, ¶ms); + let stage = ProtocolStage::new("stage4", "stage4", 4, ProtocolStageKind::Proof); + let config = jolt_artifact_config(); + let artifacts = vec![ + protocol_rust_artifact( + &config, + stage.clone(), + Role::Prover, + emit_stage4_rust(&prover_cpu).expect("emit stage4 prover"), + ), + protocol_rust_artifact( + &config, + stage, + Role::Verifier, + emit_stage4_rust(&verifier_cpu).expect("emit stage4 verifier"), + ), + ]; + for artifact in &artifacts { + validate_jolt_rust_artifact_imports(artifact).expect("stage4 import policy"); + } + + let output_root = new_temp_dir("bolt_stage4_generated_crates"); + let dependency_root = workspace_root().join("crates"); + let generated_crates = + assemble_jolt_generated_crates(artifacts, &dependency_root.display().to_string()) + .expect("assemble stage4 crates"); + write_jolt_generated_crates(&generated_crates, &output_root) + .expect("write stage4 generated crates"); + redirect_generated_prover_to_generated_verifier(&output_root, &dependency_root); + for generated in &generated_crates { + assert_generated_crate_manifest_compiles(&output_root, &generated.crate_name); + } + let _ = std::fs::remove_dir_all(output_root); +} + +#[test] +fn generic_artifact_assembly_supports_non_jolt_protocol_config() { + let config = non_jolt_artifact_config(); + let stage = ProtocolStage::new("alpha", "alpha", 1, ProtocolStageKind::Proof); + let artifacts = vec![ + protocol_rust_artifact( + &config, + stage.clone(), + Role::Prover, + non_jolt_alpha_prover_source(), + ), + protocol_rust_artifact( + &config, + stage, + Role::Verifier, + non_jolt_alpha_verifier_source(), + ), + ]; + assert_eq!( + artifacts[0].path, "acme-prover/src/stages/alpha.rs", + "generic artifact path should derive from config and stage module" + ); + assert_eq!( + artifacts[1].path, "acme-verifier/src/stages/alpha.rs", + "generic artifact path should derive from config and stage module" + ); + for artifact in &artifacts { + validate_rust_artifact_imports(&config, artifact).expect("generic import policy"); + } + + let generated = + assemble_generated_crates(&config, artifacts, "../deps").expect("assemble generic crates"); + let prover = generated + .iter() + .find(|generated| generated.crate_name == "acme-prover") + .expect("generated prover crate"); + let verifier = generated + .iter() + .find(|generated| generated.crate_name == "acme-verifier") + .expect("generated verifier crate"); + + let prover_manifest = prover + .files + .iter() + .find(|file| file.path == "Cargo.toml") + .expect("prover manifest") + .source + .as_str(); + assert!(prover_manifest.contains("name = \"acme-prover\"")); + assert!(prover_manifest.contains("acme-verifier = { path = \"../deps/acme-verifier\" }")); + assert!(prover_manifest.contains("serde = { version = \"1\", default-features = false }")); + assert!(!prover_manifest.contains("serde = { path = ")); + assert!(prover.files.iter().any(|file| file.path == "src/prover.rs")); + assert!(prover + .files + .iter() + .any(|file| file.path == "src/stages/alpha.rs")); + + let verifier_stages = verifier + .files + .iter() + .find(|file| file.path == "src/stages/mod.rs") + .expect("verifier stages module") + .source + .as_str(); + assert!(verifier_stages.contains("pub mod shared;")); + assert!(verifier_stages.contains("pub mod alpha;")); + assert!(verifier + .files + .iter() + .any(|file| file.path == "src/verifier.rs")); + assert!(verifier + .files + .iter() + .any(|file| file.path == "src/stages/shared.rs")); + + let generated_surface = generated + .iter() + .flat_map(|generated| generated.files.iter()) + .map(|file| file.source.as_str()) + .collect::>() + .join("\n"); + assert!( + !generated_surface.contains("jolt") && !generated_surface.contains("Jolt"), + "generic artifact assembly leaked Jolt names into a non-Jolt protocol fixture" + ); + assert!( + !generated_surface.contains("ark-bn254") && !generated_surface.contains("arkworks-algebra"), + "generic artifact assembly leaked Jolt/arkworks standalone manifest patches into a non-Jolt protocol fixture" + ); + assert!(generated_surface.contains("pub const TRANSCRIPT_LABEL: &[u8] = b\"acme transcript\";")); + assert!(generated_surface.contains("crate::stages::shared::StageProof")); + assert!(generated_surface.contains("pub fn prove_acme")); + assert!(generated_surface.contains("pub fn verify_acme")); +} + +#[test] +fn generated_jolt_artifacts_have_uniform_crate_layout_and_import_rules() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let (commitment_prover_cpu, commitment_verifier_cpu) = + build_commitment_pipeline_cpu(&context, ¶ms); + let (stage1_prover_cpu, stage1_verifier_cpu) = build_stage1_pipeline_cpu(&context, ¶ms); + let (stage2_prover_cpu, stage2_verifier_cpu) = build_stage2_pipeline_cpu(&context, ¶ms); + let (stage3_prover_cpu, stage3_verifier_cpu) = build_stage3_pipeline_cpu(&context, ¶ms); + let (stage4_prover_cpu, stage4_verifier_cpu) = build_stage4_pipeline_cpu(&context, ¶ms); + let (stage5_prover_cpu, stage5_verifier_cpu) = build_stage5_pipeline_cpu(&context, ¶ms); + let (stage6_prover_cpu, stage6_verifier_cpu) = build_stage6_pipeline_cpu(&context, ¶ms); + let (stage7_prover_cpu, stage7_verifier_cpu) = build_stage7_pipeline_cpu(&context, ¶ms); + let (stage8_prover_cpu, stage8_verifier_cpu) = build_stage8_pipeline_cpu(&context, ¶ms); + + let emitted = [ + ( + JoltProtocolStage::Commitment, + Role::Prover, + emit_commitment_rust(&commitment_prover_cpu).expect("emit commitment prover"), + ), + ( + JoltProtocolStage::Commitment, + Role::Verifier, + emit_commitment_rust(&commitment_verifier_cpu).expect("emit commitment verifier"), + ), + ( + JoltProtocolStage::Stage1Outer, + Role::Prover, + emit_stage1_rust(&stage1_prover_cpu).expect("emit stage1 prover"), + ), + ( + JoltProtocolStage::Stage1Outer, + Role::Verifier, + emit_stage1_rust(&stage1_verifier_cpu).expect("emit stage1 verifier"), + ), + ( + JoltProtocolStage::Stage2, + Role::Prover, + emit_stage2_rust(&stage2_prover_cpu).expect("emit stage2 prover"), + ), + ( + JoltProtocolStage::Stage2, + Role::Verifier, + emit_stage2_rust(&stage2_verifier_cpu).expect("emit stage2 verifier"), + ), + ( + JoltProtocolStage::Stage3, + Role::Prover, + emit_stage3_rust(&stage3_prover_cpu).expect("emit stage3 prover"), + ), + ( + JoltProtocolStage::Stage3, + Role::Verifier, + emit_stage3_rust(&stage3_verifier_cpu).expect("emit stage3 verifier"), + ), + ( + JoltProtocolStage::Stage4, + Role::Prover, + emit_stage4_rust(&stage4_prover_cpu).expect("emit stage4 prover"), + ), + ( + JoltProtocolStage::Stage4, + Role::Verifier, + emit_stage4_rust(&stage4_verifier_cpu).expect("emit stage4 verifier"), + ), + ( + JoltProtocolStage::Stage5, + Role::Prover, + emit_stage5_rust(&stage5_prover_cpu).expect("emit stage5 prover"), + ), + ( + JoltProtocolStage::Stage5, + Role::Verifier, + emit_stage5_rust(&stage5_verifier_cpu).expect("emit stage5 verifier"), + ), + ( + JoltProtocolStage::Stage6, + Role::Prover, + emit_stage6_rust(&stage6_prover_cpu).expect("emit stage6 prover"), + ), + ( + JoltProtocolStage::Stage6, + Role::Verifier, + emit_stage6_rust(&stage6_verifier_cpu).expect("emit stage6 verifier"), + ), + ( + JoltProtocolStage::Stage7, + Role::Prover, + emit_stage7_rust(&stage7_prover_cpu).expect("emit stage7 prover"), + ), + ( + JoltProtocolStage::Stage7, + Role::Verifier, + emit_stage7_rust(&stage7_verifier_cpu).expect("emit stage7 verifier"), + ), + ( + JoltProtocolStage::Stage8, + Role::Prover, + emit_stage8_rust(&stage8_prover_cpu).expect("emit stage8 prover"), + ), + ( + JoltProtocolStage::Stage8, + Role::Verifier, + emit_stage8_rust(&stage8_verifier_cpu).expect("emit stage8 verifier"), + ), + ]; + let artifacts = emitted + .into_iter() + .map(|(stage, role, source)| { + let artifact = jolt_rust_artifact(stage, role, source).expect("canonical artifact"); + validate_jolt_rust_artifact_imports(&artifact).expect("artifact import policy"); + artifact + }) + .collect::>(); + + let paths = artifacts + .iter() + .map(|artifact| artifact.path.as_str()) + .collect::>(); + assert_eq!( + paths, + vec![ + "jolt-prover/src/stages/commitment.rs", + "jolt-verifier/src/stages/commitment.rs", + "jolt-prover/src/stages/stage1_outer.rs", + "jolt-verifier/src/stages/stage1_outer.rs", + "jolt-prover/src/stages/stage2.rs", + "jolt-verifier/src/stages/stage2.rs", + "jolt-prover/src/stages/stage3.rs", + "jolt-verifier/src/stages/stage3.rs", + "jolt-prover/src/stages/stage4.rs", + "jolt-verifier/src/stages/stage4.rs", + "jolt-prover/src/stages/stage5.rs", + "jolt-verifier/src/stages/stage5.rs", + "jolt-prover/src/stages/stage6.rs", + "jolt-verifier/src/stages/stage6.rs", + "jolt-prover/src/stages/stage7.rs", + "jolt-verifier/src/stages/stage7.rs", + "jolt-prover/src/stages/stage8.rs", + "jolt-verifier/src/stages/stage8.rs", + ] + ); + assert!(artifacts + .iter() + .filter(|artifact| artifact.crate_name == "jolt-verifier") + .all(|artifact| !artifact.source.source.contains("jolt_kernels"))); + assert!(artifacts + .iter() + .filter(|artifact| { artifact.crate_name == "jolt-prover" && artifact.stage.is_proof() }) + .all(|artifact| artifact.source.source.contains("jolt_kernels"))); + let workspace_generated_crates = assemble_jolt_workspace_generated_crates(artifacts.clone()) + .expect("assemble workspace generated role crates"); + if std::env::var_os("JOLT_UPDATE_GOLDENS").is_some() { + write_jolt_generated_crates(&workspace_generated_crates, workspace_root().join("crates")) + .expect("update checked-in generated role crates"); + } + assert_checked_in_generated_role_crate_sources_match(&workspace_generated_crates); + let dependency_root = workspace_root().join("crates").display().to_string(); + let generated_crates = assemble_jolt_generated_crates(artifacts, &dependency_root) + .expect("assemble generated role crates"); + assert_eq!( + generated_crates + .iter() + .map(|generated| generated.crate_name.as_str()) + .collect::>(), + vec!["jolt-prover", "jolt-verifier"] + ); + for generated in &generated_crates { + assert_generated_role_crate_compiles(generated); + } + let output_root = new_temp_dir("bolt_generated_crates"); + write_jolt_generated_crates(&workspace_generated_crates, &output_root) + .expect("write generated role crates"); + for generated in &workspace_generated_crates { + for file in &generated.files { + assert!(output_root + .join(&generated.crate_name) + .join(&file.path) + .exists()); + } + } + let _ = std::fs::remove_dir_all(output_root); +} + +#[test] +fn jolt_stage1_outer_lowers_to_compute_and_cpu_kernel_ir() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let protocol = + build_stage1_outer_protocol(&context, ¶ms).expect("build stage1 outer protocol"); + let concrete = + lower_piop_and_fiat_shamir(&context, &protocol).expect("lower stage1 to concrete"); + let prover = project_prover_party(&context, &concrete).expect("project prover party"); + let verifier = project_verifier_party(&context, &concrete).expect("project verifier party"); + let prover_compute = lower_stage1_to_compute(&context, &prover).expect("lower prover stage1"); + let verifier_compute = + lower_stage1_to_compute(&context, &verifier).expect("lower verifier stage1"); + verify_compute_schema(&prover_compute).expect("prover stage1 compute schema is valid"); + verify_compute_schema(&verifier_compute).expect("verifier stage1 compute schema is valid"); + assert!(prover_compute + .to_text_mlir() + .contains("relation = @jolt.stage1.outer.uniskip")); + assert!(!prover_compute.to_text_mlir().contains("kernel = @")); + let verifier_compute_text = verifier_compute.to_text_mlir(); + assert!(verifier_compute_text.contains("\"compute.sumcheck_verify_claim\"")); + assert!(verifier_compute_text.contains("\"compute.sumcheck_verify\"")); + assert!(!verifier_compute_text.contains("\"compute.kernel\"")); + assert!(!verifier_compute_text.contains("kernel = @")); + + let prover_kernel_compute = + resolve_compute_kernels(&context, &prover_compute).expect("resolve prover kernels"); + let verifier_kernel_compute = + resolve_compute_kernels(&context, &verifier_compute).expect("resolve verifier kernels"); + verify_compute_schema(&prover_kernel_compute) + .expect("prover kernelized stage1 compute schema is valid"); + verify_compute_schema(&verifier_kernel_compute) + .expect("verifier kernelized stage1 compute schema is valid"); + + let prover_cpu = + lower_compute_to_cpu(&context, &prover_kernel_compute).expect("lower prover CPU"); + let verifier_cpu = + lower_compute_to_cpu(&context, &verifier_kernel_compute).expect("lower verifier CPU"); + verify_cpu_schema(&prover_cpu).expect("prover stage1 CPU schema is valid"); + verify_cpu_schema(&verifier_cpu).expect("verifier stage1 CPU schema is valid"); + let program = stage1_cpu_program(&prover_cpu).expect("extract prover stage1 CPU program"); + + let cpu_text = prover_cpu.to_text_mlir(); + let verifier_cpu_text = verifier_cpu.to_text_mlir(); + assert!(cpu_text.contains("\"cpu.kernel\"()")); + assert!(cpu_text.contains("kernel = @jolt.cpu.stage1.outer.uniskip")); + assert!(cpu_text.contains("kernel = @jolt.cpu.stage1.outer.remaining")); + assert!(cpu_text.contains("\"cpu.sumcheck_driver\"(%")); + assert!(cpu_text.contains("\"cpu.sumcheck_eval\"(%")); + assert!(cpu_text.contains("\"cpu.opening_claim\"(%")); + assert!(cpu_text.contains("\"cpu.opening_batch\"(%")); + assert!(cpu_text.contains("\"cpu.sumcheck_claim\"(%")); + assert!(cpu_text.contains("count = 35 : i64")); + assert!(!cpu_text.contains("\"cpu.pcs_opening_claim\"")); + assert!(verifier_cpu_text.contains("\"cpu.sumcheck_verify_claim\"")); + assert!(verifier_cpu_text.contains("\"cpu.sumcheck_verify\"")); + assert!(!verifier_cpu_text.contains("\"cpu.kernel\"")); + assert!(!verifier_cpu_text.contains("kernel = @")); + assert_eq!(program.role, Role::Prover); + assert_eq!(program.kernels.len(), 2); + assert!(program.kernels.iter().any(|kernel| { + kernel.symbol == "jolt.cpu.stage1.outer.uniskip" + && kernel.relation == "jolt.stage1.outer.uniskip" + && kernel.abi == "jolt_stage1_outer_uniskip" + })); + assert!(program.kernels.iter().any(|kernel| { + kernel.symbol == "jolt.cpu.stage1.outer.remaining" + && kernel.relation == "jolt.stage1.outer.remaining" + && kernel.abi == "jolt_stage1_outer_remaining" + })); + assert_eq!(program.claims.len(), 2); + assert_eq!(program.batches.len(), 2); + assert_eq!(program.drivers.len(), 2); + assert_eq!(program.opening_claims.len(), 36); + assert_eq!(program.opening_batches.len(), 1); + let uniskip = program + .drivers + .iter() + .find(|driver| driver.symbol == "stage1.uniskip.sumcheck") + .expect("uniskip driver"); + assert_eq!( + uniskip.kernel.as_deref(), + Some("jolt.cpu.stage1.outer.uniskip") + ); + assert_eq!(uniskip.round_schedule, vec![1]); + assert_eq!(uniskip.num_rounds, 1); + assert_eq!(uniskip.degree, 27); + let remaining = program + .drivers + .iter() + .find(|driver| driver.symbol == "stage1.outer_remaining.sumcheck") + .expect("remaining driver"); + assert_eq!( + remaining.kernel.as_deref(), + Some("jolt.cpu.stage1.outer.remaining") + ); + assert_eq!(remaining.round_schedule, vec![params.log_t + 1]); + assert_eq!(remaining.num_rounds, params.log_t + 1); + assert_eq!(remaining.degree, 3); + assert_eq!( + program + .evals + .iter() + .filter(|eval| eval.source == "stage1.outer_remaining.sumcheck") + .count(), + 35 + ); + assert_eq!(program.opening_batches[0].count, 35); + assert_eq!( + program.opening_batches[0].ordered_claims, + program.opening_batches[0].claim_operands + ); + + assert_or_update_fixture( + "tests/fixtures/stage1_outer_prover_compute.mlir", + &prover_compute.to_text_mlir(), + ); + assert_or_update_fixture( + "tests/fixtures/stage1_outer_verifier_compute.mlir", + &verifier_compute.to_text_mlir(), + ); + assert_or_update_fixture( + "tests/fixtures/stage1_outer_prover_kernel_compute.mlir", + &prover_kernel_compute.to_text_mlir(), + ); + assert_or_update_fixture( + "tests/fixtures/stage1_outer_verifier_kernel_compute.mlir", + &verifier_kernel_compute.to_text_mlir(), + ); + assert_or_update_fixture( + "tests/fixtures/stage1_outer_prover_cpu.mlir", + &prover_cpu.to_text_mlir(), + ); + assert_or_update_fixture( + "tests/fixtures/stage1_outer_verifier_cpu.mlir", + &verifier_cpu.to_text_mlir(), + ); +} + +#[test] +fn stage1_rust_emission_matches_golden_and_compiles() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let protocol = + build_stage1_outer_protocol(&context, ¶ms).expect("build stage1 outer protocol"); + let concrete = + lower_piop_and_fiat_shamir(&context, &protocol).expect("lower stage1 to concrete"); + let prover = project_prover_party(&context, &concrete).expect("project prover party"); + let verifier = project_verifier_party(&context, &concrete).expect("project verifier party"); + let prover_compute = lower_stage1_to_compute(&context, &prover).expect("lower prover stage1"); + let verifier_compute = + lower_stage1_to_compute(&context, &verifier).expect("lower verifier stage1"); + let prover_kernel_compute = + resolve_compute_kernels(&context, &prover_compute).expect("resolve prover kernels"); + let verifier_kernel_compute = + resolve_compute_kernels(&context, &verifier_compute).expect("resolve verifier kernels"); + let prover_cpu = + lower_compute_to_cpu(&context, &prover_kernel_compute).expect("lower prover CPU"); + let verifier_cpu = + lower_compute_to_cpu(&context, &verifier_kernel_compute).expect("lower verifier CPU"); + let source = emit_stage1_rust(&prover_cpu).expect("emit prover stage1 rust"); + let verifier_source = emit_stage1_rust(&verifier_cpu).expect("emit verifier stage1 rust"); + + assert_eq!(source.filename, "prove_stage1_outer.rs"); + assert_eq!(verifier_source.filename, "verify_stage1_outer.rs"); + assert!(source.source.contains("pub fn prove_stage1_outer")); + assert!(verifier_source + .source + .contains("pub fn verify_stage1_outer")); + assert!(source.source.contains("jolt_stage1_outer_uniskip")); + assert!(source.source.contains("jolt_stage1_outer_remaining")); + assert!(!verifier_source.source.contains("jolt_kernels")); + assert!(verifier_source.source.contains("jolt_sumcheck")); + assert_or_update_fixture("tests/fixtures/prove_stage1_outer.rs", &source.source); + assert_or_update_fixture( + "tests/fixtures/verify_stage1_outer.rs", + &verifier_source.source, + ); + assert_rust_source_compiles(&source.filename, &source.source); + assert_rust_source_compiles(&verifier_source.filename, &verifier_source.source); +} + +#[test] +fn generated_stage1_prover_shape_proof_verifier_accepts() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::new(2, 2, 2); + let (prover_cpu, verifier_cpu) = build_stage1_pipeline_cpu(&context, ¶ms); + let prover_source = emit_stage1_rust(&prover_cpu).expect("emit stage1 prover rust"); + let verifier_source = emit_stage1_rust(&verifier_cpu).expect("emit stage1 verifier rust"); + + assert_eq!(prover_source.filename, "prove_stage1_outer.rs"); + assert_eq!(verifier_source.filename, "verify_stage1_outer.rs"); + assert_generated_stage1_self_parity_runs( + &prover_source, + &verifier_source, + &generated_stage1_shape_self_parity_main(), + ); +} + +#[test] +fn generated_stage1_real_executor_reaches_kernel_dispatch() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::new(2, 2, 2); + let (prover_cpu, verifier_cpu) = build_stage1_pipeline_cpu(&context, ¶ms); + let prover_source = emit_stage1_rust(&prover_cpu).expect("emit stage1 prover rust"); + let verifier_source = emit_stage1_rust(&verifier_cpu).expect("emit stage1 verifier rust"); + + assert_generated_stage1_self_parity_runs( + &prover_source, + &verifier_source, + generated_stage1_real_dispatch_main(), + ); +} + +#[test] +fn generated_stage1_real_executor_self_verifies_synthetic_remaining() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::new(2, 2, 2); + let (prover_cpu, verifier_cpu) = build_stage1_pipeline_cpu(&context, ¶ms); + let prover_source = emit_stage1_rust(&prover_cpu).expect("emit stage1 prover rust"); + let verifier_source = emit_stage1_rust(&verifier_cpu).expect("emit stage1 verifier rust"); + + assert_generated_stage1_self_parity_runs( + &prover_source, + &verifier_source, + &generated_stage1_synthetic_remaining_main(), + ); +} + +#[test] +fn generated_stage1_real_executor_self_verifies_r1cs_data() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::new(2, 2, 2); + let (prover_cpu, verifier_cpu) = build_stage1_pipeline_cpu(&context, ¶ms); + let prover_source = emit_stage1_rust(&prover_cpu).expect("emit stage1 prover rust"); + let verifier_source = emit_stage1_rust(&verifier_cpu).expect("emit stage1 verifier rust"); + + assert_generated_stage1_self_parity_runs( + &prover_source, + &verifier_source, + &generated_stage1_r1cs_data_main(), + ); +} + +#[test] +fn jolt_protocol_chain_commitment_stage1_fixture_tracks_phase_order() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let chain = jolt_protocol_chain_commitment_stage1_fixture(&context, ¶ms); + + assert_or_update_fixture( + "tests/fixtures/jolt_protocol_chain_commitment_stage1.yaml", + &chain, + ); +} + +#[test] +fn generated_jolt_chain_commitment_then_stage1_self_parity_runs() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::new(2, 2, 2); + let (commitment_prover_cpu, commitment_verifier_cpu) = + build_commitment_pipeline_cpu(&context, ¶ms); + let (stage1_prover_cpu, stage1_verifier_cpu) = build_stage1_pipeline_cpu(&context, ¶ms); + let commitment_prover = + emit_commitment_rust(&commitment_prover_cpu).expect("emit commitment prover rust"); + let commitment_verifier = + emit_commitment_rust(&commitment_verifier_cpu).expect("emit commitment verifier rust"); + let stage1_prover = emit_stage1_rust(&stage1_prover_cpu).expect("emit stage1 prover rust"); + let stage1_verifier = + emit_stage1_rust(&stage1_verifier_cpu).expect("emit stage1 verifier rust"); + + assert_generated_jolt_chain_self_parity_runs( + &[ + &commitment_prover, + &commitment_verifier, + &stage1_prover, + &stage1_verifier, + ], + &generated_commitment_stage1_chain_main(), + ); +} + +#[test] +fn commitment_pipeline_matches_golden_mlir_fixtures() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let protocol = build_commitment_protocol(&context, ¶ms).expect("build protocol"); + let concrete = + lower_piop_and_fiat_shamir(&context, &protocol).expect("lower Fiat-Shamir state"); + let prover = project_prover_party(&context, &concrete).expect("project prover party"); + let verifier = project_verifier_party(&context, &concrete).expect("project verifier party"); + let prover_compute = lower_commitment_to_compute(&context, &prover).expect("lower compute"); + let verifier_compute = + lower_commitment_to_compute(&context, &verifier).expect("lower verifier compute"); + let prover_cpu = lower_compute_to_cpu(&context, &prover_compute).expect("lower to CPU"); + let verifier_cpu = + lower_compute_to_cpu(&context, &verifier_compute).expect("lower verifier to CPU"); + + assert_or_update_fixture( + "tests/fixtures/commitment_protocol.mlir", + &protocol.to_text_mlir(), + ); + assert_or_update_fixture( + "tests/fixtures/commitment_concrete.mlir", + &concrete.to_text_mlir(), + ); + assert_or_update_fixture( + "tests/fixtures/commitment_prover_party.mlir", + &prover.to_text_mlir(), + ); + assert_or_update_fixture( + "tests/fixtures/commitment_verifier_party.mlir", + &verifier.to_text_mlir(), + ); + assert_or_update_fixture( + "tests/fixtures/commitment_prover_compute.mlir", + &prover_compute.to_text_mlir(), + ); + assert_or_update_fixture( + "tests/fixtures/commitment_verifier_compute.mlir", + &verifier_compute.to_text_mlir(), + ); + assert_or_update_fixture( + "tests/fixtures/commitment_prover_cpu.mlir", + &prover_cpu.to_text_mlir(), + ); + assert_or_update_fixture( + "tests/fixtures/commitment_verifier_cpu.mlir", + &verifier_cpu.to_text_mlir(), + ); +} + +#[test] +fn commitment_rust_emission_matches_golden_and_compiles() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::fixture(); + let protocol = build_commitment_protocol(&context, ¶ms).expect("build protocol"); + let concrete = + lower_piop_and_fiat_shamir(&context, &protocol).expect("lower Fiat-Shamir state"); + let prover = project_prover_party(&context, &concrete).expect("project prover party"); + let verifier = project_verifier_party(&context, &concrete).expect("project verifier party"); + let prover_compute = lower_commitment_to_compute(&context, &prover).expect("lower compute"); + let verifier_compute = + lower_commitment_to_compute(&context, &verifier).expect("lower verifier compute"); + let prover_cpu = lower_compute_to_cpu(&context, &prover_compute).expect("lower to CPU"); + let verifier_cpu = + lower_compute_to_cpu(&context, &verifier_compute).expect("lower verifier to CPU"); + let source = emit_commitment_rust(&prover_cpu).expect("emit prover commitment rust"); + let verifier_source = + emit_commitment_rust(&verifier_cpu).expect("emit verifier commitment rust"); + + assert_eq!(source.filename, "prove_commitment_phase.rs"); + assert_eq!(verifier_source.filename, "verify_commitment_phase.rs"); + assert_or_update_fixture("tests/fixtures/prove_commitment_phase.rs", &source.source); + assert_or_update_fixture( + "tests/fixtures/verify_commitment_phase.rs", + &verifier_source.source, + ); + assert_rust_source_compiles(&source.filename, &source.source); + assert_rust_source_compiles(&verifier_source.filename, &verifier_source.source); +} + +#[test] +fn generated_commitment_prover_verifier_self_parity_runs() { + let context = MeliorContext::new(); + let prover_cpu = build_small_commitment_cpu(&context, Role::Prover); + let verifier_cpu = build_small_commitment_cpu(&context, Role::Verifier); + let prover_source = + emit_commitment_rust(&prover_cpu).expect("emit small prover commitment rust"); + let verifier_source = + emit_commitment_rust(&verifier_cpu).expect("emit small verifier commitment rust"); + + assert_eq!(prover_source.filename, "prove_commitment_phase.rs"); + assert_eq!(verifier_source.filename, "verify_commitment_phase.rs"); + assert_generated_commitment_self_parity_runs( + &prover_source, + &verifier_source, + &generated_small_self_parity_main(), + ); +} + +#[test] +fn pipeline_generated_commitment_prover_verifier_self_parity_runs() { + let context = MeliorContext::new(); + let params = JoltProtocolParams::new(0, 0, 0); + let (prover_cpu, verifier_cpu) = build_commitment_pipeline_cpu(&context, ¶ms); + let prover_source = + emit_commitment_rust(&prover_cpu).expect("emit pipeline prover commitment rust"); + let verifier_source = + emit_commitment_rust(&verifier_cpu).expect("emit pipeline verifier commitment rust"); + + assert_eq!(prover_source.filename, "prove_commitment_phase.rs"); + assert_eq!(verifier_source.filename, "verify_commitment_phase.rs"); + assert_generated_commitment_self_parity_runs( + &prover_source, + &verifier_source, + &generated_pipeline_self_parity_main(), + ); +} + +#[test] +fn commitment_rust_emission_requires_cpu_target_params() { + let context = MeliorContext::new(); + let cpu = context + .parse_module::( + r#" +module @bad attributes {bolt.phase = "cpu", bolt.role = "prover"} { + %0 = "cpu.oracle_family_init"() {count = 1 : i64, family = @bad.family, sym_name = "bad.family"} : () -> !cpu.oracle_family + %1 = "cpu.oracle_ref"() {domain = @bad.domain, num_vars = 1 : i64, oracle = @A, sym_name = "bad.A"} : () -> !cpu.oracle_buffer + %2 = "cpu.oracle_family_append"(%0, %1) {family = @bad.family, index = 0 : i64, oracle = @A, sym_name = "bad.family.append0"} : (!cpu.oracle_family, !cpu.oracle_buffer) -> !cpu.oracle_family + %3 = "cpu.pcs_commit_batch"(%2) {artifact = @bad.artifact, count = 1 : i64, domain = @bad.domain, label = "bad", num_vars = 1 : i64, oracle_family = @bad.family, ordered_oracles = [@A], pcs = @dory, sym_name = "bad.batch"} : (!cpu.oracle_family) -> !cpu.commitment_artifact +} +"#, + ) + .expect("parse bad CPU module"); + + let error = emit_commitment_rust(&cpu).expect_err("missing params rejected"); + assert!(error.to_string().contains("missing cpu.params")); +} + +fn build_small_commitment_cpu(context: &MeliorContext, role: Role) -> bolt::BoltModule<'_, Cpu> { + let (batch_op, optional_op) = match role { + Role::Prover => ("cpu.pcs_commit_batch", "cpu.pcs_commit_optional"), + Role::Verifier => ("cpu.pcs_receive_batch", "cpu.pcs_receive_optional"), + }; + context + .parse_module::(&format!( + r#" +module @small.commitment_phase attributes {{bolt.phase = "cpu", bolt.role = "{}"}} {{ + "cpu.params"() {{field = @bn254_fr, pcs = @dory, sym_name = "small.params", transcript = @blake2b_transcript}} : () -> () + "cpu.function"() {{source = @small.commitment_phase, sym_name = "small.commitment_phase"}} : () -> () + %0 = "cpu.transcript_init"() {{scheme = @blake2b_transcript, sym_name = "fs0"}} : () -> !cpu.transcript_state + %1 = "cpu.oracle_family_init"() {{count = 2 : i64, family = @small.main_polys, sym_name = "small.main_polys"}} : () -> !cpu.oracle_family + %2 = "cpu.oracle_ref"() {{domain = @small.domain, num_vars = 2 : i64, oracle = @A, sym_name = "small.A"}} : () -> !cpu.oracle_buffer + %3 = "cpu.oracle_family_append"(%1, %2) {{family = @small.main_polys, index = 0 : i64, oracle = @A, sym_name = "small.main_polys.append0"}} : (!cpu.oracle_family, !cpu.oracle_buffer) -> !cpu.oracle_family + %4 = "cpu.oracle_ref"() {{domain = @small.domain, num_vars = 2 : i64, oracle = @B, sym_name = "small.B"}} : () -> !cpu.oracle_buffer + %5 = "cpu.oracle_family_append"(%3, %4) {{family = @small.main_polys, index = 1 : i64, oracle = @B, sym_name = "small.main_polys.append1"}} : (!cpu.oracle_family, !cpu.oracle_buffer) -> !cpu.oracle_family + %6 = "{batch_op}"(%5) {{artifact = @small.main, count = 2 : i64, domain = @small.domain, label = "commitment", num_vars = 2 : i64, oracle_family = @small.main_polys, ordered_oracles = [@A, @B], pcs = @dory, sym_name = "small.main"}} : (!cpu.oracle_family) -> !cpu.commitment_artifact + %7 = "cpu.oracle_ref"() {{domain = @small.domain, num_vars = 2 : i64, oracle = @Advice, sym_name = "small.Advice"}} : () -> !cpu.oracle_buffer + %8 = "{optional_op}"(%7) {{artifact = @small.advice, domain = @small.domain, label = "advice", num_vars = 2 : i64, oracle = @Advice, pcs = @dory, skip_policy = "missing_or_zero", sym_name = "small.advice"}} : (!cpu.oracle_buffer) -> !cpu.commitment_artifact + %9 = "cpu.transcript_absorb"(%0, %6) {{label = "commitment", optional = false, sym_name = "small.absorb_main"}} : (!cpu.transcript_state, !cpu.commitment_artifact) -> !cpu.transcript_state + %10 = "cpu.transcript_absorb"(%9, %8) {{label = "advice", optional = true, sym_name = "small.absorb_advice"}} : (!cpu.transcript_state, !cpu.commitment_artifact) -> !cpu.transcript_state +}} +"#, + role.as_str() + )) + .expect("parse small CPU module") +} + +fn build_commitment_pipeline_cpu<'c>( + context: &'c MeliorContext, + params: &JoltProtocolParams, +) -> (bolt::BoltModule<'c, Cpu>, bolt::BoltModule<'c, Cpu>) { + let protocol = build_commitment_protocol(context, params).expect("build protocol"); + let concrete = lower_piop_and_fiat_shamir(context, &protocol).expect("lower Fiat-Shamir state"); + let prover = project_prover_party(context, &concrete).expect("project prover party"); + let verifier = project_verifier_party(context, &concrete).expect("project verifier party"); + let prover_compute = + lower_commitment_to_compute(context, &prover).expect("lower prover compute"); + let verifier_compute = + lower_commitment_to_compute(context, &verifier).expect("lower verifier compute"); + let prover_cpu = lower_compute_to_cpu(context, &prover_compute).expect("lower prover CPU"); + let verifier_cpu = + lower_compute_to_cpu(context, &verifier_compute).expect("lower verifier CPU"); + (prover_cpu, verifier_cpu) +} + +fn build_stage1_pipeline_cpu<'c>( + context: &'c MeliorContext, + params: &JoltProtocolParams, +) -> (bolt::BoltModule<'c, Cpu>, bolt::BoltModule<'c, Cpu>) { + let protocol = build_stage1_outer_protocol(context, params).expect("build stage1 protocol"); + let concrete = lower_piop_and_fiat_shamir(context, &protocol).expect("lower stage1 protocol"); + let prover = project_prover_party(context, &concrete).expect("project prover party"); + let verifier = project_verifier_party(context, &concrete).expect("project verifier party"); + let prover_compute = lower_stage1_to_compute(context, &prover).expect("lower prover stage1"); + let verifier_compute = + lower_stage1_to_compute(context, &verifier).expect("lower verifier stage1"); + let prover_compute = + resolve_compute_kernels(context, &prover_compute).expect("resolve prover kernels"); + let verifier_compute = + resolve_compute_kernels(context, &verifier_compute).expect("resolve verifier kernels"); + let prover_cpu = lower_compute_to_cpu(context, &prover_compute).expect("lower prover CPU"); + let verifier_cpu = + lower_compute_to_cpu(context, &verifier_compute).expect("lower verifier CPU"); + (prover_cpu, verifier_cpu) +} + +fn build_stage2_pipeline_cpu<'c>( + context: &'c MeliorContext, + params: &JoltProtocolParams, +) -> (bolt::BoltModule<'c, Cpu>, bolt::BoltModule<'c, Cpu>) { + let protocol = build_stage2_protocol(context, params).expect("build stage2 protocol"); + let concrete = lower_piop_and_fiat_shamir(context, &protocol).expect("lower stage2 protocol"); + let prover = project_prover_party(context, &concrete).expect("project prover party"); + let verifier = project_verifier_party(context, &concrete).expect("project verifier party"); + let prover_compute = lower_stage2_to_compute(context, &prover).expect("lower prover stage2"); + let verifier_compute = + lower_stage2_to_compute(context, &verifier).expect("lower verifier stage2"); + let prover_compute = + resolve_compute_kernels(context, &prover_compute).expect("resolve prover kernels"); + let verifier_compute = + resolve_compute_kernels(context, &verifier_compute).expect("resolve verifier kernels"); + let prover_cpu = lower_compute_to_cpu(context, &prover_compute).expect("lower prover CPU"); + let verifier_cpu = + lower_compute_to_cpu(context, &verifier_compute).expect("lower verifier CPU"); + (prover_cpu, verifier_cpu) +} + +fn build_stage3_pipeline_cpu<'c>( + context: &'c MeliorContext, + params: &JoltProtocolParams, +) -> (bolt::BoltModule<'c, Cpu>, bolt::BoltModule<'c, Cpu>) { + let protocol = build_stage3_protocol(context, params).expect("build stage3 protocol"); + let concrete = lower_piop_and_fiat_shamir(context, &protocol).expect("lower stage3 protocol"); + let prover = project_prover_party(context, &concrete).expect("project prover party"); + let verifier = project_verifier_party(context, &concrete).expect("project verifier party"); + let prover_compute = lower_stage3_to_compute(context, &prover).expect("lower prover stage3"); + let verifier_compute = + lower_stage3_to_compute(context, &verifier).expect("lower verifier stage3"); + let prover_compute = + resolve_compute_kernels(context, &prover_compute).expect("resolve prover kernels"); + let verifier_compute = + resolve_compute_kernels(context, &verifier_compute).expect("resolve verifier kernels"); + let prover_cpu = lower_compute_to_cpu(context, &prover_compute).expect("lower prover CPU"); + let verifier_cpu = + lower_compute_to_cpu(context, &verifier_compute).expect("lower verifier CPU"); + (prover_cpu, verifier_cpu) +} + +fn build_stage4_pipeline_cpu<'c>( + context: &'c MeliorContext, + params: &JoltProtocolParams, +) -> (bolt::BoltModule<'c, Cpu>, bolt::BoltModule<'c, Cpu>) { + let protocol = build_stage4_protocol(context, params).expect("build stage4 protocol"); + let concrete = lower_piop_and_fiat_shamir(context, &protocol).expect("lower stage4 protocol"); + let prover = project_prover_party(context, &concrete).expect("project prover party"); + let verifier = project_verifier_party(context, &concrete).expect("project verifier party"); + let prover_compute = lower_stage4_to_compute(context, &prover).expect("lower prover stage4"); + let verifier_compute = + lower_stage4_to_compute(context, &verifier).expect("lower verifier stage4"); + let prover_compute = + resolve_compute_kernels(context, &prover_compute).expect("resolve prover kernels"); + let verifier_compute = + resolve_compute_kernels(context, &verifier_compute).expect("resolve verifier kernels"); + let prover_cpu = lower_compute_to_cpu(context, &prover_compute).expect("lower prover CPU"); + let verifier_cpu = + lower_compute_to_cpu(context, &verifier_compute).expect("lower verifier CPU"); + (prover_cpu, verifier_cpu) +} + +fn build_stage5_pipeline_cpu<'c>( + context: &'c MeliorContext, + params: &JoltProtocolParams, +) -> (bolt::BoltModule<'c, Cpu>, bolt::BoltModule<'c, Cpu>) { + let protocol = build_stage5_protocol(context, params).expect("build stage5 protocol"); + let concrete = lower_piop_and_fiat_shamir(context, &protocol).expect("lower stage5 protocol"); + let prover = project_prover_party(context, &concrete).expect("project prover party"); + let verifier = project_verifier_party(context, &concrete).expect("project verifier party"); + let prover_compute = lower_stage5_to_compute(context, &prover).expect("lower prover stage5"); + let verifier_compute = + lower_stage5_to_compute(context, &verifier).expect("lower verifier stage5"); + let prover_compute = + resolve_compute_kernels(context, &prover_compute).expect("resolve prover kernels"); + let verifier_compute = + resolve_compute_kernels(context, &verifier_compute).expect("resolve verifier kernels"); + let prover_cpu = lower_compute_to_cpu(context, &prover_compute).expect("lower prover CPU"); + let verifier_cpu = + lower_compute_to_cpu(context, &verifier_compute).expect("lower verifier CPU"); + (prover_cpu, verifier_cpu) +} + +fn build_stage6_pipeline_cpu<'c>( + context: &'c MeliorContext, + params: &JoltProtocolParams, +) -> (bolt::BoltModule<'c, Cpu>, bolt::BoltModule<'c, Cpu>) { + let protocol = build_stage6_protocol(context, params).expect("build stage6 protocol"); + let concrete = lower_piop_and_fiat_shamir(context, &protocol).expect("lower stage6 protocol"); + let prover = project_prover_party(context, &concrete).expect("project prover party"); + let verifier = project_verifier_party(context, &concrete).expect("project verifier party"); + let prover_compute = lower_stage6_to_compute(context, &prover).expect("lower prover stage6"); + let verifier_compute = + lower_stage6_to_compute(context, &verifier).expect("lower verifier stage6"); + let prover_compute = + resolve_compute_kernels(context, &prover_compute).expect("resolve prover kernels"); + let verifier_compute = + resolve_compute_kernels(context, &verifier_compute).expect("resolve verifier kernels"); + let prover_cpu = lower_compute_to_cpu(context, &prover_compute).expect("lower prover CPU"); + let verifier_cpu = + lower_compute_to_cpu(context, &verifier_compute).expect("lower verifier CPU"); + (prover_cpu, verifier_cpu) +} + +fn build_stage7_pipeline_cpu<'c>( + context: &'c MeliorContext, + params: &JoltProtocolParams, +) -> (bolt::BoltModule<'c, Cpu>, bolt::BoltModule<'c, Cpu>) { + let protocol = build_stage7_protocol(context, params).expect("build stage7 protocol"); + let concrete = lower_piop_and_fiat_shamir(context, &protocol).expect("lower stage7 protocol"); + let prover = project_prover_party(context, &concrete).expect("project prover party"); + let verifier = project_verifier_party(context, &concrete).expect("project verifier party"); + let prover_compute = lower_stage7_to_compute(context, &prover).expect("lower prover stage7"); + let verifier_compute = + lower_stage7_to_compute(context, &verifier).expect("lower verifier stage7"); + let prover_compute = + resolve_compute_kernels(context, &prover_compute).expect("resolve prover kernels"); + let verifier_compute = + resolve_compute_kernels(context, &verifier_compute).expect("resolve verifier kernels"); + let prover_cpu = lower_compute_to_cpu(context, &prover_compute).expect("lower prover CPU"); + let verifier_cpu = + lower_compute_to_cpu(context, &verifier_compute).expect("lower verifier CPU"); + (prover_cpu, verifier_cpu) +} + +fn build_stage8_pipeline_cpu<'c>( + context: &'c MeliorContext, + params: &JoltProtocolParams, +) -> (bolt::BoltModule<'c, Cpu>, bolt::BoltModule<'c, Cpu>) { + let protocol = build_stage8_protocol(context, params).expect("build stage8 protocol"); + let concrete = lower_piop_and_fiat_shamir(context, &protocol).expect("lower stage8 protocol"); + let prover = project_prover_party(context, &concrete).expect("project prover party"); + let verifier = project_verifier_party(context, &concrete).expect("project verifier party"); + let prover_compute = lower_stage8_to_compute(context, &prover).expect("lower prover stage8"); + let verifier_compute = + lower_stage8_to_compute(context, &verifier).expect("lower verifier stage8"); + let prover_compute = + resolve_compute_kernels(context, &prover_compute).expect("resolve prover kernels"); + let verifier_compute = + resolve_compute_kernels(context, &verifier_compute).expect("resolve verifier kernels"); + let prover_cpu = lower_compute_to_cpu(context, &prover_compute).expect("lower prover CPU"); + let verifier_cpu = + lower_compute_to_cpu(context, &verifier_compute).expect("lower verifier CPU"); + (prover_cpu, verifier_cpu) +} + +fn non_jolt_artifact_config() -> ProtocolArtifactConfig { + ProtocolArtifactConfig { + protocol_name: "Acme".to_owned(), + type_prefix: "Acme".to_owned(), + transcript_label: "acme transcript".to_owned(), + repository: None, + prover_crate_name: "acme-prover".to_owned(), + verifier_crate_name: "acme-verifier".to_owned(), + crates_io_patches: Vec::new(), + standalone_dependency_overrides: vec![ProtocolStandaloneDependency::new( + "serde", + "serde = { version = \"1\", default-features = false }", + )], + common_dependencies: vec!["serde".to_owned()], + prover_dependencies: Vec::new(), + verifier_dependencies: Vec::new(), + instrumentation_prefix: None, + prover_forbidden_imports: vec!["forbidden_prover".to_owned()], + verifier_forbidden_imports: vec!["forbidden_verifier".to_owned()], + kernel_crate: None, + field_type: RustTypeRef::new("std::primitive::u64"), + default_transcript_type: RustTypeRef::new("crate::stages::alpha::DefaultTranscript"), + transcript_trait: RustTypeRef::new("crate::stages::alpha::Transcript"), + commitment_type: RustTypeRef::new("crate::stages::shared::Commitment"), + prover_setup_type: RustTypeRef::new("crate::stages::alpha::ProverSetup"), + role_api_extension: None, + verifier_runtime_modules: vec![ProtocolRuntimeModule { + module_name: "shared".to_owned(), + file: GeneratedFile { + path: "src/stages/shared.rs".to_owned(), + source: non_jolt_verifier_common_source(), + }, + }], + verifier_named_eval_type: RustTypeRef::new("crate::stages::shared::StageNamedEval"), + verifier_sumcheck_output_type: RustTypeRef::new( + "crate::stages::shared::StageSumcheckOutput", + ), + verifier_stage_proof_type: RustTypeRef::new("crate::stages::shared::StageProof"), + } +} + +fn non_jolt_alpha_prover_source() -> RustSourceFile { + RustSourceFile { + filename: "prove_alpha.rs".to_owned(), + source: r" +pub struct DefaultTranscript(core::marker::PhantomData); + +pub trait Transcript { + type Challenge; +} + +pub struct ProverSetup; + +#[derive(Clone, Debug)] +pub struct AlphaExecutionArtifacts { + pub sumchecks: Vec>, +} + +#[derive(Clone, Debug)] +pub struct AlphaSumcheckOutput { + pub driver: &'static str, + pub point: Vec, + pub evals: Vec>, + pub proof: (), +} + +#[derive(Clone, Debug)] +pub struct AlphaNamedEval { + pub name: &'static str, + pub oracle: &'static str, + pub value: F, +} + +#[derive(Debug)] +pub struct AlphaKernelError; + +pub trait AlphaKernelExecutor {} + +pub fn execute_alpha( + _executor: &mut E, + _transcript: &mut T, +) -> Result, AlphaKernelError> +where + E: AlphaKernelExecutor, +{ + Ok(AlphaExecutionArtifacts { + sumchecks: Vec::new(), + }) +} +" + .trim_start() + .to_owned(), + } +} + +fn non_jolt_alpha_verifier_source() -> RustSourceFile { + RustSourceFile { + filename: "verify_alpha.rs".to_owned(), + source: r" +pub struct DefaultTranscript(core::marker::PhantomData); + +pub trait Transcript { + type Challenge; +} + +pub type AlphaNamedEval = super::shared::StageNamedEval; +pub type AlphaSumcheckOutput = super::shared::StageSumcheckOutput; +pub type AlphaProof = super::shared::StageProof; + +#[derive(Clone, Debug)] +pub struct AlphaExecutionArtifacts { + pub sumchecks: Vec>, +} + +#[derive(Debug)] +pub enum VerifyAlphaError {} + +pub fn verify_alpha( + _proof: &AlphaProof, + _transcript: &mut T, +) -> Result, VerifyAlphaError> { + Ok(AlphaExecutionArtifacts { + sumchecks: Vec::new(), + }) +} +" + .trim_start() + .to_owned(), + } +} + +fn non_jolt_verifier_common_source() -> String { + r" +#[derive(Clone, Debug)] +pub struct Commitment; + +#[derive(Clone, Debug)] +pub struct StageNamedEval { + pub name: &'static str, + pub oracle: &'static str, + pub value: F, +} + +#[derive(Clone, Debug)] +pub struct StageSumcheckOutput { + pub driver: &'static str, + pub point: Vec, + pub evals: Vec>, + pub proof: (), +} + +#[derive(Clone, Debug)] +pub struct StageProof { + pub sumchecks: Vec>, +} +" + .trim_start() + .to_owned() +} + +fn jolt_protocol_chain_commitment_stage1_fixture( + context: &MeliorContext, + params: &JoltProtocolParams, +) -> String { + let (commitment_prover_cpu, commitment_verifier_cpu) = + build_commitment_pipeline_cpu(context, params); + let (stage1_prover_cpu, stage1_verifier_cpu) = build_stage1_pipeline_cpu(context, params); + let commitment_prover = + commitment_cpu_program(&commitment_prover_cpu).expect("extract commitment prover program"); + let commitment_verifier = commitment_cpu_program(&commitment_verifier_cpu) + .expect("extract commitment verifier program"); + let stage1_prover = stage1_cpu_program(&stage1_prover_cpu).expect("extract stage1 prover"); + let stage1_verifier = + stage1_cpu_program(&stage1_verifier_cpu).expect("extract stage1 verifier"); + let commitment_prover_source = + emit_commitment_rust(&commitment_prover_cpu).expect("emit commitment prover"); + let commitment_verifier_source = + emit_commitment_rust(&commitment_verifier_cpu).expect("emit commitment verifier"); + let stage1_prover_source = emit_stage1_rust(&stage1_prover_cpu).expect("emit stage1 prover"); + let stage1_verifier_source = + emit_stage1_rust(&stage1_verifier_cpu).expect("emit stage1 verifier"); + + let mut text = String::new(); + writeln!(&mut text, "# Jolt protocol chain fixture").unwrap(); + writeln!(&mut text, "params:").unwrap(); + writeln!(&mut text, " log_t: {}", params.log_t).unwrap(); + writeln!(&mut text, " log_k_bytecode: {}", params.log_k_bytecode).unwrap(); + writeln!(&mut text, " log_k_ram: {}", params.log_k_ram).unwrap(); + writeln!(&mut text, " trace_length: {}", params.trace_length).unwrap(); + writeln!(&mut text, "phases:").unwrap(); + writeln!(&mut text, " - name: commitment").unwrap(); + writeln!( + &mut text, + " protocol_fixture: tests/fixtures/commitment_protocol.mlir" + ) + .unwrap(); + writeln!( + &mut text, + " concrete_fixture: tests/fixtures/commitment_concrete.mlir" + ) + .unwrap(); + writeln!( + &mut text, + " prover_cpu_fixture: tests/fixtures/commitment_prover_cpu.mlir" + ) + .unwrap(); + writeln!( + &mut text, + " verifier_cpu_fixture: tests/fixtures/commitment_verifier_cpu.mlir" + ) + .unwrap(); + writeln!( + &mut text, + " prover_rust_fixture: tests/fixtures/{}", + commitment_prover_source.filename + ) + .unwrap(); + writeln!( + &mut text, + " verifier_rust_fixture: tests/fixtures/{}", + commitment_verifier_source.filename + ) + .unwrap(); + writeln!( + &mut text, + " prover_batches: {}", + commitment_prover.batch_plans.len() + ) + .unwrap(); + writeln!( + &mut text, + " verifier_batches: {}", + commitment_verifier.batch_plans.len() + ) + .unwrap(); + writeln!( + &mut text, + " optional_commitments: {}", + commitment_prover.optional_plans.len() + ) + .unwrap(); + writeln!( + &mut text, + " transcript_steps: {}", + commitment_prover.transcript_steps.len() + ) + .unwrap(); + writeln!(&mut text, " - name: stage1_outer").unwrap(); + writeln!(&mut text, " consumes_transcript_from: commitment").unwrap(); + writeln!( + &mut text, + " protocol_fixture: tests/fixtures/stage1_outer_protocol.mlir" + ) + .unwrap(); + writeln!( + &mut text, + " prover_compute_fixture: tests/fixtures/stage1_outer_prover_compute.mlir" + ) + .unwrap(); + writeln!( + &mut text, + " verifier_compute_fixture: tests/fixtures/stage1_outer_verifier_compute.mlir" + ) + .unwrap(); + writeln!( + &mut text, + " prover_kernel_compute_fixture: tests/fixtures/stage1_outer_prover_kernel_compute.mlir" + ) + .unwrap(); + writeln!( + &mut text, + " verifier_kernel_compute_fixture: tests/fixtures/stage1_outer_verifier_kernel_compute.mlir" + ) + .unwrap(); + writeln!( + &mut text, + " prover_cpu_fixture: tests/fixtures/stage1_outer_prover_cpu.mlir" + ) + .unwrap(); + writeln!( + &mut text, + " verifier_cpu_fixture: tests/fixtures/stage1_outer_verifier_cpu.mlir" + ) + .unwrap(); + writeln!( + &mut text, + " prover_rust_fixture: tests/fixtures/{}", + stage1_prover_source.filename + ) + .unwrap(); + writeln!( + &mut text, + " verifier_rust_fixture: tests/fixtures/{}", + stage1_verifier_source.filename + ) + .unwrap(); + writeln!( + &mut text, + " transcript_squeezes: {}", + stage1_prover.transcript_squeezes.len() + ) + .unwrap(); + writeln!( + &mut text, + " prover_sumcheck_drivers: {}", + stage1_prover.drivers.len() + ) + .unwrap(); + writeln!( + &mut text, + " verifier_sumcheck_drivers: {}", + stage1_verifier.drivers.len() + ) + .unwrap(); + writeln!( + &mut text, + " opening_claims: {}", + stage1_prover.opening_claims.len() + ) + .unwrap(); + writeln!( + &mut text, + " opening_batches: {}", + stage1_prover.opening_batches.len() + ) + .unwrap(); + writeln!(&mut text, " drivers:").unwrap(); + for driver in &stage1_prover.drivers { + writeln!( + &mut text, + " - {}: kernel={} rounds={} degree={} proof_slot={}", + driver.symbol, + driver.kernel.as_deref().unwrap_or(""), + driver.num_rounds, + driver.degree, + driver.proof_slot + ) + .unwrap(); + } + writeln!(&mut text, "parity_gates:").unwrap(); + writeln!( + &mut text, + " - pipeline_generated_commitment_prover_verifier_self_parity_runs" + ) + .unwrap(); + writeln!( + &mut text, + " - generated_stage1_real_executor_self_verifies_synthetic_remaining" + ) + .unwrap(); + writeln!( + &mut text, + " - generated_jolt_chain_commitment_then_stage1_self_parity_runs" + ) + .unwrap(); + text +} + +fn opening_claim_equal_protocol(left_oracle: &str, right_oracle: &str, mode: &str) -> String { + let right_oracle_def = if left_oracle == right_oracle { + String::new() + } else { + format!( + r#" "piop.oracle"() {{commit_domain = @trace, domain = @trace, field = @bn254_fr, layout = "virtual", sym_name = "{right_oracle}", visibility = "virtual"}} : () -> () +"# + ) + }; + format!( + r#" +module @opening.claim.equal attributes {{bolt.phase = "protocol"}} {{ + "field.define"() {{modulus_bits = 254 : i64, role = "scalar", sym_name = "bn254_fr"}} : () -> () + "hash.function"() {{algorithm = "blake2b", sym_name = "blake2b"}} : () -> () + "transcript.scheme"() {{hash = @blake2b, sym_name = "blake2b_transcript"}} : () -> () + "pcs.scheme"() {{field = @bn254_fr, sym_name = "dory"}} : () -> () + "poly.domain"() {{field = @bn254_fr, log_size = 16 : i64, sym_name = "trace"}} : () -> () + "protocol.params"() {{field = @bn254_fr, pcs = @dory, sym_name = "params", transcript = @blake2b_transcript}} : () -> () + "protocol.boundary"() {{roles = ["prover", "verifier"], sym_name = "opening.claim.equal"}} : () -> () + "piop.oracle"() {{commit_domain = @trace, domain = @trace, field = @bn254_fr, layout = "virtual", sym_name = "{left_oracle}", visibility = "virtual"}} : () -> () +{right_oracle_def} + %left:3 = "piop.opening_input"() {{claim_kind = "virtual", domain = @trace, oracle = @{left_oracle}, point_arity = 16 : i64, source_claim = @stage2.product_virtual.remainder.opening.{left_oracle}, source_stage = @stage2, sym_name = "stage3.input.stage2_left.{left_oracle}"}} : () -> (!poly.point, !field.scalar, !piop.opening_claim_type) + %right:3 = "piop.opening_input"() {{claim_kind = "virtual", domain = @trace, oracle = @{right_oracle}, point_arity = 16 : i64, source_claim = @stage2.instruction_lookup.claim_reduction.opening.{right_oracle}, source_stage = @stage2, sym_name = "stage3.input.stage2_right.{right_oracle}"}} : () -> (!poly.point, !field.scalar, !piop.opening_claim_type) + "piop.opening_claim_equal"(%left#2, %right#2) {{mode = "{mode}", sym_name = "stage3.instruction_input.left_claim_consistency"}} : (!piop.opening_claim_type, !piop.opening_claim_type) -> () +}} +"# + ) +} + +fn transcript_absorb_bytes_protocol(params: &JoltProtocolParams) -> String { + format!( + r#" +module @transcript.absorb.bytes attributes {{bolt.phase = "protocol"}} {{ + "field.define"() {{modulus_bits = 254 : i64, role = "scalar", sym_name = "bn254_fr"}} : () -> () + "hash.function"() {{algorithm = "blake2b", sym_name = "blake2b"}} : () -> () + "transcript.scheme"() {{hash = @blake2b, sym_name = "blake2b_transcript"}} : () -> () + "pcs.scheme"() {{field = @bn254_fr, sym_name = "dory"}} : () -> () + "protocol.params"() {{{params_attrs}, sym_name = "jolt.params"}} : () -> () + "protocol.boundary"() {{roles = ["prover", "verifier"], sym_name = "transcript.absorb.bytes"}} : () -> () + %0 = "transcript.state"() {{scheme = @blake2b_transcript, sym_name = "fs_after_stage3"}} : () -> !transcript.state_type + %1 = "transcript.absorb_bytes"(%0) {{label = "ram_val_check_gamma", payload = "", sym_name = "stage4.ram_val_check.domain_separator"}} : (!transcript.state_type) -> !transcript.state_type + %2:2 = "transcript.squeeze"(%1) {{count = 1 : i64, kind = "challenge_scalar", label = "ram_val_check_gamma", sym_name = "stage4.ram_val_check.gamma"}} : (!transcript.state_type) -> (!transcript.state_type, !field.scalar) +}} +"#, + params_attrs = jolt_params_attrs_source(params) + ) +} + +fn jolt_params_attrs_source(params: &JoltProtocolParams) -> String { + params + .attrs() + .into_iter() + .map(|(name, value)| format!("{name} = {value}")) + .collect::>() + .join(", ") +} + +fn explicit_sumcheck_protocol() -> &'static str { + r#" +module @explicit.sumcheck attributes {bolt.phase = "protocol"} { + "field.define"() {modulus_bits = 254 : i64, role = "scalar", sym_name = "bn254_fr"} : () -> () + "hash.function"() {algorithm = "blake2b", sym_name = "blake2b"} : () -> () + "transcript.scheme"() {hash = @blake2b, sym_name = "blake2b_transcript"} : () -> () + "pcs.scheme"() {field = @bn254_fr, sym_name = "dory"} : () -> () + "poly.domain"() {field = @bn254_fr, log_size = 16 : i64, sym_name = "trace"} : () -> () + "piop.relation"() {degree = 3 : i64, domain = @trace, kind = "sumcheck", num_rounds = 4 : i64, output_count = 1 : i64, sym_name = "jolt.stage1.outer.remaining"} : () -> () + %0 = "transcript.state"() {scheme = @blake2b_transcript, sym_name = "fs0"} : () -> !transcript.state_type + %1, %alpha = "transcript.squeeze"(%0) {count = 1 : i64, kind = "scalar", label = "sumcheck_claim", sym_name = "stage1.alpha"} : (!transcript.state_type) -> (!transcript.state_type, !field.scalar) + %stage = "piop.stage"() {name = "stage1", order = 1 : i64, roles = ["prover", "verifier"], sym_name = "stage1"} : () -> !piop.stage_type + %claim_value = "field.const"() {field = @bn254_fr, value = 0 : i64, sym_name = "stage1.outer.claim_value"} : () -> !field.scalar + %claim = "piop.sumcheck_claim"(%claim_value) {claim = @stage1.outer.claim, degree = 3 : i64, domain = @trace, num_rounds = 4 : i64, relation = @jolt.stage1.outer.remaining, stage = @stage1, sym_name = "stage1.outer.claim"} : (!field.scalar) -> !piop.sumcheck_claim_type + %batch = "piop.sumcheck_batch"(%stage, %claim) {claim_label = "sumcheck_claim", count = 1 : i64, ordered_claims = [@stage1.outer.claim], policy = "jolt_core_front_loaded", proof_slot = @stage1.sumcheck, round_label = "sumcheck_poly", round_schedule = [2, 1, 1], stage = @stage1, sym_name = "stage1.outer.batch"} : (!piop.stage_type, !piop.sumcheck_claim_type) -> !piop.sumcheck_batch_type + %2, %point, %result, %proof = "piop.sumcheck"(%1, %batch) {claim_label = "sumcheck_claim", degree = 3 : i64, num_rounds = 4 : i64, policy = "jolt_core_front_loaded", proof_slot = @stage1.sumcheck, relation = @jolt.stage1.outer.remaining, round_label = "sumcheck_poly", round_schedule = [2, 1, 1], stage = @stage1, sym_name = "stage1.outer.sumcheck"} : (!transcript.state_type, !piop.sumcheck_batch_type) -> (!transcript.state_type, !poly.point, !piop.sumcheck_result_type, !piop.sumcheck_proof_type) + %eval = "piop.sumcheck_eval"(%result) {index = 0 : i64, name = @stage1.outer.eval, oracle = @RdInc, source = @stage1.outer.sumcheck, sym_name = "stage1.outer.eval"} : (!piop.sumcheck_result_type) -> !field.scalar + %opening = "pcs.opening_claim"(%point, %eval) {domain = @trace, family = @jolt.main_witness_polys, oracle = @RdInc, point_arity = 4 : i64, sym_name = "stage1.outer.opening"} : (!poly.point, !field.scalar) -> !pcs.opening_claim_type + %openings = "pcs.opening_batch"(%opening) {count = 1 : i64, ordered_claims = [@stage1.outer.opening], policy = "jolt_core_order", proof_slot = @stage1.openings, sym_name = "stage1.opening_batch"} : (!pcs.opening_claim_type) -> !pcs.opening_batch_type + %3, %opening_proof = "pcs.batch_open"(%2, %openings) {pcs = @dory, proof_slot = @stage1.openings, sym_name = "stage1.open", transcript_label = "opening_proof"} : (!transcript.state_type, !pcs.opening_batch_type) -> (!transcript.state_type, !pcs.opening_proof_type) +} +"# +} + +fn explicit_sumcheck_compute() -> &'static str { + r#" +module @explicit.sumcheck attributes {bolt.phase = "compute", bolt.role = "prover"} { + "compute.params"() {field = @bn254_fr, pcs = @dory, sym_name = "params", transcript = @blake2b_transcript} : () -> () + "compute.function"() {source = @explicit.sumcheck, sym_name = "explicit.sumcheck"} : () -> () + "compute.relation"() {degree = 3 : i64, domain = @trace, kind = "sumcheck", num_rounds = 4 : i64, output_count = 1 : i64, sym_name = "jolt.stage1.outer.remaining"} : () -> () + %0 = "compute.transcript_init"() {scheme = @blake2b_transcript, sym_name = "fs0"} : () -> !compute.transcript_state + %1, %alpha = "compute.transcript_squeeze"(%0) {count = 1 : i64, kind = "scalar", label = "sumcheck_claim", sym_name = "stage1.alpha"} : (!compute.transcript_state) -> (!compute.transcript_state, !compute.field_value) + %claim_value = "compute.field_const"() {field = @bn254_fr, value = 0 : i64, sym_name = "stage1.outer.claim_value"} : () -> !compute.field_value + %claim = "compute.sumcheck_claim"(%claim_value) {claim = @stage1.outer.claim, degree = 3 : i64, domain = @trace, num_rounds = 4 : i64, relation = @jolt.stage1.outer.remaining, stage = @stage1, sym_name = "stage1.outer.claim"} : (!compute.field_value) -> !compute.sumcheck_claim_type + %batch = "compute.sumcheck_batch"(%claim) {claim_label = "sumcheck_claim", count = 1 : i64, ordered_claims = [@stage1.outer.claim], policy = "jolt_core_front_loaded", proof_slot = @stage1.sumcheck, round_label = "sumcheck_poly", round_schedule = [2, 1, 1], stage = @stage1, sym_name = "stage1.outer.batch"} : (!compute.sumcheck_claim_type) -> !compute.sumcheck_batch_type + %2, %point, %result, %proof = "compute.sumcheck_driver"(%1, %batch) {claim_label = "sumcheck_claim", degree = 3 : i64, num_rounds = 4 : i64, policy = "jolt_core_front_loaded", proof_slot = @stage1.sumcheck, relation = @jolt.stage1.outer.remaining, round_label = "sumcheck_poly", round_schedule = [2, 1, 1], stage = @stage1, sym_name = "stage1.outer.sumcheck"} : (!compute.transcript_state, !compute.sumcheck_batch_type) -> (!compute.transcript_state, !compute.point, !compute.sumcheck_result_type, !compute.sumcheck_proof_type) + %eval = "compute.sumcheck_eval"(%result) {index = 0 : i64, name = @stage1.outer.eval, oracle = @RdInc, source = @stage1.outer.sumcheck, sym_name = "stage1.outer.eval"} : (!compute.sumcheck_result_type) -> !compute.field_value + %opening = "compute.pcs_opening_claim"(%point, %eval) {domain = @trace, family = @jolt.main_witness_polys, oracle = @RdInc, point_arity = 4 : i64, sym_name = "stage1.outer.opening"} : (!compute.point, !compute.field_value) -> !compute.opening_claim_type + %openings = "compute.pcs_opening_batch"(%opening) {count = 1 : i64, ordered_claims = [@stage1.outer.opening], policy = "jolt_core_order", proof_slot = @stage1.openings, sym_name = "stage1.opening_batch"} : (!compute.opening_claim_type) -> !compute.opening_batch_type + %3, %opening_proof = "compute.pcs_batch_open"(%2, %openings) {pcs = @dory, proof_slot = @stage1.openings, sym_name = "stage1.open", transcript_label = "opening_proof"} : (!compute.transcript_state, !compute.opening_batch_type) -> (!compute.transcript_state, !compute.opening_proof_type) +} +"# +} + +fn assert_or_update_fixture(path: &str, actual: &str) { + let path = Path::new(env!("CARGO_MANIFEST_DIR")).join(path); + if std::env::var_os("JOLT_UPDATE_GOLDENS").is_some() { + if let Some(parent) = path.parent() { + std::fs::create_dir_all(parent).expect("create golden fixture directory"); + } + std::fs::write(&path, actual).expect("write golden fixture"); + return; + } + if !path.exists() { + return; + } + let expected = std::fs::read_to_string(&path).expect("read golden fixture"); + assert_eq!(expected, actual); +} + +fn assert_rust_source_compiles(_filename: &str, source: &str) { + let dir = new_temp_dir("bolt_emit"); + let workspace_root = workspace_root(); + std::fs::write( + dir.join("Cargo.toml"), + generated_crate_manifest(&workspace_root), + ) + .expect("write generated cargo manifest"); + std::fs::create_dir_all(dir.join("src")).expect("create generated src dir"); + if source.contains("super::common") { + let common = std::fs::read_to_string( + workspace_root.join("crates/jolt-verifier/src/stages/common.rs"), + ) + .expect("read generated verifier common stage source"); + std::fs::write(dir.join("src/common.rs"), common).expect("write generated common source"); + std::fs::write(dir.join("src/generated.rs"), source).expect("write generated source"); + std::fs::write( + dir.join("src/lib.rs"), + "pub mod common;\n#[rustfmt::skip]\npub mod generated;\n", + ) + .expect("write generated lib wrapper"); + } else { + std::fs::write(dir.join("src/lib.rs"), source).expect("write generated source"); + } + let cargo = std::env::var("CARGO").unwrap_or_else(|_| "cargo".to_owned()); + let output = Command::new(cargo) + .arg("check") + .arg("--manifest-path") + .arg(dir.join("Cargo.toml")) + .arg("-q") + .env("CARGO_TARGET_DIR", dir.join("target")) + .output() + .expect("run cargo check"); + assert!( + output.status.success(), + "generated rust did not compile\nstdout:\n{}\nstderr:\n{}", + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&output.stderr) + ); + let _ = std::fs::remove_dir_all(dir); +} + +fn assert_generated_role_crate_compiles(generated: &JoltGeneratedCrate) { + let dir = new_temp_dir(&generated.crate_name); + for file in &generated.files { + let path = dir.join(&file.path); + if let Some(parent) = path.parent() { + std::fs::create_dir_all(parent).expect("create generated crate dir"); + } + std::fs::write(path, &file.source).expect("write generated crate file"); + } + let cargo = std::env::var("CARGO").unwrap_or_else(|_| "cargo".to_owned()); + let output = Command::new(cargo) + .arg("check") + .arg("--manifest-path") + .arg(dir.join("Cargo.toml")) + .arg("-q") + .env("CARGO_TARGET_DIR", dir.join("target")) + .output() + .expect("run generated role crate check"); + assert!( + output.status.success(), + "generated role crate `{}` did not compile\nstdout:\n{}\nstderr:\n{}", + generated.crate_name, + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&output.stderr) + ); + let _ = std::fs::remove_dir_all(dir); +} + +fn assert_generated_crate_manifest_compiles(output_root: &Path, crate_name: &str) { + let cargo = std::env::var("CARGO").unwrap_or_else(|_| "cargo".to_owned()); + let output = Command::new(cargo) + .arg("check") + .arg("--manifest-path") + .arg(output_root.join(crate_name).join("Cargo.toml")) + .arg("-q") + .env( + "CARGO_TARGET_DIR", + output_root.join("target").join(crate_name), + ) + .output() + .expect("run generated crate check"); + assert!( + output.status.success(), + "generated crate `{crate_name}` did not compile\nstdout:\n{}\nstderr:\n{}", + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&output.stderr) + ); +} + +fn redirect_generated_prover_to_generated_verifier(output_root: &Path, dependency_root: &Path) { + let manifest_path = output_root.join("jolt-prover").join("Cargo.toml"); + let workspace_verifier = format!( + "jolt-verifier = {{ path = \"{}/jolt-verifier\" }}", + dependency_root.display() + ); + let generated_verifier = format!( + "jolt-verifier = {{ path = \"{}\" }}", + output_root.join("jolt-verifier").display() + ); + let manifest = std::fs::read_to_string(&manifest_path).expect("read generated prover manifest"); + let manifest = manifest.replace(&workspace_verifier, &generated_verifier); + std::fs::write(&manifest_path, manifest).expect("rewrite generated prover manifest"); +} + +fn assert_checked_in_generated_role_crate_sources_match(generated_crates: &[JoltGeneratedCrate]) { + let crates_root = workspace_root().join("crates"); + for generated in generated_crates { + for file in &generated.files { + let checked_in_path = crates_root.join(&generated.crate_name).join(&file.path); + let checked_in = + std::fs::read_to_string(&checked_in_path).expect("read checked-in generated file"); + assert_eq!( + checked_in, + file.source, + "checked-in generated crate file `{}` is stale; regenerate with the Bolt artifact writer", + checked_in_path.display() + ); + if generated.crate_name == "jolt-verifier" { + assert!( + !checked_in.contains("use jolt_prover") + && !checked_in.contains("jolt_prover::") + && !checked_in.contains("use jolt_kernels") + && !checked_in.contains("jolt_kernels::") + && !checked_in.contains("use jolt_core") + && !checked_in.contains("jolt_core::"), + "generated verifier file `{}` imports non-audit role/runtime code", + checked_in_path.display() + ); + } + if generated.crate_name == "jolt-prover" { + assert!( + !checked_in.contains("jolt_verifier::stages"), + "generated prover file `{}` imports verifier stage internals instead of only verifier-owned proof types", + checked_in_path.display() + ); + } + } + } +} + +fn assert_generated_commitment_self_parity_runs( + prover_source: &RustSourceFile, + verifier_source: &RustSourceFile, + main_source: &str, +) { + let dir = new_temp_dir("bolt_self_parity"); + let workspace_root = workspace_root(); + std::fs::write( + dir.join("Cargo.toml"), + generated_crate_manifest(&workspace_root), + ) + .expect("write generated cargo manifest"); + let src_dir = dir.join("src"); + std::fs::create_dir_all(&src_dir).expect("create generated src dir"); + std::fs::write(src_dir.join(&prover_source.filename), &prover_source.source) + .expect("write generated prover source"); + std::fs::write( + src_dir.join(&verifier_source.filename), + &verifier_source.source, + ) + .expect("write generated verifier source"); + std::fs::write(src_dir.join("main.rs"), main_source) + .expect("write generated self-parity harness"); + + let cargo = std::env::var("CARGO").unwrap_or_else(|_| "cargo".to_owned()); + let output = Command::new(cargo) + .arg("run") + .arg("--manifest-path") + .arg(dir.join("Cargo.toml")) + .arg("-q") + .env("CARGO_TARGET_DIR", dir.join("target")) + .output() + .expect("run generated self-parity crate"); + assert!( + output.status.success(), + "generated commitment self-parity failed\nstdout:\n{}\nstderr:\n{}", + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&output.stderr) + ); + let _ = std::fs::remove_dir_all(dir); +} + +fn assert_generated_stage1_self_parity_runs( + prover_source: &RustSourceFile, + verifier_source: &RustSourceFile, + main_source: &str, +) { + let dir = new_temp_dir("bolt_stage1_self_parity"); + let workspace_root = workspace_root(); + std::fs::write( + dir.join("Cargo.toml"), + generated_crate_manifest(&workspace_root), + ) + .expect("write generated cargo manifest"); + let src_dir = dir.join("src"); + std::fs::create_dir_all(&src_dir).expect("create generated src dir"); + let main_source = if verifier_source.source.contains("super::common") { + write_verifier_common_module(&src_dir, &workspace_root); + format!("mod common;\n{main_source}") + } else { + main_source.to_owned() + }; + std::fs::write(src_dir.join(&prover_source.filename), &prover_source.source) + .expect("write generated stage1 prover source"); + std::fs::write( + src_dir.join(&verifier_source.filename), + &verifier_source.source, + ) + .expect("write generated stage1 verifier source"); + std::fs::write(src_dir.join("main.rs"), main_source) + .expect("write generated stage1 self-parity harness"); + + let cargo = std::env::var("CARGO").unwrap_or_else(|_| "cargo".to_owned()); + let output = Command::new(cargo) + .arg("run") + .arg("--manifest-path") + .arg(dir.join("Cargo.toml")) + .arg("-q") + .env("CARGO_TARGET_DIR", dir.join("target")) + .output() + .expect("run generated stage1 self-parity crate"); + assert!( + output.status.success(), + "generated stage1 self-parity failed\nstdout:\n{}\nstderr:\n{}", + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&output.stderr) + ); + let _ = std::fs::remove_dir_all(dir); +} + +fn assert_generated_jolt_chain_self_parity_runs(files: &[&RustSourceFile], main_source: &str) { + let dir = new_temp_dir("bolt_chain_self_parity"); + let workspace_root = workspace_root(); + std::fs::write( + dir.join("Cargo.toml"), + generated_crate_manifest(&workspace_root), + ) + .expect("write generated cargo manifest"); + let src_dir = dir.join("src"); + std::fs::create_dir_all(&src_dir).expect("create generated src dir"); + let main_source = if files + .iter() + .any(|file| file.source.contains("super::common")) + { + write_verifier_common_module(&src_dir, &workspace_root); + format!("mod common;\n{main_source}") + } else { + main_source.to_owned() + }; + for file in files { + std::fs::write(src_dir.join(&file.filename), &file.source) + .expect("write generated chain source"); + } + std::fs::write(src_dir.join("main.rs"), main_source) + .expect("write generated chain self-parity harness"); + + let cargo = std::env::var("CARGO").unwrap_or_else(|_| "cargo".to_owned()); + let output = Command::new(cargo) + .arg("run") + .arg("--manifest-path") + .arg(dir.join("Cargo.toml")) + .arg("-q") + .env("CARGO_TARGET_DIR", dir.join("target")) + .output() + .expect("run generated chain self-parity crate"); + assert!( + output.status.success(), + "generated commitment+stage1 self-parity failed\nstdout:\n{}\nstderr:\n{}", + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&output.stderr) + ); + let _ = std::fs::remove_dir_all(dir); +} + +fn write_verifier_common_module(src_dir: &Path, workspace_root: &Path) { + let common = + std::fs::read_to_string(workspace_root.join("crates/jolt-verifier/src/stages/common.rs")) + .expect("read generated verifier common stage source"); + std::fs::write(src_dir.join("common.rs"), common).expect("write generated common source"); +} + +fn workspace_root() -> std::path::PathBuf { + Path::new(env!("CARGO_MANIFEST_DIR")) + .parent() + .and_then(Path::parent) + .expect("workspace root") + .to_path_buf() +} + +fn generated_crate_manifest(workspace_root: &Path) -> String { + format!( + r#"[package] +name = "generated-commitment-phase-check" +version = "0.0.0" +edition = "2021" + +[patch.crates-io] +ark-bn254 = {{ 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-ff = {{ git = "https://github.com/a16z/arkworks-algebra", branch = "dev/twist-shout" }} +ark-serialize = {{ git = "https://github.com/a16z/arkworks-algebra", branch = "dev/twist-shout" }} + +[dependencies] +jolt-dory = {{ path = "{}" }} +jolt-field = {{ path = "{}" }} +jolt-kernels = {{ path = "{}" }} +jolt-lookup-tables = {{ path = "{}" }} +jolt-openings = {{ path = "{}" }} +jolt-poly = {{ path = "{}" }} +jolt-r1cs = {{ path = "{}" }} +jolt-sumcheck = {{ path = "{}" }} +jolt-transcript = {{ path = "{}" }} +jolt-witness = {{ path = "{}" }} +rayon = "1.12.0" +serde = {{ version = "1.0", default-features = false, features = ["derive"] }} +tracing = {{ version = "0.1.37", default-features = false, features = ["attributes"] }} +"#, + workspace_root.join("crates/jolt-dory").display(), + workspace_root.join("crates/jolt-field").display(), + workspace_root.join("crates/jolt-kernels").display(), + workspace_root.join("crates/jolt-lookup-tables").display(), + workspace_root.join("crates/jolt-openings").display(), + workspace_root.join("crates/jolt-poly").display(), + workspace_root.join("crates/jolt-r1cs").display(), + workspace_root.join("crates/jolt-sumcheck").display(), + workspace_root.join("crates/jolt-transcript").display(), + workspace_root.join("crates/jolt-witness").display(), + ) +} + +fn new_temp_dir(prefix: &str) -> std::path::PathBuf { + let nonce = SystemTime::now() + .duration_since(UNIX_EPOCH) + .expect("system clock after unix epoch") + .as_nanos(); + let dir = std::env::temp_dir().join(format!("{}_{}_{}", prefix, std::process::id(), nonce)); + std::fs::create_dir_all(&dir).expect("create generated crate temp dir"); + dir +} + +fn generated_small_self_parity_main() -> String { + let mut source = r#"mod prove_commitment_phase; +mod verify_commitment_phase; + +use std::borrow::Cow; + +use jolt_dory::DoryScheme; +use jolt_field::{Field, Fr}; +use jolt_transcript::{Blake2bTranscript, Transcript}; + +struct Inputs; + +impl prove_commitment_phase::CommitmentInputProvider for Inputs { + fn materialize(&mut self, oracle: &'static str) -> Option> { + match oracle { + "A" => Some(Cow::Owned(vec![Fr::from_u64(1), Fr::from_u64(2)])), + "B" => Some(Cow::Owned(vec![ + Fr::from_u64(3), + Fr::from_u64(4), + Fr::from_u64(5), + Fr::from_u64(6), + ])), + "Advice" => Some(Cow::Owned(vec![Fr::from_u64(0), Fr::from_u64(0)])), + _ => None, + } + } +} + +"# + .to_owned(); + source.push_str(tracing_transcript_support()); + source.push_str( + r#" +fn main() { + let prover_setup = + DoryScheme::setup_prover(prove_commitment_phase::COMMITMENT_BATCH_PLANS[0].num_vars); + let mut inputs = Inputs; + let mut prover_transcript = TracingTranscript::new(b"self"); + let prover = prove_commitment_phase::prove_commitment_phase( + &mut inputs, + &prover_setup, + &mut prover_transcript, + ) + .expect("prover commitment phase"); + + assert_eq!(prover.commitments.len(), 3); + assert!(prover.commitments[2].is_none()); + + let mut verifier_transcript = TracingTranscript::new(b"self"); + let verifier = verify_commitment_phase::verify_commitment_phase( + &prover.commitments, + &mut verifier_transcript, + ) + .expect("verifier commitment phase"); + + assert_eq!(prover.commitments, verifier.commitments); + assert_eq!(prover.records.len(), verifier.records.len()); + assert_transcript_step_parity(&prover_transcript, &verifier_transcript); +} +"#, + ); + source +} + +fn generated_pipeline_self_parity_main() -> String { + let mut source = "mod prove_commitment_phase; +mod verify_commitment_phase; + +use jolt_dory::DoryScheme; +use jolt_field::{Field, Fr}; +use jolt_transcript::{Blake2bTranscript, Transcript}; + +" + .to_owned(); + source.push_str(tracing_transcript_support()); + source.push_str( + r#" +fn main() { + let prover_setup = + DoryScheme::setup_prover(prove_commitment_phase::COMMITMENT_BATCH_PLANS[0].num_vars); + let inputs = prove_commitment_phase::CommitmentOracleInputs { + rd_inc: &[1], + ram_inc: &[2], + instruction_keys: &[Some(0x1234_5678_9abc_def0_0123_4567_89ab_cdefu128)], + ram_addresses: &[], + bytecode_indices: &[], + untrusted_advice: None, + trusted_advice: None, + }; + let mut oracles = prove_commitment_phase::build_commitment_oracles(&inputs) + .expect("build commitment oracles"); + let mut prover_transcript = TracingTranscript::new(b"pipeline"); + let prover = prove_commitment_phase::prove_commitment_phase( + &mut oracles, + &prover_setup, + &mut prover_transcript, + ) + .expect("prover commitment phase"); + + let expected_slots = prove_commitment_phase::COMMITMENT_BATCH_PLANS + .iter() + .map(|plan| plan.oracles.len()) + .sum::() + + prove_commitment_phase::OPTIONAL_COMMITMENT_PLANS.len(); + assert_eq!(prover.commitments.len(), expected_slots); + + let mut verifier_transcript = TracingTranscript::new(b"pipeline"); + let verifier = verify_commitment_phase::verify_commitment_phase( + &prover.commitments, + &mut verifier_transcript, + ) + .expect("verifier commitment phase"); + + assert_eq!(prover.commitments, verifier.commitments); + assert_eq!(prover.records.len(), verifier.records.len()); + for (prover_record, verifier_record) in prover.records.iter().zip(&verifier.records) { + assert_eq!(prover_record.artifact, verifier_record.artifact); + assert_eq!(prover_record.oracle, verifier_record.oracle); + assert_eq!(prover_record.label, verifier_record.label); + assert_eq!(prover_record.num_vars, verifier_record.num_vars); + } + assert_transcript_step_parity(&prover_transcript, &verifier_transcript); +} +"#, + ); + source +} + +fn generated_stage1_shape_self_parity_main() -> String { + let mut source = r"mod prove_stage1_outer; +mod verify_stage1_outer; + +use jolt_field::{Field, Fr}; +use jolt_kernels::stage1::Stage1ShapeKernelExecutor; +use jolt_transcript::{Blake2bTranscript, Transcript}; + +" + .to_owned(); + source.push_str(tracing_transcript_support()); + source.push_str(&stage1_verifier_proof_adapter(true)); + source.push_str( + r#" +fn main() { + let mut prover_executor = Stage1ShapeKernelExecutor; + let mut prover_transcript = TracingTranscript::new(b"stage1"); + let prover = prove_stage1_outer::prove_stage1_outer( + &mut prover_executor, + &mut prover_transcript, + ) + .expect("generated prover runs shape kernels"); + + let proof = verifier_proof_from_prover_artifacts(&prover); + let mut verifier_transcript = TracingTranscript::new(b"stage1"); + let verifier = verify_stage1_outer::verify_stage1_outer( + &proof, + &mut verifier_transcript, + ) + .expect("generated verifier accepts shape proof"); + + assert_eq!( + prover.sumchecks.len(), + prove_stage1_outer::STAGE1_SUMCHECK_DRIVERS.len() + ); + assert_eq!(prover.sumchecks.len(), verifier.sumchecks.len()); + assert_eq!(prover.opening_batches.len(), verifier.opening_batches.len()); + for (prover_batch, verifier_batch) in prover.opening_batches.iter().zip(&verifier.opening_batches) { + assert_eq!(prover_batch.symbol, verifier_batch.symbol); + assert_eq!(prover_batch.count, verifier_batch.count); + } + for (prover_sumcheck, verifier_sumcheck) in prover.sumchecks.iter().zip(&verifier.sumchecks) { + assert_eq!(prover_sumcheck.driver, verifier_sumcheck.driver); + assert_eq!(prover_sumcheck.evals.len(), verifier_sumcheck.evals.len()); + for (prover_eval, verifier_eval) in prover_sumcheck.evals.iter().zip(&verifier_sumcheck.evals) { + assert_eq!(prover_eval.name, verifier_eval.name); + assert_eq!(prover_eval.oracle, verifier_eval.oracle); + assert_eq!(prover_eval.value, verifier_eval.value); + } + assert_eq!( + prover_sumcheck.proof.round_polynomials.len(), + verifier_sumcheck.proof.round_polynomials.len() + ); + for (prover_round, verifier_round) in prover_sumcheck + .proof + .round_polynomials + .iter() + .zip(&verifier_sumcheck.proof.round_polynomials) + { + assert_eq!(prover_round.coefficients(), verifier_round.coefficients()); + } + } + assert_ne!(prover_transcript.state(), verifier_transcript.state()); +} +"#, + ); + source +} + +fn stage1_verifier_proof_adapter(clear_points: bool) -> String { + let point_expr = if clear_points { + "Vec::new()" + } else { + "sumcheck.point.clone()" + }; + r" +fn verifier_proof_from_prover_artifacts( + artifacts: &jolt_kernels::stage1::Stage1ExecutionArtifacts, +) -> verify_stage1_outer::Stage1Proof { + verify_stage1_outer::Stage1Proof { + sumchecks: artifacts + .sumchecks + .iter() + .map(|sumcheck| verify_stage1_outer::Stage1SumcheckOutput { + driver: sumcheck.driver, + point: $POINT_EXPR, + evals: sumcheck + .evals + .iter() + .map(|eval| verify_stage1_outer::Stage1NamedEval { + name: eval.name, + oracle: eval.oracle, + value: eval.value, + }) + .collect(), + proof: sumcheck.proof.clone(), + }) + .collect(), + } +} + +" + .replace("$POINT_EXPR", point_expr) +} + +fn generated_stage1_real_dispatch_main() -> &'static str { + r#"mod prove_stage1_outer; +mod verify_stage1_outer; + +use jolt_field::{Field, Fr}; +use jolt_kernels::stage1::{ + Stage1KernelError, Stage1ProverInputs, Stage1ProverKernelExecutor, +}; +use jolt_sumcheck::SumcheckError; +use jolt_transcript::{Blake2bTranscript, Transcript}; + +fn main() { + let inputs = Stage1ProverInputs::::empty(2); + let mut prover_executor = Stage1ProverKernelExecutor::new(inputs); + let mut prover_transcript = Blake2bTranscript::::new(b"stage1"); + let prover_error = prove_stage1_outer::prove_stage1_outer( + &mut prover_executor, + &mut prover_transcript, + ) + .expect_err("real prover requires uniskip extended evaluations"); + assert_eq!( + prover_error, + Stage1KernelError::MissingKernelInput { + kernel: "jolt_stage1_outer_uniskip", + input: "uniskip_extended_evals", + } + ); + + let proof = verify_stage1_outer::Stage1Proof { + sumchecks: vec![ + verify_stage1_outer::Stage1SumcheckOutput { + driver: "stage1.uniskip.sumcheck", + point: Vec::new(), + evals: Vec::new(), + proof: Default::default(), + }, + verify_stage1_outer::Stage1SumcheckOutput { + driver: "stage1.outer_remaining.sumcheck", + point: Vec::new(), + evals: Vec::new(), + proof: Default::default(), + }, + ], + }; + let mut verifier_transcript = Blake2bTranscript::::new(b"stage1"); + let verifier_error = verify_stage1_outer::verify_stage1_outer( + &proof, + &mut verifier_transcript, + ) + .expect_err("real verifier rejects empty uniskip proof"); + assert!(matches!( + verifier_error, + verify_stage1_outer::VerifyStage1Error::Sumcheck { + driver: "stage1.uniskip.sumcheck", + error: SumcheckError::WrongNumberOfRounds { expected: 1, got: 0 }, + } + )); +} +"# +} + +fn generated_stage1_synthetic_remaining_main() -> String { + let mut source = r"mod prove_stage1_outer; +mod verify_stage1_outer; + +use jolt_field::{Field, Fr}; +use jolt_kernels::stage1::{ + Stage1OuterRemainingContext, Stage1OuterRemainingEvaluator, Stage1ProverInputs, + Stage1ProverKernelExecutor, +}; +use jolt_poly::UnivariatePoly; +use jolt_sumcheck::SumcheckError; +use jolt_transcript::{Blake2bTranscript, Transcript}; + +struct SumZeroRemainingEvaluator; + +impl Stage1OuterRemainingEvaluator for SumZeroRemainingEvaluator { + fn evaluate(&self, _context: Stage1OuterRemainingContext<'_, Fr>, point: &[Fr]) -> Fr { + point[0] + point[0] - Fr::from_u64(1) + } + + fn evaluate_virtual_oracle( + &self, + _context: Stage1OuterRemainingContext<'_, Fr>, + _oracle: &str, + point: &[Fr], + ) -> Option { + Some(point.iter().copied().sum()) + } +} + +" + .to_owned(); + source.push_str(&stage1_verifier_proof_adapter(false)); + source.push_str( + r#" +fn main() { + let extended_evals = vec![Fr::from_u64(0); 9]; + let evaluator = SumZeroRemainingEvaluator; + let inputs = Stage1ProverInputs::::empty(2) + .with_uniskip_extended_evals(&extended_evals) + .with_outer_remaining_evaluator(&evaluator); + let mut prover_executor = Stage1ProverKernelExecutor::new(inputs); + let mut prover_transcript = Blake2bTranscript::::new(b"stage1"); + let prover_artifacts = prove_stage1_outer::prove_stage1_outer( + &mut prover_executor, + &mut prover_transcript, + ) + .expect("generated real stage1 prover succeeds"); + + let proof = verifier_proof_from_prover_artifacts(&prover_artifacts); + let mut verifier_transcript = Blake2bTranscript::::new(b"stage1"); + let verifier_artifacts = verify_stage1_outer::verify_stage1_outer( + &proof, + &mut verifier_transcript, + ) + .expect("generated real stage1 verifier accepts prover proof"); + + assert_eq!(prover_transcript.state(), verifier_transcript.state()); + assert_eq!(prover_artifacts.sumchecks.len(), 2); + assert_eq!(verifier_artifacts.sumchecks.len(), 2); + assert_eq!( + prover_artifacts.sumchecks[1].point, + verifier_artifacts.sumchecks[1].point + ); + + let mut extra_proof = proof.clone(); + extra_proof.sumchecks.push(proof.sumchecks[0].clone()); + let mut verifier_transcript = Blake2bTranscript::::new(b"stage1"); + assert!(matches!( + verify_stage1_outer::verify_stage1_outer(&extra_proof, &mut verifier_transcript), + Err(verify_stage1_outer::VerifyStage1Error::UnexpectedProofCount { + expected: 2, + got: 3, + }) + )); + + let mut wrong_driver = proof.clone(); + wrong_driver.sumchecks.swap(0, 1); + let mut verifier_transcript = Blake2bTranscript::::new(b"stage1"); + assert!(matches!( + verify_stage1_outer::verify_stage1_outer(&wrong_driver, &mut verifier_transcript), + Err(verify_stage1_outer::VerifyStage1Error::InvalidProof { + driver: "stage1.uniskip.sumcheck", + reason: "driver symbol mismatch", + }) + )); + + let mut wrong_round = proof.clone(); + let mut coefficients = wrong_round.sumchecks[0].proof.round_polynomials[0] + .coefficients() + .to_vec(); + coefficients[0] += Fr::from_u64(1); + wrong_round.sumchecks[0].proof.round_polynomials[0] = UnivariatePoly::new(coefficients); + let mut verifier_transcript = Blake2bTranscript::::new(b"stage1"); + assert!(matches!( + verify_stage1_outer::verify_stage1_outer(&wrong_round, &mut verifier_transcript), + Err(verify_stage1_outer::VerifyStage1Error::Sumcheck { + driver: "stage1.uniskip.sumcheck", + error: SumcheckError::RoundCheckFailed { .. }, + }) + )); + + let mut wrong_uniskip_eval = proof.clone(); + wrong_uniskip_eval.sumchecks[0].evals[0].value += Fr::from_u64(1); + let mut verifier_transcript = Blake2bTranscript::::new(b"stage1"); + assert!(matches!( + verify_stage1_outer::verify_stage1_outer(&wrong_uniskip_eval, &mut verifier_transcript), + Err(verify_stage1_outer::VerifyStage1Error::InvalidProof { + driver: "stage1.uniskip.sumcheck", + reason: "eval value mismatch", + }) + )); + + let mut wrong_remaining_eval = proof.clone(); + wrong_remaining_eval.sumchecks[1].evals.swap(0, 1); + let mut verifier_transcript = Blake2bTranscript::::new(b"stage1"); + assert!(matches!( + verify_stage1_outer::verify_stage1_outer(&wrong_remaining_eval, &mut verifier_transcript), + Err(verify_stage1_outer::VerifyStage1Error::InvalidProof { + driver: "stage1.outer_remaining.sumcheck", + reason: "eval name mismatch", + }) + )); + + let mut wrong_point = proof.clone(); + wrong_point.sumchecks[1].point[0] += Fr::from_u64(1); + let mut verifier_transcript = Blake2bTranscript::::new(b"stage1"); + assert!(matches!( + verify_stage1_outer::verify_stage1_outer(&wrong_point, &mut verifier_transcript), + Err(verify_stage1_outer::VerifyStage1Error::InvalidProof { + driver: "stage1.outer_remaining.sumcheck", + reason: "outer remaining point mismatch", + }) + )); +} +"#, + ); + source +} + +fn generated_stage1_r1cs_data_main() -> String { + let mut source = r"mod prove_stage1_outer; +mod verify_stage1_outer; + +use jolt_field::{Field, Fr}; +use jolt_kernels::stage1::{ + Stage1OuterR1csData, Stage1ProverInputs, Stage1ProverKernelExecutor, +}; +use jolt_r1cs::{constraints::rv64, R1csKey}; +use jolt_transcript::{Blake2bTranscript, Transcript}; + +" + .to_owned(); + source.push_str(&stage1_verifier_proof_adapter(false)); + source.push_str( + r#" +fn main() { + let key = R1csKey::new(rv64::rv64_constraints::(), 4); + let mut witness = vec![Fr::from_u64(0); key.num_cycles * key.num_vars_padded]; + for cycle in 0..key.num_cycles { + let base = cycle * key.num_vars_padded; + witness[base + rv64::V_CONST] = Fr::from_u64(1); + witness[base + rv64::V_FLAG_DO_NOT_UPDATE_UNEXPANDED_PC] = Fr::from_u64(1); + key.matrices + .check_witness(&witness[base..base + rv64::NUM_VARS_PER_CYCLE]) + .expect("noop cycle satisfies RV64 constraints"); + } + let data = Stage1OuterR1csData::new(&key, &witness).expect("valid R1CS witness shape"); + let inputs = Stage1ProverInputs::::empty(key.num_cycle_vars()) + .with_outer_remaining_evaluator(&data); + let mut prover_executor = Stage1ProverKernelExecutor::new(inputs); + let mut prover_transcript = Blake2bTranscript::::new(b"stage1"); + let prover_artifacts = prove_stage1_outer::prove_stage1_outer( + &mut prover_executor, + &mut prover_transcript, + ) + .expect("generated real stage1 prover succeeds with R1CS data"); + + let proof = verifier_proof_from_prover_artifacts(&prover_artifacts); + let mut verifier_transcript = Blake2bTranscript::::new(b"stage1"); + let verifier_artifacts = verify_stage1_outer::verify_stage1_outer( + &proof, + &mut verifier_transcript, + ) + .expect("generated real stage1 verifier accepts R1CS-backed proof"); + + assert_eq!(prover_transcript.state(), verifier_transcript.state()); + assert_eq!(prover_artifacts.sumchecks.len(), 2); + assert_eq!(verifier_artifacts.sumchecks.len(), 2); + for (prover_sumcheck, verifier_sumcheck) in prover_artifacts + .sumchecks + .iter() + .zip(verifier_artifacts.sumchecks.iter()) + { + assert_eq!(prover_sumcheck.point, verifier_sumcheck.point); + assert_eq!(prover_sumcheck.evals.len(), verifier_sumcheck.evals.len()); + for (prover_eval, verifier_eval) in prover_sumcheck.evals.iter().zip(&verifier_sumcheck.evals) { + assert_eq!(prover_eval.oracle, verifier_eval.oracle); + assert_eq!(prover_eval.value, verifier_eval.value); + } + } +} +"#, + ); + source +} + +fn generated_commitment_stage1_chain_main() -> String { + let mut source = r"mod prove_commitment_phase; +mod prove_stage1_outer; +mod verify_commitment_phase; +mod verify_stage1_outer; + +use jolt_dory::DoryScheme; +use jolt_field::{Field, Fr}; +use jolt_kernels::stage1::{ + Stage1OuterRemainingContext, Stage1OuterRemainingEvaluator, Stage1ProverInputs, + Stage1ProverKernelExecutor, +}; +use jolt_transcript::{Blake2bTranscript, Transcript}; + +struct SumZeroRemainingEvaluator; + +impl Stage1OuterRemainingEvaluator for SumZeroRemainingEvaluator { + fn evaluate(&self, _context: Stage1OuterRemainingContext<'_, Fr>, point: &[Fr]) -> Fr { + point[0] + point[0] - Fr::from_u64(1) + } + + fn evaluate_virtual_oracle( + &self, + _context: Stage1OuterRemainingContext<'_, Fr>, + _oracle: &str, + point: &[Fr], + ) -> Option { + Some(point.iter().copied().sum()) + } +} + +" + .to_owned(); + source.push_str(tracing_transcript_support()); + source.push_str(&stage1_verifier_proof_adapter(false)); + source.push_str( + r#" +fn main() { + let prover_setup = + DoryScheme::setup_prover(prove_commitment_phase::COMMITMENT_BATCH_PLANS[0].num_vars); + let commitment_inputs = prove_commitment_phase::CommitmentOracleInputs { + rd_inc: &[1, 0, 0, 0], + ram_inc: &[2, 0, 0, 0], + instruction_keys: &[ + Some(0x1234_5678_9abc_def0_0123_4567_89ab_cdefu128), + Some(0), + Some(0), + Some(0), + ], + ram_addresses: &[Some(0), Some(1), Some(2), Some(3)], + bytecode_indices: &[Some(0), Some(1), Some(2), Some(3)], + untrusted_advice: None, + trusted_advice: None, + }; + let mut commitment_oracles = prove_commitment_phase::build_commitment_oracles( + &commitment_inputs, + ) + .expect("build commitment oracles"); + let mut prover_transcript = TracingTranscript::new(b"jolt-chain"); + let commitment = prove_commitment_phase::prove_commitment_phase( + &mut commitment_oracles, + &prover_setup, + &mut prover_transcript, + ) + .expect("prover commitment phase"); + + let extended_evals = vec![Fr::from_u64(0); 9]; + let evaluator = SumZeroRemainingEvaluator; + let stage1_inputs = Stage1ProverInputs::::empty(2) + .with_uniskip_extended_evals(&extended_evals) + .with_outer_remaining_evaluator(&evaluator); + let mut stage1_prover_executor = Stage1ProverKernelExecutor::new(stage1_inputs); + let stage1 = prove_stage1_outer::prove_stage1_outer( + &mut stage1_prover_executor, + &mut prover_transcript, + ) + .expect("stage1 prover phase"); + + let mut verifier_transcript = TracingTranscript::new(b"jolt-chain"); + let verified_commitment = verify_commitment_phase::verify_commitment_phase( + &commitment.commitments, + &mut verifier_transcript, + ) + .expect("verifier commitment phase"); + let stage1_proof = verifier_proof_from_prover_artifacts(&stage1); + let verified_stage1 = verify_stage1_outer::verify_stage1_outer( + &stage1_proof, + &mut verifier_transcript, + ) + .expect("stage1 verifier phase"); + + assert_eq!(commitment.commitments, verified_commitment.commitments); + assert_eq!(stage1.sumchecks.len(), 2); + assert_eq!(verified_stage1.sumchecks.len(), 2); + assert_eq!(stage1.sumchecks[1].point, verified_stage1.sumchecks[1].point); + assert_transcript_step_parity(&prover_transcript, &verifier_transcript); +} +"#, + ); + source +} + +fn tracing_transcript_support() -> &'static str { + r"#[derive(Clone, Debug, PartialEq, Eq)] +enum TranscriptEvent { + Init([u8; 32]), + Append { bytes: Vec, state: [u8; 32] }, + Challenge { state: [u8; 32] }, +} + +#[derive(Clone, Default)] +struct TracingTranscript { + inner: Blake2bTranscript, + events: Vec, +} + +impl Transcript for TracingTranscript { + type Challenge = Fr; + + fn new(label: &'static [u8]) -> Self { + let inner = Blake2bTranscript::::new(label); + let events = vec![TranscriptEvent::Init(*inner.state())]; + Self { inner, events } + } + + fn append_bytes(&mut self, bytes: &[u8]) { + self.inner.append_bytes(bytes); + self.events.push(TranscriptEvent::Append { + bytes: bytes.to_vec(), + state: *self.inner.state(), + }); + } + + fn challenge(&mut self) -> Fr { + let challenge = self.inner.challenge(); + self.events.push(TranscriptEvent::Challenge { + state: *self.inner.state(), + }); + challenge + } + + fn state(&self) -> &[u8; 32] { + self.inner.state() + } +} + +fn assert_transcript_step_parity(prover: &TracingTranscript, verifier: &TracingTranscript) { + assert_eq!(prover.events, verifier.events); + assert_eq!(prover.state(), verifier.state()); +} + +" +} diff --git a/crates/bolt/tests/verifier_cleanup.rs b/crates/bolt/tests/verifier_cleanup.rs new file mode 100644 index 0000000000..55231001df --- /dev/null +++ b/crates/bolt/tests/verifier_cleanup.rs @@ -0,0 +1,597 @@ +#![expect( + clippy::expect_used, + clippy::print_stderr, + reason = "verifier cleanup tests use explicit panic messages and print metrics for CI logs" +)] + +use std::path::{Path, PathBuf}; + +const GENERATED_VERIFIER_TARGET_LOC: usize = 6_000; +const GENERATED_VERIFIER_STRETCH_LOC: usize = 3_000; +const VERIFIER_RS_TARGET_LOC: usize = 500; +const VERIFIER_RS_STRETCH_LOC: usize = 350; +const STAGE6_STAGE7_TARGET_LOC: usize = 3_000; + +const GENERATED_VERIFIER_BASELINE_LOC_CEILING: usize = 9_185; +const SHARED_RUNTIME_BASELINE_LOC_CEILING: usize = 1_900; +const VERIFIER_RS_BASELINE_LOC_CEILING: usize = VERIFIER_RS_TARGET_LOC; +const STAGE6_STAGE7_BASELINE_LOC_CEILING: usize = STAGE6_STAGE7_TARGET_LOC; +const STAGE_LOCAL_PLAN_STRUCT_BASELINE_CEILING: usize = 18; +const FIELD_EXPR_OPERAND_CONSTANT_BASELINE_CEILING: usize = 0; +const STAGE_HELPER_FUNCTION_BASELINE_CEILING: usize = 38; +const RELATION_STRING_SITE_BASELINE_CEILING: usize = 72; + +const ALLOWED_JOLT_PROTOCOL_SYMBOLS: &[&str] = &[ + "jolt.commitment_phase", + "jolt.main_witness_commit_domain", + "jolt.main_witness_commitments", + "jolt.main_witness_polys", + "jolt.ram_address_domain", + "jolt.stage1.outer.remaining", + "jolt.stage1.outer.uniskip", + "jolt.stage1_outer", + "jolt.stage1_uniskip_domain", + "jolt.stage2", + "jolt.stage2.batched", + "jolt.stage2.instruction_lookup.claim_reduction", + "jolt.stage2.product_virtual.remainder", + "jolt.stage2.product_virtual.uniskip", + "jolt.stage2.ram.output_check", + "jolt.stage2.ram.output_check.layout", + "jolt.stage2.ram.raf_evaluation", + "jolt.stage2.ram.read_write", + "jolt.stage2_ram_rw_domain", + "jolt.stage2_uniskip_domain", + "jolt.stage3", + "jolt.stage3.batched", + "jolt.stage3.instruction_input", + "jolt.stage3.registers_claim_reduction", + "jolt.stage3.spartan_shift", + "jolt.stage4", + "jolt.stage4.batched", + "jolt.stage4.ram_val_check", + "jolt.stage4.registers_read_write", + "jolt.stage4_registers_rw_domain", + "jolt.stage5.batched", + "jolt.stage5.instruction_read_raf", + "jolt.stage5.ram_ra_claim_reduction", + "jolt.stage5.registers_val_evaluation", + "jolt.stage5_instruction_ra_chunk_domain", + "jolt.stage5_instruction_read_raf_domain", + "jolt.stage6.batched", + "jolt.stage6.booleanity", + "jolt.stage6.bytecode_read_raf", + "jolt.stage6.hamming_booleanity", + "jolt.stage6.inc_claim_reduction", + "jolt.stage6.instruction_ra_virtual", + "jolt.stage6.ram_ra_virtual", + "jolt.stage6_booleanity_domain", + "jolt.stage6_bytecode_read_raf_domain", + "jolt.stage7.batched", + "jolt.stage7.hamming_booleanity", + "jolt.stage7.hamming_weight_claim_reduction", + "jolt.stage7_hamming_weight_claim_reduction_domain", + "jolt.stage8", + "jolt.trace_domain", + "jolt.trusted_advice_commitment", + "jolt.untrusted_advice_commitment", +]; + +const GENERIC_COMPILER_JOLT_PATTERNS: &[&str] = &[ + "jolt.", + "Jolt", + "jolt_", + "jolt-", + "jolt_core", + "stage1_outer", + "stage1", + "stage2", + "stage3", + "stage4", + "stage5", + "stage6", + "stage7", + "stage8", + "uniskip", + "spartan", + "bytecode", + "hamming", + "instruction_read", + "ram_val", + "ram_ra", + "registers_read", + "lookup", + "dory", + "bn254", +]; + +#[derive(Debug, Default)] +struct VerifierCleanupMetrics { + total_loc: usize, + generated_surface_loc: usize, + shared_runtime_loc: usize, + verifier_rs_loc: usize, + stage6_stage7_loc: usize, + stage_local_generic_plan_structs: usize, + field_expr_operand_constants: usize, + stage_local_helper_functions: usize, + relation_string_sites: usize, +} + +#[test] +fn checked_in_generated_verifier_metrics_are_recorded_and_bounded() { + let verifier_src = workspace_root().join("crates/jolt-verifier/src"); + let metrics = verifier_cleanup_metrics(&verifier_src); + + eprintln!( + "\nGenerated verifier cleanup metrics\n\ + generated_surface_loc: {generated_surface_loc} (target <= {target_loc}, stretch <= {stretch_loc})\n\ + shared_runtime_loc: {shared_runtime_loc} (baseline ceiling <= {shared_runtime_baseline})\n\ + total_loc: {total_loc} (baseline ceiling <= {baseline_loc})\n\ + verifier_rs_loc: {verifier_rs_loc} (target <= {verifier_target}, stretch <= {verifier_stretch}, baseline ceiling <= {verifier_baseline})\n\ + stage6_stage7_loc: {stage6_stage7_loc} (target <= {stage67_target}, baseline ceiling <= {stage67_baseline})\n\ + stage_local_generic_plan_structs: {plan_structs} (baseline ceiling <= {plan_baseline})\n\ + field_expr_operand_constants: {operand_constants} (baseline ceiling <= {operand_baseline})\n\ + stage_local_helper_functions: {helper_functions} (baseline ceiling <= {helper_baseline})\n\ + relation_string_sites: {relation_sites} (baseline ceiling <= {relation_baseline})", + generated_surface_loc = metrics.generated_surface_loc, + shared_runtime_loc = metrics.shared_runtime_loc, + shared_runtime_baseline = SHARED_RUNTIME_BASELINE_LOC_CEILING, + total_loc = metrics.total_loc, + target_loc = GENERATED_VERIFIER_TARGET_LOC, + stretch_loc = GENERATED_VERIFIER_STRETCH_LOC, + baseline_loc = GENERATED_VERIFIER_BASELINE_LOC_CEILING, + verifier_rs_loc = metrics.verifier_rs_loc, + verifier_target = VERIFIER_RS_TARGET_LOC, + verifier_stretch = VERIFIER_RS_STRETCH_LOC, + verifier_baseline = VERIFIER_RS_BASELINE_LOC_CEILING, + stage6_stage7_loc = metrics.stage6_stage7_loc, + stage67_target = STAGE6_STAGE7_TARGET_LOC, + stage67_baseline = STAGE6_STAGE7_BASELINE_LOC_CEILING, + plan_structs = metrics.stage_local_generic_plan_structs, + plan_baseline = STAGE_LOCAL_PLAN_STRUCT_BASELINE_CEILING, + operand_constants = metrics.field_expr_operand_constants, + operand_baseline = FIELD_EXPR_OPERAND_CONSTANT_BASELINE_CEILING, + helper_functions = metrics.stage_local_helper_functions, + helper_baseline = STAGE_HELPER_FUNCTION_BASELINE_CEILING, + relation_sites = metrics.relation_string_sites, + relation_baseline = RELATION_STRING_SITE_BASELINE_CEILING, + ); + + assert!( + metrics.generated_surface_loc <= GENERATED_VERIFIER_TARGET_LOC, + "generated verifier surface is {} LOC; keep reducing generated stage/orchestration code or intentionally update the cleanup target", + metrics.generated_surface_loc + ); + assert!( + metrics.generated_surface_loc > GENERATED_VERIFIER_STRETCH_LOC, + "cleanup metric reached the stretch target; tighten the generated verifier surface gate" + ); + assert!( + metrics.shared_runtime_loc <= SHARED_RUNTIME_BASELINE_LOC_CEILING, + "shared verifier runtime grew to {} LOC; keep generic runtime small and audited", + metrics.shared_runtime_loc + ); + assert!( + metrics.total_loc <= GENERATED_VERIFIER_BASELINE_LOC_CEILING, + "checked-in verifier grew to {} LOC; lower generated/runtime surface, or intentionally update the cleanup baseline", + metrics.total_loc + ); + assert!( + metrics.verifier_rs_loc <= VERIFIER_RS_BASELINE_LOC_CEILING, + "top-level verifier grew to {} LOC; keep orchestration small and readable", + metrics.verifier_rs_loc + ); + assert!( + metrics.stage6_stage7_loc <= STAGE6_STAGE7_BASELINE_LOC_CEILING, + "Stage 6/7 generated verifier surface grew to {} LOC; compact plan data before adding more generated code", + metrics.stage6_stage7_loc + ); + assert!( + metrics.stage_local_generic_plan_structs <= STAGE_LOCAL_PLAN_STRUCT_BASELINE_CEILING, + "stage-local generic plan struct count grew to {}; move shared plan types into common verifier runtime", + metrics.stage_local_generic_plan_structs + ); + assert!( + metrics.field_expr_operand_constants == FIELD_EXPR_OPERAND_CONSTANT_BASELINE_CEILING, + "field-expression operand constants grew to {}; compact field expression encoding", + metrics.field_expr_operand_constants + ); + assert!( + metrics.stage_local_helper_functions <= STAGE_HELPER_FUNCTION_BASELINE_CEILING, + "stage-local helper function count grew to {}; factor verifier mechanics into shared runtime", + metrics.stage_local_helper_functions + ); + assert!( + metrics.relation_string_sites <= RELATION_STRING_SITE_BASELINE_CEILING, + "relation string sites grew to {}; prefer typed relation plan data or explicit allowlists", + metrics.relation_string_sites + ); +} + +#[test] +fn checked_in_generated_verifier_respects_boundary_hygiene() { + let verifier_root = workspace_root().join("crates/jolt-verifier"); + let manifest = + std::fs::read_to_string(verifier_root.join("Cargo.toml")).expect("read verifier manifest"); + for package in [ + "jolt-prover", + "jolt-kernels", + "jolt-core", + "jolt-equivalence", + "jolt-profiling", + "tracer", + ] { + assert!( + !manifest.contains(package), + "generated verifier manifest depends on forbidden package `{package}`" + ); + } + + for path in rust_files(&verifier_root.join("src")) { + let source = std::fs::read_to_string(&path).expect("read verifier source"); + for pattern in [ + "use jolt_prover", + "jolt_prover::", + "use jolt_kernels", + "jolt_kernels::", + "use jolt_core", + "jolt_core::", + "use jolt_equivalence", + "jolt_equivalence::", + "use jolt_profiling", + "jolt_profiling::", + "use tracer", + "tracer::", + ] { + assert!( + !source.contains(pattern), + "generated verifier source `{}` contains forbidden import/reference `{pattern}`", + path.display() + ); + } + assert!( + !source.contains("JoltField::Challenge") + && !source.contains("Transcript") + && !source.contains("Challenge = <"), + "generated verifier source `{}` drifted away from the full-field transcript path", + path.display() + ); + } +} + +#[test] +fn verifier_cpu_fixtures_are_kernel_free() { + let fixtures = workspace_root().join("crates/bolt/tests/fixtures"); + if !fixtures.exists() { + eprintln!("skipping optional verifier MLIR scratch fixture check; run commitment_ir with JOLT_UPDATE_GOLDENS=1 to materialize fixtures"); + return; + } + let mut checked = 0usize; + for path in files_with_extension(&fixtures, "mlir") { + let file_name = path + .file_name() + .and_then(|name| name.to_str()) + .expect("fixture file name"); + if !file_name.contains("verifier") { + continue; + } + checked += 1; + let source = std::fs::read_to_string(&path).expect("read verifier MLIR fixture"); + for pattern in ["kernel = @", "\"cpu.kernel\"", "\"compute.kernel\""] { + assert!( + !source.contains(pattern), + "verifier MLIR fixture `{}` contains forbidden kernel marker `{pattern}`", + path.display() + ); + } + } + assert!(checked > 0, "no verifier MLIR fixtures were checked"); +} + +#[test] +fn checked_in_generated_verifier_protocol_symbols_are_allowlisted() { + let verifier_root = workspace_root().join("crates/jolt-verifier/src"); + let mut checked = 0usize; + for path in rust_files(&verifier_root) { + let source = std::fs::read_to_string(&path).expect("read verifier source"); + for symbol in quoted_jolt_protocol_symbols(&source) { + checked += 1; + assert_allowed_jolt_protocol_symbol(&path, symbol); + } + } + assert!( + checked > 0, + "no generated verifier Jolt symbols were checked" + ); +} + +#[test] +fn verifier_mlir_fixtures_protocol_symbols_are_allowlisted() { + let fixtures = workspace_root().join("crates/bolt/tests/fixtures"); + if !fixtures.exists() { + eprintln!("skipping optional verifier MLIR scratch symbol check; run commitment_ir with JOLT_UPDATE_GOLDENS=1 to materialize fixtures"); + return; + } + let mut checked = 0usize; + for path in files_with_extension(&fixtures, "mlir") { + let file_name = path + .file_name() + .and_then(|name| name.to_str()) + .expect("fixture file name"); + if !file_name.contains("verifier") { + continue; + } + let source = std::fs::read_to_string(&path).expect("read verifier MLIR fixture"); + for symbol in mlir_jolt_protocol_symbols(&source) { + checked += 1; + assert_allowed_jolt_protocol_symbol(&path, symbol); + } + } + assert!(checked > 0, "no verifier MLIR Jolt symbols were checked"); +} + +#[test] +fn generic_compiler_rejects_jolt_protocol_strings() { + let root = workspace_root(); + let mut offenders = Vec::new(); + for path in generic_compiler_source_files(&root) { + let source = std::fs::read_to_string(&path).expect("read generic compiler source"); + let hits = count_generic_compiler_jolt_hits(&source); + if hits == 0 { + continue; + } + + let relative = relative_workspace_path(&root, &path); + offenders.push(format!("{relative}: {hits} hit(s)")); + } + assert!( + offenders.is_empty(), + "generic compiler source contains quarantined Jolt protocol strings:\n{}", + offenders.join("\n") + ); +} + +#[test] +fn jolt_artifact_apis_are_quarantined_out_of_generic_exports() { + let root = workspace_root(); + let artifact_source = + std::fs::read_to_string(root.join("crates/bolt/src/emit/rust/artifacts.rs")) + .expect("read generic artifact assembly"); + for pattern in [ + "JoltProtocolStage", + "JoltArtifactCrate", + "JoltRustArtifact", + "JoltGeneratedCrate", + "JoltGeneratedFile", + "jolt_artifact_config", + "jolt_rust_artifact", + "assemble_jolt_generated_crates", + "assemble_jolt_workspace_generated_crates", + "write_jolt_generated_crates", + "validate_jolt_rust_artifact_imports", + ] { + assert!( + !artifact_source.contains(pattern), + "generic artifact assembly still exposes quarantined Jolt API `{pattern}`" + ); + } + + let rust_mod_source = std::fs::read_to_string(root.join("crates/bolt/src/emit/rust/mod.rs")) + .expect("read Rust emitter exports"); + assert!( + !rust_mod_source.contains("assemble_jolt_") + && !rust_mod_source.contains("JoltProtocolStage") + && !rust_mod_source.contains("jolt_artifact_config"), + "generic Rust emitter exports still re-export Jolt artifact APIs" + ); + + let lib_source = + std::fs::read_to_string(root.join("crates/bolt/src/lib.rs")).expect("read bolt lib"); + assert!( + !lib_source.contains("pub use protocols::jolt"), + "root bolt exports must keep Jolt APIs under bolt::protocols::jolt" + ); +} + +fn verifier_cleanup_metrics(verifier_src: &Path) -> VerifierCleanupMetrics { + let mut metrics = VerifierCleanupMetrics::default(); + for path in rust_files(verifier_src) { + let source = std::fs::read_to_string(&path).expect("read verifier source"); + let relative = path + .strip_prefix(verifier_src) + .expect("relative verifier path"); + let line_count = source.lines().count(); + metrics.total_loc += line_count; + if relative == Path::new("stages/common.rs") { + metrics.shared_runtime_loc += line_count; + } else { + metrics.generated_surface_loc += line_count; + } + if relative == Path::new("verifier.rs") { + metrics.verifier_rs_loc = line_count; + } + if relative == Path::new("stages/stage6.rs") || relative == Path::new("stages/stage7.rs") { + metrics.stage6_stage7_loc += line_count; + } + if relative.starts_with("stages") { + metrics.stage_local_generic_plan_structs += + count_stage_local_generic_plan_structs(&source); + metrics.field_expr_operand_constants += count_field_expr_operand_constants(&source); + metrics.stage_local_helper_functions += count_stage_local_helper_functions(&source); + metrics.relation_string_sites += count_relation_string_sites(&source); + } + } + metrics +} + +fn count_stage_local_generic_plan_structs(source: &str) -> usize { + const PLAN_SUFFIXES: &[&str] = &[ + "FieldExprPlan", + "OpeningClaimPlan", + "OpeningClaimEqualityPlan", + "SumcheckClaimPlan", + "SumcheckDriverPlan", + "SumcheckEvalPlan", + "SumcheckInstanceResultPlan", + "PointSlicePlan", + "PointConcatPlan", + "ProgramStepPlan", + "TranscriptSqueezePlan", + "TranscriptAbsorbBytesPlan", + "CpuProgramPlan", + "VerifierProgramPlan", + "NamedEval", + ]; + source + .lines() + .filter(|line| { + let line = line.trim_start(); + (line.starts_with("pub struct Stage") || line.starts_with("pub type Stage")) + && PLAN_SUFFIXES.iter().any(|suffix| line.contains(suffix)) + }) + .count() +} + +fn count_field_expr_operand_constants(source: &str) -> usize { + source + .lines() + .filter(|line| line.contains("FIELD_EXPR_") && line.contains("OPERAND")) + .count() +} + +fn count_stage_local_helper_functions(source: &str) -> usize { + const HELPER_PREFIXES: &[&str] = &[ + "fn evaluate_stage", + "fn verify_opening_equalities", + "fn append_opening_claims", + "fn find_", + "fn expected_", + "fn pow_field", + "fn single_operand", + "fn require_operand_count", + ]; + source + .lines() + .filter(|line| { + let line = line.trim_start(); + HELPER_PREFIXES + .iter() + .any(|prefix| line.starts_with(prefix)) + }) + .count() +} + +fn count_relation_string_sites(source: &str) -> usize { + source + .lines() + .filter(|line| { + line.contains("match instance.relation") + || line.contains("match claim.relation") + || line.contains("match driver.relation") + || line.contains("relation: Some(\"jolt.") + || line.contains("relation: \"jolt.") + }) + .count() +} + +fn assert_allowed_jolt_protocol_symbol(path: &Path, symbol: &str) { + assert!( + ALLOWED_JOLT_PROTOCOL_SYMBOLS.contains(&symbol), + "`{}` contains unreviewed Jolt protocol symbol `{symbol}`", + path.display() + ); +} + +fn quoted_jolt_protocol_symbols(source: &str) -> Vec<&str> { + let mut symbols = Vec::new(); + let mut rest = source; + while let Some(offset) = rest.find("\"jolt.") { + let after_quote = &rest[offset + 1..]; + if let Some(end) = after_quote.find('"') { + symbols.push(&after_quote[..end]); + rest = &after_quote[end + 1..]; + } else { + break; + } + } + symbols +} + +fn mlir_jolt_protocol_symbols(source: &str) -> Vec<&str> { + let mut symbols = Vec::new(); + let mut rest = source; + while let Some(offset) = rest.find("@jolt") { + let after_at = &rest[offset + 1..]; + let end = after_at + .char_indices() + .find_map(|(index, ch)| { + (!matches!(ch, 'a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '.')).then_some(index) + }) + .unwrap_or(after_at.len()); + symbols.push(&after_at[..end]); + rest = &after_at[end..]; + } + symbols +} + +fn generic_compiler_source_files(root: &Path) -> Vec { + let source_root = root.join("crates/bolt/src"); + let mut files = rust_files(&source_root) + .into_iter() + .filter(|path| { + !relative_workspace_path(root, path).starts_with("crates/bolt/src/protocols/") + }) + .collect::>(); + files.sort(); + files +} + +fn count_generic_compiler_jolt_hits(source: &str) -> usize { + source + .lines() + .filter(|line| { + GENERIC_COMPILER_JOLT_PATTERNS + .iter() + .any(|pattern| line.contains(pattern)) + }) + .count() +} + +fn relative_workspace_path(root: &Path, path: &Path) -> String { + path.strip_prefix(root) + .expect("workspace-relative path") + .to_string_lossy() + .replace('\\', "/") +} + +fn rust_files(root: &Path) -> Vec { + files_with_extension(root, "rs") +} + +fn files_with_extension(root: &Path, extension: &str) -> Vec { + let mut files = Vec::new(); + collect_files_with_extension(root, extension, &mut files); + files.sort(); + files +} + +fn collect_files_with_extension(root: &Path, extension: &str, files: &mut Vec) { + for entry in std::fs::read_dir(root).expect("read directory") { + let entry = entry.expect("read directory entry"); + let path = entry.path(); + if path.is_dir() { + collect_files_with_extension(&path, extension, files); + } else if path.extension().and_then(|ext| ext.to_str()) == Some(extension) { + files.push(path); + } + } +} + +fn workspace_root() -> PathBuf { + Path::new(env!("CARGO_MANIFEST_DIR")) + .parent() + .and_then(Path::parent) + .expect("workspace root") + .to_path_buf() +} From 48fc12edd24488ac858fe434180d5004aae45c9b Mon Sep 17 00:00:00 2001 From: Markos Georghiades <53157953+Markos-The-G@users.noreply.github.com> Date: Fri, 8 May 2026 00:17:55 -0400 Subject: [PATCH 05/14] feat(generated-roles): add generated Jolt role crates Add the Bolt-generated kernel, prover, and verifier crates on top of the Bolt emitter branch. Wire the generated role crates into the workspace and keep their lint suppressions scoped to generated test modules. Validation: cargo check -p jolt-kernels -p jolt-verifier -p jolt-prover -q; cargo clippy -p jolt-kernels -p jolt-verifier -p jolt-prover -q --all-targets -- -D warnings; cargo nextest run -p jolt-kernels -p jolt-verifier -p jolt-prover --cargo-quiet. --- Cargo.lock | 47 + Cargo.toml | 8 + crates/jolt-kernels/Cargo.toml | 25 + crates/jolt-kernels/src/dense.rs | 32 + crates/jolt-kernels/src/lib.rs | 17 + crates/jolt-kernels/src/split_eq.rs | 65 + crates/jolt-kernels/src/stage1.rs | 2948 +++++++ crates/jolt-kernels/src/stage1/README.md | 17 + crates/jolt-kernels/src/stage1/rv64_typed.rs | 1207 +++ crates/jolt-kernels/src/stage2.rs | 5201 ++++++++++++ crates/jolt-kernels/src/stage3.rs | 4223 ++++++++++ crates/jolt-kernels/src/stage4.rs | 4667 +++++++++++ crates/jolt-kernels/src/stage5.rs | 4949 ++++++++++++ crates/jolt-kernels/src/stage6.rs | 7163 +++++++++++++++++ crates/jolt-kernels/src/stage7.rs | 2586 ++++++ crates/jolt-kernels/src/trace.rs | 391 + crates/jolt-prover/Cargo.toml | 22 + crates/jolt-prover/src/lib.rs | 100 + crates/jolt-prover/src/prover.rs | 2090 +++++ crates/jolt-prover/src/stages/commitment.rs | 1075 +++ crates/jolt-prover/src/stages/mod.rs | 18 + crates/jolt-prover/src/stages/stage1_outer.rs | 264 + crates/jolt-prover/src/stages/stage2.rs | 402 + crates/jolt-prover/src/stages/stage3.rs | 351 + crates/jolt-prover/src/stages/stage4.rs | 255 + crates/jolt-prover/src/stages/stage5.rs | 506 ++ crates/jolt-prover/src/stages/stage6.rs | 2515 ++++++ crates/jolt-prover/src/stages/stage7.rs | 1950 +++++ crates/jolt-prover/src/stages/stage8.rs | 173 + crates/jolt-verifier/Cargo.toml | 21 + crates/jolt-verifier/src/lib.rs | 87 + crates/jolt-verifier/src/stages/commitment.rs | 343 + crates/jolt-verifier/src/stages/common.rs | 1789 ++++ crates/jolt-verifier/src/stages/mod.rs | 19 + .../jolt-verifier/src/stages/stage1_outer.rs | 406 + crates/jolt-verifier/src/stages/stage2.rs | 1050 +++ crates/jolt-verifier/src/stages/stage3.rs | 526 ++ crates/jolt-verifier/src/stages/stage4.rs | 552 ++ crates/jolt-verifier/src/stages/stage5.rs | 662 ++ crates/jolt-verifier/src/stages/stage6.rs | 987 +++ crates/jolt-verifier/src/stages/stage7.rs | 682 ++ crates/jolt-verifier/src/stages/stage8.rs | 173 + crates/jolt-verifier/src/verifier.rs | 493 ++ 43 files changed, 51057 insertions(+) create mode 100644 crates/jolt-kernels/Cargo.toml create mode 100644 crates/jolt-kernels/src/dense.rs create mode 100644 crates/jolt-kernels/src/lib.rs create mode 100644 crates/jolt-kernels/src/split_eq.rs create mode 100644 crates/jolt-kernels/src/stage1.rs create mode 100644 crates/jolt-kernels/src/stage1/README.md create mode 100644 crates/jolt-kernels/src/stage1/rv64_typed.rs create mode 100644 crates/jolt-kernels/src/stage2.rs create mode 100644 crates/jolt-kernels/src/stage3.rs create mode 100644 crates/jolt-kernels/src/stage4.rs create mode 100644 crates/jolt-kernels/src/stage5.rs create mode 100644 crates/jolt-kernels/src/stage6.rs create mode 100644 crates/jolt-kernels/src/stage7.rs create mode 100644 crates/jolt-kernels/src/trace.rs create mode 100644 crates/jolt-prover/Cargo.toml create mode 100644 crates/jolt-prover/src/lib.rs create mode 100644 crates/jolt-prover/src/prover.rs create mode 100644 crates/jolt-prover/src/stages/commitment.rs create mode 100644 crates/jolt-prover/src/stages/mod.rs create mode 100644 crates/jolt-prover/src/stages/stage1_outer.rs create mode 100644 crates/jolt-prover/src/stages/stage2.rs create mode 100644 crates/jolt-prover/src/stages/stage3.rs create mode 100644 crates/jolt-prover/src/stages/stage4.rs create mode 100644 crates/jolt-prover/src/stages/stage5.rs create mode 100644 crates/jolt-prover/src/stages/stage6.rs create mode 100644 crates/jolt-prover/src/stages/stage7.rs create mode 100644 crates/jolt-prover/src/stages/stage8.rs create mode 100644 crates/jolt-verifier/Cargo.toml create mode 100644 crates/jolt-verifier/src/lib.rs create mode 100644 crates/jolt-verifier/src/stages/commitment.rs create mode 100644 crates/jolt-verifier/src/stages/common.rs create mode 100644 crates/jolt-verifier/src/stages/mod.rs create mode 100644 crates/jolt-verifier/src/stages/stage1_outer.rs create mode 100644 crates/jolt-verifier/src/stages/stage2.rs create mode 100644 crates/jolt-verifier/src/stages/stage3.rs create mode 100644 crates/jolt-verifier/src/stages/stage4.rs create mode 100644 crates/jolt-verifier/src/stages/stage5.rs create mode 100644 crates/jolt-verifier/src/stages/stage6.rs create mode 100644 crates/jolt-verifier/src/stages/stage7.rs create mode 100644 crates/jolt-verifier/src/stages/stage8.rs create mode 100644 crates/jolt-verifier/src/verifier.rs diff --git a/Cargo.lock b/Cargo.lock index 031c79d2dc..609fab23c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3067,6 +3067,22 @@ dependencies = [ "tracer", ] +[[package]] +name = "jolt-kernels" +version = "0.1.0" +dependencies = [ + "jolt-field", + "jolt-lookup-tables", + "jolt-poly", + "jolt-r1cs", + "jolt-sumcheck", + "jolt-trace", + "jolt-transcript", + "jolt-witness", + "rayon", + "tracing", +] + [[package]] name = "jolt-lookup-tables" version = "0.1.0" @@ -3154,6 +3170,22 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "jolt-prover" +version = "0.0.0" +dependencies = [ + "jolt-dory", + "jolt-field", + "jolt-kernels", + "jolt-openings", + "jolt-poly", + "jolt-transcript", + "jolt-verifier", + "jolt-witness", + "rayon", + "tracing", +] + [[package]] name = "jolt-r1cs" version = "0.1.0" @@ -3247,6 +3279,21 @@ dependencies = [ "sha3 0.11.0", ] +[[package]] +name = "jolt-verifier" +version = "0.0.0" +dependencies = [ + "jolt-dory", + "jolt-field", + "jolt-lookup-tables", + "jolt-openings", + "jolt-poly", + "jolt-sumcheck", + "jolt-transcript", + "serde", + "tracing", +] + [[package]] name = "jolt-witness" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index d82737b259..8de50db4df 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,9 @@ members = [ "crates/jolt-transcript", "crates/jolt-witness", "crates/bolt", + "crates/jolt-kernels", + "crates/jolt-prover", + "crates/jolt-verifier", "crates/jolt-profiling", "crates/jolt-field", "jolt-core", @@ -379,6 +382,8 @@ common = { path = "./common", default-features = false } tracer = { path = "./tracer", default-features = false } jolt-core = { path = "./jolt-core", default-features = false } jolt-crypto = { path = "./crates/jolt-crypto" } +jolt-dory = { path = "./crates/jolt-dory" } +jolt-hyperkzg = { path = "./crates/jolt-hyperkzg" } jolt-field = { path = "./crates/jolt-field" } jolt-openings = { path = "./crates/jolt-openings" } jolt-poly = { path = "./crates/jolt-poly" } @@ -387,6 +392,9 @@ jolt-sumcheck = { path = "./crates/jolt-sumcheck" } jolt-r1cs = { path = "./crates/jolt-r1cs" } jolt-witness = { path = "./crates/jolt-witness" } bolt = { path = "./crates/bolt" } +jolt-kernels = { path = "./crates/jolt-kernels" } +jolt-prover = { path = "./crates/jolt-prover" } +jolt-verifier = { path = "./crates/jolt-verifier" } jolt-riscv = { path = "./crates/jolt-riscv" } jolt-trace = { path = "./crates/jolt-trace" } jolt-lookup-tables = { path = "./crates/jolt-lookup-tables" } diff --git a/crates/jolt-kernels/Cargo.toml b/crates/jolt-kernels/Cargo.toml new file mode 100644 index 0000000000..a60c11cfc6 --- /dev/null +++ b/crates/jolt-kernels/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "jolt-kernels" +version = "0.1.0" +edition = "2021" +license = "MIT OR Apache-2.0" +authors = ["Jolt Contributors"] +repository = "https://github.com/a16z/jolt" +description = "Coarse CPU kernels targeted by the Bolt-shaped Jolt compiler" +keywords = ["SNARK", "compiler", "sumcheck", "zkvm"] +categories = ["cryptography"] + +[lints] +workspace = true + +[dependencies] +jolt-field = { path = "../jolt-field" } +jolt-lookup-tables = { path = "../jolt-lookup-tables" } +jolt-poly = { path = "../jolt-poly" } +jolt-r1cs = { path = "../jolt-r1cs" } +jolt-sumcheck = { path = "../jolt-sumcheck" } +jolt-transcript = { path = "../jolt-transcript" } +jolt-trace = { path = "../jolt-trace" } +jolt-witness = { path = "../jolt-witness" } +rayon = { workspace = true } +tracing = { workspace = true } diff --git a/crates/jolt-kernels/src/dense.rs b/crates/jolt-kernels/src/dense.rs new file mode 100644 index 0000000000..c964703db0 --- /dev/null +++ b/crates/jolt-kernels/src/dense.rs @@ -0,0 +1,32 @@ +use jolt_field::Field; +use rayon::prelude::*; + +pub(crate) const DENSE_BIND_PAR_THRESHOLD: usize = 1024; + +#[inline] +pub(crate) fn bind_dense_evals_reuse( + values: &mut Vec, + scratch: &mut Vec, + challenge: F, +) { + let half = values.len() / 2; + scratch.resize(half, F::zero()); + if half >= DENSE_BIND_PAR_THRESHOLD { + scratch + .par_iter_mut() + .enumerate() + .for_each(|(index, output)| { + let low = values[index << 1]; + let high = values[(index << 1) + 1]; + *output = low + challenge * (high - low); + }); + } else { + for (index, output) in scratch.iter_mut().enumerate() { + let low = values[index << 1]; + let high = values[(index << 1) + 1]; + *output = low + challenge * (high - low); + } + } + std::mem::swap(values, scratch); + scratch.clear(); +} diff --git a/crates/jolt-kernels/src/lib.rs b/crates/jolt-kernels/src/lib.rs new file mode 100644 index 0000000000..882e8b132c --- /dev/null +++ b/crates/jolt-kernels/src/lib.rs @@ -0,0 +1,17 @@ +//! Coarse CPU kernels used by generated Bolt/Jolt Rust. +//! +//! This crate is intentionally above the primitive protocol crates and below +//! generated code. It owns the temporary coarse CPU ABI while the compiler +//! grows finer compute lowerings. + +mod dense; +mod split_eq; + +pub mod stage1; +pub mod stage2; +pub mod stage3; +pub mod stage4; +pub mod stage5; +pub mod stage6; +pub mod stage7; +pub mod trace; diff --git a/crates/jolt-kernels/src/split_eq.rs b/crates/jolt-kernels/src/split_eq.rs new file mode 100644 index 0000000000..debd0251e4 --- /dev/null +++ b/crates/jolt-kernels/src/split_eq.rs @@ -0,0 +1,65 @@ +use jolt_field::Field; +use jolt_poly::EqPolynomial; + +use crate::dense::bind_dense_evals_reuse; + +#[derive(Clone)] +pub(crate) struct SplitEqState { + low_point: Vec, + high_point: Vec, + e_in: Vec, + e_out: Vec, + e_in_scratch: Vec, + e_out_scratch: Vec, +} + +impl SplitEqState { + #[inline] + pub(crate) fn new_low_to_high(point: &[F], scaling: Option) -> Self { + let (high_point, low_point) = point.split_at(point.len() / 2); + Self { + low_point: low_point.to_vec(), + high_point: high_point.to_vec(), + e_in: EqPolynomial::::evals(low_point, scaling), + e_out: EqPolynomial::::evals(high_point, None), + e_in_scratch: Vec::new(), + e_out_scratch: Vec::new(), + } + } + + #[inline] + pub(crate) fn e_in(&self) -> &[F] { + &self.e_in + } + + #[inline] + pub(crate) fn e_out(&self) -> &[F] { + &self.e_out + } + + #[inline] + pub(crate) fn current_target(&self) -> F { + debug_assert!(self.e_in.len() > 1 || self.e_out.len() > 1); + if self.e_in.len() > 1 { + let remaining = self.e_in.len().trailing_zeros() as usize; + self.low_point[remaining - 1] + } else { + let remaining = self.e_out.len().trailing_zeros() as usize; + self.high_point[remaining - 1] + } + } + + #[inline] + pub(crate) fn eval(&self) -> F { + self.e_in[0] * self.e_out[0] + } + + #[inline] + pub(crate) fn bind(&mut self, challenge: F) { + if self.e_in.len() > 1 { + bind_dense_evals_reuse(&mut self.e_in, &mut self.e_in_scratch, challenge); + } else { + bind_dense_evals_reuse(&mut self.e_out, &mut self.e_out_scratch, challenge); + } + } +} diff --git a/crates/jolt-kernels/src/stage1.rs b/crates/jolt-kernels/src/stage1.rs new file mode 100644 index 0000000000..6414dc72cb --- /dev/null +++ b/crates/jolt-kernels/src/stage1.rs @@ -0,0 +1,2948 @@ +//! Stage 1 outer-sumcheck kernel ABI. + +use std::error::Error; +use std::fmt::{self, Display, Formatter}; + +use jolt_field::{Field, FieldAccumulator}; +use jolt_poly::lagrange::{interpolate_to_coeffs, lagrange_evals, lagrange_kernel_eval}; +use jolt_poly::{EqPolynomial, UnivariatePoly}; +use jolt_r1cs::{constraints::rv64, R1csKey, R1csRowDotSlice, R1csRowDotTable}; +use jolt_sumcheck::SumcheckProof; +use jolt_transcript::{Label, LabelWithCount, Transcript}; +use rayon::prelude::*; + +mod rv64_typed; +pub use rv64_typed::{Stage1OuterRv64Data, Stage1Rv64Cycle}; + +const OUTER_UNISKIP_DOMAIN_SIZE: usize = 10; +const OUTER_UNISKIP_DEGREE: usize = 9; +const OUTER_UNISKIP_EXTENDED_SIZE: usize = 19; +const OUTER_UNISKIP_NUM_COEFFS: usize = 28; +const OUTER_UNISKIP_DEGREE_BOUND: usize = OUTER_UNISKIP_NUM_COEFFS - 1; +const OUTER_UNISKIP_EXTENDED_START: i64 = -(OUTER_UNISKIP_DEGREE as i64); +const OUTER_UNISKIP_BASE_START: i64 = -((OUTER_UNISKIP_DOMAIN_SIZE as i64 - 1) / 2); +const OUTER_REMAINING_DEGREE_BOUND: usize = 3; +const DENSE_BIND_PAR_THRESHOLD: usize = 1024; +const OUTER_FIRST_GROUP_ROWS: [usize; 10] = [1, 2, 3, 4, 5, 6, 11, 14, 17, 18]; +const OUTER_SECOND_GROUP_ROWS: [usize; 9] = [0, 7, 8, 9, 10, 12, 13, 15, 16]; +const OUTER_EQ_CONSTRAINT_ROWS: usize = + OUTER_FIRST_GROUP_ROWS.len() + OUTER_SECOND_GROUP_ROWS.len(); +const OUTER_UNISKIP_TARGET_COEFFS: [[i64; OUTER_UNISKIP_DOMAIN_SIZE]; OUTER_UNISKIP_DEGREE] = [ + [10, -45, 120, -210, 252, -210, 120, -45, 10, -1], + [-1, 10, -45, 120, -210, 252, -210, 120, -45, 10], + [55, -330, 990, -1848, 2310, -1980, 1155, -440, 99, -10], + [-10, 99, -440, 1155, -1980, 2310, -1848, 990, -330, 55], + [ + 220, -1485, 4752, -9240, 11880, -10395, 6160, -2376, 540, -55, + ], + [ + -55, 540, -2376, 6160, -10395, 11880, -9240, 4752, -1485, 220, + ], + [ + 715, -5148, 17160, -34320, 45045, -40040, 24024, -9360, 2145, -220, + ], + [ + -220, 2145, -9360, 24024, -40040, 45045, -34320, 17160, -5148, 715, + ], + [ + 2002, -15015, 51480, -105_105, 140_140, -126_126, 76440, -30030, 6930, -715, + ], +]; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Stage1ExecutionMode { + Prover, + Verifier, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage1Params { + pub field: &'static str, + pub pcs: &'static str, + pub transcript: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage1KernelPlan { + pub symbol: &'static str, + pub relation: &'static str, + pub kind: &'static str, + pub backend: &'static str, + pub abi: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage1SumcheckClaimPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub domain: &'static str, + pub num_rounds: usize, + pub degree: usize, + pub claim: &'static str, + pub kernel: Option<&'static str>, + pub relation: Option<&'static str>, + pub claim_value: &'static str, + pub input_openings: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage1SumcheckBatchPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub proof_slot: &'static str, + pub policy: &'static str, + pub count: usize, + pub ordered_claims: &'static [&'static str], + pub claim_operands: &'static [&'static str], + pub claim_label: &'static str, + pub round_label: &'static str, + pub round_schedule: &'static [usize], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage1SumcheckDriverPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub proof_slot: &'static str, + pub kernel: Option<&'static str>, + pub relation: Option<&'static str>, + pub batch: &'static str, + pub policy: &'static str, + pub round_schedule: &'static [usize], + pub claim_label: &'static str, + pub round_label: &'static str, + pub num_rounds: usize, + pub degree: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage1SumcheckInstanceResultPlan { + pub symbol: &'static str, + pub source: &'static str, + pub claim: &'static str, + pub relation: &'static str, + pub index: usize, + pub point_arity: usize, + pub num_rounds: usize, + pub round_offset: usize, + pub point_order: &'static str, + pub degree: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage1SumcheckEvalPlan { + pub symbol: &'static str, + pub source: &'static str, + pub name: &'static str, + pub index: usize, + pub oracle: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage1OpeningClaimPlan { + pub symbol: &'static str, + pub oracle: &'static str, + pub domain: &'static str, + pub point_arity: usize, + pub claim_kind: &'static str, + pub point_source: &'static str, + pub eval_source: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage1OpeningBatchPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub proof_slot: &'static str, + pub policy: &'static str, + pub count: usize, + pub ordered_claims: &'static [&'static str], + pub claim_operands: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage1TranscriptSqueezePlan { + pub symbol: &'static str, + pub label: &'static str, + pub kind: &'static str, + pub count: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage1CpuProgramPlan { + pub params: Stage1Params, + pub transcript_squeezes: &'static [Stage1TranscriptSqueezePlan], + pub kernels: &'static [Stage1KernelPlan], + pub claims: &'static [Stage1SumcheckClaimPlan], + pub batches: &'static [Stage1SumcheckBatchPlan], + pub drivers: &'static [Stage1SumcheckDriverPlan], + pub instance_results: &'static [Stage1SumcheckInstanceResultPlan], + pub evals: &'static [Stage1SumcheckEvalPlan], + pub opening_claims: &'static [Stage1OpeningClaimPlan], + pub opening_batches: &'static [Stage1OpeningBatchPlan], +} + +impl Stage1CpuProgramPlan { + pub fn evals_for_driver<'a>( + &'a self, + driver: &'a str, + ) -> impl Iterator + 'a { + self.evals.iter().filter(move |eval| eval.source == driver) + } + + pub fn instance_results_for_driver<'a>( + &'a self, + driver: &'a str, + ) -> impl Iterator + 'a { + self.instance_results + .iter() + .filter(move |instance| instance.source == driver) + } +} + +#[derive(Clone, Debug)] +pub struct Stage1NamedEval { + pub name: &'static str, + pub oracle: &'static str, + pub value: F, +} + +#[derive(Clone, Debug)] +pub struct Stage1SumcheckOutput { + pub driver: &'static str, + pub point: Vec, + pub evals: Vec>, + pub proof: SumcheckProof, +} + +#[derive(Clone, Debug)] +pub struct Stage1ChallengeVector { + pub symbol: &'static str, + pub values: Vec, +} + +#[derive(Clone, Debug)] +pub struct Stage1OpeningValue { + pub symbol: &'static str, + pub oracle: &'static str, + pub point: Vec, + pub eval: F, +} + +#[derive(Clone, Debug)] +pub struct Stage1ExecutionArtifacts { + pub challenge_vectors: Vec>, + pub sumchecks: Vec>, + pub opening_values: Vec>, + pub opening_batches: Vec<&'static Stage1OpeningBatchPlan>, +} + +impl Default for Stage1ExecutionArtifacts { + fn default() -> Self { + Self { + challenge_vectors: Vec::new(), + sumchecks: Vec::new(), + opening_values: Vec::new(), + opening_batches: Vec::new(), + } + } +} + +impl Stage1ExecutionArtifacts { + pub fn opening_value(&self, symbol: &str) -> Option<&Stage1OpeningValue> { + self.opening_values + .iter() + .find(|opening| opening.symbol == symbol) + } +} + +#[derive(Clone, Copy, Debug)] +pub struct Stage1OracleData<'a, F: Field> { + pub name: &'static str, + pub evaluations: &'a [F], +} + +#[derive(Clone, Copy, Debug)] +pub struct Stage1OuterRemainingContext<'a, F: Field> { + pub tau: &'a [F], + pub r0: F, +} + +pub type Stage1RemainingRoundProof = Result<(Vec, Vec>), Stage1KernelError>; + +pub trait Stage1OuterRemainingEvaluator: Sync { + fn evaluate(&self, context: Stage1OuterRemainingContext<'_, F>, point: &[F]) -> F; + + fn uniskip_extended_evals(&self, _tau: &[F]) -> Option> { + None + } + + fn evaluate_virtual_oracle( + &self, + _context: Stage1OuterRemainingContext<'_, F>, + _oracle: &str, + _point: &[F], + ) -> Option { + None + } + + fn evaluate_virtual_oracles( + &self, + context: Stage1OuterRemainingContext<'_, F>, + oracles: &[&str], + point: &[F], + ) -> Option> { + oracles + .iter() + .map(|oracle| self.evaluate_virtual_oracle(context, oracle, point)) + .collect() + } + + fn prove_remaining_rounds( + &self, + _context: Stage1OuterRemainingContext<'_, F>, + _num_rounds: usize, + _batching_coeff: F, + _initial_claim: F, + _observe_round: &mut dyn FnMut(&UnivariatePoly) -> F, + ) -> Option> { + None + } +} + +#[derive(Clone, Copy)] +pub struct Stage1ProverInputs<'a, F: Field> { + pub trace_num_vars: usize, + pub virtual_oracles: &'a [Stage1OracleData<'a, F>], + pub uniskip_extended_evals: Option<&'a [F]>, + pub outer_remaining_evaluator: Option<&'a dyn Stage1OuterRemainingEvaluator>, +} + +impl<'a, F: Field> Stage1ProverInputs<'a, F> { + pub fn new(trace_num_vars: usize, virtual_oracles: &'a [Stage1OracleData<'a, F>]) -> Self { + Self { + trace_num_vars, + virtual_oracles, + uniskip_extended_evals: None, + outer_remaining_evaluator: None, + } + } + + pub fn empty(trace_num_vars: usize) -> Self { + Self { + trace_num_vars, + virtual_oracles: &[], + uniskip_extended_evals: None, + outer_remaining_evaluator: None, + } + } + + pub fn with_uniskip_extended_evals(mut self, evaluations: &'a [F]) -> Self { + self.uniskip_extended_evals = Some(evaluations); + self + } + + pub fn with_outer_remaining_evaluator( + mut self, + evaluator: &'a dyn Stage1OuterRemainingEvaluator, + ) -> Self { + self.outer_remaining_evaluator = Some(evaluator); + self + } + + pub fn oracle(&self, name: &str) -> Option<&'a [F]> { + self.virtual_oracles + .iter() + .find(|oracle| oracle.name == name) + .map(|oracle| oracle.evaluations) + } +} + +#[derive(Debug)] +pub struct Stage1OuterR1csData<'a, F: Field> { + pub key: &'a R1csKey, + pub witness: &'a [F], + row_dots: R1csRowDotTable, +} + +impl<'a, F: Field> Stage1OuterR1csData<'a, F> { + #[tracing::instrument(skip_all, name = "Stage1OuterR1csData::new")] + pub fn new(key: &'a R1csKey, witness: &'a [F]) -> Result { + let expected = key.num_cycles * key.num_vars_padded; + if witness.len() != expected { + return Err(Stage1KernelError::InvalidInputLength { + input: "r1cs_witness", + expected, + actual: witness.len(), + }); + } + Ok(Self { + key, + witness, + row_dots: R1csRowDotTable::compute_ab_prefix(key, witness, OUTER_EQ_CONSTRAINT_ROWS), + }) + } + + fn witness_evals(&self, cycle_point: &[F]) -> Vec { + assert_eq!( + cycle_point.len(), + self.key.num_cycle_vars(), + "stage1 cycle point dimension mismatch" + ); + if let Some(cycle) = boolean_index(cycle_point) { + let base = cycle * self.key.num_vars_padded; + return self.witness[base..base + self.key.matrices.num_vars].to_vec(); + } + (0..self.key.matrices.num_vars) + .map(|variable| self.witness_eval(variable, cycle_point)) + .collect() + } + + fn witness_eval(&self, variable: usize, cycle_point: &[F]) -> F { + if let Some(cycle) = boolean_index(cycle_point) { + return self.witness[cycle * self.key.num_vars_padded + variable]; + } + let eq = EqPolynomial::new(cycle_point.to_vec()).evaluations(); + eq.iter() + .take(self.key.num_cycles) + .enumerate() + .fold(F::zero(), |acc, (cycle, &weight)| { + acc + weight * self.witness[cycle * self.key.num_vars_padded + variable] + }) + } + + fn witness_evals_for_variables(&self, variables: &[usize], cycle_point: &[F]) -> Vec { + if let Some(cycle) = boolean_index(cycle_point) { + let base = cycle * self.key.num_vars_padded; + return variables + .iter() + .map(|&variable| self.witness[base + variable]) + .collect(); + } + + let eq = EqPolynomial::new(cycle_point.to_vec()).evaluations(); + let accumulators = eq + .par_iter() + .take(self.key.num_cycles) + .enumerate() + .fold( + || vec![F::Accumulator::default(); variables.len()], + |mut local, (cycle, &weight)| { + let base = cycle * self.key.num_vars_padded; + for (accumulator, &variable) in local.iter_mut().zip(variables) { + accumulator.fmadd(weight, self.witness[base + variable]); + } + local + }, + ) + .reduce( + || vec![F::Accumulator::default(); variables.len()], + |mut left, right| { + for (left, right) in left.iter_mut().zip(right) { + left.merge(right); + } + left + }, + ); + accumulators + .into_iter() + .map(FieldAccumulator::reduce) + .collect() + } + + fn inner_sum_product(&self, r_stream: F, r0: F, witness_evals: &[F]) -> F { + let weights = lagrange_evals(OUTER_UNISKIP_BASE_START, OUTER_UNISKIP_DOMAIN_SIZE, r0); + let (az_g0, bz_g0) = self.group_matvecs(&OUTER_FIRST_GROUP_ROWS, &weights, witness_evals); + let (az_g1, bz_g1) = self.group_matvecs(&OUTER_SECOND_GROUP_ROWS, &weights, witness_evals); + let az = az_g0 + r_stream * (az_g1 - az_g0); + let bz = bz_g0 + r_stream * (bz_g1 - bz_g0); + az * bz + } + + fn group_matvecs(&self, rows: &[usize], weights: &[F], witness_evals: &[F]) -> (F, F) { + let mut az = F::zero(); + let mut bz = F::zero(); + for (&row, &weight) in rows.iter().zip(weights.iter()) { + az += weight * Self::row_dot(&self.key.matrices.a[row], witness_evals); + bz += weight * Self::row_dot(&self.key.matrices.b[row], witness_evals); + } + (az, bz) + } + + fn group_matvecs_from_dots( + rows: &[usize], + weights: &[F], + dots: R1csRowDotSlice<'_, F>, + ) -> (F, F) { + let mut az = F::zero(); + let mut bz = F::zero(); + for (&row, &weight) in rows.iter().zip(weights.iter()) { + az += weight * dots.a[row]; + bz += weight * dots.b[row]; + } + (az, bz) + } + + #[cfg(test)] + fn group_matvecs_from_integer_coeffs( + rows: &[usize], + coefficients: &[i64], + coefficient_fields: &[F], + dots: R1csRowDotSlice<'_, F>, + ) -> (F, F) { + let mut az = F::zero(); + let mut bz = F::zero(); + for ((&row, &coefficient), &coefficient_field) in rows + .iter() + .zip(coefficients.iter()) + .zip(coefficient_fields.iter()) + { + if coefficient == 0 { + continue; + } + let a = dots.a[row]; + if a == F::one() { + az += coefficient_field; + } else if a != F::zero() { + az += a.mul_i64(coefficient); + } + + let b = dots.b[row]; + if b != F::zero() { + bz += b.mul_i64(coefficient); + } + } + (az, bz) + } + + fn group_matvecs_all_uniskip_targets( + rows: &[usize], + target_coeff_fields: &[[F; OUTER_UNISKIP_DOMAIN_SIZE]; OUTER_UNISKIP_DEGREE], + dots: R1csRowDotSlice<'_, F>, + ) -> [(F, F); OUTER_UNISKIP_DEGREE] { + let mut az = [F::zero(); OUTER_UNISKIP_DEGREE]; + let mut bz = [F::zero(); OUTER_UNISKIP_DEGREE]; + for (position, &row) in rows.iter().enumerate() { + let a = dots.a[row]; + let b = dots.b[row]; + if a == F::one() { + for target in 0..OUTER_UNISKIP_DEGREE { + az[target] += target_coeff_fields[target][position]; + } + } else if a != F::zero() { + for target in 0..OUTER_UNISKIP_DEGREE { + az[target] += a.mul_i64(OUTER_UNISKIP_TARGET_COEFFS[target][position]); + } + } + if b != F::zero() { + for target in 0..OUTER_UNISKIP_DEGREE { + bz[target] += b.mul_i64(OUTER_UNISKIP_TARGET_COEFFS[target][position]); + } + } + } + core::array::from_fn(|target| (az[target], bz[target])) + } + + fn row_dot(row: &[(usize, F)], witness_evals: &[F]) -> F { + let mut acc = F::zero(); + for &(variable, coefficient) in row { + acc += coefficient * witness_evals[variable]; + } + acc + } + + fn remaining_cycle_point(point: &[F]) -> Vec { + point[1..].iter().rev().copied().collect() + } + + #[tracing::instrument(skip_all, name = "Stage1OuterR1csData::dense_outer_state")] + fn dense_outer_state( + &self, + context: Stage1OuterRemainingContext<'_, F>, + num_rounds: usize, + batching_coeff: F, + ) -> DenseOuterState { + let tau_high = context.tau[context.tau.len() - 1]; + let tau_low = &context.tau[..context.tau.len() - 1]; + let lagrange_tau_r0 = lagrange_kernel_eval( + OUTER_UNISKIP_BASE_START, + OUTER_UNISKIP_DOMAIN_SIZE, + tau_high, + context.r0, + ); + let weights = lagrange_evals( + OUTER_UNISKIP_BASE_START, + OUTER_UNISKIP_DOMAIN_SIZE, + context.r0, + ); + let len = 1usize << num_rounds; + let scale = lagrange_tau_r0 * batching_coeff; + let eq_evals = EqPolynomial::new(tau_low.to_vec()).evaluations(); + let mut eq = vec![F::zero(); len]; + let mut az = vec![F::zero(); len]; + let mut bz = vec![F::zero(); len]; + eq.par_chunks_mut(2) + .zip(az.par_chunks_mut(2)) + .zip(bz.par_chunks_mut(2)) + .enumerate() + .for_each(|(cycle, ((eq_pair, az_pair), bz_pair))| { + let index = cycle << 1; + let dots = self.row_dots.cycle(cycle); + let (az_g0, bz_g0) = + Self::group_matvecs_from_dots(&OUTER_FIRST_GROUP_ROWS, &weights, dots); + let (az_g1, bz_g1) = + Self::group_matvecs_from_dots(&OUTER_SECOND_GROUP_ROWS, &weights, dots); + eq_pair[0] = eq_evals[index] * scale; + az_pair[0] = az_g0; + bz_pair[0] = bz_g0; + eq_pair[1] = eq_evals[index + 1] * scale; + az_pair[1] = az_g1; + bz_pair[1] = bz_g1; + }); + DenseOuterState { + eq, + az, + bz, + eq_scratch: Vec::with_capacity(len / 2), + az_scratch: Vec::with_capacity(len / 2), + bz_scratch: Vec::with_capacity(len / 2), + } + } +} + +impl Stage1OuterRemainingEvaluator for Stage1OuterR1csData<'_, F> { + fn evaluate(&self, context: Stage1OuterRemainingContext<'_, F>, point: &[F]) -> F { + assert_eq!( + point.len(), + self.key.num_cycle_vars() + 1, + "stage1 outer remaining point dimension mismatch" + ); + assert_eq!( + context.tau.len(), + self.key.num_cycle_vars() + 2, + "stage1 tau dimension mismatch" + ); + let tau_high = context.tau[context.tau.len() - 1]; + let tau_low = &context.tau[..context.tau.len() - 1]; + let mut point_reversed = point.to_vec(); + point_reversed.reverse(); + let tau_weight = EqPolynomial::::mle(tau_low, &point_reversed); + let lagrange_tau_r0 = lagrange_kernel_eval( + OUTER_UNISKIP_BASE_START, + OUTER_UNISKIP_DOMAIN_SIZE, + tau_high, + context.r0, + ); + let cycle_point = Self::remaining_cycle_point(point); + let witness_evals = self.witness_evals(&cycle_point); + lagrange_tau_r0 * tau_weight * self.inner_sum_product(point[0], context.r0, &witness_evals) + } + + #[tracing::instrument(skip_all, name = "Stage1OuterR1csData::uniskip_extended_evals")] + fn uniskip_extended_evals(&self, tau: &[F]) -> Option> { + if tau.len() != self.key.num_cycle_vars() + 2 { + return None; + } + let tau_low = &tau[..tau.len() - 1]; + let num_rounds = self.key.num_cycle_vars() + 1; + let eq_evals = EqPolynomial::new(tau_low.to_vec()).evaluations(); + let num_cycles = 1usize << (num_rounds - 1); + assert_eq!(self.row_dots.cycle_count(), num_cycles); + let target_coeff_fields = + OUTER_UNISKIP_TARGET_COEFFS.map(|coefficients| coefficients.map(F::from_i64)); + let accumulators = (0..num_cycles) + .into_par_iter() + .fold( + || [F::Accumulator::default(); OUTER_UNISKIP_DEGREE], + |mut local, cycle| { + let dots = self.row_dots.cycle(cycle); + let index = cycle << 1; + let first_group = Self::group_matvecs_all_uniskip_targets( + &OUTER_FIRST_GROUP_ROWS, + &target_coeff_fields, + dots, + ); + let second_group = Self::group_matvecs_all_uniskip_targets( + &OUTER_SECOND_GROUP_ROWS, + &target_coeff_fields, + dots, + ); + for target in 0..OUTER_UNISKIP_DEGREE { + let (az_g0, bz_g0) = first_group[target]; + let (az_g1, bz_g1) = second_group[target]; + local[target].fmadd(eq_evals[index], az_g0 * bz_g0); + local[target].fmadd(eq_evals[index + 1], az_g1 * bz_g1); + } + local + }, + ) + .reduce( + || [F::Accumulator::default(); OUTER_UNISKIP_DEGREE], + |mut left, right| { + for target in 0..OUTER_UNISKIP_DEGREE { + left[target].merge(right[target]); + } + left + }, + ); + let extended_evals = accumulators.map(FieldAccumulator::reduce).to_vec(); + Some(extended_evals) + } + + fn evaluate_virtual_oracle( + &self, + _context: Stage1OuterRemainingContext<'_, F>, + oracle: &str, + point: &[F], + ) -> Option { + let variable = r1cs_oracle_variable(oracle)?; + let cycle_point = Self::remaining_cycle_point(point); + Some(self.witness_eval(variable, &cycle_point)) + } + + #[tracing::instrument(skip_all, name = "Stage1OuterR1csData::evaluate_virtual_oracles")] + fn evaluate_virtual_oracles( + &self, + _context: Stage1OuterRemainingContext<'_, F>, + oracles: &[&str], + point: &[F], + ) -> Option> { + let variables = oracles + .iter() + .map(|oracle| r1cs_oracle_variable(oracle)) + .collect::>>()?; + let cycle_point = Self::remaining_cycle_point(point); + Some(self.witness_evals_for_variables(&variables, &cycle_point)) + } + + #[tracing::instrument(skip_all, name = "Stage1OuterR1csData::prove_remaining_rounds")] + fn prove_remaining_rounds( + &self, + context: Stage1OuterRemainingContext<'_, F>, + num_rounds: usize, + batching_coeff: F, + initial_claim: F, + observe_round: &mut dyn FnMut(&UnivariatePoly) -> F, + ) -> Option> { + let mut state = self.dense_outer_state(context, num_rounds, batching_coeff); + let mut running_sum = initial_claim * batching_coeff; + let mut point = Vec::with_capacity(num_rounds); + let mut round_polynomials = Vec::with_capacity(num_rounds); + + for _round in 0..num_rounds { + let poly = state.round_poly(); + if poly.evaluate(F::zero()) + poly.evaluate(F::one()) != running_sum { + return Some(Err(Stage1KernelError::InvalidProof { + driver: "stage1.outer.remaining", + reason: "dense outer remaining claim mismatch", + })); + } + let challenge = observe_round(&poly); + running_sum = poly.evaluate(challenge); + state.bind(challenge); + point.push(challenge); + round_polynomials.push(poly); + } + Some(Ok((point, round_polynomials))) + } +} + +#[derive(Clone, Debug, Default)] +pub struct Stage1Proof { + pub sumchecks: Vec>, +} + +impl From> for Stage1Proof { + fn from(artifacts: Stage1ExecutionArtifacts) -> Self { + Self { + sumchecks: artifacts.sumchecks, + } + } +} + +#[derive(Clone, Copy, Debug)] +pub struct Stage1KernelContext<'a> { + pub mode: Stage1ExecutionMode, + pub program: &'a Stage1CpuProgramPlan, + pub kernel: &'a Stage1KernelPlan, + pub batch: &'a Stage1SumcheckBatchPlan, + pub driver: &'a Stage1SumcheckDriverPlan, +} + +pub trait Stage1KernelExecutor { + fn observe_challenge_vector( + &mut self, + _plan: &'static Stage1TranscriptSqueezePlan, + _values: &[F], + ) -> Result<(), Stage1KernelError> { + Ok(()) + } + + fn observe_sumcheck_output( + &mut self, + _output: &Stage1SumcheckOutput, + ) -> Result<(), Stage1KernelError> { + Ok(()) + } + + fn prove_sumcheck( + &mut self, + context: Stage1KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage1KernelError> + where + T: Transcript; + + fn verify_sumcheck( + &mut self, + context: Stage1KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage1KernelError> + where + T: Transcript; +} + +#[derive(Clone, Debug, Default)] +pub struct UnsupportedStage1KernelExecutor; + +impl Stage1KernelExecutor for UnsupportedStage1KernelExecutor { + fn prove_sumcheck( + &mut self, + context: Stage1KernelContext<'_>, + _transcript: &mut T, + ) -> Result, Stage1KernelError> + where + T: Transcript, + { + Err(Stage1KernelError::KernelNotImplemented { + abi: context.kernel.abi, + }) + } + + fn verify_sumcheck( + &mut self, + context: Stage1KernelContext<'_>, + _transcript: &mut T, + ) -> Result, Stage1KernelError> + where + T: Transcript, + { + Err(Stage1KernelError::KernelNotImplemented { + abi: context.kernel.abi, + }) + } +} + +#[derive(Clone, Debug, Default)] +pub struct Stage1ShapeKernelExecutor; + +impl Stage1KernelExecutor for Stage1ShapeKernelExecutor { + fn prove_sumcheck( + &mut self, + context: Stage1KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage1KernelError> + where + T: Transcript, + { + run_shape_kernel(context, transcript) + } + + fn verify_sumcheck( + &mut self, + context: Stage1KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage1KernelError> + where + T: Transcript, + { + run_shape_kernel(context, transcript) + } +} + +#[derive(Clone)] +pub struct Stage1ProverKernelExecutor<'a, F: Field> { + pub inputs: Stage1ProverInputs<'a, F>, + challenge_vectors: Vec>, + completed_sumchecks: Vec>, +} + +impl<'a, F: Field> Stage1ProverKernelExecutor<'a, F> { + pub fn new(inputs: Stage1ProverInputs<'a, F>) -> Self { + Self { + inputs, + challenge_vectors: Vec::new(), + completed_sumchecks: Vec::new(), + } + } +} + +impl Stage1KernelExecutor for Stage1ProverKernelExecutor<'_, F> { + fn observe_challenge_vector( + &mut self, + plan: &'static Stage1TranscriptSqueezePlan, + values: &[F], + ) -> Result<(), Stage1KernelError> { + self.challenge_vectors.push(Stage1ChallengeVector { + symbol: plan.symbol, + values: values.to_vec(), + }); + Ok(()) + } + + fn observe_sumcheck_output( + &mut self, + output: &Stage1SumcheckOutput, + ) -> Result<(), Stage1KernelError> { + self.completed_sumchecks.push(output.clone()); + Ok(()) + } + + fn prove_sumcheck( + &mut self, + context: Stage1KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage1KernelError> + where + T: Transcript, + { + prove_stage1_kernel( + context, + &self.inputs, + &self.challenge_vectors, + &self.completed_sumchecks, + transcript, + ) + } + + fn verify_sumcheck( + &mut self, + context: Stage1KernelContext<'_>, + _transcript: &mut T, + ) -> Result, Stage1KernelError> + where + T: Transcript, + { + Err(Stage1KernelError::WrongExecutorMode { + driver: context.driver.symbol, + expected: Stage1ExecutionMode::Prover, + actual: Stage1ExecutionMode::Verifier, + }) + } +} + +#[derive(Clone, Debug)] +pub struct Stage1VerifierKernelExecutor<'a, F: Field> { + pub proof: &'a Stage1Proof, + pub cursor: usize, + challenge_vectors: Vec>, + completed_sumchecks: Vec>, +} + +impl<'a, F: Field> Stage1VerifierKernelExecutor<'a, F> { + pub fn new(proof: &'a Stage1Proof) -> Self { + Self { + proof, + cursor: 0, + challenge_vectors: Vec::new(), + completed_sumchecks: Vec::new(), + } + } +} + +impl Stage1KernelExecutor for Stage1VerifierKernelExecutor<'_, F> { + fn observe_challenge_vector( + &mut self, + plan: &'static Stage1TranscriptSqueezePlan, + values: &[F], + ) -> Result<(), Stage1KernelError> { + self.challenge_vectors.push(Stage1ChallengeVector { + symbol: plan.symbol, + values: values.to_vec(), + }); + Ok(()) + } + + fn observe_sumcheck_output( + &mut self, + output: &Stage1SumcheckOutput, + ) -> Result<(), Stage1KernelError> { + self.completed_sumchecks.push(output.clone()); + Ok(()) + } + + fn prove_sumcheck( + &mut self, + context: Stage1KernelContext<'_>, + _transcript: &mut T, + ) -> Result, Stage1KernelError> + where + T: Transcript, + { + Err(Stage1KernelError::WrongExecutorMode { + driver: context.driver.symbol, + expected: Stage1ExecutionMode::Verifier, + actual: Stage1ExecutionMode::Prover, + }) + } + + fn verify_sumcheck( + &mut self, + context: Stage1KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage1KernelError> + where + T: Transcript, + { + let proof = self.proof.sumchecks.get(self.cursor); + self.cursor += usize::from(proof.is_some()); + verify_stage1_kernel( + context, + proof, + &self.challenge_vectors, + &self.completed_sumchecks, + transcript, + ) + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum Stage1KernelError { + MissingKernel { + driver: &'static str, + kernel: &'static str, + }, + MissingBatch { + driver: &'static str, + batch: &'static str, + }, + PlanCountMismatch { + artifact: &'static str, + expected: usize, + actual: usize, + }, + KernelNotImplemented { + abi: &'static str, + }, + WrongExecutorMode { + driver: &'static str, + expected: Stage1ExecutionMode, + actual: Stage1ExecutionMode, + }, + MissingProof { + driver: &'static str, + }, + MissingKernelInput { + kernel: &'static str, + input: &'static str, + }, + InvalidInputLength { + input: &'static str, + expected: usize, + actual: usize, + }, + UnsupportedPointOrder { + symbol: &'static str, + point_order: &'static str, + }, + InvalidProof { + driver: &'static str, + reason: &'static str, + }, +} + +impl Display for Stage1KernelError { + fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result { + match self { + Self::MissingKernel { driver, kernel } => { + write!( + formatter, + "stage1 driver @{driver} references missing kernel @{kernel}" + ) + } + Self::MissingBatch { driver, batch } => { + write!( + formatter, + "stage1 driver @{driver} references missing batch @{batch}" + ) + } + Self::PlanCountMismatch { + artifact, + expected, + actual, + } => write!( + formatter, + "stage1 plan @{artifact} count mismatch: expected {expected}, got {actual}" + ), + Self::KernelNotImplemented { abi } => { + write!(formatter, "stage1 kernel ABI `{abi}` is not implemented") + } + Self::WrongExecutorMode { + driver, + expected, + actual, + } => write!( + formatter, + "stage1 driver @{driver} ran with {actual:?} executor path, expected {expected:?}" + ), + Self::MissingProof { driver } => { + write!( + formatter, + "stage1 verifier missing proof for driver @{driver}" + ) + } + Self::MissingKernelInput { kernel, input } => { + write!( + formatter, + "stage1 kernel `{kernel}` missing input `{input}`" + ) + } + Self::InvalidInputLength { + input, + expected, + actual, + } => write!( + formatter, + "stage1 input `{input}` length mismatch: expected {expected}, got {actual}" + ), + Self::UnsupportedPointOrder { + symbol, + point_order, + } => write!( + formatter, + "stage1 instance @{symbol} uses unsupported point order `{point_order}`" + ), + Self::InvalidProof { driver, reason } => { + write!( + formatter, + "stage1 proof for driver @{driver} is invalid: {reason}" + ) + } + } + } +} + +impl Error for Stage1KernelError {} + +pub fn execute_stage1_program( + program: &'static Stage1CpuProgramPlan, + mode: Stage1ExecutionMode, + executor: &mut E, + transcript: &mut T, +) -> Result, Stage1KernelError> +where + F: Field, + E: Stage1KernelExecutor, + T: Transcript, +{ + verify_static_program_shape(program)?; + let mut artifacts = Stage1ExecutionArtifacts::default(); + for squeeze in program.transcript_squeezes { + let values = transcript.challenge_vector(squeeze.count); + executor.observe_challenge_vector(squeeze, &values)?; + artifacts.challenge_vectors.push(Stage1ChallengeVector { + symbol: squeeze.symbol, + values, + }); + } + for driver in program.drivers { + let kernel_symbol = driver.kernel.ok_or(Stage1KernelError::MissingKernel { + driver: driver.symbol, + kernel: "", + })?; + let kernel = + find_kernel(program, kernel_symbol).ok_or(Stage1KernelError::MissingKernel { + driver: driver.symbol, + kernel: kernel_symbol, + })?; + let batch = find_batch(program, driver.batch).ok_or(Stage1KernelError::MissingBatch { + driver: driver.symbol, + batch: driver.batch, + })?; + let context = Stage1KernelContext { + mode, + program, + kernel, + batch, + driver, + }; + let output = match mode { + Stage1ExecutionMode::Prover => executor.prove_sumcheck(context, transcript)?, + Stage1ExecutionMode::Verifier => executor.verify_sumcheck(context, transcript)?, + }; + executor.observe_sumcheck_output(&output)?; + artifacts.sumchecks.push(output); + } + artifacts + .opening_batches + .extend(program.opening_batches.iter()); + artifacts.opening_values = stage1_opening_values(program, &artifacts.sumchecks)?; + Ok(artifacts) +} + +fn stage1_opening_values( + program: &'static Stage1CpuProgramPlan, + sumchecks: &[Stage1SumcheckOutput], +) -> Result>, Stage1KernelError> { + let mut points = Vec::>::new(); + let mut scalars = Vec::>::new(); + for output in sumchecks { + points.push(Stage1PointValue { + symbol: output.driver, + point: output.point.clone(), + }); + for instance in program.instance_results_for_driver(output.driver) { + points.push(Stage1PointValue { + symbol: instance.symbol, + point: stage1_instance_point(instance, &output.point)?, + }); + } + for eval in program.evals_for_driver(output.driver) { + let value = output + .evals + .iter() + .find(|value| value.name == eval.name) + .or_else(|| output.evals.get(eval.index)) + .ok_or(Stage1KernelError::MissingKernelInput { + kernel: output.driver, + input: eval.symbol, + })? + .value; + scalars.push(Stage1ScalarValue { + symbol: eval.symbol, + value, + }); + scalars.push(Stage1ScalarValue { + symbol: eval.name, + value, + }); + } + } + program + .opening_claims + .iter() + .map(|claim| { + let point = points + .iter() + .find(|point| point.symbol == claim.point_source) + .ok_or(Stage1KernelError::MissingKernelInput { + kernel: claim.symbol, + input: claim.point_source, + })? + .point + .clone(); + let eval = scalars + .iter() + .find(|scalar| scalar.symbol == claim.eval_source) + .ok_or(Stage1KernelError::MissingKernelInput { + kernel: claim.symbol, + input: claim.eval_source, + })? + .value; + Ok(Stage1OpeningValue { + symbol: claim.symbol, + oracle: claim.oracle, + point, + eval, + }) + }) + .collect() +} + +fn stage1_instance_point( + instance: &Stage1SumcheckInstanceResultPlan, + point: &[F], +) -> Result, Stage1KernelError> { + let end = instance.round_offset + instance.point_arity; + let mut point = point + .get(instance.round_offset..end) + .ok_or(Stage1KernelError::InvalidInputLength { + input: instance.symbol, + expected: end, + actual: point.len(), + })? + .to_vec(); + match instance.point_order { + "as_is" => Ok(point), + "reverse" => { + point.reverse(); + Ok(point) + } + point_order => Err(Stage1KernelError::UnsupportedPointOrder { + symbol: instance.symbol, + point_order, + }), + } +} + +#[derive(Clone, Debug)] +struct Stage1PointValue { + symbol: &'static str, + point: Vec, +} + +#[derive(Clone, Copy, Debug)] +struct Stage1ScalarValue { + symbol: &'static str, + value: F, +} + +fn verify_static_program_shape( + program: &'static Stage1CpuProgramPlan, +) -> Result<(), Stage1KernelError> { + for batch in program.batches { + verify_count(batch.symbol, batch.count, batch.ordered_claims.len())?; + verify_count(batch.symbol, batch.count, batch.claim_operands.len())?; + } + for batch in program.opening_batches { + verify_count(batch.symbol, batch.count, batch.ordered_claims.len())?; + verify_count(batch.symbol, batch.count, batch.claim_operands.len())?; + } + Ok(()) +} + +fn verify_count( + artifact: &'static str, + expected: usize, + actual: usize, +) -> Result<(), Stage1KernelError> { + if expected == actual { + Ok(()) + } else { + Err(Stage1KernelError::PlanCountMismatch { + artifact, + expected, + actual, + }) + } +} + +fn find_kernel( + program: &'static Stage1CpuProgramPlan, + symbol: &str, +) -> Option<&'static Stage1KernelPlan> { + program + .kernels + .iter() + .find(|kernel| kernel.symbol == symbol) +} + +fn find_batch( + program: &'static Stage1CpuProgramPlan, + symbol: &str, +) -> Option<&'static Stage1SumcheckBatchPlan> { + program.batches.iter().find(|batch| batch.symbol == symbol) +} + +fn prove_stage1_kernel( + context: Stage1KernelContext<'_>, + inputs: &Stage1ProverInputs<'_, F>, + challenge_vectors: &[Stage1ChallengeVector], + completed_sumchecks: &[Stage1SumcheckOutput], + transcript: &mut T, +) -> Result, Stage1KernelError> +where + F: Field, + T: Transcript, +{ + match context.kernel.abi { + "jolt_stage1_outer_uniskip" => { + prove_outer_uniskip(context, inputs, challenge_vectors, transcript) + } + "jolt_stage1_outer_remaining" => prove_outer_remaining( + context, + inputs, + challenge_vectors, + completed_sumchecks, + transcript, + ), + abi => Err(Stage1KernelError::KernelNotImplemented { abi }), + } +} + +fn verify_stage1_kernel( + context: Stage1KernelContext<'_>, + proof: Option<&Stage1SumcheckOutput>, + challenge_vectors: &[Stage1ChallengeVector], + completed_sumchecks: &[Stage1SumcheckOutput], + transcript: &mut T, +) -> Result, Stage1KernelError> +where + F: Field, + T: Transcript, +{ + match context.kernel.abi { + "jolt_stage1_outer_uniskip" => { + verify_outer_uniskip(context, proof, challenge_vectors, transcript) + } + "jolt_stage1_outer_remaining" => { + verify_outer_remaining(context, proof, completed_sumchecks, transcript) + } + abi => Err(Stage1KernelError::KernelNotImplemented { abi }), + } +} + +#[tracing::instrument(skip_all, name = "prove_outer_uniskip")] +fn prove_outer_uniskip( + context: Stage1KernelContext<'_>, + inputs: &Stage1ProverInputs<'_, F>, + challenge_vectors: &[Stage1ChallengeVector], + transcript: &mut T, +) -> Result, Stage1KernelError> +where + F: Field, + T: Transcript, +{ + let tau = find_challenge_vector(challenge_vectors, "stage1.tau").ok_or( + Stage1KernelError::MissingKernelInput { + kernel: context.kernel.abi, + input: "stage1.tau", + }, + )?; + let tau_high = tau + .last() + .copied() + .ok_or(Stage1KernelError::InvalidInputLength { + input: "stage1.tau", + expected: 1, + actual: 0, + })?; + let owned_extended_evals; + let extended_evals = if let Some(extended_evals) = inputs.uniskip_extended_evals { + extended_evals + } else { + let evaluator = + inputs + .outer_remaining_evaluator + .ok_or(Stage1KernelError::MissingKernelInput { + kernel: context.kernel.abi, + input: "uniskip_extended_evals", + })?; + owned_extended_evals = + evaluator + .uniskip_extended_evals(tau) + .ok_or(Stage1KernelError::MissingKernelInput { + kernel: context.kernel.abi, + input: "uniskip_extended_evals", + })?; + owned_extended_evals.as_slice() + }; + let poly = build_outer_uniskip_poly(extended_evals, tau_high)?; + append_univariate_poly(transcript, context.driver.round_label, &poly); + let r0 = transcript.challenge(); + let eval = poly.evaluate(r0); + append_labeled_scalar(transcript, "opening_claim", &eval); + Ok(Stage1SumcheckOutput { + driver: context.driver.symbol, + point: vec![r0], + evals: driver_evals(context, eval), + proof: SumcheckProof { + round_polynomials: vec![poly], + }, + }) +} + +#[tracing::instrument(skip_all, name = "prove_outer_remaining")] +fn prove_outer_remaining( + context: Stage1KernelContext<'_>, + inputs: &Stage1ProverInputs<'_, F>, + challenge_vectors: &[Stage1ChallengeVector], + completed_sumchecks: &[Stage1SumcheckOutput], + transcript: &mut T, +) -> Result, Stage1KernelError> +where + F: Field, + T: Transcript, +{ + let evaluator = + inputs + .outer_remaining_evaluator + .ok_or(Stage1KernelError::MissingKernelInput { + kernel: context.kernel.abi, + input: "outer_remaining_evaluator", + })?; + let tau = find_challenge_vector(challenge_vectors, "stage1.tau").ok_or( + Stage1KernelError::MissingKernelInput { + kernel: context.kernel.abi, + input: "stage1.tau", + }, + )?; + let (r0, input_claim) = uniskip_point_and_claim(completed_sumchecks).ok_or( + Stage1KernelError::MissingKernelInput { + kernel: context.kernel.abi, + input: "stage1.uniskip.eval", + }, + )?; + let remaining_context = Stage1OuterRemainingContext { tau, r0 }; + append_labeled_scalar(transcript, context.driver.claim_label, &input_claim); + let batching_coeff = transcript.challenge(); + let fast_path = evaluator.prove_remaining_rounds( + remaining_context, + context.driver.num_rounds, + batching_coeff, + input_claim, + &mut |poly| { + append_compressed_univariate_poly(transcript, context.driver.round_label, poly); + transcript.challenge() + }, + ); + let (point, round_polynomials) = if let Some(result) = fast_path { + result? + } else { + prove_outer_remaining_fallback( + context, + evaluator, + remaining_context, + batching_coeff, + input_claim, + transcript, + )? + }; + + let evals = remaining_driver_evals(context, evaluator, remaining_context, &point)?; + append_opening_claims(transcript, &evals); + Ok(Stage1SumcheckOutput { + driver: context.driver.symbol, + point, + evals, + proof: SumcheckProof { round_polynomials }, + }) +} + +fn verify_outer_uniskip( + context: Stage1KernelContext<'_>, + proof: Option<&Stage1SumcheckOutput>, + _challenge_vectors: &[Stage1ChallengeVector], + transcript: &mut T, +) -> Result, Stage1KernelError> +where + F: Field, + T: Transcript, +{ + let Some(proof) = proof else { + return Err(Stage1KernelError::MissingProof { + driver: context.driver.symbol, + }); + }; + if proof.driver != context.driver.symbol { + return Err(Stage1KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "driver symbol mismatch", + }); + } + let Some(poly) = proof.proof.round_polynomials.first() else { + return Err(Stage1KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "missing uniskip round polynomial", + }); + }; + if proof.proof.round_polynomials.len() != 1 { + return Err(Stage1KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "unexpected uniskip round count", + }); + } + if polynomial_degree(poly) > OUTER_UNISKIP_DEGREE_BOUND { + return Err(Stage1KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "uniskip polynomial exceeds degree bound", + }); + } + append_univariate_poly(transcript, context.driver.round_label, poly); + let r0 = transcript.challenge(); + if !uniskip_sum_matches(poly, F::zero()) { + return Err(Stage1KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "uniskip polynomial sum check failed", + }); + } + let eval = poly.evaluate(r0); + if !proof.point.is_empty() && (proof.point.len() != 1 || proof.point[0] != r0) { + return Err(Stage1KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "uniskip point mismatch", + }); + } + validate_eval_shape(context, &proof.evals, Some(eval))?; + append_labeled_scalar(transcript, "opening_claim", &eval); + Ok(Stage1SumcheckOutput { + driver: context.driver.symbol, + point: vec![r0], + evals: driver_evals(context, eval), + proof: proof.proof.clone(), + }) +} + +fn verify_outer_remaining( + context: Stage1KernelContext<'_>, + proof: Option<&Stage1SumcheckOutput>, + completed_sumchecks: &[Stage1SumcheckOutput], + transcript: &mut T, +) -> Result, Stage1KernelError> +where + F: Field, + T: Transcript, +{ + let Some(proof) = proof else { + return Err(Stage1KernelError::MissingProof { + driver: context.driver.symbol, + }); + }; + if proof.driver != context.driver.symbol { + return Err(Stage1KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "driver symbol mismatch", + }); + } + if proof.proof.round_polynomials.len() != context.driver.num_rounds { + return Err(Stage1KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "unexpected outer remaining round count", + }); + } + let input_claim = + uniskip_output_claim(completed_sumchecks).ok_or(Stage1KernelError::MissingKernelInput { + kernel: context.kernel.abi, + input: "stage1.uniskip.eval", + })?; + append_labeled_scalar(transcript, context.driver.claim_label, &input_claim); + let batching_coeff = transcript.challenge(); + let mut running_sum = input_claim * batching_coeff; + let mut point = Vec::with_capacity(context.driver.num_rounds); + + for poly in &proof.proof.round_polynomials { + if polynomial_degree(poly) > OUTER_REMAINING_DEGREE_BOUND { + return Err(Stage1KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "outer remaining polynomial exceeds degree bound", + }); + } + if poly.evaluate(F::zero()) + poly.evaluate(F::one()) != running_sum { + return Err(Stage1KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "outer remaining round check failed", + }); + } + append_compressed_univariate_poly(transcript, context.driver.round_label, poly); + let challenge = transcript.challenge(); + running_sum = poly.evaluate(challenge); + point.push(challenge); + } + if !proof.point.is_empty() && proof.point != point { + return Err(Stage1KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "outer remaining point mismatch", + }); + } + validate_eval_shape(context, &proof.evals, None)?; + append_opening_claims(transcript, &proof.evals); + Ok(Stage1SumcheckOutput { + driver: context.driver.symbol, + point, + evals: proof.evals.clone(), + proof: proof.proof.clone(), + }) +} + +fn prove_outer_remaining_fallback( + context: Stage1KernelContext<'_>, + evaluator: &dyn Stage1OuterRemainingEvaluator, + remaining_context: Stage1OuterRemainingContext<'_, F>, + batching_coeff: F, + input_claim: F, + transcript: &mut T, +) -> Result<(Vec, Vec>), Stage1KernelError> +where + F: Field, + T: Transcript, +{ + let mut running_sum = input_claim * batching_coeff; + let mut point = Vec::with_capacity(context.driver.num_rounds); + let mut round_polynomials = Vec::with_capacity(context.driver.num_rounds); + for _round in 0..context.driver.num_rounds { + let poly = outer_remaining_round_poly( + evaluator, + remaining_context, + context.driver.num_rounds, + &point, + ); + let scaled_poly = scale_poly(&poly, batching_coeff); + if scaled_poly.evaluate(F::zero()) + scaled_poly.evaluate(F::one()) != running_sum { + return Err(Stage1KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "outer remaining prover claim mismatch", + }); + } + append_compressed_univariate_poly(transcript, context.driver.round_label, &scaled_poly); + let challenge = transcript.challenge(); + running_sum = scaled_poly.evaluate(challenge); + point.push(challenge); + round_polynomials.push(scaled_poly); + } + Ok((point, round_polynomials)) +} + +fn find_challenge_vector<'a, F: Field>( + challenges: &'a [Stage1ChallengeVector], + symbol: &str, +) -> Option<&'a [F]> { + challenges + .iter() + .find(|challenge| challenge.symbol == symbol) + .map(|challenge| challenge.values.as_slice()) +} + +fn build_outer_uniskip_poly( + extended_evals: &[F], + tau_high: F, +) -> Result, Stage1KernelError> { + if extended_evals.len() != OUTER_UNISKIP_DEGREE { + return Err(Stage1KernelError::InvalidInputLength { + input: "uniskip_extended_evals", + expected: OUTER_UNISKIP_DEGREE, + actual: extended_evals.len(), + }); + } + + let mut t1_values = vec![F::zero(); OUTER_UNISKIP_EXTENDED_SIZE]; + for (value, target) in extended_evals.iter().zip(outer_uniskip_targets()) { + let index = (target - OUTER_UNISKIP_EXTENDED_START) as usize; + t1_values[index] = *value; + } + + let t1_coeffs = interpolate_to_coeffs(OUTER_UNISKIP_EXTENDED_START, &t1_values); + let lagrange_values = lagrange_evals( + OUTER_UNISKIP_BASE_START, + OUTER_UNISKIP_DOMAIN_SIZE, + tau_high, + ); + let lagrange_coeffs = interpolate_to_coeffs(OUTER_UNISKIP_BASE_START, &lagrange_values); + + let mut coefficients = vec![F::zero(); OUTER_UNISKIP_NUM_COEFFS]; + for (i, &lagrange_coeff) in lagrange_coeffs.iter().enumerate() { + for (j, &t1_coeff) in t1_coeffs.iter().enumerate() { + coefficients[i + j] += lagrange_coeff * t1_coeff; + } + } + Ok(UnivariatePoly::new(coefficients)) +} + +/// Returns the off-domain targets used by the Stage 1 outer univariate-skip +/// round polynomial. +pub fn outer_uniskip_targets() -> [i64; OUTER_UNISKIP_DEGREE] { + let ext_left = OUTER_UNISKIP_EXTENDED_START; + let ext_right = OUTER_UNISKIP_DEGREE as i64; + let base_left = OUTER_UNISKIP_BASE_START; + let base_right = base_left + OUTER_UNISKIP_DOMAIN_SIZE as i64 - 1; + let mut targets = [0i64; OUTER_UNISKIP_DEGREE]; + let mut index = 0; + let mut negative = base_left - 1; + let mut positive = base_right + 1; + while negative >= ext_left && positive <= ext_right && index < OUTER_UNISKIP_DEGREE { + targets[index] = negative; + index += 1; + if index >= OUTER_UNISKIP_DEGREE { + break; + } + targets[index] = positive; + index += 1; + negative -= 1; + positive += 1; + } + while index < OUTER_UNISKIP_DEGREE && negative >= ext_left { + targets[index] = negative; + index += 1; + negative -= 1; + } + while index < OUTER_UNISKIP_DEGREE && positive <= ext_right { + targets[index] = positive; + index += 1; + positive += 1; + } + targets +} + +/// Recovers the Stage 1 outer univariate-skip extended evaluations from a +/// first-round proof polynomial. +pub fn outer_uniskip_extended_evals_from_round_poly( + round_poly: &UnivariatePoly, + tau_high: F, +) -> Vec { + outer_uniskip_targets() + .into_iter() + .map(|target| { + let y = F::from_i64(target); + let kernel = lagrange_kernel_eval( + OUTER_UNISKIP_BASE_START, + OUTER_UNISKIP_DOMAIN_SIZE, + tau_high, + y, + ); + round_poly.evaluate(y) / kernel + }) + .collect() +} + +fn boolean_index(point: &[F]) -> Option { + let mut index = 0usize; + for value in point { + index <<= 1; + if *value == F::one() { + index |= 1; + } else if *value != F::zero() { + return None; + } + } + Some(index) +} + +fn r1cs_oracle_variable(oracle: &str) -> Option { + match oracle { + "LeftInstructionInput" => Some(rv64::V_LEFT_INSTRUCTION_INPUT), + "RightInstructionInput" => Some(rv64::V_RIGHT_INSTRUCTION_INPUT), + "Product" => Some(rv64::V_PRODUCT), + "ShouldBranch" => Some(rv64::V_SHOULD_BRANCH), + "PC" => Some(rv64::V_PC), + "UnexpandedPC" => Some(rv64::V_UNEXPANDED_PC), + "Imm" => Some(rv64::V_IMM), + "RamAddress" => Some(rv64::V_RAM_ADDRESS), + "Rs1Value" => Some(rv64::V_RS1_VALUE), + "Rs2Value" => Some(rv64::V_RS2_VALUE), + "RdWriteValue" => Some(rv64::V_RD_WRITE_VALUE), + "RamReadValue" => Some(rv64::V_RAM_READ_VALUE), + "RamWriteValue" => Some(rv64::V_RAM_WRITE_VALUE), + "LeftLookupOperand" => Some(rv64::V_LEFT_LOOKUP_OPERAND), + "RightLookupOperand" => Some(rv64::V_RIGHT_LOOKUP_OPERAND), + "NextUnexpandedPC" => Some(rv64::V_NEXT_UNEXPANDED_PC), + "NextPC" => Some(rv64::V_NEXT_PC), + "NextIsVirtual" => Some(rv64::V_NEXT_IS_VIRTUAL), + "NextIsFirstInSequence" => Some(rv64::V_NEXT_IS_FIRST_IN_SEQUENCE), + "LookupOutput" => Some(rv64::V_LOOKUP_OUTPUT), + "ShouldJump" => Some(rv64::V_SHOULD_JUMP), + "OpFlagAddOperands" => Some(rv64::V_FLAG_ADD_OPERANDS), + "OpFlagSubtractOperands" => Some(rv64::V_FLAG_SUBTRACT_OPERANDS), + "OpFlagMultiplyOperands" => Some(rv64::V_FLAG_MULTIPLY_OPERANDS), + "OpFlagLoad" => Some(rv64::V_FLAG_LOAD), + "OpFlagStore" => Some(rv64::V_FLAG_STORE), + "OpFlagJump" => Some(rv64::V_FLAG_JUMP), + "OpFlagWriteLookupOutputToRD" => Some(rv64::V_FLAG_WRITE_LOOKUP_OUTPUT_TO_RD), + "OpFlagVirtualInstruction" => Some(rv64::V_FLAG_VIRTUAL_INSTRUCTION), + "OpFlagAssert" => Some(rv64::V_FLAG_ASSERT), + "OpFlagDoNotUpdateUnexpandedPC" => Some(rv64::V_FLAG_DO_NOT_UPDATE_UNEXPANDED_PC), + "OpFlagAdvice" => Some(rv64::V_FLAG_ADVICE), + "OpFlagIsCompressed" => Some(rv64::V_FLAG_IS_COMPRESSED), + "OpFlagIsFirstInSequence" => Some(rv64::V_FLAG_IS_FIRST_IN_SEQUENCE), + "OpFlagIsLastInSequence" => Some(rv64::V_FLAG_IS_LAST_IN_SEQUENCE), + _ => None, + } +} + +fn append_univariate_poly(transcript: &mut T, label: &'static str, poly: &UnivariatePoly) +where + F: Field, + T: Transcript, +{ + transcript.append(&LabelWithCount( + label.as_bytes(), + poly.coefficients().len() as u64, + )); + for coefficient in poly.coefficients() { + transcript.append(coefficient); + } +} + +fn append_compressed_univariate_poly( + transcript: &mut T, + label: &'static str, + poly: &UnivariatePoly, +) where + F: Field, + T: Transcript, +{ + let compressed = poly.compress(); + transcript.append(&LabelWithCount( + label.as_bytes(), + compressed.coeffs_except_linear_term().len() as u64, + )); + for coefficient in compressed.coeffs_except_linear_term() { + transcript.append(coefficient); + } +} + +fn append_labeled_scalar(transcript: &mut T, label: &'static str, scalar: &F) +where + F: Field, + T: Transcript, +{ + transcript.append(&Label(label.as_bytes())); + transcript.append(scalar); +} + +fn append_opening_claims(transcript: &mut T, evals: &[Stage1NamedEval]) +where + F: Field, + T: Transcript, +{ + for eval in evals { + append_labeled_scalar(transcript, "opening_claim", &eval.value); + } +} + +struct DenseOuterState { + eq: Vec, + az: Vec, + bz: Vec, + eq_scratch: Vec, + az_scratch: Vec, + bz_scratch: Vec, +} + +impl DenseOuterState { + #[tracing::instrument(skip_all, name = "DenseOuterState::round_poly")] + fn round_poly(&self) -> UnivariatePoly { + let pair_count = self.eq.len() / 2; + let accumulators = if pair_count >= DENSE_BIND_PAR_THRESHOLD { + self.eq + .par_chunks_exact(2) + .zip(self.az.par_chunks_exact(2)) + .zip(self.bz.par_chunks_exact(2)) + .map(|((eq_pair, az_pair), bz_pair)| { + let mut local = [F::Accumulator::default(); OUTER_REMAINING_DEGREE_BOUND + 1]; + let eq0 = eq_pair[0]; + let eq_delta = eq_pair[1] - eq_pair[0]; + let az0 = az_pair[0]; + let az_delta = az_pair[1] - az_pair[0]; + let bz0 = bz_pair[0]; + let bz_delta = bz_pair[1] - bz_pair[0]; + accumulate_cubic_product_coefficients( + &mut local, eq0, eq_delta, az0, az_delta, bz0, bz_delta, + ); + local + }) + .reduce( + || [F::Accumulator::default(); OUTER_REMAINING_DEGREE_BOUND + 1], + |mut left, right| { + for i in 0..left.len() { + left[i].merge(right[i]); + } + left + }, + ) + } else { + self.eq + .chunks_exact(2) + .zip(self.az.chunks_exact(2)) + .zip(self.bz.chunks_exact(2)) + .fold( + [F::Accumulator::default(); OUTER_REMAINING_DEGREE_BOUND + 1], + |mut local, ((eq_pair, az_pair), bz_pair)| { + let eq0 = eq_pair[0]; + let eq_delta = eq_pair[1] - eq_pair[0]; + let az0 = az_pair[0]; + let az_delta = az_pair[1] - az_pair[0]; + let bz0 = bz_pair[0]; + let bz_delta = bz_pair[1] - bz_pair[0]; + accumulate_cubic_product_coefficients( + &mut local, eq0, eq_delta, az0, az_delta, bz0, bz_delta, + ); + local + }, + ) + }; + UnivariatePoly::new(accumulators.map(FieldAccumulator::reduce).to_vec()) + } + + #[tracing::instrument(skip_all, name = "DenseOuterState::bind")] + fn bind(&mut self, challenge: F) { + bind_dense_evals_reuse(&mut self.eq, &mut self.eq_scratch, challenge); + bind_dense_evals_reuse(&mut self.az, &mut self.az_scratch, challenge); + bind_dense_evals_reuse(&mut self.bz, &mut self.bz_scratch, challenge); + } +} + +#[inline] +fn accumulate_cubic_product_coefficients( + coefficients: &mut [F::Accumulator; OUTER_REMAINING_DEGREE_BOUND + 1], + eq0: F, + eq_delta: F, + az0: F, + az_delta: F, + bz0: F, + bz_delta: F, +) { + let az0_bz0 = az0 * bz0; + let az_delta_bz0 = az_delta * bz0; + let az0_bz_delta = az0 * bz_delta; + let az_delta_bz_delta = az_delta * bz_delta; + + coefficients[0].fmadd(eq0, az0_bz0); + coefficients[1].fmadd(eq_delta, az0_bz0); + coefficients[1].fmadd(eq0, az_delta_bz0); + coefficients[1].fmadd(eq0, az0_bz_delta); + coefficients[2].fmadd(eq_delta, az_delta_bz0); + coefficients[2].fmadd(eq_delta, az0_bz_delta); + coefficients[2].fmadd(eq0, az_delta_bz_delta); + coefficients[3].fmadd(eq_delta, az_delta_bz_delta); +} + +fn bind_dense_evals_reuse(values: &mut Vec, scratch: &mut Vec, challenge: F) { + let half = values.len() / 2; + scratch.resize(half, F::zero()); + if half >= DENSE_BIND_PAR_THRESHOLD { + scratch + .par_iter_mut() + .enumerate() + .for_each(|(index, output)| { + let low = values[index << 1]; + let high = values[(index << 1) + 1]; + *output = low + (high - low) * challenge; + }); + } else { + for (index, output) in scratch.iter_mut().enumerate() { + let low = values[index << 1]; + let high = values[(index << 1) + 1]; + *output = low + (high - low) * challenge; + } + } + std::mem::swap(values, scratch); + scratch.clear(); +} + +fn outer_remaining_round_poly( + evaluator: &dyn Stage1OuterRemainingEvaluator, + context: Stage1OuterRemainingContext<'_, F>, + num_rounds: usize, + prefix: &[F], +) -> UnivariatePoly { + let suffix_rounds = num_rounds - prefix.len() - 1; + let mut evals = Vec::with_capacity(OUTER_REMAINING_DEGREE_BOUND + 1); + for x in 0..=OUTER_REMAINING_DEGREE_BOUND { + let mut sum = F::zero(); + for suffix in 0..(1usize << suffix_rounds) { + let mut point = Vec::with_capacity(num_rounds); + point.extend_from_slice(prefix); + point.push(F::from_u64(x as u64)); + for bit in 0..suffix_rounds { + point.push(F::from_u64(((suffix >> bit) & 1) as u64)); + } + sum += evaluator.evaluate(context, &point); + } + evals.push(sum); + } + UnivariatePoly::new(interpolate_to_coeffs(0, &evals)) +} + +fn scale_poly(poly: &UnivariatePoly, scalar: F) -> UnivariatePoly { + UnivariatePoly::new( + poly.coefficients() + .iter() + .map(|coefficient| *coefficient * scalar) + .collect(), + ) +} + +fn remaining_driver_evals( + context: Stage1KernelContext<'_>, + evaluator: &dyn Stage1OuterRemainingEvaluator, + remaining_context: Stage1OuterRemainingContext<'_, F>, + point: &[F], +) -> Result>, Stage1KernelError> { + let plans = context + .program + .evals + .iter() + .filter(|eval| eval.source == context.driver.symbol) + .collect::>(); + let oracles = plans.iter().map(|eval| eval.oracle).collect::>(); + let values = evaluator + .evaluate_virtual_oracles(remaining_context, &oracles, point) + .ok_or(Stage1KernelError::MissingKernelInput { + kernel: context.kernel.abi, + input: "remaining_driver_evals", + })?; + if values.len() != plans.len() { + return Err(Stage1KernelError::InvalidInputLength { + input: "remaining_driver_evals", + expected: plans.len(), + actual: values.len(), + }); + } + Ok(plans + .into_iter() + .zip(values) + .map(|(eval, value)| Stage1NamedEval { + name: eval.name, + oracle: eval.oracle, + value, + }) + .collect()) +} + +fn uniskip_output_claim(sumchecks: &[Stage1SumcheckOutput]) -> Option { + uniskip_point_and_claim(sumchecks).map(|(_, claim)| claim) +} + +fn uniskip_point_and_claim(sumchecks: &[Stage1SumcheckOutput]) -> Option<(F, F)> { + sumchecks.iter().find_map(|sumcheck| { + let point = *sumcheck.point.first()?; + let claim = sumcheck + .evals + .iter() + .find(|eval| eval.oracle == "UnivariateSkip") + .map(|eval| eval.value)?; + Some((point, claim)) + }) +} + +fn uniskip_sum_matches(poly: &UnivariatePoly, claim: F) -> bool { + let power_sums = integer_domain_power_sums( + OUTER_UNISKIP_BASE_START, + OUTER_UNISKIP_DOMAIN_SIZE, + poly.coefficients().len(), + ); + let sum = poly + .coefficients() + .iter() + .zip(power_sums) + .fold(F::zero(), |acc, (coefficient, power_sum)| { + acc + coefficient.mul_i128(power_sum) + }); + sum == claim +} + +fn integer_domain_power_sums(domain_start: i64, domain_size: usize, count: usize) -> Vec { + let mut sums = vec![0i128; count]; + for offset in 0..domain_size { + let point = i128::from(domain_start + offset as i64); + let mut power = 1i128; + for sum in &mut sums { + *sum += power; + power *= point; + } + } + sums +} + +fn polynomial_degree(poly: &UnivariatePoly) -> usize { + poly.coefficients().len().saturating_sub(1) +} + +fn driver_evals(context: Stage1KernelContext<'_>, value: F) -> Vec> { + context + .program + .evals + .iter() + .filter(|eval| eval.source == context.driver.symbol) + .map(|eval| Stage1NamedEval { + name: eval.name, + oracle: eval.oracle, + value, + }) + .collect() +} + +fn validate_eval_shape( + context: Stage1KernelContext<'_>, + actual: &[Stage1NamedEval], + expected_value: Option, +) -> Result<(), Stage1KernelError> { + let expected = context + .program + .evals + .iter() + .filter(|eval| eval.source == context.driver.symbol) + .collect::>(); + if actual.len() != expected.len() { + return Err(Stage1KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "eval count mismatch", + }); + } + for (actual, expected) in actual.iter().zip(expected) { + if actual.name != expected.name { + return Err(Stage1KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "eval name mismatch", + }); + } + if actual.oracle != expected.oracle { + return Err(Stage1KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "eval oracle mismatch", + }); + } + if expected_value + .as_ref() + .is_some_and(|expected_value| actual.value != *expected_value) + { + return Err(Stage1KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "eval value mismatch", + }); + } + } + Ok(()) +} + +fn run_shape_kernel( + context: Stage1KernelContext<'_>, + transcript: &mut T, +) -> Result, Stage1KernelError> +where + F: Field, + T: Transcript, +{ + match context.kernel.abi { + "jolt_stage1_outer_uniskip" | "jolt_stage1_outer_remaining" => { + Ok(shape_sumcheck_output(context, transcript)) + } + abi => Err(Stage1KernelError::KernelNotImplemented { abi }), + } +} + +fn shape_sumcheck_output( + context: Stage1KernelContext<'_>, + transcript: &mut T, +) -> Stage1SumcheckOutput +where + F: Field, + T: Transcript, +{ + let point = (0..context.driver.num_rounds) + .map(|_| transcript.challenge()) + .collect(); + let evals = context + .program + .evals + .iter() + .filter(|eval| eval.source == context.driver.symbol) + .map(|eval| Stage1NamedEval { + name: eval.name, + oracle: eval.oracle, + value: F::from_u64(eval.index as u64), + }) + .collect(); + Stage1SumcheckOutput { + driver: context.driver.symbol, + point, + evals, + proof: shape_sumcheck_proof(context.driver), + } +} + +fn shape_sumcheck_proof(driver: &Stage1SumcheckDriverPlan) -> SumcheckProof { + let coefficients = vec![F::zero(); driver.degree + 1]; + SumcheckProof { + round_polynomials: (0..driver.num_rounds) + .map(|_| UnivariatePoly::new(coefficients.clone())) + .collect(), + } +} + +#[cfg(test)] +#[expect(clippy::expect_used, reason = "tests use explicit panic messages")] +mod tests { + use jolt_field::{Field, Fr}; + use jolt_transcript::{MockTranscript, Transcript}; + + use super::*; + + static KERNELS: &[Stage1KernelPlan] = &[Stage1KernelPlan { + symbol: "kernel", + relation: "relation", + kind: "sumcheck", + backend: "cpu", + abi: "jolt_stage1_outer_uniskip", + }]; + static FULL_KERNELS: &[Stage1KernelPlan] = &[ + Stage1KernelPlan { + symbol: "uniskip_kernel", + relation: "jolt.stage1.outer.uniskip", + kind: "sumcheck", + backend: "cpu", + abi: "jolt_stage1_outer_uniskip", + }, + Stage1KernelPlan { + symbol: "remaining_kernel", + relation: "jolt.stage1.outer.remaining", + kind: "sumcheck", + backend: "cpu", + abi: "jolt_stage1_outer_remaining", + }, + ]; + static CLAIMS: &[Stage1SumcheckClaimPlan] = &[Stage1SumcheckClaimPlan { + symbol: "claim", + stage: "stage", + domain: "domain", + num_rounds: 1, + degree: OUTER_UNISKIP_DEGREE_BOUND, + claim: "zero", + kernel: Some("kernel"), + relation: None, + claim_value: "zero", + input_openings: &[], + }]; + static BATCHES: &[Stage1SumcheckBatchPlan] = &[Stage1SumcheckBatchPlan { + symbol: "batch", + stage: "stage", + proof_slot: "proof", + policy: "single", + count: 1, + ordered_claims: &["claim"], + claim_operands: &["claim"], + claim_label: "claim_label", + round_label: "round_label", + round_schedule: &[1], + }]; + static BAD_BATCHES: &[Stage1SumcheckBatchPlan] = &[Stage1SumcheckBatchPlan { + symbol: "batch", + stage: "stage", + proof_slot: "proof", + policy: "single", + count: 2, + ordered_claims: &["claim"], + claim_operands: &["claim"], + claim_label: "claim_label", + round_label: "round_label", + round_schedule: &[1], + }]; + + #[test] + fn cubic_product_coefficients_match_interpolation() { + let eq0 = Fr::from_u64(3); + let eq_delta = Fr::from_u64(5); + let az0 = Fr::from_u64(7); + let az_delta = Fr::from_u64(11); + let bz0 = Fr::from_u64(13); + let bz_delta = Fr::from_u64(17); + + let mut accumulators = + [::Accumulator::default(); OUTER_REMAINING_DEGREE_BOUND + 1]; + accumulate_cubic_product_coefficients( + &mut accumulators, + eq0, + eq_delta, + az0, + az_delta, + bz0, + bz_delta, + ); + let direct = accumulators.map(FieldAccumulator::reduce).to_vec(); + + let evals = (0..=OUTER_REMAINING_DEGREE_BOUND) + .map(|x| { + let point = Fr::from_u64(x as u64); + (eq0 + eq_delta * point) * (az0 + az_delta * point) * (bz0 + bz_delta * point) + }) + .collect::>(); + assert_eq!(direct, interpolate_to_coeffs(0, &evals)); + } + + #[test] + fn uniskip_integer_coefficients_match_lagrange_weights() { + for (target, coefficients) in outer_uniskip_targets() + .into_iter() + .zip(OUTER_UNISKIP_TARGET_COEFFS) + { + let weights = lagrange_evals( + OUTER_UNISKIP_BASE_START, + OUTER_UNISKIP_DOMAIN_SIZE, + Fr::from_i64(target), + ); + let expected = coefficients.map(Fr::from_i64).to_vec(); + assert_eq!(weights, expected); + } + } + + #[test] + fn integer_coeff_group_matvec_matches_field_weights() { + let mut a_values = [Fr::from_u64(0); OUTER_EQ_CONSTRAINT_ROWS]; + let mut b_values = [Fr::from_u64(0); OUTER_EQ_CONSTRAINT_ROWS]; + for i in 0..OUTER_EQ_CONSTRAINT_ROWS { + a_values[i] = match i % 3 { + 0 => Fr::from_u64(0), + 1 => Fr::from_u64(1), + _ => Fr::from_u64((i + 2) as u64), + }; + b_values[i] = Fr::from_i64(i as i64 - 7); + } + let dots = R1csRowDotSlice { + a: &a_values, + b: &b_values, + }; + let coefficients = &OUTER_UNISKIP_TARGET_COEFFS[3]; + let coefficient_fields = coefficients.map(Fr::from_i64); + let weights = coefficient_fields.to_vec(); + + let integer = Stage1OuterR1csData::group_matvecs_from_integer_coeffs( + &OUTER_FIRST_GROUP_ROWS, + coefficients, + &coefficient_fields, + dots, + ); + let field = + Stage1OuterR1csData::group_matvecs_from_dots(&OUTER_FIRST_GROUP_ROWS, &weights, dots); + assert_eq!(integer, field); + } + + static FULL_CLAIMS: &[Stage1SumcheckClaimPlan] = &[ + Stage1SumcheckClaimPlan { + symbol: "uniskip_claim", + stage: "stage", + domain: "uniskip_domain", + num_rounds: 1, + degree: OUTER_UNISKIP_DEGREE_BOUND, + claim: "zero", + kernel: Some("uniskip_kernel"), + relation: None, + claim_value: "zero", + input_openings: &[], + }, + Stage1SumcheckClaimPlan { + symbol: "remaining_claim", + stage: "stage", + domain: "trace_domain", + num_rounds: 2, + degree: OUTER_REMAINING_DEGREE_BOUND, + claim: "stage1.uniskip.opening", + kernel: Some("remaining_kernel"), + relation: None, + claim_value: "stage1.uniskip.eval", + input_openings: &["stage1.uniskip.opening"], + }, + ]; + static FULL_BATCHES: &[Stage1SumcheckBatchPlan] = &[ + Stage1SumcheckBatchPlan { + symbol: "uniskip_batch", + stage: "stage", + proof_slot: "uniskip_proof", + policy: "single", + count: 1, + ordered_claims: &["uniskip_claim"], + claim_operands: &["uniskip_claim"], + claim_label: "uniskip_claim", + round_label: "uniskip_poly", + round_schedule: &[1], + }, + Stage1SumcheckBatchPlan { + symbol: "remaining_batch", + stage: "stage", + proof_slot: "remaining_proof", + policy: "jolt_core_front_loaded", + count: 1, + ordered_claims: &["remaining_claim"], + claim_operands: &["remaining_claim"], + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + round_schedule: &[2], + }, + ]; + static DRIVERS: &[Stage1SumcheckDriverPlan] = &[Stage1SumcheckDriverPlan { + symbol: "driver", + stage: "stage", + proof_slot: "proof", + kernel: Some("kernel"), + relation: None, + batch: "batch", + policy: "single", + round_schedule: &[1], + claim_label: "claim_label", + round_label: "round_label", + num_rounds: 1, + degree: OUTER_UNISKIP_DEGREE_BOUND, + }]; + static FULL_DRIVERS: &[Stage1SumcheckDriverPlan] = &[ + Stage1SumcheckDriverPlan { + symbol: "stage1.uniskip.sumcheck", + stage: "stage", + proof_slot: "uniskip_proof", + kernel: Some("uniskip_kernel"), + relation: None, + batch: "uniskip_batch", + policy: "univariate_skip", + round_schedule: &[1], + claim_label: "uniskip_claim", + round_label: "uniskip_poly", + num_rounds: 1, + degree: OUTER_UNISKIP_DEGREE_BOUND, + }, + Stage1SumcheckDriverPlan { + symbol: "stage1.outer_remaining.sumcheck", + stage: "stage", + proof_slot: "remaining_proof", + kernel: Some("remaining_kernel"), + relation: None, + batch: "remaining_batch", + policy: "jolt_core_front_loaded", + round_schedule: &[2], + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + num_rounds: 2, + degree: OUTER_REMAINING_DEGREE_BOUND, + }, + ]; + static FULL_EVALS: &[Stage1SumcheckEvalPlan] = &[ + Stage1SumcheckEvalPlan { + symbol: "uniskip_eval", + source: "stage1.uniskip.sumcheck", + name: "stage1.uniskip.eval", + index: 0, + oracle: "UnivariateSkip", + }, + Stage1SumcheckEvalPlan { + symbol: "remaining_eval", + source: "stage1.outer_remaining.sumcheck", + name: "stage1.outer_remaining.eval.Synthetic", + index: 0, + oracle: "Synthetic", + }, + ]; + static SQUEEZES: &[Stage1TranscriptSqueezePlan] = &[Stage1TranscriptSqueezePlan { + symbol: "stage1.tau", + label: "outer_tau", + kind: "challenge_vector", + count: 2, + }]; + static REAL_SQUEEZES: &[Stage1TranscriptSqueezePlan] = &[Stage1TranscriptSqueezePlan { + symbol: "stage1.tau", + label: "outer_tau", + kind: "challenge_vector", + count: 3, + }]; + static PROGRAM: Stage1CpuProgramPlan = Stage1CpuProgramPlan { + params: Stage1Params { + field: "bn254_fr", + pcs: "dory", + transcript: "blake2b_transcript", + }, + transcript_squeezes: SQUEEZES, + kernels: KERNELS, + claims: CLAIMS, + batches: BATCHES, + drivers: DRIVERS, + instance_results: &[], + evals: &[], + opening_claims: &[], + opening_batches: &[], + }; + static BAD_PROGRAM: Stage1CpuProgramPlan = Stage1CpuProgramPlan { + params: Stage1Params { + field: "bn254_fr", + pcs: "dory", + transcript: "blake2b_transcript", + }, + transcript_squeezes: SQUEEZES, + kernels: KERNELS, + claims: CLAIMS, + batches: BAD_BATCHES, + drivers: DRIVERS, + instance_results: &[], + evals: &[], + opening_claims: &[], + opening_batches: &[], + }; + static FULL_PROGRAM: Stage1CpuProgramPlan = Stage1CpuProgramPlan { + params: Stage1Params { + field: "bn254_fr", + pcs: "dory", + transcript: "blake2b_transcript", + }, + transcript_squeezes: SQUEEZES, + kernels: FULL_KERNELS, + claims: FULL_CLAIMS, + batches: FULL_BATCHES, + drivers: FULL_DRIVERS, + instance_results: &[], + evals: FULL_EVALS, + opening_claims: &[], + opening_batches: &[], + }; + static REAL_EVALS: &[Stage1SumcheckEvalPlan] = &[ + Stage1SumcheckEvalPlan { + symbol: "uniskip_eval", + source: "stage1.uniskip.sumcheck", + name: "stage1.uniskip.eval", + index: 0, + oracle: "UnivariateSkip", + }, + Stage1SumcheckEvalPlan { + symbol: "remaining_eval", + source: "stage1.outer_remaining.sumcheck", + name: "stage1.outer_remaining.eval.PC", + index: 0, + oracle: "PC", + }, + ]; + static REAL_PROGRAM: Stage1CpuProgramPlan = Stage1CpuProgramPlan { + params: Stage1Params { + field: "bn254_fr", + pcs: "dory", + transcript: "blake2b_transcript", + }, + transcript_squeezes: REAL_SQUEEZES, + kernels: FULL_KERNELS, + claims: FULL_CLAIMS, + batches: FULL_BATCHES, + drivers: FULL_DRIVERS, + instance_results: &[], + evals: REAL_EVALS, + opening_claims: &[], + opening_batches: &[], + }; + + struct SumZeroRemainingEvaluator; + + impl Stage1OuterRemainingEvaluator for SumZeroRemainingEvaluator { + fn evaluate(&self, _context: Stage1OuterRemainingContext<'_, Fr>, point: &[Fr]) -> Fr { + point[0] + point[0] - Fr::from_u64(1) + } + + fn evaluate_virtual_oracle( + &self, + _context: Stage1OuterRemainingContext<'_, Fr>, + oracle: &str, + point: &[Fr], + ) -> Option { + (oracle == "Synthetic").then(|| point.iter().copied().sum()) + } + } + + #[derive(Default)] + struct RecordingExecutor { + modes: Vec, + drivers: Vec<&'static str>, + } + + impl RecordingExecutor { + fn output( + &mut self, + context: Stage1KernelContext<'_>, + point: F, + ) -> Stage1SumcheckOutput { + self.modes.push(context.mode); + self.drivers.push(context.driver.symbol); + Stage1SumcheckOutput { + driver: context.driver.symbol, + point: vec![point], + evals: Vec::new(), + proof: SumcheckProof::default(), + } + } + } + + impl Stage1KernelExecutor for RecordingExecutor { + fn prove_sumcheck( + &mut self, + context: Stage1KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage1KernelError> + where + T: Transcript, + { + Ok(self.output(context, transcript.challenge())) + } + + fn verify_sumcheck( + &mut self, + context: Stage1KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage1KernelError> + where + T: Transcript, + { + Ok(self.output(context, transcript.challenge())) + } + } + + fn noop_r1cs_key_and_witness(num_cycles: usize) -> (R1csKey, Vec) { + let matrices = rv64::rv64_constraints::(); + let key = R1csKey::new(matrices, num_cycles); + let mut witness = vec![Fr::from_u64(0); key.num_cycles * key.num_vars_padded]; + for cycle in 0..key.num_cycles { + let base = cycle * key.num_vars_padded; + witness[base + rv64::V_CONST] = Fr::from_u64(1); + witness[base + rv64::V_FLAG_DO_NOT_UPDATE_UNEXPANDED_PC] = Fr::from_u64(1); + key.matrices + .check_witness(&witness[base..base + rv64::NUM_VARS_PER_CYCLE]) + .expect("noop cycle satisfies RV64 constraints"); + } + (key, witness) + } + + #[test] + fn execute_stage1_program_dispatches_driver_to_executor() { + let mut executor = RecordingExecutor::default(); + let mut transcript = MockTranscript::::new(b"stage1"); + let artifacts = execute_stage1_program( + &PROGRAM, + Stage1ExecutionMode::Prover, + &mut executor, + &mut transcript, + ) + .expect("dispatch succeeds"); + + assert_eq!(executor.modes, vec![Stage1ExecutionMode::Prover]); + assert_eq!(executor.drivers, vec!["driver"]); + assert_eq!(artifacts.sumchecks.len(), 1); + assert_eq!(artifacts.challenge_vectors.len(), 1); + assert_eq!(artifacts.sumchecks[0].driver, "driver"); + assert_eq!(artifacts.sumchecks[0].point.len(), 1); + } + + #[test] + fn execute_stage1_program_rejects_static_count_mismatch() { + let mut executor = RecordingExecutor::default(); + let mut transcript = MockTranscript::::new(b"stage1"); + let error = execute_stage1_program( + &BAD_PROGRAM, + Stage1ExecutionMode::Verifier, + &mut executor, + &mut transcript, + ) + .expect_err("bad static plan rejected"); + + assert_eq!( + error, + Stage1KernelError::PlanCountMismatch { + artifact: "batch", + expected: 2, + actual: 1, + } + ); + assert!(executor.drivers.is_empty()); + } + + #[test] + fn shape_kernel_executor_runs_known_stage1_kernel_abis() { + let mut executor = Stage1ShapeKernelExecutor; + let mut transcript = MockTranscript::::new(b"stage1"); + let artifacts = execute_stage1_program( + &PROGRAM, + Stage1ExecutionMode::Verifier, + &mut executor, + &mut transcript, + ) + .expect("shape kernel dispatch succeeds"); + + assert_eq!(artifacts.sumchecks.len(), 1); + assert_eq!(artifacts.sumchecks[0].driver, "driver"); + assert_eq!(artifacts.sumchecks[0].point.len(), 1); + assert_eq!(artifacts.sumchecks[0].proof.round_polynomials.len(), 1); + assert_eq!( + artifacts.sumchecks[0].proof.round_polynomials[0] + .coefficients() + .len(), + OUTER_UNISKIP_DEGREE_BOUND + 1 + ); + } + + #[test] + fn prover_kernel_executor_requires_uniskip_extended_evals() { + let inputs = Stage1ProverInputs::::empty(1); + let mut executor = Stage1ProverKernelExecutor::new(inputs); + let mut transcript = MockTranscript::::new(b"stage1"); + let error = execute_stage1_program( + &PROGRAM, + Stage1ExecutionMode::Prover, + &mut executor, + &mut transcript, + ) + .expect_err("real prover requires extended evaluations"); + + assert_eq!( + error, + Stage1KernelError::MissingKernelInput { + kernel: "jolt_stage1_outer_uniskip", + input: "uniskip_extended_evals", + } + ); + } + + #[test] + fn uniskip_kernel_prover_verifier_self_parity() { + let extended_evals = (1..=OUTER_UNISKIP_DEGREE) + .map(|index| Fr::from_u64(index as u64)) + .collect::>(); + let inputs = Stage1ProverInputs::empty(1).with_uniskip_extended_evals(&extended_evals); + let mut prover_executor = Stage1ProverKernelExecutor::new(inputs); + let mut prover_transcript = MockTranscript::::new(b"stage1"); + let prover_artifacts = execute_stage1_program( + &PROGRAM, + Stage1ExecutionMode::Prover, + &mut prover_executor, + &mut prover_transcript, + ) + .expect("uniskip prover succeeds"); + + let proof = Stage1Proof::from(prover_artifacts.clone()); + let mut verifier_executor = Stage1VerifierKernelExecutor::new(&proof); + let mut verifier_transcript = MockTranscript::::new(b"stage1"); + let verifier_artifacts = execute_stage1_program( + &PROGRAM, + Stage1ExecutionMode::Verifier, + &mut verifier_executor, + &mut verifier_transcript, + ) + .expect("uniskip verifier accepts prover proof"); + + assert_eq!(prover_transcript.state(), verifier_transcript.state()); + assert_eq!(prover_artifacts.sumchecks.len(), 1); + assert_eq!(verifier_artifacts.sumchecks.len(), 1); + assert_eq!( + prover_artifacts.sumchecks[0].point, + verifier_artifacts.sumchecks[0].point + ); + assert_eq!( + prover_artifacts.sumchecks[0].proof.round_polynomials[0].coefficients(), + verifier_artifacts.sumchecks[0].proof.round_polynomials[0].coefficients() + ); + } + + #[test] + fn full_stage1_uniskip_and_remaining_self_parity() { + let extended_evals = vec![Fr::from_u64(0); OUTER_UNISKIP_DEGREE]; + let evaluator = SumZeroRemainingEvaluator; + let inputs = Stage1ProverInputs::empty(1) + .with_uniskip_extended_evals(&extended_evals) + .with_outer_remaining_evaluator(&evaluator); + let mut prover_executor = Stage1ProverKernelExecutor::new(inputs); + let mut prover_transcript = MockTranscript::::new(b"stage1"); + let prover_artifacts = execute_stage1_program( + &FULL_PROGRAM, + Stage1ExecutionMode::Prover, + &mut prover_executor, + &mut prover_transcript, + ) + .expect("full stage1 prover succeeds"); + + let proof = Stage1Proof::from(prover_artifacts.clone()); + let mut verifier_executor = Stage1VerifierKernelExecutor::new(&proof); + let mut verifier_transcript = MockTranscript::::new(b"stage1"); + let verifier_artifacts = execute_stage1_program( + &FULL_PROGRAM, + Stage1ExecutionMode::Verifier, + &mut verifier_executor, + &mut verifier_transcript, + ) + .expect("full stage1 verifier accepts prover proof"); + + assert_eq!(prover_transcript.state(), verifier_transcript.state()); + assert_eq!(prover_artifacts.sumchecks.len(), 2); + assert_eq!(verifier_artifacts.sumchecks.len(), 2); + assert_eq!( + prover_artifacts.sumchecks[1].point, + verifier_artifacts.sumchecks[1].point + ); + assert_eq!(prover_artifacts.sumchecks[1].evals.len(), 1); + assert_eq!( + prover_artifacts.sumchecks[1].evals[0].value, + verifier_artifacts.sumchecks[1].evals[0].value + ); + } + + #[test] + fn full_stage1_r1cs_data_self_parity() { + let (key, witness) = noop_r1cs_key_and_witness(2); + let data = Stage1OuterR1csData::new(&key, &witness).expect("valid R1CS witness shape"); + let inputs = + Stage1ProverInputs::empty(key.num_cycle_vars()).with_outer_remaining_evaluator(&data); + let mut prover_executor = Stage1ProverKernelExecutor::new(inputs); + let mut prover_transcript = MockTranscript::::new(b"stage1"); + let prover_artifacts = execute_stage1_program( + &REAL_PROGRAM, + Stage1ExecutionMode::Prover, + &mut prover_executor, + &mut prover_transcript, + ) + .expect("real R1CS-backed stage1 prover succeeds"); + + let proof = Stage1Proof::from(prover_artifacts.clone()); + let mut verifier_executor = Stage1VerifierKernelExecutor::new(&proof); + let mut verifier_transcript = MockTranscript::::new(b"stage1"); + let verifier_artifacts = execute_stage1_program( + &REAL_PROGRAM, + Stage1ExecutionMode::Verifier, + &mut verifier_executor, + &mut verifier_transcript, + ) + .expect("real R1CS-backed stage1 verifier accepts prover proof"); + + assert_eq!(prover_transcript.state(), verifier_transcript.state()); + assert_eq!(prover_artifacts.sumchecks.len(), 2); + assert_eq!(verifier_artifacts.sumchecks.len(), 2); + assert_eq!( + prover_artifacts.sumchecks[1].evals[0].value, + verifier_artifacts.sumchecks[1].evals[0].value + ); + } + + #[test] + fn full_stage1_r1cs_data_verifier_rejects_tampered_remaining_round() { + let (key, witness) = noop_r1cs_key_and_witness(2); + let data = Stage1OuterR1csData::new(&key, &witness).expect("valid R1CS witness shape"); + let inputs = + Stage1ProverInputs::empty(key.num_cycle_vars()).with_outer_remaining_evaluator(&data); + let mut prover_executor = Stage1ProverKernelExecutor::new(inputs); + let mut prover_transcript = MockTranscript::::new(b"stage1"); + let prover_artifacts = execute_stage1_program( + &REAL_PROGRAM, + Stage1ExecutionMode::Prover, + &mut prover_executor, + &mut prover_transcript, + ) + .expect("real R1CS-backed stage1 prover succeeds"); + + let mut proof = Stage1Proof::from(prover_artifacts); + let remaining = &mut proof.sumchecks[1].proof.round_polynomials[0]; + let mut coefficients = remaining.clone().into_coefficients(); + coefficients[0] += Fr::from_u64(1); + *remaining = UnivariatePoly::new(coefficients); + + let mut verifier_executor = Stage1VerifierKernelExecutor::new(&proof); + let mut verifier_transcript = MockTranscript::::new(b"stage1"); + let error = execute_stage1_program( + &REAL_PROGRAM, + Stage1ExecutionMode::Verifier, + &mut verifier_executor, + &mut verifier_transcript, + ) + .expect_err("tampered remaining round is rejected"); + + assert_eq!( + error, + Stage1KernelError::InvalidProof { + driver: "stage1.outer_remaining.sumcheck", + reason: "outer remaining round check failed", + } + ); + } + + #[test] + fn verifier_kernel_executor_rejects_invalid_uniskip_proof() { + let proof = Stage1Proof { + sumchecks: vec![Stage1SumcheckOutput { + driver: "driver", + point: Vec::new(), + evals: Vec::new(), + proof: SumcheckProof::default(), + }], + }; + let mut executor = Stage1VerifierKernelExecutor::new(&proof); + let mut transcript = MockTranscript::::new(b"stage1"); + let error = execute_stage1_program( + &PROGRAM, + Stage1ExecutionMode::Verifier, + &mut executor, + &mut transcript, + ) + .expect_err("empty verifier proof is invalid"); + + assert_eq!( + error, + Stage1KernelError::InvalidProof { + driver: "driver", + reason: "missing uniskip round polynomial", + } + ); + } +} diff --git a/crates/jolt-kernels/src/stage1/README.md b/crates/jolt-kernels/src/stage1/README.md new file mode 100644 index 0000000000..1e9fa3a517 --- /dev/null +++ b/crates/jolt-kernels/src/stage1/README.md @@ -0,0 +1,17 @@ +Stage 1 kernel modules +====================== + +`stage1.rs` owns the generated-code ABI: static plans, sumcheck execution, +proof verification, and the generic R1CS-backed fallback evaluator. + +`rv64_typed.rs` owns the RV64 coarse CPU specialization. It must remain a +semantic refinement of the generic R1CS evaluator: typed oracle evaluations and +sumcheck products are tested against the R1CS column path before equivalence +tests compare Bolt against jolt-core. + +Future Stage 1 kernels should follow the same shape: + +- Keep protocol scheduling in `stage1.rs`. +- Put workload-specific arithmetic in a focused typed module. +- Preserve a generic fallback or parity oracle for new specializations. +- Add a local typed-vs-generic test before wiring core equivalence. diff --git a/crates/jolt-kernels/src/stage1/rv64_typed.rs b/crates/jolt-kernels/src/stage1/rv64_typed.rs new file mode 100644 index 0000000000..1d52ebe8c2 --- /dev/null +++ b/crates/jolt-kernels/src/stage1/rv64_typed.rs @@ -0,0 +1,1207 @@ +use std::cmp::Ordering; + +use jolt_field::signed::{S128, S160, S192, S64}; +use jolt_field::{Field, Fr, Limbs}; +use jolt_poly::lagrange::{lagrange_evals, lagrange_kernel_eval}; +use jolt_poly::{EqPolynomial, UnivariatePoly}; +use jolt_r1cs::R1csKey; +use rayon::prelude::*; + +use super::{ + boolean_index, DenseOuterState, Stage1KernelError, Stage1OuterR1csData, + Stage1OuterRemainingContext, Stage1OuterRemainingEvaluator, Stage1RemainingRoundProof, + OUTER_SECOND_GROUP_ROWS, OUTER_UNISKIP_BASE_START, OUTER_UNISKIP_DEGREE, + OUTER_UNISKIP_DOMAIN_SIZE, OUTER_UNISKIP_TARGET_COEFFS, +}; + +const RV64_NUM_CIRCUIT_FLAGS: usize = 14; +const FLAG_ADD_OPERANDS: usize = 0; +const FLAG_SUBTRACT_OPERANDS: usize = 1; +const FLAG_MULTIPLY_OPERANDS: usize = 2; +const FLAG_LOAD: usize = 3; +const FLAG_STORE: usize = 4; +const FLAG_JUMP: usize = 5; +const FLAG_WRITE_LOOKUP_OUTPUT_TO_RD: usize = 6; +const FLAG_VIRTUAL_INSTRUCTION: usize = 7; +const FLAG_ASSERT: usize = 8; +const FLAG_DO_NOT_UPDATE_UNEXPANDED_PC: usize = 9; +const FLAG_ADVICE: usize = 10; +const FLAG_IS_COMPRESSED: usize = 11; +const FLAG_IS_FIRST_IN_SEQUENCE: usize = 12; +const FLAG_IS_LAST_IN_SEQUENCE: usize = 13; + +#[derive(Clone, Copy, Debug)] +pub struct Stage1Rv64Cycle { + pub left_input: u64, + pub right_input: S64, + pub product: S128, + pub left_lookup: u64, + pub right_lookup: u128, + pub lookup_output: u64, + pub rs1_read_value: u64, + pub rs2_read_value: u64, + pub rd_write_value: u64, + pub ram_addr: u64, + pub ram_read_value: u64, + pub ram_write_value: u64, + pub pc: u64, + pub next_pc: u64, + pub unexpanded_pc: u64, + pub next_unexpanded_pc: u64, + pub imm: S64, + pub flags: [bool; RV64_NUM_CIRCUIT_FLAGS], + pub should_jump: bool, + pub should_branch: bool, + pub next_is_virtual: bool, + pub next_is_first_in_sequence: bool, +} + +impl Stage1Rv64Cycle { + pub fn padding() -> Self { + let mut flags = [false; RV64_NUM_CIRCUIT_FLAGS]; + flags[FLAG_DO_NOT_UPDATE_UNEXPANDED_PC] = true; + Self { + left_input: 0, + right_input: S64::from_u64(0), + product: S128::from_u64(0), + left_lookup: 0, + right_lookup: 0, + lookup_output: 0, + rs1_read_value: 0, + rs2_read_value: 0, + rd_write_value: 0, + ram_addr: 0, + ram_read_value: 0, + ram_write_value: 0, + pc: 0, + next_pc: 0, + unexpanded_pc: 0, + next_unexpanded_pc: 0, + imm: S64::from_u64(0), + flags, + should_jump: false, + should_branch: false, + next_is_virtual: false, + next_is_first_in_sequence: false, + } + } +} + +#[derive(Debug)] +pub struct Stage1OuterRv64Data<'a> { + field_data: Stage1OuterR1csData<'a, Fr>, + cycles: &'a [Stage1Rv64Cycle], +} + +impl<'a> Stage1OuterRv64Data<'a> { + pub fn new( + key: &'a R1csKey, + witness: &'a [Fr], + cycles: &'a [Stage1Rv64Cycle], + ) -> Result { + if cycles.len() != key.num_cycles { + return Err(Stage1KernelError::InvalidInputLength { + input: "rv64_cycles", + expected: key.num_cycles, + actual: cycles.len(), + }); + } + Ok(Self { + field_data: Stage1OuterR1csData::new(key, witness)?, + cycles, + }) + } + + #[tracing::instrument(skip_all, name = "Stage1OuterRv64Data::dense_outer_state")] + fn dense_outer_state( + &self, + context: Stage1OuterRemainingContext<'_, Fr>, + num_rounds: usize, + batching_coeff: Fr, + ) -> DenseOuterState { + let tau_high = context.tau[context.tau.len() - 1]; + let tau_low = &context.tau[..context.tau.len() - 1]; + let lagrange_tau_r0 = lagrange_kernel_eval( + OUTER_UNISKIP_BASE_START, + OUTER_UNISKIP_DOMAIN_SIZE, + tau_high, + context.r0, + ); + let weights = lagrange_evals( + OUTER_UNISKIP_BASE_START, + OUTER_UNISKIP_DOMAIN_SIZE, + context.r0, + ); + let len = 1usize << num_rounds; + let scale = lagrange_tau_r0 * batching_coeff; + let eq_evals = EqPolynomial::new(tau_low.to_vec()).evaluations(); + let mut eq = vec![Fr::from_u64(0); len]; + let mut az = vec![Fr::from_u64(0); len]; + let mut bz = vec![Fr::from_u64(0); len]; + eq.par_chunks_mut(2) + .zip(az.par_chunks_mut(2)) + .zip(bz.par_chunks_mut(2)) + .enumerate() + .for_each(|(cycle, ((eq_pair, az_pair), bz_pair))| { + let index = cycle << 1; + let eval = Stage1Rv64Eval::new(&self.cycles[cycle]); + let (az_g0, bz_g0) = eval.first_group_linear(&weights); + let (az_g1, bz_g1) = eval.second_group_linear(&weights); + eq_pair[0] = eq_evals[index] * scale; + az_pair[0] = az_g0; + bz_pair[0] = bz_g0; + eq_pair[1] = eq_evals[index + 1] * scale; + az_pair[1] = az_g1; + bz_pair[1] = bz_g1; + }); + DenseOuterState { + eq, + az, + bz, + eq_scratch: Vec::with_capacity(len / 2), + az_scratch: Vec::with_capacity(len / 2), + bz_scratch: Vec::with_capacity(len / 2), + } + } +} + +impl Stage1OuterRemainingEvaluator for Stage1OuterRv64Data<'_> { + fn evaluate(&self, context: Stage1OuterRemainingContext<'_, Fr>, point: &[Fr]) -> Fr { + self.field_data.evaluate(context, point) + } + + #[tracing::instrument(skip_all, name = "Stage1OuterRv64Data::uniskip_extended_evals")] + fn uniskip_extended_evals(&self, tau: &[Fr]) -> Option> { + if tau.len() != self.field_data.key.num_cycle_vars() + 2 { + return None; + } + let tau_low = &tau[..tau.len() - 1]; + let num_rounds = self.field_data.key.num_cycle_vars() + 1; + let eq_evals = EqPolynomial::new(tau_low.to_vec()).evaluations(); + let num_cycles = 1usize << (num_rounds - 1); + if self.cycles.len() != num_cycles { + return None; + } + let accumulators = (0..num_cycles) + .into_par_iter() + .fold( + || [FrSignedProductAccumulator::zero(); OUTER_UNISKIP_DEGREE], + |mut local, cycle| { + let eval = Stage1Rv64Eval::new(&self.cycles[cycle]); + let (first_products, second_products) = eval.uniskip_products(); + let index = cycle << 1; + for (target, accumulator) in local.iter_mut().enumerate() { + accumulator.fmadd_s192(eq_evals[index], first_products[target]); + accumulator.fmadd_s192(eq_evals[index + 1], second_products[target]); + } + local + }, + ) + .reduce( + || [FrSignedProductAccumulator::zero(); OUTER_UNISKIP_DEGREE], + |mut left, right| { + for (left, right) in left.iter_mut().zip(right) { + left.merge(right); + } + left + }, + ); + Some( + accumulators + .into_iter() + .map(FrSignedProductAccumulator::reduce) + .collect(), + ) + } + + fn evaluate_virtual_oracle( + &self, + context: Stage1OuterRemainingContext<'_, Fr>, + oracle: &str, + point: &[Fr], + ) -> Option { + self.evaluate_virtual_oracles(context, &[oracle], point) + .and_then(|values| values.into_iter().next()) + } + + #[tracing::instrument(skip_all, name = "Stage1OuterRv64Data::evaluate_virtual_oracles")] + fn evaluate_virtual_oracles( + &self, + _context: Stage1OuterRemainingContext<'_, Fr>, + oracles: &[&str], + point: &[Fr], + ) -> Option> { + if point.len() != self.field_data.key.num_cycle_vars() + 1 { + return None; + } + let rv64_oracles = oracles + .iter() + .map(|oracle| Stage1Rv64Oracle::from_name(oracle)) + .collect::>>()?; + let cycle_point = Stage1OuterR1csData::::remaining_cycle_point(point); + if let Some(cycle) = boolean_index(&cycle_point) { + let row = self.cycles.get(cycle)?; + return Some( + rv64_oracles + .iter() + .map(|oracle| oracle.field_value(row)) + .collect(), + ); + } + + let eq = EqPolynomial::new(cycle_point).evaluations(); + let accumulators = eq + .par_iter() + .take(self.cycles.len()) + .enumerate() + .fold( + || vec![FrSignedProductAccumulator::zero(); rv64_oracles.len()], + |mut local, (cycle, &weight)| { + let row = &self.cycles[cycle]; + for (accumulator, oracle) in local.iter_mut().zip(&rv64_oracles) { + accumulator.fmadd_rv64_scalar(weight, oracle.scalar(row)); + } + local + }, + ) + .reduce( + || vec![FrSignedProductAccumulator::zero(); rv64_oracles.len()], + |mut left, right| { + for (left, right) in left.iter_mut().zip(right) { + left.merge(right); + } + left + }, + ); + Some( + accumulators + .into_iter() + .map(FrSignedProductAccumulator::reduce) + .collect(), + ) + } + + fn prove_remaining_rounds( + &self, + context: Stage1OuterRemainingContext<'_, Fr>, + num_rounds: usize, + batching_coeff: Fr, + initial_claim: Fr, + observe_round: &mut dyn FnMut(&UnivariatePoly) -> Fr, + ) -> Option> { + let mut state = self.dense_outer_state(context, num_rounds, batching_coeff); + let mut running_sum = initial_claim * batching_coeff; + let mut point = Vec::with_capacity(num_rounds); + let mut round_polynomials = Vec::with_capacity(num_rounds); + + for _round in 0..num_rounds { + let poly = state.round_poly(); + if poly.evaluate(Fr::from_u64(0)) + poly.evaluate(Fr::from_u64(1)) != running_sum { + return Some(Err(Stage1KernelError::InvalidProof { + driver: "stage1.outer.remaining", + reason: "dense outer remaining claim mismatch", + })); + } + let challenge = observe_round(&poly); + running_sum = poly.evaluate(challenge); + state.bind(challenge); + point.push(challenge); + round_polynomials.push(poly); + } + Some(Ok((point, round_polynomials))) + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +enum Stage1Rv64Oracle { + LeftInstructionInput, + RightInstructionInput, + Product, + ShouldBranch, + Pc, + UnexpandedPc, + Imm, + RamAddress, + Rs1Value, + Rs2Value, + RdWriteValue, + RamReadValue, + RamWriteValue, + LeftLookupOperand, + RightLookupOperand, + NextUnexpandedPc, + NextPc, + NextIsVirtual, + NextIsFirstInSequence, + LookupOutput, + ShouldJump, + OpFlagAddOperands, + OpFlagSubtractOperands, + OpFlagMultiplyOperands, + OpFlagLoad, + OpFlagStore, + OpFlagJump, + OpFlagWriteLookupOutputToRd, + OpFlagVirtualInstruction, + OpFlagAssert, + OpFlagDoNotUpdateUnexpandedPc, + OpFlagAdvice, + OpFlagIsCompressed, + OpFlagIsFirstInSequence, + OpFlagIsLastInSequence, +} + +impl Stage1Rv64Oracle { + fn from_name(name: &str) -> Option { + match name { + "LeftInstructionInput" => Some(Self::LeftInstructionInput), + "RightInstructionInput" => Some(Self::RightInstructionInput), + "Product" => Some(Self::Product), + "ShouldBranch" => Some(Self::ShouldBranch), + "PC" => Some(Self::Pc), + "UnexpandedPC" => Some(Self::UnexpandedPc), + "Imm" => Some(Self::Imm), + "RamAddress" => Some(Self::RamAddress), + "Rs1Value" => Some(Self::Rs1Value), + "Rs2Value" => Some(Self::Rs2Value), + "RdWriteValue" => Some(Self::RdWriteValue), + "RamReadValue" => Some(Self::RamReadValue), + "RamWriteValue" => Some(Self::RamWriteValue), + "LeftLookupOperand" => Some(Self::LeftLookupOperand), + "RightLookupOperand" => Some(Self::RightLookupOperand), + "NextUnexpandedPC" => Some(Self::NextUnexpandedPc), + "NextPC" => Some(Self::NextPc), + "NextIsVirtual" => Some(Self::NextIsVirtual), + "NextIsFirstInSequence" => Some(Self::NextIsFirstInSequence), + "LookupOutput" => Some(Self::LookupOutput), + "ShouldJump" => Some(Self::ShouldJump), + "OpFlagAddOperands" => Some(Self::OpFlagAddOperands), + "OpFlagSubtractOperands" => Some(Self::OpFlagSubtractOperands), + "OpFlagMultiplyOperands" => Some(Self::OpFlagMultiplyOperands), + "OpFlagLoad" => Some(Self::OpFlagLoad), + "OpFlagStore" => Some(Self::OpFlagStore), + "OpFlagJump" => Some(Self::OpFlagJump), + "OpFlagWriteLookupOutputToRD" => Some(Self::OpFlagWriteLookupOutputToRd), + "OpFlagVirtualInstruction" => Some(Self::OpFlagVirtualInstruction), + "OpFlagAssert" => Some(Self::OpFlagAssert), + "OpFlagDoNotUpdateUnexpandedPC" => Some(Self::OpFlagDoNotUpdateUnexpandedPc), + "OpFlagAdvice" => Some(Self::OpFlagAdvice), + "OpFlagIsCompressed" => Some(Self::OpFlagIsCompressed), + "OpFlagIsFirstInSequence" => Some(Self::OpFlagIsFirstInSequence), + "OpFlagIsLastInSequence" => Some(Self::OpFlagIsLastInSequence), + _ => None, + } + } + + #[inline] + fn scalar(self, row: &Stage1Rv64Cycle) -> Stage1Rv64Scalar { + match self { + Self::LeftInstructionInput => Stage1Rv64Scalar::U64(row.left_input), + Self::RightInstructionInput => Stage1Rv64Scalar::S64(row.right_input), + Self::Product => Stage1Rv64Scalar::S128(row.product), + Self::ShouldBranch => Stage1Rv64Scalar::Bool(row.should_branch), + Self::Pc => Stage1Rv64Scalar::U64(row.pc), + Self::UnexpandedPc => Stage1Rv64Scalar::U64(row.unexpanded_pc), + Self::Imm => Stage1Rv64Scalar::S64(row.imm), + Self::RamAddress => Stage1Rv64Scalar::U64(row.ram_addr), + Self::Rs1Value => Stage1Rv64Scalar::U64(row.rs1_read_value), + Self::Rs2Value => Stage1Rv64Scalar::U64(row.rs2_read_value), + Self::RdWriteValue => Stage1Rv64Scalar::U64(row.rd_write_value), + Self::RamReadValue => Stage1Rv64Scalar::U64(row.ram_read_value), + Self::RamWriteValue => Stage1Rv64Scalar::U64(row.ram_write_value), + Self::LeftLookupOperand => Stage1Rv64Scalar::U64(row.left_lookup), + Self::RightLookupOperand => Stage1Rv64Scalar::U128(row.right_lookup), + Self::NextUnexpandedPc => Stage1Rv64Scalar::U64(row.next_unexpanded_pc), + Self::NextPc => Stage1Rv64Scalar::U64(row.next_pc), + Self::NextIsVirtual => Stage1Rv64Scalar::Bool(row.next_is_virtual), + Self::NextIsFirstInSequence => Stage1Rv64Scalar::Bool(row.next_is_first_in_sequence), + Self::LookupOutput => Stage1Rv64Scalar::U64(row.lookup_output), + Self::ShouldJump => Stage1Rv64Scalar::Bool(row.should_jump), + Self::OpFlagAddOperands => Stage1Rv64Scalar::Bool(row.flags[FLAG_ADD_OPERANDS]), + Self::OpFlagSubtractOperands => { + Stage1Rv64Scalar::Bool(row.flags[FLAG_SUBTRACT_OPERANDS]) + } + Self::OpFlagMultiplyOperands => { + Stage1Rv64Scalar::Bool(row.flags[FLAG_MULTIPLY_OPERANDS]) + } + Self::OpFlagLoad => Stage1Rv64Scalar::Bool(row.flags[FLAG_LOAD]), + Self::OpFlagStore => Stage1Rv64Scalar::Bool(row.flags[FLAG_STORE]), + Self::OpFlagJump => Stage1Rv64Scalar::Bool(row.flags[FLAG_JUMP]), + Self::OpFlagWriteLookupOutputToRd => { + Stage1Rv64Scalar::Bool(row.flags[FLAG_WRITE_LOOKUP_OUTPUT_TO_RD]) + } + Self::OpFlagVirtualInstruction => { + Stage1Rv64Scalar::Bool(row.flags[FLAG_VIRTUAL_INSTRUCTION]) + } + Self::OpFlagAssert => Stage1Rv64Scalar::Bool(row.flags[FLAG_ASSERT]), + Self::OpFlagDoNotUpdateUnexpandedPc => { + Stage1Rv64Scalar::Bool(row.flags[FLAG_DO_NOT_UPDATE_UNEXPANDED_PC]) + } + Self::OpFlagAdvice => Stage1Rv64Scalar::Bool(row.flags[FLAG_ADVICE]), + Self::OpFlagIsCompressed => Stage1Rv64Scalar::Bool(row.flags[FLAG_IS_COMPRESSED]), + Self::OpFlagIsFirstInSequence => { + Stage1Rv64Scalar::Bool(row.flags[FLAG_IS_FIRST_IN_SEQUENCE]) + } + Self::OpFlagIsLastInSequence => { + Stage1Rv64Scalar::Bool(row.flags[FLAG_IS_LAST_IN_SEQUENCE]) + } + } + } + + #[inline] + fn field_value(self, row: &Stage1Rv64Cycle) -> Fr { + let mut accumulator = FrSignedProductAccumulator::zero(); + accumulator.fmadd_rv64_scalar(Fr::from_u64(1), self.scalar(row)); + accumulator.reduce() + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +enum Stage1Rv64Scalar { + Bool(bool), + U64(u64), + U128(u128), + S64(S64), + S128(S128), +} + +struct Stage1Rv64Eval<'a> { + row: &'a Stage1Rv64Cycle, +} + +impl<'a> Stage1Rv64Eval<'a> { + fn new(row: &'a Stage1Rv64Cycle) -> Self { + Self { row } + } + + #[inline] + fn first_group_linear(&self, weights: &[Fr]) -> (Fr, Fr) { + let mut az = Fr::from_u64(0); + let mut bz = FrSignedProductAccumulator::zero(); + + Self::accumulate_first_linear( + &mut az, + &mut bz, + weights[0], + self.not_load_store(), + S128::from_u64(self.row.ram_addr), + ); + Self::accumulate_first_linear( + &mut az, + &mut bz, + weights[1], + self.row.flags[FLAG_LOAD], + S128::zero_extend_from(&S64::from_diff_u64s( + self.row.ram_read_value, + self.row.ram_write_value, + )), + ); + Self::accumulate_first_linear( + &mut az, + &mut bz, + weights[2], + self.row.flags[FLAG_LOAD], + S128::zero_extend_from(&S64::from_diff_u64s( + self.row.ram_read_value, + self.row.rd_write_value, + )), + ); + Self::accumulate_first_linear( + &mut az, + &mut bz, + weights[3], + self.row.flags[FLAG_STORE], + S128::zero_extend_from(&S64::from_diff_u64s( + self.row.rs2_read_value, + self.row.ram_write_value, + )), + ); + Self::accumulate_first_linear( + &mut az, + &mut bz, + weights[4], + self.add_sub_mul(), + S128::from_u64(self.row.left_lookup), + ); + Self::accumulate_first_linear( + &mut az, + &mut bz, + weights[5], + !self.add_sub_mul(), + S128::zero_extend_from(&S64::from_diff_u64s( + self.row.left_lookup, + self.row.left_input, + )), + ); + Self::accumulate_first_linear( + &mut az, + &mut bz, + weights[6], + self.row.flags[FLAG_ASSERT], + S128::zero_extend_from(&S64::from_diff_u64s(self.row.lookup_output, 1)), + ); + Self::accumulate_first_linear( + &mut az, + &mut bz, + weights[7], + self.row.should_jump, + S128::zero_extend_from(&S64::from_diff_u64s( + self.row.next_unexpanded_pc, + self.row.lookup_output, + )), + ); + Self::accumulate_first_linear( + &mut az, + &mut bz, + weights[8], + self.row.flags[FLAG_VIRTUAL_INSTRUCTION] && !self.row.flags[FLAG_IS_LAST_IN_SEQUENCE], + S128::zero_extend_from(&S64::from_diff_u64s( + self.row.next_pc, + self.row.pc.wrapping_add(1), + )), + ); + Self::accumulate_first_linear( + &mut az, + &mut bz, + weights[9], + self.row.next_is_virtual && !self.row.next_is_first_in_sequence, + S128::from_u64(u64::from(!self.row.flags[FLAG_DO_NOT_UPDATE_UNEXPANDED_PC])), + ); + + (az, bz.reduce()) + } + + #[inline] + fn second_group_linear(&self, weights: &[Fr]) -> (Fr, Fr) { + let mut az = Fr::from_u64(0); + let mut bz = FrSignedProductAccumulator::zero(); + + Self::accumulate_second_linear( + &mut az, + &mut bz, + weights[0], + self.load_or_store(), + S192::from_i128(self.ram_addr_minus_rs1_plus_imm()), + ); + Self::accumulate_second_linear( + &mut az, + &mut bz, + weights[1], + self.row.flags[FLAG_ADD_OPERANDS], + (S160::from(self.row.right_lookup) - S160::from(self.right_add_expected())) + .to_signed_bigint_nplus1::<3>(), + ); + Self::accumulate_second_linear( + &mut az, + &mut bz, + weights[2], + self.row.flags[FLAG_SUBTRACT_OPERANDS], + (S160::from(self.row.right_lookup) - S160::from(self.right_sub_expected())) + .to_signed_bigint_nplus1::<3>(), + ); + Self::accumulate_second_linear( + &mut az, + &mut bz, + weights[3], + self.row.flags[FLAG_MULTIPLY_OPERANDS], + (S160::from(self.row.right_lookup) - S160::from(self.row.product)) + .to_signed_bigint_nplus1::<3>(), + ); + Self::accumulate_second_linear( + &mut az, + &mut bz, + weights[4], + !self.add_sub_mul_advice(), + (S160::from(self.row.right_lookup) + - S160::from(S128::zero_extend_from(&self.row.right_input))) + .to_signed_bigint_nplus1::<3>(), + ); + Self::accumulate_second_linear( + &mut az, + &mut bz, + weights[5], + self.row.flags[FLAG_WRITE_LOOKUP_OUTPUT_TO_RD], + S192::zero_extend_from(&S64::from_diff_u64s( + self.row.rd_write_value, + self.row.lookup_output, + )), + ); + Self::accumulate_second_linear( + &mut az, + &mut bz, + weights[6], + self.row.flags[FLAG_JUMP], + S192::zero_extend_from(&S64::from_diff_u64s( + self.row.rd_write_value, + self.expected_pc_plus_const(), + )), + ); + Self::accumulate_second_linear( + &mut az, + &mut bz, + weights[7], + self.row.should_branch, + S192::from_i128(self.next_unexpanded_pc_minus_pc_plus_imm()), + ); + Self::accumulate_second_linear( + &mut az, + &mut bz, + weights[8], + !self.row.flags[FLAG_JUMP] && !self.row.should_branch, + S192::zero_extend_from(&S64::from_diff_u64s( + self.row.next_unexpanded_pc, + self.expected_next_unexpanded_pc(), + )), + ); + + (az, bz.reduce()) + } + + #[inline] + fn uniskip_products(&self) -> ([S192; OUTER_UNISKIP_DEGREE], [S192; OUTER_UNISKIP_DEGREE]) { + let (first_guards, first_terms) = self.first_group_terms(); + let (second_guards, second_terms) = self.second_group_terms(); + ( + core::array::from_fn(|target| { + Self::first_group_product_from_terms(target, &first_guards, &first_terms) + }), + core::array::from_fn(|target| { + Self::second_group_product_from_terms(target, &second_guards, &second_terms) + }), + ) + } + + #[inline] + fn first_group_terms( + &self, + ) -> ( + [bool; OUTER_UNISKIP_DOMAIN_SIZE], + [S128; OUTER_UNISKIP_DOMAIN_SIZE], + ) { + ( + [ + self.not_load_store(), + self.row.flags[FLAG_LOAD], + self.row.flags[FLAG_LOAD], + self.row.flags[FLAG_STORE], + self.add_sub_mul(), + !self.add_sub_mul(), + self.row.flags[FLAG_ASSERT], + self.row.should_jump, + self.row.flags[FLAG_VIRTUAL_INSTRUCTION] + && !self.row.flags[FLAG_IS_LAST_IN_SEQUENCE], + self.row.next_is_virtual && !self.row.next_is_first_in_sequence, + ], + [ + S128::from_u64(self.row.ram_addr), + S128::zero_extend_from(&S64::from_diff_u64s( + self.row.ram_read_value, + self.row.ram_write_value, + )), + S128::zero_extend_from(&S64::from_diff_u64s( + self.row.ram_read_value, + self.row.rd_write_value, + )), + S128::zero_extend_from(&S64::from_diff_u64s( + self.row.rs2_read_value, + self.row.ram_write_value, + )), + S128::from_u64(self.row.left_lookup), + S128::zero_extend_from(&S64::from_diff_u64s( + self.row.left_lookup, + self.row.left_input, + )), + S128::zero_extend_from(&S64::from_diff_u64s(self.row.lookup_output, 1)), + S128::zero_extend_from(&S64::from_diff_u64s( + self.row.next_unexpanded_pc, + self.row.lookup_output, + )), + S128::zero_extend_from(&S64::from_diff_u64s( + self.row.next_pc, + self.row.pc.wrapping_add(1), + )), + S128::from_u64(u64::from(!self.row.flags[FLAG_DO_NOT_UPDATE_UNEXPANDED_PC])), + ], + ) + } + + #[inline] + fn second_group_terms( + &self, + ) -> ( + [bool; OUTER_SECOND_GROUP_ROWS.len()], + [S192; OUTER_SECOND_GROUP_ROWS.len()], + ) { + ( + [ + self.load_or_store(), + self.row.flags[FLAG_ADD_OPERANDS], + self.row.flags[FLAG_SUBTRACT_OPERANDS], + self.row.flags[FLAG_MULTIPLY_OPERANDS], + !self.add_sub_mul_advice(), + self.row.flags[FLAG_WRITE_LOOKUP_OUTPUT_TO_RD], + self.row.flags[FLAG_JUMP], + self.row.should_branch, + !self.row.flags[FLAG_JUMP] && !self.row.should_branch, + ], + [ + S192::from_i128(self.ram_addr_minus_rs1_plus_imm()), + (S160::from(self.row.right_lookup) - S160::from(self.right_add_expected())) + .to_signed_bigint_nplus1::<3>(), + (S160::from(self.row.right_lookup) - S160::from(self.right_sub_expected())) + .to_signed_bigint_nplus1::<3>(), + (S160::from(self.row.right_lookup) - S160::from(self.row.product)) + .to_signed_bigint_nplus1::<3>(), + (S160::from(self.row.right_lookup) + - S160::from(S128::zero_extend_from(&self.row.right_input))) + .to_signed_bigint_nplus1::<3>(), + S192::zero_extend_from(&S64::from_diff_u64s( + self.row.rd_write_value, + self.row.lookup_output, + )), + S192::zero_extend_from(&S64::from_diff_u64s( + self.row.rd_write_value, + self.expected_pc_plus_const(), + )), + S192::from_i128(self.next_unexpanded_pc_minus_pc_plus_imm()), + S192::zero_extend_from(&S64::from_diff_u64s( + self.row.next_unexpanded_pc, + self.expected_next_unexpanded_pc(), + )), + ], + ) + } + + #[inline] + fn first_group_product_from_terms( + target: usize, + guards: &[bool; OUTER_UNISKIP_DOMAIN_SIZE], + terms: &[S128; OUTER_UNISKIP_DOMAIN_SIZE], + ) -> S192 { + let coefficients = OUTER_UNISKIP_TARGET_COEFFS[target]; + let mut az = 0i32; + let mut bz = S128::zero(); + for ((&guard, &term), &coefficient) in guards.iter().zip(terms).zip(&coefficients) { + Self::accumulate_first(&mut az, &mut bz, coefficient as i32, guard, term); + } + S64::from_i64(az as i64).mul_trunc::<2, 3>(&bz) + } + + #[inline] + fn second_group_product_from_terms( + target: usize, + guards: &[bool; OUTER_SECOND_GROUP_ROWS.len()], + terms: &[S192; OUTER_SECOND_GROUP_ROWS.len()], + ) -> S192 { + let coefficients = OUTER_UNISKIP_TARGET_COEFFS[target]; + let mut az = 0i32; + let mut bz = S192::zero(); + for ((&guard, &term), &coefficient) in guards.iter().zip(terms).zip(&coefficients) { + Self::accumulate_second(&mut az, &mut bz, coefficient as i32, guard, term); + } + S64::from_i64(az as i64).mul_trunc::<3, 3>(&bz) + } + + #[inline] + fn accumulate_first_linear( + az: &mut Fr, + bz: &mut FrSignedProductAccumulator, + weight: Fr, + guard: bool, + term: S128, + ) { + if guard { + *az += weight; + } else { + bz.fmadd_s128(weight, term); + } + } + + #[inline] + fn accumulate_second_linear( + az: &mut Fr, + bz: &mut FrSignedProductAccumulator, + weight: Fr, + guard: bool, + term: S192, + ) { + if guard { + *az += weight; + } else { + bz.fmadd_s192(weight, term); + } + } + + #[inline] + fn accumulate_first(az: &mut i32, bz: &mut S128, coefficient: i32, guard: bool, term: S128) { + if guard { + *az += coefficient; + } else { + fmadd_i32_s128(bz, coefficient, term); + } + } + + #[inline] + fn accumulate_second(az: &mut i32, bz: &mut S192, coefficient: i32, guard: bool, term: S192) { + if guard { + *az += coefficient; + } else { + fmadd_i32_s192(bz, coefficient, term); + } + } + + #[inline] + fn not_load_store(&self) -> bool { + !self.load_or_store() + } + + #[inline] + fn load_or_store(&self) -> bool { + self.row.flags[FLAG_LOAD] || self.row.flags[FLAG_STORE] + } + + #[inline] + fn add_sub_mul(&self) -> bool { + self.row.flags[FLAG_ADD_OPERANDS] + || self.row.flags[FLAG_SUBTRACT_OPERANDS] + || self.row.flags[FLAG_MULTIPLY_OPERANDS] + } + + #[inline] + fn add_sub_mul_advice(&self) -> bool { + self.add_sub_mul() || self.row.flags[FLAG_ADVICE] + } + + #[inline] + fn ram_addr_minus_rs1_plus_imm(&self) -> i128 { + let expected = if self.row.imm.is_positive { + self.row.rs1_read_value as i128 + self.row.imm.magnitude_as_u64() as i128 + } else { + self.row.rs1_read_value as i128 - self.row.imm.magnitude_as_u64() as i128 + }; + self.row.ram_addr as i128 - expected + } + + #[inline] + fn right_add_expected(&self) -> i128 { + self.row.left_input as i128 + self.row.right_input.to_i128() + } + + #[inline] + fn right_sub_expected(&self) -> i128 { + self.row.left_input as i128 - self.row.right_input.to_i128() + (1i128 << 64) + } + + #[inline] + fn expected_pc_plus_const(&self) -> u64 { + let const_term = 4 - if self.row.flags[FLAG_IS_COMPRESSED] { + 2 + } else { + 0 + }; + self.row.unexpanded_pc.wrapping_add(const_term) + } + + #[inline] + fn next_unexpanded_pc_minus_pc_plus_imm(&self) -> i128 { + self.row.next_unexpanded_pc as i128 + - (self.row.unexpanded_pc as i128 + self.row.imm.to_i128()) + } + + #[inline] + fn expected_next_unexpanded_pc(&self) -> u64 { + let const_term = + 4 - if self.row.flags[FLAG_DO_NOT_UPDATE_UNEXPANDED_PC] { + 4 + } else { + 0 + } - if self.row.flags[FLAG_IS_COMPRESSED] { + 2 + } else { + 0 + }; + self.row.unexpanded_pc.wrapping_add(const_term) + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +struct FrSignedProductAccumulator { + positive: Limbs<9>, + negative: Limbs<9>, +} + +impl FrSignedProductAccumulator { + #[inline] + fn zero() -> Self { + Self { + positive: Limbs::zero(), + negative: Limbs::zero(), + } + } + + #[inline] + fn fmadd_s192(&mut self, field: Fr, scalar: S192) { + if scalar.magnitude_limbs() == [0u64; 3] { + return; + } + self.fmadd_limbs(field, &scalar.magnitude, scalar.is_positive); + } + + #[inline] + fn fmadd_rv64_scalar(&mut self, field: Fr, scalar: Stage1Rv64Scalar) { + match scalar { + Stage1Rv64Scalar::Bool(value) => { + if value { + self.add_positive_field(field); + } + } + Stage1Rv64Scalar::U64(value) => self.fmadd_u64(field, value), + Stage1Rv64Scalar::U128(value) => self.fmadd_u128(field, value), + Stage1Rv64Scalar::S64(value) => self.fmadd_s64(field, value), + Stage1Rv64Scalar::S128(value) => self.fmadd_s128(field, value), + } + } + + #[inline] + fn fmadd_u64(&mut self, field: Fr, scalar: u64) { + if scalar == 0 { + return; + } + if scalar == 1 { + self.add_positive_field(field); + return; + } + self.fmadd_limbs(field, &Limbs::<1>::from_u64(scalar), true); + } + + #[inline] + fn fmadd_u128(&mut self, field: Fr, scalar: u128) { + if scalar == 0 { + return; + } + if scalar <= u64::MAX as u128 { + self.fmadd_u64(field, scalar as u64); + return; + } + self.fmadd_limbs( + field, + &Limbs::<2>::new([scalar as u64, (scalar >> 64) as u64]), + true, + ); + } + + #[inline] + fn fmadd_s64(&mut self, field: Fr, scalar: S64) { + if scalar.magnitude_limbs() == [0u64; 1] { + return; + } + if scalar.is_positive { + self.fmadd_u64(field, scalar.magnitude_as_u64()); + return; + } + self.fmadd_limbs(field, scalar.as_magnitude(), false); + } + + #[inline] + fn fmadd_s128(&mut self, field: Fr, scalar: S128) { + if scalar.magnitude_limbs() == [0u64; 2] { + return; + } + self.fmadd_limbs(field, scalar.as_magnitude(), scalar.is_positive); + } + + #[inline] + fn add_positive_field(&mut self, field: Fr) { + self.positive + .add_assign_trunc::<9>(&Limbs::<9>::zero_extend_from::<4>(&field.inner_limbs())); + } + + #[inline] + fn fmadd_limbs(&mut self, field: Fr, scalar: &Limbs, is_positive: bool) { + let mut product = Limbs::<9>::zero(); + product.fmadd::<4, L>(&field.inner_limbs(), scalar); + if is_positive { + self.positive.add_assign_trunc::<9>(&product); + } else { + self.negative.add_assign_trunc::<9>(&product); + } + } + + #[inline] + fn merge(&mut self, other: Self) { + self.positive.add_assign_trunc::<9>(&other.positive); + self.negative.add_assign_trunc::<9>(&other.negative); + } + + #[inline] + fn reduce(self) -> Fr { + match self.positive.cmp(&self.negative) { + Ordering::Greater | Ordering::Equal => { + let difference = self.positive.sub_trunc::<9, 9>(&self.negative); + Fr::from_barrett_reduced_limbs(difference) + } + Ordering::Less => { + let difference = self.negative.sub_trunc::<9, 9>(&self.positive); + -Fr::from_barrett_reduced_limbs(difference) + } + } + } +} + +#[inline] +fn fmadd_i32_s128(sum: &mut S128, coefficient: i32, term: S128) { + if coefficient == 0 || term.magnitude_as_u128() == 0 { + return; + } + let coefficient_s64 = S64::from_i64(coefficient as i64); + *sum += coefficient_s64.mul_trunc::<2, 2>(&term); +} + +#[inline] +fn fmadd_i32_s192(sum: &mut S192, coefficient: i32, term: S192) { + if coefficient == 0 || term.magnitude_limbs() == [0u64; 3] { + return; + } + let coefficient_s64 = S64::from_i64(coefficient as i64); + *sum += coefficient_s64.mul_trunc::<3, 3>(&term); +} + +#[cfg(test)] +#[expect(clippy::expect_used, reason = "tests use explicit panic messages")] +mod tests { + use jolt_field::{Field, Fr}; + use jolt_r1cs::{constraints::rv64, R1csKey}; + + use super::*; + + static RV64_ORACLE_NAMES: &[&str] = &[ + "LeftInstructionInput", + "RightInstructionInput", + "Product", + "ShouldBranch", + "PC", + "UnexpandedPC", + "Imm", + "RamAddress", + "Rs1Value", + "Rs2Value", + "RdWriteValue", + "RamReadValue", + "RamWriteValue", + "LeftLookupOperand", + "RightLookupOperand", + "NextUnexpandedPC", + "NextPC", + "NextIsVirtual", + "NextIsFirstInSequence", + "LookupOutput", + "ShouldJump", + "OpFlagAddOperands", + "OpFlagSubtractOperands", + "OpFlagMultiplyOperands", + "OpFlagLoad", + "OpFlagStore", + "OpFlagJump", + "OpFlagWriteLookupOutputToRD", + "OpFlagVirtualInstruction", + "OpFlagAssert", + "OpFlagDoNotUpdateUnexpandedPC", + "OpFlagAdvice", + "OpFlagIsCompressed", + "OpFlagIsFirstInSequence", + "OpFlagIsLastInSequence", + ]; + + fn rv64_eval_test_cycles() -> Vec { + let mut first = Stage1Rv64Cycle::padding(); + first.left_input = 7; + first.right_input = S64::from_i64(-5); + first.product = S128::from_i128(-35); + first.left_lookup = 11; + first.right_lookup = u128::MAX - 4; + first.lookup_output = 1; + first.rs1_read_value = 13; + first.rs2_read_value = 17; + first.rd_write_value = 19; + first.ram_addr = 23; + first.ram_read_value = 29; + first.ram_write_value = 31; + first.pc = 37; + first.next_pc = 41; + first.unexpanded_pc = 43; + first.next_unexpanded_pc = 47; + first.imm = S64::from_i64(-53); + first.flags[FLAG_ADD_OPERANDS] = true; + first.flags[FLAG_LOAD] = true; + first.flags[FLAG_IS_FIRST_IN_SEQUENCE] = true; + first.should_branch = true; + first.next_is_virtual = true; + + let mut second = Stage1Rv64Cycle::padding(); + second.left_input = 59; + second.right_input = S64::from_u64(61); + second.product = S128::from_u128(3599); + second.left_lookup = 67; + second.right_lookup = 71; + second.lookup_output = 73; + second.rs1_read_value = 79; + second.rs2_read_value = 83; + second.rd_write_value = 89; + second.ram_addr = 97; + second.ram_read_value = 101; + second.ram_write_value = 103; + second.pc = 107; + second.next_pc = 109; + second.unexpanded_pc = 113; + second.next_unexpanded_pc = 127; + second.imm = S64::from_u64(131); + second.flags[FLAG_MULTIPLY_OPERANDS] = true; + second.flags[FLAG_STORE] = true; + second.flags[FLAG_JUMP] = true; + second.flags[FLAG_IS_LAST_IN_SEQUENCE] = true; + second.should_jump = true; + second.next_is_first_in_sequence = true; + + vec![first, second] + } + + fn rv64_eval_test_witness(key: &R1csKey, cycles: &[Stage1Rv64Cycle]) -> Vec { + let mut witness = vec![Fr::from_u64(0); key.num_cycles * key.num_vars_padded]; + for (cycle, row) in cycles.iter().enumerate() { + let base = cycle * key.num_vars_padded; + witness[base + rv64::V_CONST] = Fr::from_u64(1); + for name in RV64_ORACLE_NAMES { + let oracle = Stage1Rv64Oracle::from_name(name).expect("known RV64 oracle"); + let variable = + super::super::r1cs_oracle_variable(name).expect("known R1CS variable"); + witness[base + variable] = oracle.field_value(row); + } + } + witness + } + + #[test] + fn typed_virtual_oracle_evals_match_r1cs_columns() { + let cycles = rv64_eval_test_cycles(); + let key = R1csKey::new(rv64::rv64_constraints::(), cycles.len()); + let witness = rv64_eval_test_witness(&key, &cycles); + let r1cs_data = Stage1OuterR1csData::new(&key, &witness).expect("valid witness shape"); + let rv64_data = + Stage1OuterRv64Data::new(&key, &witness, &cycles).expect("valid RV64 shape"); + let tau = [Fr::from_u64(0); 3]; + let context = Stage1OuterRemainingContext { + tau: &tau, + r0: Fr::from_u64(0), + }; + + for point in [ + vec![Fr::from_u64(3), Fr::from_u64(5)], + vec![Fr::from_u64(3), Fr::from_u64(1)], + ] { + assert_eq!( + rv64_data.evaluate_virtual_oracles(context, RV64_ORACLE_NAMES, &point), + r1cs_data.evaluate_virtual_oracles(context, RV64_ORACLE_NAMES, &point) + ); + } + } +} diff --git a/crates/jolt-kernels/src/stage2.rs b/crates/jolt-kernels/src/stage2.rs new file mode 100644 index 0000000000..d62df82e0f --- /dev/null +++ b/crates/jolt-kernels/src/stage2.rs @@ -0,0 +1,5201 @@ +use std::borrow::Cow; +use std::cmp::Ordering; +use std::error::Error; +use std::fmt::{self, Display, Formatter}; +use std::mem::MaybeUninit; + +use crate::dense::{bind_dense_evals_reuse, DENSE_BIND_PAR_THRESHOLD}; +use crate::split_eq::SplitEqState; +use jolt_field::signed::{S128, S256}; +use jolt_field::{Field, FieldAccumulator, Fr, Limbs}; +use jolt_poly::lagrange::{interpolate_to_coeffs, lagrange_evals, lagrange_kernel_eval}; +use jolt_poly::EqPolynomial; +use jolt_poly::UnivariatePoly; +use jolt_sumcheck::SumcheckProof; +use jolt_transcript::{Label, LabelWithCount, Transcript}; +use rayon::prelude::*; + +const PRODUCT_VIRTUAL_UNISKIP_DOMAIN_START: i64 = -1; +const PRODUCT_VIRTUAL_UNISKIP_DOMAIN_SIZE: usize = 3; +const PRODUCT_VIRTUAL_UNISKIP_DEGREE: usize = 2; +const PRODUCT_VIRTUAL_UNISKIP_EXTENDED_START: i64 = -(PRODUCT_VIRTUAL_UNISKIP_DEGREE as i64); +const PRODUCT_VIRTUAL_UNISKIP_EXTENDED_SIZE: usize = 2 * PRODUCT_VIRTUAL_UNISKIP_DEGREE + 1; +const PRODUCT_VIRTUAL_UNISKIP_NUM_COEFFS: usize = 3 * PRODUCT_VIRTUAL_UNISKIP_DEGREE + 1; +const PRODUCT_VIRTUAL_UNISKIP_TARGET_COEFFS: [[i32; PRODUCT_VIRTUAL_UNISKIP_DOMAIN_SIZE]; + PRODUCT_VIRTUAL_UNISKIP_DEGREE] = [[3, -3, 1], [1, -3, 3]]; +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Stage2ExecutionMode { + Prover, + Verifier, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Stage2Relation { + ProductVirtualUniskip, + RamReadWrite, + ProductVirtualRemainder, + InstructionLookupClaimReduction, + RamRafEvaluation, + RamOutputCheck, + Batched, +} + +impl Stage2Relation { + pub fn from_symbol(symbol: &str) -> Option { + match symbol { + "jolt.stage2.product_virtual.uniskip" => Some(Self::ProductVirtualUniskip), + "jolt.stage2.ram.read_write" => Some(Self::RamReadWrite), + "jolt.stage2.product_virtual.remainder" => Some(Self::ProductVirtualRemainder), + "jolt.stage2.instruction_lookup.claim_reduction" => { + Some(Self::InstructionLookupClaimReduction) + } + "jolt.stage2.ram.raf_evaluation" => Some(Self::RamRafEvaluation), + "jolt.stage2.ram.output_check" => Some(Self::RamOutputCheck), + "jolt.stage2.batched" => Some(Self::Batched), + _ => None, + } + } + + pub fn symbol(self) -> &'static str { + match self { + Self::ProductVirtualUniskip => "jolt.stage2.product_virtual.uniskip", + Self::RamReadWrite => "jolt.stage2.ram.read_write", + Self::ProductVirtualRemainder => "jolt.stage2.product_virtual.remainder", + Self::InstructionLookupClaimReduction => { + "jolt.stage2.instruction_lookup.claim_reduction" + } + Self::RamRafEvaluation => "jolt.stage2.ram.raf_evaluation", + Self::RamOutputCheck => "jolt.stage2.ram.output_check", + Self::Batched => "jolt.stage2.batched", + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Stage2KernelAbi { + ProductVirtualUniskip, + RamReadWrite, + ProductVirtualRemainder, + InstructionLookupClaimReduction, + RamRafEvaluation, + RamOutputCheck, + Batched, +} + +impl Stage2KernelAbi { + pub fn from_name(name: &str) -> Option { + match name { + "jolt_stage2_product_virtual_uniskip" => Some(Self::ProductVirtualUniskip), + "jolt_stage2_ram_read_write" => Some(Self::RamReadWrite), + "jolt_stage2_product_virtual_remainder" => Some(Self::ProductVirtualRemainder), + "jolt_stage2_instruction_lookup_claim_reduction" => { + Some(Self::InstructionLookupClaimReduction) + } + "jolt_stage2_ram_raf_evaluation" => Some(Self::RamRafEvaluation), + "jolt_stage2_ram_output_check" => Some(Self::RamOutputCheck), + "jolt_stage2_batched" => Some(Self::Batched), + _ => None, + } + } + + pub fn name(self) -> &'static str { + match self { + Self::ProductVirtualUniskip => "jolt_stage2_product_virtual_uniskip", + Self::RamReadWrite => "jolt_stage2_ram_read_write", + Self::ProductVirtualRemainder => "jolt_stage2_product_virtual_remainder", + Self::InstructionLookupClaimReduction => { + "jolt_stage2_instruction_lookup_claim_reduction" + } + Self::RamRafEvaluation => "jolt_stage2_ram_raf_evaluation", + Self::RamOutputCheck => "jolt_stage2_ram_output_check", + Self::Batched => "jolt_stage2_batched", + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage2Params { + pub field: &'static str, + pub pcs: &'static str, + pub transcript: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage2KernelPlan { + pub symbol: &'static str, + pub relation: &'static str, + pub kind: &'static str, + pub backend: &'static str, + pub abi: &'static str, +} + +impl Stage2KernelPlan { + pub fn relation_kind(&self) -> Result { + Stage2Relation::from_symbol(self.relation).ok_or(Stage2KernelError::UnknownRelation { + relation: self.relation, + }) + } + + pub fn abi_kind(&self) -> Result { + Stage2KernelAbi::from_name(self.abi) + .ok_or(Stage2KernelError::UnknownKernelAbi { abi: self.abi }) + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage2TranscriptSqueezePlan { + pub symbol: &'static str, + pub label: &'static str, + pub kind: &'static str, + pub count: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage2OpeningInputPlan { + pub symbol: &'static str, + pub source_stage: &'static str, + pub source_claim: &'static str, + pub oracle: &'static str, + pub domain: &'static str, + pub point_arity: usize, + pub claim_kind: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage2FieldConstantPlan { + pub symbol: &'static str, + pub field: &'static str, + pub value: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage2FieldExprPlan { + pub symbol: &'static str, + pub kind: &'static str, + pub formula: &'static str, + pub operand_names: &'static [&'static str], + pub operands: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage2SumcheckClaimPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub domain: &'static str, + pub num_rounds: usize, + pub degree: usize, + pub claim: &'static str, + pub kernel: Option<&'static str>, + pub relation: Option<&'static str>, + pub claim_value: &'static str, + pub input_openings: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage2SumcheckBatchPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub proof_slot: &'static str, + pub policy: &'static str, + pub count: usize, + pub ordered_claims: &'static [&'static str], + pub claim_operands: &'static [&'static str], + pub claim_label: &'static str, + pub round_label: &'static str, + pub round_schedule: &'static [usize], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage2SumcheckDriverPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub proof_slot: &'static str, + pub kernel: Option<&'static str>, + pub relation: Option<&'static str>, + pub batch: &'static str, + pub policy: &'static str, + pub round_schedule: &'static [usize], + pub claim_label: &'static str, + pub round_label: &'static str, + pub num_rounds: usize, + pub degree: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage2SumcheckInstanceResultPlan { + pub symbol: &'static str, + pub source: &'static str, + pub claim: &'static str, + pub relation: &'static str, + pub index: usize, + pub point_arity: usize, + pub num_rounds: usize, + pub round_offset: usize, + pub point_order: &'static str, + pub degree: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage2SumcheckEvalPlan { + pub symbol: &'static str, + pub source: &'static str, + pub name: &'static str, + pub index: usize, + pub oracle: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage2PointSlicePlan { + pub symbol: &'static str, + pub source: &'static str, + pub offset: usize, + pub length: usize, + pub input: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage2PointConcatPlan { + pub symbol: &'static str, + pub layout: &'static str, + pub arity: usize, + pub inputs: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage2OpeningClaimPlan { + pub symbol: &'static str, + pub oracle: &'static str, + pub domain: &'static str, + pub point_arity: usize, + pub claim_kind: &'static str, + pub point_source: &'static str, + pub eval_source: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage2OpeningBatchPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub proof_slot: &'static str, + pub policy: &'static str, + pub count: usize, + pub ordered_claims: &'static [&'static str], + pub claim_operands: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage2ProgramStepPlan { + pub kind: &'static str, + pub symbol: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage2CpuProgramPlan { + pub params: Stage2Params, + pub steps: &'static [Stage2ProgramStepPlan], + pub transcript_squeezes: &'static [Stage2TranscriptSqueezePlan], + pub opening_inputs: &'static [Stage2OpeningInputPlan], + pub field_constants: &'static [Stage2FieldConstantPlan], + pub field_exprs: &'static [Stage2FieldExprPlan], + pub kernels: &'static [Stage2KernelPlan], + pub claims: &'static [Stage2SumcheckClaimPlan], + pub batches: &'static [Stage2SumcheckBatchPlan], + pub drivers: &'static [Stage2SumcheckDriverPlan], + pub instance_results: &'static [Stage2SumcheckInstanceResultPlan], + pub evals: &'static [Stage2SumcheckEvalPlan], + pub point_slices: &'static [Stage2PointSlicePlan], + pub point_concats: &'static [Stage2PointConcatPlan], + pub opening_claims: &'static [Stage2OpeningClaimPlan], + pub opening_batches: &'static [Stage2OpeningBatchPlan], +} + +impl Stage2CpuProgramPlan { + pub fn kernel(&self, symbol: &str) -> Option<&Stage2KernelPlan> { + find_kernel(self, symbol) + } + + pub fn batch(&self, symbol: &str) -> Option<&Stage2SumcheckBatchPlan> { + find_batch(self, symbol) + } + + pub fn claim(&self, symbol: &str) -> Option<&Stage2SumcheckClaimPlan> { + self.claims.iter().find(|claim| claim.symbol == symbol) + } + + pub fn evals_for_driver<'a>( + &'a self, + driver: &'a str, + ) -> impl Iterator + 'a { + self.evals.iter().filter(move |eval| eval.source == driver) + } + + pub fn instance_results_for_driver<'a>( + &'a self, + driver: &'a str, + ) -> impl Iterator + 'a { + self.instance_results + .iter() + .filter(move |instance| instance.source == driver) + } +} + +#[derive(Clone, Debug)] +pub struct Stage2NamedEval { + pub name: &'static str, + pub oracle: &'static str, + pub value: F, +} + +#[derive(Clone, Debug)] +pub struct Stage2SumcheckOutput { + pub driver: &'static str, + pub point: Vec, + pub evals: Vec>, + pub opening_claims: Vec>, + pub proof: SumcheckProof, +} + +#[derive(Clone, Debug)] +pub struct Stage2ChallengeVector { + pub symbol: &'static str, + pub values: Vec, +} + +#[derive(Clone, Debug)] +pub struct Stage2OpeningClaimValue { + pub symbol: &'static str, + pub oracle: &'static str, + pub domain: &'static str, + pub claim_kind: &'static str, + pub point: Vec, + pub eval: F, +} + +#[derive(Clone, Debug)] +pub struct Stage2ExecutionArtifacts { + pub challenge_vectors: Vec>, + pub sumchecks: Vec>, + pub opening_claims: Vec>, + pub opening_batches: Vec<&'static Stage2OpeningBatchPlan>, +} + +impl Default for Stage2ExecutionArtifacts { + fn default() -> Self { + Self { + challenge_vectors: Vec::new(), + sumchecks: Vec::new(), + opening_claims: Vec::new(), + opening_batches: Vec::new(), + } + } +} + +#[derive(Clone, Debug, Default)] +pub struct Stage2Proof { + pub sumchecks: Vec>, +} + +impl From> for Stage2Proof { + fn from(artifacts: Stage2ExecutionArtifacts) -> Self { + Self { + sumchecks: artifacts.sumchecks, + } + } +} + +#[derive(Clone, Debug)] +pub struct Stage2ScalarValue { + pub symbol: &'static str, + pub value: F, +} + +#[derive(Clone, Debug)] +pub struct Stage2PointValue { + pub symbol: &'static str, + pub point: Vec, +} + +#[derive(Clone, Debug)] +pub struct Stage2OpeningInputValue { + pub symbol: &'static str, + pub point: Vec, + pub eval: F, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage2ProductVirtualCycle { + pub instruction_left_input: u64, + pub instruction_right_input: i128, + pub should_branch_lookup_output: u64, + pub write_lookup_output_to_rd_flag: bool, + pub jump_flag: bool, + pub should_branch_flag: bool, + pub not_next_noop: bool, + pub virtual_instruction_flag: bool, +} + +impl Stage2ProductVirtualCycle { + pub fn padding() -> Self { + Self { + instruction_left_input: 0, + instruction_right_input: 0, + should_branch_lookup_output: 0, + write_lookup_output_to_rd_flag: false, + jump_flag: false, + should_branch_flag: false, + not_next_noop: false, + virtual_instruction_flag: false, + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage2InstructionLookupCycle { + pub lookup_output: u64, + pub left_lookup_operand: u64, + pub right_lookup_operand: u128, + pub left_instruction_input: u64, + pub right_instruction_input: i128, +} + +impl Stage2InstructionLookupCycle { + pub fn padding() -> Self { + Self { + lookup_output: 0, + left_lookup_operand: 0, + right_lookup_operand: 0, + left_instruction_input: 0, + right_instruction_input: 0, + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage2RamAccess { + pub remapped_address: Option, + pub read_value: u64, + pub write_value: u64, +} + +impl Stage2RamAccess { + pub fn noop() -> Self { + Self { + remapped_address: None, + read_value: 0, + write_value: 0, + } + } +} + +#[derive(Clone, Copy, Debug)] +pub struct Stage2RamOutputLayout { + pub io_start: usize, + pub io_end: usize, +} + +#[derive(Clone, Copy, Debug)] +pub struct Stage2RamData<'a> { + pub log_k: usize, + pub start_address: u64, + pub initial_ram: &'a [u64], + pub final_ram: &'a [u64], + pub accesses: &'a [Stage2RamAccess], + pub output_layout: Option, +} + +#[derive(Clone, Debug, Default)] +pub struct Stage2ValueStore { + scalars: Vec>, + points: Vec>, +} + +impl Stage2ValueStore { + pub fn new() -> Self { + Self::default() + } + + pub fn with_opening_inputs(inputs: &[Stage2OpeningInputValue]) -> Self { + let mut store = Self::new(); + store.insert_opening_inputs(inputs); + store + } + + pub fn insert_opening_inputs(&mut self, inputs: &[Stage2OpeningInputValue]) { + for input in inputs { + self.insert_scalar(input.symbol, input.eval); + self.insert_point(input.symbol, input.point.clone()); + } + } + + pub fn insert_scalar(&mut self, symbol: &'static str, value: F) { + if let Some(existing) = self + .scalars + .iter_mut() + .find(|existing| existing.symbol == symbol) + { + existing.value = value; + } else { + self.scalars.push(Stage2ScalarValue { symbol, value }); + } + } + + pub fn insert_point(&mut self, symbol: &'static str, point: Vec) { + if let Some(existing) = self + .points + .iter_mut() + .find(|existing| existing.symbol == symbol) + { + existing.point = point; + } else { + self.points.push(Stage2PointValue { symbol, point }); + } + } + + pub fn try_scalar(&self, symbol: &str) -> Option { + self.scalars + .iter() + .find(|value| value.symbol == symbol) + .map(|value| value.value) + } + + pub fn scalar(&self, symbol: &'static str) -> Result { + self.try_scalar(symbol) + .ok_or(Stage2KernelError::MissingValue { symbol }) + } + + pub fn point(&self, symbol: &'static str) -> Result<&[F], Stage2KernelError> { + self.try_point(symbol) + .ok_or(Stage2KernelError::MissingValue { symbol }) + } + + pub fn try_point(&self, symbol: &str) -> Option<&[F]> { + self.points + .iter() + .find(|value| value.symbol == symbol) + .map(|value| value.point.as_slice()) + } + + pub fn seed_constants( + &mut self, + program: &'static Stage2CpuProgramPlan, + ) -> Result<(), Stage2KernelError> { + for constant in program.field_constants { + self.insert_scalar(constant.symbol, F::from_u64(constant.value as u64)); + } + Ok(()) + } + + pub fn observe_challenge_vector( + &mut self, + _program: &'static Stage2CpuProgramPlan, + plan: &'static Stage2TranscriptSqueezePlan, + values: &[F], + ) -> Result<(), Stage2KernelError> { + if matches!(plan.kind, "challenge_scalar" | "scalar") { + if values.len() != 1 { + return Err(Stage2KernelError::InvalidInputLength { + input: plan.symbol, + expected: 1, + actual: values.len(), + }); + } + self.insert_scalar(plan.symbol, values[0]); + } + Ok(()) + } + + pub fn observe_sumcheck_output( + &mut self, + program: &'static Stage2CpuProgramPlan, + output: &Stage2SumcheckOutput, + ) -> Result<(), Stage2KernelError> { + self.observe_sumcheck_values(program, output.driver, &output.point, &output.evals) + } + + pub fn observe_sumcheck_values( + &mut self, + program: &'static Stage2CpuProgramPlan, + driver: &'static str, + point: &[F], + evals: &[Stage2NamedEval], + ) -> Result<(), Stage2KernelError> { + self.insert_point(driver, point.to_vec()); + for instance in program.instance_results_for_driver(driver) { + let end = instance.round_offset + instance.point_arity; + let mut point = point + .get(instance.round_offset..end) + .ok_or(Stage2KernelError::InvalidInputLength { + input: instance.symbol, + expected: end, + actual: point.len(), + })? + .to_vec(); + match instance.point_order { + "as_is" => {} + "reverse" => point.reverse(), + _ => { + return Err(Stage2KernelError::InvalidProof { + driver, + reason: "unsupported point order", + }); + } + } + self.insert_point(instance.symbol, point); + } + for eval in program.evals_for_driver(driver) { + let value = evals + .iter() + .find(|value| value.name == eval.name) + .or_else(|| evals.get(eval.index)) + .ok_or(Stage2KernelError::MissingValue { + symbol: eval.symbol, + })? + .value; + self.insert_scalar(eval.symbol, value); + self.insert_scalar(eval.name, value); + } + Ok(()) + } + + pub fn evaluate_available_points( + &mut self, + program: &'static Stage2CpuProgramPlan, + ) -> Result { + let mut inserted = 0usize; + loop { + let mut progress = 0usize; + for slice in program.point_slices { + if self.try_point(slice.symbol).is_some() { + continue; + } + let Some(input) = self.try_point(slice.input) else { + continue; + }; + let end = slice.offset + slice.length; + let point = input + .get(slice.offset..end) + .ok_or(Stage2KernelError::InvalidInputLength { + input: slice.symbol, + expected: end, + actual: input.len(), + })? + .to_vec(); + self.insert_point(slice.symbol, point); + progress += 1; + } + for concat in program.point_concats { + if self.try_point(concat.symbol).is_some() { + continue; + } + let Some(point) = self.try_concat_point(concat) else { + continue; + }; + verify_count(concat.symbol, concat.arity, point.len())?; + self.insert_point(concat.symbol, point); + progress += 1; + } + inserted += progress; + if progress == 0 { + return Ok(inserted); + } + } + } + + pub fn evaluate_available_field_exprs( + &mut self, + program: &'static Stage2CpuProgramPlan, + ) -> Result { + let mut inserted = 0usize; + loop { + let mut progress = 0usize; + for expr in program.field_exprs { + if self.try_scalar(expr.symbol).is_some() { + continue; + } + let Some(operands) = self.try_expr_operands(expr) else { + continue; + }; + let value = evaluate_stage2_field_expr(expr, &operands)?; + self.insert_scalar(expr.symbol, value); + progress += 1; + } + inserted += progress; + if progress == 0 { + return Ok(inserted); + } + } + } + + pub fn claim_value( + &mut self, + program: &'static Stage2CpuProgramPlan, + claim: &Stage2SumcheckClaimPlan, + ) -> Result { + let _ = self.evaluate_available_field_exprs(program)?; + self.scalar(claim.claim_value) + } + + pub fn batch_claim_values( + &mut self, + program: &'static Stage2CpuProgramPlan, + batch: &Stage2SumcheckBatchPlan, + ) -> Result, Stage2KernelError> { + batch + .claim_operands + .iter() + .map(|symbol| { + let claim = program + .claim(symbol) + .ok_or(Stage2KernelError::MissingClaim { + batch: batch.symbol, + claim: symbol, + })?; + self.claim_value(program, claim) + }) + .collect() + } + + fn try_expr_operands(&self, expr: &Stage2FieldExprPlan) -> Option> { + expr.operands + .iter() + .map(|operand| self.try_scalar(operand)) + .collect() + } + + fn try_concat_point(&self, concat: &Stage2PointConcatPlan) -> Option> { + let mut point = Vec::with_capacity(concat.arity); + for input in concat.inputs { + point.extend_from_slice(self.try_point(input)?); + } + Some(point) + } +} + +pub fn evaluate_stage2_field_expr( + expr: &Stage2FieldExprPlan, + operands: &[F], +) -> Result { + if let Some(value) = evaluate_stage2_field_op(expr, operands)? { + return Ok(value); + } + match expr.formula { + "opening_eval" => single_operand(expr.symbol, operands), + "jolt_stage2_product_virtual_uniskip_input" => { + require_operand_count(expr.symbol, 4, operands.len())?; + let weights = lagrange_evals( + PRODUCT_VIRTUAL_UNISKIP_DOMAIN_START, + PRODUCT_VIRTUAL_UNISKIP_DOMAIN_SIZE, + operands[0], + ); + Ok(weights[0] * operands[1] + weights[1] * operands[2] + weights[2] * operands[3]) + } + "jolt_stage2_ram_read_write_input" => { + require_operand_count(expr.symbol, 3, operands.len())?; + Ok(operands[1] + operands[0] * operands[2]) + } + "jolt_stage2_instruction_lookup_input" => { + require_operand_count(expr.symbol, 6, operands.len())?; + let gamma = operands[0]; + let gamma_sqr = gamma.square(); + let gamma_cub = gamma_sqr * gamma; + let gamma_quart = gamma_sqr.square(); + Ok(operands[1] + + gamma * operands[2] + + gamma_sqr * operands[3] + + gamma_cub * operands[4] + + gamma_quart * operands[5]) + } + formula => Err(Stage2KernelError::UnsupportedFieldExpr { + symbol: expr.symbol, + formula, + }), + } +} + +fn evaluate_stage2_field_op( + expr: &Stage2FieldExprPlan, + operands: &[F], +) -> Result, Stage2KernelError> { + match expr.formula { + "field.add" => { + require_operand_count(expr.symbol, 2, operands.len())?; + Ok(Some(operands[0] + operands[1])) + } + "field.sub" => { + require_operand_count(expr.symbol, 2, operands.len())?; + Ok(Some(operands[0] - operands[1])) + } + "field.mul" => { + require_operand_count(expr.symbol, 2, operands.len())?; + Ok(Some(operands[0] * operands[1])) + } + "field.neg" => { + require_operand_count(expr.symbol, 1, operands.len())?; + Ok(Some(-operands[0])) + } + _ => { + if let Some(exponent) = expr.formula.strip_prefix("field.pow:") { + require_operand_count(expr.symbol, 1, operands.len())?; + let exponent = exponent.parse::().map_err(|_| { + Stage2KernelError::UnsupportedFieldExpr { + symbol: expr.symbol, + formula: expr.formula, + } + })?; + return Ok(Some(pow_field(operands[0], exponent))); + } + if let Some(spec) = expr.formula.strip_prefix("poly.lagrange_basis_eval:") { + require_operand_count(expr.symbol, 1, operands.len())?; + let (domain_start, domain_size, index) = parse_lagrange_basis_spec(expr, spec)?; + let weights = lagrange_evals(domain_start, domain_size, operands[0]); + let value = + weights + .get(index) + .copied() + .ok_or(Stage2KernelError::InvalidInputLength { + input: expr.symbol, + expected: index + 1, + actual: weights.len(), + })?; + return Ok(Some(value)); + } + Ok(None) + } + } +} + +fn parse_lagrange_basis_spec( + expr: &Stage2FieldExprPlan, + spec: &str, +) -> Result<(i64, usize, usize), Stage2KernelError> { + let parts = spec.split(':').collect::>(); + if parts.len() != 3 { + return Err(Stage2KernelError::UnsupportedFieldExpr { + symbol: expr.symbol, + formula: expr.formula, + }); + } + let domain_start = + parts[0] + .parse::() + .map_err(|_| Stage2KernelError::UnsupportedFieldExpr { + symbol: expr.symbol, + formula: expr.formula, + })?; + let domain_size = + parts[1] + .parse::() + .map_err(|_| Stage2KernelError::UnsupportedFieldExpr { + symbol: expr.symbol, + formula: expr.formula, + })?; + let index = parts[2] + .parse::() + .map_err(|_| Stage2KernelError::UnsupportedFieldExpr { + symbol: expr.symbol, + formula: expr.formula, + })?; + Ok((domain_start, domain_size, index)) +} + +fn pow_field(base: F, mut exponent: usize) -> F { + let mut result = F::one(); + let mut power = base; + while exponent != 0 { + if exponent & 1 == 1 { + result *= power; + } + power = power.square(); + exponent >>= 1; + } + result +} + +fn single_operand(symbol: &'static str, operands: &[F]) -> Result { + require_operand_count(symbol, 1, operands.len())?; + Ok(operands[0]) +} + +fn require_operand_count( + input: &'static str, + expected: usize, + actual: usize, +) -> Result<(), Stage2KernelError> { + if expected == actual { + Ok(()) + } else { + Err(Stage2KernelError::InvalidInputLength { + input, + expected, + actual, + }) + } +} + +#[derive(Clone, Copy, Debug)] +pub struct Stage2KernelContext<'a> { + pub mode: Stage2ExecutionMode, + pub program: &'static Stage2CpuProgramPlan, + pub kernel: &'a Stage2KernelPlan, + pub batch: &'a Stage2SumcheckBatchPlan, + pub driver: &'a Stage2SumcheckDriverPlan, +} + +impl Stage2KernelContext<'_> { + pub fn relation_kind(&self) -> Result { + self.kernel.relation_kind() + } + + pub fn abi_kind(&self) -> Result { + self.kernel.abi_kind() + } + + pub fn batch_claims(&self) -> Result, Stage2KernelError> { + self.batch + .claim_operands + .iter() + .map(|symbol| { + self.program + .claim(symbol) + .ok_or(Stage2KernelError::MissingClaim { + batch: self.batch.symbol, + claim: symbol, + }) + }) + .collect() + } +} + +pub trait Stage2KernelExecutor { + fn observe_challenge_vector( + &mut self, + _plan: &'static Stage2TranscriptSqueezePlan, + _values: &[F], + ) -> Result<(), Stage2KernelError> { + Ok(()) + } + + fn observe_sumcheck_output( + &mut self, + _output: &Stage2SumcheckOutput, + ) -> Result<(), Stage2KernelError> { + Ok(()) + } + + fn prove_sumcheck( + &mut self, + context: Stage2KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage2KernelError> + where + T: Transcript; + + fn verify_sumcheck( + &mut self, + context: Stage2KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage2KernelError> + where + T: Transcript; +} + +#[derive(Clone, Debug, Default)] +pub struct UnsupportedStage2KernelExecutor; + +impl Stage2KernelExecutor for UnsupportedStage2KernelExecutor { + fn prove_sumcheck( + &mut self, + context: Stage2KernelContext<'_>, + _transcript: &mut T, + ) -> Result, Stage2KernelError> + where + T: Transcript, + { + Err(Stage2KernelError::KernelNotImplemented { + abi: context.kernel.abi, + }) + } + + fn verify_sumcheck( + &mut self, + context: Stage2KernelContext<'_>, + _transcript: &mut T, + ) -> Result, Stage2KernelError> + where + T: Transcript, + { + Err(Stage2KernelError::KernelNotImplemented { + abi: context.kernel.abi, + }) + } +} + +#[derive(Clone)] +pub struct Stage2ProverInputs<'a, F: Field> { + pub opening_inputs: &'a [Stage2OpeningInputValue], + pub product_uniskip_extended_evals: Option>, + pub product_virtual_cycles: Option<&'a [Stage2ProductVirtualCycle]>, + pub instruction_lookup_cycles: Option<&'a [Stage2InstructionLookupCycle]>, + pub ram: Option<&'a Stage2RamData<'a>>, +} + +impl<'a, F: Field> Stage2ProverInputs<'a, F> { + pub fn new(opening_inputs: &'a [Stage2OpeningInputValue]) -> Self { + Self { + opening_inputs, + product_uniskip_extended_evals: None, + product_virtual_cycles: None, + instruction_lookup_cycles: None, + ram: None, + } + } + + pub fn empty() -> Self { + Self { + opening_inputs: &[], + product_uniskip_extended_evals: None, + product_virtual_cycles: None, + instruction_lookup_cycles: None, + ram: None, + } + } + + pub fn with_product_uniskip_extended_evals(mut self, evaluations: &'a [F]) -> Self { + self.product_uniskip_extended_evals = Some(Cow::Borrowed(evaluations)); + self + } + + pub fn with_product_virtual_cycles(mut self, cycles: &'a [Stage2ProductVirtualCycle]) -> Self { + self.product_virtual_cycles = Some(cycles); + self + } + + pub fn with_instruction_lookup_cycles( + mut self, + cycles: &'a [Stage2InstructionLookupCycle], + ) -> Self { + self.instruction_lookup_cycles = Some(cycles); + self + } + + pub fn with_ram_data(mut self, ram: &'a Stage2RamData<'a>) -> Self { + self.ram = Some(ram); + self + } +} + +impl<'a> Stage2ProverInputs<'a, Fr> { + pub fn with_product_virtual_witness( + mut self, + cycles: &'a [Stage2ProductVirtualCycle], + ) -> Result { + let tau_low = self + .opening_inputs + .iter() + .find(|input| input.symbol == "stage2.input.stage1.Product") + .map(|input| input.point.as_slice()) + .ok_or(Stage2KernelError::MissingValue { + symbol: "stage2.input.stage1.Product", + })?; + let extended_evals = product_virtual_uniskip_extended_evals(cycles, tau_low)?; + self.product_uniskip_extended_evals = Some(Cow::Owned(extended_evals.to_vec())); + self.product_virtual_cycles = Some(cycles); + Ok(self) + } +} + +#[derive(Clone)] +pub struct Stage2ProverKernelExecutor<'a, F: Field> { + pub inputs: Stage2ProverInputs<'a, F>, + challenge_vectors: Vec>, + completed_sumchecks: Vec>, +} + +impl<'a, F: Field> Stage2ProverKernelExecutor<'a, F> { + pub fn new(inputs: Stage2ProverInputs<'a, F>) -> Self { + Self { + inputs, + challenge_vectors: Vec::new(), + completed_sumchecks: Vec::new(), + } + } + + fn value_store( + &self, + program: &'static Stage2CpuProgramPlan, + ) -> Result, Stage2KernelError> { + let mut store = Stage2ValueStore::with_opening_inputs(self.inputs.opening_inputs); + store.seed_constants(program)?; + for challenge in &self.challenge_vectors { + store.insert_point(challenge.symbol, challenge.values.clone()); + if let Some(plan) = program + .transcript_squeezes + .iter() + .find(|plan| plan.symbol == challenge.symbol) + .filter(|plan| matches!(plan.kind, "challenge_scalar" | "scalar")) + { + if challenge.values.len() != 1 { + return Err(Stage2KernelError::InvalidInputLength { + input: plan.symbol, + expected: 1, + actual: challenge.values.len(), + }); + } + store.insert_scalar(plan.symbol, challenge.values[0]); + } + } + for output in &self.completed_sumchecks { + store.observe_sumcheck_output(program, output)?; + } + let _ = store.evaluate_available_points(program)?; + let _ = store.evaluate_available_field_exprs(program)?; + Ok(store) + } +} + +impl Stage2KernelExecutor for Stage2ProverKernelExecutor<'_, F> { + fn observe_challenge_vector( + &mut self, + plan: &'static Stage2TranscriptSqueezePlan, + values: &[F], + ) -> Result<(), Stage2KernelError> { + self.challenge_vectors.push(Stage2ChallengeVector { + symbol: plan.symbol, + values: values.to_vec(), + }); + Ok(()) + } + + fn observe_sumcheck_output( + &mut self, + output: &Stage2SumcheckOutput, + ) -> Result<(), Stage2KernelError> { + self.completed_sumchecks.push(output.clone()); + Ok(()) + } + + fn prove_sumcheck( + &mut self, + context: Stage2KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage2KernelError> + where + T: Transcript, + { + prove_stage2_kernel( + context, + &self.inputs, + self.value_store(context.program)?, + transcript, + ) + } + + fn verify_sumcheck( + &mut self, + context: Stage2KernelContext<'_>, + _transcript: &mut T, + ) -> Result, Stage2KernelError> + where + T: Transcript, + { + Err(Stage2KernelError::WrongExecutorMode { + driver: context.driver.symbol, + expected: Stage2ExecutionMode::Prover, + actual: Stage2ExecutionMode::Verifier, + }) + } +} + +#[derive(Clone)] +pub struct Stage2VerifierKernelExecutor<'a, F: Field> { + pub proof: &'a Stage2Proof, + pub opening_inputs: &'a [Stage2OpeningInputValue], + pub ram: Option<&'a Stage2RamData<'a>>, + pub cursor: usize, + challenge_vectors: Vec>, + completed_sumchecks: Vec>, +} + +impl<'a, F: Field> Stage2VerifierKernelExecutor<'a, F> { + pub fn new( + proof: &'a Stage2Proof, + opening_inputs: &'a [Stage2OpeningInputValue], + ) -> Self { + Self { + proof, + opening_inputs, + ram: None, + cursor: 0, + challenge_vectors: Vec::new(), + completed_sumchecks: Vec::new(), + } + } + + pub fn with_ram_data(mut self, ram: &'a Stage2RamData<'a>) -> Self { + self.ram = Some(ram); + self + } + + fn value_store( + &self, + program: &'static Stage2CpuProgramPlan, + ) -> Result, Stage2KernelError> { + let mut store = Stage2ValueStore::with_opening_inputs(self.opening_inputs); + store.seed_constants(program)?; + for challenge in &self.challenge_vectors { + store.insert_point(challenge.symbol, challenge.values.clone()); + if let Some(plan) = program + .transcript_squeezes + .iter() + .find(|plan| plan.symbol == challenge.symbol) + .filter(|plan| matches!(plan.kind, "challenge_scalar" | "scalar")) + { + if challenge.values.len() != 1 { + return Err(Stage2KernelError::InvalidInputLength { + input: plan.symbol, + expected: 1, + actual: challenge.values.len(), + }); + } + store.insert_scalar(plan.symbol, challenge.values[0]); + } + } + for output in &self.completed_sumchecks { + store.observe_sumcheck_output(program, output)?; + } + let _ = store.evaluate_available_points(program)?; + let _ = store.evaluate_available_field_exprs(program)?; + Ok(store) + } +} + +impl Stage2KernelExecutor for Stage2VerifierKernelExecutor<'_, F> { + fn observe_challenge_vector( + &mut self, + plan: &'static Stage2TranscriptSqueezePlan, + values: &[F], + ) -> Result<(), Stage2KernelError> { + self.challenge_vectors.push(Stage2ChallengeVector { + symbol: plan.symbol, + values: values.to_vec(), + }); + Ok(()) + } + + fn observe_sumcheck_output( + &mut self, + output: &Stage2SumcheckOutput, + ) -> Result<(), Stage2KernelError> { + self.completed_sumchecks.push(output.clone()); + Ok(()) + } + + fn prove_sumcheck( + &mut self, + context: Stage2KernelContext<'_>, + _transcript: &mut T, + ) -> Result, Stage2KernelError> + where + T: Transcript, + { + Err(Stage2KernelError::WrongExecutorMode { + driver: context.driver.symbol, + expected: Stage2ExecutionMode::Verifier, + actual: Stage2ExecutionMode::Prover, + }) + } + + fn verify_sumcheck( + &mut self, + context: Stage2KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage2KernelError> + where + T: Transcript, + { + let proof = + self.proof + .sumchecks + .get(self.cursor) + .ok_or(Stage2KernelError::MissingProof { + driver: context.driver.symbol, + })?; + self.cursor += 1; + verify_stage2_kernel( + context, + self.value_store(context.program)?, + proof, + self.ram, + transcript, + ) + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum Stage2KernelError { + MissingKernel { + driver: &'static str, + kernel: &'static str, + }, + MissingBatch { + driver: &'static str, + batch: &'static str, + }, + MissingClaim { + batch: &'static str, + claim: &'static str, + }, + MissingValue { + symbol: &'static str, + }, + PlanCountMismatch { + artifact: &'static str, + expected: usize, + actual: usize, + }, + InvalidInputLength { + input: &'static str, + expected: usize, + actual: usize, + }, + UnsupportedFieldExpr { + symbol: &'static str, + formula: &'static str, + }, + UnknownRelation { + relation: &'static str, + }, + UnknownKernelAbi { + abi: &'static str, + }, + KernelNotImplemented { + abi: &'static str, + }, + WrongExecutorMode { + driver: &'static str, + expected: Stage2ExecutionMode, + actual: Stage2ExecutionMode, + }, + MissingProof { + driver: &'static str, + }, + MissingKernelInput { + kernel: &'static str, + input: &'static str, + }, + InvalidProof { + driver: &'static str, + reason: &'static str, + }, +} + +impl Display for Stage2KernelError { + fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result { + match self { + Self::MissingKernel { driver, kernel } => { + write!( + formatter, + "stage2 driver @{driver} references missing kernel @{kernel}" + ) + } + Self::MissingBatch { driver, batch } => { + write!( + formatter, + "stage2 driver @{driver} references missing batch @{batch}" + ) + } + Self::MissingClaim { batch, claim } => { + write!( + formatter, + "stage2 batch @{batch} references missing claim @{claim}" + ) + } + Self::MissingValue { symbol } => { + write!(formatter, "stage2 value @{symbol} is not available") + } + Self::PlanCountMismatch { + artifact, + expected, + actual, + } => write!( + formatter, + "stage2 plan @{artifact} count mismatch: expected {expected}, got {actual}" + ), + Self::InvalidInputLength { + input, + expected, + actual, + } => write!( + formatter, + "stage2 input `{input}` length mismatch: expected {expected}, got {actual}" + ), + Self::UnsupportedFieldExpr { symbol, formula } => write!( + formatter, + "stage2 field expr @{symbol} uses unsupported formula `{formula}`" + ), + Self::UnknownRelation { relation } => { + write!(formatter, "stage2 relation @{relation} is not registered") + } + Self::UnknownKernelAbi { abi } => { + write!(formatter, "stage2 kernel ABI `{abi}` is not registered") + } + Self::KernelNotImplemented { abi } => { + write!(formatter, "stage2 kernel ABI `{abi}` is not implemented") + } + Self::WrongExecutorMode { + driver, + expected, + actual, + } => write!( + formatter, + "stage2 driver @{driver} ran with {actual:?} executor path, expected {expected:?}" + ), + Self::MissingProof { driver } => { + write!( + formatter, + "stage2 verifier missing proof for driver @{driver}" + ) + } + Self::MissingKernelInput { kernel, input } => { + write!( + formatter, + "stage2 kernel `{kernel}` missing input `{input}`" + ) + } + Self::InvalidProof { driver, reason } => { + write!( + formatter, + "stage2 proof for driver @{driver} is invalid: {reason}" + ) + } + } + } +} + +impl Error for Stage2KernelError {} + +fn prove_stage2_kernel( + context: Stage2KernelContext<'_>, + inputs: &Stage2ProverInputs<'_, F>, + store: Stage2ValueStore, + transcript: &mut T, +) -> Result, Stage2KernelError> +where + F: Field, + T: Transcript, +{ + match context.abi_kind()? { + Stage2KernelAbi::ProductVirtualUniskip => { + prove_product_virtual_uniskip(context, inputs, store, transcript) + } + Stage2KernelAbi::Batched => prove_batched_stage2(context, inputs, store, transcript), + abi => Err(Stage2KernelError::KernelNotImplemented { abi: abi.name() }), + } +} + +fn verify_stage2_kernel( + context: Stage2KernelContext<'_>, + store: Stage2ValueStore, + proof: &Stage2SumcheckOutput, + ram: Option<&Stage2RamData<'_>>, + transcript: &mut T, +) -> Result, Stage2KernelError> +where + F: Field, + T: Transcript, +{ + match context.abi_kind()? { + Stage2KernelAbi::ProductVirtualUniskip => { + verify_product_virtual_uniskip(context, store, proof, transcript) + } + Stage2KernelAbi::Batched => verify_batched_stage2(context, store, proof, ram, transcript), + abi => Err(Stage2KernelError::KernelNotImplemented { abi: abi.name() }), + } +} + +#[tracing::instrument(skip_all, name = "Stage2::prove_product_virtual_uniskip")] +fn prove_product_virtual_uniskip( + context: Stage2KernelContext<'_>, + inputs: &Stage2ProverInputs<'_, F>, + mut store: Stage2ValueStore, + transcript: &mut T, +) -> Result, Stage2KernelError> +where + F: Field, + T: Transcript, +{ + let claim = + context + .batch_claims()? + .into_iter() + .next() + .ok_or(Stage2KernelError::MissingClaim { + batch: context.batch.symbol, + claim: "stage2.product_virtual.uniskip.input", + })?; + let input_claim = store.claim_value(context.program, claim)?; + let base_evals = product_uniskip_base_evals(&store)?; + let extended_evals = inputs.product_uniskip_extended_evals.as_deref().ok_or( + Stage2KernelError::MissingKernelInput { + kernel: context.kernel.abi, + input: "product_uniskip_extended_evals", + }, + )?; + let poly = build_product_uniskip_poly( + &base_evals, + extended_evals, + store.scalar("stage2.product_virtual.tau_high")?, + )?; + if !product_uniskip_sum_matches(&poly, input_claim) { + return Err(Stage2KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "product uniskip input claim mismatch", + }); + } + append_univariate_poly(transcript, context.driver.round_label, &poly); + let r0 = transcript.challenge(); + let eval = poly.evaluate(r0); + append_labeled_scalar(transcript, "opening_claim", &eval); + Ok(Stage2SumcheckOutput { + driver: context.driver.symbol, + point: vec![r0], + evals: driver_evals(context, eval), + opening_claims: Vec::new(), + proof: SumcheckProof { + round_polynomials: vec![poly], + }, + }) +} + +fn verify_product_virtual_uniskip( + context: Stage2KernelContext<'_>, + mut store: Stage2ValueStore, + proof: &Stage2SumcheckOutput, + transcript: &mut T, +) -> Result, Stage2KernelError> +where + F: Field, + T: Transcript, +{ + if proof.driver != context.driver.symbol { + return Err(Stage2KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "driver symbol mismatch", + }); + } + let [poly] = proof.proof.round_polynomials.as_slice() else { + return Err(Stage2KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "unexpected product uniskip round count", + }); + }; + if polynomial_degree(poly) > context.driver.degree { + return Err(Stage2KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "product uniskip polynomial exceeds degree bound", + }); + } + let claim = + context + .batch_claims()? + .into_iter() + .next() + .ok_or(Stage2KernelError::MissingClaim { + batch: context.batch.symbol, + claim: "stage2.product_virtual.uniskip.input", + })?; + let input_claim = store.claim_value(context.program, claim)?; + if !product_uniskip_sum_matches(poly, input_claim) { + return Err(Stage2KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "product uniskip input claim mismatch", + }); + } + append_univariate_poly(transcript, context.driver.round_label, poly); + let r0 = transcript.challenge(); + if !proof.point.is_empty() && proof.point != [r0] { + return Err(Stage2KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "product uniskip point mismatch", + }); + } + let eval = poly.evaluate(r0); + append_labeled_scalar(transcript, "opening_claim", &eval); + let evals = driver_evals(context, eval); + verify_driver_evals(context.driver.symbol, &evals, &proof.evals)?; + Ok(Stage2SumcheckOutput { + driver: context.driver.symbol, + point: vec![r0], + evals, + opening_claims: Vec::new(), + proof: proof.proof.clone(), + }) +} + +#[tracing::instrument(skip_all, name = "Stage2::prove_batched")] +fn prove_batched_stage2( + context: Stage2KernelContext<'_>, + inputs: &Stage2ProverInputs<'_, F>, + mut store: Stage2ValueStore, + transcript: &mut T, +) -> Result, Stage2KernelError> +where + F: Field, + T: Transcript, +{ + let claims = context.batch_claims()?; + let input_claims = store.batch_claim_values(context.program, context.batch)?; + for claim in &input_claims { + append_labeled_scalar(transcript, context.batch.claim_label, claim); + } + let batching_coeffs = transcript.challenge_vector(claims.len()); + let max_rounds = context.driver.num_rounds; + let mut instances = Vec::with_capacity(claims.len()); + for (index, claim) in claims.iter().enumerate() { + instances.push(Stage2BatchedInstance { + claim, + relation: claim_relation(context.program, claim)?, + offset: instance_round_offset(context.program, context.driver.symbol, claim.symbol)?, + previous_claim: input_claims[index].mul_pow_2(max_rounds - claim.num_rounds), + state: Stage2ProverInstanceState::new(context.program, claim, inputs, &store)?, + }); + } + + let mut point = Vec::with_capacity(max_rounds); + let mut round_polynomials = Vec::with_capacity(max_rounds); + let mut batched_claim = instances + .iter() + .zip(&batching_coeffs) + .map(|(instance, &coefficient)| instance.previous_claim * coefficient) + .sum::(); + let two_inv = F::from_u64(2) + .inverse() + .ok_or(Stage2KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "field element 2 is not invertible", + })?; + + for round in 0..max_rounds { + let mut individual_polys = Vec::with_capacity(instances.len()); + for instance in &mut instances { + let poly = if instance.is_active(round) { + instance + .state + .round_poly(round - instance.offset, instance.previous_claim)? + } else { + UnivariatePoly::new(vec![instance.previous_claim * two_inv]) + }; + #[cfg(debug_assertions)] + { + if poly.evaluate(F::zero()) + poly.evaluate(F::one()) != instance.previous_claim { + return Err(Stage2KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched instance round claim mismatch", + }); + } + } + individual_polys.push(poly); + } + let batched_poly = combine_univariate_polys(&individual_polys, &batching_coeffs); + #[cfg(debug_assertions)] + { + if batched_poly.evaluate(F::zero()) + batched_poly.evaluate(F::one()) != batched_claim { + return Err(Stage2KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched round claim mismatch", + }); + } + } + append_compressed_univariate_poly(transcript, context.driver.round_label, &batched_poly); + let challenge = transcript.challenge(); + point.push(challenge); + batched_claim = batched_poly.evaluate(challenge); + + for (instance, poly) in instances.iter_mut().zip(individual_polys) { + instance.previous_claim = poly.evaluate(challenge); + if instance.is_active(round) { + instance.state.ingest_challenge(challenge)?; + } + } + round_polynomials.push(batched_poly); + } + + let mut evals = Vec::new(); + for instance in &instances { + evals.extend(instance.state.final_evals(instance.relation)?); + } + let expected = expected_batched_output_claim( + context, + &store, + &evals, + &point, + &batching_coeffs, + inputs.ram, + )?; + if batched_claim != expected { + return Err(Stage2KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched output claim mismatch", + }); + } + store.observe_sumcheck_values(context.program, context.driver.symbol, &point, &evals)?; + let opening_claims = append_opening_claims(context.program, &mut store, transcript, &evals)?; + Ok(Stage2SumcheckOutput { + driver: context.driver.symbol, + point, + evals, + opening_claims, + proof: SumcheckProof { round_polynomials }, + }) +} + +fn verify_batched_stage2( + context: Stage2KernelContext<'_>, + mut store: Stage2ValueStore, + proof: &Stage2SumcheckOutput, + ram: Option<&Stage2RamData<'_>>, + transcript: &mut T, +) -> Result, Stage2KernelError> +where + F: Field, + T: Transcript, +{ + if proof.driver != context.driver.symbol { + return Err(Stage2KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "driver symbol mismatch", + }); + } + if proof.proof.round_polynomials.len() != context.driver.num_rounds { + return Err(Stage2KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "unexpected batched round count", + }); + } + let claims = context.batch_claims()?; + let input_claims = store.batch_claim_values(context.program, context.batch)?; + for claim in &input_claims { + append_labeled_scalar(transcript, context.batch.claim_label, claim); + } + let batching_coeffs = transcript.challenge_vector(claims.len()); + let max_rounds = context.driver.num_rounds; + let mut running_claim = input_claims + .iter() + .zip(claims.iter()) + .zip(&batching_coeffs) + .map(|((claim, plan), &coefficient)| { + claim.mul_pow_2(max_rounds - plan.num_rounds) * coefficient + }) + .sum::(); + let mut point = Vec::with_capacity(max_rounds); + + for poly in &proof.proof.round_polynomials { + if polynomial_degree(poly) > context.driver.degree { + return Err(Stage2KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched polynomial exceeds degree bound", + }); + } + if poly.evaluate(F::zero()) + poly.evaluate(F::one()) != running_claim { + return Err(Stage2KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched round check failed", + }); + } + append_compressed_univariate_poly(transcript, context.driver.round_label, poly); + let challenge = transcript.challenge(); + running_claim = poly.evaluate(challenge); + point.push(challenge); + } + if !proof.point.is_empty() && proof.point != point { + return Err(Stage2KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched point mismatch", + }); + } + let expected = expected_batched_output_claim( + context, + &store, + &proof.evals, + &point, + &batching_coeffs, + ram, + )?; + if running_claim != expected { + return Err(Stage2KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched output claim mismatch", + }); + } + store.observe_sumcheck_values(context.program, context.driver.symbol, &point, &proof.evals)?; + let opening_claims = + append_opening_claims(context.program, &mut store, transcript, &proof.evals)?; + Ok(Stage2SumcheckOutput { + driver: context.driver.symbol, + point, + evals: proof.evals.clone(), + opening_claims, + proof: proof.proof.clone(), + }) +} + +struct Stage2BatchedInstance<'a, F: Field> { + claim: &'a Stage2SumcheckClaimPlan, + relation: Stage2Relation, + offset: usize, + previous_claim: F, + state: Stage2ProverInstanceState<'a, F>, +} + +impl Stage2BatchedInstance<'_, F> { + fn is_active(&self, round: usize) -> bool { + round >= self.offset && round < self.offset + self.claim.num_rounds + } +} + +enum Stage2ProverInstanceState<'a, F: Field> { + RamReadWrite(RamReadWriteState), + ProductVirtualRemainder(ProductRemainderState<'a, F>), + InstructionLookupClaimReduction(InstructionLookupState<'a, F>), + RamRafEvaluation(DenseInstanceState), + RamOutputCheck(RamOutputState<'a, F>), +} + +impl<'a, F: Field> Stage2ProverInstanceState<'a, F> { + fn new( + program: &'static Stage2CpuProgramPlan, + claim: &Stage2SumcheckClaimPlan, + inputs: &Stage2ProverInputs<'a, F>, + store: &Stage2ValueStore, + ) -> Result { + match claim_relation(program, claim)? { + Stage2Relation::RamReadWrite => Ok(Self::RamReadWrite(RamReadWriteState::new( + claim, inputs, store, + )?)), + Stage2Relation::ProductVirtualRemainder => Ok(Self::ProductVirtualRemainder( + product_remainder_state(claim, inputs, store)?, + )), + Stage2Relation::InstructionLookupClaimReduction => { + Ok(Self::InstructionLookupClaimReduction( + instruction_lookup_state(claim, inputs, store)?, + )) + } + Stage2Relation::RamRafEvaluation => { + Ok(Self::RamRafEvaluation(ram_raf_state(claim, inputs, store)?)) + } + Stage2Relation::RamOutputCheck => Ok(Self::RamOutputCheck(ram_output_state( + claim, inputs, store, + )?)), + relation => Err(Stage2KernelError::KernelNotImplemented { + abi: relation.symbol(), + }), + } + } + + fn round_poly( + &mut self, + round: usize, + previous_claim: F, + ) -> Result, Stage2KernelError> { + match self { + Self::RamReadWrite(state) => state.round_poly(round, previous_claim), + Self::ProductVirtualRemainder(state) => Ok(state.round_poly(previous_claim)), + Self::InstructionLookupClaimReduction(state) => Ok(state.round_poly(previous_claim)), + Self::RamRafEvaluation(state) => Ok(state.round_poly(previous_claim)), + Self::RamOutputCheck(state) => Ok(state.round_poly(previous_claim)), + } + } + + fn ingest_challenge(&mut self, challenge: F) -> Result<(), Stage2KernelError> { + match self { + Self::RamReadWrite(state) => state.ingest_challenge(challenge), + Self::ProductVirtualRemainder(state) => { + state.bind(challenge); + Ok(()) + } + Self::InstructionLookupClaimReduction(state) => { + state.bind(challenge); + Ok(()) + } + Self::RamRafEvaluation(state) => { + state.bind(challenge); + Ok(()) + } + Self::RamOutputCheck(state) => { + state.bind(challenge); + Ok(()) + } + } + } + + fn final_evals( + &self, + relation: Stage2Relation, + ) -> Result>, Stage2KernelError> { + match self { + Self::RamReadWrite(state) => Ok(vec![ + named_eval( + "stage2.ram_read_write.eval.RamVal", + "RamVal", + state.val_eval()?, + ), + named_eval( + "stage2.ram_read_write.eval.RamRa", + "RamRa", + state.ra_eval()?, + ), + named_eval( + "stage2.ram_read_write.eval.RamInc", + "RamInc", + state.inc_eval()?, + ), + ]), + Self::ProductVirtualRemainder(state) => state.final_evals(relation), + Self::InstructionLookupClaimReduction(state) => state.final_evals(relation), + Self::RamOutputCheck(state) => state.final_evals(relation), + Self::RamRafEvaluation(state) => Ok(vec![named_eval( + "stage2.ram_raf.eval.RamRa", + "RamRa", + state.factor_eval(0, relation)?, + )]), + } + } +} + +struct ProductRemainderState<'a, F: Field> { + cycles: &'a [Stage2ProductVirtualCycle], + left: Vec, + right: Vec, + left_scratch: Vec, + right_scratch: Vec, + split_eq: SplitEqState, + point: Vec, +} + +impl ProductRemainderState<'_, F> { + fn round_poly(&self, previous_claim: F) -> UnivariatePoly { + product_remainder_split_round_poly(&self.left, &self.right, &self.split_eq, previous_claim) + } + + #[tracing::instrument(skip_all, name = "ProductRemainderState::bind")] + fn bind(&mut self, challenge: F) { + let left = &mut self.left; + let left_scratch = &mut self.left_scratch; + let right = &mut self.right; + let right_scratch = &mut self.right_scratch; + rayon::join( + || bind_dense_evals_reuse(left, left_scratch, challenge), + || bind_dense_evals_reuse(right, right_scratch, challenge), + ); + self.split_eq.bind(challenge); + self.point.push(challenge); + } + + fn final_evals( + &self, + relation: Stage2Relation, + ) -> Result>, Stage2KernelError> { + product_remainder_final_evals(self.cycles, &self.point, relation) + } +} + +#[tracing::instrument(skip_all, name = "ProductRemainderState::round_poly")] +fn product_remainder_split_round_poly( + left: &[F], + right: &[F], + split_eq: &SplitEqState, + previous_claim: F, +) -> UnivariatePoly { + let e_in = split_eq.e_in(); + let e_out = split_eq.e_out(); + let (q_constant, q_quadratic) = if e_in.len() > 1 { + product_remainder_low_round_coefficients(left, right, e_in, e_out) + } else { + product_remainder_high_round_coefficients(left, right, e_in[0], e_out) + }; + gruen_cubic_poly( + split_eq.current_target(), + q_constant, + q_quadratic, + previous_claim, + ) +} + +fn product_remainder_low_round_coefficients( + left: &[F], + right: &[F], + e_in: &[F], + e_out: &[F], +) -> (F, F) { + let in_len = e_in.len(); + let in_pairs = in_len / 2; + if left.len() / 2 >= DENSE_BIND_PAR_THRESHOLD { + let accumulators = (0..e_out.len()) + .into_par_iter() + .map(|x_out| { + let mut local = [F::Accumulator::default(); 2]; + let base = x_out * in_len; + let out_weight = e_out[x_out]; + for pair in 0..in_pairs { + accumulate_product_remainder_quadratic_pair( + &mut local, + out_weight * (e_in[2 * pair] + e_in[2 * pair + 1]), + left[base + 2 * pair], + left[base + 2 * pair + 1], + right[base + 2 * pair], + right[base + 2 * pair + 1], + ); + } + local + }) + .reduce( + || [F::Accumulator::default(); 2], + |mut left, right| { + for (left, right) in left.iter_mut().zip(right) { + left.merge(right); + } + left + }, + ); + (accumulators[0].reduce(), accumulators[1].reduce()) + } else { + let mut total = [F::Accumulator::default(); 2]; + for (x_out, &out_weight) in e_out.iter().enumerate() { + let base = x_out * in_len; + for pair in 0..in_pairs { + accumulate_product_remainder_quadratic_pair( + &mut total, + out_weight * (e_in[2 * pair] + e_in[2 * pair + 1]), + left[base + 2 * pair], + left[base + 2 * pair + 1], + right[base + 2 * pair], + right[base + 2 * pair + 1], + ); + } + } + (total[0].reduce(), total[1].reduce()) + } +} + +fn product_remainder_high_round_coefficients( + left: &[F], + right: &[F], + in_weight: F, + e_out: &[F], +) -> (F, F) { + let pairs = e_out.len() / 2; + if pairs >= DENSE_BIND_PAR_THRESHOLD { + let accumulators = (0..pairs) + .into_par_iter() + .map(|pair| { + let mut local = [F::Accumulator::default(); 2]; + accumulate_product_remainder_quadratic_pair( + &mut local, + in_weight * (e_out[2 * pair] + e_out[2 * pair + 1]), + left[2 * pair], + left[2 * pair + 1], + right[2 * pair], + right[2 * pair + 1], + ); + local + }) + .reduce( + || [F::Accumulator::default(); 2], + |mut left, right| { + for (left, right) in left.iter_mut().zip(right) { + left.merge(right); + } + left + }, + ); + (accumulators[0].reduce(), accumulators[1].reduce()) + } else { + let mut total = [F::Accumulator::default(); 2]; + for pair in 0..pairs { + accumulate_product_remainder_quadratic_pair( + &mut total, + in_weight * (e_out[2 * pair] + e_out[2 * pair + 1]), + left[2 * pair], + left[2 * pair + 1], + right[2 * pair], + right[2 * pair + 1], + ); + } + (total[0].reduce(), total[1].reduce()) + } +} + +fn accumulate_product_remainder_quadratic_pair( + accumulators: &mut [F::Accumulator; 2], + weight: F, + left0: F, + left1: F, + right0: F, + right1: F, +) { + accumulators[0].fmadd(weight * left0, right0); + accumulators[1].fmadd(weight * (left1 - left0), right1 - right0); +} + +fn gruen_cubic_poly( + target: F, + q_constant: F, + q_quadratic_coeff: F, + previous_claim: F, +) -> UnivariatePoly { + let eq_eval_1 = target; + let eq_eval_0 = F::one() - target; + let eq_delta = eq_eval_1 - eq_eval_0; + let eq_eval_2 = eq_eval_1 + eq_delta; + let eq_eval_3 = eq_eval_2 + eq_delta; + let cubic_eval_0 = eq_eval_0 * q_constant; + let cubic_eval_1 = previous_claim - cubic_eval_0; + let quadratic_eval_1 = cubic_eval_1 / eq_eval_1; + let e_times_2 = q_quadratic_coeff + q_quadratic_coeff; + let quadratic_eval_2 = quadratic_eval_1 + quadratic_eval_1 - q_constant + e_times_2; + let quadratic_eval_3 = quadratic_eval_2 + quadratic_eval_1 - q_constant + e_times_2 + e_times_2; + UnivariatePoly::from_evals(&[ + cubic_eval_0, + cubic_eval_1, + eq_eval_2 * quadratic_eval_2, + eq_eval_3 * quadratic_eval_3, + ]) +} + +struct InstructionLookupState<'a, F: Field> { + cycles: &'a [Stage2InstructionLookupCycle], + r_spartan: Vec, + gamma: F, + gamma_sqr: F, + gamma_cub: F, + gamma_quart: F, + phase: InstructionLookupPhase, +} + +impl InstructionLookupState<'_, F> { + fn round_poly(&self, previous_claim: F) -> UnivariatePoly { + self.phase.round_poly(previous_claim) + } + + fn bind(&mut self, challenge: F) { + if let InstructionLookupPhase::Phase1(phase1) = &self.phase { + if phase1.should_transition_to_phase2() { + let mut challenges = phase1.challenges.clone(); + challenges.push(challenge); + self.phase = InstructionLookupPhase::Phase2(InstructionLookupPhase2::new( + self.cycles, + &self.r_spartan, + &challenges, + [self.gamma, self.gamma_sqr, self.gamma_cub, self.gamma_quart], + )); + return; + } + } + self.phase.bind(challenge); + } + + fn final_evals( + &self, + _relation: Stage2Relation, + ) -> Result>, Stage2KernelError> { + let InstructionLookupPhase::Phase2(phase2) = &self.phase else { + return Err(Stage2KernelError::InvalidProof { + driver: Stage2Relation::InstructionLookupClaimReduction.symbol(), + reason: "instruction lookup did not reach phase 2", + }); + }; + phase2.final_evals() + } +} + +enum InstructionLookupPhase { + Phase1(InstructionLookupPhase1), + Phase2(InstructionLookupPhase2), +} + +impl InstructionLookupPhase { + fn round_poly(&self, previous_claim: F) -> UnivariatePoly { + match self { + Self::Phase1(state) => state.round_poly(previous_claim), + Self::Phase2(state) => state.round_poly(previous_claim), + } + } + + fn bind(&mut self, challenge: F) { + match self { + Self::Phase1(state) => state.bind(challenge), + Self::Phase2(state) => state.bind(challenge), + } + } +} + +struct InstructionLookupPhase1 { + p: Vec, + q: Vec, + challenges: Vec, +} + +impl InstructionLookupPhase1 { + fn new(cycles: &[Stage2InstructionLookupCycle], r_spartan: &[F], gamma_powers: [F; 4]) -> Self { + let (r_hi, r_lo) = r_spartan.split_at(r_spartan.len() / 2); + let p = EqPolynomial::::evals(r_lo, None); + let eq_suffix = EqPolynomial::::evals(r_hi, None); + let prefix_len = p.len(); + let q = (0..prefix_len) + .into_par_iter() + .map(|x_lo| { + let mut accumulators = [F::Accumulator::default(); 5]; + for (x_hi, &weight) in eq_suffix.iter().enumerate() { + let index = x_lo + (x_hi * prefix_len); + accumulate_instruction_lookup_outputs( + &mut accumulators, + &cycles[index], + weight, + ); + } + combine_instruction_lookup_values( + accumulators.map(FieldAccumulator::reduce), + gamma_powers, + ) + }) + .collect(); + Self { + p, + q, + challenges: Vec::new(), + } + } + + #[tracing::instrument(skip_all, name = "InstructionLookupPhase1::round_poly")] + fn round_poly(&self, _previous_claim: F) -> UnivariatePoly { + round_poly_from_factor_slices(&[&self.p, &self.q], 2) + } + + #[tracing::instrument(skip_all, name = "InstructionLookupPhase1::bind")] + fn bind(&mut self, challenge: F) { + self.challenges.push(challenge); + let mut scratch = Vec::new(); + bind_dense_evals_reuse(&mut self.p, &mut scratch, challenge); + bind_dense_evals_reuse(&mut self.q, &mut scratch, challenge); + } + + fn should_transition_to_phase2(&self) -> bool { + self.p.len() == 2 + } +} + +struct InstructionLookupPhase2 { + eq: Vec, + combined: Vec, + outputs: [Vec; 5], +} + +impl InstructionLookupPhase2 { + #[tracing::instrument(skip_all, name = "InstructionLookupPhase2::new")] + fn new( + cycles: &[Stage2InstructionLookupCycle], + r_spartan: &[F], + challenges: &[F], + gamma_powers: [F; 4], + ) -> Self { + let n_remaining_rounds = r_spartan.len() - challenges.len(); + let remaining_len = 1usize << n_remaining_rounds; + let prefix_point = reverse_slice(challenges); + let (r_hi, r_lo) = r_spartan.split_at(r_spartan.len() / 2); + let eq_prefix = EqPolynomial::::mle(&prefix_point, r_lo); + let prefix_eq_evals = EqPolynomial::::evals(&prefix_point, None); + let rows = (0..remaining_len) + .into_par_iter() + .map(|x_hi| { + let start = x_hi * prefix_eq_evals.len(); + let mut accumulators = [F::Accumulator::default(); 5]; + for (x_lo, &weight) in prefix_eq_evals.iter().enumerate() { + accumulate_instruction_lookup_outputs( + &mut accumulators, + &cycles[start + x_lo], + weight, + ); + } + let outputs = accumulators.map(FieldAccumulator::reduce); + let combined = combine_instruction_lookup_values(outputs, gamma_powers); + (outputs, combined) + }) + .collect::>(); + let mut outputs = core::array::from_fn(|_| Vec::with_capacity(remaining_len)); + let mut combined = Vec::with_capacity(remaining_len); + for (row_outputs, row_combined) in rows { + for (output, value) in outputs.iter_mut().zip(row_outputs) { + output.push(value); + } + combined.push(row_combined); + } + Self { + eq: EqPolynomial::::evals(r_hi, Some(eq_prefix)), + combined, + outputs, + } + } + + #[tracing::instrument(skip_all, name = "InstructionLookupPhase2::round_poly")] + fn round_poly(&self, _previous_claim: F) -> UnivariatePoly { + round_poly_from_factor_slices(&[&self.eq, &self.combined], 2) + } + + #[tracing::instrument(skip_all, name = "InstructionLookupPhase2::bind")] + fn bind(&mut self, challenge: F) { + let mut scratch = Vec::new(); + bind_dense_evals_reuse(&mut self.eq, &mut scratch, challenge); + bind_dense_evals_reuse(&mut self.combined, &mut scratch, challenge); + for output in &mut self.outputs { + bind_dense_evals_reuse(output, &mut scratch, challenge); + } + } + + fn final_evals(&self) -> Result>, Stage2KernelError> { + INSTRUCTION_LOOKUP_EVAL_NAMES + .iter() + .zip(&self.outputs) + .map(|(&(name, oracle), output)| { + output + .first() + .copied() + .map(|value| named_eval(name, oracle, value)) + .ok_or(Stage2KernelError::InvalidProof { + driver: Stage2Relation::InstructionLookupClaimReduction.symbol(), + reason: "empty instruction lookup output", + }) + }) + .collect() + } +} + +fn combine_instruction_lookup_values(values: [F; 5], gamma_powers: [F; 4]) -> F { + values[0] + + gamma_powers[0] * values[1] + + gamma_powers[1] * values[2] + + gamma_powers[2] * values[3] + + gamma_powers[3] * values[4] +} + +#[derive(Clone)] +struct DenseInstanceState { + factors: Vec>, + factor_scratch: Vec>, + point: Vec, +} + +impl DenseInstanceState { + fn new(factors: Vec>) -> Self { + let factor_scratch = (0..factors.len()).map(|_| Vec::new()).collect(); + Self { + factors, + factor_scratch, + point: Vec::new(), + } + } + + #[tracing::instrument(skip_all, name = "Stage2DenseState::round_poly")] + fn round_poly(&self, _previous_claim: F) -> UnivariatePoly { + round_poly_from_factors(&self.factors, self.degree()) + } + + fn degree(&self) -> usize { + self.factors.len() + } + + #[tracing::instrument(skip_all, name = "Stage2DenseState::bind")] + fn bind(&mut self, challenge: F) { + for (factor, scratch) in self.factors.iter_mut().zip(&mut self.factor_scratch) { + bind_dense_evals_reuse(factor, scratch, challenge); + } + self.point.push(challenge); + } + + fn factor_eval(&self, index: usize, relation: Stage2Relation) -> Result { + self.factors + .get(index) + .and_then(|values| values.first()) + .copied() + .ok_or(Stage2KernelError::InvalidProof { + driver: relation.symbol(), + reason: "empty dense factor", + }) + } +} + +#[derive(Clone)] +struct RamOutputState<'a, F: Field> { + dense: DenseInstanceState, + final_ram: &'a [u64], + nonzero_final_ram: Vec<(usize, u64)>, +} + +impl RamOutputState<'_, F> { + fn round_poly(&self, previous_claim: F) -> UnivariatePoly { + self.dense.round_poly(previous_claim) + } + + fn bind(&mut self, challenge: F) { + self.dense.bind(challenge); + } + + fn final_evals( + &self, + _relation: Stage2Relation, + ) -> Result>, Stage2KernelError> { + Ok(vec![named_eval( + "stage2.ram_output.eval.RamValFinal", + "RamValFinal", + ram_eval_reversed(self.final_ram, &self.nonzero_final_ram, &self.dense.point), + )]) + } +} + +#[tracing::instrument(skip_all, name = "Stage2::product_remainder_state")] +fn product_remainder_state<'a, F: Field>( + _claim: &Stage2SumcheckClaimPlan, + inputs: &Stage2ProverInputs<'a, F>, + store: &Stage2ValueStore, +) -> Result, Stage2KernelError> { + let cycles = inputs + .product_virtual_cycles + .ok_or(Stage2KernelError::MissingKernelInput { + kernel: "jolt_stage2_product_virtual_remainder", + input: "product_virtual_cycles", + })?; + let tau_low = store.point("stage2.input.stage1.Product")?; + let expected = + 1usize + .checked_shl(tau_low.len() as u32) + .ok_or(Stage2KernelError::InvalidInputLength { + input: "stage2.product_virtual.cycles", + expected: usize::BITS as usize, + actual: tau_low.len(), + })?; + if cycles.len() != expected { + return Err(Stage2KernelError::InvalidInputLength { + input: "stage2.product_virtual.cycles", + expected, + actual: cycles.len(), + }); + } + let tau_high = store.scalar("stage2.product_virtual.tau_high")?; + let r0 = *store + .point("stage2.product_virtual.uniskip.sumcheck")? + .first() + .ok_or(Stage2KernelError::MissingValue { + symbol: "stage2.product_virtual.uniskip.sumcheck", + })?; + let lagrange_tau_r0 = lagrange_kernel_eval( + PRODUCT_VIRTUAL_UNISKIP_DOMAIN_START, + PRODUCT_VIRTUAL_UNISKIP_DOMAIN_SIZE, + tau_high, + r0, + ); + let weights = lagrange_evals( + PRODUCT_VIRTUAL_UNISKIP_DOMAIN_START, + PRODUCT_VIRTUAL_UNISKIP_DOMAIN_SIZE, + r0, + ); + let mut left = vec![F::zero(); cycles.len()]; + let mut right = vec![F::zero(); cycles.len()]; + left.par_iter_mut() + .zip(right.par_iter_mut()) + .zip(cycles.par_iter()) + .for_each(|((left, right), cycle)| { + *left = weights[0].mul_u64(cycle.instruction_left_input) + + weights[1].mul_u64(cycle.should_branch_lookup_output) + + if cycle.jump_flag { + weights[2] + } else { + F::zero() + }; + *right = weights[0].mul_i128(cycle.instruction_right_input) + + if cycle.should_branch_flag { + weights[1] + } else { + F::zero() + } + + if cycle.not_next_noop { + weights[2] + } else { + F::zero() + }; + }); + Ok(ProductRemainderState { + cycles, + left, + right, + left_scratch: Vec::new(), + right_scratch: Vec::new(), + split_eq: SplitEqState::new_low_to_high(tau_low, Some(lagrange_tau_r0)), + point: Vec::new(), + }) +} + +#[tracing::instrument(skip_all, name = "Stage2::instruction_lookup_state")] +fn instruction_lookup_state<'a, F: Field>( + _claim: &Stage2SumcheckClaimPlan, + inputs: &Stage2ProverInputs<'a, F>, + store: &Stage2ValueStore, +) -> Result, Stage2KernelError> { + let cycles = inputs + .instruction_lookup_cycles + .ok_or(Stage2KernelError::MissingKernelInput { + kernel: "jolt_stage2_instruction_lookup_claim_reduction", + input: "instruction_lookup_cycles", + })?; + let r_spartan = store.point("stage2.input.stage1.LookupOutput")?; + let expected = 1usize.checked_shl(r_spartan.len() as u32).ok_or( + Stage2KernelError::InvalidInputLength { + input: "stage2.instruction_lookup.cycles", + expected: usize::BITS as usize, + actual: r_spartan.len(), + }, + )?; + if cycles.len() != expected { + return Err(Stage2KernelError::InvalidInputLength { + input: "stage2.instruction_lookup.cycles", + expected, + actual: cycles.len(), + }); + } + let gamma = store.scalar("stage2.instruction_lookup.gamma")?; + let gamma_sqr = gamma.square(); + let gamma_cub = gamma_sqr * gamma; + let gamma_quart = gamma_sqr.square(); + Ok(InstructionLookupState { + cycles, + r_spartan: r_spartan.to_vec(), + gamma, + gamma_sqr, + gamma_cub, + gamma_quart, + phase: InstructionLookupPhase::Phase1(InstructionLookupPhase1::new( + cycles, + r_spartan, + [gamma, gamma_sqr, gamma_cub, gamma_quart], + )), + }) +} + +#[tracing::instrument(skip_all, name = "Stage2::ram_raf_state")] +fn ram_raf_state( + claim: &Stage2SumcheckClaimPlan, + inputs: &Stage2ProverInputs<'_, F>, + store: &Stage2ValueStore, +) -> Result, Stage2KernelError> { + let ram = inputs.ram.ok_or(Stage2KernelError::MissingKernelInput { + kernel: "jolt_stage2_ram_raf_evaluation", + input: "ram", + })?; + require_operand_count("stage2.ram_raf.num_rounds", ram.log_k, claim.num_rounds)?; + let r_cycle = store.point("stage2.input.stage1.RamAddress")?; + let eq_cycle = EqPolynomial::::evals(r_cycle, None); + if ram.accesses.len() != eq_cycle.len() { + return Err(Stage2KernelError::InvalidInputLength { + input: "stage2.ram.accesses", + expected: eq_cycle.len(), + actual: ram.accesses.len(), + }); + } + let k = 1usize << ram.log_k; + let mut ra = vec![F::zero(); k]; + for (access, weight) in ram.accesses.iter().zip(eq_cycle) { + if let Some(address) = access.remapped_address { + ra[address] += weight; + } + } + let mut next_address = F::from_u64(ram.start_address); + let address_step = F::from_u64(8); + let mut unmap = Vec::with_capacity(k); + for _ in 0..k { + unmap.push(next_address); + next_address += address_step; + } + Ok(DenseInstanceState::new(vec![ra, unmap])) +} + +#[tracing::instrument(skip_all, name = "Stage2::ram_output_state")] +fn ram_output_state<'a, F: Field>( + claim: &Stage2SumcheckClaimPlan, + inputs: &Stage2ProverInputs<'a, F>, + store: &Stage2ValueStore, +) -> Result, Stage2KernelError> { + let ram = inputs.ram.ok_or(Stage2KernelError::MissingKernelInput { + kernel: "jolt_stage2_ram_output_check", + input: "ram", + })?; + require_operand_count("stage2.ram_output.num_rounds", ram.log_k, claim.num_rounds)?; + let layout = ram + .output_layout + .ok_or(Stage2KernelError::MissingKernelInput { + kernel: "jolt_stage2_ram_output_check", + input: "ram.output_layout", + })?; + let k = 1usize << ram.log_k; + require_operand_count("stage2.ram.final_ram", k, ram.final_ram.len())?; + let r_address = store.point("stage2.ram_output.r_address")?; + let eq = EqPolynomial::::evals(r_address, None); + let mut io_mask = vec![F::zero(); k]; + let mut diff = vec![F::zero(); k]; + let mut nonzero_final_ram = Vec::new(); + for index in 0..k { + let final_value = ram.final_ram[index]; + if final_value != 0 { + nonzero_final_ram.push((index, final_value)); + } + if index >= layout.io_start && index < layout.io_end { + io_mask[index] = F::one(); + } else if final_value != 0 { + diff[index] = F::from_u64(final_value); + } + } + Ok(RamOutputState { + dense: DenseInstanceState::new(vec![eq, io_mask, diff]), + final_ram: ram.final_ram, + nonzero_final_ram, + }) +} + +#[derive(Clone, Debug)] +struct RamCycleEntry { + row: usize, + col: usize, + prev_val: u64, + next_val: u64, + val_coeff: F, + ra_coeff: F, +} + +#[derive(Clone, Debug)] +struct RamAddressEntry { + row: usize, + col: usize, + prev_val: F, + next_val: F, + val_coeff: F, + ra_coeff: F, +} + +#[derive(Clone)] +struct RamReadWriteState { + gamma: F, + log_t: usize, + round: usize, + cycle_eq: SplitEqState, + cycle_entries: Vec>, + address_entries: Vec>, + address_scratch: Vec>, + inc: Vec, + inc_scratch: Vec, + val_init: Vec, + val_init_scratch: Vec, +} + +impl RamReadWriteState { + #[tracing::instrument(skip_all, name = "RamReadWriteState::new")] + fn new( + _claim: &Stage2SumcheckClaimPlan, + inputs: &Stage2ProverInputs<'_, F>, + store: &Stage2ValueStore, + ) -> Result { + let ram = inputs.ram.ok_or(Stage2KernelError::MissingKernelInput { + kernel: "jolt_stage2_ram_read_write", + input: "ram", + })?; + let r_cycle = store.point("stage2.input.stage1.RamReadValue")?; + let log_t = r_cycle.len(); + let t = 1usize << log_t; + let k = 1usize << ram.log_k; + require_operand_count("stage2.ram.accesses", t, ram.accesses.len())?; + require_operand_count("stage2.ram.initial_ram", k, ram.initial_ram.len())?; + let gamma = store.scalar("stage2.ram_read_write.gamma")?; + let mut cycle_entries = Vec::with_capacity(ram.accesses.len()); + let mut inc = Vec::with_capacity(t); + for (row, access) in ram.accesses.iter().enumerate() { + inc.push(if access.write_value == access.read_value { + F::zero() + } else { + F::from_u64(access.write_value) - F::from_u64(access.read_value) + }); + if let Some(col) = access.remapped_address { + cycle_entries.push(RamCycleEntry { + row, + col, + prev_val: access.read_value, + next_val: access.write_value, + val_coeff: F::from_u64(access.read_value), + ra_coeff: F::one(), + }); + } + } + Ok(Self { + gamma, + log_t, + round: 0, + cycle_eq: SplitEqState::new_low_to_high(r_cycle, None), + cycle_entries, + address_entries: Vec::new(), + address_scratch: Vec::new(), + inc, + inc_scratch: Vec::new(), + val_init: ram + .initial_ram + .iter() + .map(|&value| { + if value == 0 { + F::zero() + } else { + F::from_u64(value) + } + }) + .collect(), + val_init_scratch: Vec::new(), + }) + } + + fn round_poly( + &mut self, + _round: usize, + previous_claim: F, + ) -> Result, Stage2KernelError> { + if self.round < self.log_t { + Ok(self.cycle_round_poly(previous_claim)) + } else { + Ok(self.address_round_poly(previous_claim)) + } + } + + fn ingest_challenge(&mut self, challenge: F) -> Result<(), Stage2KernelError> { + if self.round < self.log_t { + self.bind_cycle(challenge); + if self.round + 1 == self.log_t { + self.address_entries = self + .cycle_entries + .drain(..) + .map(|entry| RamAddressEntry { + row: entry.row, + col: entry.col, + prev_val: F::from_u64(entry.prev_val), + next_val: F::from_u64(entry.next_val), + val_coeff: entry.val_coeff, + ra_coeff: entry.ra_coeff, + }) + .collect(); + self.address_entries + .sort_by_key(|entry| (entry.col, entry.row)); + } + } else { + self.bind_address(challenge); + } + self.round += 1; + Ok(()) + } + + #[tracing::instrument(skip_all, name = "RamReadWriteState::cycle_round_poly")] + fn cycle_round_poly(&self, previous_claim: F) -> UnivariatePoly { + let e_in = self.cycle_eq.e_in(); + let e_out = self.cycle_eq.e_out(); + let (q_constant, q_quadratic) = if e_in.len() > 1 { + cycle_low_round_coefficients(&self.cycle_entries, &self.inc, e_in, e_out, self.gamma) + } else { + cycle_high_round_coefficients( + &self.cycle_entries, + &self.inc, + e_in[0], + e_out, + self.gamma, + ) + }; + gruen_cubic_poly( + self.cycle_eq.current_target(), + q_constant, + q_quadratic, + previous_claim, + ) + } + + #[tracing::instrument(skip_all, name = "RamReadWriteState::address_round_poly")] + fn address_round_poly(&self, previous_claim: F) -> UnivariatePoly { + let mut evals = [F::zero(); 2]; + let cycle_eq = self.cycle_eq_eval(); + let mut cursor = 0; + while cursor < self.address_entries.len() { + let pair = self.address_entries[cursor].col / 2; + let start = cursor; + while cursor < self.address_entries.len() + && self.address_entries[cursor].col / 2 == pair + { + cursor += 1; + } + let entries = &self.address_entries[start..cursor]; + let odd_start = entries.partition_point(|entry| entry.col % 2 == 0); + let even = &entries[..odd_start]; + let odd = &entries[odd_start..]; + let even_checkpoint = self.val_init[2 * pair]; + let odd_checkpoint = self.val_init[2 * pair + 1]; + for (x, eval_index) in [(0usize, 0usize), (2usize, 1usize)] { + evals[eval_index] += address_pair_eval( + even, + odd, + even_checkpoint, + odd_checkpoint, + RamEvalWeights { + inc: self.inc[0], + eq: cycle_eq, + gamma: self.gamma, + x: F::from_u64(x as u64), + }, + ); + } + } + UnivariatePoly::from_evals_and_hint(previous_claim, &evals) + } + + #[tracing::instrument(skip_all, name = "RamReadWriteState::bind_cycle")] + fn bind_cycle(&mut self, challenge: F) { + self.cycle_entries = bind_cycle_entries_parallel(&self.cycle_entries, challenge); + let inc = &mut self.inc; + let inc_scratch = &mut self.inc_scratch; + bind_dense_evals_reuse(inc, inc_scratch, challenge); + self.cycle_eq.bind(challenge); + } + + #[tracing::instrument(skip_all, name = "RamReadWriteState::bind_address")] + fn bind_address(&mut self, challenge: F) { + let mut bound = std::mem::take(&mut self.address_scratch); + bound.clear(); + bound.reserve(self.address_entries.len()); + let mut cursor = 0; + while cursor < self.address_entries.len() { + let pair = self.address_entries[cursor].col / 2; + let start = cursor; + while cursor < self.address_entries.len() + && self.address_entries[cursor].col / 2 == pair + { + cursor += 1; + } + let entries = &self.address_entries[start..cursor]; + let odd_start = entries.partition_point(|entry| entry.col % 2 == 0); + bind_address_cols( + &entries[..odd_start], + &entries[odd_start..], + self.val_init[2 * pair], + self.val_init[2 * pair + 1], + challenge, + &mut bound, + ); + } + std::mem::swap(&mut self.address_entries, &mut bound); + self.address_scratch = bound; + bind_dense_evals_reuse(&mut self.val_init, &mut self.val_init_scratch, challenge); + } + + fn ra_eval(&self) -> Result { + Ok(self + .address_entries + .first() + .filter(|entry| entry.col == 0 && entry.row == 0) + .map_or(F::zero(), |entry| entry.ra_coeff)) + } + + fn val_eval(&self) -> Result { + Ok(self + .address_entries + .first() + .filter(|entry| entry.col == 0 && entry.row == 0) + .map_or(self.val_init[0], |entry| entry.val_coeff)) + } + + fn inc_eval(&self) -> Result { + Ok(self.inc[0]) + } + + fn cycle_eq_eval(&self) -> F { + self.cycle_eq.eval() + } +} + +fn cycle_low_round_coefficients( + entries: &[RamCycleEntry], + inc: &[F], + e_in: &[F], + e_out: &[F], + gamma: F, +) -> (F, F) { + let in_pairs = e_in.len() / 2; + let accumulators = if entries.len() >= DENSE_BIND_PAR_THRESHOLD { + entries + .par_chunk_by(|left, right| (left.row / 2) / in_pairs == (right.row / 2) / in_pairs) + .map(|entries| { + let mut local = [F::Accumulator::default(); 2]; + accumulate_cycle_outer_chunk( + &mut local, entries, inc, e_in, e_out, in_pairs, gamma, + ); + local + }) + .reduce( + || [F::Accumulator::default(); 2], + |mut left, right| { + for index in 0..left.len() { + left[index].merge(right[index]); + } + left + }, + ) + } else { + entries + .chunk_by(|left, right| (left.row / 2) / in_pairs == (right.row / 2) / in_pairs) + .fold([F::Accumulator::default(); 2], |mut local, entries| { + accumulate_cycle_outer_chunk( + &mut local, entries, inc, e_in, e_out, in_pairs, gamma, + ); + local + }) + }; + (accumulators[0].reduce(), accumulators[1].reduce()) +} + +fn cycle_high_round_coefficients( + entries: &[RamCycleEntry], + inc: &[F], + in_weight: F, + e_out: &[F], + gamma: F, +) -> (F, F) { + let accumulators = if entries.len() >= DENSE_BIND_PAR_THRESHOLD { + entries + .par_chunk_by(|left, right| left.row / 2 == right.row / 2) + .map(|entries| { + let mut local = [F::Accumulator::default(); 2]; + let pair = entries[0].row / 2; + let weight = in_weight * (e_out[2 * pair] + e_out[2 * pair + 1]); + accumulate_cycle_row_pair(&mut local, entries, inc, weight, gamma); + local + }) + .reduce( + || [F::Accumulator::default(); 2], + |mut left, right| { + for index in 0..left.len() { + left[index].merge(right[index]); + } + left + }, + ) + } else { + entries + .chunk_by(|left, right| left.row / 2 == right.row / 2) + .fold([F::Accumulator::default(); 2], |mut local, entries| { + let pair = entries[0].row / 2; + let weight = in_weight * (e_out[2 * pair] + e_out[2 * pair + 1]); + accumulate_cycle_row_pair(&mut local, entries, inc, weight, gamma); + local + }) + }; + (accumulators[0].reduce(), accumulators[1].reduce()) +} + +fn accumulate_cycle_outer_chunk( + accumulators: &mut [F::Accumulator; 2], + entries: &[RamCycleEntry], + inc: &[F], + e_in: &[F], + e_out: &[F], + in_pairs: usize, + gamma: F, +) { + let x_out = (entries[0].row / 2) / in_pairs; + let out_weight = e_out[x_out]; + for entries in entries.chunk_by(|left, right| left.row / 2 == right.row / 2) { + let pair = entries[0].row / 2; + let x_in = pair % in_pairs; + let weight = out_weight * (e_in[2 * x_in] + e_in[2 * x_in + 1]); + accumulate_cycle_row_pair(accumulators, entries, inc, weight, gamma); + } +} + +fn accumulate_cycle_row_pair( + accumulators: &mut [F::Accumulator; 2], + entries: &[RamCycleEntry], + inc: &[F], + weight: F, + gamma: F, +) { + let pair = entries[0].row / 2; + let odd_start = entries.partition_point(|entry| entry.row % 2 == 0); + let even = &entries[..odd_start]; + let odd = &entries[odd_start..]; + let row = pair * 2; + let inc_pair = [inc[row], inc[row + 1]]; + accumulate_cycle_pair_body(accumulators, even, odd, inc_pair, weight, gamma); +} + +fn accumulate_cycle_pair_body( + accumulators: &mut [F::Accumulator; 2], + even: &[RamCycleEntry], + odd: &[RamCycleEntry], + inc_pair: [F; 2], + weight: F, + gamma: F, +) { + let mut i = 0; + let mut j = 0; + while i < even.len() && j < odd.len() { + match even[i].col.cmp(&odd[j].col) { + Ordering::Equal => { + accumulate_cycle_entry_quadratic( + accumulators, + Some(&even[i]), + Some(&odd[j]), + inc_pair, + weight, + gamma, + ); + i += 1; + j += 1; + } + Ordering::Less => { + accumulate_cycle_entry_quadratic( + accumulators, + Some(&even[i]), + None, + inc_pair, + weight, + gamma, + ); + i += 1; + } + Ordering::Greater => { + accumulate_cycle_entry_quadratic( + accumulators, + None, + Some(&odd[j]), + inc_pair, + weight, + gamma, + ); + j += 1; + } + } + } + for entry in &even[i..] { + accumulate_cycle_entry_quadratic(accumulators, Some(entry), None, inc_pair, weight, gamma); + } + for entry in &odd[j..] { + accumulate_cycle_entry_quadratic(accumulators, None, Some(entry), inc_pair, weight, gamma); + } +} + +fn accumulate_cycle_entry_quadratic( + accumulators: &mut [F::Accumulator; 2], + even: Option<&RamCycleEntry>, + odd: Option<&RamCycleEntry>, + inc_pair: [F; 2], + weight: F, + gamma: F, +) { + let (ra0, ra1, val0, val1) = match (even, odd) { + (Some(even), Some(odd)) => (even.ra_coeff, odd.ra_coeff, even.val_coeff, odd.val_coeff), + (Some(even), None) => ( + even.ra_coeff, + F::zero(), + even.val_coeff, + F::from_u64(even.next_val), + ), + (None, Some(odd)) => ( + F::zero(), + odd.ra_coeff, + F::from_u64(odd.prev_val), + odd.val_coeff, + ), + (None, None) => unreachable!(), + }; + let one_plus_gamma = F::one() + gamma; + let inc_delta = inc_pair[1] - inc_pair[0]; + let body0 = one_plus_gamma * val0 + gamma * inc_pair[0]; + let body_delta = one_plus_gamma * (val1 - val0) + gamma * inc_delta; + accumulators[0].fmadd(weight * ra0, body0); + accumulators[1].fmadd(weight * (ra1 - ra0), body_delta); +} + +fn address_pair_eval( + even: &[RamAddressEntry], + odd: &[RamAddressEntry], + mut even_checkpoint: F, + mut odd_checkpoint: F, + weights: RamEvalWeights, +) -> F { + let mut total = F::zero(); + let mut i = 0; + let mut j = 0; + while i < even.len() && j < odd.len() { + match even[i].row.cmp(&odd[j].row) { + Ordering::Equal => { + total += address_entry_eval( + Some(&even[i]), + Some(&odd[j]), + even_checkpoint, + odd_checkpoint, + weights, + ); + even_checkpoint = even[i].next_val; + odd_checkpoint = odd[j].next_val; + i += 1; + j += 1; + } + Ordering::Less => { + total += address_entry_eval( + Some(&even[i]), + None, + even_checkpoint, + odd_checkpoint, + weights, + ); + even_checkpoint = even[i].next_val; + i += 1; + } + Ordering::Greater => { + total += address_entry_eval( + None, + Some(&odd[j]), + even_checkpoint, + odd_checkpoint, + weights, + ); + odd_checkpoint = odd[j].next_val; + j += 1; + } + } + } + for entry in &even[i..] { + total += address_entry_eval(Some(entry), None, even_checkpoint, odd_checkpoint, weights); + even_checkpoint = entry.next_val; + } + for entry in &odd[j..] { + total += address_entry_eval(None, Some(entry), even_checkpoint, odd_checkpoint, weights); + odd_checkpoint = entry.next_val; + } + total +} + +#[derive(Clone, Copy)] +struct RamEvalWeights { + inc: F, + eq: F, + gamma: F, + x: F, +} + +fn address_entry_eval( + even: Option<&RamAddressEntry>, + odd: Option<&RamAddressEntry>, + even_checkpoint: F, + odd_checkpoint: F, + weights: RamEvalWeights, +) -> F { + let (ra0, ra1, val0, val1) = match (even, odd) { + (Some(even), Some(odd)) => (even.ra_coeff, odd.ra_coeff, even.val_coeff, odd.val_coeff), + (Some(even), None) => (even.ra_coeff, F::zero(), even.val_coeff, odd_checkpoint), + (None, Some(odd)) => (F::zero(), odd.ra_coeff, even_checkpoint, odd.val_coeff), + (None, None) => unreachable!(), + }; + let ra = line(ra0, ra1, weights.x); + let val = line(val0, val1, weights.x); + weights.eq * ra * (val + weights.gamma * (val + weights.inc)) +} + +fn bind_cycle_entries_parallel( + entries: &[RamCycleEntry], + challenge: F, +) -> Vec> { + let row_lengths = entries + .par_chunk_by(|left, right| left.row / 2 == right.row / 2) + .map(|entries| { + let odd_start = entries.partition_point(|entry| entry.row % 2 == 0); + let bound_len = bind_cycle_rows_len(&entries[..odd_start], &entries[odd_start..]); + (entries.len(), bound_len) + }) + .collect::>(); + let bound_len = row_lengths.iter().map(|(_, bound_len)| *bound_len).sum(); + let mut bound = Vec::with_capacity(bound_len); + let mut output_remainder = bound.spare_capacity_mut(); + let mut input_remainder = entries; + let mut input_slices = Vec::with_capacity(row_lengths.len()); + let mut output_slices = Vec::with_capacity(row_lengths.len()); + for (input_len, output_len) in row_lengths { + let (output, rest_output) = output_remainder.split_at_mut(output_len); + output_remainder = rest_output; + output_slices.push(output); + let (input, rest_input) = input_remainder.split_at(input_len); + input_remainder = rest_input; + input_slices.push(input); + } + input_slices + .par_iter() + .zip(output_slices.into_par_iter()) + .for_each(|(input, output)| { + let odd_start = input.partition_point(|entry| entry.row % 2 == 0); + let written = + bind_cycle_rows(&input[..odd_start], &input[odd_start..], challenge, output); + debug_assert_eq!(written, output.len()); + }); + // SAFETY: every output slice is disjoint, and `bind_cycle_rows` writes exactly the + // precomputed number of initialized entries into each slice before `set_len`. + unsafe { + bound.set_len(bound_len); + } + bound +} + +fn bind_cycle_rows_len(even: &[RamCycleEntry], odd: &[RamCycleEntry]) -> usize { + let mut i = 0; + let mut j = 0; + let mut len = 0; + while i < even.len() && j < odd.len() { + len += 1; + match even[i].col.cmp(&odd[j].col) { + Ordering::Equal => { + i += 1; + j += 1; + } + Ordering::Less => i += 1, + Ordering::Greater => j += 1, + } + } + len + even.len() - i + odd.len() - j +} + +fn bind_cycle_rows( + even: &[RamCycleEntry], + odd: &[RamCycleEntry], + challenge: F, + out: &mut [MaybeUninit>], +) -> usize { + let mut i = 0; + let mut j = 0; + let mut written = 0; + while i < even.len() && j < odd.len() { + match even[i].col.cmp(&odd[j].col) { + Ordering::Equal => { + let _ = + out[written].write(bind_cycle_entry(Some(&even[i]), Some(&odd[j]), challenge)); + written += 1; + i += 1; + j += 1; + } + Ordering::Less => { + let _ = out[written].write(bind_cycle_entry(Some(&even[i]), None, challenge)); + written += 1; + i += 1; + } + Ordering::Greater => { + let _ = out[written].write(bind_cycle_entry(None, Some(&odd[j]), challenge)); + written += 1; + j += 1; + } + } + } + for entry in &even[i..] { + let _ = out[written].write(bind_cycle_entry(Some(entry), None, challenge)); + written += 1; + } + for entry in &odd[j..] { + let _ = out[written].write(bind_cycle_entry(None, Some(entry), challenge)); + written += 1; + } + written +} + +fn bind_cycle_entry( + even: Option<&RamCycleEntry>, + odd: Option<&RamCycleEntry>, + r: F, +) -> RamCycleEntry { + match (even, odd) { + (Some(even), Some(odd)) => RamCycleEntry { + row: even.row / 2, + col: even.col, + ra_coeff: line(even.ra_coeff, odd.ra_coeff, r), + val_coeff: line(even.val_coeff, odd.val_coeff, r), + prev_val: even.prev_val, + next_val: odd.next_val, + }, + (Some(even), None) => RamCycleEntry { + row: even.row / 2, + col: even.col, + ra_coeff: line(even.ra_coeff, F::zero(), r), + val_coeff: line(even.val_coeff, F::from_u64(even.next_val), r), + prev_val: even.prev_val, + next_val: even.next_val, + }, + (None, Some(odd)) => RamCycleEntry { + row: odd.row / 2, + col: odd.col, + ra_coeff: line(F::zero(), odd.ra_coeff, r), + val_coeff: line(F::from_u64(odd.prev_val), odd.val_coeff, r), + prev_val: odd.prev_val, + next_val: odd.next_val, + }, + (None, None) => unreachable!(), + } +} + +fn bind_address_cols( + even: &[RamAddressEntry], + odd: &[RamAddressEntry], + mut even_checkpoint: F, + mut odd_checkpoint: F, + challenge: F, + out: &mut Vec>, +) { + let mut i = 0; + let mut j = 0; + while i < even.len() && j < odd.len() { + match even[i].row.cmp(&odd[j].row) { + Ordering::Equal => { + out.push(bind_address_entry( + Some(&even[i]), + Some(&odd[j]), + even_checkpoint, + odd_checkpoint, + challenge, + )); + even_checkpoint = even[i].next_val; + odd_checkpoint = odd[j].next_val; + i += 1; + j += 1; + } + Ordering::Less => { + out.push(bind_address_entry( + Some(&even[i]), + None, + even_checkpoint, + odd_checkpoint, + challenge, + )); + even_checkpoint = even[i].next_val; + i += 1; + } + Ordering::Greater => { + out.push(bind_address_entry( + None, + Some(&odd[j]), + even_checkpoint, + odd_checkpoint, + challenge, + )); + odd_checkpoint = odd[j].next_val; + j += 1; + } + } + } + for entry in &even[i..] { + out.push(bind_address_entry( + Some(entry), + None, + even_checkpoint, + odd_checkpoint, + challenge, + )); + even_checkpoint = entry.next_val; + } + for entry in &odd[j..] { + out.push(bind_address_entry( + None, + Some(entry), + even_checkpoint, + odd_checkpoint, + challenge, + )); + odd_checkpoint = entry.next_val; + } +} + +fn bind_address_entry( + even: Option<&RamAddressEntry>, + odd: Option<&RamAddressEntry>, + even_checkpoint: F, + odd_checkpoint: F, + r: F, +) -> RamAddressEntry { + match (even, odd) { + (Some(even), Some(odd)) => RamAddressEntry { + row: even.row, + col: even.col / 2, + ra_coeff: line(even.ra_coeff, odd.ra_coeff, r), + val_coeff: line(even.val_coeff, odd.val_coeff, r), + prev_val: line(even.prev_val, odd.prev_val, r), + next_val: line(even.next_val, odd.next_val, r), + }, + (Some(even), None) => RamAddressEntry { + row: even.row, + col: even.col / 2, + ra_coeff: line(even.ra_coeff, F::zero(), r), + val_coeff: line(even.val_coeff, odd_checkpoint, r), + prev_val: line(even.prev_val, odd_checkpoint, r), + next_val: line(even.next_val, odd_checkpoint, r), + }, + (None, Some(odd)) => RamAddressEntry { + row: odd.row, + col: odd.col / 2, + ra_coeff: line(F::zero(), odd.ra_coeff, r), + val_coeff: line(even_checkpoint, odd.val_coeff, r), + prev_val: line(even_checkpoint, odd.prev_val, r), + next_val: line(even_checkpoint, odd.next_val, r), + }, + (None, None) => unreachable!(), + } +} + +fn expected_batched_output_claim( + context: Stage2KernelContext<'_>, + store: &Stage2ValueStore, + evals: &[Stage2NamedEval], + point: &[F], + batching_coeffs: &[F], + ram: Option<&Stage2RamData<'_>>, +) -> Result { + let mut expected = F::zero(); + for (claim, &coefficient) in context.batch_claims()?.iter().zip(batching_coeffs) { + let instance = context + .program + .instance_results + .iter() + .find(|instance| { + instance.claim == claim.symbol && instance.source == context.driver.symbol + }) + .ok_or(Stage2KernelError::MissingClaim { + batch: context.batch.symbol, + claim: claim.symbol, + })?; + let local_point = point + .get(instance.round_offset..instance.round_offset + instance.num_rounds) + .ok_or(Stage2KernelError::InvalidInputLength { + input: instance.symbol, + expected: instance.round_offset + instance.num_rounds, + actual: point.len(), + })?; + let claim_value = match Stage2Relation::from_symbol(instance.relation).ok_or( + Stage2KernelError::UnknownRelation { + relation: instance.relation, + }, + )? { + Stage2Relation::RamReadWrite => expected_ram_read_write(store, evals, local_point)?, + Stage2Relation::ProductVirtualRemainder => { + expected_product_remainder(store, evals, local_point)? + } + Stage2Relation::InstructionLookupClaimReduction => { + expected_instruction_lookup(store, evals, local_point)? + } + Stage2Relation::RamRafEvaluation => expected_ram_raf(store, evals, local_point, ram)?, + Stage2Relation::RamOutputCheck => expected_ram_output(store, evals, local_point, ram)?, + relation => { + return Err(Stage2KernelError::KernelNotImplemented { + abi: relation.symbol(), + }) + } + }; + expected += coefficient * claim_value; + } + Ok(expected) +} + +fn expected_ram_read_write( + store: &Stage2ValueStore, + evals: &[Stage2NamedEval], + local_point: &[F], +) -> Result { + let r_cycle_stage1 = store.point("stage2.input.stage1.RamReadValue")?; + let log_t = r_cycle_stage1.len(); + let r_cycle = reverse_slice(&local_point[..log_t]); + let eq_eval = EqPolynomial::::mle(r_cycle_stage1, &r_cycle); + let gamma = store.scalar("stage2.ram_read_write.gamma")?; + let val = eval_by_name(evals, "stage2.ram_read_write.eval.RamVal")?; + let ra = eval_by_name(evals, "stage2.ram_read_write.eval.RamRa")?; + let inc = eval_by_name(evals, "stage2.ram_read_write.eval.RamInc")?; + Ok(eq_eval * ra * (val + gamma * (val + inc))) +} + +fn expected_product_remainder( + store: &Stage2ValueStore, + evals: &[Stage2NamedEval], + local_point: &[F], +) -> Result { + let tau_low = store.point("stage2.input.stage1.Product")?; + let tau_high = store.scalar("stage2.product_virtual.tau_high")?; + let r0 = *store + .point("stage2.product_virtual.uniskip.sumcheck")? + .first() + .ok_or(Stage2KernelError::MissingValue { + symbol: "stage2.product_virtual.uniskip.sumcheck", + })?; + let r_tail = reverse_slice(local_point); + let low = EqPolynomial::::mle(tau_low, &r_tail); + let high = lagrange_kernel_eval( + PRODUCT_VIRTUAL_UNISKIP_DOMAIN_START, + PRODUCT_VIRTUAL_UNISKIP_DOMAIN_SIZE, + tau_high, + r0, + ); + let weights = lagrange_evals( + PRODUCT_VIRTUAL_UNISKIP_DOMAIN_START, + PRODUCT_VIRTUAL_UNISKIP_DOMAIN_SIZE, + r0, + ); + let left = weights[0] + * eval_by_name( + evals, + "stage2.product_virtual.remainder.eval.LeftInstructionInput", + )? + + weights[1] * eval_by_name(evals, "stage2.product_virtual.remainder.eval.LookupOutput")? + + weights[2] * eval_by_name(evals, "stage2.product_virtual.remainder.eval.OpFlagJump")?; + let right = weights[0] + * eval_by_name( + evals, + "stage2.product_virtual.remainder.eval.RightInstructionInput", + )? + + weights[1] + * eval_by_name( + evals, + "stage2.product_virtual.remainder.eval.InstructionFlagBranch", + )? + + weights[2] + * (F::one() - eval_by_name(evals, "stage2.product_virtual.remainder.eval.NextIsNoop")?); + Ok(high * low * left * right) +} + +fn expected_instruction_lookup( + store: &Stage2ValueStore, + evals: &[Stage2NamedEval], + local_point: &[F], +) -> Result { + let opening_point = reverse_slice(local_point); + let r_spartan = store.point("stage2.input.stage1.LookupOutput")?; + let eq_eval = EqPolynomial::::mle(&opening_point, r_spartan); + let gamma = store.scalar("stage2.instruction_lookup.gamma")?; + let gamma_sqr = gamma.square(); + let gamma_cub = gamma_sqr * gamma; + let gamma_quart = gamma_sqr.square(); + let weighted = eval_by_name( + evals, + "stage2.instruction_lookup.claim_reduction.eval.LookupOutput", + )? + gamma + * eval_by_name( + evals, + "stage2.instruction_lookup.claim_reduction.eval.LeftLookupOperand", + )? + + gamma_sqr + * eval_by_name( + evals, + "stage2.instruction_lookup.claim_reduction.eval.RightLookupOperand", + )? + + gamma_cub + * eval_by_name( + evals, + "stage2.instruction_lookup.claim_reduction.eval.LeftInstructionInput", + )? + + gamma_quart + * eval_by_name( + evals, + "stage2.instruction_lookup.claim_reduction.eval.RightInstructionInput", + )?; + Ok(eq_eval * weighted) +} + +fn expected_ram_raf( + _store: &Stage2ValueStore, + evals: &[Stage2NamedEval], + local_point: &[F], + ram: Option<&Stage2RamData<'_>>, +) -> Result { + let ram = ram.ok_or(Stage2KernelError::MissingKernelInput { + kernel: "jolt_stage2_ram_raf_evaluation", + input: "ram", + })?; + let address = reverse_slice(local_point); + let unmap = unmap_eval(ram.log_k, ram.start_address, &address); + Ok(unmap * eval_by_name(evals, "stage2.ram_raf.eval.RamRa")?) +} + +fn expected_ram_output( + store: &Stage2ValueStore, + evals: &[Stage2NamedEval], + local_point: &[F], + ram: Option<&Stage2RamData<'_>>, +) -> Result { + let ram = ram.ok_or(Stage2KernelError::MissingKernelInput { + kernel: "jolt_stage2_ram_output_check", + input: "ram", + })?; + let layout = ram + .output_layout + .ok_or(Stage2KernelError::MissingKernelInput { + kernel: "jolt_stage2_ram_output_check", + input: "ram.output_layout", + })?; + let r_address = store.point("stage2.ram_output.r_address")?; + let opening_point = reverse_slice(local_point); + let eq_eval = EqPolynomial::::mle(r_address, &opening_point); + let io_mask = range_mask_eval(layout.io_start, layout.io_end, &opening_point); + let val_io = sparse_final_ram_eval( + ram.final_ram, + layout.io_start, + layout.io_end, + &opening_point, + ); + let val_final = eval_by_name(evals, "stage2.ram_output.eval.RamValFinal")?; + Ok(eq_eval * io_mask * (val_final - val_io)) +} + +fn eval_by_name( + evals: &[Stage2NamedEval], + name: &'static str, +) -> Result { + evals + .iter() + .find(|eval| eval.name == name) + .map(|eval| eval.value) + .ok_or(Stage2KernelError::MissingValue { symbol: name }) +} + +fn reverse_slice(values: &[F]) -> Vec { + values.iter().rev().copied().collect() +} + +fn unmap_eval(log_k: usize, start_address: u64, point: &[F]) -> F { + point + .iter() + .enumerate() + .fold(F::from_u64(start_address), |acc, (index, &value)| { + acc + value.mul_pow_2(log_k - 1 - index).mul_u64(8) + }) +} + +fn range_mask_eval(start: usize, end: usize, point: &[F]) -> F { + eq_prefix_sum(end, point) - eq_prefix_sum(start, point) +} + +fn sparse_final_ram_eval(values: &[u64], start: usize, end: usize, point: &[F]) -> F { + let mut total = F::zero(); + for (offset, &value) in values[start..end].iter().enumerate() { + if value != 0 { + total += F::from_u64(value) * eq_eval_at_index(start + offset, point); + } + } + total +} + +fn ram_eval_reversed(values: &[u64], nonzero_values: &[(usize, u64)], point: &[F]) -> F { + let opening_point = reverse_slice(point); + if nonzero_values.len() * opening_point.len() <= values.len() { + nonzero_values + .iter() + .map(|&(index, value)| F::from_u64(value) * eq_eval_at_index(index, &opening_point)) + .sum() + } else { + let eq = EqPolynomial::::evals(&opening_point, None); + values + .par_iter() + .zip(eq.par_iter()) + .fold(F::Accumulator::default, |mut total, (&value, &weight)| { + if value != 0 { + total.fmadd(F::from_u64(value), weight); + } + total + }) + .reduce(F::Accumulator::default, |mut left, right| { + left.merge(right); + left + }) + .reduce() + } +} + +fn eq_prefix_sum(end: usize, point: &[F]) -> F { + let domain_len = 1usize << point.len(); + if end >= domain_len { + return F::one(); + } + let mut sum = F::zero(); + let mut prefix = F::one(); + for (bit, &r) in point.iter().enumerate() { + let mask = 1usize << (point.len() - 1 - bit); + if end & mask == 0 { + prefix *= F::one() - r; + } else { + sum += prefix * (F::one() - r); + prefix *= r; + } + } + sum +} + +fn eq_eval_at_index(index: usize, point: &[F]) -> F { + point.iter().enumerate().fold(F::one(), |acc, (bit, &r)| { + let mask = 1usize << (point.len() - 1 - bit); + if index & mask == 0 { + acc * (F::one() - r) + } else { + acc * r + } + }) +} + +const PRODUCT_REMAINDER_EVAL_NAMES: [(&str, &str); 8] = [ + ( + "stage2.product_virtual.remainder.eval.LeftInstructionInput", + "LeftInstructionInput", + ), + ( + "stage2.product_virtual.remainder.eval.RightInstructionInput", + "RightInstructionInput", + ), + ( + "stage2.product_virtual.remainder.eval.OpFlagJump", + "OpFlagJump", + ), + ( + "stage2.product_virtual.remainder.eval.OpFlagWriteLookupOutputToRD", + "OpFlagWriteLookupOutputToRD", + ), + ( + "stage2.product_virtual.remainder.eval.LookupOutput", + "LookupOutput", + ), + ( + "stage2.product_virtual.remainder.eval.InstructionFlagBranch", + "InstructionFlagBranch", + ), + ( + "stage2.product_virtual.remainder.eval.NextIsNoop", + "NextIsNoop", + ), + ( + "stage2.product_virtual.remainder.eval.OpFlagVirtualInstruction", + "OpFlagVirtualInstruction", + ), +]; + +const INSTRUCTION_LOOKUP_EVAL_NAMES: [(&str, &str); 5] = [ + ( + "stage2.instruction_lookup.claim_reduction.eval.LookupOutput", + "LookupOutput", + ), + ( + "stage2.instruction_lookup.claim_reduction.eval.LeftLookupOperand", + "LeftLookupOperand", + ), + ( + "stage2.instruction_lookup.claim_reduction.eval.RightLookupOperand", + "RightLookupOperand", + ), + ( + "stage2.instruction_lookup.claim_reduction.eval.LeftInstructionInput", + "LeftInstructionInput", + ), + ( + "stage2.instruction_lookup.claim_reduction.eval.RightInstructionInput", + "RightInstructionInput", + ), +]; + +fn product_remainder_final_evals( + cycles: &[Stage2ProductVirtualCycle], + point: &[F], + relation: Stage2Relation, +) -> Result>, Stage2KernelError> { + let values = product_remainder_output_evals(cycles, point, relation)?; + Ok(PRODUCT_REMAINDER_EVAL_NAMES + .iter() + .zip(values) + .map(|(&(name, oracle), value)| named_eval(name, oracle, value)) + .collect()) +} + +fn product_remainder_output_evals( + cycles: &[Stage2ProductVirtualCycle], + point: &[F], + relation: Stage2Relation, +) -> Result<[F; 8], Stage2KernelError> { + let expected = + 1usize + .checked_shl(point.len() as u32) + .ok_or(Stage2KernelError::InvalidInputLength { + input: "stage2.product_remainder_output.point", + expected: usize::BITS as usize, + actual: point.len(), + })?; + if cycles.len() != expected { + return Err(Stage2KernelError::InvalidInputLength { + input: relation.symbol(), + expected, + actual: cycles.len(), + }); + } + let opening_point = reverse_slice(point); + let (r_hi, r_lo) = opening_point.split_at(opening_point.len() / 2); + let (eq_out, eq_in) = rayon::join( + || EqPolynomial::::evals(r_hi, None), + || EqPolynomial::::evals(r_lo, None), + ); + let accumulators = (0..eq_out.len()) + .into_par_iter() + .map(|x_out| { + let start = x_out * eq_in.len(); + let mut inner = [F::Accumulator::default(); 8]; + for (x_in, &weight) in eq_in.iter().enumerate() { + accumulate_product_remainder_outputs(&mut inner, &cycles[start + x_in], weight); + } + let mut outer = [F::Accumulator::default(); 8]; + for (outer, inner) in outer.iter_mut().zip(inner) { + outer.fmadd(inner.reduce(), eq_out[x_out]); + } + outer + }) + .reduce( + || [F::Accumulator::default(); 8], + |mut left, right| { + for (left, right) in left.iter_mut().zip(right) { + left.merge(right); + } + left + }, + ); + Ok(accumulators.map(FieldAccumulator::reduce)) +} + +fn accumulate_product_remainder_outputs( + accumulators: &mut [F::Accumulator; 8], + cycle: &Stage2ProductVirtualCycle, + weight: F, +) { + accumulators[0].fmadd_u64(weight, cycle.instruction_left_input); + accumulators[1].fmadd(weight, F::from_i128(cycle.instruction_right_input)); + accumulators[2].fmadd_bool(weight, cycle.jump_flag); + accumulators[3].fmadd_bool(weight, cycle.write_lookup_output_to_rd_flag); + accumulators[4].fmadd_u64(weight, cycle.should_branch_lookup_output); + accumulators[5].fmadd_bool(weight, cycle.should_branch_flag); + accumulators[6].fmadd_bool(weight, !cycle.not_next_noop); + accumulators[7].fmadd_bool(weight, cycle.virtual_instruction_flag); +} + +fn accumulate_instruction_lookup_outputs( + accumulators: &mut [F::Accumulator; 5], + cycle: &Stage2InstructionLookupCycle, + weight: F, +) { + accumulators[0].fmadd_u64(weight, cycle.lookup_output); + accumulators[1].fmadd_u64(weight, cycle.left_lookup_operand); + accumulators[2].fmadd(weight, F::from_u128(cycle.right_lookup_operand)); + accumulators[3].fmadd_u64(weight, cycle.left_instruction_input); + accumulators[4].fmadd(weight, F::from_i128(cycle.right_instruction_input)); +} + +fn named_eval(name: &'static str, oracle: &'static str, value: F) -> Stage2NamedEval { + Stage2NamedEval { + name, + oracle, + value, + } +} + +fn claim_relation( + program: &'static Stage2CpuProgramPlan, + claim: &Stage2SumcheckClaimPlan, +) -> Result { + if let Some(relation) = claim.relation { + return Stage2Relation::from_symbol(relation) + .ok_or(Stage2KernelError::UnknownRelation { relation }); + } + let kernel_symbol = claim.kernel.ok_or(Stage2KernelError::MissingKernel { + driver: claim.symbol, + kernel: "", + })?; + let kernel = find_kernel(program, kernel_symbol).ok_or(Stage2KernelError::MissingKernel { + driver: claim.symbol, + kernel: kernel_symbol, + })?; + kernel.relation_kind() +} + +fn instance_round_offset( + program: &'static Stage2CpuProgramPlan, + driver: &'static str, + claim: &'static str, +) -> Result { + program + .instance_results + .iter() + .find(|instance| instance.source == driver && instance.claim == claim) + .map(|instance| instance.round_offset) + .ok_or(Stage2KernelError::MissingClaim { + batch: driver, + claim, + }) +} + +fn combine_univariate_polys( + polynomials: &[UnivariatePoly], + coefficients: &[F], +) -> UnivariatePoly { + let max_len = polynomials + .iter() + .map(|poly| poly.coefficients().len()) + .max() + .unwrap_or(0); + let mut combined = vec![F::zero(); max_len]; + for (poly, &coefficient) in polynomials.iter().zip(coefficients) { + for (combined, &term) in combined.iter_mut().zip(poly.coefficients()) { + *combined += term * coefficient; + } + } + trim_trailing_zero_coefficients(UnivariatePoly::new(combined), 3) +} + +fn trim_trailing_zero_coefficients( + polynomial: UnivariatePoly, + min_len: usize, +) -> UnivariatePoly { + let mut coefficients = polynomial.into_coefficients(); + while coefficients.len() > min_len && coefficients.last() == Some(&F::zero()) { + let _ = coefficients.pop(); + } + UnivariatePoly::new(coefficients) +} + +fn round_poly_from_factors(factors: &[Vec], degree: usize) -> UnivariatePoly { + let factor_slices = factors.iter().map(Vec::as_slice).collect::>(); + round_poly_from_factor_slices(&factor_slices, degree) +} + +fn round_poly_from_factor_slices(factors: &[&[F]], degree: usize) -> UnivariatePoly { + if factors.is_empty() { + return UnivariatePoly::zero(); + } + let half = factors[0].len() / 2; + let accumulators = if half >= DENSE_BIND_PAR_THRESHOLD { + (0..half) + .into_par_iter() + .map(|row| dense_product_coefficients(factors, row)) + .reduce( + || [F::Accumulator::default(); 4], + |mut left, right| { + for index in 0..left.len() { + left[index].merge(right[index]); + } + left + }, + ) + } else { + (0..half).fold([F::Accumulator::default(); 4], |mut total, row| { + let row_coeffs = dense_product_coefficients(factors, row); + for index in 0..total.len() { + total[index].merge(row_coeffs[index]); + } + total + }) + }; + UnivariatePoly::new( + accumulators[..=degree] + .iter() + .copied() + .map(FieldAccumulator::reduce) + .collect(), + ) +} + +fn dense_product_coefficients(factors: &[&[F]], row: usize) -> [F::Accumulator; 4] { + if factors.len() == 2 { + let left0 = factors[0][2 * row]; + let left_delta = factors[0][2 * row + 1] - left0; + let right0 = factors[1][2 * row]; + let right_delta = factors[1][2 * row + 1] - right0; + let mut accumulators = [F::Accumulator::default(); 4]; + accumulators[0].fmadd(left0, right0); + accumulators[1].fmadd(left_delta, right0); + accumulators[1].fmadd(left0, right_delta); + accumulators[2].fmadd(left_delta, right_delta); + return accumulators; + } + if factors.len() == 3 { + let first0 = factors[0][2 * row]; + let first_delta = factors[0][2 * row + 1] - first0; + let second0 = factors[1][2 * row]; + let second_delta = factors[1][2 * row + 1] - second0; + let third0 = factors[2][2 * row]; + let third_delta = factors[2][2 * row + 1] - third0; + let mut accumulators = [F::Accumulator::default(); 4]; + accumulate_cubic_product_coefficients( + &mut accumulators, + first0, + first_delta, + second0, + second_delta, + third0, + third_delta, + ); + return accumulators; + } + + let mut coefficients = [F::zero(); 4]; + coefficients[0] = F::one(); + for (degree, factor) in factors.iter().enumerate() { + let low = factor[2 * row]; + let delta = factor[2 * row + 1] - low; + for index in (0..=degree).rev() { + coefficients[index + 1] += coefficients[index] * delta; + coefficients[index] *= low; + } + } + let mut accumulators = [F::Accumulator::default(); 4]; + for (accumulator, coefficient) in accumulators.iter_mut().zip(coefficients) { + accumulator.acc_add(coefficient); + } + accumulators +} + +fn accumulate_cubic_product_coefficients( + coefficients: &mut [F::Accumulator; 4], + first0: F, + first_delta: F, + second0: F, + second_delta: F, + third0: F, + third_delta: F, +) { + let second0_third0 = second0 * third0; + let second_delta_third0 = second_delta * third0; + let second0_third_delta = second0 * third_delta; + let second_delta_third_delta = second_delta * third_delta; + + coefficients[0].fmadd(first0, second0_third0); + coefficients[1].fmadd(first_delta, second0_third0); + coefficients[1].fmadd(first0, second_delta_third0); + coefficients[1].fmadd(first0, second0_third_delta); + coefficients[2].fmadd(first_delta, second_delta_third0); + coefficients[2].fmadd(first_delta, second0_third_delta); + coefficients[2].fmadd(first0, second_delta_third_delta); + coefficients[3].fmadd(first_delta, second_delta_third_delta); +} + +fn line(lo: F, hi: F, x: F) -> F { + lo + x * (hi - lo) +} + +fn product_uniskip_base_evals( + store: &Stage2ValueStore, +) -> Result<[F; PRODUCT_VIRTUAL_UNISKIP_DOMAIN_SIZE], Stage2KernelError> { + Ok([ + store.scalar("stage2.input.stage1.Product")?, + store.scalar("stage2.input.stage1.ShouldBranch")?, + store.scalar("stage2.input.stage1.ShouldJump")?, + ]) +} + +#[tracing::instrument(skip_all, name = "stage2_product_virtual_uniskip_extended_evals")] +pub fn product_virtual_uniskip_extended_evals( + cycles: &[Stage2ProductVirtualCycle], + tau_low: &[Fr], +) -> Result<[Fr; PRODUCT_VIRTUAL_UNISKIP_DEGREE], Stage2KernelError> { + let expected = + 1usize + .checked_shl(tau_low.len() as u32) + .ok_or(Stage2KernelError::InvalidInputLength { + input: "stage2.product_virtual.tau_low", + expected: usize::BITS as usize, + actual: tau_low.len(), + })?; + if cycles.len() != expected { + return Err(Stage2KernelError::InvalidInputLength { + input: "stage2.product_virtual.cycles", + expected, + actual: cycles.len(), + }); + } + + let eq_evals = EqPolynomial::::evals(tau_low, None); + let accumulators = eq_evals + .par_iter() + .zip(cycles.par_iter()) + .fold( + || [FrSignedScalarAccumulator::zero(); PRODUCT_VIRTUAL_UNISKIP_DEGREE], + |mut local, (&weight, cycle)| { + for (target, accumulator) in local.iter_mut().enumerate() { + accumulator.fmadd_s256( + weight, + product_virtual_extended_fused_product(cycle, target), + ); + } + local + }, + ) + .reduce( + || [FrSignedScalarAccumulator::zero(); PRODUCT_VIRTUAL_UNISKIP_DEGREE], + |mut left, right| { + for (left, right) in left.iter_mut().zip(right) { + left.merge(right); + } + left + }, + ); + + Ok(accumulators.map(FrSignedScalarAccumulator::reduce)) +} + +fn product_virtual_extended_fused_product( + cycle: &Stage2ProductVirtualCycle, + target: usize, +) -> S256 { + let coefficients = PRODUCT_VIRTUAL_UNISKIP_TARGET_COEFFS[target]; + let left = coefficients[0] as i128 * cycle.instruction_left_input as i128 + + coefficients[1] as i128 * cycle.should_branch_lookup_output as i128 + + coefficients[2] as i128 * i128::from(cycle.jump_flag); + let right = coefficients[0] as i128 * cycle.instruction_right_input + + coefficients[1] as i128 * i128::from(cycle.should_branch_flag) + + coefficients[2] as i128 * i128::from(cycle.not_next_noop); + S128::from_i128(left).mul_trunc::<2, 4>(&S128::from_i128(right)) +} + +#[derive(Clone, Copy)] +struct FrSignedScalarAccumulator { + positive: Limbs<9>, + negative: Limbs<9>, +} + +impl FrSignedScalarAccumulator { + fn zero() -> Self { + Self { + positive: Limbs::zero(), + negative: Limbs::zero(), + } + } + + fn fmadd_s256(&mut self, field: Fr, scalar: S256) { + if scalar.magnitude_limbs() == [0u64; 4] { + return; + } + self.fmadd_limbs(field, scalar.as_magnitude(), scalar.is_positive); + } + + fn fmadd_limbs(&mut self, field: Fr, scalar: &Limbs, is_positive: bool) { + let mut product = Limbs::<9>::zero(); + product.fmadd::<4, L>(&field.inner_limbs(), scalar); + if is_positive { + self.positive.add_assign_trunc::<9>(&product); + } else { + self.negative.add_assign_trunc::<9>(&product); + } + } + + fn merge(&mut self, other: Self) { + self.positive.add_assign_trunc::<9>(&other.positive); + self.negative.add_assign_trunc::<9>(&other.negative); + } + + fn reduce(self) -> Fr { + match self.positive.cmp(&self.negative) { + Ordering::Greater | Ordering::Equal => { + Fr::from_barrett_reduced_limbs(self.positive.sub_trunc::<9, 9>(&self.negative)) + } + Ordering::Less => { + -Fr::from_barrett_reduced_limbs(self.negative.sub_trunc::<9, 9>(&self.positive)) + } + } + } +} + +fn build_product_uniskip_poly( + base_evals: &[F; PRODUCT_VIRTUAL_UNISKIP_DOMAIN_SIZE], + extended_evals: &[F], + tau_high: F, +) -> Result, Stage2KernelError> { + if extended_evals.len() != PRODUCT_VIRTUAL_UNISKIP_DEGREE { + return Err(Stage2KernelError::InvalidInputLength { + input: "product_uniskip_extended_evals", + expected: PRODUCT_VIRTUAL_UNISKIP_DEGREE, + actual: extended_evals.len(), + }); + } + + let mut t1_values = vec![F::zero(); PRODUCT_VIRTUAL_UNISKIP_EXTENDED_SIZE]; + for (index, value) in base_evals.iter().enumerate() { + let target = PRODUCT_VIRTUAL_UNISKIP_DOMAIN_START + index as i64; + t1_values[(target - PRODUCT_VIRTUAL_UNISKIP_EXTENDED_START) as usize] = *value; + } + for (value, target) in extended_evals.iter().zip(product_uniskip_targets()) { + t1_values[(target - PRODUCT_VIRTUAL_UNISKIP_EXTENDED_START) as usize] = *value; + } + + let t1_coeffs = interpolate_to_coeffs(PRODUCT_VIRTUAL_UNISKIP_EXTENDED_START, &t1_values); + let lagrange_values = lagrange_evals( + PRODUCT_VIRTUAL_UNISKIP_DOMAIN_START, + PRODUCT_VIRTUAL_UNISKIP_DOMAIN_SIZE, + tau_high, + ); + let lagrange_coeffs = + interpolate_to_coeffs(PRODUCT_VIRTUAL_UNISKIP_DOMAIN_START, &lagrange_values); + + let mut coefficients = vec![F::zero(); PRODUCT_VIRTUAL_UNISKIP_NUM_COEFFS]; + for (i, &lagrange_coeff) in lagrange_coeffs.iter().enumerate() { + for (j, &t1_coeff) in t1_coeffs.iter().enumerate() { + coefficients[i + j] += lagrange_coeff * t1_coeff; + } + } + Ok(UnivariatePoly::new(coefficients)) +} + +fn product_uniskip_targets() -> [i64; PRODUCT_VIRTUAL_UNISKIP_DEGREE] { + [-2, 2] +} + +fn product_uniskip_sum_matches(poly: &UnivariatePoly, claim: F) -> bool { + (0..PRODUCT_VIRTUAL_UNISKIP_DOMAIN_SIZE) + .map(|index| { + poly.evaluate(F::from_i64( + PRODUCT_VIRTUAL_UNISKIP_DOMAIN_START + index as i64, + )) + }) + .sum::() + == claim +} + +fn polynomial_degree(poly: &UnivariatePoly) -> usize { + poly.coefficients() + .iter() + .rposition(|coefficient| *coefficient != F::zero()) + .unwrap_or(0) +} + +fn append_univariate_poly(transcript: &mut T, label: &'static str, poly: &UnivariatePoly) +where + F: Field, + T: Transcript, +{ + transcript.append(&LabelWithCount( + label.as_bytes(), + poly.coefficients().len() as u64, + )); + for coefficient in poly.coefficients() { + transcript.append(coefficient); + } +} + +fn append_compressed_univariate_poly( + transcript: &mut T, + label: &'static str, + poly: &UnivariatePoly, +) where + F: Field, + T: Transcript, +{ + let compressed = poly.compress(); + transcript.append(&LabelWithCount( + label.as_bytes(), + compressed.coeffs_except_linear_term().len() as u64, + )); + for coefficient in compressed.coeffs_except_linear_term() { + transcript.append(coefficient); + } +} + +fn append_labeled_scalar(transcript: &mut T, label: &'static str, scalar: &F) +where + F: Field, + T: Transcript, +{ + transcript.append(&Label(label.as_bytes())); + transcript.append(scalar); +} + +fn append_opening_claims( + program: &'static Stage2CpuProgramPlan, + store: &mut Stage2ValueStore, + transcript: &mut T, + evals: &[Stage2NamedEval], +) -> Result>, Stage2KernelError> +where + F: Field, + T: Transcript, +{ + if program.opening_batches.is_empty() { + for eval in evals { + append_labeled_scalar(transcript, "opening_claim", &eval.value); + } + return Ok(Vec::new()); + } + let _ = store.evaluate_available_points(program)?; + let mut opening_claims = Vec::new(); + let mut seen = seed_stage2_opening_aliases(store, program); + for batch in program.opening_batches { + for symbol in batch.claim_operands { + let claim = + find_opening_claim(program, symbol).ok_or(Stage2KernelError::MissingClaim { + batch: batch.symbol, + claim: symbol, + })?; + let point = store.point(claim.point_source)?.to_vec(); + let value = store.scalar(claim.eval_source)?; + let duplicate = has_seen_opening(&seen, claim.claim_kind, claim.oracle, &point); + if !duplicate { + append_labeled_scalar(transcript, "opening_claim", &value); + seen.push((claim.claim_kind, claim.oracle, point.clone())); + } + opening_claims.push(Stage2OpeningClaimValue { + symbol: claim.symbol, + oracle: claim.oracle, + domain: claim.domain, + claim_kind: claim.claim_kind, + point: point.clone(), + eval: value, + }); + } + } + Ok(opening_claims) +} + +fn seed_stage2_opening_aliases( + store: &Stage2ValueStore, + program: &'static Stage2CpuProgramPlan, +) -> Vec<(&'static str, &'static str, Vec)> { + program + .opening_inputs + .iter() + .filter_map(|input| { + store + .try_point(input.symbol) + .map(|point| (input.claim_kind, input.oracle, point.to_vec())) + }) + .collect() +} + +fn has_seen_opening( + seen: &[(&'static str, &'static str, Vec)], + claim_kind: &'static str, + oracle: &'static str, + point: &[F], +) -> bool { + seen.iter().any(|(seen_kind, seen_oracle, seen_point)| { + *seen_kind == claim_kind && *seen_oracle == oracle && seen_point.as_slice() == point + }) +} + +fn driver_evals(context: Stage2KernelContext<'_>, value: F) -> Vec> { + context + .program + .evals_for_driver(context.driver.symbol) + .map(|eval| Stage2NamedEval { + name: eval.name, + oracle: eval.oracle, + value, + }) + .collect() +} + +fn verify_driver_evals( + driver: &'static str, + expected: &[Stage2NamedEval], + actual: &[Stage2NamedEval], +) -> Result<(), Stage2KernelError> { + if expected.len() != actual.len() { + return Err(Stage2KernelError::InvalidProof { + driver, + reason: "product uniskip eval count mismatch", + }); + } + for (expected, actual) in expected.iter().zip(actual) { + if expected.name != actual.name + || expected.oracle != actual.oracle + || expected.value != actual.value + { + return Err(Stage2KernelError::InvalidProof { + driver, + reason: "product uniskip eval mismatch", + }); + } + } + Ok(()) +} + +pub fn execute_stage2_program( + program: &'static Stage2CpuProgramPlan, + mode: Stage2ExecutionMode, + executor: &mut E, + transcript: &mut T, +) -> Result, Stage2KernelError> +where + F: Field, + E: Stage2KernelExecutor, + T: Transcript, +{ + verify_static_program_shape(program)?; + let mut artifacts = Stage2ExecutionArtifacts::default(); + if program.steps.is_empty() { + for squeeze in program.transcript_squeezes { + execute_stage2_squeeze(squeeze, executor, transcript, &mut artifacts)?; + } + for driver in program.drivers { + execute_stage2_driver(program, mode, driver, executor, transcript, &mut artifacts)?; + } + } else { + for step in program.steps { + match step.kind { + "transcript_squeeze" => { + let squeeze = find_transcript_squeeze(program, step.symbol).ok_or( + Stage2KernelError::MissingValue { + symbol: step.symbol, + }, + )?; + execute_stage2_squeeze(squeeze, executor, transcript, &mut artifacts)?; + } + "sumcheck_driver" => { + let driver = find_driver(program, step.symbol).ok_or( + Stage2KernelError::MissingKernel { + driver: step.symbol, + kernel: step.symbol, + }, + )?; + execute_stage2_driver( + program, + mode, + driver, + executor, + transcript, + &mut artifacts, + )?; + } + _ => { + return Err(Stage2KernelError::InvalidProof { + driver: step.symbol, + reason: "unsupported stage2 program step", + }) + } + } + } + } + artifacts + .opening_batches + .extend(program.opening_batches.iter()); + Ok(artifacts) +} + +fn execute_stage2_squeeze( + squeeze: &'static Stage2TranscriptSqueezePlan, + executor: &mut E, + transcript: &mut T, + artifacts: &mut Stage2ExecutionArtifacts, +) -> Result<(), Stage2KernelError> +where + F: Field, + E: Stage2KernelExecutor, + T: Transcript, +{ + let values = transcript.challenge_vector(squeeze.count); + executor.observe_challenge_vector(squeeze, &values)?; + artifacts.challenge_vectors.push(Stage2ChallengeVector { + symbol: squeeze.symbol, + values, + }); + Ok(()) +} + +fn execute_stage2_driver( + program: &'static Stage2CpuProgramPlan, + mode: Stage2ExecutionMode, + driver: &'static Stage2SumcheckDriverPlan, + executor: &mut E, + transcript: &mut T, + artifacts: &mut Stage2ExecutionArtifacts, +) -> Result<(), Stage2KernelError> +where + F: Field, + E: Stage2KernelExecutor, + T: Transcript, +{ + let kernel_symbol = driver.kernel.ok_or(Stage2KernelError::MissingKernel { + driver: driver.symbol, + kernel: "", + })?; + let kernel = find_kernel(program, kernel_symbol).ok_or(Stage2KernelError::MissingKernel { + driver: driver.symbol, + kernel: kernel_symbol, + })?; + let batch = find_batch(program, driver.batch).ok_or(Stage2KernelError::MissingBatch { + driver: driver.symbol, + batch: driver.batch, + })?; + let context = Stage2KernelContext { + mode, + program, + kernel, + batch, + driver, + }; + let output = match mode { + Stage2ExecutionMode::Prover => executor.prove_sumcheck(context, transcript)?, + Stage2ExecutionMode::Verifier => executor.verify_sumcheck(context, transcript)?, + }; + executor.observe_sumcheck_output(&output)?; + artifacts + .opening_claims + .extend(output.opening_claims.clone()); + artifacts.sumchecks.push(output); + Ok(()) +} + +fn verify_static_program_shape( + program: &'static Stage2CpuProgramPlan, +) -> Result<(), Stage2KernelError> { + for expr in program.field_exprs { + verify_count(expr.symbol, expr.operand_names.len(), expr.operands.len())?; + } + for batch in program.batches { + verify_count(batch.symbol, batch.count, batch.ordered_claims.len())?; + verify_count(batch.symbol, batch.count, batch.claim_operands.len())?; + } + for batch in program.opening_batches { + verify_count(batch.symbol, batch.count, batch.ordered_claims.len())?; + verify_count(batch.symbol, batch.count, batch.claim_operands.len())?; + } + for step in program.steps { + match step.kind { + "transcript_squeeze" => { + let _ = find_transcript_squeeze(program, step.symbol).ok_or( + Stage2KernelError::MissingValue { + symbol: step.symbol, + }, + )?; + } + "sumcheck_driver" => { + let _ = + find_driver(program, step.symbol).ok_or(Stage2KernelError::MissingKernel { + driver: step.symbol, + kernel: step.symbol, + })?; + } + _ => { + return Err(Stage2KernelError::InvalidProof { + driver: step.symbol, + reason: "unsupported stage2 program step", + }) + } + } + } + Ok(()) +} + +fn verify_count( + artifact: &'static str, + expected: usize, + actual: usize, +) -> Result<(), Stage2KernelError> { + if expected == actual { + Ok(()) + } else { + Err(Stage2KernelError::PlanCountMismatch { + artifact, + expected, + actual, + }) + } +} + +fn find_kernel<'a>( + program: &'a Stage2CpuProgramPlan, + symbol: &str, +) -> Option<&'a Stage2KernelPlan> { + program + .kernels + .iter() + .find(|kernel| kernel.symbol == symbol) +} + +fn find_batch<'a>( + program: &'a Stage2CpuProgramPlan, + symbol: &str, +) -> Option<&'a Stage2SumcheckBatchPlan> { + program.batches.iter().find(|batch| batch.symbol == symbol) +} + +fn find_driver<'a>( + program: &'a Stage2CpuProgramPlan, + symbol: &str, +) -> Option<&'a Stage2SumcheckDriverPlan> { + program + .drivers + .iter() + .find(|driver| driver.symbol == symbol) +} + +fn find_transcript_squeeze<'a>( + program: &'a Stage2CpuProgramPlan, + symbol: &str, +) -> Option<&'a Stage2TranscriptSqueezePlan> { + program + .transcript_squeezes + .iter() + .find(|squeeze| squeeze.symbol == symbol) +} + +fn find_opening_claim<'a>( + program: &'a Stage2CpuProgramPlan, + symbol: &str, +) -> Option<&'a Stage2OpeningClaimPlan> { + program + .opening_claims + .iter() + .find(|claim| claim.symbol == symbol) +} + +#[cfg(test)] +#[expect(clippy::expect_used, reason = "tests use explicit panic messages")] +mod tests { + use super::*; + use jolt_field::Fr; + use jolt_transcript::MockTranscript; + + #[test] + fn stage2_relation_and_abi_registry_is_complete() { + let relations = [ + Stage2Relation::ProductVirtualUniskip, + Stage2Relation::RamReadWrite, + Stage2Relation::ProductVirtualRemainder, + Stage2Relation::InstructionLookupClaimReduction, + Stage2Relation::RamRafEvaluation, + Stage2Relation::RamOutputCheck, + Stage2Relation::Batched, + ]; + for relation in relations { + assert_eq!( + Stage2Relation::from_symbol(relation.symbol()), + Some(relation) + ); + } + + let abis = [ + Stage2KernelAbi::ProductVirtualUniskip, + Stage2KernelAbi::RamReadWrite, + Stage2KernelAbi::ProductVirtualRemainder, + Stage2KernelAbi::InstructionLookupClaimReduction, + Stage2KernelAbi::RamRafEvaluation, + Stage2KernelAbi::RamOutputCheck, + Stage2KernelAbi::Batched, + ]; + for abi in abis { + assert_eq!(Stage2KernelAbi::from_name(abi.name()), Some(abi)); + } + } + + #[test] + fn stage2_field_exprs_match_jolt_input_claim_formulas() { + let product_expr = Stage2FieldExprPlan { + symbol: "product_expr", + kind: "weighted_sum", + formula: "jolt_stage2_product_virtual_uniskip_input", + operand_names: &[], + operands: &[], + }; + let product = evaluate_stage2_field_expr( + &product_expr, + &[ + Fr::from_u64(0), + Fr::from_u64(11), + Fr::from_u64(13), + Fr::from_u64(17), + ], + ) + .expect("product expression evaluates"); + assert_eq!(product, Fr::from_u64(13)); + + let ram_expr = Stage2FieldExprPlan { + symbol: "ram_expr", + kind: "weighted_sum", + formula: "jolt_stage2_ram_read_write_input", + operand_names: &[], + operands: &[], + }; + let ram = evaluate_stage2_field_expr( + &ram_expr, + &[Fr::from_u64(7), Fr::from_u64(11), Fr::from_u64(13)], + ) + .expect("ram expression evaluates"); + assert_eq!(ram, Fr::from_u64(102)); + + let instruction_expr = Stage2FieldExprPlan { + symbol: "instruction_expr", + kind: "weighted_sum", + formula: "jolt_stage2_instruction_lookup_input", + operand_names: &[], + operands: &[], + }; + let instruction = evaluate_stage2_field_expr( + &instruction_expr, + &[ + Fr::from_u64(2), + Fr::from_u64(1), + Fr::from_u64(3), + Fr::from_u64(5), + Fr::from_u64(7), + Fr::from_u64(11), + ], + ) + .expect("instruction expression evaluates"); + assert_eq!(instruction, Fr::from_u64(259)); + + let add_expr = Stage2FieldExprPlan { + symbol: "add_expr", + kind: "op", + formula: "field.add", + operand_names: &[], + operands: &[], + }; + let add = evaluate_stage2_field_expr(&add_expr, &[Fr::from_u64(5), Fr::from_u64(8)]) + .expect("field add evaluates"); + assert_eq!(add, Fr::from_u64(13)); + + let lagrange_expr = Stage2FieldExprPlan { + symbol: "lagrange_expr", + kind: "op", + formula: "poly.lagrange_basis_eval:-1:3:1", + operand_names: &[], + operands: &[], + }; + let weight = evaluate_stage2_field_expr(&lagrange_expr, &[Fr::from_u64(0)]) + .expect("lagrange basis evaluates"); + assert_eq!(weight, Fr::from_u64(1)); + } + + #[test] + fn value_store_resolves_challenges_openings_and_claims() { + let program = minimal_program( + vec![Stage2TranscriptSqueezePlan { + symbol: "gamma", + label: "gamma", + kind: "challenge_scalar", + count: 1, + }], + Vec::new(), + vec![Stage2FieldExprPlan { + symbol: "ram_expr", + kind: "weighted_sum", + formula: "jolt_stage2_ram_read_write_input", + operand_names: &["gamma", "read", "write"], + operands: &["gamma", "read", "write"], + }], + vec![Stage2SumcheckClaimPlan { + symbol: "claim", + stage: "stage2", + domain: "domain", + num_rounds: 1, + degree: 3, + claim: "claim", + kernel: Some("kernel"), + relation: None, + claim_value: "ram_expr", + input_openings: &["read", "write"], + }], + Vec::new(), + Vec::new(), + ); + + let mut store = Stage2ValueStore::with_opening_inputs(&[ + Stage2OpeningInputValue { + symbol: "read", + point: vec![Fr::from_u64(0)], + eval: Fr::from_u64(11), + }, + Stage2OpeningInputValue { + symbol: "write", + point: vec![Fr::from_u64(1)], + eval: Fr::from_u64(13), + }, + ]); + store + .observe_challenge_vector(program, &program.transcript_squeezes[0], &[Fr::from_u64(7)]) + .expect("challenge vector observed"); + assert_eq!( + store + .claim_value(program, &program.claims[0]) + .expect("claim value resolves"), + Fr::from_u64(102) + ); + } + + #[test] + fn value_store_records_sumcheck_instance_points_and_evals() { + let program = minimal_program( + Vec::new(), + Vec::new(), + Vec::new(), + Vec::new(), + vec![Stage2SumcheckInstanceResultPlan { + symbol: "instance", + source: "driver", + claim: "claim", + relation: "relation", + index: 0, + point_arity: 2, + num_rounds: 2, + round_offset: 1, + point_order: "as_is", + degree: 3, + }], + vec![Stage2SumcheckEvalPlan { + symbol: "eval.symbol", + source: "driver", + name: "eval.name", + index: 0, + oracle: "Oracle", + }], + ); + let output = Stage2SumcheckOutput { + driver: "driver", + point: vec![Fr::from_u64(3), Fr::from_u64(5), Fr::from_u64(7)], + evals: vec![Stage2NamedEval { + name: "eval.name", + oracle: "Oracle", + value: Fr::from_u64(11), + }], + opening_claims: Vec::new(), + proof: SumcheckProof::default(), + }; + let mut store = Stage2ValueStore::new(); + store + .observe_sumcheck_output(program, &output) + .expect("sumcheck output observed"); + + assert_eq!( + store.point("instance").expect("instance point"), + &[Fr::from_u64(5), Fr::from_u64(7)] + ); + assert_eq!( + store.scalar("eval.symbol").expect("eval symbol"), + Fr::from_u64(11) + ); + assert_eq!( + store.scalar("eval.name").expect("eval name"), + Fr::from_u64(11) + ); + } + + #[test] + fn product_virtual_uniskip_kernel_proves_first_round_arithmetic() { + let program = product_uniskip_program(); + let opening_inputs = [ + Stage2OpeningInputValue { + symbol: "stage2.input.stage1.Product", + point: vec![Fr::from_u64(0)], + eval: Fr::from_u64(11), + }, + Stage2OpeningInputValue { + symbol: "stage2.input.stage1.ShouldBranch", + point: vec![Fr::from_u64(0)], + eval: Fr::from_u64(13), + }, + Stage2OpeningInputValue { + symbol: "stage2.input.stage1.ShouldJump", + point: vec![Fr::from_u64(0)], + eval: Fr::from_u64(17), + }, + ]; + let extended_evals = [Fr::from_u64(23), Fr::from_u64(29)]; + let inputs = Stage2ProverInputs::new(&opening_inputs) + .with_product_uniskip_extended_evals(&extended_evals); + let mut executor = Stage2ProverKernelExecutor::new(inputs); + let mut transcript = MockTranscript::::new(b"stage2"); + + let artifacts = execute_stage2_program( + program, + Stage2ExecutionMode::Prover, + &mut executor, + &mut transcript, + ) + .expect("product uniskip proves"); + + assert_eq!(artifacts.challenge_vectors.len(), 1); + assert_eq!(artifacts.sumchecks.len(), 1); + let output = &artifacts.sumchecks[0]; + let poly = &output.proof.round_polynomials[0]; + let tau = artifacts.challenge_vectors[0].values[0]; + let input_claim = evaluate_stage2_field_expr( + &program.field_exprs[0], + &[tau, Fr::from_u64(11), Fr::from_u64(13), Fr::from_u64(17)], + ) + .expect("input claim evaluates"); + + assert_eq!( + poly.coefficients().len(), + PRODUCT_VIRTUAL_UNISKIP_NUM_COEFFS + ); + assert!(product_uniskip_sum_matches(poly, input_claim)); + assert_eq!(output.evals.len(), 1); + assert_eq!( + output.evals[0].name, + "stage2.product_virtual.uniskip.eval.UnivariateSkip" + ); + assert_eq!(output.evals[0].value, poly.evaluate(output.point[0])); + } + + #[test] + fn product_virtual_uniskip_kernel_requires_extended_evals() { + let program = product_uniskip_program(); + let opening_inputs = [ + Stage2OpeningInputValue { + symbol: "stage2.input.stage1.Product", + point: Vec::new(), + eval: Fr::from_u64(11), + }, + Stage2OpeningInputValue { + symbol: "stage2.input.stage1.ShouldBranch", + point: Vec::new(), + eval: Fr::from_u64(13), + }, + Stage2OpeningInputValue { + symbol: "stage2.input.stage1.ShouldJump", + point: Vec::new(), + eval: Fr::from_u64(17), + }, + ]; + let mut executor = + Stage2ProverKernelExecutor::new(Stage2ProverInputs::new(&opening_inputs)); + let mut transcript = MockTranscript::::new(b"stage2"); + + let error = execute_stage2_program( + program, + Stage2ExecutionMode::Prover, + &mut executor, + &mut transcript, + ) + .expect_err("missing extended evals are rejected"); + + assert_eq!( + error, + Stage2KernelError::MissingKernelInput { + kernel: "jolt_stage2_product_virtual_uniskip", + input: "product_uniskip_extended_evals", + } + ); + } + + #[test] + fn product_virtual_uniskip_extended_evals_use_trace_cycle_data() { + let cycles = [ + Stage2ProductVirtualCycle { + instruction_left_input: 7, + instruction_right_input: -3, + should_branch_lookup_output: 11, + write_lookup_output_to_rd_flag: true, + jump_flag: false, + should_branch_flag: true, + not_next_noop: true, + virtual_instruction_flag: false, + }, + Stage2ProductVirtualCycle { + instruction_left_input: 13, + instruction_right_input: 5, + should_branch_lookup_output: 17, + write_lookup_output_to_rd_flag: false, + jump_flag: true, + should_branch_flag: false, + not_next_noop: false, + virtual_instruction_flag: true, + }, + ]; + let tau_low = [Fr::from_u64(19)]; + let evals = product_virtual_uniskip_extended_evals(&cycles, &tau_low) + .expect("extended evals compute"); + + let eq = EqPolynomial::::evals(&tau_low, None); + let expected = core::array::from_fn(|target| { + eq.iter() + .zip(&cycles) + .map(|(&weight, cycle)| { + let product = product_virtual_extended_fused_product(cycle, target); + let mut accumulator = FrSignedScalarAccumulator::zero(); + accumulator.fmadd_s256(weight, product); + accumulator.reduce() + }) + .sum::() + }); + assert_eq!(evals, expected); + } + + #[test] + fn product_virtual_witness_builder_uses_product_opening_point() { + let cycles = [ + Stage2ProductVirtualCycle { + instruction_left_input: 7, + instruction_right_input: -3, + should_branch_lookup_output: 11, + write_lookup_output_to_rd_flag: true, + jump_flag: false, + should_branch_flag: true, + not_next_noop: true, + virtual_instruction_flag: false, + }, + Stage2ProductVirtualCycle { + instruction_left_input: 13, + instruction_right_input: 5, + should_branch_lookup_output: 17, + write_lookup_output_to_rd_flag: false, + jump_flag: true, + should_branch_flag: false, + not_next_noop: false, + virtual_instruction_flag: true, + }, + ]; + let opening_inputs = [Stage2OpeningInputValue { + symbol: "stage2.input.stage1.Product", + point: vec![Fr::from_u64(19)], + eval: Fr::from_u64(11), + }]; + let expected = product_virtual_uniskip_extended_evals(&cycles, &[Fr::from_u64(19)]) + .expect("extended evals compute"); + + let inputs = Stage2ProverInputs::new(&opening_inputs) + .with_product_virtual_witness(&cycles) + .expect("builder derives product virtual witness"); + + assert_eq!(inputs.product_virtual_cycles, Some(cycles.as_slice())); + assert_eq!( + inputs + .product_uniskip_extended_evals + .as_deref() + .expect("extended evals"), + expected.as_slice() + ); + } + + fn minimal_program( + transcript_squeezes: Vec, + field_constants: Vec, + field_exprs: Vec, + claims: Vec, + instance_results: Vec, + evals: Vec, + ) -> &'static Stage2CpuProgramPlan { + Box::leak(Box::new(Stage2CpuProgramPlan { + params: Stage2Params { + field: "bn254_fr", + pcs: "dory", + transcript: "blake2b_transcript", + }, + steps: &[], + transcript_squeezes: leak_slice(transcript_squeezes), + opening_inputs: &[], + field_constants: leak_slice(field_constants), + field_exprs: leak_slice(field_exprs), + kernels: &[], + claims: leak_slice(claims), + batches: &[], + drivers: &[], + instance_results: leak_slice(instance_results), + evals: leak_slice(evals), + point_slices: &[], + point_concats: &[], + opening_claims: &[], + opening_batches: &[], + })) + } + + fn leak_slice(values: Vec) -> &'static [T] { + Box::leak(values.into_boxed_slice()) + } + + fn product_uniskip_program() -> &'static Stage2CpuProgramPlan { + Box::leak(Box::new(Stage2CpuProgramPlan { + params: Stage2Params { + field: "bn254_fr", + pcs: "dory", + transcript: "blake2b_transcript", + }, + steps: &[], + transcript_squeezes: leak_slice(vec![Stage2TranscriptSqueezePlan { + symbol: "stage2.product_virtual.tau_high", + label: "product_virtual_tau_high", + kind: "challenge_scalar", + count: 1, + }]), + opening_inputs: &[], + field_constants: &[], + field_exprs: leak_slice(vec![Stage2FieldExprPlan { + symbol: "stage2.product_virtual.uniskip.claim_expr", + kind: "weighted_sum", + formula: "jolt_stage2_product_virtual_uniskip_input", + operand_names: &[ + "stage2.product_virtual.tau_high", + "stage2.input.stage1.Product", + "stage2.input.stage1.ShouldBranch", + "stage2.input.stage1.ShouldJump", + ], + operands: &[ + "stage2.product_virtual.tau_high", + "stage2.input.stage1.Product", + "stage2.input.stage1.ShouldBranch", + "stage2.input.stage1.ShouldJump", + ], + }]), + kernels: leak_slice(vec![Stage2KernelPlan { + symbol: "jolt.cpu.stage2.product_virtual.uniskip", + relation: "jolt.stage2.product_virtual.uniskip", + kind: "sumcheck", + backend: "cpu", + abi: "jolt_stage2_product_virtual_uniskip", + }]), + claims: leak_slice(vec![Stage2SumcheckClaimPlan { + symbol: "stage2.product_virtual.uniskip.input", + stage: "stage2", + domain: "jolt.stage2_uniskip_domain", + num_rounds: 1, + degree: 6, + claim: "stage2.product_virtual.weighted_stage1_outputs", + kernel: Some("jolt.cpu.stage2.product_virtual.uniskip"), + relation: None, + claim_value: "stage2.product_virtual.uniskip.claim_expr", + input_openings: &[ + "stage2.input.stage1.Product", + "stage2.input.stage1.ShouldBranch", + "stage2.input.stage1.ShouldJump", + ], + }]), + batches: leak_slice(vec![Stage2SumcheckBatchPlan { + symbol: "stage2.product_virtual.uniskip.batch", + stage: "stage2", + proof_slot: "stage2.product_virtual.uni_skip_first_round", + policy: "single_instance", + count: 1, + ordered_claims: &["stage2.product_virtual.uniskip.input"], + claim_operands: &["stage2.product_virtual.uniskip.input"], + claim_label: "uniskip_claim", + round_label: "uniskip_poly", + round_schedule: &[1], + }]), + drivers: leak_slice(vec![Stage2SumcheckDriverPlan { + symbol: "stage2.product_virtual.uniskip.sumcheck", + stage: "stage2", + proof_slot: "stage2.product_virtual.uni_skip_first_round", + kernel: Some("jolt.cpu.stage2.product_virtual.uniskip"), + relation: None, + batch: "stage2.product_virtual.uniskip.batch", + policy: "univariate_skip", + round_schedule: &[1], + claim_label: "uniskip_claim", + round_label: "uniskip_poly", + num_rounds: 1, + degree: 6, + }]), + instance_results: &[], + evals: leak_slice(vec![Stage2SumcheckEvalPlan { + symbol: "stage2.product_virtual.uniskip.eval.UnivariateSkip", + source: "stage2.product_virtual.uniskip.sumcheck", + name: "stage2.product_virtual.uniskip.eval.UnivariateSkip", + index: 0, + oracle: "UnivariateSkip", + }]), + point_slices: &[], + point_concats: &[], + opening_claims: &[], + opening_batches: &[], + })) + } +} diff --git a/crates/jolt-kernels/src/stage3.rs b/crates/jolt-kernels/src/stage3.rs new file mode 100644 index 0000000000..c0d90870f5 --- /dev/null +++ b/crates/jolt-kernels/src/stage3.rs @@ -0,0 +1,4223 @@ +//! Stage 3 coarse-kernel ABI used by Bolt-generated Jolt prover code. + +#![expect( + clippy::too_many_arguments, + reason = "kernel constructors mirror generated staged protocol inputs" +)] + +use std::error::Error; +use std::fmt::{self, Display, Formatter}; + +use crate::dense::DENSE_BIND_PAR_THRESHOLD; +use crate::split_eq::SplitEqState; +use jolt_field::{Field, FieldAccumulator}; +use jolt_poly::{EqPlusOnePolynomial, EqPlusOnePrefixSuffix, EqPolynomial, UnivariatePoly}; +use jolt_sumcheck::SumcheckProof; +use jolt_transcript::{Label, LabelWithCount, Transcript}; +use rayon::prelude::*; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Stage3ExecutionMode { + Prover, + Verifier, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Stage3Relation { + SpartanShift, + InstructionInput, + RegistersClaimReduction, + Batched, +} + +impl Stage3Relation { + pub fn from_symbol(symbol: &str) -> Option { + match symbol { + "jolt.stage3.spartan_shift" => Some(Self::SpartanShift), + "jolt.stage3.instruction_input" => Some(Self::InstructionInput), + "jolt.stage3.registers_claim_reduction" => Some(Self::RegistersClaimReduction), + "jolt.stage3.batched" => Some(Self::Batched), + _ => None, + } + } + + pub fn symbol(self) -> &'static str { + match self { + Self::SpartanShift => "jolt.stage3.spartan_shift", + Self::InstructionInput => "jolt.stage3.instruction_input", + Self::RegistersClaimReduction => "jolt.stage3.registers_claim_reduction", + Self::Batched => "jolt.stage3.batched", + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Stage3KernelAbi { + SpartanShift, + InstructionInput, + RegistersClaimReduction, + Batched, +} + +impl Stage3KernelAbi { + pub fn from_name(name: &str) -> Option { + match name { + "jolt_stage3_spartan_shift" => Some(Self::SpartanShift), + "jolt_stage3_instruction_input" => Some(Self::InstructionInput), + "jolt_stage3_registers_claim_reduction" => Some(Self::RegistersClaimReduction), + "jolt_stage3_batched" => Some(Self::Batched), + _ => None, + } + } + + pub fn name(self) -> &'static str { + match self { + Self::SpartanShift => "jolt_stage3_spartan_shift", + Self::InstructionInput => "jolt_stage3_instruction_input", + Self::RegistersClaimReduction => "jolt_stage3_registers_claim_reduction", + Self::Batched => "jolt_stage3_batched", + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage3Params { + pub field: &'static str, + pub pcs: &'static str, + pub transcript: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage3KernelPlan { + pub symbol: &'static str, + pub relation: &'static str, + pub kind: &'static str, + pub backend: &'static str, + pub abi: &'static str, +} + +impl Stage3KernelPlan { + pub fn relation_kind(&self) -> Result { + Stage3Relation::from_symbol(self.relation).ok_or(Stage3KernelError::UnknownRelation { + relation: self.relation, + }) + } + + pub fn abi_kind(&self) -> Result { + Stage3KernelAbi::from_name(self.abi) + .ok_or(Stage3KernelError::UnknownKernelAbi { abi: self.abi }) + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage3TranscriptSqueezePlan { + pub symbol: &'static str, + pub label: &'static str, + pub kind: &'static str, + pub count: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage3ProgramStepPlan { + pub kind: &'static str, + pub symbol: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage3OpeningInputPlan { + pub symbol: &'static str, + pub source_stage: &'static str, + pub source_claim: &'static str, + pub oracle: &'static str, + pub domain: &'static str, + pub point_arity: usize, + pub claim_kind: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage3FieldConstantPlan { + pub symbol: &'static str, + pub field: &'static str, + pub value: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage3FieldExprPlan { + pub symbol: &'static str, + pub kind: &'static str, + pub formula: &'static str, + pub operand_names: &'static [&'static str], + pub operands: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage3SumcheckClaimPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub domain: &'static str, + pub num_rounds: usize, + pub degree: usize, + pub claim: &'static str, + pub kernel: Option<&'static str>, + pub relation: Option<&'static str>, + pub claim_value: &'static str, + pub input_openings: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage3SumcheckBatchPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub proof_slot: &'static str, + pub policy: &'static str, + pub count: usize, + pub ordered_claims: &'static [&'static str], + pub claim_operands: &'static [&'static str], + pub claim_label: &'static str, + pub round_label: &'static str, + pub round_schedule: &'static [usize], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage3SumcheckDriverPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub proof_slot: &'static str, + pub kernel: Option<&'static str>, + pub relation: Option<&'static str>, + pub batch: &'static str, + pub policy: &'static str, + pub round_schedule: &'static [usize], + pub claim_label: &'static str, + pub round_label: &'static str, + pub num_rounds: usize, + pub degree: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage3SumcheckInstanceResultPlan { + pub symbol: &'static str, + pub source: &'static str, + pub claim: &'static str, + pub relation: &'static str, + pub index: usize, + pub point_arity: usize, + pub num_rounds: usize, + pub round_offset: usize, + pub point_order: &'static str, + pub degree: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage3SumcheckEvalPlan { + pub symbol: &'static str, + pub source: &'static str, + pub name: &'static str, + pub index: usize, + pub oracle: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage3PointSlicePlan { + pub symbol: &'static str, + pub source: &'static str, + pub offset: usize, + pub length: usize, + pub input: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage3PointConcatPlan { + pub symbol: &'static str, + pub layout: &'static str, + pub arity: usize, + pub inputs: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage3OpeningClaimPlan { + pub symbol: &'static str, + pub oracle: &'static str, + pub domain: &'static str, + pub point_arity: usize, + pub claim_kind: &'static str, + pub point_source: &'static str, + pub eval_source: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage3OpeningClaimEqualityPlan { + pub symbol: &'static str, + pub mode: &'static str, + pub lhs: &'static str, + pub rhs: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage3OpeningBatchPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub proof_slot: &'static str, + pub policy: &'static str, + pub count: usize, + pub ordered_claims: &'static [&'static str], + pub claim_operands: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage3CpuProgramPlan { + pub params: Stage3Params, + pub steps: &'static [Stage3ProgramStepPlan], + pub transcript_squeezes: &'static [Stage3TranscriptSqueezePlan], + pub opening_inputs: &'static [Stage3OpeningInputPlan], + pub field_constants: &'static [Stage3FieldConstantPlan], + pub field_exprs: &'static [Stage3FieldExprPlan], + pub kernels: &'static [Stage3KernelPlan], + pub claims: &'static [Stage3SumcheckClaimPlan], + pub batches: &'static [Stage3SumcheckBatchPlan], + pub drivers: &'static [Stage3SumcheckDriverPlan], + pub instance_results: &'static [Stage3SumcheckInstanceResultPlan], + pub evals: &'static [Stage3SumcheckEvalPlan], + pub point_slices: &'static [Stage3PointSlicePlan], + pub point_concats: &'static [Stage3PointConcatPlan], + pub opening_claims: &'static [Stage3OpeningClaimPlan], + pub opening_equalities: &'static [Stage3OpeningClaimEqualityPlan], + pub opening_batches: &'static [Stage3OpeningBatchPlan], +} + +impl Stage3CpuProgramPlan { + pub fn kernel(&self, symbol: &str) -> Option<&Stage3KernelPlan> { + find_kernel(self, symbol) + } + + pub fn batch(&self, symbol: &str) -> Option<&Stage3SumcheckBatchPlan> { + find_batch(self, symbol) + } + + pub fn claim(&self, symbol: &str) -> Option<&Stage3SumcheckClaimPlan> { + self.claims.iter().find(|claim| claim.symbol == symbol) + } + + pub fn instance_results_for_driver( + &self, + driver: &'static str, + ) -> impl Iterator { + self.instance_results + .iter() + .filter(move |instance| instance.source == driver) + } + + pub fn evals_for_driver( + &self, + driver: &'static str, + ) -> impl Iterator { + self.evals.iter().filter(move |eval| eval.source == driver) + } +} + +#[derive(Clone, Debug)] +pub struct Stage3NamedEval { + pub name: &'static str, + pub oracle: &'static str, + pub value: F, +} + +#[derive(Clone, Debug)] +pub struct Stage3SumcheckOutput { + pub driver: &'static str, + pub point: Vec, + pub evals: Vec>, + pub opening_claims: Vec>, + pub proof: SumcheckProof, +} + +#[derive(Clone, Debug)] +pub struct Stage3ChallengeVector { + pub symbol: &'static str, + pub values: Vec, +} + +#[derive(Clone, Debug)] +pub struct Stage3OpeningClaimValue { + pub symbol: &'static str, + pub oracle: &'static str, + pub domain: &'static str, + pub claim_kind: &'static str, + pub point: Vec, + pub eval: F, +} + +#[derive(Clone, Debug)] +pub struct Stage3ExecutionArtifacts { + pub challenge_vectors: Vec>, + pub sumchecks: Vec>, + pub opening_claims: Vec>, + pub opening_batches: Vec<&'static Stage3OpeningBatchPlan>, +} + +impl Default for Stage3ExecutionArtifacts { + fn default() -> Self { + Self { + challenge_vectors: Vec::new(), + sumchecks: Vec::new(), + opening_claims: Vec::new(), + opening_batches: Vec::new(), + } + } +} + +#[derive(Clone, Debug, Default)] +pub struct Stage3Proof { + pub sumchecks: Vec>, +} + +impl From> for Stage3Proof { + fn from(artifacts: Stage3ExecutionArtifacts) -> Self { + Self { + sumchecks: artifacts.sumchecks, + } + } +} + +#[derive(Clone, Debug)] +pub struct Stage3ScalarValue { + pub symbol: &'static str, + pub value: F, +} + +#[derive(Clone, Debug)] +pub struct Stage3PointValue { + pub symbol: &'static str, + pub point: Vec, +} + +#[derive(Clone, Debug)] +pub struct Stage3OpeningInputValue { + pub symbol: &'static str, + pub point: Vec, + pub eval: F, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage3Cycle { + pub unexpanded_pc: u64, + pub pc: u64, + pub is_virtual: bool, + pub is_first_in_sequence: bool, + pub is_noop: bool, + pub left_operand_is_rs1: bool, + pub rs1_value: u64, + pub left_operand_is_pc: bool, + pub right_operand_is_rs2: bool, + pub rs2_value: u64, + pub right_operand_is_imm: bool, + pub imm: i128, + pub rd_write_value: u64, +} + +impl Stage3Cycle { + pub fn padding() -> Self { + Self { + unexpanded_pc: 0, + pc: 0, + is_virtual: false, + is_first_in_sequence: false, + is_noop: true, + left_operand_is_rs1: false, + rs1_value: 0, + left_operand_is_pc: false, + right_operand_is_rs2: false, + rs2_value: 0, + right_operand_is_imm: false, + imm: 0, + rd_write_value: 0, + } + } +} + +#[derive(Clone, Debug, Default)] +pub struct Stage3ValueStore { + scalars: Vec>, + points: Vec>, +} + +impl Stage3ValueStore { + pub fn new() -> Self { + Self::default() + } + + pub fn with_opening_inputs(inputs: &[Stage3OpeningInputValue]) -> Self { + let mut store = Self::new(); + store.insert_opening_inputs(inputs); + store + } + + pub fn insert_opening_inputs(&mut self, inputs: &[Stage3OpeningInputValue]) { + for input in inputs { + self.insert_scalar(input.symbol, input.eval); + self.insert_point(input.symbol, input.point.clone()); + } + } + + pub fn insert_scalar(&mut self, symbol: &'static str, value: F) { + if let Some(existing) = self + .scalars + .iter_mut() + .find(|existing| existing.symbol == symbol) + { + existing.value = value; + } else { + self.scalars.push(Stage3ScalarValue { symbol, value }); + } + } + + pub fn insert_point(&mut self, symbol: &'static str, point: Vec) { + if let Some(existing) = self + .points + .iter_mut() + .find(|existing| existing.symbol == symbol) + { + existing.point = point; + } else { + self.points.push(Stage3PointValue { symbol, point }); + } + } + + pub fn try_scalar(&self, symbol: &str) -> Option { + self.scalars + .iter() + .find(|value| value.symbol == symbol) + .map(|value| value.value) + } + + pub fn scalar(&self, symbol: &'static str) -> Result { + self.try_scalar(symbol) + .ok_or(Stage3KernelError::MissingValue { symbol }) + } + + pub fn try_point(&self, symbol: &str) -> Option<&[F]> { + self.points + .iter() + .find(|value| value.symbol == symbol) + .map(|value| value.point.as_slice()) + } + + pub fn point(&self, symbol: &'static str) -> Result<&[F], Stage3KernelError> { + self.try_point(symbol) + .ok_or(Stage3KernelError::MissingValue { symbol }) + } + + pub fn seed_constants( + &mut self, + program: &'static Stage3CpuProgramPlan, + ) -> Result<(), Stage3KernelError> { + for constant in program.field_constants { + self.insert_scalar(constant.symbol, F::from_u64(constant.value as u64)); + } + Ok(()) + } + + pub fn observe_challenge_vector( + &mut self, + plan: &'static Stage3TranscriptSqueezePlan, + values: &[F], + ) -> Result<(), Stage3KernelError> { + if matches!(plan.kind, "challenge_scalar" | "scalar") { + require_operand_count(plan.symbol, 1, values.len())?; + self.insert_scalar(plan.symbol, values[0]); + } + self.insert_point(plan.symbol, values.to_vec()); + Ok(()) + } + + pub fn observe_sumcheck_output( + &mut self, + program: &'static Stage3CpuProgramPlan, + output: &Stage3SumcheckOutput, + ) -> Result<(), Stage3KernelError> { + self.observe_sumcheck_values(program, output.driver, &output.point, &output.evals) + } + + pub fn observe_sumcheck_values( + &mut self, + program: &'static Stage3CpuProgramPlan, + driver: &'static str, + point: &[F], + evals: &[Stage3NamedEval], + ) -> Result<(), Stage3KernelError> { + self.insert_point(driver, point.to_vec()); + for instance in program.instance_results_for_driver(driver) { + let end = instance.round_offset + instance.point_arity; + let mut point = point + .get(instance.round_offset..end) + .ok_or(Stage3KernelError::InvalidInputLength { + input: instance.symbol, + expected: end, + actual: point.len(), + })? + .to_vec(); + match instance.point_order { + "as_is" => {} + "reverse" => point.reverse(), + _ => { + return Err(Stage3KernelError::InvalidProof { + driver, + reason: "unsupported point order", + }); + } + } + self.insert_point(instance.symbol, point); + } + for eval in program.evals_for_driver(driver) { + let value = evals + .iter() + .find(|value| value.name == eval.name) + .or_else(|| evals.get(eval.index)) + .ok_or(Stage3KernelError::MissingValue { + symbol: eval.symbol, + })? + .value; + self.insert_scalar(eval.symbol, value); + self.insert_scalar(eval.name, value); + } + Ok(()) + } + + pub fn evaluate_available_points( + &mut self, + program: &'static Stage3CpuProgramPlan, + ) -> Result { + let mut inserted = 0usize; + loop { + let mut progress = 0usize; + for slice in program.point_slices { + if self.try_point(slice.symbol).is_some() { + continue; + } + let Some(input) = self.try_point(slice.input) else { + continue; + }; + let end = slice.offset + slice.length; + let point = input + .get(slice.offset..end) + .ok_or(Stage3KernelError::InvalidInputLength { + input: slice.symbol, + expected: end, + actual: input.len(), + })? + .to_vec(); + self.insert_point(slice.symbol, point); + progress += 1; + } + for concat in program.point_concats { + if self.try_point(concat.symbol).is_some() { + continue; + } + let Some(point) = self.try_concat_point(concat) else { + continue; + }; + verify_count(concat.symbol, concat.arity, point.len())?; + self.insert_point(concat.symbol, point); + progress += 1; + } + inserted += progress; + if progress == 0 { + return Ok(inserted); + } + } + } + + pub fn evaluate_available_field_exprs( + &mut self, + program: &'static Stage3CpuProgramPlan, + ) -> Result { + let mut inserted = 0usize; + loop { + let mut progress = 0usize; + for expr in program.field_exprs { + if self.try_scalar(expr.symbol).is_some() { + continue; + } + let Some(operands) = self.try_expr_operands(expr) else { + continue; + }; + self.insert_scalar(expr.symbol, evaluate_stage3_field_expr(expr, &operands)?); + progress += 1; + } + inserted += progress; + if progress == 0 { + return Ok(inserted); + } + } + } + + pub fn verify_opening_equalities( + &self, + program: &'static Stage3CpuProgramPlan, + ) -> Result<(), Stage3KernelError> { + for equality in program.opening_equalities { + match equality.mode { + "point_and_eval" => { + if self.point(equality.lhs)? != self.point(equality.rhs)? + || self.scalar(equality.lhs)? != self.scalar(equality.rhs)? + { + return Err(Stage3KernelError::InvalidProof { + driver: equality.symbol, + reason: "opening claim equality failed", + }); + } + } + _ => { + return Err(Stage3KernelError::InvalidProof { + driver: equality.symbol, + reason: "unsupported opening equality mode", + }); + } + } + } + Ok(()) + } + + pub fn claim_value( + &mut self, + program: &'static Stage3CpuProgramPlan, + claim: &Stage3SumcheckClaimPlan, + ) -> Result { + let _ = self.evaluate_available_field_exprs(program)?; + self.scalar(claim.claim_value) + } + + pub fn batch_claim_values( + &mut self, + program: &'static Stage3CpuProgramPlan, + batch: &Stage3SumcheckBatchPlan, + ) -> Result, Stage3KernelError> { + batch + .claim_operands + .iter() + .map(|symbol| { + let claim = program + .claim(symbol) + .ok_or(Stage3KernelError::MissingClaim { + batch: batch.symbol, + claim: symbol, + })?; + self.claim_value(program, claim) + }) + .collect() + } + + fn try_expr_operands(&self, expr: &Stage3FieldExprPlan) -> Option> { + expr.operands + .iter() + .map(|operand| self.try_scalar(operand)) + .collect() + } + + fn try_concat_point(&self, concat: &Stage3PointConcatPlan) -> Option> { + let mut point = Vec::with_capacity(concat.arity); + for input in concat.inputs { + point.extend_from_slice(self.try_point(input)?); + } + Some(point) + } +} + +pub fn evaluate_stage3_field_expr( + expr: &Stage3FieldExprPlan, + operands: &[F], +) -> Result { + match expr.formula { + "opening_eval" => single_operand(expr.symbol, operands), + "field.add" => { + require_operand_count(expr.symbol, 2, operands.len())?; + Ok(operands[0] + operands[1]) + } + "field.sub" => { + require_operand_count(expr.symbol, 2, operands.len())?; + Ok(operands[0] - operands[1]) + } + "field.mul" => { + require_operand_count(expr.symbol, 2, operands.len())?; + Ok(operands[0] * operands[1]) + } + "field.neg" => { + require_operand_count(expr.symbol, 1, operands.len())?; + Ok(-operands[0]) + } + _ => { + if let Some(exponent) = expr.formula.strip_prefix("field.pow:") { + require_operand_count(expr.symbol, 1, operands.len())?; + let exponent = exponent.parse::().map_err(|_| { + Stage3KernelError::UnsupportedFieldExpr { + symbol: expr.symbol, + formula: expr.formula, + } + })?; + return Ok(pow_field(operands[0], exponent)); + } + Err(Stage3KernelError::UnsupportedFieldExpr { + symbol: expr.symbol, + formula: expr.formula, + }) + } + } +} + +fn pow_field(base: F, mut exponent: usize) -> F { + let mut result = F::one(); + let mut power = base; + while exponent != 0 { + if exponent & 1 == 1 { + result *= power; + } + power = power.square(); + exponent >>= 1; + } + result +} + +fn single_operand(symbol: &'static str, operands: &[F]) -> Result { + require_operand_count(symbol, 1, operands.len())?; + Ok(operands[0]) +} + +fn require_operand_count( + input: &'static str, + expected: usize, + actual: usize, +) -> Result<(), Stage3KernelError> { + if expected == actual { + Ok(()) + } else { + Err(Stage3KernelError::InvalidInputLength { + input, + expected, + actual, + }) + } +} + +#[derive(Clone, Copy, Debug)] +pub struct Stage3KernelContext<'a> { + pub mode: Stage3ExecutionMode, + pub program: &'static Stage3CpuProgramPlan, + pub kernel: &'a Stage3KernelPlan, + pub batch: &'a Stage3SumcheckBatchPlan, + pub driver: &'a Stage3SumcheckDriverPlan, +} + +impl Stage3KernelContext<'_> { + pub fn relation_kind(&self) -> Result { + self.kernel.relation_kind() + } + + pub fn abi_kind(&self) -> Result { + self.kernel.abi_kind() + } + + pub fn batch_claims(&self) -> Result, Stage3KernelError> { + self.batch + .claim_operands + .iter() + .map(|symbol| { + self.program + .claim(symbol) + .ok_or(Stage3KernelError::MissingClaim { + batch: self.batch.symbol, + claim: symbol, + }) + }) + .collect() + } +} + +pub trait Stage3KernelExecutor { + fn observe_challenge_vector( + &mut self, + _plan: &'static Stage3TranscriptSqueezePlan, + _values: &[F], + ) -> Result<(), Stage3KernelError> { + Ok(()) + } + + fn observe_sumcheck_output( + &mut self, + _output: &Stage3SumcheckOutput, + ) -> Result<(), Stage3KernelError> { + Ok(()) + } + + fn prove_sumcheck( + &mut self, + context: Stage3KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage3KernelError> + where + T: Transcript; + + fn verify_sumcheck( + &mut self, + context: Stage3KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage3KernelError> + where + T: Transcript; +} + +#[derive(Clone, Debug, Default)] +pub struct UnsupportedStage3KernelExecutor; + +impl Stage3KernelExecutor for UnsupportedStage3KernelExecutor { + fn prove_sumcheck( + &mut self, + context: Stage3KernelContext<'_>, + _transcript: &mut T, + ) -> Result, Stage3KernelError> + where + T: Transcript, + { + Err(Stage3KernelError::KernelNotImplemented { + abi: context.kernel.abi, + }) + } + + fn verify_sumcheck( + &mut self, + context: Stage3KernelContext<'_>, + _transcript: &mut T, + ) -> Result, Stage3KernelError> + where + T: Transcript, + { + Err(Stage3KernelError::KernelNotImplemented { + abi: context.kernel.abi, + }) + } +} + +#[derive(Clone, Copy)] +pub struct Stage3ProverInputs<'a, F: Field> { + pub opening_inputs: &'a [Stage3OpeningInputValue], + pub cycles: Option<&'a [Stage3Cycle]>, +} + +impl<'a, F: Field> Stage3ProverInputs<'a, F> { + pub fn new(opening_inputs: &'a [Stage3OpeningInputValue]) -> Self { + Self { + opening_inputs, + cycles: None, + } + } + + pub fn empty() -> Self { + Self { + opening_inputs: &[], + cycles: None, + } + } + + pub fn with_cycles(mut self, cycles: &'a [Stage3Cycle]) -> Self { + self.cycles = Some(cycles); + self + } +} + +#[derive(Clone)] +pub struct Stage3ProverKernelExecutor<'a, F: Field> { + pub inputs: Stage3ProverInputs<'a, F>, + challenge_vectors: Vec>, + completed_sumchecks: Vec>, +} + +impl<'a, F: Field> Stage3ProverKernelExecutor<'a, F> { + pub fn new(inputs: Stage3ProverInputs<'a, F>) -> Self { + Self { + inputs, + challenge_vectors: Vec::new(), + completed_sumchecks: Vec::new(), + } + } + + fn value_store( + &self, + program: &'static Stage3CpuProgramPlan, + ) -> Result, Stage3KernelError> { + value_store_from_observations( + program, + self.inputs.opening_inputs, + &self.challenge_vectors, + &self.completed_sumchecks, + ) + } +} + +impl Stage3KernelExecutor for Stage3ProverKernelExecutor<'_, F> { + fn observe_challenge_vector( + &mut self, + plan: &'static Stage3TranscriptSqueezePlan, + values: &[F], + ) -> Result<(), Stage3KernelError> { + self.challenge_vectors.push(Stage3ChallengeVector { + symbol: plan.symbol, + values: values.to_vec(), + }); + Ok(()) + } + + fn observe_sumcheck_output( + &mut self, + output: &Stage3SumcheckOutput, + ) -> Result<(), Stage3KernelError> { + self.completed_sumchecks.push(output.clone()); + Ok(()) + } + + fn prove_sumcheck( + &mut self, + context: Stage3KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage3KernelError> + where + T: Transcript, + { + prove_stage3_kernel( + context, + &self.inputs, + self.value_store(context.program)?, + transcript, + ) + } + + fn verify_sumcheck( + &mut self, + context: Stage3KernelContext<'_>, + _transcript: &mut T, + ) -> Result, Stage3KernelError> + where + T: Transcript, + { + Err(Stage3KernelError::WrongExecutorMode { + driver: context.driver.symbol, + expected: Stage3ExecutionMode::Prover, + actual: Stage3ExecutionMode::Verifier, + }) + } +} + +#[derive(Clone)] +pub struct Stage3VerifierKernelExecutor<'a, F: Field> { + pub proof: &'a Stage3Proof, + pub opening_inputs: &'a [Stage3OpeningInputValue], + pub cursor: usize, + challenge_vectors: Vec>, + completed_sumchecks: Vec>, +} + +impl<'a, F: Field> Stage3VerifierKernelExecutor<'a, F> { + pub fn new( + proof: &'a Stage3Proof, + opening_inputs: &'a [Stage3OpeningInputValue], + ) -> Self { + Self { + proof, + opening_inputs, + cursor: 0, + challenge_vectors: Vec::new(), + completed_sumchecks: Vec::new(), + } + } + + fn value_store( + &self, + program: &'static Stage3CpuProgramPlan, + ) -> Result, Stage3KernelError> { + value_store_from_observations( + program, + self.opening_inputs, + &self.challenge_vectors, + &self.completed_sumchecks, + ) + } +} + +impl Stage3KernelExecutor for Stage3VerifierKernelExecutor<'_, F> { + fn observe_challenge_vector( + &mut self, + plan: &'static Stage3TranscriptSqueezePlan, + values: &[F], + ) -> Result<(), Stage3KernelError> { + self.challenge_vectors.push(Stage3ChallengeVector { + symbol: plan.symbol, + values: values.to_vec(), + }); + Ok(()) + } + + fn observe_sumcheck_output( + &mut self, + output: &Stage3SumcheckOutput, + ) -> Result<(), Stage3KernelError> { + self.completed_sumchecks.push(output.clone()); + Ok(()) + } + + fn prove_sumcheck( + &mut self, + context: Stage3KernelContext<'_>, + _transcript: &mut T, + ) -> Result, Stage3KernelError> + where + T: Transcript, + { + Err(Stage3KernelError::WrongExecutorMode { + driver: context.driver.symbol, + expected: Stage3ExecutionMode::Verifier, + actual: Stage3ExecutionMode::Prover, + }) + } + + fn verify_sumcheck( + &mut self, + context: Stage3KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage3KernelError> + where + T: Transcript, + { + let proof = + self.proof + .sumchecks + .get(self.cursor) + .ok_or(Stage3KernelError::MissingProof { + driver: context.driver.symbol, + })?; + self.cursor += 1; + verify_stage3_kernel( + context, + self.value_store(context.program)?, + proof, + transcript, + ) + } +} + +fn value_store_from_observations( + program: &'static Stage3CpuProgramPlan, + opening_inputs: &[Stage3OpeningInputValue], + challenge_vectors: &[Stage3ChallengeVector], + completed_sumchecks: &[Stage3SumcheckOutput], +) -> Result, Stage3KernelError> { + let mut store = Stage3ValueStore::with_opening_inputs(opening_inputs); + store.seed_constants(program)?; + for challenge in challenge_vectors { + let plan = program + .transcript_squeezes + .iter() + .find(|plan| plan.symbol == challenge.symbol) + .ok_or(Stage3KernelError::MissingValue { + symbol: challenge.symbol, + })?; + store.observe_challenge_vector(plan, &challenge.values)?; + } + for output in completed_sumchecks { + store.observe_sumcheck_output(program, output)?; + } + let _ = store.evaluate_available_points(program)?; + let _ = store.evaluate_available_field_exprs(program)?; + store.verify_opening_equalities(program)?; + Ok(store) +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum Stage3KernelError { + MissingKernel { + driver: &'static str, + kernel: &'static str, + }, + MissingBatch { + driver: &'static str, + batch: &'static str, + }, + MissingClaim { + batch: &'static str, + claim: &'static str, + }, + MissingValue { + symbol: &'static str, + }, + PlanCountMismatch { + artifact: &'static str, + expected: usize, + actual: usize, + }, + InvalidInputLength { + input: &'static str, + expected: usize, + actual: usize, + }, + UnsupportedFieldExpr { + symbol: &'static str, + formula: &'static str, + }, + UnknownRelation { + relation: &'static str, + }, + UnknownKernelAbi { + abi: &'static str, + }, + KernelNotImplemented { + abi: &'static str, + }, + WrongExecutorMode { + driver: &'static str, + expected: Stage3ExecutionMode, + actual: Stage3ExecutionMode, + }, + MissingProof { + driver: &'static str, + }, + MissingKernelInput { + kernel: &'static str, + input: &'static str, + }, + InvalidProof { + driver: &'static str, + reason: &'static str, + }, +} + +impl Display for Stage3KernelError { + fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result { + match self { + Self::MissingKernel { driver, kernel } => { + write!( + formatter, + "stage3 driver @{driver} references missing kernel @{kernel}" + ) + } + Self::MissingBatch { driver, batch } => { + write!( + formatter, + "stage3 driver @{driver} references missing batch @{batch}" + ) + } + Self::MissingClaim { batch, claim } => { + write!( + formatter, + "stage3 batch @{batch} references missing claim @{claim}" + ) + } + Self::MissingValue { symbol } => { + write!(formatter, "stage3 value @{symbol} is not available") + } + Self::PlanCountMismatch { + artifact, + expected, + actual, + } => write!( + formatter, + "stage3 plan @{artifact} count mismatch: expected {expected}, got {actual}" + ), + Self::InvalidInputLength { + input, + expected, + actual, + } => write!( + formatter, + "stage3 input `{input}` length mismatch: expected {expected}, got {actual}" + ), + Self::UnsupportedFieldExpr { symbol, formula } => write!( + formatter, + "stage3 field expr @{symbol} uses unsupported formula `{formula}`" + ), + Self::UnknownRelation { relation } => { + write!(formatter, "stage3 relation @{relation} is not registered") + } + Self::UnknownKernelAbi { abi } => { + write!(formatter, "stage3 kernel ABI `{abi}` is not registered") + } + Self::KernelNotImplemented { abi } => { + write!(formatter, "stage3 kernel ABI `{abi}` is not implemented") + } + Self::WrongExecutorMode { + driver, + expected, + actual, + } => write!( + formatter, + "stage3 driver @{driver} ran with {actual:?} executor path, expected {expected:?}" + ), + Self::MissingProof { driver } => { + write!( + formatter, + "stage3 verifier missing proof for driver @{driver}" + ) + } + Self::MissingKernelInput { kernel, input } => { + write!( + formatter, + "stage3 kernel `{kernel}` missing input `{input}`" + ) + } + Self::InvalidProof { driver, reason } => { + write!( + formatter, + "stage3 proof for driver @{driver} is invalid: {reason}" + ) + } + } + } +} + +impl Error for Stage3KernelError {} + +fn prove_stage3_kernel( + context: Stage3KernelContext<'_>, + inputs: &Stage3ProverInputs<'_, F>, + store: Stage3ValueStore, + transcript: &mut T, +) -> Result, Stage3KernelError> +where + F: Field, + T: Transcript, +{ + match context.abi_kind()? { + Stage3KernelAbi::Batched => prove_batched_stage3(context, inputs, store, transcript), + abi => Err(Stage3KernelError::KernelNotImplemented { abi: abi.name() }), + } +} + +fn verify_stage3_kernel( + context: Stage3KernelContext<'_>, + store: Stage3ValueStore, + proof: &Stage3SumcheckOutput, + transcript: &mut T, +) -> Result, Stage3KernelError> +where + F: Field, + T: Transcript, +{ + match context.abi_kind()? { + Stage3KernelAbi::Batched => verify_batched_stage3(context, store, proof, transcript), + abi => Err(Stage3KernelError::KernelNotImplemented { abi: abi.name() }), + } +} + +#[tracing::instrument(skip_all, name = "Stage3::prove_batched")] +fn prove_batched_stage3( + context: Stage3KernelContext<'_>, + inputs: &Stage3ProverInputs<'_, F>, + mut store: Stage3ValueStore, + transcript: &mut T, +) -> Result, Stage3KernelError> +where + F: Field, + T: Transcript, +{ + let claims = context.batch_claims()?; + let input_claims = store.batch_claim_values(context.program, context.batch)?; + for claim in &input_claims { + append_labeled_scalar(transcript, context.batch.claim_label, claim); + } + let batching_coeffs = transcript.challenge_vector(claims.len()); + let max_rounds = context.driver.num_rounds; + let two_inv = F::from_u64(2) + .inverse() + .ok_or(Stage3KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "field element 2 is not invertible", + })?; + let mut instances = Vec::with_capacity(claims.len()); + for (index, claim) in claims.iter().enumerate() { + instances.push(Stage3BatchedInstance { + claim, + relation: claim_relation(context.program, claim)?, + offset: instance_round_offset(context.program, context.driver.symbol, claim.symbol)?, + previous_claim: input_claims[index].mul_pow_2(max_rounds - claim.num_rounds), + state: Stage3ProverInstanceState::new(context.program, claim, inputs, &store)?, + }); + } + + let mut point = Vec::with_capacity(max_rounds); + let mut round_polynomials = Vec::with_capacity(max_rounds); + let mut batched_claim = instances + .iter() + .zip(&batching_coeffs) + .map(|(instance, &coefficient)| instance.previous_claim * coefficient) + .sum::(); + for round in 0..max_rounds { + let mut individual_polys = Vec::with_capacity(instances.len()); + for instance in &mut instances { + let poly = if instance.is_active(round) { + instance + .state + .round_poly(round - instance.offset, instance.previous_claim)? + } else { + UnivariatePoly::new(vec![instance.previous_claim * two_inv]) + }; + #[cfg(debug_assertions)] + { + if poly.evaluate(F::zero()) + poly.evaluate(F::one()) != instance.previous_claim { + return Err(Stage3KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched instance round claim mismatch", + }); + } + } + individual_polys.push(poly); + } + let batched_poly = combine_univariate_polys(&individual_polys, &batching_coeffs); + #[cfg(debug_assertions)] + { + if batched_poly.evaluate(F::zero()) + batched_poly.evaluate(F::one()) != batched_claim { + return Err(Stage3KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched round claim mismatch", + }); + } + } + append_compressed_univariate_poly(transcript, context.driver.round_label, &batched_poly); + let challenge = transcript.challenge(); + point.push(challenge); + batched_claim = batched_poly.evaluate(challenge); + for (instance, poly) in instances.iter_mut().zip(individual_polys) { + instance.previous_claim = poly.evaluate(challenge); + if instance.is_active(round) { + instance.state.ingest_challenge(challenge); + } + } + round_polynomials.push(batched_poly); + } + + let mut evals = Vec::new(); + for instance in &instances { + evals.extend(instance.state.final_evals(instance.relation)?); + } + let expected = + expected_batched_output_claim(context, &store, &evals, &point, &batching_coeffs)?; + if batched_claim != expected { + return Err(Stage3KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched output claim mismatch", + }); + } + store.observe_sumcheck_values(context.program, context.driver.symbol, &point, &evals)?; + let opening_claims = append_opening_claims(context.program, &mut store, transcript, &evals)?; + Ok(Stage3SumcheckOutput { + driver: context.driver.symbol, + point, + evals, + opening_claims, + proof: SumcheckProof { round_polynomials }, + }) +} + +fn verify_batched_stage3( + context: Stage3KernelContext<'_>, + mut store: Stage3ValueStore, + proof: &Stage3SumcheckOutput, + transcript: &mut T, +) -> Result, Stage3KernelError> +where + F: Field, + T: Transcript, +{ + if proof.driver != context.driver.symbol { + return Err(Stage3KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "driver symbol mismatch", + }); + } + if proof.proof.round_polynomials.len() != context.driver.num_rounds { + return Err(Stage3KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "unexpected batched round count", + }); + } + let claims = context.batch_claims()?; + let input_claims = store.batch_claim_values(context.program, context.batch)?; + for claim in &input_claims { + append_labeled_scalar(transcript, context.batch.claim_label, claim); + } + let batching_coeffs = transcript.challenge_vector(claims.len()); + let max_rounds = context.driver.num_rounds; + let mut running_claim = input_claims + .iter() + .zip(claims.iter()) + .zip(&batching_coeffs) + .map(|((claim, plan), &coefficient)| { + claim.mul_pow_2(max_rounds - plan.num_rounds) * coefficient + }) + .sum::(); + let mut point = Vec::with_capacity(max_rounds); + for poly in &proof.proof.round_polynomials { + if polynomial_degree(poly) > context.driver.degree { + return Err(Stage3KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched polynomial exceeds degree bound", + }); + } + if poly.evaluate(F::zero()) + poly.evaluate(F::one()) != running_claim { + return Err(Stage3KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched round check failed", + }); + } + append_compressed_univariate_poly(transcript, context.driver.round_label, poly); + let challenge = transcript.challenge(); + running_claim = poly.evaluate(challenge); + point.push(challenge); + } + if !proof.point.is_empty() && proof.point != point { + return Err(Stage3KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched point mismatch", + }); + } + let expected = + expected_batched_output_claim(context, &store, &proof.evals, &point, &batching_coeffs)?; + if running_claim != expected { + return Err(Stage3KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched output claim mismatch", + }); + } + store.observe_sumcheck_values(context.program, context.driver.symbol, &point, &proof.evals)?; + let opening_claims = + append_opening_claims(context.program, &mut store, transcript, &proof.evals)?; + Ok(Stage3SumcheckOutput { + driver: context.driver.symbol, + point, + evals: proof.evals.clone(), + opening_claims, + proof: proof.proof.clone(), + }) +} + +struct Stage3BatchedInstance<'a, F: Field> { + claim: &'a Stage3SumcheckClaimPlan, + relation: Stage3Relation, + offset: usize, + previous_claim: F, + state: Stage3ProverInstanceState, +} + +impl Stage3BatchedInstance<'_, F> { + fn is_active(&self, round: usize) -> bool { + round >= self.offset && round < self.offset + self.claim.num_rounds + } +} + +enum Stage3ProverInstanceState { + SpartanShift(SpartanShiftState), + SumOfProducts(SumOfProductsState), +} + +impl Stage3ProverInstanceState { + fn new( + program: &'static Stage3CpuProgramPlan, + claim: &Stage3SumcheckClaimPlan, + inputs: &Stage3ProverInputs<'_, F>, + store: &Stage3ValueStore, + ) -> Result { + match claim_relation(program, claim)? { + Stage3Relation::SpartanShift => { + return spartan_shift_state(claim, inputs, store).map(Self::SpartanShift); + } + Stage3Relation::InstructionInput => instruction_input_state(claim, inputs, store), + Stage3Relation::RegistersClaimReduction => registers_state(claim, inputs, store), + relation @ Stage3Relation::Batched => Err(Stage3KernelError::KernelNotImplemented { + abi: relation.symbol(), + }), + } + .map(Self::SumOfProducts) + } + + fn round_poly( + &self, + _round: usize, + previous_claim: F, + ) -> Result, Stage3KernelError> { + match self { + Self::SpartanShift(state) => Ok(state.round_poly(previous_claim)), + Self::SumOfProducts(state) => Ok(state.round_poly(previous_claim)), + } + } + + fn ingest_challenge(&mut self, challenge: F) { + match self { + Self::SpartanShift(state) => state.bind(challenge), + Self::SumOfProducts(state) => state.bind(challenge), + } + } + + fn final_evals( + &self, + relation: Stage3Relation, + ) -> Result>, Stage3KernelError> { + match self { + Self::SpartanShift(state) => state.final_evals(relation), + Self::SumOfProducts(state) => state.final_evals(relation), + } + } +} + +#[derive(Clone)] +struct SpartanShiftState { + phase: SpartanShiftPhase, + r_outer: Vec, + r_product: Vec, + gamma: F, + gamma2: F, + gamma3: F, + gamma4: F, + point: Vec, +} + +#[derive(Clone)] +enum SpartanShiftPhase { + Phase1(SpartanShiftPhase1), + Phase2(SpartanShiftPhase2), +} + +#[derive(Clone)] +struct SpartanShiftPhase1 { + prefix_suffix_pairs: Vec<(Vec, Vec)>, + scratch: Vec<(Vec, Vec)>, + cycles: Vec, +} + +#[derive(Clone)] +struct SpartanShiftPhase2 { + eq_outer: Vec, + eq_product: Vec, + weighted_next_values: Vec, + not_noop: Vec, + unexpanded_pc: Vec, + pc: Vec, + is_virtual: Vec, + is_first_in_sequence: Vec, + is_noop: Vec, + scratch: Vec>, +} + +#[derive(Clone)] +struct SumOfProductsState { + kind: SumOfProductsKind, + factors: Vec>, + factor_scratch: Vec>, + split_eq: Option>, + terms: Vec>, + outputs: Vec, + deferred_outputs: Vec>, + point: Vec, +} + +#[derive(Clone, Copy)] +enum SumOfProductsKind { + InstructionInput, + Registers, +} + +#[derive(Clone)] +struct ProductTerm { + coefficient: F, +} + +#[derive(Clone, Copy)] +struct FactorOutput { + name: &'static str, + oracle: &'static str, + factor: usize, +} + +#[derive(Clone)] +struct DeferredOutput { + name: &'static str, + oracle: &'static str, + values: Vec, +} + +impl SumOfProductsState { + fn new( + kind: SumOfProductsKind, + factors: Vec>, + split_eq: Option>, + terms: Vec>, + outputs: Vec, + deferred_outputs: Vec>, + ) -> Self { + let factor_scratch = (0..factors.len()).map(|_| Vec::new()).collect(); + Self { + kind, + factors, + factor_scratch, + split_eq, + terms, + outputs, + deferred_outputs, + point: Vec::new(), + } + } + + fn round_poly(&self, previous_claim: F) -> UnivariatePoly { + let Some(split_eq) = self.split_eq.as_ref() else { + std::process::abort(); + }; + match self.kind { + SumOfProductsKind::InstructionInput => round_poly_from_instruction_input( + &self.factors, + &self.terms, + split_eq, + previous_claim, + ), + SumOfProductsKind::Registers => { + round_poly_from_registers(&self.factors, &self.terms, split_eq, previous_claim) + } + } + } + + fn bind(&mut self, challenge: F) { + let half = self.factors.first().map_or(0, |factor| factor.len() / 2); + if half >= DENSE_BIND_PAR_THRESHOLD { + self.factors + .par_iter_mut() + .zip(self.factor_scratch.par_iter_mut()) + .for_each(|(factor, scratch)| { + bind_dense_evals_reuse_serial(factor, scratch, challenge); + }); + } else { + for (factor, scratch) in self.factors.iter_mut().zip(&mut self.factor_scratch) { + bind_dense_evals_reuse_serial(factor, scratch, challenge); + } + } + if let Some(split_eq) = &mut self.split_eq { + split_eq.bind(challenge); + } + self.point.push(challenge); + } + + fn factor_eval(&self, index: usize, relation: Stage3Relation) -> Result { + self.factors + .get(index) + .and_then(|values| values.first()) + .copied() + .ok_or(Stage3KernelError::InvalidProof { + driver: relation.symbol(), + reason: "empty stage3 factor", + }) + } + + fn final_evals( + &self, + relation: Stage3Relation, + ) -> Result>, Stage3KernelError> { + let mut evals = self + .outputs + .iter() + .map(|output| { + Ok(named_eval( + output.name, + output.oracle, + self.factor_eval(output.factor, relation)?, + )) + }) + .collect::, _>>()?; + if !self.deferred_outputs.is_empty() { + let point = reverse_slice(&self.point); + let eq = EqPolynomial::::evals(&point, None); + evals.extend(self.deferred_outputs.iter().map(|output| { + named_eval( + output.name, + output.oracle, + deferred_output_eval(&output.values, &eq), + ) + })); + } + Ok(evals) + } +} + +impl SpartanShiftState { + fn new( + cycles: &[Stage3Cycle], + r_outer: &[F], + r_product: &[F], + gamma: F, + gamma2: F, + gamma3: F, + gamma4: F, + ) -> Self { + Self { + phase: SpartanShiftPhase::Phase1(SpartanShiftPhase1::new( + cycles, r_outer, r_product, gamma, gamma2, gamma3, gamma4, + )), + r_outer: r_outer.to_vec(), + r_product: r_product.to_vec(), + gamma, + gamma2, + gamma3, + gamma4, + point: Vec::new(), + } + } + + fn round_poly(&self, previous_claim: F) -> UnivariatePoly { + match &self.phase { + SpartanShiftPhase::Phase1(state) => state.round_poly(), + SpartanShiftPhase::Phase2(state) => state.round_poly(previous_claim), + } + } + + fn bind(&mut self, challenge: F) { + let transition = match &mut self.phase { + SpartanShiftPhase::Phase1(state) => { + if state.should_transition_to_phase2() { + true + } else { + state.bind(challenge); + false + } + } + SpartanShiftPhase::Phase2(state) => { + state.bind(challenge); + false + } + }; + self.point.push(challenge); + if transition { + let SpartanShiftPhase::Phase1(state) = &self.phase else { + unreachable!("checked phase before transition"); + }; + let phase2 = SpartanShiftPhase2::new( + &state.cycles, + &self.point, + &self.r_outer, + &self.r_product, + self.gamma, + self.gamma2, + self.gamma3, + self.gamma4, + ); + self.phase = SpartanShiftPhase::Phase2(phase2); + } + } + + fn final_evals( + &self, + relation: Stage3Relation, + ) -> Result>, Stage3KernelError> { + let SpartanShiftPhase::Phase2(state) = &self.phase else { + return Err(Stage3KernelError::InvalidProof { + driver: relation.symbol(), + reason: "spartan shift did not finish phase 2", + }); + }; + state.final_evals(relation) + } +} + +impl SpartanShiftPhase1 { + fn new( + cycles: &[Stage3Cycle], + r_outer: &[F], + r_product: &[F], + gamma: F, + gamma2: F, + gamma3: F, + gamma4: F, + ) -> Self { + let outer = EqPlusOnePrefixSuffix::new(r_outer); + let product = EqPlusOnePrefixSuffix::new(r_product); + let q_values = + spartan_shift_phase1_q_values(cycles, &outer, &product, gamma, gamma2, gamma3, gamma4); + let mut q_outer_0 = Vec::with_capacity(q_values.len()); + let mut q_outer_1 = Vec::with_capacity(q_values.len()); + let mut q_product_0 = Vec::with_capacity(q_values.len()); + let mut q_product_1 = Vec::with_capacity(q_values.len()); + for [outer_0, outer_1, product_0, product_1] in q_values { + q_outer_0.push(outer_0); + q_outer_1.push(outer_1); + q_product_0.push(product_0); + q_product_1.push(product_1); + } + let prefix_suffix_pairs = vec![ + (outer.prefix_0, q_outer_0), + (outer.prefix_1, q_outer_1), + (product.prefix_0, q_product_0), + (product.prefix_1, q_product_1), + ]; + let scratch = prefix_suffix_pairs + .iter() + .map(|_| (Vec::new(), Vec::new())) + .collect(); + Self { + prefix_suffix_pairs, + scratch, + cycles: cycles.to_vec(), + } + } + + fn round_poly(&self) -> UnivariatePoly { + let half = self.prefix_suffix_pairs[0].0.len() / 2; + round_poly_from_stage3_coefficients(half, 2, |row, acc| { + for (prefix, suffix) in &self.prefix_suffix_pairs { + let (prefix_0, prefix_delta) = linear_pair(prefix, row); + let (suffix_0, suffix_delta) = linear_pair(suffix, row); + accumulate_linear_product( + acc, + F::one(), + prefix_0, + prefix_delta, + suffix_0, + suffix_delta, + ); + } + }) + } + + fn bind(&mut self, challenge: F) { + for ((prefix, suffix), (prefix_scratch, suffix_scratch)) in self + .prefix_suffix_pairs + .iter_mut() + .zip(self.scratch.iter_mut()) + { + bind_dense_evals_reuse_serial(prefix, prefix_scratch, challenge); + bind_dense_evals_reuse_serial(suffix, suffix_scratch, challenge); + } + } + + fn should_transition_to_phase2(&self) -> bool { + self.prefix_suffix_pairs[0].0.len() == 2 + } +} + +impl SpartanShiftPhase2 { + fn new( + cycles: &[Stage3Cycle], + low_challenges: &[F], + r_outer: &[F], + r_product: &[F], + gamma: F, + gamma2: F, + gamma3: F, + gamma4: F, + ) -> Self { + let low_point = reverse_slice(low_challenges); + let low_eq = EqPolynomial::::evals(&low_point, None); + let eq_outer = spartan_shift_phase2_eq_plus_one(r_outer, &low_eq); + let eq_product = spartan_shift_phase2_eq_plus_one(r_product, &low_eq); + let ( + unexpanded_pc, + pc, + is_virtual, + is_first_in_sequence, + is_noop, + weighted_next_values, + not_noop, + ) = spartan_shift_phase2_outputs(cycles, &low_eq, gamma, gamma2, gamma3); + let not_noop = not_noop + .iter() + .map(|&value| gamma4 * value) + .collect::>(); + Self { + eq_outer, + eq_product, + weighted_next_values, + not_noop, + unexpanded_pc, + pc, + is_virtual, + is_first_in_sequence, + is_noop, + scratch: (0..9).map(|_| Vec::new()).collect(), + } + } + + fn round_poly(&self, _previous_claim: F) -> UnivariatePoly { + round_poly_from_stage3_coefficients(self.eq_outer.len() / 2, 2, |row, acc| { + let (eq_outer_0, eq_outer_delta) = linear_pair(&self.eq_outer, row); + let (eq_product_0, eq_product_delta) = linear_pair(&self.eq_product, row); + let (next_values_0, next_values_delta) = linear_pair(&self.weighted_next_values, row); + let (not_noop_0, not_noop_delta) = linear_pair(&self.not_noop, row); + accumulate_linear_product( + acc, + F::one(), + eq_outer_0, + eq_outer_delta, + next_values_0, + next_values_delta, + ); + accumulate_linear_product( + acc, + F::one(), + eq_product_0, + eq_product_delta, + not_noop_0, + not_noop_delta, + ); + }) + } + + fn bind(&mut self, challenge: F) { + bind_dense_evals_reuse_serial(&mut self.eq_outer, &mut self.scratch[0], challenge); + bind_dense_evals_reuse_serial(&mut self.eq_product, &mut self.scratch[1], challenge); + bind_dense_evals_reuse_serial( + &mut self.weighted_next_values, + &mut self.scratch[2], + challenge, + ); + bind_dense_evals_reuse_serial(&mut self.not_noop, &mut self.scratch[3], challenge); + bind_dense_evals_reuse_serial(&mut self.unexpanded_pc, &mut self.scratch[4], challenge); + bind_dense_evals_reuse_serial(&mut self.pc, &mut self.scratch[5], challenge); + bind_dense_evals_reuse_serial(&mut self.is_virtual, &mut self.scratch[6], challenge); + bind_dense_evals_reuse_serial( + &mut self.is_first_in_sequence, + &mut self.scratch[7], + challenge, + ); + bind_dense_evals_reuse_serial(&mut self.is_noop, &mut self.scratch[8], challenge); + } + + fn final_evals( + &self, + relation: Stage3Relation, + ) -> Result>, Stage3KernelError> { + let value = |values: &[F]| { + values + .first() + .copied() + .ok_or(Stage3KernelError::InvalidProof { + driver: relation.symbol(), + reason: "empty spartan shift output", + }) + }; + Ok(vec![ + named_eval( + "stage3.spartan_shift.eval.UnexpandedPC", + "UnexpandedPC", + value(&self.unexpanded_pc)?, + ), + named_eval("stage3.spartan_shift.eval.PC", "PC", value(&self.pc)?), + named_eval( + "stage3.spartan_shift.eval.OpFlagVirtualInstruction", + "OpFlagVirtualInstruction", + value(&self.is_virtual)?, + ), + named_eval( + "stage3.spartan_shift.eval.OpFlagIsFirstInSequence", + "OpFlagIsFirstInSequence", + value(&self.is_first_in_sequence)?, + ), + named_eval( + "stage3.spartan_shift.eval.InstructionFlagIsNoop", + "InstructionFlagIsNoop", + value(&self.is_noop)?, + ), + ]) + } +} + +fn spartan_shift_state( + claim: &Stage3SumcheckClaimPlan, + inputs: &Stage3ProverInputs<'_, F>, + store: &Stage3ValueStore, +) -> Result, Stage3KernelError> { + let cycles = stage3_cycles(inputs, claim.num_rounds)?; + let r_outer = store.point("stage3.input.stage1.NextPC")?; + let r_product = store.point("stage3.input.stage2.product_virtual.NextIsNoop")?; + let gamma = store.scalar("stage3.spartan_shift.gamma")?; + let gamma2 = store.scalar("stage3.spartan_shift.gamma2")?; + let gamma3 = store.scalar("stage3.spartan_shift.gamma3")?; + let gamma4 = store.scalar("stage3.spartan_shift.gamma4")?; + Ok(SpartanShiftState::new( + cycles, r_outer, r_product, gamma, gamma2, gamma3, gamma4, + )) +} + +fn instruction_input_state( + claim: &Stage3SumcheckClaimPlan, + inputs: &Stage3ProverInputs<'_, F>, + store: &Stage3ValueStore, +) -> Result, Stage3KernelError> { + let cycles = stage3_cycles(inputs, claim.num_rounds)?; + let eq_point = store.point("stage3.input.stage2.product_virtual.LeftInstructionInput")?; + let gamma = store.scalar("stage3.instruction_input.gamma")?; + let ( + right_operand_is_rs2, + rs2_value, + right_operand_is_imm, + imm, + left_operand_is_rs1, + rs1_value, + left_operand_is_pc, + unexpanded_pc, + ) = instruction_input_factors(cycles); + let factors = vec![ + right_operand_is_rs2, + rs2_value, + right_operand_is_imm, + imm, + left_operand_is_rs1, + rs1_value, + left_operand_is_pc, + unexpanded_pc, + ]; + Ok(SumOfProductsState::new( + SumOfProductsKind::InstructionInput, + factors, + Some(SplitEqState::new_low_to_high(eq_point, None)), + vec![ + ProductTerm { + coefficient: F::one(), + }, + ProductTerm { + coefficient: F::one(), + }, + ProductTerm { coefficient: gamma }, + ProductTerm { coefficient: gamma }, + ], + vec![ + FactorOutput { + name: "stage3.instruction_input.eval.InstructionFlagLeftOperandIsRs1Value", + oracle: "InstructionFlagLeftOperandIsRs1Value", + factor: 4, + }, + FactorOutput { + name: "stage3.instruction_input.eval.Rs1Value", + oracle: "Rs1Value", + factor: 5, + }, + FactorOutput { + name: "stage3.instruction_input.eval.InstructionFlagLeftOperandIsPC", + oracle: "InstructionFlagLeftOperandIsPC", + factor: 6, + }, + FactorOutput { + name: "stage3.instruction_input.eval.UnexpandedPC", + oracle: "UnexpandedPC", + factor: 7, + }, + FactorOutput { + name: "stage3.instruction_input.eval.InstructionFlagRightOperandIsRs2Value", + oracle: "InstructionFlagRightOperandIsRs2Value", + factor: 0, + }, + FactorOutput { + name: "stage3.instruction_input.eval.Rs2Value", + oracle: "Rs2Value", + factor: 1, + }, + FactorOutput { + name: "stage3.instruction_input.eval.InstructionFlagRightOperandIsImm", + oracle: "InstructionFlagRightOperandIsImm", + factor: 2, + }, + FactorOutput { + name: "stage3.instruction_input.eval.Imm", + oracle: "Imm", + factor: 3, + }, + ], + Vec::new(), + )) +} + +fn registers_state( + claim: &Stage3SumcheckClaimPlan, + inputs: &Stage3ProverInputs<'_, F>, + store: &Stage3ValueStore, +) -> Result, Stage3KernelError> { + let cycles = stage3_cycles(inputs, claim.num_rounds)?; + let eq_point = store.point("stage3.input.stage1.RdWriteValue")?; + let gamma = store.scalar("stage3.registers.gamma")?; + let gamma2 = store.scalar("stage3.registers.gamma2")?; + let (rd_write_value, rs1_value, rs2_value) = register_factors(cycles); + let factors = vec![rd_write_value, rs1_value, rs2_value]; + Ok(SumOfProductsState::new( + SumOfProductsKind::Registers, + factors, + Some(SplitEqState::new_low_to_high(eq_point, None)), + vec![ + ProductTerm { + coefficient: F::one(), + }, + ProductTerm { coefficient: gamma }, + ProductTerm { + coefficient: gamma2, + }, + ], + vec![ + FactorOutput { + name: "stage3.registers_claim_reduction.eval.RdWriteValue", + oracle: "RdWriteValue", + factor: 0, + }, + FactorOutput { + name: "stage3.registers_claim_reduction.eval.Rs1Value", + oracle: "Rs1Value", + factor: 1, + }, + FactorOutput { + name: "stage3.registers_claim_reduction.eval.Rs2Value", + oracle: "Rs2Value", + factor: 2, + }, + ], + Vec::new(), + )) +} + +fn stage3_cycles<'a, F: Field>( + inputs: &'a Stage3ProverInputs<'_, F>, + num_rounds: usize, +) -> Result<&'a [Stage3Cycle], Stage3KernelError> { + let cycles = inputs.cycles.ok_or(Stage3KernelError::MissingKernelInput { + kernel: "jolt_stage3_batched", + input: "cycles", + })?; + let expected = + 1usize + .checked_shl(num_rounds as u32) + .ok_or(Stage3KernelError::InvalidInputLength { + input: "stage3.cycles", + expected: usize::BITS as usize, + actual: num_rounds, + })?; + require_operand_count("stage3.cycles", expected, cycles.len())?; + Ok(cycles) +} + +type InstructionInputFactors = ( + Vec, + Vec, + Vec, + Vec, + Vec, + Vec, + Vec, + Vec, +); +type RegisterFactors = (Vec, Vec, Vec); + +fn spartan_shift_phase1_q_values( + cycles: &[Stage3Cycle], + outer: &EqPlusOnePrefixSuffix, + product: &EqPlusOnePrefixSuffix, + gamma: F, + gamma2: F, + gamma3: F, + gamma4: F, +) -> Vec<[F; 4]> { + let prefix_len = outer.prefix_0.len(); + let suffix_len = outer.suffix_0.len(); + debug_assert_eq!(prefix_len * suffix_len, cycles.len()); + (0..prefix_len) + .into_par_iter() + .map(|x_lo| { + let mut acc = [F::Accumulator::default(); 4]; + for x_hi in 0..suffix_len { + let cycle = cycles[x_lo + x_hi * prefix_len]; + let mut weighted = F::from_u64(cycle.unexpanded_pc) + gamma * F::from_u64(cycle.pc); + if cycle.is_virtual { + weighted += gamma2; + } + if cycle.is_first_in_sequence { + weighted += gamma3; + } + acc[0].fmadd(outer.suffix_0[x_hi], weighted); + acc[1].fmadd(outer.suffix_1[x_hi], weighted); + if !cycle.is_noop { + acc[2].fmadd(gamma4, product.suffix_0[x_hi]); + acc[3].fmadd(gamma4, product.suffix_1[x_hi]); + } + } + [ + acc[0].reduce(), + acc[1].reduce(), + acc[2].reduce(), + acc[3].reduce(), + ] + }) + .collect() +} + +fn spartan_shift_phase2_eq_plus_one(point: &[F], low_eq: &[F]) -> Vec { + let split = EqPlusOnePrefixSuffix::new(point); + let prefix_0_eval = deferred_output_eval(&split.prefix_0, low_eq); + let prefix_1_eval = deferred_output_eval(&split.prefix_1, low_eq); + debug_assert_eq!(split.prefix_0.len(), low_eq.len()); + split + .suffix_0 + .iter() + .zip(split.suffix_1.iter()) + .map(|(&suffix_0, &suffix_1)| prefix_0_eval * suffix_0 + prefix_1_eval * suffix_1) + .collect() +} + +type SpartanShiftPhase2Outputs = (Vec, Vec, Vec, Vec, Vec, Vec, Vec); + +fn spartan_shift_phase2_outputs( + cycles: &[Stage3Cycle], + low_eq: &[F], + gamma: F, + gamma2: F, + gamma3: F, +) -> SpartanShiftPhase2Outputs { + let low_len = low_eq.len(); + let high_len = cycles.len() / low_len; + let mut unexpanded_pc = vec![F::zero(); high_len]; + let mut pc = vec![F::zero(); high_len]; + let mut is_virtual = vec![F::zero(); high_len]; + let mut is_first_in_sequence = vec![F::zero(); high_len]; + let mut is_noop = vec![F::zero(); high_len]; + let mut weighted_next_values = vec![F::zero(); high_len]; + let mut not_noop = vec![F::zero(); high_len]; + ( + &mut unexpanded_pc, + &mut pc, + &mut is_virtual, + &mut is_first_in_sequence, + &mut is_noop, + &mut weighted_next_values, + &mut not_noop, + 0..high_len, + ) + .into_par_iter() + .for_each( + |( + unexpanded_pc, + pc, + is_virtual, + is_first_in_sequence, + is_noop, + weighted_next_values, + not_noop, + x_hi, + )| { + let mut unexpanded_acc = F::Accumulator::default(); + let mut pc_acc = F::Accumulator::default(); + let mut virtual_acc = F::Accumulator::default(); + let mut first_acc = F::Accumulator::default(); + let mut noop_acc = F::Accumulator::default(); + let base = x_hi * low_len; + for (x_lo, &weight) in low_eq.iter().enumerate() { + let cycle = cycles[base + x_lo]; + unexpanded_acc.fmadd_u64(weight, cycle.unexpanded_pc); + pc_acc.fmadd_u64(weight, cycle.pc); + virtual_acc.fmadd_bool(weight, cycle.is_virtual); + first_acc.fmadd_bool(weight, cycle.is_first_in_sequence); + noop_acc.fmadd_bool(weight, cycle.is_noop); + } + *unexpanded_pc = unexpanded_acc.reduce(); + *pc = pc_acc.reduce(); + *is_virtual = virtual_acc.reduce(); + *is_first_in_sequence = first_acc.reduce(); + *is_noop = noop_acc.reduce(); + *weighted_next_values = *unexpanded_pc + + gamma * *pc + + gamma2 * *is_virtual + + gamma3 * *is_first_in_sequence; + *not_noop = F::one() - *is_noop; + }, + ); + ( + unexpanded_pc, + pc, + is_virtual, + is_first_in_sequence, + is_noop, + weighted_next_values, + not_noop, + ) +} + +fn instruction_input_factors(cycles: &[Stage3Cycle]) -> InstructionInputFactors { + let mut right_operand_is_rs2 = vec![F::zero(); cycles.len()]; + let mut rs2_value = vec![F::zero(); cycles.len()]; + let mut right_operand_is_imm = vec![F::zero(); cycles.len()]; + let mut imm = vec![F::zero(); cycles.len()]; + let mut left_operand_is_rs1 = vec![F::zero(); cycles.len()]; + let mut rs1_value = vec![F::zero(); cycles.len()]; + let mut left_operand_is_pc = vec![F::zero(); cycles.len()]; + let mut unexpanded_pc = vec![F::zero(); cycles.len()]; + ( + &mut right_operand_is_rs2, + &mut rs2_value, + &mut right_operand_is_imm, + &mut imm, + &mut left_operand_is_rs1, + &mut rs1_value, + &mut left_operand_is_pc, + &mut unexpanded_pc, + cycles, + ) + .into_par_iter() + .for_each( + |( + right_operand_is_rs2, + rs2_value, + right_operand_is_imm, + imm, + left_operand_is_rs1, + rs1_value, + left_operand_is_pc, + unexpanded_pc, + cycle, + )| { + *right_operand_is_rs2 = F::from_bool(cycle.right_operand_is_rs2); + *rs2_value = F::from_u64(cycle.rs2_value); + *right_operand_is_imm = F::from_bool(cycle.right_operand_is_imm); + *imm = F::from_i128(cycle.imm); + *left_operand_is_rs1 = F::from_bool(cycle.left_operand_is_rs1); + *rs1_value = F::from_u64(cycle.rs1_value); + *left_operand_is_pc = F::from_bool(cycle.left_operand_is_pc); + *unexpanded_pc = F::from_u64(cycle.unexpanded_pc); + }, + ); + ( + right_operand_is_rs2, + rs2_value, + right_operand_is_imm, + imm, + left_operand_is_rs1, + rs1_value, + left_operand_is_pc, + unexpanded_pc, + ) +} + +fn register_factors(cycles: &[Stage3Cycle]) -> RegisterFactors { + let mut rd_write_value = vec![F::zero(); cycles.len()]; + let mut rs1_value = vec![F::zero(); cycles.len()]; + let mut rs2_value = vec![F::zero(); cycles.len()]; + (&mut rd_write_value, &mut rs1_value, &mut rs2_value, cycles) + .into_par_iter() + .for_each(|(rd_write_value, rs1_value, rs2_value, cycle)| { + *rd_write_value = F::from_u64(cycle.rd_write_value); + *rs1_value = F::from_u64(cycle.rs1_value); + *rs2_value = F::from_u64(cycle.rs2_value); + }); + (rd_write_value, rs1_value, rs2_value) +} + +fn expected_batched_output_claim( + context: Stage3KernelContext<'_>, + store: &Stage3ValueStore, + evals: &[Stage3NamedEval], + point: &[F], + batching_coeffs: &[F], +) -> Result { + let mut expected = F::zero(); + for (claim, &coefficient) in context.batch_claims()?.iter().zip(batching_coeffs) { + let instance = context + .program + .instance_results + .iter() + .find(|instance| { + instance.claim == claim.symbol && instance.source == context.driver.symbol + }) + .ok_or(Stage3KernelError::MissingClaim { + batch: context.batch.symbol, + claim: claim.symbol, + })?; + let local_point = point + .get(instance.round_offset..instance.round_offset + instance.num_rounds) + .ok_or(Stage3KernelError::InvalidInputLength { + input: instance.symbol, + expected: instance.round_offset + instance.num_rounds, + actual: point.len(), + })?; + let claim_value = match Stage3Relation::from_symbol(instance.relation).ok_or( + Stage3KernelError::UnknownRelation { + relation: instance.relation, + }, + )? { + Stage3Relation::SpartanShift => expected_spartan_shift(store, evals, local_point)?, + Stage3Relation::InstructionInput => { + expected_instruction_input(store, evals, local_point)? + } + Stage3Relation::RegistersClaimReduction => { + expected_registers(store, evals, local_point)? + } + relation @ Stage3Relation::Batched => { + return Err(Stage3KernelError::KernelNotImplemented { + abi: relation.symbol(), + }) + } + }; + expected += coefficient * claim_value; + } + Ok(expected) +} + +fn expected_spartan_shift( + store: &Stage3ValueStore, + evals: &[Stage3NamedEval], + local_point: &[F], +) -> Result { + let opening_point = reverse_slice(local_point); + let eq_outer = + EqPlusOnePolynomial::::new(store.point("stage3.input.stage1.NextPC")?.to_vec()) + .evaluate(&opening_point); + let eq_product = EqPlusOnePolynomial::::new( + store + .point("stage3.input.stage2.product_virtual.NextIsNoop")? + .to_vec(), + ) + .evaluate(&opening_point); + let gamma = store.scalar("stage3.spartan_shift.gamma")?; + let gamma2 = store.scalar("stage3.spartan_shift.gamma2")?; + let gamma3 = store.scalar("stage3.spartan_shift.gamma3")?; + let gamma4 = store.scalar("stage3.spartan_shift.gamma4")?; + let weighted_outer = eval_by_name(evals, "stage3.spartan_shift.eval.UnexpandedPC")? + + gamma * eval_by_name(evals, "stage3.spartan_shift.eval.PC")? + + gamma2 * eval_by_name(evals, "stage3.spartan_shift.eval.OpFlagVirtualInstruction")? + + gamma3 * eval_by_name(evals, "stage3.spartan_shift.eval.OpFlagIsFirstInSequence")?; + Ok(eq_outer * weighted_outer + + gamma4 + * eq_product + * (F::one() - eval_by_name(evals, "stage3.spartan_shift.eval.InstructionFlagIsNoop")?)) +} + +fn expected_instruction_input( + store: &Stage3ValueStore, + evals: &[Stage3NamedEval], + local_point: &[F], +) -> Result { + let opening_point = reverse_slice(local_point); + let eq_eval = EqPolynomial::::mle( + &opening_point, + store.point("stage3.input.stage2.product_virtual.LeftInstructionInput")?, + ); + let left = eval_by_name( + evals, + "stage3.instruction_input.eval.InstructionFlagLeftOperandIsRs1Value", + )? * eval_by_name(evals, "stage3.instruction_input.eval.Rs1Value")? + + eval_by_name( + evals, + "stage3.instruction_input.eval.InstructionFlagLeftOperandIsPC", + )? * eval_by_name(evals, "stage3.instruction_input.eval.UnexpandedPC")?; + let right = eval_by_name( + evals, + "stage3.instruction_input.eval.InstructionFlagRightOperandIsRs2Value", + )? * eval_by_name(evals, "stage3.instruction_input.eval.Rs2Value")? + + eval_by_name( + evals, + "stage3.instruction_input.eval.InstructionFlagRightOperandIsImm", + )? * eval_by_name(evals, "stage3.instruction_input.eval.Imm")?; + Ok(eq_eval * (right + store.scalar("stage3.instruction_input.gamma")? * left)) +} + +fn expected_registers( + store: &Stage3ValueStore, + evals: &[Stage3NamedEval], + local_point: &[F], +) -> Result { + let opening_point = reverse_slice(local_point); + let eq_eval = EqPolynomial::::mle( + &opening_point, + store.point("stage3.input.stage1.RdWriteValue")?, + ); + Ok(eq_eval + * (eval_by_name(evals, "stage3.registers_claim_reduction.eval.RdWriteValue")? + + store.scalar("stage3.registers.gamma")? + * eval_by_name(evals, "stage3.registers_claim_reduction.eval.Rs1Value")? + + store.scalar("stage3.registers.gamma2")? + * eval_by_name(evals, "stage3.registers_claim_reduction.eval.Rs2Value")?)) +} + +fn eval_by_name( + evals: &[Stage3NamedEval], + name: &'static str, +) -> Result { + evals + .iter() + .find(|eval| eval.name == name) + .map(|eval| eval.value) + .ok_or(Stage3KernelError::MissingValue { symbol: name }) +} + +fn deferred_output_eval(values: &[F], eq: &[F]) -> F { + debug_assert_eq!(values.len(), eq.len()); + if values.len() >= DENSE_BIND_PAR_THRESHOLD { + values + .par_iter() + .zip(eq.par_iter()) + .map(|(&value, &weight)| value * weight) + .sum() + } else { + values + .iter() + .zip(eq) + .map(|(&value, &weight)| value * weight) + .sum() + } +} + +fn reverse_slice(values: &[F]) -> Vec { + values.iter().rev().copied().collect() +} + +fn named_eval(name: &'static str, oracle: &'static str, value: F) -> Stage3NamedEval { + Stage3NamedEval { + name, + oracle, + value, + } +} + +fn claim_relation( + program: &'static Stage3CpuProgramPlan, + claim: &Stage3SumcheckClaimPlan, +) -> Result { + if let Some(relation) = claim.relation { + return Stage3Relation::from_symbol(relation) + .ok_or(Stage3KernelError::UnknownRelation { relation }); + } + let kernel_symbol = claim.kernel.ok_or(Stage3KernelError::MissingKernel { + driver: claim.symbol, + kernel: "", + })?; + let kernel = find_kernel(program, kernel_symbol).ok_or(Stage3KernelError::MissingKernel { + driver: claim.symbol, + kernel: kernel_symbol, + })?; + kernel.relation_kind() +} + +fn instance_round_offset( + program: &'static Stage3CpuProgramPlan, + driver: &'static str, + claim: &'static str, +) -> Result { + program + .instance_results + .iter() + .find(|instance| instance.source == driver && instance.claim == claim) + .map(|instance| instance.round_offset) + .ok_or(Stage3KernelError::MissingClaim { + batch: driver, + claim, + }) +} + +fn combine_univariate_polys( + polynomials: &[UnivariatePoly], + coefficients: &[F], +) -> UnivariatePoly { + let max_len = polynomials + .iter() + .map(|poly| poly.coefficients().len()) + .max() + .unwrap_or(0); + let mut combined = vec![F::zero(); max_len]; + for (poly, &coefficient) in polynomials.iter().zip(coefficients) { + for (combined, &term) in combined.iter_mut().zip(poly.coefficients()) { + *combined += term * coefficient; + } + } + UnivariatePoly::new(combined) +} + +fn round_poly_from_instruction_input( + factors: &[Vec], + terms: &[ProductTerm], + split_eq: &SplitEqState, + previous_claim: F, +) -> UnivariatePoly { + debug_assert_eq!(factors.len(), 8); + debug_assert_eq!(terms.len(), 4); + let gamma = terms[2].coefficient; + let (q_constant, q_quadratic) = + instruction_input_split_round_coefficients(factors, split_eq, gamma); + gruen_cubic_poly( + split_eq.current_target(), + q_constant, + q_quadratic, + previous_claim, + ) +} + +fn round_poly_from_registers( + factors: &[Vec], + terms: &[ProductTerm], + split_eq: &SplitEqState, + previous_claim: F, +) -> UnivariatePoly { + debug_assert_eq!(factors.len(), 3); + debug_assert_eq!(terms.len(), 3); + let gamma = terms[1].coefficient; + let gamma2 = terms[2].coefficient; + let q_constant = registers_split_round_constant(factors, split_eq, gamma, gamma2); + gruen_quadratic_poly(split_eq.current_target(), q_constant, previous_claim) +} + +fn instruction_input_split_round_coefficients( + factors: &[Vec], + split_eq: &SplitEqState, + gamma: F, +) -> (F, F) { + let e_in = split_eq.e_in(); + let e_out = split_eq.e_out(); + if e_in.len() > 1 { + instruction_input_low_round_coefficients(factors, e_in, e_out, gamma) + } else { + instruction_input_high_round_coefficients(factors, e_in[0], e_out, gamma) + } +} + +fn instruction_input_low_round_coefficients( + factors: &[Vec], + e_in: &[F], + e_out: &[F], + gamma: F, +) -> (F, F) { + let in_len = e_in.len(); + let in_pairs = in_len / 2; + if factors[0].len() / 2 >= DENSE_BIND_PAR_THRESHOLD { + let accumulators = (0..e_out.len()) + .into_par_iter() + .map(|x_out| { + let mut local = [F::Accumulator::default(); 2]; + let base_pair = x_out * in_pairs; + let out_weight = e_out[x_out]; + for pair in 0..in_pairs { + accumulate_instruction_input_quadratic_pair( + &mut local, + out_weight * (e_in[2 * pair] + e_in[2 * pair + 1]), + factors, + base_pair + pair, + gamma, + ); + } + local + }) + .reduce( + || [F::Accumulator::default(); 2], + |mut left, right| { + for (left, right) in left.iter_mut().zip(right) { + left.merge(right); + } + left + }, + ); + (accumulators[0].reduce(), accumulators[1].reduce()) + } else { + let mut total = [F::Accumulator::default(); 2]; + for (x_out, &out_weight) in e_out.iter().enumerate() { + let base_pair = x_out * in_pairs; + for pair in 0..in_pairs { + accumulate_instruction_input_quadratic_pair( + &mut total, + out_weight * (e_in[2 * pair] + e_in[2 * pair + 1]), + factors, + base_pair + pair, + gamma, + ); + } + } + (total[0].reduce(), total[1].reduce()) + } +} + +fn instruction_input_high_round_coefficients( + factors: &[Vec], + in_weight: F, + e_out: &[F], + gamma: F, +) -> (F, F) { + let pairs = e_out.len() / 2; + if pairs >= DENSE_BIND_PAR_THRESHOLD { + let accumulators = (0..pairs) + .into_par_iter() + .map(|pair| { + let mut local = [F::Accumulator::default(); 2]; + accumulate_instruction_input_quadratic_pair( + &mut local, + in_weight * (e_out[2 * pair] + e_out[2 * pair + 1]), + factors, + pair, + gamma, + ); + local + }) + .reduce( + || [F::Accumulator::default(); 2], + |mut left, right| { + for (left, right) in left.iter_mut().zip(right) { + left.merge(right); + } + left + }, + ); + (accumulators[0].reduce(), accumulators[1].reduce()) + } else { + let mut total = [F::Accumulator::default(); 2]; + for pair in 0..pairs { + accumulate_instruction_input_quadratic_pair( + &mut total, + in_weight * (e_out[2 * pair] + e_out[2 * pair + 1]), + factors, + pair, + gamma, + ); + } + (total[0].reduce(), total[1].reduce()) + } +} + +fn accumulate_instruction_input_quadratic_pair( + accumulators: &mut [F::Accumulator; 2], + weight: F, + factors: &[Vec], + row: usize, + gamma: F, +) { + accumulate_quadratic_coefficients( + accumulators, + weight, + F::one(), + &factors[0], + &factors[1], + row, + ); + accumulate_quadratic_coefficients( + accumulators, + weight, + F::one(), + &factors[2], + &factors[3], + row, + ); + accumulate_quadratic_coefficients(accumulators, weight, gamma, &factors[4], &factors[5], row); + accumulate_quadratic_coefficients(accumulators, weight, gamma, &factors[6], &factors[7], row); +} + +fn accumulate_quadratic_coefficients( + accumulators: &mut [F::Accumulator; 2], + weight: F, + scale: F, + left: &[F], + right: &[F], + row: usize, +) { + let (left_0, left_delta) = linear_pair(left, row); + let (right_0, right_delta) = linear_pair(right, row); + let scaled_weight = weight * scale; + accumulators[0].fmadd(scaled_weight * left_0, right_0); + accumulators[1].fmadd(scaled_weight * left_delta, right_delta); +} + +fn registers_split_round_constant( + factors: &[Vec], + split_eq: &SplitEqState, + gamma: F, + gamma2: F, +) -> F { + let e_in = split_eq.e_in(); + let e_out = split_eq.e_out(); + if e_in.len() > 1 { + registers_low_round_constant(factors, e_in, e_out, gamma, gamma2) + } else { + registers_high_round_constant(factors, e_in[0], e_out, gamma, gamma2) + } +} + +fn registers_low_round_constant( + factors: &[Vec], + e_in: &[F], + e_out: &[F], + gamma: F, + gamma2: F, +) -> F { + let in_len = e_in.len(); + let in_pairs = in_len / 2; + if factors[0].len() / 2 >= DENSE_BIND_PAR_THRESHOLD { + (0..e_out.len()) + .into_par_iter() + .map(|x_out| { + let mut local = F::Accumulator::default(); + let base_pair = x_out * in_pairs; + let out_weight = e_out[x_out]; + for pair in 0..in_pairs { + accumulate_register_constant( + &mut local, + out_weight * (e_in[2 * pair] + e_in[2 * pair + 1]), + factors, + base_pair + pair, + gamma, + gamma2, + ); + } + local + }) + .reduce(F::Accumulator::default, |mut left, right| { + left.merge(right); + left + }) + .reduce() + } else { + let mut total = F::Accumulator::default(); + for (x_out, &out_weight) in e_out.iter().enumerate() { + let base_pair = x_out * in_pairs; + for pair in 0..in_pairs { + accumulate_register_constant( + &mut total, + out_weight * (e_in[2 * pair] + e_in[2 * pair + 1]), + factors, + base_pair + pair, + gamma, + gamma2, + ); + } + } + total.reduce() + } +} + +fn registers_high_round_constant( + factors: &[Vec], + in_weight: F, + e_out: &[F], + gamma: F, + gamma2: F, +) -> F { + let pairs = e_out.len() / 2; + if pairs >= DENSE_BIND_PAR_THRESHOLD { + (0..pairs) + .into_par_iter() + .map(|pair| { + let mut local = F::Accumulator::default(); + accumulate_register_constant( + &mut local, + in_weight * (e_out[2 * pair] + e_out[2 * pair + 1]), + factors, + pair, + gamma, + gamma2, + ); + local + }) + .reduce(F::Accumulator::default, |mut left, right| { + left.merge(right); + left + }) + .reduce() + } else { + let mut total = F::Accumulator::default(); + for pair in 0..pairs { + accumulate_register_constant( + &mut total, + in_weight * (e_out[2 * pair] + e_out[2 * pair + 1]), + factors, + pair, + gamma, + gamma2, + ); + } + total.reduce() + } +} + +fn accumulate_register_constant( + accumulator: &mut F::Accumulator, + weight: F, + factors: &[Vec], + row: usize, + gamma: F, + gamma2: F, +) { + accumulator.fmadd(weight, factors[0][2 * row]); + accumulator.fmadd(weight * gamma, factors[1][2 * row]); + accumulator.fmadd(weight * gamma2, factors[2][2 * row]); +} + +fn gruen_cubic_poly( + target: F, + q_constant: F, + q_quadratic_coeff: F, + previous_claim: F, +) -> UnivariatePoly { + let eq_eval_1 = target; + let eq_eval_0 = F::one() - target; + let eq_delta = eq_eval_1 - eq_eval_0; + let eq_eval_2 = eq_eval_1 + eq_delta; + let eq_eval_3 = eq_eval_2 + eq_delta; + let cubic_eval_0 = eq_eval_0 * q_constant; + let cubic_eval_1 = previous_claim - cubic_eval_0; + let quadratic_eval_1 = cubic_eval_1 / eq_eval_1; + let e_times_2 = q_quadratic_coeff + q_quadratic_coeff; + let quadratic_eval_2 = quadratic_eval_1 + quadratic_eval_1 - q_constant + e_times_2; + let quadratic_eval_3 = quadratic_eval_2 + quadratic_eval_1 - q_constant + e_times_2 + e_times_2; + UnivariatePoly::from_evals(&[ + cubic_eval_0, + cubic_eval_1, + eq_eval_2 * quadratic_eval_2, + eq_eval_3 * quadratic_eval_3, + ]) +} + +fn gruen_quadratic_poly( + target: F, + q_constant: F, + previous_claim: F, +) -> UnivariatePoly { + let eq_eval_1 = target; + let eq_eval_0 = F::one() - target; + let eq_delta = eq_eval_1 - eq_eval_0; + let eq_eval_2 = eq_eval_1 + eq_delta; + let quadratic_eval_0 = eq_eval_0 * q_constant; + let quadratic_eval_1 = previous_claim - quadratic_eval_0; + let linear_eval_1 = quadratic_eval_1 / eq_eval_1; + let linear_eval_2 = linear_eval_1 + linear_eval_1 - q_constant; + UnivariatePoly::from_evals(&[ + quadratic_eval_0, + quadratic_eval_1, + eq_eval_2 * linear_eval_2, + ]) +} + +fn round_poly_from_stage3_coefficients( + half: usize, + degree: usize, + coefficients: C, +) -> UnivariatePoly +where + F: Field, + C: Fn(usize, &mut [F::Accumulator; 4]) + Sync, +{ + let accumulators = if half >= DENSE_BIND_PAR_THRESHOLD { + (0..half) + .into_par_iter() + .map(|row| { + let mut local = [F::Accumulator::default(); 4]; + coefficients(row, &mut local); + local + }) + .reduce( + || [F::Accumulator::default(); 4], + |mut left, right| { + for index in 0..left.len() { + left[index].merge(right[index]); + } + left + }, + ) + } else { + (0..half).fold([F::Accumulator::default(); 4], |mut total, row| { + coefficients(row, &mut total); + total + }) + }; + UnivariatePoly::new( + accumulators[..=degree] + .iter() + .copied() + .map(FieldAccumulator::reduce) + .collect(), + ) +} + +#[inline] +fn linear_pair(factor: &[F], row: usize) -> (F, F) { + let low = factor[2 * row]; + (low, factor[2 * row + 1] - low) +} + +#[inline] +fn accumulate_linear_product( + acc: &mut [F::Accumulator; 4], + scale: F, + left_0: F, + left_delta: F, + right_0: F, + right_delta: F, +) { + acc[0].fmadd(scale * left_0, right_0); + acc[1].fmadd(scale * left_delta, right_0); + acc[1].fmadd(scale * left_0, right_delta); + acc[2].fmadd(scale * left_delta, right_delta); +} + +#[inline] +fn bind_dense_evals_reuse_serial( + values: &mut Vec, + scratch: &mut Vec, + challenge: F, +) { + let half = values.len() / 2; + scratch.resize(half, F::zero()); + for (index, output) in scratch.iter_mut().enumerate() { + let low = values[index << 1]; + let high = values[(index << 1) + 1]; + *output = low + challenge * (high - low); + } + std::mem::swap(values, scratch); + scratch.clear(); +} + +fn polynomial_degree(poly: &UnivariatePoly) -> usize { + poly.coefficients() + .iter() + .rposition(|coefficient| *coefficient != F::zero()) + .unwrap_or(0) +} + +fn append_compressed_univariate_poly( + transcript: &mut T, + label: &'static str, + poly: &UnivariatePoly, +) where + F: Field, + T: Transcript, +{ + let compressed = poly.compress(); + transcript.append(&LabelWithCount( + label.as_bytes(), + compressed.coeffs_except_linear_term().len() as u64, + )); + for coefficient in compressed.coeffs_except_linear_term() { + transcript.append(coefficient); + } +} + +fn append_labeled_scalar(transcript: &mut T, label: &'static str, scalar: &F) +where + F: Field, + T: Transcript, +{ + transcript.append(&Label(label.as_bytes())); + transcript.append(scalar); +} + +fn append_opening_claims( + program: &'static Stage3CpuProgramPlan, + store: &mut Stage3ValueStore, + transcript: &mut T, + evals: &[Stage3NamedEval], +) -> Result>, Stage3KernelError> +where + F: Field, + T: Transcript, +{ + if program.opening_batches.is_empty() { + for eval in evals { + append_labeled_scalar(transcript, "opening_claim", &eval.value); + } + return Ok(Vec::new()); + } + let _ = store.evaluate_available_points(program)?; + let mut opening_claims = Vec::new(); + let mut seen = seed_stage3_opening_aliases(store, program); + for batch in program.opening_batches { + for symbol in batch.claim_operands { + let claim = + find_opening_claim(program, symbol).ok_or(Stage3KernelError::MissingClaim { + batch: batch.symbol, + claim: symbol, + })?; + let point = store.point(claim.point_source)?.to_vec(); + let value = store.scalar(claim.eval_source)?; + let duplicate = has_seen_opening(&seen, claim.claim_kind, claim.oracle, &point); + if !duplicate { + append_labeled_scalar(transcript, "opening_claim", &value); + seen.push((claim.claim_kind, claim.oracle, point.clone())); + } + opening_claims.push(Stage3OpeningClaimValue { + symbol: claim.symbol, + oracle: claim.oracle, + domain: claim.domain, + claim_kind: claim.claim_kind, + point: point.clone(), + eval: value, + }); + } + } + Ok(opening_claims) +} + +fn seed_stage3_opening_aliases( + store: &Stage3ValueStore, + program: &'static Stage3CpuProgramPlan, +) -> Vec<(&'static str, &'static str, Vec)> { + program + .opening_inputs + .iter() + .filter_map(|input| { + store + .try_point(input.symbol) + .map(|point| (input.claim_kind, input.oracle, point.to_vec())) + }) + .collect() +} + +fn has_seen_opening( + seen: &[(&'static str, &'static str, Vec)], + claim_kind: &'static str, + oracle: &'static str, + point: &[F], +) -> bool { + seen.iter().any(|(seen_kind, seen_oracle, seen_point)| { + *seen_kind == claim_kind && *seen_oracle == oracle && seen_point.as_slice() == point + }) +} + +fn find_opening_claim<'a>( + program: &'a Stage3CpuProgramPlan, + symbol: &str, +) -> Option<&'a Stage3OpeningClaimPlan> { + program + .opening_claims + .iter() + .find(|claim| claim.symbol == symbol) +} + +pub fn execute_stage3_program( + program: &'static Stage3CpuProgramPlan, + mode: Stage3ExecutionMode, + executor: &mut E, + transcript: &mut T, +) -> Result, Stage3KernelError> +where + F: Field, + E: Stage3KernelExecutor, + T: Transcript, +{ + verify_static_program_shape(program)?; + let mut artifacts = Stage3ExecutionArtifacts::default(); + for step in program.steps { + match step.kind { + "transcript_squeeze" => { + let squeeze = find_transcript_squeeze(program, step.symbol).ok_or( + Stage3KernelError::MissingValue { + symbol: step.symbol, + }, + )?; + execute_stage3_squeeze(squeeze, executor, transcript, &mut artifacts)?; + } + "sumcheck_driver" => { + let driver = + find_driver(program, step.symbol).ok_or(Stage3KernelError::MissingKernel { + driver: step.symbol, + kernel: step.symbol, + })?; + execute_stage3_driver(program, mode, driver, executor, transcript, &mut artifacts)?; + } + _ => { + return Err(Stage3KernelError::InvalidProof { + driver: step.symbol, + reason: "unsupported stage3 program step", + }); + } + } + } + artifacts + .opening_batches + .extend(program.opening_batches.iter()); + Ok(artifacts) +} + +fn execute_stage3_squeeze( + squeeze: &'static Stage3TranscriptSqueezePlan, + executor: &mut E, + transcript: &mut T, + artifacts: &mut Stage3ExecutionArtifacts, +) -> Result<(), Stage3KernelError> +where + F: Field, + E: Stage3KernelExecutor, + T: Transcript, +{ + let values = transcript.challenge_vector(squeeze.count); + executor.observe_challenge_vector(squeeze, &values)?; + artifacts.challenge_vectors.push(Stage3ChallengeVector { + symbol: squeeze.symbol, + values, + }); + Ok(()) +} + +fn execute_stage3_driver( + program: &'static Stage3CpuProgramPlan, + mode: Stage3ExecutionMode, + driver: &'static Stage3SumcheckDriverPlan, + executor: &mut E, + transcript: &mut T, + artifacts: &mut Stage3ExecutionArtifacts, +) -> Result<(), Stage3KernelError> +where + F: Field, + E: Stage3KernelExecutor, + T: Transcript, +{ + let kernel_symbol = driver.kernel.ok_or(Stage3KernelError::MissingKernel { + driver: driver.symbol, + kernel: "", + })?; + let kernel = find_kernel(program, kernel_symbol).ok_or(Stage3KernelError::MissingKernel { + driver: driver.symbol, + kernel: kernel_symbol, + })?; + let batch = find_batch(program, driver.batch).ok_or(Stage3KernelError::MissingBatch { + driver: driver.symbol, + batch: driver.batch, + })?; + let context = Stage3KernelContext { + mode, + program, + kernel, + batch, + driver, + }; + let output = match mode { + Stage3ExecutionMode::Prover => executor.prove_sumcheck(context, transcript)?, + Stage3ExecutionMode::Verifier => executor.verify_sumcheck(context, transcript)?, + }; + executor.observe_sumcheck_output(&output)?; + artifacts + .opening_claims + .extend(output.opening_claims.clone()); + artifacts.sumchecks.push(output); + Ok(()) +} + +fn verify_static_program_shape( + program: &'static Stage3CpuProgramPlan, +) -> Result<(), Stage3KernelError> { + for expr in program.field_exprs { + verify_count(expr.symbol, expr.operand_names.len(), expr.operands.len())?; + } + for batch in program.batches { + verify_count(batch.symbol, batch.count, batch.ordered_claims.len())?; + verify_count(batch.symbol, batch.count, batch.claim_operands.len())?; + } + for batch in program.opening_batches { + verify_count(batch.symbol, batch.count, batch.ordered_claims.len())?; + verify_count(batch.symbol, batch.count, batch.claim_operands.len())?; + } + for kernel in program.kernels { + let relation = kernel.relation_kind()?; + let abi = kernel.abi_kind()?; + if relation + .symbol() + .replace("jolt.stage3.", "jolt_stage3_") + .replace('.', "_") + != abi.name() + { + return Err(Stage3KernelError::InvalidProof { + driver: kernel.symbol, + reason: "kernel relation and ABI mismatch", + }); + } + } + Ok(()) +} + +fn verify_count( + artifact: &'static str, + expected: usize, + actual: usize, +) -> Result<(), Stage3KernelError> { + if expected == actual { + Ok(()) + } else { + Err(Stage3KernelError::PlanCountMismatch { + artifact, + expected, + actual, + }) + } +} + +fn find_kernel<'a>( + program: &'a Stage3CpuProgramPlan, + symbol: &str, +) -> Option<&'a Stage3KernelPlan> { + program + .kernels + .iter() + .find(|kernel| kernel.symbol == symbol) +} + +fn find_batch<'a>( + program: &'a Stage3CpuProgramPlan, + symbol: &str, +) -> Option<&'a Stage3SumcheckBatchPlan> { + program.batches.iter().find(|batch| batch.symbol == symbol) +} + +fn find_driver<'a>( + program: &'a Stage3CpuProgramPlan, + symbol: &str, +) -> Option<&'a Stage3SumcheckDriverPlan> { + program + .drivers + .iter() + .find(|driver| driver.symbol == symbol) +} + +fn find_transcript_squeeze<'a>( + program: &'a Stage3CpuProgramPlan, + symbol: &str, +) -> Option<&'a Stage3TranscriptSqueezePlan> { + program + .transcript_squeezes + .iter() + .find(|squeeze| squeeze.symbol == symbol) +} + +#[cfg(test)] +#[expect(clippy::expect_used, reason = "stage3 kernel tests fail fast")] +mod tests { + use super::*; + use jolt_field::Fr; + use jolt_transcript::Blake2bTranscript; + + #[test] + fn stage3_relation_and_abi_registry_is_complete() { + let relations = [ + Stage3Relation::SpartanShift, + Stage3Relation::InstructionInput, + Stage3Relation::RegistersClaimReduction, + Stage3Relation::Batched, + ]; + for relation in relations { + assert_eq!( + Stage3Relation::from_symbol(relation.symbol()), + Some(relation) + ); + } + + let abis = [ + Stage3KernelAbi::SpartanShift, + Stage3KernelAbi::InstructionInput, + Stage3KernelAbi::RegistersClaimReduction, + Stage3KernelAbi::Batched, + ]; + for abi in abis { + assert_eq!(Stage3KernelAbi::from_name(abi.name()), Some(abi)); + } + } + + #[test] + fn stage3_batched_kernel_proves_and_verifies_synthetic_trace() { + let program = synthetic_stage3_program(); + let cycles = synthetic_cycles(); + let opening_inputs = synthetic_opening_inputs(&cycles); + let prover_inputs = Stage3ProverInputs::new(&opening_inputs).with_cycles(&cycles); + let mut prover = Stage3ProverKernelExecutor::new(prover_inputs); + let mut prover_transcript = Blake2bTranscript::::new(b"stage3_test"); + + let artifacts = execute_stage3_program( + program, + Stage3ExecutionMode::Prover, + &mut prover, + &mut prover_transcript, + ) + .expect("stage3 prover succeeds"); + + assert_eq!(artifacts.sumchecks.len(), 1); + assert_eq!(artifacts.sumchecks[0].proof.round_polynomials.len(), 2); + let proof = Stage3Proof::from(artifacts); + let mut verifier = Stage3VerifierKernelExecutor::new(&proof, &opening_inputs); + let mut verifier_transcript = Blake2bTranscript::::new(b"stage3_test"); + let verified = execute_stage3_program( + program, + Stage3ExecutionMode::Verifier, + &mut verifier, + &mut verifier_transcript, + ) + .expect("stage3 verifier accepts prover proof"); + + assert_eq!(verified.sumchecks.len(), 1); + assert_eq!(prover_transcript.state(), verifier_transcript.state()); + } + + #[test] + fn stage3_batched_kernel_rejects_tampered_eval() { + let program = synthetic_stage3_program(); + let cycles = synthetic_cycles(); + let opening_inputs = synthetic_opening_inputs(&cycles); + let mut prover = Stage3ProverKernelExecutor::new( + Stage3ProverInputs::new(&opening_inputs).with_cycles(&cycles), + ); + let mut prover_transcript = Blake2bTranscript::::new(b"stage3_test"); + let mut proof = Stage3Proof::from( + execute_stage3_program( + program, + Stage3ExecutionMode::Prover, + &mut prover, + &mut prover_transcript, + ) + .expect("stage3 prover succeeds"), + ); + proof.sumchecks[0].evals[0].value += Fr::from_u64(1); + + let mut verifier = Stage3VerifierKernelExecutor::new(&proof, &opening_inputs); + let mut verifier_transcript = Blake2bTranscript::::new(b"stage3_test"); + let error = execute_stage3_program( + program, + Stage3ExecutionMode::Verifier, + &mut verifier, + &mut verifier_transcript, + ) + .expect_err("tampered proof is rejected"); + + assert!(matches!(error, Stage3KernelError::InvalidProof { .. })); + } + + fn synthetic_stage3_program() -> &'static Stage3CpuProgramPlan { + let exprs = leak_slice(vec![ + field_expr( + "stage3.spartan_shift.gamma2", + "field.pow:2", + vec!["stage3.spartan_shift.gamma"], + ), + field_expr( + "stage3.spartan_shift.gamma3", + "field.mul", + vec!["stage3.spartan_shift.gamma2", "stage3.spartan_shift.gamma"], + ), + field_expr( + "stage3.spartan_shift.gamma4", + "field.mul", + vec!["stage3.spartan_shift.gamma2", "stage3.spartan_shift.gamma2"], + ), + field_expr( + "stage3.spartan_shift.term.NextPC", + "field.mul", + vec!["stage3.spartan_shift.gamma", "stage3.input.stage1.NextPC"], + ), + field_expr( + "stage3.spartan_shift.term.NextIsVirtual", + "field.mul", + vec![ + "stage3.spartan_shift.gamma2", + "stage3.input.stage1.NextIsVirtual", + ], + ), + field_expr( + "stage3.spartan_shift.term.NextIsFirstInSequence", + "field.mul", + vec![ + "stage3.spartan_shift.gamma3", + "stage3.input.stage1.NextIsFirstInSequence", + ], + ), + field_expr( + "stage3.spartan_shift.one_minus.NextIsNoop", + "field.sub", + vec![ + "stage3.field.one", + "stage3.input.stage2.product_virtual.NextIsNoop", + ], + ), + field_expr( + "stage3.spartan_shift.term.NextIsNoop", + "field.mul", + vec![ + "stage3.spartan_shift.gamma4", + "stage3.spartan_shift.one_minus.NextIsNoop", + ], + ), + field_expr( + "stage3.spartan_shift.partial.NextUnexpandedPCNextPC", + "field.add", + vec![ + "stage3.input.stage1.NextUnexpandedPC", + "stage3.spartan_shift.term.NextPC", + ], + ), + field_expr( + "stage3.spartan_shift.partial.NextIsVirtual", + "field.add", + vec![ + "stage3.spartan_shift.partial.NextUnexpandedPCNextPC", + "stage3.spartan_shift.term.NextIsVirtual", + ], + ), + field_expr( + "stage3.spartan_shift.partial.NextIsFirstInSequence", + "field.add", + vec![ + "stage3.spartan_shift.partial.NextIsVirtual", + "stage3.spartan_shift.term.NextIsFirstInSequence", + ], + ), + field_expr( + "stage3.spartan_shift.claim_expr", + "field.add", + vec![ + "stage3.spartan_shift.partial.NextIsFirstInSequence", + "stage3.spartan_shift.term.NextIsNoop", + ], + ), + field_expr( + "stage3.instruction_input.term.LeftInstructionInput", + "field.mul", + vec![ + "stage3.instruction_input.gamma", + "stage3.input.stage2.product_virtual.LeftInstructionInput", + ], + ), + field_expr( + "stage3.instruction_input.claim_expr", + "field.add", + vec![ + "stage3.input.stage2.product_virtual.RightInstructionInput", + "stage3.instruction_input.term.LeftInstructionInput", + ], + ), + field_expr( + "stage3.registers.gamma2", + "field.pow:2", + vec!["stage3.registers.gamma"], + ), + field_expr( + "stage3.registers.term.Rs1Value", + "field.mul", + vec!["stage3.registers.gamma", "stage3.input.stage1.Rs1Value"], + ), + field_expr( + "stage3.registers.term.Rs2Value", + "field.mul", + vec!["stage3.registers.gamma2", "stage3.input.stage1.Rs2Value"], + ), + field_expr( + "stage3.registers.partial.RdWriteValueRs1Value", + "field.add", + vec![ + "stage3.input.stage1.RdWriteValue", + "stage3.registers.term.Rs1Value", + ], + ), + field_expr( + "stage3.registers.claim_expr", + "field.add", + vec![ + "stage3.registers.partial.RdWriteValueRs1Value", + "stage3.registers.term.Rs2Value", + ], + ), + ]); + + Box::leak(Box::new(Stage3CpuProgramPlan { + params: Stage3Params { + field: "bn254_fr", + pcs: "dory", + transcript: "blake2b_transcript", + }, + steps: leak_slice(vec![ + Stage3ProgramStepPlan { + kind: "transcript_squeeze", + symbol: "stage3.spartan_shift.gamma", + }, + Stage3ProgramStepPlan { + kind: "transcript_squeeze", + symbol: "stage3.instruction_input.gamma", + }, + Stage3ProgramStepPlan { + kind: "transcript_squeeze", + symbol: "stage3.registers.gamma", + }, + Stage3ProgramStepPlan { + kind: "sumcheck_driver", + symbol: "stage3.sumcheck", + }, + ]), + transcript_squeezes: leak_slice(vec![ + Stage3TranscriptSqueezePlan { + symbol: "stage3.spartan_shift.gamma", + label: "spartan_shift_gamma", + kind: "challenge_scalar", + count: 1, + }, + Stage3TranscriptSqueezePlan { + symbol: "stage3.instruction_input.gamma", + label: "instruction_input_gamma", + kind: "challenge_scalar", + count: 1, + }, + Stage3TranscriptSqueezePlan { + symbol: "stage3.registers.gamma", + label: "registers_gamma", + kind: "challenge_scalar", + count: 1, + }, + ]), + opening_inputs: leak_slice(stage3_opening_input_plans()), + field_constants: leak_slice(vec![Stage3FieldConstantPlan { + symbol: "stage3.field.one", + field: "bn254_fr", + value: 1, + }]), + field_exprs: exprs, + kernels: leak_slice(vec![ + kernel( + "jolt.cpu.stage3.spartan_shift", + "jolt.stage3.spartan_shift", + "jolt_stage3_spartan_shift", + ), + kernel( + "jolt.cpu.stage3.instruction_input", + "jolt.stage3.instruction_input", + "jolt_stage3_instruction_input", + ), + kernel( + "jolt.cpu.stage3.registers_claim_reduction", + "jolt.stage3.registers_claim_reduction", + "jolt_stage3_registers_claim_reduction", + ), + kernel( + "jolt.cpu.stage3.batched", + "jolt.stage3.batched", + "jolt_stage3_batched", + ), + ]), + claims: leak_slice(vec![ + claim( + "stage3.spartan_shift.input", + "jolt.cpu.stage3.spartan_shift", + "stage3.spartan_shift.claim_expr", + 2, + vec![ + "stage3.input.stage1.NextUnexpandedPC", + "stage3.input.stage1.NextPC", + "stage3.input.stage1.NextIsVirtual", + "stage3.input.stage1.NextIsFirstInSequence", + "stage3.input.stage2.product_virtual.NextIsNoop", + ], + ), + claim( + "stage3.instruction_input.input", + "jolt.cpu.stage3.instruction_input", + "stage3.instruction_input.claim_expr", + 3, + vec![ + "stage3.input.stage2.product_virtual.RightInstructionInput", + "stage3.input.stage2.product_virtual.LeftInstructionInput", + ], + ), + claim( + "stage3.registers_claim_reduction.input", + "jolt.cpu.stage3.registers_claim_reduction", + "stage3.registers.claim_expr", + 2, + vec![ + "stage3.input.stage1.RdWriteValue", + "stage3.input.stage1.Rs1Value", + "stage3.input.stage1.Rs2Value", + ], + ), + ]), + batches: leak_slice(vec![Stage3SumcheckBatchPlan { + symbol: "stage3.batch", + stage: "stage3", + proof_slot: "stage3.sumcheck", + policy: "jolt_core_stage3_aligned", + count: 3, + ordered_claims: leak_slice(vec![ + "stage3.spartan_shift.input", + "stage3.instruction_input.input", + "stage3.registers_claim_reduction.input", + ]), + claim_operands: leak_slice(vec![ + "stage3.spartan_shift.input", + "stage3.instruction_input.input", + "stage3.registers_claim_reduction.input", + ]), + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + round_schedule: leak_slice(vec![2]), + }]), + drivers: leak_slice(vec![Stage3SumcheckDriverPlan { + symbol: "stage3.sumcheck", + stage: "stage3", + proof_slot: "stage3.sumcheck", + kernel: Some("jolt.cpu.stage3.batched"), + relation: None, + batch: "stage3.batch", + policy: "jolt_core_stage3_aligned", + round_schedule: leak_slice(vec![2]), + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + num_rounds: 2, + degree: 3, + }]), + instance_results: leak_slice(vec![ + instance( + "stage3.spartan_shift.instance", + "stage3.spartan_shift.input", + "jolt.stage3.spartan_shift", + 0, + 2, + ), + instance( + "stage3.instruction_input.instance", + "stage3.instruction_input.input", + "jolt.stage3.instruction_input", + 1, + 3, + ), + instance( + "stage3.registers_claim_reduction.instance", + "stage3.registers_claim_reduction.input", + "jolt.stage3.registers_claim_reduction", + 2, + 2, + ), + ]), + evals: leak_slice(stage3_eval_plans()), + point_slices: &[], + point_concats: &[], + opening_claims: leak_slice(stage3_opening_claim_plans()), + opening_equalities: leak_slice(vec![ + Stage3OpeningClaimEqualityPlan { + symbol: "stage3.instruction_input.left_claim_consistency", + mode: "point_and_eval", + lhs: "stage3.input.stage2.product_virtual.LeftInstructionInput", + rhs: "stage3.input.stage2.instruction_lookup.LeftInstructionInput", + }, + Stage3OpeningClaimEqualityPlan { + symbol: "stage3.instruction_input.right_claim_consistency", + mode: "point_and_eval", + lhs: "stage3.input.stage2.product_virtual.RightInstructionInput", + rhs: "stage3.input.stage2.instruction_lookup.RightInstructionInput", + }, + ]), + opening_batches: leak_slice(vec![Stage3OpeningBatchPlan { + symbol: "stage3.openings", + stage: "stage3", + proof_slot: "stage3.openings", + policy: "jolt_stage3_output_order", + count: 16, + ordered_claims: leak_slice( + stage3_opening_claim_plans() + .iter() + .map(|claim| claim.symbol) + .collect(), + ), + claim_operands: leak_slice( + stage3_opening_claim_plans() + .iter() + .map(|claim| claim.symbol) + .collect(), + ), + }]), + })) + } + + fn synthetic_cycles() -> [Stage3Cycle; 4] { + [ + Stage3Cycle { + unexpanded_pc: 10, + pc: 0, + is_virtual: false, + is_first_in_sequence: false, + is_noop: false, + left_operand_is_rs1: true, + rs1_value: 3, + left_operand_is_pc: false, + right_operand_is_rs2: true, + rs2_value: 5, + right_operand_is_imm: false, + imm: 0, + rd_write_value: 8, + }, + Stage3Cycle { + unexpanded_pc: 14, + pc: 1, + is_virtual: true, + is_first_in_sequence: true, + is_noop: false, + left_operand_is_rs1: false, + rs1_value: 0, + left_operand_is_pc: true, + right_operand_is_rs2: false, + rs2_value: 0, + right_operand_is_imm: true, + imm: -7, + rd_write_value: 21, + }, + Stage3Cycle { + unexpanded_pc: 18, + pc: 2, + is_virtual: false, + is_first_in_sequence: false, + is_noop: true, + left_operand_is_rs1: false, + rs1_value: 0, + left_operand_is_pc: false, + right_operand_is_rs2: false, + rs2_value: 0, + right_operand_is_imm: false, + imm: 0, + rd_write_value: 0, + }, + Stage3Cycle { + unexpanded_pc: 22, + pc: 3, + is_virtual: true, + is_first_in_sequence: false, + is_noop: false, + left_operand_is_rs1: true, + rs1_value: 9, + left_operand_is_pc: false, + right_operand_is_rs2: false, + rs2_value: 0, + right_operand_is_imm: true, + imm: 11, + rd_write_value: 20, + }, + ] + } + + fn synthetic_opening_inputs(cycles: &[Stage3Cycle]) -> Vec> { + let r_outer = vec![Fr::from_u64(2), Fr::from_u64(3)]; + let r_product = vec![Fr::from_u64(5), Fr::from_u64(7)]; + let r_instruction = vec![Fr::from_u64(11), Fr::from_u64(13)]; + let r_registers = vec![Fr::from_u64(17), Fr::from_u64(19)]; + vec![ + opening( + "stage3.input.stage1.NextUnexpandedPC", + &r_outer, + eq_plus_one_eval(cycles, &r_outer, |cycle| Fr::from_u64(cycle.unexpanded_pc)), + ), + opening( + "stage3.input.stage1.NextPC", + &r_outer, + eq_plus_one_eval(cycles, &r_outer, |cycle| Fr::from_u64(cycle.pc)), + ), + opening( + "stage3.input.stage1.NextIsVirtual", + &r_outer, + eq_plus_one_eval(cycles, &r_outer, |cycle| Fr::from_bool(cycle.is_virtual)), + ), + opening( + "stage3.input.stage1.NextIsFirstInSequence", + &r_outer, + eq_plus_one_eval(cycles, &r_outer, |cycle| { + Fr::from_bool(cycle.is_first_in_sequence) + }), + ), + opening( + "stage3.input.stage2.product_virtual.NextIsNoop", + &r_product, + eq_plus_one_eval(cycles, &r_product, |cycle| Fr::from_bool(cycle.is_noop)) + + r_product.iter().copied().product::(), + ), + opening( + "stage3.input.stage2.product_virtual.LeftInstructionInput", + &r_instruction, + mle_eval(cycles, &r_instruction, left_instruction_input), + ), + opening( + "stage3.input.stage2.product_virtual.RightInstructionInput", + &r_instruction, + mle_eval(cycles, &r_instruction, right_instruction_input), + ), + opening( + "stage3.input.stage2.instruction_lookup.LeftInstructionInput", + &r_instruction, + mle_eval(cycles, &r_instruction, left_instruction_input), + ), + opening( + "stage3.input.stage2.instruction_lookup.RightInstructionInput", + &r_instruction, + mle_eval(cycles, &r_instruction, right_instruction_input), + ), + opening( + "stage3.input.stage1.RdWriteValue", + &r_registers, + mle_eval(cycles, &r_registers, |cycle| { + Fr::from_u64(cycle.rd_write_value) + }), + ), + opening( + "stage3.input.stage1.Rs1Value", + &r_registers, + mle_eval(cycles, &r_registers, |cycle| Fr::from_u64(cycle.rs1_value)), + ), + opening( + "stage3.input.stage1.Rs2Value", + &r_registers, + mle_eval(cycles, &r_registers, |cycle| Fr::from_u64(cycle.rs2_value)), + ), + ] + } + + fn field_expr( + symbol: &'static str, + formula: &'static str, + operands: Vec<&'static str>, + ) -> Stage3FieldExprPlan { + let operands = leak_slice(operands); + Stage3FieldExprPlan { + symbol, + kind: "op", + formula, + operand_names: operands, + operands, + } + } + + fn kernel(symbol: &'static str, relation: &'static str, abi: &'static str) -> Stage3KernelPlan { + Stage3KernelPlan { + symbol, + relation, + kind: "sumcheck", + backend: "cpu", + abi, + } + } + + fn claim( + symbol: &'static str, + kernel: &'static str, + claim_value: &'static str, + degree: usize, + input_openings: Vec<&'static str>, + ) -> Stage3SumcheckClaimPlan { + Stage3SumcheckClaimPlan { + symbol, + stage: "stage3", + domain: "jolt.trace_domain", + num_rounds: 2, + degree, + claim: symbol, + kernel: Some(kernel), + relation: None, + claim_value, + input_openings: leak_slice(input_openings), + } + } + + fn instance( + symbol: &'static str, + claim: &'static str, + relation: &'static str, + index: usize, + degree: usize, + ) -> Stage3SumcheckInstanceResultPlan { + Stage3SumcheckInstanceResultPlan { + symbol, + source: "stage3.sumcheck", + claim, + relation, + index, + point_arity: 2, + num_rounds: 2, + round_offset: 0, + point_order: "reverse", + degree, + } + } + + fn opening(symbol: &'static str, point: &[Fr], eval: Fr) -> Stage3OpeningInputValue { + Stage3OpeningInputValue { + symbol, + point: point.to_vec(), + eval, + } + } + + fn mle_eval(cycles: &[Stage3Cycle], point: &[Fr], f: impl Fn(&Stage3Cycle) -> Fr) -> Fr { + EqPolynomial::::evals(point, None) + .iter() + .zip(cycles) + .map(|(&weight, cycle)| weight * f(cycle)) + .sum() + } + + fn eq_plus_one_eval( + cycles: &[Stage3Cycle], + point: &[Fr], + f: impl Fn(&Stage3Cycle) -> Fr, + ) -> Fr { + EqPlusOnePolynomial::::evals(point, None) + .1 + .iter() + .zip(cycles) + .map(|(&weight, cycle)| weight * f(cycle)) + .sum() + } + + fn left_instruction_input(cycle: &Stage3Cycle) -> Fr { + Fr::from_bool(cycle.left_operand_is_rs1) * Fr::from_u64(cycle.rs1_value) + + Fr::from_bool(cycle.left_operand_is_pc) * Fr::from_u64(cycle.unexpanded_pc) + } + + fn right_instruction_input(cycle: &Stage3Cycle) -> Fr { + Fr::from_bool(cycle.right_operand_is_rs2) * Fr::from_u64(cycle.rs2_value) + + Fr::from_bool(cycle.right_operand_is_imm) * Fr::from_i128(cycle.imm) + } + + fn stage3_opening_input_plans() -> Vec { + vec![ + opening_input_plan( + "stage3.input.stage1.NextUnexpandedPC", + "stage1", + "NextUnexpandedPC", + ), + opening_input_plan("stage3.input.stage1.NextPC", "stage1", "NextPC"), + opening_input_plan( + "stage3.input.stage1.NextIsVirtual", + "stage1", + "NextIsVirtual", + ), + opening_input_plan( + "stage3.input.stage1.NextIsFirstInSequence", + "stage1", + "NextIsFirstInSequence", + ), + opening_input_plan( + "stage3.input.stage2.product_virtual.NextIsNoop", + "stage2", + "NextIsNoop", + ), + opening_input_plan( + "stage3.input.stage2.product_virtual.LeftInstructionInput", + "stage2", + "LeftInstructionInput", + ), + opening_input_plan( + "stage3.input.stage2.product_virtual.RightInstructionInput", + "stage2", + "RightInstructionInput", + ), + opening_input_plan( + "stage3.input.stage2.instruction_lookup.LeftInstructionInput", + "stage2", + "LeftInstructionInput", + ), + opening_input_plan( + "stage3.input.stage2.instruction_lookup.RightInstructionInput", + "stage2", + "RightInstructionInput", + ), + opening_input_plan("stage3.input.stage1.RdWriteValue", "stage1", "RdWriteValue"), + opening_input_plan("stage3.input.stage1.Rs1Value", "stage1", "Rs1Value"), + opening_input_plan("stage3.input.stage1.Rs2Value", "stage1", "Rs2Value"), + ] + } + + fn opening_input_plan( + symbol: &'static str, + source_stage: &'static str, + oracle: &'static str, + ) -> Stage3OpeningInputPlan { + Stage3OpeningInputPlan { + symbol, + source_stage, + source_claim: symbol, + oracle, + domain: "jolt.trace_domain", + point_arity: 2, + claim_kind: "virtual", + } + } + + fn stage3_eval_plans() -> Vec { + vec![ + eval("stage3.spartan_shift.eval.UnexpandedPC", "UnexpandedPC", 0), + eval("stage3.spartan_shift.eval.PC", "PC", 1), + eval( + "stage3.spartan_shift.eval.OpFlagVirtualInstruction", + "OpFlagVirtualInstruction", + 2, + ), + eval( + "stage3.spartan_shift.eval.OpFlagIsFirstInSequence", + "OpFlagIsFirstInSequence", + 3, + ), + eval( + "stage3.spartan_shift.eval.InstructionFlagIsNoop", + "InstructionFlagIsNoop", + 4, + ), + eval( + "stage3.instruction_input.eval.InstructionFlagLeftOperandIsRs1Value", + "InstructionFlagLeftOperandIsRs1Value", + 5, + ), + eval("stage3.instruction_input.eval.Rs1Value", "Rs1Value", 6), + eval( + "stage3.instruction_input.eval.InstructionFlagLeftOperandIsPC", + "InstructionFlagLeftOperandIsPC", + 7, + ), + eval( + "stage3.instruction_input.eval.UnexpandedPC", + "UnexpandedPC", + 8, + ), + eval( + "stage3.instruction_input.eval.InstructionFlagRightOperandIsRs2Value", + "InstructionFlagRightOperandIsRs2Value", + 9, + ), + eval("stage3.instruction_input.eval.Rs2Value", "Rs2Value", 10), + eval( + "stage3.instruction_input.eval.InstructionFlagRightOperandIsImm", + "InstructionFlagRightOperandIsImm", + 11, + ), + eval("stage3.instruction_input.eval.Imm", "Imm", 12), + eval( + "stage3.registers_claim_reduction.eval.RdWriteValue", + "RdWriteValue", + 13, + ), + eval( + "stage3.registers_claim_reduction.eval.Rs1Value", + "Rs1Value", + 14, + ), + eval( + "stage3.registers_claim_reduction.eval.Rs2Value", + "Rs2Value", + 15, + ), + ] + } + + fn eval(symbol: &'static str, oracle: &'static str, index: usize) -> Stage3SumcheckEvalPlan { + Stage3SumcheckEvalPlan { + symbol, + source: "stage3.sumcheck", + name: symbol, + index, + oracle, + } + } + + fn stage3_opening_claim_plans() -> Vec { + stage3_eval_plans() + .into_iter() + .map(|eval| Stage3OpeningClaimPlan { + symbol: eval.symbol.replace(".eval.", ".opening.").leak(), + oracle: eval.oracle, + domain: "jolt.trace_domain", + point_arity: 2, + claim_kind: "virtual", + point_source: match eval.symbol { + name if name.starts_with("stage3.spartan_shift.") => { + "stage3.spartan_shift.instance" + } + name if name.starts_with("stage3.instruction_input.") => { + "stage3.instruction_input.instance" + } + _ => "stage3.registers_claim_reduction.instance", + }, + eval_source: eval.symbol, + }) + .collect() + } + + fn leak_slice(values: Vec) -> &'static [T] { + Box::leak(values.into_boxed_slice()) + } +} diff --git a/crates/jolt-kernels/src/stage4.rs b/crates/jolt-kernels/src/stage4.rs new file mode 100644 index 0000000000..27ef3df87e --- /dev/null +++ b/crates/jolt-kernels/src/stage4.rs @@ -0,0 +1,4667 @@ +//! Stage 4 coarse-kernel ABI used by Bolt-generated Jolt prover code. + +#![expect( + clippy::large_enum_variant, + reason = "kernel states stay inline to avoid boxing hot prover state" +)] +#![expect( + clippy::too_many_arguments, + reason = "kernel constructors mirror generated staged protocol inputs" +)] + +use std::error::Error; +use std::fmt::{self, Display, Formatter}; +use std::mem::MaybeUninit; + +use crate::dense::{bind_dense_evals_reuse, DENSE_BIND_PAR_THRESHOLD}; +use crate::split_eq::SplitEqState; +use crate::stage2::Stage2RamAccess; +use jolt_field::{Field, FieldAccumulator}; +use jolt_poly::{EqPolynomial, UnivariatePoly}; +use jolt_sumcheck::SumcheckProof; +use jolt_transcript::{Label, LabelWithCount, Transcript}; +use jolt_witness::{stage4_5_sparse_trace_witness, Stage45SparseTraceWitness}; +use rayon::prelude::*; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Stage4ExecutionMode { + Prover, + Verifier, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Stage4Relation { + RegistersReadWrite, + RamValCheck, + Batched, +} + +impl Stage4Relation { + pub fn from_symbol(symbol: &str) -> Option { + match symbol { + "jolt.stage4.registers_read_write" => Some(Self::RegistersReadWrite), + "jolt.stage4.ram_val_check" => Some(Self::RamValCheck), + "jolt.stage4.batched" => Some(Self::Batched), + _ => None, + } + } + + pub fn symbol(self) -> &'static str { + match self { + Self::RegistersReadWrite => "jolt.stage4.registers_read_write", + Self::RamValCheck => "jolt.stage4.ram_val_check", + Self::Batched => "jolt.stage4.batched", + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Stage4KernelAbi { + RegistersReadWrite, + RamValCheck, + Batched, +} + +impl Stage4KernelAbi { + pub fn from_name(name: &str) -> Option { + match name { + "jolt_stage4_registers_read_write" => Some(Self::RegistersReadWrite), + "jolt_stage4_ram_val_check" => Some(Self::RamValCheck), + "jolt_stage4_batched" => Some(Self::Batched), + _ => None, + } + } + + pub fn name(self) -> &'static str { + match self { + Self::RegistersReadWrite => "jolt_stage4_registers_read_write", + Self::RamValCheck => "jolt_stage4_ram_val_check", + Self::Batched => "jolt_stage4_batched", + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4Params { + pub field: &'static str, + pub pcs: &'static str, + pub transcript: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4KernelPlan { + pub symbol: &'static str, + pub relation: &'static str, + pub kind: &'static str, + pub backend: &'static str, + pub abi: &'static str, +} + +impl Stage4KernelPlan { + pub fn relation_kind(&self) -> Result { + Stage4Relation::from_symbol(self.relation).ok_or(Stage4KernelError::UnknownRelation { + relation: self.relation, + }) + } + + pub fn abi_kind(&self) -> Result { + Stage4KernelAbi::from_name(self.abi) + .ok_or(Stage4KernelError::UnknownKernelAbi { abi: self.abi }) + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4TranscriptSqueezePlan { + pub symbol: &'static str, + pub label: &'static str, + pub kind: &'static str, + pub count: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4TranscriptAbsorbBytesPlan { + pub symbol: &'static str, + pub label: &'static str, + pub payload: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4ProgramStepPlan { + pub kind: &'static str, + pub symbol: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4OpeningInputPlan { + pub symbol: &'static str, + pub source_stage: &'static str, + pub source_claim: &'static str, + pub oracle: &'static str, + pub domain: &'static str, + pub point_arity: usize, + pub claim_kind: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4FieldConstantPlan { + pub symbol: &'static str, + pub field: &'static str, + pub value: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4FieldExprPlan { + pub symbol: &'static str, + pub kind: &'static str, + pub formula: &'static str, + pub operand_names: &'static [&'static str], + pub operands: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4SumcheckClaimPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub domain: &'static str, + pub num_rounds: usize, + pub degree: usize, + pub claim: &'static str, + pub kernel: Option<&'static str>, + pub relation: Option<&'static str>, + pub claim_value: &'static str, + pub input_openings: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4SumcheckBatchPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub proof_slot: &'static str, + pub policy: &'static str, + pub count: usize, + pub ordered_claims: &'static [&'static str], + pub claim_operands: &'static [&'static str], + pub claim_label: &'static str, + pub round_label: &'static str, + pub round_schedule: &'static [usize], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4SumcheckDriverPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub proof_slot: &'static str, + pub kernel: Option<&'static str>, + pub relation: Option<&'static str>, + pub batch: &'static str, + pub policy: &'static str, + pub round_schedule: &'static [usize], + pub claim_label: &'static str, + pub round_label: &'static str, + pub num_rounds: usize, + pub degree: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4SumcheckInstanceResultPlan { + pub symbol: &'static str, + pub source: &'static str, + pub claim: &'static str, + pub relation: &'static str, + pub index: usize, + pub point_arity: usize, + pub num_rounds: usize, + pub round_offset: usize, + pub point_order: &'static str, + pub degree: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4SumcheckEvalPlan { + pub symbol: &'static str, + pub source: &'static str, + pub name: &'static str, + pub index: usize, + pub oracle: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4PointSlicePlan { + pub symbol: &'static str, + pub source: &'static str, + pub offset: usize, + pub length: usize, + pub input: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4PointConcatPlan { + pub symbol: &'static str, + pub layout: &'static str, + pub arity: usize, + pub inputs: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4OpeningClaimPlan { + pub symbol: &'static str, + pub oracle: &'static str, + pub domain: &'static str, + pub point_arity: usize, + pub claim_kind: &'static str, + pub point_source: &'static str, + pub eval_source: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4OpeningClaimEqualityPlan { + pub symbol: &'static str, + pub mode: &'static str, + pub lhs: &'static str, + pub rhs: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4OpeningBatchPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub proof_slot: &'static str, + pub policy: &'static str, + pub count: usize, + pub ordered_claims: &'static [&'static str], + pub claim_operands: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4CpuProgramPlan { + pub role: &'static str, + pub params: Stage4Params, + pub steps: &'static [Stage4ProgramStepPlan], + pub transcript_squeezes: &'static [Stage4TranscriptSqueezePlan], + pub transcript_absorb_bytes: &'static [Stage4TranscriptAbsorbBytesPlan], + pub opening_inputs: &'static [Stage4OpeningInputPlan], + pub field_constants: &'static [Stage4FieldConstantPlan], + pub field_exprs: &'static [Stage4FieldExprPlan], + pub kernels: &'static [Stage4KernelPlan], + pub claims: &'static [Stage4SumcheckClaimPlan], + pub batches: &'static [Stage4SumcheckBatchPlan], + pub drivers: &'static [Stage4SumcheckDriverPlan], + pub instance_results: &'static [Stage4SumcheckInstanceResultPlan], + pub evals: &'static [Stage4SumcheckEvalPlan], + pub point_slices: &'static [Stage4PointSlicePlan], + pub point_concats: &'static [Stage4PointConcatPlan], + pub opening_claims: &'static [Stage4OpeningClaimPlan], + pub opening_equalities: &'static [Stage4OpeningClaimEqualityPlan], + pub opening_batches: &'static [Stage4OpeningBatchPlan], +} + +impl Stage4CpuProgramPlan { + pub fn claim(&self, symbol: &str) -> Option<&Stage4SumcheckClaimPlan> { + self.claims.iter().find(|claim| claim.symbol == symbol) + } + + pub fn instance_results_for_driver( + &self, + driver: &'static str, + ) -> impl Iterator { + self.instance_results + .iter() + .filter(move |instance| instance.source == driver) + } + + pub fn evals_for_driver( + &self, + driver: &'static str, + ) -> impl Iterator { + self.evals.iter().filter(move |eval| eval.source == driver) + } +} + +#[derive(Clone, Debug)] +pub struct Stage4NamedEval { + pub name: &'static str, + pub oracle: &'static str, + pub value: F, +} + +#[derive(Clone, Debug)] +pub struct Stage4SumcheckOutput { + pub driver: &'static str, + pub point: Vec, + pub evals: Vec>, + pub opening_claims: Vec>, + pub proof: SumcheckProof, +} + +#[derive(Clone, Debug)] +pub struct Stage4ChallengeVector { + pub symbol: &'static str, + pub values: Vec, +} + +#[derive(Clone, Debug)] +pub struct Stage4OpeningClaimValue { + pub symbol: &'static str, + pub oracle: &'static str, + pub domain: &'static str, + pub claim_kind: &'static str, + pub point: Vec, + pub eval: F, +} + +#[derive(Clone, Debug)] +pub struct Stage4ExecutionArtifacts { + pub challenge_vectors: Vec>, + pub sumchecks: Vec>, + pub opening_claims: Vec>, + pub opening_batches: Vec<&'static Stage4OpeningBatchPlan>, +} + +impl Default for Stage4ExecutionArtifacts { + fn default() -> Self { + Self { + challenge_vectors: Vec::new(), + sumchecks: Vec::new(), + opening_claims: Vec::new(), + opening_batches: Vec::new(), + } + } +} + +#[derive(Clone, Debug, Default)] +pub struct Stage4Proof { + pub sumchecks: Vec>, +} + +impl From> for Stage4Proof { + fn from(artifacts: Stage4ExecutionArtifacts) -> Self { + Self { + sumchecks: artifacts.sumchecks, + } + } +} + +#[derive(Clone, Debug)] +pub struct Stage4OpeningInputValue { + pub symbol: &'static str, + pub point: Vec, + pub eval: F, +} + +#[derive(Clone, Copy)] +pub struct Stage4RegistersWitness<'a, F: Field> { + pub register_count: usize, + pub trace_len: usize, + pub registers_val: &'a [F], + pub rs1_ra: &'a [F], + pub rs2_ra: &'a [F], + pub rd_wa: &'a [F], + pub accesses: Option<&'a [Stage4RegisterAccess]>, + pub rd_inc: &'a [F], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4RegisterRead { + pub address: usize, + pub value: u64, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage4RegisterWrite { + pub address: usize, + pub pre_value: u64, + pub post_value: u64, +} + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub struct Stage4RegisterAccess { + pub rs1: Option, + pub rs2: Option, + pub rd: Option, +} + +pub fn stage4_5_sparse_trace_witness_from_accesses( + register_accesses: &[Stage4RegisterAccess], + ram_accesses: &[Stage2RamAccess], +) -> Stage45SparseTraceWitness { + stage4_5_sparse_trace_witness( + register_accesses.iter().map(|access| { + access + .rd + .map(|rd| (rd.address, rd.pre_value, rd.post_value)) + }), + ram_accesses.iter().map(|access| { + ( + access.remapped_address, + access.read_value, + access.write_value, + ) + }), + ) +} + +#[derive(Clone, Copy)] +pub struct Stage4RamWitness<'a, F: Field> { + pub ram_k: usize, + pub trace_len: usize, + pub ram_ra: &'a [F], + pub write_address_indices: Option<&'a [Option]>, + pub ram_inc: &'a [F], +} + +#[derive(Clone, Copy)] +pub struct Stage4ProverInputs<'a, F: Field> { + pub opening_inputs: &'a [Stage4OpeningInputValue], + pub registers: Option>, + pub ram: Option>, +} + +impl<'a, F: Field> Stage4ProverInputs<'a, F> { + pub fn new(opening_inputs: &'a [Stage4OpeningInputValue]) -> Self { + Self { + opening_inputs, + registers: None, + ram: None, + } + } + + pub fn empty() -> Self { + Self { + opening_inputs: &[], + registers: None, + ram: None, + } + } + + pub fn with_registers(mut self, registers: Stage4RegistersWitness<'a, F>) -> Self { + self.registers = Some(registers); + self + } + + pub fn with_ram(mut self, ram: Stage4RamWitness<'a, F>) -> Self { + self.ram = Some(ram); + self + } + + pub fn with_sparse_trace_witness( + self, + register_count: usize, + trace_len: usize, + ram_k: usize, + register_accesses: &'a [Stage4RegisterAccess], + rd_inc: &'a [F], + write_address_indices: &'a [Option], + ram_inc: &'a [F], + ) -> Self { + self.with_registers(Stage4RegistersWitness { + register_count, + trace_len, + registers_val: &[], + rs1_ra: &[], + rs2_ra: &[], + rd_wa: &[], + accesses: Some(register_accesses), + rd_inc, + }) + .with_ram(Stage4RamWitness { + ram_k, + trace_len, + ram_ra: &[], + write_address_indices: Some(write_address_indices), + ram_inc, + }) + } + + pub fn with_stage45_sparse_trace_witness( + self, + register_count: usize, + trace_len: usize, + ram_k: usize, + register_accesses: &'a [Stage4RegisterAccess], + witness: &'a Stage45SparseTraceWitness, + ) -> Self { + self.with_sparse_trace_witness( + register_count, + trace_len, + ram_k, + register_accesses, + &witness.rd_inc, + &witness.ram_addresses, + &witness.ram_inc, + ) + } +} + +#[derive(Clone, Debug)] +pub struct Stage4ScalarValue { + pub symbol: &'static str, + pub value: F, +} + +#[derive(Clone, Debug)] +pub struct Stage4PointValue { + pub symbol: &'static str, + pub point: Vec, +} + +#[derive(Clone, Debug, Default)] +pub struct Stage4ValueStore { + scalars: Vec>, + points: Vec>, +} + +impl Stage4ValueStore { + pub fn new() -> Self { + Self::default() + } + + pub fn with_opening_inputs(inputs: &[Stage4OpeningInputValue]) -> Self { + let mut store = Self::new(); + store.insert_opening_inputs(inputs); + store + } + + pub fn insert_opening_inputs(&mut self, inputs: &[Stage4OpeningInputValue]) { + for input in inputs { + self.insert_scalar(input.symbol, input.eval); + self.insert_point(input.symbol, input.point.clone()); + } + } + + pub fn insert_scalar(&mut self, symbol: &'static str, value: F) { + if let Some(existing) = self + .scalars + .iter_mut() + .find(|existing| existing.symbol == symbol) + { + existing.value = value; + } else { + self.scalars.push(Stage4ScalarValue { symbol, value }); + } + } + + pub fn insert_point(&mut self, symbol: &'static str, point: Vec) { + if let Some(existing) = self + .points + .iter_mut() + .find(|existing| existing.symbol == symbol) + { + existing.point = point; + } else { + self.points.push(Stage4PointValue { symbol, point }); + } + } + + pub fn try_scalar(&self, symbol: &str) -> Option { + self.scalars + .iter() + .find(|value| value.symbol == symbol) + .map(|value| value.value) + } + + pub fn scalar(&self, symbol: &'static str) -> Result { + self.try_scalar(symbol) + .ok_or(Stage4KernelError::MissingValue { symbol }) + } + + pub fn try_point(&self, symbol: &str) -> Option<&[F]> { + self.points + .iter() + .find(|value| value.symbol == symbol) + .map(|value| value.point.as_slice()) + } + + pub fn point(&self, symbol: &'static str) -> Result<&[F], Stage4KernelError> { + self.try_point(symbol) + .ok_or(Stage4KernelError::MissingValue { symbol }) + } + + pub fn seed_constants( + &mut self, + program: &'static Stage4CpuProgramPlan, + ) -> Result<(), Stage4KernelError> { + for constant in program.field_constants { + self.insert_scalar(constant.symbol, F::from_u64(constant.value as u64)); + } + Ok(()) + } + + pub fn observe_challenge_vector( + &mut self, + plan: &'static Stage4TranscriptSqueezePlan, + values: &[F], + ) -> Result<(), Stage4KernelError> { + if matches!(plan.kind, "challenge_scalar" | "scalar") { + require_operand_count(plan.symbol, 1, values.len())?; + self.insert_scalar(plan.symbol, values[0]); + } + self.insert_point(plan.symbol, values.to_vec()); + let _ = values; + Ok(()) + } + + pub fn observe_sumcheck_output( + &mut self, + program: &'static Stage4CpuProgramPlan, + output: &Stage4SumcheckOutput, + ) -> Result<(), Stage4KernelError> { + self.observe_sumcheck_values(program, output.driver, &output.point, &output.evals) + } + + pub fn observe_sumcheck_values( + &mut self, + program: &'static Stage4CpuProgramPlan, + driver: &'static str, + point: &[F], + evals: &[Stage4NamedEval], + ) -> Result<(), Stage4KernelError> { + self.insert_point(driver, point.to_vec()); + for instance in program.instance_results_for_driver(driver) { + let end = instance.round_offset + instance.point_arity; + let mut instance_point = point + .get(instance.round_offset..end) + .ok_or(Stage4KernelError::InvalidInputLength { + input: instance.symbol, + expected: end, + actual: point.len(), + })? + .to_vec(); + match instance.point_order { + "as_is" => {} + "reverse" => instance_point.reverse(), + "stage4_registers_rw" => { + instance_point = + normalize_stage4_registers_rw_point(program, driver, &instance_point)?; + } + _ => { + return Err(Stage4KernelError::InvalidProof { + driver, + reason: "unsupported point order", + }); + } + } + self.insert_point(instance.symbol, instance_point); + } + for eval in program.evals_for_driver(driver) { + let value = evals + .iter() + .find(|value| value.name == eval.name) + .or_else(|| evals.get(eval.index)) + .ok_or(Stage4KernelError::MissingValue { + symbol: eval.symbol, + })? + .value; + self.insert_scalar(eval.symbol, value); + self.insert_scalar(eval.name, value); + } + let _ = self.evaluate_available_points(program)?; + let _ = self.evaluate_available_field_exprs(program)?; + self.verify_opening_equalities(program)?; + Ok(()) + } + + pub fn evaluate_available_points( + &mut self, + program: &'static Stage4CpuProgramPlan, + ) -> Result { + let mut inserted = 0usize; + loop { + let mut progress = 0usize; + for slice in program.point_slices { + if self.try_point(slice.symbol).is_some() { + continue; + } + let Some(input) = self.try_point(slice.input) else { + continue; + }; + let end = slice.offset + slice.length; + let point = input + .get(slice.offset..end) + .ok_or(Stage4KernelError::InvalidInputLength { + input: slice.symbol, + expected: end, + actual: input.len(), + })? + .to_vec(); + self.insert_point(slice.symbol, point); + progress += 1; + } + for concat in program.point_concats { + if self.try_point(concat.symbol).is_some() { + continue; + } + let Some(point) = self.try_concat_point(concat) else { + continue; + }; + verify_count(concat.symbol, concat.arity, point.len())?; + self.insert_point(concat.symbol, point); + progress += 1; + } + inserted += progress; + if progress == 0 { + return Ok(inserted); + } + } + } + + pub fn evaluate_available_field_exprs( + &mut self, + program: &'static Stage4CpuProgramPlan, + ) -> Result { + let mut inserted = 0usize; + loop { + let mut progress = 0usize; + for expr in program.field_exprs { + if self.try_scalar(expr.symbol).is_some() { + continue; + } + let Some(operands) = self.try_expr_operands(expr) else { + continue; + }; + self.insert_scalar(expr.symbol, evaluate_stage4_field_expr(expr, &operands)?); + progress += 1; + } + inserted += progress; + if progress == 0 { + return Ok(inserted); + } + } + } + + pub fn verify_opening_equalities( + &self, + program: &'static Stage4CpuProgramPlan, + ) -> Result<(), Stage4KernelError> { + for equality in program.opening_equalities { + match equality.mode { + "point_and_eval" => { + if self.point(equality.lhs)? != self.point(equality.rhs)? + || self.scalar(equality.lhs)? != self.scalar(equality.rhs)? + { + return Err(Stage4KernelError::InvalidProof { + driver: equality.symbol, + reason: "opening claim equality failed", + }); + } + } + _ => { + return Err(Stage4KernelError::InvalidProof { + driver: equality.symbol, + reason: "unsupported opening equality mode", + }); + } + } + } + Ok(()) + } + + pub fn claim_value( + &mut self, + program: &'static Stage4CpuProgramPlan, + claim: &Stage4SumcheckClaimPlan, + ) -> Result { + let _ = self.evaluate_available_field_exprs(program)?; + self.scalar(claim.claim_value) + } + + pub fn batch_claim_values( + &mut self, + program: &'static Stage4CpuProgramPlan, + batch: &Stage4SumcheckBatchPlan, + ) -> Result, Stage4KernelError> { + batch + .claim_operands + .iter() + .map(|symbol| { + let claim = program + .claim(symbol) + .ok_or(Stage4KernelError::MissingClaim { + batch: batch.symbol, + claim: symbol, + })?; + self.claim_value(program, claim) + }) + .collect() + } + + fn try_expr_operands(&self, expr: &Stage4FieldExprPlan) -> Option> { + expr.operands + .iter() + .map(|operand| self.try_scalar(operand)) + .collect() + } + + fn try_concat_point(&self, concat: &Stage4PointConcatPlan) -> Option> { + let mut point = Vec::with_capacity(concat.arity); + for input in concat.inputs { + point.extend_from_slice(self.try_point(input)?); + } + Some(point) + } +} + +pub fn evaluate_stage4_field_expr( + expr: &Stage4FieldExprPlan, + operands: &[F], +) -> Result { + match expr.formula { + "opening_eval" => single_operand(expr.symbol, operands), + "field.add" => { + require_operand_count(expr.symbol, 2, operands.len())?; + Ok(operands[0] + operands[1]) + } + "field.sub" => { + require_operand_count(expr.symbol, 2, operands.len())?; + Ok(operands[0] - operands[1]) + } + "field.mul" => { + require_operand_count(expr.symbol, 2, operands.len())?; + Ok(operands[0] * operands[1]) + } + "field.neg" => { + require_operand_count(expr.symbol, 1, operands.len())?; + Ok(-operands[0]) + } + _ => { + if let Some(exponent) = expr.formula.strip_prefix("field.pow:") { + require_operand_count(expr.symbol, 1, operands.len())?; + let exponent = exponent.parse::().map_err(|_| { + Stage4KernelError::UnsupportedFieldExpr { + symbol: expr.symbol, + formula: expr.formula, + } + })?; + return Ok(pow_field(operands[0], exponent)); + } + Err(Stage4KernelError::UnsupportedFieldExpr { + symbol: expr.symbol, + formula: expr.formula, + }) + } + } +} + +fn pow_field(base: F, mut exponent: usize) -> F { + let mut result = F::one(); + let mut power = base; + while exponent != 0 { + if exponent & 1 == 1 { + result *= power; + } + power = power.square(); + exponent >>= 1; + } + result +} + +fn single_operand(symbol: &'static str, operands: &[F]) -> Result { + require_operand_count(symbol, 1, operands.len())?; + Ok(operands[0]) +} + +fn require_operand_count( + input: &'static str, + expected: usize, + actual: usize, +) -> Result<(), Stage4KernelError> { + if expected == actual { + Ok(()) + } else { + Err(Stage4KernelError::InvalidInputLength { + input, + expected, + actual, + }) + } +} + +#[derive(Clone, Copy, Debug)] +pub struct Stage4KernelContext<'a> { + pub mode: Stage4ExecutionMode, + pub program: &'static Stage4CpuProgramPlan, + pub kernel: &'a Stage4KernelPlan, + pub batch: &'a Stage4SumcheckBatchPlan, + pub driver: &'a Stage4SumcheckDriverPlan, +} + +impl Stage4KernelContext<'_> { + pub fn relation_kind(&self) -> Result { + self.kernel.relation_kind() + } + + pub fn abi_kind(&self) -> Result { + self.kernel.abi_kind() + } + + pub fn batch_claims(&self) -> Result, Stage4KernelError> { + self.batch + .claim_operands + .iter() + .map(|symbol| { + self.program + .claim(symbol) + .ok_or(Stage4KernelError::MissingClaim { + batch: self.batch.symbol, + claim: symbol, + }) + }) + .collect() + } +} + +pub trait Stage4KernelExecutor { + fn observe_challenge_vector( + &mut self, + _plan: &'static Stage4TranscriptSqueezePlan, + _values: &[F], + ) -> Result<(), Stage4KernelError> { + Ok(()) + } + + fn observe_sumcheck_output( + &mut self, + _output: &Stage4SumcheckOutput, + ) -> Result<(), Stage4KernelError> { + Ok(()) + } + + fn prove_sumcheck( + &mut self, + context: Stage4KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage4KernelError> + where + T: Transcript; + + fn verify_sumcheck( + &mut self, + context: Stage4KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage4KernelError> + where + T: Transcript; +} + +#[derive(Clone, Debug, Default)] +pub struct UnsupportedStage4KernelExecutor; + +impl Stage4KernelExecutor for UnsupportedStage4KernelExecutor { + fn prove_sumcheck( + &mut self, + context: Stage4KernelContext<'_>, + _transcript: &mut T, + ) -> Result, Stage4KernelError> + where + T: Transcript, + { + Err(Stage4KernelError::KernelNotImplemented { + abi: context.kernel.abi, + }) + } + + fn verify_sumcheck( + &mut self, + context: Stage4KernelContext<'_>, + _transcript: &mut T, + ) -> Result, Stage4KernelError> + where + T: Transcript, + { + Err(Stage4KernelError::KernelNotImplemented { + abi: context.kernel.abi, + }) + } +} + +#[derive(Clone)] +pub struct Stage4ProverKernelExecutor<'a, F: Field> { + pub inputs: Stage4ProverInputs<'a, F>, + challenge_vectors: Vec>, + completed_sumchecks: Vec>, +} + +impl<'a, F: Field> Stage4ProverKernelExecutor<'a, F> { + pub fn new(inputs: Stage4ProverInputs<'a, F>) -> Self { + Self { + inputs, + challenge_vectors: Vec::new(), + completed_sumchecks: Vec::new(), + } + } + + fn value_store( + &self, + program: &'static Stage4CpuProgramPlan, + ) -> Result, Stage4KernelError> { + value_store_from_observations( + program, + self.inputs.opening_inputs, + &self.challenge_vectors, + &self.completed_sumchecks, + ) + } +} + +impl Stage4KernelExecutor for Stage4ProverKernelExecutor<'_, F> { + fn observe_challenge_vector( + &mut self, + plan: &'static Stage4TranscriptSqueezePlan, + values: &[F], + ) -> Result<(), Stage4KernelError> { + self.challenge_vectors.push(Stage4ChallengeVector { + symbol: plan.symbol, + values: values.to_vec(), + }); + Ok(()) + } + + fn observe_sumcheck_output( + &mut self, + output: &Stage4SumcheckOutput, + ) -> Result<(), Stage4KernelError> { + self.completed_sumchecks.push(output.clone()); + Ok(()) + } + + fn prove_sumcheck( + &mut self, + context: Stage4KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage4KernelError> + where + T: Transcript, + { + prove_stage4_kernel( + context, + &self.inputs, + self.value_store(context.program)?, + transcript, + ) + } + + fn verify_sumcheck( + &mut self, + context: Stage4KernelContext<'_>, + _transcript: &mut T, + ) -> Result, Stage4KernelError> + where + T: Transcript, + { + Err(Stage4KernelError::WrongExecutorMode { + driver: context.driver.symbol, + expected: Stage4ExecutionMode::Prover, + actual: Stage4ExecutionMode::Verifier, + }) + } +} + +#[derive(Clone)] +pub struct Stage4VerifierKernelExecutor<'a, F: Field> { + pub proof: &'a Stage4Proof, + pub opening_inputs: &'a [Stage4OpeningInputValue], + pub cursor: usize, + challenge_vectors: Vec>, + completed_sumchecks: Vec>, +} + +impl<'a, F: Field> Stage4VerifierKernelExecutor<'a, F> { + pub fn new( + proof: &'a Stage4Proof, + opening_inputs: &'a [Stage4OpeningInputValue], + ) -> Self { + Self { + proof, + opening_inputs, + cursor: 0, + challenge_vectors: Vec::new(), + completed_sumchecks: Vec::new(), + } + } + + fn value_store( + &self, + program: &'static Stage4CpuProgramPlan, + ) -> Result, Stage4KernelError> { + value_store_from_observations( + program, + self.opening_inputs, + &self.challenge_vectors, + &self.completed_sumchecks, + ) + } +} + +impl Stage4KernelExecutor for Stage4VerifierKernelExecutor<'_, F> { + fn observe_challenge_vector( + &mut self, + plan: &'static Stage4TranscriptSqueezePlan, + values: &[F], + ) -> Result<(), Stage4KernelError> { + self.challenge_vectors.push(Stage4ChallengeVector { + symbol: plan.symbol, + values: values.to_vec(), + }); + Ok(()) + } + + fn observe_sumcheck_output( + &mut self, + output: &Stage4SumcheckOutput, + ) -> Result<(), Stage4KernelError> { + self.completed_sumchecks.push(output.clone()); + Ok(()) + } + + fn prove_sumcheck( + &mut self, + context: Stage4KernelContext<'_>, + _transcript: &mut T, + ) -> Result, Stage4KernelError> + where + T: Transcript, + { + Err(Stage4KernelError::WrongExecutorMode { + driver: context.driver.symbol, + expected: Stage4ExecutionMode::Verifier, + actual: Stage4ExecutionMode::Prover, + }) + } + + fn verify_sumcheck( + &mut self, + context: Stage4KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage4KernelError> + where + T: Transcript, + { + let proof = + self.proof + .sumchecks + .get(self.cursor) + .ok_or(Stage4KernelError::MissingProof { + driver: context.driver.symbol, + })?; + self.cursor += 1; + verify_stage4_kernel( + context, + self.value_store(context.program)?, + proof, + transcript, + ) + } +} + +fn value_store_from_observations( + program: &'static Stage4CpuProgramPlan, + opening_inputs: &[Stage4OpeningInputValue], + challenge_vectors: &[Stage4ChallengeVector], + completed_sumchecks: &[Stage4SumcheckOutput], +) -> Result, Stage4KernelError> { + let mut store = Stage4ValueStore::with_opening_inputs(opening_inputs); + store.seed_constants(program)?; + for challenge in challenge_vectors { + let plan = program + .transcript_squeezes + .iter() + .find(|plan| plan.symbol == challenge.symbol) + .ok_or(Stage4KernelError::MissingValue { + symbol: challenge.symbol, + })?; + store.observe_challenge_vector(plan, &challenge.values)?; + } + for output in completed_sumchecks { + store.observe_sumcheck_output(program, output)?; + } + let _ = store.evaluate_available_points(program)?; + let _ = store.evaluate_available_field_exprs(program)?; + store.verify_opening_equalities(program)?; + Ok(store) +} + +pub fn execute_stage4_program( + program: &'static Stage4CpuProgramPlan, + mode: Stage4ExecutionMode, + executor: &mut E, + transcript: &mut T, +) -> Result, Stage4KernelError> +where + F: Field, + T: Transcript, + E: Stage4KernelExecutor, +{ + let mut artifacts = Stage4ExecutionArtifacts::default(); + for step in program.steps { + match step.kind { + "transcript_squeeze" => { + let squeeze = + find_squeeze(program, step.symbol).ok_or(Stage4KernelError::MissingValue { + symbol: step.symbol, + })?; + let values = transcript.challenge_vector(squeeze.count); + executor.observe_challenge_vector(squeeze, &values)?; + artifacts.challenge_vectors.push(Stage4ChallengeVector { + symbol: squeeze.symbol, + values, + }); + } + "transcript_absorb_bytes" => { + let absorb = find_absorb_bytes(program, step.symbol).ok_or( + Stage4KernelError::MissingValue { + symbol: step.symbol, + }, + )?; + absorb_stage4_bytes(absorb, transcript); + } + "sumcheck_driver" => { + let driver = + find_driver(program, step.symbol).ok_or(Stage4KernelError::MissingDriver { + driver: step.symbol, + })?; + let kernel_symbol = driver.kernel.ok_or(Stage4KernelError::MissingKernel { + driver: driver.symbol, + kernel: "", + })?; + let kernel = find_kernel(program, kernel_symbol).ok_or( + Stage4KernelError::MissingKernel { + driver: driver.symbol, + kernel: kernel_symbol, + }, + )?; + let batch = + find_batch(program, driver.batch).ok_or(Stage4KernelError::MissingBatch { + driver: driver.symbol, + batch: driver.batch, + })?; + let context = Stage4KernelContext { + mode, + program, + kernel, + batch, + driver, + }; + let output = match mode { + Stage4ExecutionMode::Prover => executor.prove_sumcheck(context, transcript)?, + Stage4ExecutionMode::Verifier => { + executor.verify_sumcheck(context, transcript)? + } + }; + executor.observe_sumcheck_output(&output)?; + artifacts + .opening_claims + .extend(output.opening_claims.clone()); + artifacts.sumchecks.push(output); + } + _ => { + return Err(Stage4KernelError::InvalidProgramStep { + symbol: step.symbol, + kind: step.kind, + }); + } + } + } + artifacts + .opening_batches + .extend(program.opening_batches.iter()); + Ok(artifacts) +} + +fn absorb_stage4_bytes(absorb: &'static Stage4TranscriptAbsorbBytesPlan, transcript: &mut T) +where + T: Transcript, +{ + transcript.append(&LabelWithCount( + absorb.label.as_bytes(), + absorb.payload.len() as u64, + )); + transcript.append_bytes(absorb.payload.as_bytes()); +} + +fn prove_stage4_kernel( + context: Stage4KernelContext<'_>, + inputs: &Stage4ProverInputs<'_, F>, + store: Stage4ValueStore, + transcript: &mut T, +) -> Result, Stage4KernelError> +where + F: Field, + T: Transcript, +{ + match context.abi_kind()? { + Stage4KernelAbi::Batched => prove_batched_stage4(context, inputs, store, transcript), + abi => Err(Stage4KernelError::KernelNotImplemented { abi: abi.name() }), + } +} + +fn verify_stage4_kernel( + context: Stage4KernelContext<'_>, + store: Stage4ValueStore, + proof: &Stage4SumcheckOutput, + transcript: &mut T, +) -> Result, Stage4KernelError> +where + F: Field, + T: Transcript, +{ + match context.abi_kind()? { + Stage4KernelAbi::Batched => verify_batched_stage4(context, store, proof, transcript), + abi => Err(Stage4KernelError::KernelNotImplemented { abi: abi.name() }), + } +} + +#[tracing::instrument(skip_all, name = "Stage4::prove_batched")] +fn prove_batched_stage4( + context: Stage4KernelContext<'_>, + inputs: &Stage4ProverInputs<'_, F>, + mut store: Stage4ValueStore, + transcript: &mut T, +) -> Result, Stage4KernelError> +where + F: Field, + T: Transcript, +{ + let claims = context.batch_claims()?; + let input_claims = store.batch_claim_values(context.program, context.batch)?; + for claim in &input_claims { + append_labeled_scalar(transcript, context.batch.claim_label, claim); + } + let batching_coeffs = transcript.challenge_vector(claims.len()); + let max_rounds = context.driver.num_rounds; + let two_inv = F::from_u64(2) + .inverse() + .ok_or(Stage4KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "field element 2 is not invertible", + })?; + let mut instances = Vec::with_capacity(claims.len()); + for (index, claim) in claims.iter().enumerate() { + let offset = instance_round_offset(context.program, context.driver.symbol, claim.symbol)?; + if offset + claim.num_rounds > max_rounds { + return Err(Stage4KernelError::InvalidInputLength { + input: claim.symbol, + expected: max_rounds, + actual: offset + claim.num_rounds, + }); + } + let active_scale = F::one().mul_pow_2(max_rounds - offset - claim.num_rounds); + instances.push(Stage4BatchedInstance { + claim, + relation: claim_relation(context.program, claim)?, + offset, + previous_claim: input_claims[index].mul_pow_2(max_rounds - claim.num_rounds), + state: Stage4ProverInstanceState::new( + context.program, + claim, + inputs, + &store, + active_scale, + )?, + }); + } + + let mut point = Vec::with_capacity(max_rounds); + let mut round_polynomials = Vec::with_capacity(max_rounds); + let mut batched_claim = instances + .iter() + .zip(&batching_coeffs) + .map(|(instance, &coefficient)| instance.previous_claim * coefficient) + .sum::(); + for round in 0..max_rounds { + let mut individual_polys = Vec::with_capacity(instances.len()); + for instance in &mut instances { + let poly = if instance.is_active(round) { + instance + .state + .round_poly(instance.previous_claim, instance.relation)? + } else { + UnivariatePoly::new(vec![instance.previous_claim * two_inv]) + }; + #[cfg(debug_assertions)] + { + if poly.evaluate(F::zero()) + poly.evaluate(F::one()) != instance.previous_claim { + return Err(Stage4KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched instance round claim mismatch", + }); + } + } + individual_polys.push(poly); + } + let batched_poly = combine_univariate_polys(&individual_polys, &batching_coeffs); + #[cfg(debug_assertions)] + { + if batched_poly.evaluate(F::zero()) + batched_poly.evaluate(F::one()) != batched_claim { + return Err(Stage4KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched round claim mismatch", + }); + } + } + append_compressed_univariate_poly(transcript, context.driver.round_label, &batched_poly); + let challenge = transcript.challenge(); + point.push(challenge); + batched_claim = batched_poly.evaluate(challenge); + for (instance, poly) in instances.iter_mut().zip(individual_polys) { + instance.previous_claim = poly.evaluate(challenge); + if instance.is_active(round) { + instance.state.ingest_challenge(challenge); + } + } + round_polynomials.push(batched_poly); + } + + let mut evals = Vec::new(); + for instance in &instances { + evals.extend(instance.state.final_evals(instance.relation)?); + } + let expected = + expected_batched_output_claim(context, &store, &evals, &point, &batching_coeffs)?; + if batched_claim != expected { + return Err(Stage4KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched output claim mismatch", + }); + } + store.observe_sumcheck_values(context.program, context.driver.symbol, &point, &evals)?; + let opening_claims = append_opening_claims(context.program, &mut store, transcript, &evals)?; + Ok(Stage4SumcheckOutput { + driver: context.driver.symbol, + point, + evals, + opening_claims, + proof: SumcheckProof { round_polynomials }, + }) +} + +fn verify_batched_stage4( + context: Stage4KernelContext<'_>, + mut store: Stage4ValueStore, + proof: &Stage4SumcheckOutput, + transcript: &mut T, +) -> Result, Stage4KernelError> +where + F: Field, + T: Transcript, +{ + if proof.driver != context.driver.symbol { + return Err(Stage4KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "driver symbol mismatch", + }); + } + if proof.proof.round_polynomials.len() != context.driver.num_rounds { + return Err(Stage4KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "unexpected batched round count", + }); + } + let claims = context.batch_claims()?; + let input_claims = store.batch_claim_values(context.program, context.batch)?; + for claim in &input_claims { + append_labeled_scalar(transcript, context.batch.claim_label, claim); + } + let batching_coeffs = transcript.challenge_vector(claims.len()); + let max_rounds = context.driver.num_rounds; + let mut running_claim = input_claims + .iter() + .zip(claims.iter()) + .zip(&batching_coeffs) + .map(|((claim, plan), &coefficient)| { + claim.mul_pow_2(max_rounds - plan.num_rounds) * coefficient + }) + .sum::(); + let mut point = Vec::with_capacity(max_rounds); + for poly in &proof.proof.round_polynomials { + if polynomial_degree(poly) > context.driver.degree { + return Err(Stage4KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched polynomial exceeds degree bound", + }); + } + if poly.evaluate(F::zero()) + poly.evaluate(F::one()) != running_claim { + return Err(Stage4KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched round check failed", + }); + } + append_compressed_univariate_poly(transcript, context.driver.round_label, poly); + let challenge = transcript.challenge(); + running_claim = poly.evaluate(challenge); + point.push(challenge); + } + if !proof.point.is_empty() && proof.point != point { + return Err(Stage4KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched point mismatch", + }); + } + let expected = + expected_batched_output_claim(context, &store, &proof.evals, &point, &batching_coeffs)?; + if running_claim != expected { + return Err(Stage4KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched output claim mismatch", + }); + } + let output = Stage4SumcheckOutput { + driver: context.driver.symbol, + point, + evals: proof.evals.clone(), + opening_claims: Vec::new(), + proof: proof.proof.clone(), + }; + store.observe_sumcheck_output(context.program, &output)?; + let opening_claims = + append_opening_claims(context.program, &mut store, transcript, &output.evals)?; + let output = Stage4SumcheckOutput { + opening_claims, + ..output + }; + Ok(output) +} + +struct Stage4BatchedInstance<'a, F: Field> { + claim: &'a Stage4SumcheckClaimPlan, + relation: Stage4Relation, + offset: usize, + previous_claim: F, + state: Stage4ProverInstanceState, +} + +impl Stage4BatchedInstance<'_, F> { + fn is_active(&self, round: usize) -> bool { + round >= self.offset && round < self.offset + self.claim.num_rounds + } +} + +enum Stage4ProverInstanceState { + Dense(DenseStage4State), + SparseRegisters(SparseRegistersState), +} + +impl Stage4ProverInstanceState { + fn new( + program: &'static Stage4CpuProgramPlan, + claim: &Stage4SumcheckClaimPlan, + inputs: &Stage4ProverInputs<'_, F>, + store: &Stage4ValueStore, + active_scale: F, + ) -> Result { + match claim_relation(program, claim)? { + Stage4Relation::RegistersReadWrite => { + registers_read_write_state(claim, inputs, store, active_scale) + } + Stage4Relation::RamValCheck => { + ram_val_check_state(claim, inputs, store, active_scale).map(Self::Dense) + } + relation @ Stage4Relation::Batched => Err(Stage4KernelError::KernelNotImplemented { + abi: relation.symbol(), + }), + } + } + + fn round_poly( + &mut self, + previous_claim: F, + relation: Stage4Relation, + ) -> Result, Stage4KernelError> { + match self { + Self::Dense(state) => state.round_poly(previous_claim, relation), + Self::SparseRegisters(state) => state.round_poly(previous_claim, relation), + } + } + + fn ingest_challenge(&mut self, challenge: F) { + match self { + Self::Dense(state) => state.bind(challenge), + Self::SparseRegisters(state) => state.bind(challenge), + } + } + + fn final_evals( + &self, + relation: Stage4Relation, + ) -> Result>, Stage4KernelError> { + match self { + Self::Dense(state) => state.final_evals(relation), + Self::SparseRegisters(state) => state.final_evals(relation), + } + } +} + +#[derive(Clone)] +struct DenseStage4State { + factors: Vec>, + factor_scratch: Vec>, + terms: Vec>, + outputs: Vec, + active_scale: F, +} + +#[derive(Clone)] +struct DenseTerm { + coefficient: F, + factors: Vec, +} + +#[derive(Clone, Copy)] +struct FactorOutput { + name: &'static str, + oracle: &'static str, + factor: usize, +} + +impl DenseStage4State { + fn new( + factors: Vec>, + terms: Vec>, + outputs: Vec, + active_scale: F, + ) -> Self { + let factor_scratch = (0..factors.len()).map(|_| Vec::new()).collect(); + Self { + factors, + factor_scratch, + terms, + outputs, + active_scale, + } + } + + fn round_poly( + &self, + previous_claim: F, + relation: Stage4Relation, + ) -> Result, Stage4KernelError> { + let first_len = self.factors.first().map_or(0, Vec::len); + if first_len == 0 || !first_len.is_power_of_two() { + return Err(Stage4KernelError::InvalidProof { + driver: relation.symbol(), + reason: "stage4 dense factor has invalid length", + }); + } + if self.factors.iter().any(|factor| factor.len() != first_len) { + return Err(Stage4KernelError::InvalidProof { + driver: relation.symbol(), + reason: "stage4 dense factors have inconsistent lengths", + }); + } + let poly = + round_poly_from_dense_terms(&self.factors, &self.terms, self.active_scale, relation)?; + if poly.evaluate(F::zero()) + poly.evaluate(F::one()) != previous_claim { + return Err(Stage4KernelError::InvalidProof { + driver: relation.symbol(), + reason: "stage4 relation input claim mismatch", + }); + } + Ok(poly) + } + + fn bind(&mut self, challenge: F) { + if self.factors.first().map_or(0, Vec::len) / 2 >= DENSE_BIND_PAR_THRESHOLD { + self.factors + .par_iter_mut() + .zip(self.factor_scratch.par_iter_mut()) + .for_each(|(factor, scratch)| { + bind_dense_evals_reuse(factor, scratch, challenge); + }); + } else { + for (factor, scratch) in self.factors.iter_mut().zip(&mut self.factor_scratch) { + bind_dense_evals_reuse(factor, scratch, challenge); + } + } + } + + fn factor_eval(&self, index: usize, relation: Stage4Relation) -> Result { + self.factors + .get(index) + .and_then(|values| values.first()) + .copied() + .ok_or(Stage4KernelError::InvalidProof { + driver: relation.symbol(), + reason: "empty stage4 factor", + }) + } + + fn final_evals( + &self, + relation: Stage4Relation, + ) -> Result>, Stage4KernelError> { + self.outputs + .iter() + .map(|output| { + Ok(named_eval( + output.name, + output.oracle, + self.factor_eval(output.factor, relation)?, + )) + }) + .collect() + } +} + +#[derive(Clone)] +struct SparseRegistersState { + register_count: usize, + trace_len: usize, + current_trace_len: usize, + entries: Vec>, + entry_scratch: Vec>, + rs2_reads: Vec<(usize, usize)>, + eq_cycle: SplitEqState, + rd_inc: Vec, + rd_inc_scratch: Vec, + gamma: F, + gamma2: F, + active_scale: F, + bound_point: Vec, + dense: Option>, +} + +#[derive(Clone, Copy, Debug)] +struct SparseRegisterEntry { + row: usize, + col: u8, + val: F, + prev_val: u64, + next_val: u64, + read_ra: F, + rd_wa: F, +} + +impl SparseRegistersState { + fn new( + register_count: usize, + trace_len: usize, + accesses: &[Stage4RegisterAccess], + rd_inc: &[F], + trace_point: &[F], + gamma: F, + gamma2: F, + active_scale: F, + ) -> Result { + require_operand_count("stage4.registers.accesses", trace_len, accesses.len())?; + require_operand_count("stage4.registers.RdInc", trace_len, rd_inc.len())?; + let mut entries = Vec::with_capacity(accesses.len().saturating_mul(3)); + let mut rs2_reads = Vec::with_capacity(accesses.len()); + for (row, access) in accesses.iter().enumerate() { + append_sparse_register_entries( + register_count, + row, + *access, + gamma, + gamma2, + &mut entries, + )?; + if let Some(rs2) = access.rs2 { + rs2_reads.push((row, rs2.address)); + } + } + let eq_cycle = SplitEqState::new_low_to_high(trace_point, None); + let mut state = Self { + register_count, + trace_len, + current_trace_len: trace_len, + entries, + entry_scratch: Vec::new(), + rs2_reads, + eq_cycle, + rd_inc: rd_inc.to_vec(), + rd_inc_scratch: Vec::new(), + gamma, + gamma2, + active_scale, + bound_point: Vec::with_capacity( + log2_exact(register_count, "stage4.register_count")? + + log2_exact(trace_len, "stage4.trace_len")?, + ), + dense: None, + }; + if trace_len == 1 { + state.materialize_dense()?; + } + Ok(state) + } + + fn round_poly( + &mut self, + previous_claim: F, + relation: Stage4Relation, + ) -> Result, Stage4KernelError> { + if let Some(dense) = &self.dense { + return dense.round_poly(previous_claim, relation); + } + if self.current_trace_len <= 1 { + return Err(Stage4KernelError::InvalidProof { + driver: relation.symbol(), + reason: "stage4 sparse registers state was not materialized", + }); + } + let (mut q_constant, mut q_quadratic) = sparse_register_split_round_coefficients( + &self.entries, + &self.eq_cycle, + &self.rd_inc, + self.current_trace_len, + )?; + q_constant *= self.active_scale; + q_quadratic *= self.active_scale; + let poly = gruen_cubic_poly( + self.eq_cycle.current_target(), + q_constant, + q_quadratic, + previous_claim, + ); + if poly.evaluate(F::zero()) + poly.evaluate(F::one()) != previous_claim { + return Err(Stage4KernelError::InvalidProof { + driver: relation.symbol(), + reason: "stage4 sparse registers input claim mismatch", + }); + } + Ok(poly) + } + + fn bind(&mut self, challenge: F) { + self.bound_point.push(challenge); + if let Some(dense) = &mut self.dense { + dense.bind(challenge); + return; + } + bind_sparse_register_entries_into( + &self.entries, + self.current_trace_len, + challenge, + &mut self.entry_scratch, + ); + std::mem::swap(&mut self.entries, &mut self.entry_scratch); + self.entry_scratch.clear(); + self.eq_cycle.bind(challenge); + bind_dense_evals_reuse(&mut self.rd_inc, &mut self.rd_inc_scratch, challenge); + self.current_trace_len /= 2; + if self.current_trace_len == 1 { + let _ = self.materialize_dense(); + } + } + + fn final_evals( + &self, + relation: Stage4Relation, + ) -> Result>, Stage4KernelError> { + let dense = self.dense.as_ref().ok_or(Stage4KernelError::InvalidProof { + driver: relation.symbol(), + reason: "stage4 sparse registers state was not materialized", + })?; + let registers_val = dense.factor_eval(1, relation)?; + let combined_read_ra = dense.factor_eval(2, relation)?; + let rd_wa = dense.factor_eval(3, relation)?; + let rd_inc = dense.factor_eval(4, relation)?; + let rs2_ra = self.final_rs2_read_eval(relation)?; + let gamma_inverse = self + .gamma + .inverse() + .ok_or(Stage4KernelError::InvalidProof { + driver: relation.symbol(), + reason: "stage4 registers challenge is not invertible", + })?; + let rs1_ra = (combined_read_ra - self.gamma2 * rs2_ra) * gamma_inverse; + #[cfg(debug_assertions)] + { + let expected = self.gamma * rs1_ra + self.gamma2 * rs2_ra; + if combined_read_ra != expected { + return Err(Stage4KernelError::InvalidProof { + driver: relation.symbol(), + reason: "stage4 sparse registers final read claim mismatch", + }); + } + } + Ok(vec![ + named_eval( + "stage4.registers_read_write.eval.RegistersVal", + "RegistersVal", + registers_val, + ), + named_eval("stage4.registers_read_write.eval.Rs1Ra", "Rs1Ra", rs1_ra), + named_eval("stage4.registers_read_write.eval.Rs2Ra", "Rs2Ra", rs2_ra), + named_eval("stage4.registers_read_write.eval.RdWa", "RdWa", rd_wa), + named_eval("stage4.registers_read_write.eval.RdInc", "RdInc", rd_inc), + ]) + } + + fn materialize_dense(&mut self) -> Result<(), Stage4KernelError> { + let mut registers_val = vec![F::zero(); self.register_count]; + let mut read_ra = vec![F::zero(); self.register_count]; + let mut rd_wa = vec![F::zero(); self.register_count]; + for entry in &self.entries { + let col = usize::from(entry.col); + if entry.row != 0 || col >= self.register_count { + return Err(Stage4KernelError::InvalidInputLength { + input: "stage4.registers.accesses", + expected: self.register_count, + actual: col + 1, + }); + } + registers_val[col] = entry.val; + read_ra[col] = entry.read_ra; + rd_wa[col] = entry.rd_wa; + } + let eq_eval = self.eq_cycle.eval(); + let rd_inc_eval = + self.rd_inc + .first() + .copied() + .ok_or(Stage4KernelError::InvalidInputLength { + input: "stage4.registers.RdInc", + expected: 1, + actual: 0, + })?; + self.dense = Some(registers_combined_dense_state( + vec![eq_eval; self.register_count], + registers_val, + read_ra, + rd_wa, + vec![rd_inc_eval; self.register_count], + self.active_scale, + )); + Ok(()) + } + + fn final_rs2_read_eval(&self, relation: Stage4Relation) -> Result { + let trace_rounds = log2_exact(self.trace_len, "stage4.trace_len")?; + let register_rounds = log2_exact(self.register_count, "stage4.register_count")?; + if self.bound_point.len() != trace_rounds + register_rounds { + return Err(Stage4KernelError::InvalidInputLength { + input: "stage4.registers_read_write.instance", + expected: trace_rounds + register_rounds, + actual: self.bound_point.len(), + }); + } + let (cycle_point, address_point) = self.bound_point.split_at(trace_rounds); + let r_cycle = reverse_slice(cycle_point); + let r_address = reverse_slice(address_point); + let (cycle_eq, address_eq) = rayon::join( + || EqPolynomial::::evals(&r_cycle, None), + || EqPolynomial::::evals(&r_address, None), + ); + if cycle_eq.len() != self.trace_len || address_eq.len() != self.register_count { + return Err(Stage4KernelError::InvalidProof { + driver: relation.symbol(), + reason: "stage4 sparse registers final read point has invalid shape", + }); + } + Ok(sparse_register_read_eval( + &self.rs2_reads, + &cycle_eq, + &address_eq, + )) + } +} + +fn registers_read_write_state( + claim: &Stage4SumcheckClaimPlan, + inputs: &Stage4ProverInputs<'_, F>, + store: &Stage4ValueStore, + active_scale: F, +) -> Result, Stage4KernelError> { + let witness = inputs + .registers + .ok_or(Stage4KernelError::MissingKernelInput { + kernel: "jolt_stage4_batched", + input: "registers", + })?; + let expected_len = witness + .register_count + .checked_mul(witness.trace_len) + .ok_or(Stage4KernelError::InvalidInputLength { + input: "stage4.registers", + expected: usize::MAX, + actual: witness.register_count, + })?; + + let trace_point = store.point("stage4.input.stage3.registers.RdWriteValue")?; + let register_rounds = log2_exact(witness.register_count, "stage4.register_count")?; + let trace_rounds = log2_exact(witness.trace_len, "stage4.trace_len")?; + require_operand_count( + "stage4.registers.trace_point", + trace_rounds, + trace_point.len(), + )?; + require_operand_count( + claim.symbol, + register_rounds + trace_rounds, + claim.num_rounds, + )?; + + let gamma = store.scalar("stage4.registers_read_write.gamma")?; + let gamma2 = store + .try_scalar("stage4.registers_read_write.gamma2") + .unwrap_or_else(|| gamma * gamma); + + if let Some(accesses) = witness.accesses { + return SparseRegistersState::new( + witness.register_count, + witness.trace_len, + accesses, + witness.rd_inc, + trace_point, + gamma, + gamma2, + active_scale, + ) + .map(Stage4ProverInstanceState::SparseRegisters); + } + + require_operand_count( + "stage4.registers.RegistersVal", + expected_len, + witness.registers_val.len(), + )?; + require_operand_count("stage4.registers.Rs1Ra", expected_len, witness.rs1_ra.len())?; + require_operand_count("stage4.registers.Rs2Ra", expected_len, witness.rs2_ra.len())?; + require_operand_count("stage4.registers.RdWa", expected_len, witness.rd_wa.len())?; + require_operand_count( + "stage4.registers.RdInc", + witness.trace_len, + witness.rd_inc.len(), + )?; + let eq_cycle = EqPolynomial::::evals(trace_point, None); + let mut eq_cycle_expanded = Vec::with_capacity(expected_len); + let mut rd_inc_expanded = Vec::with_capacity(expected_len); + for _address in 0..witness.register_count { + eq_cycle_expanded.extend_from_slice(&eq_cycle); + rd_inc_expanded.extend_from_slice(witness.rd_inc); + } + + Ok(Stage4ProverInstanceState::Dense(registers_dense_state( + eq_cycle_expanded, + witness.registers_val.to_vec(), + witness.rs1_ra.to_vec(), + witness.rs2_ra.to_vec(), + witness.rd_wa.to_vec(), + rd_inc_expanded, + gamma, + gamma2, + active_scale, + ))) +} + +fn registers_dense_state( + eq_cycle: Vec, + registers_val: Vec, + rs1_ra: Vec, + rs2_ra: Vec, + rd_wa: Vec, + rd_inc: Vec, + gamma: F, + gamma2: F, + active_scale: F, +) -> DenseStage4State { + DenseStage4State::new( + vec![eq_cycle, registers_val, rs1_ra, rs2_ra, rd_wa, rd_inc], + vec![ + DenseTerm { + coefficient: F::one(), + factors: vec![0, 4, 1], + }, + DenseTerm { + coefficient: F::one(), + factors: vec![0, 4, 5], + }, + DenseTerm { + coefficient: gamma, + factors: vec![0, 2, 1], + }, + DenseTerm { + coefficient: gamma2, + factors: vec![0, 3, 1], + }, + ], + vec![ + FactorOutput { + name: "stage4.registers_read_write.eval.RegistersVal", + oracle: "RegistersVal", + factor: 1, + }, + FactorOutput { + name: "stage4.registers_read_write.eval.Rs1Ra", + oracle: "Rs1Ra", + factor: 2, + }, + FactorOutput { + name: "stage4.registers_read_write.eval.Rs2Ra", + oracle: "Rs2Ra", + factor: 3, + }, + FactorOutput { + name: "stage4.registers_read_write.eval.RdWa", + oracle: "RdWa", + factor: 4, + }, + FactorOutput { + name: "stage4.registers_read_write.eval.RdInc", + oracle: "RdInc", + factor: 5, + }, + ], + active_scale, + ) +} + +fn registers_combined_dense_state( + eq_cycle: Vec, + registers_val: Vec, + read_ra: Vec, + rd_wa: Vec, + rd_inc: Vec, + active_scale: F, +) -> DenseStage4State { + DenseStage4State::new( + vec![eq_cycle, registers_val, read_ra, rd_wa, rd_inc], + vec![ + DenseTerm { + coefficient: F::one(), + factors: vec![0, 3, 1], + }, + DenseTerm { + coefficient: F::one(), + factors: vec![0, 3, 4], + }, + DenseTerm { + coefficient: F::one(), + factors: vec![0, 2, 1], + }, + ], + Vec::new(), + active_scale, + ) +} + +fn append_sparse_register_entries( + register_count: usize, + row: usize, + access: Stage4RegisterAccess, + gamma: F, + gamma2: F, + entries: &mut Vec>, +) -> Result<(), Stage4KernelError> { + let start = entries.len(); + if let Some(rs1) = access.rs1 { + validate_register_address(register_count, rs1.address)?; + let col = sparse_register_col(rs1.address)?; + entries.push(SparseRegisterEntry { + row, + col, + val: F::from_u64(rs1.value), + prev_val: rs1.value, + next_val: rs1.value, + read_ra: gamma, + rd_wa: F::zero(), + }); + } + if let Some(rs2) = access.rs2 { + validate_register_address(register_count, rs2.address)?; + let col = sparse_register_col(rs2.address)?; + if let Some(entry) = entries[start..].iter_mut().find(|entry| entry.col == col) { + entry.read_ra += gamma2; + } else { + entries.push(SparseRegisterEntry { + row, + col, + val: F::from_u64(rs2.value), + prev_val: rs2.value, + next_val: rs2.value, + read_ra: gamma2, + rd_wa: F::zero(), + }); + } + } + if let Some(rd) = access.rd { + validate_register_address(register_count, rd.address)?; + let col = sparse_register_col(rd.address)?; + if let Some(entry) = entries[start..].iter_mut().find(|entry| entry.col == col) { + entry.rd_wa = F::one(); + entry.next_val = rd.post_value; + } else { + entries.push(SparseRegisterEntry { + row, + col, + val: F::from_u64(rd.pre_value), + prev_val: rd.pre_value, + next_val: rd.post_value, + read_ra: F::zero(), + rd_wa: F::one(), + }); + } + } + entries[start..].sort_by_key(|entry| entry.col); + Ok(()) +} + +fn sparse_register_col(address: usize) -> Result { + u8::try_from(address).map_err(|_| Stage4KernelError::InvalidInputLength { + input: "stage4.registers.accesses", + expected: usize::from(u8::MAX) + 1, + actual: address + 1, + }) +} + +fn validate_register_address( + register_count: usize, + address: usize, +) -> Result<(), Stage4KernelError> { + if address < register_count { + Ok(()) + } else { + Err(Stage4KernelError::InvalidInputLength { + input: "stage4.registers.accesses", + expected: register_count, + actual: address + 1, + }) + } +} + +fn sparse_register_split_round_coefficients( + entries: &[SparseRegisterEntry], + eq_cycle: &SplitEqState, + rd_inc: &[F], + current_trace_len: usize, +) -> Result<(F, F), Stage4KernelError> { + if let Some(entry) = entries.last() { + if entry.row >= current_trace_len { + return Err(Stage4KernelError::InvalidInputLength { + input: "stage4.registers.accesses", + expected: current_trace_len, + actual: entry.row + 1, + }); + } + } + let e_in = eq_cycle.e_in(); + let e_out = eq_cycle.e_out(); + if e_in.len() > 1 { + sparse_register_low_round_coefficients(entries, rd_inc, e_in, e_out) + } else { + sparse_register_high_round_coefficients(entries, rd_inc, e_in[0], e_out) + } +} + +fn sparse_register_low_round_coefficients( + entries: &[SparseRegisterEntry], + rd_inc: &[F], + e_in: &[F], + e_out: &[F], +) -> Result<(F, F), Stage4KernelError> { + let in_pairs = e_in.len() / 2; + if entries.len() >= DENSE_BIND_PAR_THRESHOLD { + let accumulators = entries + .par_chunk_by(|left, right| (left.row / 2) / in_pairs == (right.row / 2) / in_pairs) + .map(|entries| { + let mut local = [F::Accumulator::default(); 2]; + accumulate_sparse_register_low_outer_chunk( + &mut local, entries, rd_inc, e_in, e_out, in_pairs, + ); + local + }) + .reduce( + || [F::Accumulator::default(); 2], + |mut left, right| { + for (left, right) in left.iter_mut().zip(right) { + left.merge(right); + } + left + }, + ); + return Ok((accumulators[0].reduce(), accumulators[1].reduce())); + } + + let mut accumulators = [F::Accumulator::default(); 2]; + let mut cursor = 0usize; + while cursor < entries.len() { + let pair = entries[cursor].row / 2; + let x_out = pair / in_pairs; + let x_in = pair % in_pairs; + let weight = e_out[x_out] * (e_in[2 * x_in] + e_in[2 * x_in + 1]); + let even_row = 2 * pair; + let odd_row = even_row + 1; + let even_start = cursor; + while cursor < entries.len() && entries[cursor].row == even_row { + cursor += 1; + } + let even = &entries[even_start..cursor]; + let odd_start = cursor; + while cursor < entries.len() && entries[cursor].row == odd_row { + cursor += 1; + } + let odd = &entries[odd_start..cursor]; + accumulate_sparse_register_row_pair_body_coefficients( + &mut accumulators, + even, + odd, + rd_inc[even_row], + rd_inc[odd_row] - rd_inc[even_row], + weight, + ); + } + Ok((accumulators[0].reduce(), accumulators[1].reduce())) +} + +fn sparse_register_high_round_coefficients( + entries: &[SparseRegisterEntry], + rd_inc: &[F], + in_weight: F, + e_out: &[F], +) -> Result<(F, F), Stage4KernelError> { + if entries.len() >= DENSE_BIND_PAR_THRESHOLD { + let accumulators = entries + .par_chunk_by(|left, right| left.row / 2 == right.row / 2) + .map(|entries| { + let mut local = [F::Accumulator::default(); 2]; + let pair = entries[0].row / 2; + let weight = in_weight * (e_out[2 * pair] + e_out[2 * pair + 1]); + accumulate_sparse_register_row_pair_chunk(&mut local, entries, rd_inc, weight); + local + }) + .reduce( + || [F::Accumulator::default(); 2], + |mut left, right| { + for (left, right) in left.iter_mut().zip(right) { + left.merge(right); + } + left + }, + ); + return Ok((accumulators[0].reduce(), accumulators[1].reduce())); + } + + let mut accumulators = [F::Accumulator::default(); 2]; + let mut cursor = 0usize; + while cursor < entries.len() { + let pair = entries[cursor].row / 2; + let weight = in_weight * (e_out[2 * pair] + e_out[2 * pair + 1]); + let start = cursor; + let even_row = 2 * pair; + while cursor < entries.len() + && (entries[cursor].row == even_row || entries[cursor].row == even_row + 1) + { + cursor += 1; + } + accumulate_sparse_register_row_pair_chunk( + &mut accumulators, + &entries[start..cursor], + rd_inc, + weight, + ); + } + Ok((accumulators[0].reduce(), accumulators[1].reduce())) +} + +fn accumulate_sparse_register_low_outer_chunk( + accumulators: &mut [F::Accumulator; 2], + entries: &[SparseRegisterEntry], + rd_inc: &[F], + e_in: &[F], + e_out: &[F], + in_pairs: usize, +) { + let x_out = (entries[0].row / 2) / in_pairs; + let out_weight = e_out[x_out]; + for entries in entries.chunk_by(|left, right| left.row / 2 == right.row / 2) { + let pair = entries[0].row / 2; + let x_in = pair % in_pairs; + let weight = out_weight * (e_in[2 * x_in] + e_in[2 * x_in + 1]); + accumulate_sparse_register_row_pair_chunk(accumulators, entries, rd_inc, weight); + } +} + +fn accumulate_sparse_register_row_pair_chunk( + accumulators: &mut [F::Accumulator; 2], + entries: &[SparseRegisterEntry], + rd_inc: &[F], + weight: F, +) { + let pair = entries[0].row / 2; + let even_row = 2 * pair; + let odd_start = entries.partition_point(|entry| entry.row == even_row); + let (even, odd) = entries.split_at(odd_start); + accumulate_sparse_register_row_pair_body_coefficients( + accumulators, + even, + odd, + rd_inc[even_row], + rd_inc[even_row + 1] - rd_inc[even_row], + weight, + ); +} + +#[derive(Clone)] +struct SparseRegisterPairRange { + pair: usize, + even: std::ops::Range, + odd: std::ops::Range, +} + +fn sparse_register_pair_ranges_into( + entries: &[SparseRegisterEntry], + current_trace_len: usize, + ranges: &mut Vec, +) -> Result<(), Stage4KernelError> { + let half = current_trace_len / 2; + ranges.clear(); + let mut cursor = 0usize; + while cursor < entries.len() { + let pair = entries[cursor].row / 2; + if pair >= half { + return Err(Stage4KernelError::InvalidInputLength { + input: "stage4.registers.accesses", + expected: current_trace_len, + actual: entries[cursor].row + 1, + }); + } + let even_row = 2 * pair; + let odd_row = even_row + 1; + let even_start = cursor; + while cursor < entries.len() && entries[cursor].row == even_row { + cursor += 1; + } + let even = even_start..cursor; + let odd_start = cursor; + while cursor < entries.len() && entries[cursor].row == odd_row { + cursor += 1; + } + let odd = odd_start..cursor; + ranges.push(SparseRegisterPairRange { pair, even, odd }); + } + Ok(()) +} + +fn sparse_register_pair_ranges( + entries: &[SparseRegisterEntry], + current_trace_len: usize, +) -> Result, Stage4KernelError> { + let mut ranges = Vec::new(); + sparse_register_pair_ranges_into(entries, current_trace_len, &mut ranges)?; + Ok(ranges) +} + +fn accumulate_sparse_register_row_pair_body_coefficients( + accumulators: &mut [F::Accumulator; 2], + even: &[SparseRegisterEntry], + odd: &[SparseRegisterEntry], + inc0: F, + inc_delta: F, + weight: F, +) { + let mut i = 0usize; + let mut j = 0usize; + while i < even.len() || j < odd.len() { + let (even_entry, odd_entry) = + if j >= odd.len() || (i < even.len() && even[i].col < odd[j].col) { + let pair = (Some(&even[i]), None); + i += 1; + pair + } else if i >= even.len() || odd[j].col < even[i].col { + let pair = (None, Some(&odd[j])); + j += 1; + pair + } else { + let pair = (Some(&even[i]), Some(&odd[j])); + i += 1; + j += 1; + pair + }; + accumulate_sparse_register_entry_pair_body_coefficients( + accumulators, + even_entry, + odd_entry, + inc0, + inc_delta, + weight, + ); + } +} + +#[derive(Clone, Copy)] +struct SparseRegisterEval { + val: F, + read_ra: F, + rd_wa: F, +} + +#[derive(Clone, Copy)] +struct SparseRegisterLinear { + val0: F, + val_delta: F, + read_ra0: F, + read_ra_delta: F, + rd_wa0: F, + rd_wa_delta: F, +} + +fn accumulate_sparse_register_entry_pair_body_coefficients( + accumulators: &mut [F::Accumulator; 2], + even: Option<&SparseRegisterEntry>, + odd: Option<&SparseRegisterEntry>, + inc0: F, + inc_delta: F, + weight: F, +) { + let linear = sparse_register_entry_linear(even, odd); + let val_inc0 = linear.val0 + inc0; + let val_inc_delta = linear.val_delta + inc_delta; + let body0 = linear.rd_wa0 * val_inc0 + linear.read_ra0 * linear.val0; + let body2 = linear.rd_wa_delta * val_inc_delta + linear.read_ra_delta * linear.val_delta; + + accumulators[0].fmadd(weight, body0); + accumulators[1].fmadd(weight, body2); +} + +fn sparse_register_entry_linear( + even: Option<&SparseRegisterEntry>, + odd: Option<&SparseRegisterEntry>, +) -> SparseRegisterLinear { + match (even, odd) { + (Some(even), Some(odd)) => SparseRegisterLinear { + val0: even.val, + val_delta: odd.val - even.val, + read_ra0: even.read_ra, + read_ra_delta: odd.read_ra - even.read_ra, + rd_wa0: even.rd_wa, + rd_wa_delta: odd.rd_wa - even.rd_wa, + }, + (Some(even), None) => SparseRegisterLinear { + val0: even.val, + val_delta: F::from_u64(even.next_val) - even.val, + read_ra0: even.read_ra, + read_ra_delta: -even.read_ra, + rd_wa0: even.rd_wa, + rd_wa_delta: -even.rd_wa, + }, + (None, Some(odd)) => SparseRegisterLinear { + val0: F::from_u64(odd.prev_val), + val_delta: odd.val - F::from_u64(odd.prev_val), + read_ra0: F::zero(), + read_ra_delta: odd.read_ra, + rd_wa0: F::zero(), + rd_wa_delta: odd.rd_wa, + }, + (None, None) => SparseRegisterLinear { + val0: F::zero(), + val_delta: F::zero(), + read_ra0: F::zero(), + read_ra_delta: F::zero(), + rd_wa0: F::zero(), + rd_wa_delta: F::zero(), + }, + } +} + +fn sparse_register_entry_eval( + even: Option<&SparseRegisterEntry>, + odd: Option<&SparseRegisterEntry>, + x: F, +) -> SparseRegisterEval { + match (even, odd) { + (Some(even), Some(odd)) => SparseRegisterEval { + val: linear_eval(even.val, odd.val, x), + read_ra: linear_eval(even.read_ra, odd.read_ra, x), + rd_wa: linear_eval(even.rd_wa, odd.rd_wa, x), + }, + (Some(even), None) => SparseRegisterEval { + val: linear_eval(even.val, F::from_u64(even.next_val), x), + read_ra: linear_eval(even.read_ra, F::zero(), x), + rd_wa: linear_eval(even.rd_wa, F::zero(), x), + }, + (None, Some(odd)) => SparseRegisterEval { + val: linear_eval(F::from_u64(odd.prev_val), odd.val, x), + read_ra: linear_eval(F::zero(), odd.read_ra, x), + rd_wa: linear_eval(F::zero(), odd.rd_wa, x), + }, + (None, None) => SparseRegisterEval { + val: F::zero(), + read_ra: F::zero(), + rd_wa: F::zero(), + }, + } +} + +fn bind_sparse_register_entries_into( + entries: &[SparseRegisterEntry], + current_trace_len: usize, + challenge: F, + output: &mut Vec>, +) { + output.clear(); + if entries.len() >= DENSE_BIND_PAR_THRESHOLD { + if let Ok(ranges) = sparse_register_pair_ranges(entries, current_trace_len) { + let bound_lengths = ranges + .par_iter() + .map(|range| { + sparse_register_row_pair_bound_len( + &entries[range.even.clone()], + &entries[range.odd.clone()], + ) + }) + .collect::>(); + let output_len = bound_lengths.iter().sum(); + output.reserve(output_len); + let mut spare = output.spare_capacity_mut(); + let mut output_slices = Vec::with_capacity(ranges.len()); + for &bound_len in &bound_lengths { + let (slice, rest) = spare.split_at_mut(bound_len); + output_slices.push(slice); + spare = rest; + } + ranges + .par_iter() + .zip(output_slices.into_par_iter()) + .for_each(|(range, output)| { + bind_sparse_register_row_pair_into( + &entries[range.even.clone()], + &entries[range.odd.clone()], + range.pair, + challenge, + output, + ); + }); + // SAFETY: every slot in `output_slices` was initialized exactly once by + // `bind_sparse_register_row_pair_into`. + unsafe { + output.set_len(output_len); + } + return; + } + } + + bind_sparse_register_entries_sequential_into(entries, challenge, output); +} + +fn bind_sparse_register_entries_sequential_into( + entries: &[SparseRegisterEntry], + challenge: F, + output: &mut Vec>, +) { + output.reserve(entries.len()); + let mut cursor = 0usize; + while cursor < entries.len() { + let pair = entries[cursor].row / 2; + let even_row = 2 * pair; + let odd_row = even_row + 1; + let even_start = cursor; + while cursor < entries.len() && entries[cursor].row == even_row { + cursor += 1; + } + let even = &entries[even_start..cursor]; + let odd_start = cursor; + while cursor < entries.len() && entries[cursor].row == odd_row { + cursor += 1; + } + let odd = &entries[odd_start..cursor]; + bind_sparse_register_row_pair(even, odd, pair, challenge, output); + } +} + +fn sparse_register_row_pair_bound_len( + even: &[SparseRegisterEntry], + odd: &[SparseRegisterEntry], +) -> usize { + let mut i = 0usize; + let mut j = 0usize; + let mut len = 0usize; + while i < even.len() || j < odd.len() { + if j >= odd.len() || (i < even.len() && even[i].col < odd[j].col) { + i += 1; + } else if i >= even.len() || odd[j].col < even[i].col { + j += 1; + } else { + i += 1; + j += 1; + } + len += 1; + } + len +} + +fn bind_sparse_register_row_pair_into( + even: &[SparseRegisterEntry], + odd: &[SparseRegisterEntry], + row: usize, + challenge: F, + output: &mut [MaybeUninit>], +) { + let mut i = 0usize; + let mut j = 0usize; + let mut out = 0usize; + while i < even.len() || j < odd.len() { + let (even_entry, odd_entry, col) = + if j >= odd.len() || (i < even.len() && even[i].col < odd[j].col) { + let pair = (Some(&even[i]), None, even[i].col); + i += 1; + pair + } else if i >= even.len() || odd[j].col < even[i].col { + let pair = (None, Some(&odd[j]), odd[j].col); + j += 1; + pair + } else { + let pair = (Some(&even[i]), Some(&odd[j]), even[i].col); + i += 1; + j += 1; + pair + }; + output[out] = MaybeUninit::new(bind_sparse_register_entry_pair( + even_entry, odd_entry, row, col, challenge, + )); + out += 1; + } + debug_assert_eq!(out, output.len()); +} + +fn bind_sparse_register_row_pair( + even: &[SparseRegisterEntry], + odd: &[SparseRegisterEntry], + row: usize, + challenge: F, + output: &mut Vec>, +) { + let mut i = 0usize; + let mut j = 0usize; + while i < even.len() || j < odd.len() { + let (even_entry, odd_entry, col) = + if j >= odd.len() || (i < even.len() && even[i].col < odd[j].col) { + let pair = (Some(&even[i]), None, even[i].col); + i += 1; + pair + } else if i >= even.len() || odd[j].col < even[i].col { + let pair = (None, Some(&odd[j]), odd[j].col); + j += 1; + pair + } else { + let pair = (Some(&even[i]), Some(&odd[j]), even[i].col); + i += 1; + j += 1; + pair + }; + output.push(bind_sparse_register_entry_pair( + even_entry, odd_entry, row, col, challenge, + )); + } +} + +fn bind_sparse_register_entry_pair( + even: Option<&SparseRegisterEntry>, + odd: Option<&SparseRegisterEntry>, + row: usize, + col: u8, + challenge: F, +) -> SparseRegisterEntry { + let value = sparse_register_entry_eval(even, odd, challenge); + let (prev_val, next_val) = match (even, odd) { + (Some(even), Some(odd)) => (even.prev_val, odd.next_val), + (Some(even), None) => (even.prev_val, even.next_val), + (None, Some(odd)) => (odd.prev_val, odd.next_val), + (None, None) => (0, 0), + }; + SparseRegisterEntry { + row, + col, + val: value.val, + prev_val, + next_val, + read_ra: value.read_ra, + rd_wa: value.rd_wa, + } +} + +fn sparse_register_read_eval( + reads: &[(usize, usize)], + cycle_eq: &[F], + address_eq: &[F], +) -> F { + if reads.len() >= DENSE_BIND_PAR_THRESHOLD { + reads + .par_iter() + .map(|&(row, col)| { + debug_assert!(row < cycle_eq.len()); + debug_assert!(col < address_eq.len()); + cycle_eq[row] * address_eq[col] + }) + .sum() + } else { + reads + .iter() + .map(|&(row, col)| { + debug_assert!(row < cycle_eq.len()); + debug_assert!(col < address_eq.len()); + cycle_eq[row] * address_eq[col] + }) + .sum() + } +} + +fn linear_eval(low: F, high: F, x: F) -> F { + low + x * (high - low) +} + +fn gruen_cubic_poly( + target: F, + q_constant: F, + q_quadratic_coeff: F, + previous_claim: F, +) -> UnivariatePoly { + let eq_eval_1 = target; + let eq_eval_0 = F::one() - target; + let eq_delta = eq_eval_1 - eq_eval_0; + let eq_eval_2 = eq_eval_1 + eq_delta; + let eq_eval_3 = eq_eval_2 + eq_delta; + let cubic_eval_0 = eq_eval_0 * q_constant; + let cubic_eval_1 = previous_claim - cubic_eval_0; + let quadratic_eval_1 = cubic_eval_1 / eq_eval_1; + let e_times_2 = q_quadratic_coeff + q_quadratic_coeff; + let quadratic_eval_2 = quadratic_eval_1 + quadratic_eval_1 - q_constant + e_times_2; + let quadratic_eval_3 = quadratic_eval_2 + quadratic_eval_1 - q_constant + e_times_2 + e_times_2; + UnivariatePoly::from_evals(&[ + cubic_eval_0, + cubic_eval_1, + eq_eval_2 * quadratic_eval_2, + eq_eval_3 * quadratic_eval_3, + ]) +} + +#[tracing::instrument(skip_all, name = "ram_val_check_state")] +fn ram_val_check_state( + claim: &Stage4SumcheckClaimPlan, + inputs: &Stage4ProverInputs<'_, F>, + store: &Stage4ValueStore, + active_scale: F, +) -> Result, Stage4KernelError> { + let witness = inputs.ram.ok_or(Stage4KernelError::MissingKernelInput { + kernel: "jolt_stage4_batched", + input: "ram", + })?; + let expected_len = witness.ram_k.checked_mul(witness.trace_len).ok_or( + Stage4KernelError::InvalidInputLength { + input: "stage4.ram", + expected: usize::MAX, + actual: witness.ram_k, + }, + )?; + require_operand_count( + "stage4.ram.RamInc", + witness.trace_len, + witness.ram_inc.len(), + )?; + + let ram_val_point = store.point("stage4.input.stage2.RamVal")?; + let trace_rounds = log2_exact(witness.trace_len, "stage4.ram.trace_len")?; + let ram_rounds = log2_exact(witness.ram_k, "stage4.ram_k")?; + require_operand_count("stage4.ram_val_check.input", trace_rounds, claim.num_rounds)?; + require_operand_count( + "stage4.input.stage2.RamVal", + ram_rounds + trace_rounds, + ram_val_point.len(), + )?; + let (address_point, cycle_point) = ram_val_point.split_at(ram_rounds); + let address_eq = EqPolynomial::::evals(address_point, None); + let ram_ra_at_address = ram_ra_at_address(witness, &address_eq, expected_len)?; + + let gamma = store.scalar("stage4.ram_val_check.gamma")?; + let mut lt_plus_gamma = lt_evals_big_endian(cycle_point); + require_operand_count( + "stage4.ram_val_check.lt", + witness.trace_len, + lt_plus_gamma.len(), + )?; + lt_plus_gamma + .par_iter_mut() + .for_each(|value| *value += gamma); + + Ok(DenseStage4State::new( + vec![lt_plus_gamma, ram_ra_at_address, witness.ram_inc.to_vec()], + vec![DenseTerm { + coefficient: F::one(), + factors: vec![0, 1, 2], + }], + vec![ + FactorOutput { + name: "stage4.ram_val_check.eval.RamRa", + oracle: "RamRa", + factor: 1, + }, + FactorOutput { + name: "stage4.ram_val_check.eval.RamInc", + oracle: "RamInc", + factor: 2, + }, + ], + active_scale, + )) +} + +fn ram_ra_at_address( + witness: Stage4RamWitness<'_, F>, + address_eq: &[F], + dense_len: usize, +) -> Result, Stage4KernelError> { + if !witness.ram_ra.is_empty() { + require_operand_count("stage4.ram.RamRa", dense_len, witness.ram_ra.len())?; + let mut output = vec![F::zero(); witness.trace_len]; + for (address, &weight) in address_eq.iter().enumerate() { + let base = address * witness.trace_len; + for (cycle, output) in output.iter_mut().enumerate() { + *output += weight * witness.ram_ra[base + cycle]; + } + } + return Ok(output); + } + + let Some(write_address_indices) = witness.write_address_indices else { + return Err(Stage4KernelError::MissingKernelInput { + kernel: "jolt_stage4_batched", + input: "ram_ra", + }); + }; + require_operand_count( + "stage4.ram.write_address_indices", + witness.trace_len, + write_address_indices.len(), + )?; + write_address_indices + .iter() + .map(|address| match address { + Some(address) => { + address_eq + .get(*address) + .copied() + .ok_or(Stage4KernelError::InvalidInputLength { + input: "stage4.ram.write_address_indices", + expected: address_eq.len(), + actual: address + 1, + }) + } + None => Ok(F::zero()), + }) + .collect() +} + +fn round_poly_from_dense_terms( + factors: &[Vec], + terms: &[DenseTerm], + active_scale: F, + relation: Stage4Relation, +) -> Result, Stage4KernelError> { + let half = factors.first().map_or(0, |factor| factor.len() / 2); + for term in terms { + if term.factors.len() > 3 { + return Err(Stage4KernelError::InvalidProof { + driver: relation.symbol(), + reason: "stage4 dense term exceeds degree bound", + }); + } + if term.factors.iter().any(|factor| *factor >= factors.len()) { + return Err(Stage4KernelError::InvalidProof { + driver: relation.symbol(), + reason: "stage4 dense term references missing factor", + }); + } + } + + let accumulators = if half >= DENSE_BIND_PAR_THRESHOLD { + (0..half) + .into_par_iter() + .map(|row| dense_row_coefficients(factors, terms, row)) + .reduce( + || [F::Accumulator::default(); 4], + |mut left, right| { + for index in 0..left.len() { + left[index].merge(right[index]); + } + left + }, + ) + } else { + (0..half).fold([F::Accumulator::default(); 4], |mut total, row| { + let row_coefficients = dense_row_coefficients(factors, terms, row); + for index in 0..total.len() { + total[index].merge(row_coefficients[index]); + } + total + }) + }; + + Ok(UnivariatePoly::new( + accumulators + .into_iter() + .map(FieldAccumulator::reduce) + .map(|coefficient| coefficient * active_scale) + .collect(), + )) +} + +fn dense_row_coefficients( + factors: &[Vec], + terms: &[DenseTerm], + row: usize, +) -> [F::Accumulator; 4] { + let mut coefficients = [F::Accumulator::default(); 4]; + for term in terms { + match term.factors.as_slice() { + [] => coefficients[0].acc_add(term.coefficient), + [first] => { + let (first0, first_delta) = linear_factor_pair(&factors[*first], row); + coefficients[0].fmadd(term.coefficient, first0); + coefficients[1].fmadd(term.coefficient, first_delta); + } + [first, second] => { + let (first0, first_delta) = linear_factor_pair(&factors[*first], row); + let (second0, second_delta) = linear_factor_pair(&factors[*second], row); + accumulate_quadratic_coefficients( + &mut coefficients, + term.coefficient, + first0, + first_delta, + second0, + second_delta, + ); + } + [first, second, third] => { + let (first0, first_delta) = linear_factor_pair(&factors[*first], row); + let (second0, second_delta) = linear_factor_pair(&factors[*second], row); + let (third0, third_delta) = linear_factor_pair(&factors[*third], row); + accumulate_cubic_coefficients( + &mut coefficients, + term.coefficient, + first0, + first_delta, + second0, + second_delta, + third0, + third_delta, + ); + } + _ => unreachable!("dense terms are validated before evaluation"), + } + } + coefficients +} + +#[inline] +fn linear_factor_pair(factor: &[F], row: usize) -> (F, F) { + let low = factor[2 * row]; + (low, factor[2 * row + 1] - low) +} + +#[inline] +fn accumulate_quadratic_coefficients( + coefficients: &mut [F::Accumulator; 4], + scale: F, + first0: F, + first_delta: F, + second0: F, + second_delta: F, +) { + coefficients[0].fmadd(scale * first0, second0); + coefficients[1].fmadd(scale * first_delta, second0); + coefficients[1].fmadd(scale * first0, second_delta); + coefficients[2].fmadd(scale * first_delta, second_delta); +} + +#[inline] +fn accumulate_cubic_coefficients( + coefficients: &mut [F::Accumulator; 4], + scale: F, + first0: F, + first_delta: F, + second0: F, + second_delta: F, + third0: F, + third_delta: F, +) { + let second0_third0 = second0 * third0; + let second_delta_third0 = second_delta * third0; + let second0_third_delta = second0 * third_delta; + let second_delta_third_delta = second_delta * third_delta; + let scaled_first0 = scale * first0; + let scaled_first_delta = scale * first_delta; + + coefficients[0].fmadd(scaled_first0, second0_third0); + coefficients[1].fmadd(scaled_first_delta, second0_third0); + coefficients[1].fmadd(scaled_first0, second_delta_third0); + coefficients[1].fmadd(scaled_first0, second0_third_delta); + coefficients[2].fmadd(scaled_first_delta, second_delta_third0); + coefficients[2].fmadd(scaled_first_delta, second0_third_delta); + coefficients[2].fmadd(scaled_first0, second_delta_third_delta); + coefficients[3].fmadd(scaled_first_delta, second_delta_third_delta); +} + +fn expected_batched_output_claim( + context: Stage4KernelContext<'_>, + store: &Stage4ValueStore, + evals: &[Stage4NamedEval], + point: &[F], + batching_coeffs: &[F], +) -> Result { + let mut expected = F::zero(); + for (claim, &coefficient) in context.batch_claims()?.iter().zip(batching_coeffs) { + let instance = context + .program + .instance_results + .iter() + .find(|instance| { + instance.claim == claim.symbol && instance.source == context.driver.symbol + }) + .ok_or(Stage4KernelError::MissingClaim { + batch: context.batch.symbol, + claim: claim.symbol, + })?; + let local_point = point + .get(instance.round_offset..instance.round_offset + instance.num_rounds) + .ok_or(Stage4KernelError::InvalidInputLength { + input: instance.symbol, + expected: instance.round_offset + instance.num_rounds, + actual: point.len(), + })?; + let claim_value = match Stage4Relation::from_symbol(instance.relation).ok_or( + Stage4KernelError::UnknownRelation { + relation: instance.relation, + }, + )? { + Stage4Relation::RegistersReadWrite => { + expected_registers_read_write(store, evals, local_point)? + } + Stage4Relation::RamValCheck => expected_ram_val_check(store, evals, local_point)?, + relation @ Stage4Relation::Batched => { + return Err(Stage4KernelError::KernelNotImplemented { + abi: relation.symbol(), + }) + } + }; + expected += coefficient * claim_value; + } + Ok(expected) +} + +fn expected_registers_read_write( + store: &Stage4ValueStore, + evals: &[Stage4NamedEval], + local_point: &[F], +) -> Result { + let trace_point = store.point("stage4.input.stage3.registers.RdWriteValue")?; + let r_cycle = normalize_stage4_registers_rw_cycle_point( + local_point, + trace_point.len(), + "stage4.registers_read_write.instance", + )?; + let eq_eval = EqPolynomial::::mle(&r_cycle, trace_point); + let registers_val = eval_by_name(evals, "stage4.registers_read_write.eval.RegistersVal")?; + let rs1_ra = eval_by_name(evals, "stage4.registers_read_write.eval.Rs1Ra")?; + let rs2_ra = eval_by_name(evals, "stage4.registers_read_write.eval.Rs2Ra")?; + let rd_wa = eval_by_name(evals, "stage4.registers_read_write.eval.RdWa")?; + let rd_inc = eval_by_name(evals, "stage4.registers_read_write.eval.RdInc")?; + let gamma = store.scalar("stage4.registers_read_write.gamma")?; + Ok(eq_eval + * (rd_wa * (registers_val + rd_inc) + + gamma * (rs1_ra * registers_val + gamma * rs2_ra * registers_val))) +} + +fn expected_ram_val_check( + store: &Stage4ValueStore, + evals: &[Stage4NamedEval], + local_point: &[F], +) -> Result { + let ram_val_point = store.point("stage4.input.stage2.RamVal")?; + let r_cycle_prime = reverse_slice(local_point); + let r_cycle = suffix_point( + ram_val_point, + r_cycle_prime.len(), + "stage4.input.stage2.RamVal", + )?; + let lt_eval = lt_polynomial_eval(&r_cycle_prime, r_cycle); + let gamma = store.scalar("stage4.ram_val_check.gamma")?; + let ram_ra = eval_by_name(evals, "stage4.ram_val_check.eval.RamRa")?; + let ram_inc = eval_by_name(evals, "stage4.ram_val_check.eval.RamInc")?; + Ok(ram_inc * ram_ra * (lt_eval + gamma)) +} + +fn eval_by_name( + evals: &[Stage4NamedEval], + name: &'static str, +) -> Result { + evals + .iter() + .find(|eval| eval.name == name) + .map(|eval| eval.value) + .ok_or(Stage4KernelError::MissingValue { symbol: name }) +} + +fn named_eval(name: &'static str, oracle: &'static str, value: F) -> Stage4NamedEval { + Stage4NamedEval { + name, + oracle, + value, + } +} + +fn claim_relation( + program: &'static Stage4CpuProgramPlan, + claim: &Stage4SumcheckClaimPlan, +) -> Result { + if let Some(relation) = claim.relation { + return Stage4Relation::from_symbol(relation) + .ok_or(Stage4KernelError::UnknownRelation { relation }); + } + let kernel_symbol = claim.kernel.ok_or(Stage4KernelError::MissingKernel { + driver: claim.symbol, + kernel: "", + })?; + let kernel = find_kernel(program, kernel_symbol).ok_or(Stage4KernelError::MissingKernel { + driver: claim.symbol, + kernel: kernel_symbol, + })?; + kernel.relation_kind() +} + +fn instance_round_offset( + program: &'static Stage4CpuProgramPlan, + driver: &'static str, + claim: &'static str, +) -> Result { + program + .instance_results + .iter() + .find(|instance| instance.source == driver && instance.claim == claim) + .map(|instance| instance.round_offset) + .ok_or(Stage4KernelError::MissingClaim { + batch: driver, + claim, + }) +} + +fn combine_univariate_polys( + polynomials: &[UnivariatePoly], + coefficients: &[F], +) -> UnivariatePoly { + let max_len = polynomials + .iter() + .map(|poly| poly.coefficients().len()) + .max() + .unwrap_or(0); + let mut combined = vec![F::zero(); max_len]; + for (poly, &coefficient) in polynomials.iter().zip(coefficients) { + for (combined, &term) in combined.iter_mut().zip(poly.coefficients()) { + *combined += term * coefficient; + } + } + UnivariatePoly::new(combined) +} + +fn polynomial_degree(poly: &UnivariatePoly) -> usize { + poly.coefficients() + .iter() + .rposition(|coefficient| *coefficient != F::zero()) + .unwrap_or(0) +} + +fn append_compressed_univariate_poly( + transcript: &mut T, + label: &'static str, + poly: &UnivariatePoly, +) where + F: Field, + T: Transcript, +{ + let compressed = poly.compress(); + transcript.append(&LabelWithCount( + label.as_bytes(), + compressed.coeffs_except_linear_term().len() as u64, + )); + for coefficient in compressed.coeffs_except_linear_term() { + transcript.append(coefficient); + } +} + +fn append_labeled_scalar(transcript: &mut T, label: &'static str, scalar: &F) +where + F: Field, + T: Transcript, +{ + transcript.append(&Label(label.as_bytes())); + transcript.append(scalar); +} + +fn append_opening_claims( + program: &'static Stage4CpuProgramPlan, + store: &mut Stage4ValueStore, + transcript: &mut T, + evals: &[Stage4NamedEval], +) -> Result>, Stage4KernelError> +where + F: Field, + T: Transcript, +{ + if program.opening_batches.is_empty() { + for eval in evals { + append_labeled_scalar(transcript, "opening_claim", &eval.value); + } + return Ok(Vec::new()); + } + let _ = store.evaluate_available_points(program)?; + let mut opening_claims = Vec::new(); + let mut seen = seed_stage4_opening_aliases(store, program); + for batch in program.opening_batches { + for symbol in batch.claim_operands { + let claim = + find_opening_claim(program, symbol).ok_or(Stage4KernelError::MissingClaim { + batch: batch.symbol, + claim: symbol, + })?; + let point = store.point(claim.point_source)?.to_vec(); + let value = store.scalar(claim.eval_source)?; + let duplicate = has_seen_opening(&seen, claim.claim_kind, claim.oracle, &point); + if !duplicate { + append_labeled_scalar(transcript, "opening_claim", &value); + seen.push((claim.claim_kind, claim.oracle, point.clone())); + } + opening_claims.push(Stage4OpeningClaimValue { + symbol: claim.symbol, + oracle: claim.oracle, + domain: claim.domain, + claim_kind: claim.claim_kind, + point: point.clone(), + eval: value, + }); + } + } + Ok(opening_claims) +} + +fn seed_stage4_opening_aliases( + store: &Stage4ValueStore, + program: &'static Stage4CpuProgramPlan, +) -> Vec<(&'static str, &'static str, Vec)> { + program + .opening_inputs + .iter() + .filter_map(|input| { + store + .try_point(input.symbol) + .map(|point| (input.claim_kind, input.oracle, point.to_vec())) + }) + .collect() +} + +fn has_seen_opening( + seen: &[(&'static str, &'static str, Vec)], + claim_kind: &'static str, + oracle: &'static str, + point: &[F], +) -> bool { + seen.iter().any(|(seen_kind, seen_oracle, seen_point)| { + *seen_kind == claim_kind && *seen_oracle == oracle && seen_point.as_slice() == point + }) +} + +fn find_opening_claim<'a>( + program: &'a Stage4CpuProgramPlan, + symbol: &str, +) -> Option<&'a Stage4OpeningClaimPlan> { + program + .opening_claims + .iter() + .find(|claim| claim.symbol == symbol) +} + +fn normalize_stage4_registers_rw_point( + program: &'static Stage4CpuProgramPlan, + driver: &'static str, + point: &[F], +) -> Result, Stage4KernelError> { + let driver_plan = + find_driver(program, driver).ok_or(Stage4KernelError::MissingDriver { driver })?; + if driver_plan.round_schedule.len() != 2 { + return Err(Stage4KernelError::InvalidProof { + driver, + reason: "stage4 registers point normalization requires [cycle, address] schedule", + }); + } + let cycle_rounds = driver_plan.round_schedule[0]; + let address_rounds = driver_plan.round_schedule[1]; + if point.len() != cycle_rounds + address_rounds { + return Err(Stage4KernelError::InvalidInputLength { + input: "stage4.registers_read_write.instance", + expected: cycle_rounds + address_rounds, + actual: point.len(), + }); + } + let (cycle, address) = point.split_at(cycle_rounds); + Ok(address + .iter() + .rev() + .copied() + .chain(cycle.iter().rev().copied()) + .collect()) +} + +fn normalize_stage4_registers_rw_cycle_point( + point: &[F], + cycle_rounds: usize, + input: &'static str, +) -> Result, Stage4KernelError> { + let cycle = point + .get(..cycle_rounds) + .filter(|cycle| cycle.len() == cycle_rounds) + .ok_or(Stage4KernelError::InvalidInputLength { + input, + expected: cycle_rounds, + actual: point.len(), + })?; + Ok(cycle.iter().rev().copied().collect()) +} + +fn suffix_point<'a, F: Field>( + point: &'a [F], + length: usize, + input: &'static str, +) -> Result<&'a [F], Stage4KernelError> { + point + .get(point.len().saturating_sub(length)..) + .filter(|suffix| suffix.len() == length) + .ok_or(Stage4KernelError::InvalidInputLength { + input, + expected: length, + actual: point.len(), + }) +} + +fn reverse_slice(values: &[F]) -> Vec { + values.iter().rev().copied().collect() +} + +fn lt_polynomial_eval(x: &[F], y: &[F]) -> F { + debug_assert_eq!(x.len(), y.len()); + let mut lt_eval = F::zero(); + let mut eq_term = F::one(); + for (x_i, y_i) in x.iter().zip(y.iter()) { + lt_eval += (F::one() - *x_i) * *y_i * eq_term; + eq_term *= F::one() - *x_i - *y_i + *x_i * *y_i + *x_i * *y_i; + } + lt_eval +} + +fn lt_evals_big_endian(point: &[F]) -> Vec { + let mut evals = vec![F::zero(); 1usize << point.len()]; + for (index, r) in point.iter().rev().enumerate() { + let (left, right) = evals.split_at_mut(1usize << index); + left.iter_mut().zip(right).for_each(|(left, right)| { + *right = *left * *r; + *left += *r - *right; + }); + } + evals +} + +#[cfg(test)] +fn boolean_point_from_index(index: usize, bits: usize) -> Vec { + (0..bits) + .rev() + .map(|bit| F::from_bool(((index >> bit) & 1) == 1)) + .collect() +} + +fn log2_exact(value: usize, input: &'static str) -> Result { + if value.is_power_of_two() { + Ok(value.ilog2() as usize) + } else { + Err(Stage4KernelError::InvalidInputLength { + input, + expected: value.next_power_of_two(), + actual: value, + }) + } +} + +fn verify_count( + artifact: &'static str, + expected: usize, + actual: usize, +) -> Result<(), Stage4KernelError> { + if expected == actual { + Ok(()) + } else { + Err(Stage4KernelError::PlanCountMismatch { + artifact, + expected, + actual, + }) + } +} + +fn find_squeeze( + program: &'static Stage4CpuProgramPlan, + symbol: &str, +) -> Option<&'static Stage4TranscriptSqueezePlan> { + program + .transcript_squeezes + .iter() + .find(|squeeze| squeeze.symbol == symbol) +} + +fn find_absorb_bytes( + program: &'static Stage4CpuProgramPlan, + symbol: &str, +) -> Option<&'static Stage4TranscriptAbsorbBytesPlan> { + program + .transcript_absorb_bytes + .iter() + .find(|absorb| absorb.symbol == symbol) +} + +fn find_driver( + program: &'static Stage4CpuProgramPlan, + symbol: &str, +) -> Option<&'static Stage4SumcheckDriverPlan> { + program + .drivers + .iter() + .find(|driver| driver.symbol == symbol) +} + +fn find_kernel( + program: &'static Stage4CpuProgramPlan, + symbol: &str, +) -> Option<&'static Stage4KernelPlan> { + program + .kernels + .iter() + .find(|kernel| kernel.symbol == symbol) +} + +fn find_batch( + program: &'static Stage4CpuProgramPlan, + symbol: &str, +) -> Option<&'static Stage4SumcheckBatchPlan> { + program.batches.iter().find(|batch| batch.symbol == symbol) +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum Stage4KernelError { + MissingClaim { + batch: &'static str, + claim: &'static str, + }, + MissingValue { + symbol: &'static str, + }, + MissingDriver { + driver: &'static str, + }, + MissingKernel { + driver: &'static str, + kernel: &'static str, + }, + MissingBatch { + driver: &'static str, + batch: &'static str, + }, + UnknownRelation { + relation: &'static str, + }, + UnknownKernelAbi { + abi: &'static str, + }, + PlanCountMismatch { + artifact: &'static str, + expected: usize, + actual: usize, + }, + InvalidInputLength { + input: &'static str, + expected: usize, + actual: usize, + }, + UnsupportedFieldExpr { + symbol: &'static str, + formula: &'static str, + }, + KernelNotImplemented { + abi: &'static str, + }, + WrongExecutorMode { + driver: &'static str, + expected: Stage4ExecutionMode, + actual: Stage4ExecutionMode, + }, + MissingProof { + driver: &'static str, + }, + MissingKernelInput { + kernel: &'static str, + input: &'static str, + }, + InvalidProgramStep { + symbol: &'static str, + kind: &'static str, + }, + InvalidProof { + driver: &'static str, + reason: &'static str, + }, +} + +impl Display for Stage4KernelError { + fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result { + match self { + Self::MissingClaim { batch, claim } => { + write!( + formatter, + "stage4 batch @{batch} references missing claim @{claim}" + ) + } + Self::MissingValue { symbol } => { + write!(formatter, "stage4 value @{symbol} is not available") + } + Self::MissingDriver { driver } => { + write!(formatter, "stage4 driver @{driver} is not available") + } + Self::MissingKernel { driver, kernel } => { + write!( + formatter, + "stage4 driver @{driver} references missing kernel @{kernel}" + ) + } + Self::MissingBatch { driver, batch } => { + write!( + formatter, + "stage4 driver @{driver} references missing batch @{batch}" + ) + } + Self::UnknownRelation { relation } => { + write!(formatter, "stage4 relation @{relation} is not registered") + } + Self::UnknownKernelAbi { abi } => { + write!(formatter, "stage4 kernel ABI `{abi}` is not registered") + } + Self::PlanCountMismatch { + artifact, + expected, + actual, + } => write!( + formatter, + "stage4 plan @{artifact} count mismatch: expected {expected}, got {actual}" + ), + Self::InvalidInputLength { + input, + expected, + actual, + } => write!( + formatter, + "stage4 input `{input}` length mismatch: expected {expected}, got {actual}" + ), + Self::UnsupportedFieldExpr { symbol, formula } => write!( + formatter, + "stage4 field expr @{symbol} uses unsupported formula `{formula}`" + ), + Self::KernelNotImplemented { abi } => { + write!(formatter, "stage4 kernel ABI `{abi}` is not implemented") + } + Self::WrongExecutorMode { + driver, + expected, + actual, + } => write!( + formatter, + "stage4 driver @{driver} ran with {actual:?} executor path, expected {expected:?}" + ), + Self::MissingProof { driver } => { + write!( + formatter, + "stage4 verifier missing proof for driver @{driver}" + ) + } + Self::MissingKernelInput { kernel, input } => { + write!( + formatter, + "stage4 kernel `{kernel}` missing input `{input}`" + ) + } + Self::InvalidProgramStep { symbol, kind } => { + write!( + formatter, + "stage4 program step @{symbol} has unsupported kind `{kind}`" + ) + } + Self::InvalidProof { driver, reason } => { + write!( + formatter, + "stage4 proof for driver @{driver} is invalid: {reason}" + ) + } + } + } +} + +impl Error for Stage4KernelError {} + +#[cfg(test)] +#[expect(clippy::expect_used, reason = "stage4 kernel tests fail fast")] +mod tests { + use super::*; + use jolt_field::Fr; + use jolt_transcript::Blake2bTranscript; + + #[test] + fn lt_evals_big_endian_matches_pointwise() { + let point = frs(&[3, 5, 7]); + let table = lt_evals_big_endian(&point); + + assert_eq!(table.len(), 8); + for (index, value) in table.iter().enumerate() { + let bits = boolean_point_from_index::(index, point.len()); + assert_eq!(*value, lt_polynomial_eval(&bits, &point)); + } + } + + #[test] + fn stage4_batched_kernel_proves_and_verifies_synthetic_witness() { + let program = synthetic_stage4_program(); + let data = SyntheticStage4Data::new(); + let opening_inputs = data.opening_inputs(); + let prover_inputs = Stage4ProverInputs::new(&opening_inputs) + .with_registers(data.registers_witness()) + .with_ram(data.ram_witness()); + let mut prover = Stage4ProverKernelExecutor::new(prover_inputs); + let mut prover_transcript = Blake2bTranscript::::new(b"stage4_test"); + + let artifacts = execute_stage4_program( + program, + Stage4ExecutionMode::Prover, + &mut prover, + &mut prover_transcript, + ) + .expect("stage4 prover succeeds"); + + assert_eq!(artifacts.sumchecks.len(), 1); + assert_eq!(artifacts.sumchecks[0].proof.round_polynomials.len(), 3); + let proof = Stage4Proof::from(artifacts); + let mut verifier = Stage4VerifierKernelExecutor::new(&proof, &opening_inputs); + let mut verifier_transcript = Blake2bTranscript::::new(b"stage4_test"); + let verified = execute_stage4_program( + program, + Stage4ExecutionMode::Verifier, + &mut verifier, + &mut verifier_transcript, + ) + .expect("stage4 verifier accepts prover proof"); + + assert_eq!(verified.sumchecks.len(), 1); + assert_eq!(prover_transcript.state(), verifier_transcript.state()); + } + + #[test] + fn stage4_batched_kernel_proves_with_sparse_ram_addresses() { + let program = synthetic_stage4_program(); + let data = SyntheticStage4Data::new(); + let opening_inputs = data.opening_inputs(); + let prover_inputs = Stage4ProverInputs::new(&opening_inputs) + .with_registers(data.registers_witness()) + .with_ram(data.sparse_ram_witness()); + let mut prover = Stage4ProverKernelExecutor::new(prover_inputs); + let mut prover_transcript = Blake2bTranscript::::new(b"stage4_test"); + + let artifacts = execute_stage4_program( + program, + Stage4ExecutionMode::Prover, + &mut prover, + &mut prover_transcript, + ) + .expect("stage4 prover succeeds with sparse RAM addresses"); + + let proof = Stage4Proof::from(artifacts); + let mut verifier = Stage4VerifierKernelExecutor::new(&proof, &opening_inputs); + let mut verifier_transcript = Blake2bTranscript::::new(b"stage4_test"); + let verified = execute_stage4_program( + program, + Stage4ExecutionMode::Verifier, + &mut verifier, + &mut verifier_transcript, + ) + .expect("stage4 verifier accepts sparse RAM proof"); + + assert_eq!(verified.sumchecks.len(), 1); + assert_eq!(prover_transcript.state(), verifier_transcript.state()); + } + + #[test] + fn stage4_batched_kernel_proves_with_sparse_register_accesses() { + let program = synthetic_stage4_program(); + let data = SyntheticStage4Data::new(); + let opening_inputs = data.opening_inputs(); + let prover_inputs = Stage4ProverInputs::new(&opening_inputs) + .with_registers(data.sparse_registers_witness()) + .with_ram(data.sparse_ram_witness()); + let mut prover = Stage4ProverKernelExecutor::new(prover_inputs); + let mut prover_transcript = Blake2bTranscript::::new(b"stage4_test"); + + let artifacts = execute_stage4_program( + program, + Stage4ExecutionMode::Prover, + &mut prover, + &mut prover_transcript, + ) + .expect("stage4 prover succeeds with sparse register accesses"); + + let proof = Stage4Proof::from(artifacts); + let mut verifier = Stage4VerifierKernelExecutor::new(&proof, &opening_inputs); + let mut verifier_transcript = Blake2bTranscript::::new(b"stage4_test"); + let verified = execute_stage4_program( + program, + Stage4ExecutionMode::Verifier, + &mut verifier, + &mut verifier_transcript, + ) + .expect("stage4 verifier accepts sparse register proof"); + + assert_eq!(verified.sumchecks.len(), 1); + assert_eq!(prover_transcript.state(), verifier_transcript.state()); + } + + #[test] + fn stage4_batched_kernel_rejects_tampered_eval() { + let program = synthetic_stage4_program(); + let data = SyntheticStage4Data::new(); + let opening_inputs = data.opening_inputs(); + let mut prover = Stage4ProverKernelExecutor::new( + Stage4ProverInputs::new(&opening_inputs) + .with_registers(data.registers_witness()) + .with_ram(data.ram_witness()), + ); + let mut prover_transcript = Blake2bTranscript::::new(b"stage4_test"); + let mut proof = Stage4Proof::from( + execute_stage4_program( + program, + Stage4ExecutionMode::Prover, + &mut prover, + &mut prover_transcript, + ) + .expect("stage4 prover succeeds"), + ); + proof.sumchecks[0].evals[0].value += Fr::from_u64(1); + + let mut verifier = Stage4VerifierKernelExecutor::new(&proof, &opening_inputs); + let mut verifier_transcript = Blake2bTranscript::::new(b"stage4_test"); + let error = execute_stage4_program( + program, + Stage4ExecutionMode::Verifier, + &mut verifier, + &mut verifier_transcript, + ) + .expect_err("tampered proof is rejected"); + + assert!(matches!(error, Stage4KernelError::InvalidProof { .. })); + } + + #[test] + fn sparse_trace_witness_from_accesses_groups_stage4_and_stage2_accesses() { + let register_accesses = [ + Stage4RegisterAccess { + rd: Some(Stage4RegisterWrite { + address: 2, + pre_value: 5, + post_value: 9, + }), + ..Stage4RegisterAccess::default() + }, + Stage4RegisterAccess::default(), + ]; + let ram_accesses = [ + Stage2RamAccess { + remapped_address: Some(7), + read_value: 11, + write_value: 3, + }, + Stage2RamAccess::noop(), + ]; + + let witness = + stage4_5_sparse_trace_witness_from_accesses::(®ister_accesses, &ram_accesses); + + assert_eq!(witness.rd_inc, vec![Fr::from_u64(4), Fr::from_u64(0)]); + assert_eq!(witness.rd_write_addresses, vec![Some(2), None]); + assert_eq!(witness.ram_addresses, vec![Some(7), None]); + assert_eq!(witness.ram_inc, vec![-Fr::from_u64(8), Fr::from_u64(0)]); + } + + #[derive(Clone)] + struct SyntheticStage4Data { + registers_val: Vec, + rs1_ra: Vec, + rs2_ra: Vec, + rd_wa: Vec, + register_accesses: Vec, + rd_inc: Vec, + ram_ra: Vec, + ram_write_addresses: Vec>, + ram_inc: Vec, + } + + impl SyntheticStage4Data { + fn new() -> Self { + Self { + registers_val: frs(&[10, 12, 12, 15, 20, 20, 21, 21]), + rs1_ra: frs(&[1, 0, 1, 0, 0, 1, 0, 1]), + rs2_ra: frs(&[0, 1, 0, 1, 1, 0, 1, 0]), + rd_wa: frs(&[1, 0, 1, 0, 0, 1, 0, 1]), + register_accesses: synthetic_register_accesses(), + rd_inc: frs(&[2, 1, 3, 4]), + ram_ra: frs(&[1, 0, 1, 0, 0, 1, 0, 1]), + ram_write_addresses: vec![Some(0), Some(1), Some(0), Some(1)], + ram_inc: frs(&[5, 7, 0, 2]), + } + } + + fn registers_witness(&self) -> Stage4RegistersWitness<'_, Fr> { + Stage4RegistersWitness { + register_count: 2, + trace_len: 4, + registers_val: &self.registers_val, + rs1_ra: &self.rs1_ra, + rs2_ra: &self.rs2_ra, + rd_wa: &self.rd_wa, + accesses: None, + rd_inc: &self.rd_inc, + } + } + + fn sparse_registers_witness(&self) -> Stage4RegistersWitness<'_, Fr> { + Stage4RegistersWitness { + register_count: 2, + trace_len: 4, + registers_val: &[], + rs1_ra: &[], + rs2_ra: &[], + rd_wa: &[], + accesses: Some(&self.register_accesses), + rd_inc: &self.rd_inc, + } + } + + fn ram_witness(&self) -> Stage4RamWitness<'_, Fr> { + Stage4RamWitness { + ram_k: 2, + trace_len: 4, + ram_ra: &self.ram_ra, + write_address_indices: None, + ram_inc: &self.ram_inc, + } + } + + fn sparse_ram_witness(&self) -> Stage4RamWitness<'_, Fr> { + Stage4RamWitness { + ram_k: 2, + trace_len: 4, + ram_ra: &[], + write_address_indices: Some(&self.ram_write_addresses), + ram_inc: &self.ram_inc, + } + } + + fn opening_inputs(&self) -> Vec> { + let trace_point = frs(&[5, 7]); + let ram_address_point = frs(&[11]); + let ram_cycle_point = frs(&[13, 17]); + let ram_val_point = [ram_address_point.as_slice(), ram_cycle_point.as_slice()].concat(); + let rd_write_values = self.rd_write_values(); + let rs1_values = self.read_values(&self.rs1_ra); + let rs2_values = self.read_values(&self.rs2_ra); + let ram_init = ram_initial_eval(&ram_address_point); + let ram_ra_at_address = self.ram_ra_at_address(&ram_address_point); + let ram_val_delta = ram_val_delta(&ram_ra_at_address, &self.ram_inc, &ram_cycle_point); + let ram_final_delta = ram_final_delta(&ram_ra_at_address, &self.ram_inc); + vec![ + opening( + "stage4.input.stage3.registers.RdWriteValue", + &trace_point, + mle_eval(&rd_write_values, &trace_point), + ), + opening( + "stage4.input.stage3.registers.Rs1Value", + &trace_point, + mle_eval(&rs1_values, &trace_point), + ), + opening( + "stage4.input.stage3.registers.Rs2Value", + &trace_point, + mle_eval(&rs2_values, &trace_point), + ), + opening( + "stage4.input.stage3.instruction.Rs1Value", + &trace_point, + mle_eval(&rs1_values, &trace_point), + ), + opening( + "stage4.input.stage3.instruction.Rs2Value", + &trace_point, + mle_eval(&rs2_values, &trace_point), + ), + opening( + "stage4.input.stage2.RamVal", + &ram_val_point, + ram_init + ram_val_delta, + ), + opening( + "stage4.input.stage2.RamValFinal", + &ram_address_point, + ram_init + ram_final_delta, + ), + opening( + "stage4.input.initial_ram.RamValInit", + &ram_address_point, + ram_init, + ), + ] + } + + fn rd_write_values(&self) -> Vec { + (0..4) + .map(|cycle| { + (0..2) + .map(|address| { + let index = address * 4 + cycle; + self.rd_wa[index] * (self.registers_val[index] + self.rd_inc[cycle]) + }) + .sum() + }) + .collect() + } + + fn read_values(&self, read_address: &[Fr]) -> Vec { + (0..4) + .map(|cycle| { + (0..2) + .map(|address| { + let index = address * 4 + cycle; + read_address[index] * self.registers_val[index] + }) + .sum() + }) + .collect() + } + + fn ram_ra_at_address(&self, address_point: &[Fr]) -> Vec { + let address_eq = EqPolynomial::::evals(address_point, None); + (0..4) + .map(|cycle| { + (0..2) + .map(|address| address_eq[address] * self.ram_ra[address * 4 + cycle]) + .sum() + }) + .collect() + } + } + + fn synthetic_stage4_program() -> &'static Stage4CpuProgramPlan { + Box::leak(Box::new(Stage4CpuProgramPlan { + role: "prover", + params: Stage4Params { + field: "bn254_fr", + pcs: "dory", + transcript: "blake2b_transcript", + }, + steps: leak_slice(vec![ + Stage4ProgramStepPlan { + kind: "transcript_squeeze", + symbol: "stage4.registers_read_write.gamma", + }, + Stage4ProgramStepPlan { + kind: "transcript_absorb_bytes", + symbol: "stage4.ram_val_check.domain_separator", + }, + Stage4ProgramStepPlan { + kind: "transcript_squeeze", + symbol: "stage4.ram_val_check.gamma", + }, + Stage4ProgramStepPlan { + kind: "sumcheck_driver", + symbol: "stage4.sumcheck", + }, + ]), + transcript_squeezes: leak_slice(vec![ + Stage4TranscriptSqueezePlan { + symbol: "stage4.registers_read_write.gamma", + label: "registers_read_write_gamma", + kind: "challenge_scalar", + count: 1, + }, + Stage4TranscriptSqueezePlan { + symbol: "stage4.ram_val_check.gamma", + label: "ram_val_check_gamma", + kind: "challenge_scalar", + count: 1, + }, + ]), + transcript_absorb_bytes: leak_slice(vec![Stage4TranscriptAbsorbBytesPlan { + symbol: "stage4.ram_val_check.domain_separator", + label: "ram_val_check_gamma", + payload: "", + }]), + opening_inputs: leak_slice(stage4_opening_input_plans()), + field_constants: &[], + field_exprs: leak_slice(stage4_field_exprs()), + kernels: leak_slice(vec![ + kernel( + "jolt.cpu.stage4.registers_read_write", + "jolt.stage4.registers_read_write", + "jolt_stage4_registers_read_write", + ), + kernel( + "jolt.cpu.stage4.ram_val_check", + "jolt.stage4.ram_val_check", + "jolt_stage4_ram_val_check", + ), + kernel( + "jolt.cpu.stage4.batched", + "jolt.stage4.batched", + "jolt_stage4_batched", + ), + ]), + claims: leak_slice(vec![ + Stage4SumcheckClaimPlan { + symbol: "stage4.registers_read_write.input", + stage: "stage4", + domain: "jolt.stage4_registers_rw_domain", + num_rounds: 3, + degree: 3, + claim: "stage4.registers_read_write.weighted_values", + kernel: Some("jolt.cpu.stage4.registers_read_write"), + relation: None, + claim_value: "stage4.registers_read_write.claim_expr", + input_openings: leak_slice(vec![ + "stage4.input.stage3.registers.RdWriteValue", + "stage4.input.stage3.registers.Rs1Value", + "stage4.input.stage3.registers.Rs2Value", + ]), + }, + Stage4SumcheckClaimPlan { + symbol: "stage4.ram_val_check.input", + stage: "stage4", + domain: "jolt.trace_domain", + num_rounds: 2, + degree: 3, + claim: "stage4.ram_val_check.weighted_values", + kernel: Some("jolt.cpu.stage4.ram_val_check"), + relation: None, + claim_value: "stage4.ram_val_check.claim_expr", + input_openings: leak_slice(vec![ + "stage4.input.stage2.RamVal", + "stage4.input.stage2.RamValFinal", + "stage4.input.initial_ram.RamValInit", + ]), + }, + ]), + batches: leak_slice(vec![Stage4SumcheckBatchPlan { + symbol: "stage4.batch", + stage: "stage4", + proof_slot: "stage4.sumcheck", + policy: "jolt_core_stage4_aligned", + count: 2, + ordered_claims: leak_slice(vec![ + "stage4.registers_read_write.input", + "stage4.ram_val_check.input", + ]), + claim_operands: leak_slice(vec![ + "stage4.registers_read_write.input", + "stage4.ram_val_check.input", + ]), + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + round_schedule: leak_slice(vec![2, 1]), + }]), + drivers: leak_slice(vec![Stage4SumcheckDriverPlan { + symbol: "stage4.sumcheck", + stage: "stage4", + proof_slot: "stage4.sumcheck", + kernel: Some("jolt.cpu.stage4.batched"), + relation: None, + batch: "stage4.batch", + policy: "jolt_core_stage4_aligned", + round_schedule: leak_slice(vec![2, 1]), + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + num_rounds: 3, + degree: 3, + }]), + instance_results: leak_slice(vec![ + Stage4SumcheckInstanceResultPlan { + symbol: "stage4.registers_read_write.instance", + source: "stage4.sumcheck", + claim: "stage4.registers_read_write.input", + relation: "jolt.stage4.registers_read_write", + index: 0, + point_arity: 3, + num_rounds: 3, + round_offset: 0, + point_order: "stage4_registers_rw", + degree: 3, + }, + Stage4SumcheckInstanceResultPlan { + symbol: "stage4.ram_val_check.instance", + source: "stage4.sumcheck", + claim: "stage4.ram_val_check.input", + relation: "jolt.stage4.ram_val_check", + index: 1, + point_arity: 2, + num_rounds: 2, + round_offset: 1, + point_order: "reverse", + degree: 3, + }, + ]), + evals: leak_slice(stage4_eval_plans()), + point_slices: leak_slice(vec![ + Stage4PointSlicePlan { + symbol: "stage4.registers_read_write.point.RdInc", + source: "stage4.registers_read_write.instance", + offset: 1, + length: 2, + input: "stage4.registers_read_write.instance", + }, + Stage4PointSlicePlan { + symbol: "stage4.ram_val_check.point.RamAddress", + source: "stage4.input.stage2.RamVal", + offset: 0, + length: 1, + input: "stage4.input.stage2.RamVal", + }, + ]), + point_concats: leak_slice(vec![Stage4PointConcatPlan { + symbol: "stage4.ram_val_check.point.RamRa", + layout: "address_then_cycle", + arity: 3, + inputs: leak_slice(vec![ + "stage4.ram_val_check.point.RamAddress", + "stage4.ram_val_check.instance", + ]), + }]), + opening_claims: leak_slice(stage4_opening_claim_plans()), + opening_equalities: leak_slice(vec![ + Stage4OpeningClaimEqualityPlan { + symbol: "stage4.registers.rs1_claim_consistency", + mode: "point_and_eval", + lhs: "stage4.input.stage3.registers.Rs1Value", + rhs: "stage4.input.stage3.instruction.Rs1Value", + }, + Stage4OpeningClaimEqualityPlan { + symbol: "stage4.registers.rs2_claim_consistency", + mode: "point_and_eval", + lhs: "stage4.input.stage3.registers.Rs2Value", + rhs: "stage4.input.stage3.instruction.Rs2Value", + }, + ]), + opening_batches: leak_slice(vec![Stage4OpeningBatchPlan { + symbol: "stage4.openings", + stage: "stage4", + proof_slot: "stage4.openings", + policy: "jolt_stage4_output_order", + count: 7, + ordered_claims: leak_slice( + stage4_opening_claim_plans() + .iter() + .map(|claim| claim.symbol) + .collect(), + ), + claim_operands: leak_slice( + stage4_opening_claim_plans() + .iter() + .map(|claim| claim.symbol) + .collect(), + ), + }]), + })) + } + + fn stage4_field_exprs() -> Vec { + vec![ + field_expr( + "stage4.registers_read_write.gamma2", + "field.pow:2", + vec!["stage4.registers_read_write.gamma"], + ), + field_expr( + "stage4.registers_read_write.term.Rs1Value", + "field.mul", + vec![ + "stage4.registers_read_write.gamma", + "stage4.input.stage3.registers.Rs1Value", + ], + ), + field_expr( + "stage4.registers_read_write.term.Rs2Value", + "field.mul", + vec![ + "stage4.registers_read_write.gamma2", + "stage4.input.stage3.registers.Rs2Value", + ], + ), + field_expr( + "stage4.registers_read_write.partial.RdWriteValueRs1Value", + "field.add", + vec![ + "stage4.input.stage3.registers.RdWriteValue", + "stage4.registers_read_write.term.Rs1Value", + ], + ), + field_expr( + "stage4.registers_read_write.claim_expr", + "field.add", + vec![ + "stage4.registers_read_write.partial.RdWriteValueRs1Value", + "stage4.registers_read_write.term.Rs2Value", + ], + ), + field_expr( + "stage4.ram_val_check.delta.RamVal", + "field.sub", + vec![ + "stage4.input.stage2.RamVal", + "stage4.input.initial_ram.RamValInit", + ], + ), + field_expr( + "stage4.ram_val_check.delta.RamValFinal", + "field.sub", + vec![ + "stage4.input.stage2.RamValFinal", + "stage4.input.initial_ram.RamValInit", + ], + ), + field_expr( + "stage4.ram_val_check.term.RamValFinal", + "field.mul", + vec![ + "stage4.ram_val_check.gamma", + "stage4.ram_val_check.delta.RamValFinal", + ], + ), + field_expr( + "stage4.ram_val_check.claim_expr", + "field.add", + vec![ + "stage4.ram_val_check.delta.RamVal", + "stage4.ram_val_check.term.RamValFinal", + ], + ), + ] + } + + fn stage4_opening_input_plans() -> Vec { + vec![ + opening_input_plan( + "stage4.input.stage3.registers.RdWriteValue", + "RdWriteValue", + 2, + ), + opening_input_plan("stage4.input.stage3.registers.Rs1Value", "Rs1Value", 2), + opening_input_plan("stage4.input.stage3.registers.Rs2Value", "Rs2Value", 2), + opening_input_plan("stage4.input.stage3.instruction.Rs1Value", "Rs1Value", 2), + opening_input_plan("stage4.input.stage3.instruction.Rs2Value", "Rs2Value", 2), + opening_input_plan("stage4.input.stage2.RamVal", "RamVal", 3), + opening_input_plan("stage4.input.stage2.RamValFinal", "RamValFinal", 1), + opening_input_plan("stage4.input.initial_ram.RamValInit", "RamValInit", 1), + ] + } + + fn stage4_eval_plans() -> Vec { + vec![ + eval( + "stage4.registers_read_write.eval.RegistersVal", + "RegistersVal", + 0, + ), + eval("stage4.registers_read_write.eval.Rs1Ra", "Rs1Ra", 1), + eval("stage4.registers_read_write.eval.Rs2Ra", "Rs2Ra", 2), + eval("stage4.registers_read_write.eval.RdWa", "RdWa", 3), + eval("stage4.registers_read_write.eval.RdInc", "RdInc", 4), + eval("stage4.ram_val_check.eval.RamRa", "RamRa", 0), + eval("stage4.ram_val_check.eval.RamInc", "RamInc", 1), + ] + } + + fn stage4_opening_claim_plans() -> Vec { + vec![ + opening_claim( + "stage4.registers_read_write.opening.RegistersVal", + "RegistersVal", + "stage4.registers_read_write.instance", + "stage4.registers_read_write.eval.RegistersVal", + 3, + "virtual", + ), + opening_claim( + "stage4.registers_read_write.opening.Rs1Ra", + "Rs1Ra", + "stage4.registers_read_write.instance", + "stage4.registers_read_write.eval.Rs1Ra", + 3, + "virtual", + ), + opening_claim( + "stage4.registers_read_write.opening.Rs2Ra", + "Rs2Ra", + "stage4.registers_read_write.instance", + "stage4.registers_read_write.eval.Rs2Ra", + 3, + "virtual", + ), + opening_claim( + "stage4.registers_read_write.opening.RdWa", + "RdWa", + "stage4.registers_read_write.instance", + "stage4.registers_read_write.eval.RdWa", + 3, + "virtual", + ), + opening_claim( + "stage4.registers_read_write.opening.RdInc", + "RdInc", + "stage4.registers_read_write.point.RdInc", + "stage4.registers_read_write.eval.RdInc", + 2, + "committed", + ), + opening_claim( + "stage4.ram_val_check.opening.RamRa", + "RamRa", + "stage4.ram_val_check.point.RamRa", + "stage4.ram_val_check.eval.RamRa", + 3, + "virtual", + ), + opening_claim( + "stage4.ram_val_check.opening.RamInc", + "RamInc", + "stage4.ram_val_check.instance", + "stage4.ram_val_check.eval.RamInc", + 2, + "committed", + ), + ] + } + + fn field_expr( + symbol: &'static str, + formula: &'static str, + operands: Vec<&'static str>, + ) -> Stage4FieldExprPlan { + let operands = leak_slice(operands); + Stage4FieldExprPlan { + symbol, + kind: "op", + formula, + operand_names: operands, + operands, + } + } + + fn kernel(symbol: &'static str, relation: &'static str, abi: &'static str) -> Stage4KernelPlan { + Stage4KernelPlan { + symbol, + relation, + kind: "sumcheck", + backend: "cpu", + abi, + } + } + + fn opening_input_plan( + symbol: &'static str, + oracle: &'static str, + point_arity: usize, + ) -> Stage4OpeningInputPlan { + Stage4OpeningInputPlan { + symbol, + source_stage: "synthetic", + source_claim: symbol, + oracle, + domain: "synthetic", + point_arity, + claim_kind: "virtual", + } + } + + fn eval(symbol: &'static str, oracle: &'static str, index: usize) -> Stage4SumcheckEvalPlan { + Stage4SumcheckEvalPlan { + symbol, + source: "stage4.sumcheck", + name: symbol, + index, + oracle, + } + } + + fn opening_claim( + symbol: &'static str, + oracle: &'static str, + point_source: &'static str, + eval_source: &'static str, + point_arity: usize, + claim_kind: &'static str, + ) -> Stage4OpeningClaimPlan { + Stage4OpeningClaimPlan { + symbol, + oracle, + domain: "synthetic", + point_arity, + claim_kind, + point_source, + eval_source, + } + } + + fn opening(symbol: &'static str, point: &[Fr], eval: Fr) -> Stage4OpeningInputValue { + Stage4OpeningInputValue { + symbol, + point: point.to_vec(), + eval, + } + } + + fn mle_eval(values: &[Fr], point: &[Fr]) -> Fr { + EqPolynomial::::evals(point, None) + .iter() + .zip(values) + .map(|(&weight, &value)| weight * value) + .sum() + } + + fn ram_initial_eval(address_point: &[Fr]) -> Fr { + let initial = frs(&[11, 13]); + mle_eval(&initial, address_point) + } + + fn ram_val_delta(ram_ra_at_address: &[Fr], ram_inc: &[Fr], cycle_point: &[Fr]) -> Fr { + (0..4) + .map(|cycle| { + let cycle_bits = boolean_point_from_index::(cycle, 2); + ram_inc[cycle] + * ram_ra_at_address[cycle] + * lt_polynomial_eval(&cycle_bits, cycle_point) + }) + .sum() + } + + fn ram_final_delta(ram_ra_at_address: &[Fr], ram_inc: &[Fr]) -> Fr { + ram_ra_at_address + .iter() + .zip(ram_inc) + .map(|(&ra, &inc)| ra * inc) + .sum() + } + + fn synthetic_register_accesses() -> Vec { + vec![ + Stage4RegisterAccess { + rs1: Some(Stage4RegisterRead { + address: 0, + value: 10, + }), + rs2: Some(Stage4RegisterRead { + address: 1, + value: 20, + }), + rd: Some(Stage4RegisterWrite { + address: 0, + pre_value: 10, + post_value: 12, + }), + }, + Stage4RegisterAccess { + rs1: Some(Stage4RegisterRead { + address: 1, + value: 20, + }), + rs2: Some(Stage4RegisterRead { + address: 0, + value: 12, + }), + rd: Some(Stage4RegisterWrite { + address: 1, + pre_value: 20, + post_value: 21, + }), + }, + Stage4RegisterAccess { + rs1: Some(Stage4RegisterRead { + address: 0, + value: 12, + }), + rs2: Some(Stage4RegisterRead { + address: 1, + value: 21, + }), + rd: Some(Stage4RegisterWrite { + address: 0, + pre_value: 12, + post_value: 15, + }), + }, + Stage4RegisterAccess { + rs1: Some(Stage4RegisterRead { + address: 1, + value: 21, + }), + rs2: Some(Stage4RegisterRead { + address: 0, + value: 15, + }), + rd: Some(Stage4RegisterWrite { + address: 1, + pre_value: 21, + post_value: 25, + }), + }, + ] + } + + fn frs(values: &[u64]) -> Vec { + values.iter().copied().map(Fr::from_u64).collect() + } + + fn leak_slice(values: Vec) -> &'static [T] { + Box::leak(values.into_boxed_slice()) + } +} diff --git a/crates/jolt-kernels/src/stage5.rs b/crates/jolt-kernels/src/stage5.rs new file mode 100644 index 0000000000..41a6c40dd0 --- /dev/null +++ b/crates/jolt-kernels/src/stage5.rs @@ -0,0 +1,4949 @@ +//! Stage 5 coarse-kernel ABI used by Bolt-generated Jolt prover code. + +#![expect( + clippy::large_enum_variant, + reason = "kernel states stay inline to avoid boxing hot prover state" +)] +#![expect( + clippy::too_many_arguments, + reason = "kernel constructors mirror generated staged protocol inputs" +)] + +use std::collections::HashMap; +use std::error::Error; +use std::fmt::{self, Display, Formatter}; + +use crate::dense::{bind_dense_evals_reuse, DENSE_BIND_PAR_THRESHOLD}; +use jolt_field::{Field, FieldAccumulator, FieldScalarAccumulator}; +use jolt_lookup_tables::{ + tables::{ + prefixes::{PrefixEval, ALL_PREFIXES, NUM_PREFIXES}, + Suffixes, + }, + uninterleave_bits, LookupBits, LookupTableKind, +}; +use jolt_poly::{bind_high_to_low, EqPolynomial, UnivariatePoly}; +use jolt_transcript::{Label, LabelWithCount, Transcript}; +use jolt_witness::Stage45SparseTraceWitness; +use rayon::prelude::*; + +type PrefixPairEvals = ([PrefixEval; NUM_PREFIXES], [PrefixEval; NUM_PREFIXES]); + +pub use crate::stage4::{ + Stage4ChallengeVector as Stage5ChallengeVector, Stage4CpuProgramPlan as Stage5CpuProgramPlan, + Stage4ExecutionArtifacts as Stage5ExecutionArtifacts, + Stage4ExecutionMode as Stage5ExecutionMode, Stage4FieldConstantPlan as Stage5FieldConstantPlan, + Stage4FieldExprPlan as Stage5FieldExprPlan, Stage4KernelPlan as Stage5KernelPlan, + Stage4NamedEval as Stage5NamedEval, Stage4OpeningBatchPlan as Stage5OpeningBatchPlan, + Stage4OpeningClaimEqualityPlan as Stage5OpeningClaimEqualityPlan, + Stage4OpeningClaimPlan as Stage5OpeningClaimPlan, + Stage4OpeningClaimValue as Stage5OpeningClaimValue, + Stage4OpeningInputPlan as Stage5OpeningInputPlan, + Stage4OpeningInputValue as Stage5OpeningInputValue, Stage4Params as Stage5Params, + Stage4PointConcatPlan as Stage5PointConcatPlan, Stage4PointSlicePlan as Stage5PointSlicePlan, + Stage4ProgramStepPlan as Stage5ProgramStepPlan, Stage4Proof as Stage5Proof, + Stage4SumcheckBatchPlan as Stage5SumcheckBatchPlan, + Stage4SumcheckClaimPlan as Stage5SumcheckClaimPlan, + Stage4SumcheckDriverPlan as Stage5SumcheckDriverPlan, + Stage4SumcheckEvalPlan as Stage5SumcheckEvalPlan, + Stage4SumcheckInstanceResultPlan as Stage5SumcheckInstanceResultPlan, + Stage4SumcheckOutput as Stage5SumcheckOutput, + Stage4TranscriptAbsorbBytesPlan as Stage5TranscriptAbsorbBytesPlan, + Stage4TranscriptSqueezePlan as Stage5TranscriptSqueezePlan, +}; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Stage5Relation { + InstructionReadRaf, + RamRaClaimReduction, + RegistersValEvaluation, + Batched, +} + +impl Stage5Relation { + pub fn from_symbol(symbol: &str) -> Option { + match symbol { + "jolt.stage5.instruction_read_raf" => Some(Self::InstructionReadRaf), + "jolt.stage5.ram_ra_claim_reduction" => Some(Self::RamRaClaimReduction), + "jolt.stage5.registers_val_evaluation" => Some(Self::RegistersValEvaluation), + "jolt.stage5.batched" => Some(Self::Batched), + _ => None, + } + } + + pub fn symbol(self) -> &'static str { + match self { + Self::InstructionReadRaf => "jolt.stage5.instruction_read_raf", + Self::RamRaClaimReduction => "jolt.stage5.ram_ra_claim_reduction", + Self::RegistersValEvaluation => "jolt.stage5.registers_val_evaluation", + Self::Batched => "jolt.stage5.batched", + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Stage5KernelAbi { + InstructionReadRaf, + RamRaClaimReduction, + RegistersValEvaluation, + Batched, +} + +impl Stage5KernelAbi { + pub fn from_name(name: &str) -> Option { + match name { + "jolt_stage5_instruction_read_raf" => Some(Self::InstructionReadRaf), + "jolt_stage5_ram_ra_claim_reduction" => Some(Self::RamRaClaimReduction), + "jolt_stage5_registers_val_evaluation" => Some(Self::RegistersValEvaluation), + "jolt_stage5_batched" => Some(Self::Batched), + _ => None, + } + } + + pub fn name(self) -> &'static str { + match self { + Self::InstructionReadRaf => "jolt_stage5_instruction_read_raf", + Self::RamRaClaimReduction => "jolt_stage5_ram_ra_claim_reduction", + Self::RegistersValEvaluation => "jolt_stage5_registers_val_evaluation", + Self::Batched => "jolt_stage5_batched", + } + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum Stage5KernelError { + MissingClaim { + batch: &'static str, + claim: &'static str, + }, + MissingValue { + symbol: &'static str, + }, + MissingDriver { + driver: &'static str, + }, + MissingKernel { + driver: &'static str, + kernel: &'static str, + }, + MissingBatch { + driver: &'static str, + batch: &'static str, + }, + UnknownRelation { + relation: &'static str, + }, + UnknownKernelAbi { + abi: &'static str, + }, + PlanCountMismatch { + artifact: &'static str, + expected: usize, + actual: usize, + }, + InvalidInputLength { + input: &'static str, + expected: usize, + actual: usize, + }, + UnsupportedFieldExpr { + symbol: &'static str, + formula: &'static str, + }, + KernelNotImplemented { + abi: &'static str, + }, + WrongExecutorMode { + driver: &'static str, + expected: Stage5ExecutionMode, + actual: Stage5ExecutionMode, + }, + MissingProof { + driver: &'static str, + }, + MissingKernelInput { + kernel: &'static str, + input: &'static str, + }, + InvalidProgramStep { + symbol: &'static str, + kind: &'static str, + }, + InvalidProof { + driver: &'static str, + reason: &'static str, + }, +} + +impl Display for Stage5KernelError { + fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result { + match self { + Self::MissingClaim { batch, claim } => { + write!( + formatter, + "stage5 batch @{batch} references missing claim @{claim}" + ) + } + Self::MissingValue { symbol } => { + write!(formatter, "stage5 value @{symbol} is not available") + } + Self::MissingDriver { driver } => { + write!(formatter, "stage5 driver @{driver} is not available") + } + Self::MissingKernel { driver, kernel } => { + write!( + formatter, + "stage5 driver @{driver} references missing kernel @{kernel}" + ) + } + Self::MissingBatch { driver, batch } => { + write!( + formatter, + "stage5 driver @{driver} references missing batch @{batch}" + ) + } + Self::UnknownRelation { relation } => { + write!(formatter, "unknown stage5 relation `{relation}`") + } + Self::UnknownKernelAbi { abi } => { + write!(formatter, "unknown stage5 kernel ABI `{abi}`") + } + Self::PlanCountMismatch { + artifact, + expected, + actual, + } => { + write!( + formatter, + "stage5 {artifact} plan count mismatch: expected {expected}, got {actual}" + ) + } + Self::InvalidInputLength { + input, + expected, + actual, + } => { + write!( + formatter, + "stage5 input `{input}` has length {actual}, expected {expected}" + ) + } + Self::UnsupportedFieldExpr { symbol, formula } => { + write!( + formatter, + "stage5 field expr @{symbol} uses unsupported formula `{formula}`" + ) + } + Self::KernelNotImplemented { abi } => { + write!(formatter, "stage5 kernel ABI `{abi}` is not implemented") + } + Self::WrongExecutorMode { + driver, + expected, + actual, + } => { + write!( + formatter, + "stage5 driver @{driver} expected {expected:?} executor, got {actual:?}" + ) + } + Self::MissingProof { driver } => { + write!(formatter, "stage5 proof for driver @{driver} is missing") + } + Self::MissingKernelInput { kernel, input } => { + write!( + formatter, + "stage5 kernel `{kernel}` is missing required input `{input}`" + ) + } + Self::InvalidProgramStep { symbol, kind } => { + write!( + formatter, + "stage5 program step @{symbol} has invalid kind `{kind}`" + ) + } + Self::InvalidProof { driver, reason } => { + write!( + formatter, + "stage5 proof for driver @{driver} is invalid: {reason}" + ) + } + } + } +} + +impl Error for Stage5KernelError {} + +#[derive(Clone, Copy)] +pub struct Stage5RegistersValWitness<'a, F: Field> { + pub register_count: usize, + pub trace_len: usize, + pub rd_inc: &'a [F], + pub rd_wa: &'a [F], + pub rd_write_addresses: Option<&'a [Option]>, +} + +#[derive(Clone, Copy)] +pub struct Stage5RamRaWitness<'a, F: Field> { + pub ram_k: usize, + pub trace_len: usize, + pub ram_ra: &'a [F], + pub remapped_addresses: Option<&'a [Option]>, +} + +#[derive(Clone, Copy)] +pub struct Stage5InstructionReadRafWitness<'a> { + pub trace_len: usize, + pub lookup_indices: &'a [u128], + pub lookup_table_indices: &'a [Option], + pub is_interleaved_operands: &'a [bool], + pub ra_virtual_log_k_chunk: usize, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage5InstructionReadRafEvaluations { + pub lookup_table_flags: Vec, + pub instruction_ra: Vec, + pub instruction_raf_flag: F, +} + +#[derive(Clone, Copy)] +pub struct Stage5ProverInputs<'a, F: Field> { + pub opening_inputs: &'a [Stage5OpeningInputValue], + pub instruction_read_raf: Option>, + pub ram_ra: Option>, + pub registers_val: Option>, +} + +impl<'a, F: Field> Stage5ProverInputs<'a, F> { + pub fn new(opening_inputs: &'a [Stage5OpeningInputValue]) -> Self { + Self { + opening_inputs, + instruction_read_raf: None, + ram_ra: None, + registers_val: None, + } + } + + pub fn empty() -> Self { + Self { + opening_inputs: &[], + instruction_read_raf: None, + ram_ra: None, + registers_val: None, + } + } + + pub fn with_instruction_read_raf( + mut self, + instruction_read_raf: Stage5InstructionReadRafWitness<'a>, + ) -> Self { + self.instruction_read_raf = Some(instruction_read_raf); + self + } + + pub fn with_ram_ra(mut self, ram_ra: Stage5RamRaWitness<'a, F>) -> Self { + self.ram_ra = Some(ram_ra); + self + } + + pub fn with_registers_val(mut self, registers_val: Stage5RegistersValWitness<'a, F>) -> Self { + self.registers_val = Some(registers_val); + self + } + + pub fn with_sparse_trace_witness( + self, + trace_len: usize, + ram_k: usize, + register_count: usize, + lookup_indices: &'a [u128], + lookup_table_indices: &'a [Option], + is_interleaved_operands: &'a [bool], + ra_virtual_log_k_chunk: usize, + remapped_addresses: &'a [Option], + rd_inc: &'a [F], + rd_write_addresses: &'a [Option], + ) -> Self { + self.with_instruction_read_raf(Stage5InstructionReadRafWitness { + trace_len, + lookup_indices, + lookup_table_indices, + is_interleaved_operands, + ra_virtual_log_k_chunk, + }) + .with_ram_ra(Stage5RamRaWitness { + ram_k, + trace_len, + ram_ra: &[], + remapped_addresses: Some(remapped_addresses), + }) + .with_registers_val(Stage5RegistersValWitness { + register_count, + trace_len, + rd_inc, + rd_wa: &[], + rd_write_addresses: Some(rd_write_addresses), + }) + } + + pub fn with_stage45_sparse_trace_witness( + self, + trace_len: usize, + ram_k: usize, + register_count: usize, + lookup_indices: &'a [u128], + lookup_table_indices: &'a [Option], + is_interleaved_operands: &'a [bool], + ra_virtual_log_k_chunk: usize, + witness: &'a Stage45SparseTraceWitness, + ) -> Self { + self.with_sparse_trace_witness( + trace_len, + ram_k, + register_count, + lookup_indices, + lookup_table_indices, + is_interleaved_operands, + ra_virtual_log_k_chunk, + &witness.ram_addresses, + &witness.rd_inc, + &witness.rd_write_addresses, + ) + } +} + +#[derive(Clone, Copy, Debug)] +pub struct Stage5KernelContext<'a> { + pub mode: Stage5ExecutionMode, + pub program: &'static Stage5CpuProgramPlan, + pub kernel: &'a Stage5KernelPlan, + pub batch: &'a Stage5SumcheckBatchPlan, + pub driver: &'a Stage5SumcheckDriverPlan, +} + +impl Stage5KernelContext<'_> { + pub fn relation_kind(&self) -> Result { + Stage5Relation::from_symbol(self.kernel.relation).ok_or( + Stage5KernelError::UnknownRelation { + relation: self.kernel.relation, + }, + ) + } + + pub fn abi_kind(&self) -> Result { + Stage5KernelAbi::from_name(self.kernel.abi).ok_or(Stage5KernelError::UnknownKernelAbi { + abi: self.kernel.abi, + }) + } + + pub fn batch_claims(&self) -> Result, Stage5KernelError> { + self.batch + .claim_operands + .iter() + .map(|symbol| { + self.program + .claim(symbol) + .ok_or(Stage5KernelError::MissingClaim { + batch: self.batch.symbol, + claim: symbol, + }) + }) + .collect() + } +} + +pub trait Stage5KernelExecutor { + fn observe_challenge_vector( + &mut self, + _plan: &'static Stage5TranscriptSqueezePlan, + _values: &[F], + ) -> Result<(), Stage5KernelError> { + Ok(()) + } + + fn observe_sumcheck_output( + &mut self, + _output: &Stage5SumcheckOutput, + ) -> Result<(), Stage5KernelError> { + Ok(()) + } + + fn prove_sumcheck( + &mut self, + context: Stage5KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage5KernelError> + where + T: Transcript; + + fn verify_sumcheck( + &mut self, + context: Stage5KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage5KernelError> + where + T: Transcript; +} + +#[derive(Clone, Debug, Default)] +pub struct UnsupportedStage5KernelExecutor; + +impl Stage5KernelExecutor for UnsupportedStage5KernelExecutor { + fn prove_sumcheck( + &mut self, + context: Stage5KernelContext<'_>, + _transcript: &mut T, + ) -> Result, Stage5KernelError> + where + T: Transcript, + { + Err(Stage5KernelError::KernelNotImplemented { + abi: context.kernel.abi, + }) + } + + fn verify_sumcheck( + &mut self, + context: Stage5KernelContext<'_>, + _transcript: &mut T, + ) -> Result, Stage5KernelError> + where + T: Transcript, + { + Err(Stage5KernelError::KernelNotImplemented { + abi: context.kernel.abi, + }) + } +} + +#[derive(Clone)] +pub struct Stage5ProverKernelExecutor<'a, F: Field> { + pub inputs: Stage5ProverInputs<'a, F>, + challenge_vectors: Vec>, + completed_sumchecks: Vec>, +} + +impl<'a, F: Field> Stage5ProverKernelExecutor<'a, F> { + pub fn new(inputs: Stage5ProverInputs<'a, F>) -> Self { + Self { + inputs, + challenge_vectors: Vec::new(), + completed_sumchecks: Vec::new(), + } + } + + fn value_store( + &self, + program: &'static Stage5CpuProgramPlan, + ) -> Result, Stage5KernelError> { + value_store_from_observations( + program, + self.inputs.opening_inputs, + &self.challenge_vectors, + &self.completed_sumchecks, + ) + } +} + +impl Stage5KernelExecutor for Stage5ProverKernelExecutor<'_, F> { + fn observe_challenge_vector( + &mut self, + plan: &'static Stage5TranscriptSqueezePlan, + values: &[F], + ) -> Result<(), Stage5KernelError> { + self.challenge_vectors.push(Stage5ChallengeVector { + symbol: plan.symbol, + values: values.to_vec(), + }); + Ok(()) + } + + fn observe_sumcheck_output( + &mut self, + output: &Stage5SumcheckOutput, + ) -> Result<(), Stage5KernelError> { + self.completed_sumchecks.push(output.clone()); + Ok(()) + } + + fn prove_sumcheck( + &mut self, + context: Stage5KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage5KernelError> + where + T: Transcript, + { + prove_stage5_kernel( + context, + &self.inputs, + self.value_store(context.program)?, + transcript, + ) + } + + fn verify_sumcheck( + &mut self, + context: Stage5KernelContext<'_>, + _transcript: &mut T, + ) -> Result, Stage5KernelError> + where + T: Transcript, + { + Err(Stage5KernelError::WrongExecutorMode { + driver: context.driver.symbol, + expected: Stage5ExecutionMode::Prover, + actual: Stage5ExecutionMode::Verifier, + }) + } +} + +#[derive(Clone)] +pub struct Stage5ProofCarryingKernelExecutor<'a, F: Field> { + pub proof: &'a Stage5Proof, + pub opening_inputs: &'a [Stage5OpeningInputValue], + pub cursor: usize, + challenge_vectors: Vec>, + completed_sumchecks: Vec>, +} + +impl<'a, F: Field> Stage5ProofCarryingKernelExecutor<'a, F> { + pub fn new( + proof: &'a Stage5Proof, + opening_inputs: &'a [Stage5OpeningInputValue], + ) -> Self { + Self { + proof, + opening_inputs, + cursor: 0, + challenge_vectors: Vec::new(), + completed_sumchecks: Vec::new(), + } + } + + fn value_store( + &self, + program: &'static Stage5CpuProgramPlan, + ) -> Result, Stage5KernelError> { + value_store_from_observations( + program, + self.opening_inputs, + &self.challenge_vectors, + &self.completed_sumchecks, + ) + } + + fn next_proof( + &mut self, + driver: &'static str, + ) -> Result<&'a Stage5SumcheckOutput, Stage5KernelError> { + let proof = self + .proof + .sumchecks + .get(self.cursor) + .ok_or(Stage5KernelError::MissingProof { driver })?; + self.cursor += 1; + Ok(proof) + } +} + +impl Stage5KernelExecutor for Stage5ProofCarryingKernelExecutor<'_, F> { + fn observe_challenge_vector( + &mut self, + plan: &'static Stage5TranscriptSqueezePlan, + values: &[F], + ) -> Result<(), Stage5KernelError> { + self.challenge_vectors.push(Stage5ChallengeVector { + symbol: plan.symbol, + values: values.to_vec(), + }); + Ok(()) + } + + fn observe_sumcheck_output( + &mut self, + output: &Stage5SumcheckOutput, + ) -> Result<(), Stage5KernelError> { + self.completed_sumchecks.push(output.clone()); + Ok(()) + } + + fn prove_sumcheck( + &mut self, + context: Stage5KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage5KernelError> + where + T: Transcript, + { + let proof = self.next_proof(context.driver.symbol)?; + verify_stage5_kernel( + context, + self.value_store(context.program)?, + proof, + transcript, + ) + } + + fn verify_sumcheck( + &mut self, + context: Stage5KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage5KernelError> + where + T: Transcript, + { + let proof = self.next_proof(context.driver.symbol)?; + verify_stage5_kernel( + context, + self.value_store(context.program)?, + proof, + transcript, + ) + } +} + +#[derive(Clone, Debug, Default)] +pub struct Stage5ValueStore { + scalars: Vec<(&'static str, F)>, + points: Vec<(&'static str, Vec)>, +} + +impl Stage5ValueStore { + pub fn with_opening_inputs(inputs: &[Stage5OpeningInputValue]) -> Self { + let mut store = Self::default(); + for input in inputs { + store.insert_scalar(input.symbol, input.eval); + store.insert_point(input.symbol, input.point.clone()); + } + store + } + + pub fn seed_constants(&mut self, program: &'static Stage5CpuProgramPlan) { + for constant in program.field_constants { + self.insert_scalar(constant.symbol, F::from_u64(constant.value as u64)); + } + } + + pub fn observe_challenge_vector( + &mut self, + program: &'static Stage5CpuProgramPlan, + plan: &'static Stage5TranscriptSqueezePlan, + values: &[F], + ) -> Result<(), Stage5KernelError> { + self.insert_point(plan.symbol, values.to_vec()); + if matches!(plan.kind, "challenge_scalar" | "scalar") { + require_operand_count(plan.symbol, 1, values.len())?; + self.insert_scalar(plan.symbol, values[0]); + } + let _ = self.evaluate_available_field_exprs(program)?; + Ok(()) + } + + pub fn observe_sumcheck_output( + &mut self, + program: &'static Stage5CpuProgramPlan, + output: &Stage5SumcheckOutput, + ) -> Result<(), Stage5KernelError> { + self.observe_sumcheck_values(program, output.driver, &output.point, &output.evals) + } + + pub fn observe_sumcheck_values( + &mut self, + program: &'static Stage5CpuProgramPlan, + driver: &'static str, + point: &[F], + evals: &[Stage5NamedEval], + ) -> Result<(), Stage5KernelError> { + self.insert_point(driver, point.to_vec()); + for instance in program + .instance_results + .iter() + .filter(|instance| instance.source == driver) + { + let end = instance.round_offset + instance.point_arity; + let mut instance_point = point + .get(instance.round_offset..end) + .ok_or(Stage5KernelError::InvalidInputLength { + input: instance.symbol, + expected: end, + actual: point.len(), + })? + .to_vec(); + match instance.point_order { + "as_is" => {} + "instruction_read_raf" => { + instance_point = normalize_instruction_read_raf_point(&instance_point)?; + } + "reverse" => instance_point.reverse(), + _ => { + return Err(Stage5KernelError::InvalidProof { + driver, + reason: "unsupported point order", + }); + } + } + self.insert_point(instance.symbol, instance_point); + } + for eval in program.evals.iter().filter(|eval| eval.source == driver) { + let value = evals + .iter() + .find(|value| value.name == eval.name) + .or_else(|| evals.get(eval.index)) + .ok_or(Stage5KernelError::MissingValue { + symbol: eval.symbol, + })? + .value; + self.insert_scalar(eval.symbol, value); + self.insert_scalar(eval.name, value); + } + let _ = self.evaluate_available_points(program)?; + let _ = self.evaluate_available_field_exprs(program)?; + self.verify_opening_equalities(program)?; + Ok(()) + } + + pub fn claim_value( + &mut self, + program: &'static Stage5CpuProgramPlan, + claim: &Stage5SumcheckClaimPlan, + ) -> Result { + let _ = self.evaluate_available_field_exprs(program)?; + self.scalar(claim.claim_value) + } + + pub fn batch_claim_values( + &mut self, + program: &'static Stage5CpuProgramPlan, + batch: &Stage5SumcheckBatchPlan, + ) -> Result, Stage5KernelError> { + batch + .claim_operands + .iter() + .map(|symbol| { + let claim = program + .claim(symbol) + .ok_or(Stage5KernelError::MissingClaim { + batch: batch.symbol, + claim: symbol, + })?; + self.claim_value(program, claim) + }) + .collect() + } + + pub fn evaluate_available_points( + &mut self, + program: &'static Stage5CpuProgramPlan, + ) -> Result { + let mut inserted = 0usize; + loop { + let mut progress = 0usize; + for slice in program.point_slices { + if self.try_point(slice.symbol).is_some() { + continue; + } + let Some(input) = self.try_point(slice.input) else { + continue; + }; + let end = slice.offset + slice.length; + let point = input + .get(slice.offset..end) + .ok_or(Stage5KernelError::InvalidInputLength { + input: slice.symbol, + expected: end, + actual: input.len(), + })? + .to_vec(); + self.insert_point(slice.symbol, point); + progress += 1; + } + for concat in program.point_concats { + if self.try_point(concat.symbol).is_some() { + continue; + } + let Some(point) = self.try_concat_point(concat) else { + continue; + }; + require_operand_count(concat.symbol, concat.arity, point.len())?; + self.insert_point(concat.symbol, point); + progress += 1; + } + inserted += progress; + if progress == 0 { + return Ok(inserted); + } + } + } + + pub fn evaluate_available_field_exprs( + &mut self, + program: &'static Stage5CpuProgramPlan, + ) -> Result { + let mut inserted = 0usize; + loop { + let mut progress = 0usize; + for expr in program.field_exprs { + if self.try_scalar(expr.symbol).is_some() { + continue; + } + let Some(operands) = self.try_expr_operands(expr) else { + continue; + }; + self.insert_scalar(expr.symbol, evaluate_stage5_field_expr(expr, &operands)?); + progress += 1; + } + inserted += progress; + if progress == 0 { + return Ok(inserted); + } + } + } + + pub fn verify_opening_equalities( + &self, + program: &'static Stage5CpuProgramPlan, + ) -> Result<(), Stage5KernelError> { + for equality in program.opening_equalities { + match equality.mode { + "point_and_eval" => { + if self.point(equality.lhs)? != self.point(equality.rhs)? + || self.scalar(equality.lhs)? != self.scalar(equality.rhs)? + { + return Err(Stage5KernelError::InvalidProof { + driver: equality.symbol, + reason: "opening claim equality failed", + }); + } + } + _ => { + return Err(Stage5KernelError::InvalidProof { + driver: equality.symbol, + reason: "unsupported opening equality mode", + }); + } + } + } + Ok(()) + } + + pub fn insert_scalar(&mut self, symbol: &'static str, value: F) { + if let Some((_, existing)) = self + .scalars + .iter_mut() + .find(|(existing, _)| *existing == symbol) + { + *existing = value; + } else { + self.scalars.push((symbol, value)); + } + } + + pub fn insert_point(&mut self, symbol: &'static str, point: Vec) { + if let Some((_, existing)) = self + .points + .iter_mut() + .find(|(existing, _)| *existing == symbol) + { + *existing = point; + } else { + self.points.push((symbol, point)); + } + } + + pub fn scalar(&self, symbol: &'static str) -> Result { + self.try_scalar(symbol) + .ok_or(Stage5KernelError::MissingValue { symbol }) + } + + pub fn try_scalar(&self, symbol: &str) -> Option { + self.scalars + .iter() + .find(|(existing, _)| *existing == symbol) + .map(|(_, value)| *value) + } + + pub fn point(&self, symbol: &'static str) -> Result<&[F], Stage5KernelError> { + self.try_point(symbol) + .ok_or(Stage5KernelError::MissingValue { symbol }) + } + + pub fn try_point(&self, symbol: &str) -> Option<&[F]> { + self.points + .iter() + .find(|(existing, _)| *existing == symbol) + .map(|(_, point)| point.as_slice()) + } + + fn try_expr_operands(&self, expr: &Stage5FieldExprPlan) -> Option> { + expr.operands + .iter() + .map(|operand| self.try_scalar(operand)) + .collect() + } + + fn try_concat_point(&self, concat: &Stage5PointConcatPlan) -> Option> { + let mut point = Vec::with_capacity(concat.arity); + for input in concat.inputs { + point.extend_from_slice(self.try_point(input)?); + } + Some(point) + } +} + +fn value_store_from_observations( + program: &'static Stage5CpuProgramPlan, + opening_inputs: &[Stage5OpeningInputValue], + challenge_vectors: &[Stage5ChallengeVector], + completed_sumchecks: &[Stage5SumcheckOutput], +) -> Result, Stage5KernelError> { + let mut store = Stage5ValueStore::with_opening_inputs(opening_inputs); + store.seed_constants(program); + for challenge in challenge_vectors { + let plan = program + .transcript_squeezes + .iter() + .find(|plan| plan.symbol == challenge.symbol) + .ok_or(Stage5KernelError::MissingValue { + symbol: challenge.symbol, + })?; + store.observe_challenge_vector(program, plan, &challenge.values)?; + } + for output in completed_sumchecks { + store.observe_sumcheck_output(program, output)?; + } + let _ = store.evaluate_available_points(program)?; + let _ = store.evaluate_available_field_exprs(program)?; + store.verify_opening_equalities(program)?; + Ok(store) +} + +pub fn evaluate_stage5_field_expr( + expr: &Stage5FieldExprPlan, + operands: &[F], +) -> Result { + match expr.formula { + "opening_eval" => single_operand(expr.symbol, operands), + "field.add" => { + require_operand_count(expr.symbol, 2, operands.len())?; + Ok(operands[0] + operands[1]) + } + "field.sub" => { + require_operand_count(expr.symbol, 2, operands.len())?; + Ok(operands[0] - operands[1]) + } + "field.mul" => { + require_operand_count(expr.symbol, 2, operands.len())?; + Ok(operands[0] * operands[1]) + } + "field.neg" => { + require_operand_count(expr.symbol, 1, operands.len())?; + Ok(-operands[0]) + } + formula => { + if let Some(exponent) = formula.strip_prefix("field.pow:") { + require_operand_count(expr.symbol, 1, operands.len())?; + let exponent = exponent.parse::().map_err(|_| { + Stage5KernelError::UnsupportedFieldExpr { + symbol: expr.symbol, + formula, + } + })?; + return Ok(pow_field(operands[0], exponent)); + } + Err(Stage5KernelError::UnsupportedFieldExpr { + symbol: expr.symbol, + formula, + }) + } + } +} + +fn prove_stage5_kernel( + context: Stage5KernelContext<'_>, + inputs: &Stage5ProverInputs<'_, F>, + store: Stage5ValueStore, + transcript: &mut T, +) -> Result, Stage5KernelError> +where + F: Field, + T: Transcript, +{ + match context.abi_kind()? { + Stage5KernelAbi::Batched => prove_batched_stage5(context, inputs, store, transcript), + abi => Err(Stage5KernelError::KernelNotImplemented { abi: abi.name() }), + } +} + +fn verify_stage5_kernel( + context: Stage5KernelContext<'_>, + store: Stage5ValueStore, + proof: &Stage5SumcheckOutput, + transcript: &mut T, +) -> Result, Stage5KernelError> +where + F: Field, + T: Transcript, +{ + match context.abi_kind()? { + Stage5KernelAbi::Batched => verify_batched_stage5(context, store, proof, transcript), + abi => Err(Stage5KernelError::KernelNotImplemented { abi: abi.name() }), + } +} + +#[tracing::instrument(skip_all, name = "Stage5::prove_batched")] +fn prove_batched_stage5( + context: Stage5KernelContext<'_>, + inputs: &Stage5ProverInputs<'_, F>, + mut store: Stage5ValueStore, + transcript: &mut T, +) -> Result, Stage5KernelError> +where + F: Field, + T: Transcript, +{ + let claims = context.batch_claims()?; + let input_claims = store.batch_claim_values(context.program, context.batch)?; + for claim in &input_claims { + append_labeled_scalar(transcript, context.batch.claim_label, claim); + } + let batching_coeffs = transcript.challenge_vector(claims.len()); + let max_rounds = context.driver.num_rounds; + let two_inv = F::from_u64(2) + .inverse() + .ok_or(Stage5KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "field element 2 is not invertible", + })?; + let mut instances = Vec::with_capacity(claims.len()); + for (index, claim) in claims.iter().enumerate() { + let offset = instance_round_offset(context.program, context.driver.symbol, claim.symbol)?; + if offset + claim.num_rounds > max_rounds { + return Err(Stage5KernelError::InvalidInputLength { + input: claim.symbol, + expected: max_rounds, + actual: offset + claim.num_rounds, + }); + } + let active_scale = F::one().mul_pow_2(max_rounds - offset - claim.num_rounds); + instances.push(Stage5BatchedInstance { + claim, + relation: claim_relation(context.program, claim)?, + offset, + previous_claim: input_claims[index].mul_pow_2(max_rounds - claim.num_rounds), + state: Stage5ProverInstanceState::new( + context.program, + claim, + inputs, + &store, + active_scale, + )?, + }); + } + + let mut point = Vec::with_capacity(max_rounds); + let mut round_polynomials = Vec::with_capacity(max_rounds); + let mut batched_claim = instances + .iter() + .zip(&batching_coeffs) + .map(|(instance, &coefficient)| instance.previous_claim * coefficient) + .sum::(); + for round in 0..max_rounds { + let mut individual_polys = Vec::with_capacity(instances.len()); + for instance in &mut instances { + let poly = if instance.is_active(round) { + instance + .state + .round_poly(instance.previous_claim, instance.relation)? + } else { + UnivariatePoly::new(vec![instance.previous_claim * two_inv]) + }; + individual_polys.push(poly); + } + let batched_poly = combine_univariate_polys(&individual_polys, &batching_coeffs); + if batched_poly.evaluate(F::zero()) + batched_poly.evaluate(F::one()) != batched_claim { + return Err(Stage5KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched round claim mismatch", + }); + } + append_compressed_univariate_poly(transcript, context.driver.round_label, &batched_poly); + let challenge = transcript.challenge(); + point.push(challenge); + batched_claim = batched_poly.evaluate(challenge); + for (instance, poly) in instances.iter_mut().zip(individual_polys) { + instance.previous_claim = poly.evaluate(challenge); + if instance.is_active(round) { + instance.state.ingest_challenge(challenge); + } + } + round_polynomials.push(batched_poly); + } + + let mut evals = Vec::new(); + for instance in &instances { + evals.extend(instance.state.final_evals(instance.relation)?); + } + let expected = + expected_batched_output_claim(context, &store, &evals, &point, &batching_coeffs)?; + if batched_claim != expected { + return Err(Stage5KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched output claim mismatch", + }); + } + store.observe_sumcheck_values(context.program, context.driver.symbol, &point, &evals)?; + let opening_claims = append_opening_claims(context.program, &mut store, transcript, &evals)?; + Ok(Stage5SumcheckOutput { + driver: context.driver.symbol, + point, + evals, + opening_claims, + proof: jolt_sumcheck::SumcheckProof { round_polynomials }, + }) +} + +fn verify_batched_stage5( + context: Stage5KernelContext<'_>, + mut store: Stage5ValueStore, + proof: &Stage5SumcheckOutput, + transcript: &mut T, +) -> Result, Stage5KernelError> +where + F: Field, + T: Transcript, +{ + if proof.driver != context.driver.symbol { + return Err(Stage5KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "driver symbol mismatch", + }); + } + if proof.proof.round_polynomials.len() != context.driver.num_rounds { + return Err(Stage5KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "unexpected batched round count", + }); + } + + let claims = context.batch_claims()?; + let input_claims = store.batch_claim_values(context.program, context.batch)?; + for claim in &input_claims { + append_labeled_scalar(transcript, context.batch.claim_label, claim); + } + let batching_coeffs = transcript.challenge_vector(claims.len()); + let max_rounds = context.driver.num_rounds; + let mut running_claim = input_claims + .iter() + .zip(claims.iter()) + .zip(&batching_coeffs) + .map(|((claim, plan), &coefficient)| { + claim.mul_pow_2(max_rounds - plan.num_rounds) * coefficient + }) + .sum::(); + let mut point = Vec::with_capacity(max_rounds); + for poly in &proof.proof.round_polynomials { + if polynomial_degree(poly) > context.driver.degree { + return Err(Stage5KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched polynomial exceeds degree bound", + }); + } + if poly.evaluate(F::zero()) + poly.evaluate(F::one()) != running_claim { + return Err(Stage5KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched round check failed", + }); + } + append_compressed_univariate_poly(transcript, context.driver.round_label, poly); + let challenge = transcript.challenge(); + running_claim = poly.evaluate(challenge); + point.push(challenge); + } + if !proof.point.is_empty() && proof.point != point { + return Err(Stage5KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched point mismatch", + }); + } + let expected = + expected_batched_output_claim(context, &store, &proof.evals, &point, &batching_coeffs)?; + if running_claim != expected { + return Err(Stage5KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched output claim mismatch", + }); + } + + let output = Stage5SumcheckOutput { + driver: context.driver.symbol, + point, + evals: proof.evals.clone(), + opening_claims: Vec::new(), + proof: proof.proof.clone(), + }; + store.observe_sumcheck_output(context.program, &output)?; + let opening_claims = + append_opening_claims(context.program, &mut store, transcript, &output.evals)?; + let output = Stage5SumcheckOutput { + opening_claims, + ..output + }; + Ok(output) +} + +struct Stage5BatchedInstance<'a, F: Field> { + claim: &'a Stage5SumcheckClaimPlan, + relation: Stage5Relation, + offset: usize, + previous_claim: F, + state: Stage5ProverInstanceState, +} + +impl Stage5BatchedInstance<'_, F> { + fn is_active(&self, round: usize) -> bool { + round >= self.offset && round < self.offset + self.claim.num_rounds + } +} + +enum Stage5ProverInstanceState { + Dense(DenseStage5State), + InstructionReadRaf(InstructionReadRafStage5State), +} + +impl Stage5ProverInstanceState { + fn new( + program: &'static Stage5CpuProgramPlan, + claim: &Stage5SumcheckClaimPlan, + inputs: &Stage5ProverInputs<'_, F>, + store: &Stage5ValueStore, + active_scale: F, + ) -> Result { + match claim_relation(program, claim)? { + Stage5Relation::InstructionReadRaf => { + instruction_read_raf_state(program, claim, inputs, store, active_scale) + .map(Self::InstructionReadRaf) + } + Stage5Relation::RegistersValEvaluation => { + registers_val_evaluation_state(claim, inputs, store, active_scale).map(Self::Dense) + } + Stage5Relation::RamRaClaimReduction => { + ram_ra_claim_reduction_state(claim, inputs, store, active_scale).map(Self::Dense) + } + relation @ Stage5Relation::Batched => Err(Stage5KernelError::KernelNotImplemented { + abi: relation.symbol(), + }), + } + } + + fn round_poly( + &mut self, + previous_claim: F, + relation: Stage5Relation, + ) -> Result, Stage5KernelError> { + match self { + Self::Dense(state) => state.round_poly(previous_claim, relation), + Self::InstructionReadRaf(state) => state.round_poly(previous_claim, relation), + } + } + + fn ingest_challenge(&mut self, challenge: F) { + match self { + Self::Dense(state) => state.bind(challenge), + Self::InstructionReadRaf(state) => state.bind(challenge), + } + } + + fn final_evals( + &self, + relation: Stage5Relation, + ) -> Result>, Stage5KernelError> { + match self { + Self::Dense(state) => state.final_evals(relation), + Self::InstructionReadRaf(state) => state.final_evals(relation), + } + } +} + +struct DenseStage5State { + factors: Vec>, + factor_scratch: Vec>, + terms: Vec>, + outputs: Vec, + active_scale: F, +} + +#[derive(Clone)] +struct DenseTerm { + coefficient: F, + factors: Vec, +} + +#[derive(Clone, Copy)] +struct FactorOutput { + name: &'static str, + oracle: &'static str, + factor: usize, +} + +#[derive(Clone, Copy)] +enum InstructionReadRafOutputKind { + LookupTableFlag(usize), + InstructionRa(usize), + InstructionRafFlag, +} + +#[derive(Clone, Copy)] +struct InstructionReadRafOutputPlan { + index: usize, + name: &'static str, + oracle: &'static str, + kind: InstructionReadRafOutputKind, +} + +struct InstructionReadRafStage5State { + trace_len: usize, + lookup_indices: Vec, + lookup_table_indices: Vec>, + is_interleaved_operands: Vec, + lookup_groups: Vec>, + lookup_group_indices_by_cycle: Vec, + lookup_groups_by_table: Vec>, + ra_virtual_log_k_chunk: usize, + u_evals: Vec, + gamma: F, + gamma2: F, + active_scale: F, + round: usize, + address_challenges: Vec, + cycle_challenges: Vec, + address_phase: Option>, + left_operand_checkpoint: F, + right_operand_checkpoint: F, + identity_checkpoint: F, + read_prefix_checkpoints: Vec>, + cycle_state: Option>, + outputs: Vec, +} + +struct InstructionReadRafLookupGroup { + lookup_index: u128, + lookup_table_index: Option, + is_interleaved_operands: bool, + u_eval_sum: F, + phase_u_eval_sum: F, +} + +struct InstructionReadRafAddressPhase { + phase: usize, + left_operand_prefix: Vec, + right_operand_prefix: Vec, + identity_prefix: Vec, + raf_shift_half_q: Vec, + raf_left_q: Vec, + raf_right_q: Vec, + raf_shift_full_q: Vec, + raf_identity_q: Vec, + read_prefix_polys: Vec>, + read_suffix_polys: Vec>, +} + +struct InstructionReadRafReadTablePhase { + table: LookupTableKind<64>, + suffix_polys: Vec>, +} + +struct InstructionReadRafCycleState { + factors: Vec>, + factor_scratch: Vec>, +} + +impl DenseStage5State { + fn new( + factors: Vec>, + terms: Vec>, + outputs: Vec, + active_scale: F, + ) -> Self { + let factor_scratch = (0..factors.len()).map(|_| Vec::new()).collect(); + Self { + factors, + factor_scratch, + terms, + outputs, + active_scale, + } + } + + fn round_poly( + &self, + previous_claim: F, + relation: Stage5Relation, + ) -> Result, Stage5KernelError> { + let first_len = self.factors.first().map_or(0, Vec::len); + if first_len == 0 || !first_len.is_power_of_two() { + return Err(Stage5KernelError::InvalidProof { + driver: relation.symbol(), + reason: "stage5 dense factor has invalid length", + }); + } + if self.factors.iter().any(|factor| factor.len() != first_len) { + return Err(Stage5KernelError::InvalidProof { + driver: relation.symbol(), + reason: "stage5 dense factors have inconsistent lengths", + }); + } + let poly = + round_poly_from_dense_terms(&self.factors, &self.terms, self.active_scale, relation)?; + if poly.evaluate(F::zero()) + poly.evaluate(F::one()) != previous_claim { + return Err(Stage5KernelError::InvalidProof { + driver: relation.symbol(), + reason: "stage5 relation input claim mismatch", + }); + } + Ok(poly) + } + + fn bind(&mut self, challenge: F) { + if self.factors.first().map_or(0, Vec::len) / 2 >= DENSE_BIND_PAR_THRESHOLD { + self.factors + .par_iter_mut() + .zip(self.factor_scratch.par_iter_mut()) + .for_each(|(factor, scratch)| { + bind_dense_evals_reuse(factor, scratch, challenge); + }); + } else { + for (factor, scratch) in self.factors.iter_mut().zip(&mut self.factor_scratch) { + bind_dense_evals_reuse(factor, scratch, challenge); + } + } + } + + fn factor_eval(&self, index: usize, relation: Stage5Relation) -> Result { + self.factors + .get(index) + .and_then(|values| values.first()) + .copied() + .ok_or(Stage5KernelError::InvalidProof { + driver: relation.symbol(), + reason: "empty stage5 factor", + }) + } + + fn final_evals( + &self, + relation: Stage5Relation, + ) -> Result>, Stage5KernelError> { + self.outputs + .iter() + .map(|output| { + Ok(named_eval( + output.name, + output.oracle, + self.factor_eval(output.factor, relation)?, + )) + }) + .collect() + } +} + +impl InstructionReadRafStage5State { + const LOG_K: usize = 128; + const ADDRESS_CHUNK_BITS: usize = 8; + + fn round_poly( + &mut self, + previous_claim: F, + relation: Stage5Relation, + ) -> Result, Stage5KernelError> { + if self.round < Self::LOG_K { + self.ensure_address_phase(); + let Some(address_phase) = self.address_phase.as_ref() else { + std::process::abort(); + }; + let (read, raf_components) = if address_phase.left_operand_prefix.len() <= 32 { + ( + address_phase.read_table_round_evals(), + address_phase.raf_round_component_evals(), + ) + } else { + rayon::join( + || address_phase.read_table_round_evals(), + || address_phase.raf_round_component_evals(), + ) + }; + let eval_at_0 = (read[0] + + self.gamma * raf_components[0][0] + + self.gamma2 * (raf_components[1][0] + raf_components[2][0])) + * self.active_scale; + let eval_at_2 = (read[1] + + self.gamma * raf_components[0][1] + + self.gamma2 * (raf_components[1][1] + raf_components[2][1])) + * self.active_scale; + let result = Ok(UnivariatePoly::from_evals_and_hint( + previous_claim, + &[eval_at_0, eval_at_2], + )); + return result; + } + + if self.cycle_state.is_none() { + self.cycle_state = Some(self.materialize_cycle_state()?); + } + let Some(cycle_state) = self.cycle_state.as_ref() else { + std::process::abort(); + }; + cycle_state.round_poly(previous_claim, self.active_scale, relation) + } + + fn bind(&mut self, challenge: F) { + if self.round < Self::LOG_K { + self.ensure_address_phase(); + self.address_challenges.push(challenge); + if let Some(phase) = &mut self.address_phase { + phase.bind(challenge); + } + if (self.round + 1).is_multiple_of(Self::ADDRESS_CHUNK_BITS) { + self.finish_address_phase(); + } + } else { + self.cycle_challenges.push(challenge); + if let Some(cycle_state) = &mut self.cycle_state { + cycle_state.bind(challenge); + } + } + self.round += 1; + } + + fn final_evals( + &self, + relation: Stage5Relation, + ) -> Result>, Stage5KernelError> { + require_operand_count( + "stage5.instruction_read_raf.address_challenges", + Self::LOG_K, + self.address_challenges.len(), + )?; + require_operand_count( + "stage5.instruction_read_raf.cycle_challenges", + log2_exact(self.trace_len, "stage5.instruction_read_raf.trace_len")?, + self.cycle_challenges.len(), + )?; + + let normalized_cycle_point = reverse_slice(&self.cycle_challenges); + let evaluations = self.instruction_read_raf_output_evals_from_groups( + &self.address_challenges, + &normalized_cycle_point, + )?; + self.outputs + .iter() + .map(|output| { + let value = match output.kind { + InstructionReadRafOutputKind::LookupTableFlag(index) => { + evaluations.lookup_table_flags.get(index).copied().ok_or( + Stage5KernelError::InvalidInputLength { + input: "stage5.instruction_read_raf.lookup_table_flags", + expected: evaluations.lookup_table_flags.len(), + actual: index + 1, + }, + )? + } + InstructionReadRafOutputKind::InstructionRa(index) => { + evaluations.instruction_ra.get(index).copied().ok_or( + Stage5KernelError::InvalidInputLength { + input: "stage5.instruction_read_raf.instruction_ra", + expected: evaluations.instruction_ra.len(), + actual: index + 1, + }, + )? + } + InstructionReadRafOutputKind::InstructionRafFlag => { + evaluations.instruction_raf_flag + } + }; + Ok(named_eval(output.name, output.oracle, value)) + }) + .collect::, _>>() + .map_err(|error| match error { + Stage5KernelError::InvalidInputLength { .. } => error, + _ => Stage5KernelError::InvalidProof { + driver: relation.symbol(), + reason: "invalid instruction read raf output", + }, + }) + } + + fn ensure_address_phase(&mut self) { + debug_assert!(Self::LOG_K.is_multiple_of(Self::ADDRESS_CHUNK_BITS)); + let phase = self.round / Self::ADDRESS_CHUNK_BITS; + if self + .address_phase + .as_ref() + .is_some_and(|address_phase| address_phase.phase == phase) + { + return; + } + self.address_phase = Some(self.build_address_phase(phase)); + } + + fn build_address_phase(&self, phase: usize) -> InstructionReadRafAddressPhase { + let chunk_bits = Self::ADDRESS_CHUNK_BITS; + let poly_len = 1usize << chunk_bits; + let suffix_len = Self::LOG_K - (phase + 1) * chunk_bits; + let left_operand_prefix = + operand_prefix_poly(self.left_operand_checkpoint, chunk_bits, true); + let right_operand_prefix = + operand_prefix_poly(self.right_operand_checkpoint, chunk_bits, false); + let identity_prefix = identity_prefix_poly(self.identity_checkpoint, chunk_bits); + let read_prefix_polys = ALL_PREFIXES + .par_iter() + .map(|prefix| { + (0..poly_len) + .map(|bits| { + prefix + .evaluate( + &self.read_prefix_checkpoints, + LookupBits::new(bits as u128, chunk_bits), + suffix_len, + ) + .into_inner() + }) + .collect::>() + }) + .collect::>(); + + let shift_half_value = 1u128 << (suffix_len / 2); + let shift_full_value = 1u128 << suffix_len; + let shift_half = F::from_u128(shift_half_value); + let shift_full = F::from_u128(shift_full_value); + let suffix_mask = if suffix_len == 128 { + u128::MAX + } else { + (1u128 << suffix_len) - 1 + }; + + let q_total_len = 5 * poly_len; + let q_chunk_size = self + .lookup_groups + .len() + .div_ceil(rayon::current_num_threads()) + .max(1); + let q_rows = self + .lookup_groups + .par_chunks(q_chunk_size) + .fold( + || vec![F::zero(); q_total_len], + |mut acc, groups| { + let shift_half_offset = 0; + let left_offset = poly_len; + let right_offset = 2 * poly_len; + let shift_full_offset = 3 * poly_len; + let identity_offset = 4 * poly_len; + + for group in groups { + let index = ((group.lookup_index >> suffix_len) as usize) & (poly_len - 1); + let suffix_bits = group.lookup_index & suffix_mask; + let weight = group.phase_u_eval_sum; + + if group.is_interleaved_operands { + acc[shift_half_offset + index] += weight; + let (left_suffix, right_suffix) = uninterleave_bits(suffix_bits); + if left_suffix != 0 { + acc[left_offset + index] += weight.mul_u64(left_suffix); + } + if right_suffix != 0 { + acc[right_offset + index] += weight.mul_u64(right_suffix); + } + } else { + acc[shift_full_offset + index] += weight; + if suffix_bits != 0 { + acc[identity_offset + index] += weight.mul_u128(suffix_bits); + } + } + } + acc + }, + ) + .reduce( + || vec![F::zero(); q_total_len], + |mut left, right| { + for (left_value, right_value) in left.iter_mut().zip(right) { + *left_value += right_value; + } + left + }, + ); + let mut raf_shift_half_q = q_rows[..poly_len].to_vec(); + let raf_left_q = q_rows[poly_len..2 * poly_len].to_vec(); + let raf_right_q = q_rows[2 * poly_len..3 * poly_len].to_vec(); + let mut raf_shift_full_q = q_rows[3 * poly_len..4 * poly_len].to_vec(); + let raf_identity_q = q_rows[4 * poly_len..5 * poly_len].to_vec(); + if shift_half_value != 1 { + for value in &mut raf_shift_half_q { + *value *= shift_half; + } + } + if shift_full_value != 1 { + for value in &mut raf_shift_full_q { + *value *= shift_full; + } + } + + let tables = LookupTableKind::<64>::all(); + let read_suffix_polys = tables + .par_iter() + .enumerate() + .filter_map(|(table_index, table)| { + if self.lookup_groups_by_table[table_index].is_empty() { + return None; + } + let suffixes = table.suffixes(); + let mut accumulators = + vec![vec![F::ScalarAccumulator::default(); poly_len]; suffixes.len()]; + let mut one_suffix = None; + let mut boolean_suffixes = Vec::new(); + let mut valued_suffixes = Vec::new(); + for (suffix_index, suffix) in suffixes.iter().enumerate() { + if matches!(suffix, Suffixes::One) { + one_suffix = Some(suffix_index); + } else if suffix.is_01_valued() { + boolean_suffixes.push((suffix_index, suffix)); + } else { + valued_suffixes.push((suffix_index, suffix)); + } + } + for &group_index in &self.lookup_groups_by_table[table_index] { + let group = &self.lookup_groups[group_index]; + let index = ((group.lookup_index >> suffix_len) as usize) & (poly_len - 1); + let suffix_bits = LookupBits::new(group.lookup_index & suffix_mask, suffix_len); + let weight = group.phase_u_eval_sum; + if let Some(suffix_index) = one_suffix { + accumulators[suffix_index][index].add(weight); + } + for &(suffix_index, suffix) in &boolean_suffixes { + let suffix_value = suffix.suffix_mle(suffix_bits); + debug_assert!(suffix_value == 0 || suffix_value == 1); + if suffix_value == 1 { + accumulators[suffix_index][index].add(weight); + } + } + for &(suffix_index, suffix) in &valued_suffixes { + let suffix_value = suffix.suffix_mle(suffix_bits); + accumulators[suffix_index][index].add_mul_u64(weight, suffix_value); + } + } + let polys = accumulators + .into_iter() + .map(|poly| { + poly.into_iter() + .map(FieldScalarAccumulator::reduce) + .collect::>() + }) + .collect::>(); + Some(InstructionReadRafReadTablePhase { + table: *table, + suffix_polys: polys, + }) + }) + .collect::>(); + + InstructionReadRafAddressPhase { + phase, + left_operand_prefix, + right_operand_prefix, + identity_prefix, + raf_shift_half_q, + raf_left_q, + raf_right_q, + raf_shift_full_q, + raf_identity_q, + read_prefix_polys, + read_suffix_polys, + } + } + + fn finish_address_phase(&mut self) { + let Some(phase) = self.address_phase.take() else { + return; + }; + self.left_operand_checkpoint = phase.left_operand_prefix[0]; + self.right_operand_checkpoint = phase.right_operand_prefix[0]; + self.identity_checkpoint = phase.identity_prefix[0]; + self.read_prefix_checkpoints = phase + .read_prefix_polys + .iter() + .map(|poly| PrefixEval::from(poly[0])) + .collect(); + + let chunk_bits = Self::ADDRESS_CHUNK_BITS; + let start = phase.phase * chunk_bits; + let end = start + chunk_bits; + let point = &self.address_challenges[start..end]; + let shift = Self::LOG_K - end; + let mask = (1u128 << chunk_bits) - 1; + let eq_table = (0..(1usize << chunk_bits)) + .map(|bits| eq_eval_at_bits(point, bits as u128, chunk_bits)) + .collect::>(); + self.lookup_groups.par_iter_mut().for_each(|group| { + let chunk_value = (group.lookup_index >> shift) & mask; + group.phase_u_eval_sum *= eq_table[chunk_value as usize]; + }); + } + + fn materialize_cycle_state( + &self, + ) -> Result, Stage5KernelError> { + require_operand_count( + "stage5.instruction_read_raf.address_challenges", + Self::LOG_K, + self.address_challenges.len(), + )?; + let tables = LookupTableKind::<64>::all(); + let ra_chunks = Self::LOG_K / self.ra_virtual_log_k_chunk; + let mut factors = Vec::with_capacity(2 + ra_chunks); + factors.push(self.u_evals.clone()); + let table_values_at_address = tables + .par_iter() + .enumerate() + .map(|(table_index, table)| { + if self.lookup_groups_by_table[table_index].is_empty() { + F::zero() + } else { + table.evaluate_mle::(&self.address_challenges) + } + }) + .collect::>(); + let raf_interleaved = self.gamma * operand_polynomial_eval(&self.address_challenges, true) + + self.gamma2 * operand_polynomial_eval(&self.address_challenges, false); + let raf_identity = self.gamma2 * identity_polynomial_eval(&self.address_challenges); + factors.push( + (0..self.trace_len) + .into_par_iter() + .map(|cycle| { + let table_value = self.lookup_table_indices[cycle] + .map_or_else(F::zero, |table_index| table_values_at_address[table_index]); + let raf_value = if self.is_interleaved_operands[cycle] { + raf_interleaved + } else { + raf_identity + }; + table_value + raf_value + }) + .collect(), + ); + + let chunk_bits = self.ra_virtual_log_k_chunk; + let chunk_mask = if chunk_bits == 128 { + u128::MAX + } else { + (1u128 << chunk_bits) - 1 + }; + for chunk in 0..ra_chunks { + let chunk_point = + &self.address_challenges[chunk * chunk_bits..(chunk + 1) * chunk_bits]; + let eq_tables = eq_eval_bit_chunk_tables(chunk_point, 8); + let shift = Self::LOG_K - (chunk + 1) * chunk_bits; + factors.push( + self.lookup_indices + .par_iter() + .map(|&lookup_index| { + let chunk_value = (lookup_index >> shift) & chunk_mask; + eq_eval_at_bits_from_chunk_tables(&eq_tables, chunk_value, chunk_bits, 8) + }) + .collect(), + ); + } + InstructionReadRafCycleState::new(factors, Stage5Relation::InstructionReadRaf) + } + + fn instruction_read_raf_output_evals_from_groups( + &self, + address_point: &[F], + cycle_point: &[F], + ) -> Result, Stage5KernelError> { + require_operand_count( + "stage5.instruction_read_raf.address_point", + Self::LOG_K, + address_point.len(), + )?; + let trace_len_from_point = 1usize.checked_shl(cycle_point.len() as u32).ok_or( + Stage5KernelError::InvalidInputLength { + input: "stage5.instruction_read_raf.cycle_point", + expected: usize::BITS as usize, + actual: cycle_point.len(), + }, + )?; + require_operand_count( + "stage5.instruction_read_raf.trace_len", + trace_len_from_point, + self.trace_len, + )?; + + let tables = LookupTableKind::<64>::all(); + let table_count = tables.len(); + let cycle_eq = EqPolynomial::::evals(cycle_point, None); + require_operand_count( + "stage5.instruction_read_raf.eq_cycle", + self.trace_len, + cycle_eq.len(), + )?; + + let mut lookup_table_flags = vec![F::zero(); table_count]; + let mut instruction_raf_flag = F::zero(); + let mut group_weights = vec![F::zero(); self.lookup_groups.len()]; + for (&group_index, &weight) in self.lookup_group_indices_by_cycle.iter().zip(&cycle_eq) { + group_weights[group_index] += weight; + } + + for (group, &weight) in self.lookup_groups.iter().zip(&group_weights) { + if let Some(table_index) = group.lookup_table_index { + let Some(flag) = lookup_table_flags.get_mut(table_index) else { + return Err(Stage5KernelError::InvalidInputLength { + input: "stage5.instruction_read_raf.lookup_table_indices", + expected: table_count, + actual: table_index + 1, + }); + }; + *flag += weight; + } + if !group.is_interleaved_operands { + instruction_raf_flag += weight; + } + } + + let ra_chunks = Self::LOG_K / self.ra_virtual_log_k_chunk; + let cycle_state = self + .cycle_state + .as_ref() + .ok_or(Stage5KernelError::InvalidProof { + driver: Stage5Relation::InstructionReadRaf.symbol(), + reason: "instruction read raf cycle state is not materialized", + })?; + let instruction_ra = (0..ra_chunks) + .map(|chunk| { + cycle_state + .factor_eval(2 + chunk) + .ok_or(Stage5KernelError::InvalidInputLength { + input: "stage5.instruction_read_raf.instruction_ra", + expected: cycle_state.factors.len(), + actual: 2 + chunk + 1, + }) + }) + .collect::, _>>()?; + + Ok(Stage5InstructionReadRafEvaluations { + lookup_table_flags, + instruction_ra, + instruction_raf_flag, + }) + } +} + +impl InstructionReadRafAddressPhase { + fn read_table_round_evals(&self) -> [F; 2] { + let len = self.read_prefix_polys.first().map_or(0, |poly| poly.len()); + debug_assert!(len > 1); + debug_assert!(self.read_prefix_polys.iter().all(|poly| poly.len() == len)); + debug_assert!(self + .read_suffix_polys + .iter() + .flat_map(|read_table| read_table.suffix_polys.iter()) + .all(|poly| poly.len() == len)); + let half = len / 2; + let prefix_evals = (0..half) + .map(|row| { + ( + self.read_prefix_evals(row, false), + self.read_prefix_evals(row, true), + ) + }) + .collect::>(); + if half <= 16 { + self.read_suffix_polys + .iter() + .fold([F::zero(), F::zero()], |mut total, read_table| { + let eval = read_table_component_eval(read_table, half, &prefix_evals); + total[0] += eval[0]; + total[1] += eval[1]; + total + }) + } else { + self.read_suffix_polys + .par_iter() + .map(|read_table| read_table_component_eval(read_table, half, &prefix_evals)) + .reduce( + || [F::zero(), F::zero()], + |mut left, right| { + left[0] += right[0]; + left[1] += right[1]; + left + }, + ) + } + } + + fn read_prefix_evals(&self, row: usize, at_2: bool) -> [PrefixEval; NUM_PREFIXES] { + let half = self.read_prefix_polys[0].len() / 2; + let mut values = [PrefixEval::from(F::zero()); NUM_PREFIXES]; + for (value, poly) in values.iter_mut().zip(&self.read_prefix_polys) { + let low = poly[row]; + let eval = if at_2 { + let high = poly[row + half]; + high + high - low + } else { + low + }; + *value = PrefixEval::from(eval); + } + values + } + + fn raf_round_component_evals(&self) -> [[F; 2]; 3] { + let (left_0, left_2) = prefix_suffix_round_evals( + Some(&self.left_operand_prefix), + &self.raf_shift_half_q, + &self.raf_left_q, + ); + let (right_0, right_2) = prefix_suffix_round_evals( + Some(&self.right_operand_prefix), + &self.raf_shift_half_q, + &self.raf_right_q, + ); + let (identity_0, identity_2) = prefix_suffix_round_evals( + Some(&self.identity_prefix), + &self.raf_shift_full_q, + &self.raf_identity_q, + ); + [ + [left_0, left_2], + [right_0, right_2], + [identity_0, identity_2], + ] + } + + fn bind(&mut self, challenge: F) { + if self.left_operand_prefix.len() <= 32 { + bind_high_to_low(&mut self.left_operand_prefix, challenge); + bind_high_to_low(&mut self.right_operand_prefix, challenge); + bind_high_to_low(&mut self.identity_prefix, challenge); + bind_high_to_low(&mut self.raf_shift_half_q, challenge); + bind_high_to_low(&mut self.raf_left_q, challenge); + bind_high_to_low(&mut self.raf_right_q, challenge); + bind_high_to_low(&mut self.raf_shift_full_q, challenge); + bind_high_to_low(&mut self.raf_identity_q, challenge); + for poly in &mut self.read_prefix_polys { + bind_high_to_low(poly, challenge); + } + for read_table in &mut self.read_suffix_polys { + for poly in &mut read_table.suffix_polys { + bind_high_to_low(poly, challenge); + } + } + return; + } + + let left_operand_prefix = &mut self.left_operand_prefix; + let right_operand_prefix = &mut self.right_operand_prefix; + let identity_prefix = &mut self.identity_prefix; + let raf_shift_half_q = &mut self.raf_shift_half_q; + let raf_left_q = &mut self.raf_left_q; + let raf_right_q = &mut self.raf_right_q; + let raf_shift_full_q = &mut self.raf_shift_full_q; + let raf_identity_q = &mut self.raf_identity_q; + let read_prefix_polys = &mut self.read_prefix_polys; + let read_suffix_polys = &mut self.read_suffix_polys; + rayon::scope(|scope| { + scope.spawn(|_| { + bind_high_to_low(left_operand_prefix, challenge); + bind_high_to_low(right_operand_prefix, challenge); + bind_high_to_low(identity_prefix, challenge); + }); + scope.spawn(|_| { + bind_high_to_low(raf_shift_half_q, challenge); + bind_high_to_low(raf_left_q, challenge); + bind_high_to_low(raf_right_q, challenge); + bind_high_to_low(raf_shift_full_q, challenge); + bind_high_to_low(raf_identity_q, challenge); + }); + scope.spawn(|_| { + read_prefix_polys + .par_iter_mut() + .for_each(|poly| bind_high_to_low(poly, challenge)); + }); + scope.spawn(|_| { + read_suffix_polys.par_iter_mut().for_each(|read_table| { + for poly in &mut read_table.suffix_polys { + bind_high_to_low(poly, challenge); + } + }); + }); + }); + } +} + +fn read_table_component_eval( + read_table: &InstructionReadRafReadTablePhase, + half: usize, + prefix_evals: &[PrefixPairEvals], +) -> [F; 2] { + let mut eval_0 = F::zero(); + let mut eval_2_left = F::zero(); + let mut eval_2_right = F::zero(); + for row in 0..half { + let (prefixes_0, prefixes_2) = &prefix_evals[row]; + let mut suffixes_left = [F::zero(); 4]; + let mut suffixes_right = [F::zero(); 4]; + for (suffix_index, poly) in read_table.suffix_polys.iter().enumerate() { + suffixes_left[suffix_index] = poly[row]; + suffixes_right[suffix_index] = poly[row + half]; + } + let suffix_count = read_table.suffix_polys.len(); + eval_0 += read_table + .table + .combine(prefixes_0, &suffixes_left[..suffix_count]); + eval_2_left += read_table + .table + .combine(prefixes_2, &suffixes_left[..suffix_count]); + eval_2_right += read_table + .table + .combine(prefixes_2, &suffixes_right[..suffix_count]); + } + [eval_0, eval_2_right + eval_2_right - eval_2_left] +} + +#[inline] +fn prefix_suffix_round_evals(prefix: Option<&[F]>, q0: &[F], q1: &[F]) -> (F, F) { + let len = q0.len(); + debug_assert_eq!(q1.len(), len); + debug_assert!(len > 1); + let half = len / 2; + let mut eval_0 = F::zero(); + let mut eval_2_left = F::zero(); + let mut eval_2_right = F::zero(); + for row in 0..half { + let (prefix_0, prefix_2) = prefix.map_or((F::one(), F::one()), |poly| { + debug_assert_eq!(poly.len(), len); + let low = poly[row]; + let high = poly[row + half]; + (low, high + high - low) + }); + eval_0 += prefix_0 * q0[row] + q1[row]; + eval_2_left += prefix_2 * q0[row] + q1[row]; + eval_2_right += prefix_2 * q0[row + half] + q1[row + half]; + } + (eval_0, eval_2_right + eval_2_right - eval_2_left) +} + +fn operand_prefix_poly(checkpoint: F, chunk_bits: usize, left: bool) -> Vec { + debug_assert!(chunk_bits.is_multiple_of(2)); + let shift = 1u128 << (chunk_bits / 2); + (0..(1usize << chunk_bits)) + .map(|bits| { + let lookup_bits = LookupBits::new(bits as u128, chunk_bits); + let (left_bits, right_bits) = lookup_bits.uninterleave(); + let operand_bits: u64 = if left { + left_bits.into() + } else { + right_bits.into() + }; + checkpoint.mul_u128(shift) + F::from_u64(operand_bits) + }) + .collect() +} + +fn identity_prefix_poly(checkpoint: F, chunk_bits: usize) -> Vec { + let shift = 1u128 << chunk_bits; + (0..(1usize << chunk_bits)) + .map(|bits| checkpoint.mul_u128(shift) + F::from_u64(bits as u64)) + .collect() +} + +impl InstructionReadRafCycleState { + fn new(factors: Vec>, relation: Stage5Relation) -> Result { + let first_len = factors.first().map_or(0, Vec::len); + if first_len == 0 || !first_len.is_power_of_two() { + return Err(Stage5KernelError::InvalidProof { + driver: relation.symbol(), + reason: "instruction read raf cycle factor has invalid length", + }); + } + if factors.iter().any(|factor| factor.len() != first_len) { + return Err(Stage5KernelError::InvalidProof { + driver: relation.symbol(), + reason: "instruction read raf cycle factors have inconsistent lengths", + }); + } + let factor_scratch = (0..factors.len()).map(|_| Vec::new()).collect(); + Ok(Self { + factors, + factor_scratch, + }) + } + + fn round_poly( + &self, + previous_claim: F, + active_scale: F, + relation: Stage5Relation, + ) -> Result, Stage5KernelError> { + let coefficients = self.round_coefficients(active_scale); + let poly = UnivariatePoly::new(coefficients); + if poly.evaluate(F::zero()) + poly.evaluate(F::one()) != previous_claim { + return Err(Stage5KernelError::InvalidProof { + driver: relation.symbol(), + reason: "instruction read raf cycle input claim mismatch", + }); + } + Ok(poly) + } + + fn factor_eval(&self, index: usize) -> Option { + self.factors + .get(index) + .and_then(|factor| factor.first()) + .copied() + } + + fn round_coefficients(&self, active_scale: F) -> Vec { + const MAX_DEGREE_PLUS_ONE: usize = 16; + let degree = self.factors.len(); + debug_assert!(degree < MAX_DEGREE_PLUS_ONE); + let half = self.factors[0].len() / 2; + let mut sums = if half >= DENSE_BIND_PAR_THRESHOLD { + (0..half) + .into_par_iter() + .fold( + || [F::zero(); MAX_DEGREE_PLUS_ONE], + |mut sums, row| { + accumulate_cycle_row_coefficients(&mut sums, &self.factors, degree, row); + sums + }, + ) + .reduce( + || [F::zero(); MAX_DEGREE_PLUS_ONE], + |mut left, right| { + for coefficient_index in 0..=degree { + left[coefficient_index] += right[coefficient_index]; + } + left + }, + ) + } else { + (0..half).fold([F::zero(); MAX_DEGREE_PLUS_ONE], |mut sums, row| { + accumulate_cycle_row_coefficients(&mut sums, &self.factors, degree, row); + sums + }) + }; + sums[..=degree] + .iter_mut() + .map(|coefficient| *coefficient * active_scale) + .collect() + } + + fn bind(&mut self, challenge: F) { + if self.factors.first().map_or(0, Vec::len) / 2 >= DENSE_BIND_PAR_THRESHOLD { + self.factors + .par_iter_mut() + .zip(self.factor_scratch.par_iter_mut()) + .for_each(|(factor, scratch)| { + bind_dense_evals_reuse(factor, scratch, challenge); + }); + } else { + for (factor, scratch) in self.factors.iter_mut().zip(&mut self.factor_scratch) { + bind_dense_evals_reuse(factor, scratch, challenge); + } + } + } +} + +fn accumulate_cycle_row_coefficients( + sums: &mut [F; N], + factors: &[Vec], + degree: usize, + row: usize, +) { + let mut coefficients = [F::zero(); N]; + coefficients[0] = F::one(); + for (current_degree, factor) in factors.iter().enumerate() { + let low = factor[2 * row]; + let diff = factor[2 * row + 1] - low; + coefficients[current_degree + 1] = F::zero(); + for coefficient_index in (0..=current_degree).rev() { + let coefficient = coefficients[coefficient_index]; + coefficients[coefficient_index + 1] += coefficient * diff; + coefficients[coefficient_index] = coefficient * low; + } + } + for coefficient_index in 0..=degree { + sums[coefficient_index] += coefficients[coefficient_index]; + } +} + +fn instruction_read_raf_state( + program: &'static Stage5CpuProgramPlan, + claim: &Stage5SumcheckClaimPlan, + inputs: &Stage5ProverInputs<'_, F>, + store: &Stage5ValueStore, + active_scale: F, +) -> Result, Stage5KernelError> { + const LOG_K: usize = 128; + const XLEN: usize = 64; + + let witness = inputs + .instruction_read_raf + .ok_or(Stage5KernelError::MissingKernelInput { + kernel: "jolt_stage5_instruction_read_raf", + input: "instruction_read_raf", + })?; + let trace_rounds = log2_exact(witness.trace_len, "stage5.instruction_read_raf.trace_len")?; + require_operand_count( + "stage5.instruction_read_raf.input", + LOG_K + trace_rounds, + claim.num_rounds, + )?; + require_operand_count( + "stage5.instruction_read_raf.lookup_indices", + witness.trace_len, + witness.lookup_indices.len(), + )?; + require_operand_count( + "stage5.instruction_read_raf.lookup_table_indices", + witness.trace_len, + witness.lookup_table_indices.len(), + )?; + require_operand_count( + "stage5.instruction_read_raf.is_interleaved_operands", + witness.trace_len, + witness.is_interleaved_operands.len(), + )?; + if witness.ra_virtual_log_k_chunk == 0 || !LOG_K.is_multiple_of(witness.ra_virtual_log_k_chunk) + { + return Err(Stage5KernelError::InvalidInputLength { + input: "stage5.instruction_read_raf.ra_virtual_log_k_chunk", + expected: LOG_K, + actual: witness.ra_virtual_log_k_chunk, + }); + } + + let table_count = LookupTableKind::::all().len(); + for table_index in witness.lookup_table_indices.iter().flatten() { + if *table_index >= table_count { + return Err(Stage5KernelError::InvalidInputLength { + input: "stage5.instruction_read_raf.lookup_table_indices", + expected: table_count, + actual: table_index + 1, + }); + } + } + + let r_reduction = store.point("stage5.input.stage2.instruction.LookupOutput")?; + require_operand_count( + "stage5.input.stage2.instruction.LookupOutput", + trace_rounds, + r_reduction.len(), + )?; + let u_evals = EqPolynomial::::evals(r_reduction, None); + require_operand_count( + "stage5.instruction_read_raf.u_evals", + witness.trace_len, + u_evals.len(), + )?; + + let gamma = store.scalar("stage5.instruction_read_raf.gamma")?; + let gamma2 = store + .try_scalar("stage5.instruction_read_raf.gamma2") + .unwrap_or_else(|| gamma * gamma); + let ra_chunks = LOG_K / witness.ra_virtual_log_k_chunk; + let outputs = instruction_read_raf_output_plans(program, claim, table_count, ra_chunks)?; + + let (lookup_groups, lookup_group_indices_by_cycle) = + instruction_read_raf_lookup_groups(witness, &u_evals)?; + let mut lookup_groups_by_table = vec![Vec::new(); table_count]; + for (group_index, group) in lookup_groups.iter().enumerate() { + if let Some(table_index) = group.lookup_table_index { + lookup_groups_by_table[table_index].push(group_index); + } + } + + Ok(InstructionReadRafStage5State { + trace_len: witness.trace_len, + lookup_indices: witness.lookup_indices.to_vec(), + lookup_table_indices: witness.lookup_table_indices.to_vec(), + is_interleaved_operands: witness.is_interleaved_operands.to_vec(), + lookup_groups, + lookup_group_indices_by_cycle, + lookup_groups_by_table, + ra_virtual_log_k_chunk: witness.ra_virtual_log_k_chunk, + u_evals, + gamma, + gamma2, + active_scale, + round: 0, + address_challenges: Vec::with_capacity(LOG_K), + cycle_challenges: Vec::with_capacity(trace_rounds), + address_phase: None, + left_operand_checkpoint: F::zero(), + right_operand_checkpoint: F::zero(), + identity_checkpoint: F::zero(), + read_prefix_checkpoints: ALL_PREFIXES + .iter() + .map(|prefix| prefix.default_checkpoint::()) + .collect(), + cycle_state: None, + outputs, + }) +} + +fn instruction_read_raf_lookup_groups( + witness: Stage5InstructionReadRafWitness<'_>, + u_evals: &[F], +) -> Result<(Vec>, Vec), Stage5KernelError> { + require_operand_count( + "stage5.instruction_read_raf.group_u_evals", + witness.trace_len, + u_evals.len(), + )?; + + let mut index_by_key: std::collections::HashMap<(u128, Option, bool), usize> = + std::collections::HashMap::with_capacity(witness.trace_len); + let mut groups = Vec::>::new(); + let mut group_indices_by_cycle = Vec::with_capacity(witness.trace_len); + for (cycle, u_eval) in u_evals.iter().copied().enumerate().take(witness.trace_len) { + let key = ( + witness.lookup_indices[cycle], + witness.lookup_table_indices[cycle], + witness.is_interleaved_operands[cycle], + ); + if let Some(&group_index) = index_by_key.get(&key) { + groups[group_index].u_eval_sum += u_eval; + groups[group_index].phase_u_eval_sum += u_eval; + group_indices_by_cycle.push(group_index); + } else { + let group_index = groups.len(); + let _ = index_by_key.insert(key, group_index); + groups.push(InstructionReadRafLookupGroup { + lookup_index: key.0, + lookup_table_index: key.1, + is_interleaved_operands: key.2, + u_eval_sum: u_eval, + phase_u_eval_sum: u_eval, + }); + group_indices_by_cycle.push(group_index); + } + } + Ok((groups, group_indices_by_cycle)) +} + +fn instruction_read_raf_output_plans( + program: &'static Stage5CpuProgramPlan, + claim: &Stage5SumcheckClaimPlan, + table_count: usize, + ra_chunks: usize, +) -> Result, Stage5KernelError> { + let instance = program + .instance_results + .iter() + .find(|instance| { + instance.claim == claim.symbol + && instance.relation == Stage5Relation::InstructionReadRaf.symbol() + }) + .ok_or(Stage5KernelError::MissingClaim { + batch: "stage5.instruction_read_raf.outputs", + claim: claim.symbol, + })?; + + let mut outputs = Vec::with_capacity(table_count + ra_chunks + 1); + let mut table_flags = vec![false; table_count]; + let mut instruction_ra = vec![false; ra_chunks]; + let mut has_raf_flag = false; + + for eval in program + .evals + .iter() + .filter(|eval| eval.source == instance.source) + { + if let Some(suffix) = eval + .name + .strip_prefix("stage5.instruction_read_raf.eval.LookupTableFlag_") + { + let index = parse_instruction_read_raf_eval_index( + suffix, + "stage5.instruction_read_raf.eval.LookupTableFlag_", + )?; + if index >= table_count || table_flags[index] { + return Err(Stage5KernelError::InvalidProof { + driver: eval.name, + reason: "invalid instruction read raf table flag eval", + }); + } + table_flags[index] = true; + outputs.push(InstructionReadRafOutputPlan { + index: eval.index, + name: eval.name, + oracle: eval.oracle, + kind: InstructionReadRafOutputKind::LookupTableFlag(index), + }); + continue; + } + + if let Some(suffix) = eval + .name + .strip_prefix("stage5.instruction_read_raf.eval.InstructionRa_") + { + let index = parse_instruction_read_raf_eval_index( + suffix, + "stage5.instruction_read_raf.eval.InstructionRa_", + )?; + if index >= ra_chunks || instruction_ra[index] { + return Err(Stage5KernelError::InvalidProof { + driver: eval.name, + reason: "invalid instruction read raf ra eval", + }); + } + instruction_ra[index] = true; + outputs.push(InstructionReadRafOutputPlan { + index: eval.index, + name: eval.name, + oracle: eval.oracle, + kind: InstructionReadRafOutputKind::InstructionRa(index), + }); + continue; + } + + if eval.name == "stage5.instruction_read_raf.eval.InstructionRafFlag" { + if has_raf_flag { + return Err(Stage5KernelError::InvalidProof { + driver: eval.name, + reason: "duplicate instruction read raf flag eval", + }); + } + has_raf_flag = true; + outputs.push(InstructionReadRafOutputPlan { + index: eval.index, + name: eval.name, + oracle: eval.oracle, + kind: InstructionReadRafOutputKind::InstructionRafFlag, + }); + } + } + + if table_flags.iter().any(|seen| !*seen) { + return Err(Stage5KernelError::MissingValue { + symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_", + }); + } + if instruction_ra.iter().any(|seen| !*seen) { + return Err(Stage5KernelError::MissingValue { + symbol: "stage5.instruction_read_raf.eval.InstructionRa_", + }); + } + if !has_raf_flag { + return Err(Stage5KernelError::MissingValue { + symbol: "stage5.instruction_read_raf.eval.InstructionRafFlag", + }); + } + outputs.sort_by_key(|output| output.index); + Ok(outputs) +} + +fn parse_instruction_read_raf_eval_index( + suffix: &str, + prefix: &'static str, +) -> Result { + suffix + .parse::() + .map_err(|_| Stage5KernelError::InvalidProof { + driver: prefix, + reason: "invalid instruction read raf eval suffix", + }) +} + +fn ram_ra_claim_reduction_state( + claim: &Stage5SumcheckClaimPlan, + inputs: &Stage5ProverInputs<'_, F>, + store: &Stage5ValueStore, + active_scale: F, +) -> Result, Stage5KernelError> { + let witness = inputs.ram_ra.ok_or(Stage5KernelError::MissingKernelInput { + kernel: "jolt_stage5_batched", + input: "ram_ra", + })?; + let trace_rounds = log2_exact(witness.trace_len, "stage5.ram.trace_len")?; + let ram_rounds = log2_exact(witness.ram_k, "stage5.ram_k")?; + require_operand_count( + "stage5.ram_ra_claim_reduction.input", + trace_rounds, + claim.num_rounds, + )?; + + let ram_raf_point = store.point("stage5.input.stage2.ram_raf.RamRa")?; + let ram_rw_point = store.point("stage5.input.stage2.ram_read_write.RamRa")?; + let ram_val_point = store.point("stage5.input.stage4.ram_val_check.RamRa")?; + for (input, point) in [ + ("stage5.input.stage2.ram_raf.RamRa", ram_raf_point), + ("stage5.input.stage2.ram_read_write.RamRa", ram_rw_point), + ("stage5.input.stage4.ram_val_check.RamRa", ram_val_point), + ] { + require_operand_count(input, ram_rounds + trace_rounds, point.len())?; + } + let (address_point, r_cycle_raf) = ram_raf_point.split_at(ram_rounds); + let (_, r_cycle_rw) = ram_rw_point.split_at(ram_rounds); + let (_, r_cycle_val) = ram_val_point.split_at(ram_rounds); + let address_eq = EqPolynomial::::evals(address_point, None); + let ram_ra = ram_ra_at_address(witness, &address_eq)?; + let gamma = store.scalar("stage5.ram_ra_claim_reduction.gamma")?; + let gamma2 = store + .try_scalar("stage5.ram_ra_claim_reduction.gamma2") + .unwrap_or_else(|| gamma * gamma); + let mut eq_combined = EqPolynomial::::evals(r_cycle_raf, None); + let eq_rw = EqPolynomial::::evals(r_cycle_rw, None); + let eq_val = EqPolynomial::::evals(r_cycle_val, None); + require_operand_count( + "stage5.ram_ra_claim_reduction.eq", + witness.trace_len, + eq_combined.len(), + )?; + for ((combined, rw), val) in eq_combined.iter_mut().zip(eq_rw).zip(eq_val) { + *combined += gamma * rw + gamma2 * val; + } + + Ok(DenseStage5State::new( + vec![eq_combined, ram_ra], + vec![DenseTerm { + coefficient: F::one(), + factors: vec![0, 1], + }], + vec![FactorOutput { + name: "stage5.ram_ra_claim_reduction.eval.RamRa", + oracle: "RamRa", + factor: 1, + }], + active_scale, + )) +} + +fn ram_ra_at_address( + witness: Stage5RamRaWitness<'_, F>, + address_eq: &[F], +) -> Result, Stage5KernelError> { + let expected_len = witness.ram_k.checked_mul(witness.trace_len).ok_or( + Stage5KernelError::InvalidInputLength { + input: "stage5.ram_ra_claim_reduction.RamRa", + expected: usize::MAX, + actual: witness.ram_k, + }, + )?; + if !witness.ram_ra.is_empty() { + require_operand_count( + "stage5.ram_ra_claim_reduction.RamRa", + expected_len, + witness.ram_ra.len(), + )?; + let mut output = vec![F::zero(); witness.trace_len]; + for (address, &weight) in address_eq.iter().enumerate() { + let base = address * witness.trace_len; + for (cycle, output) in output.iter_mut().enumerate() { + *output += weight * witness.ram_ra[base + cycle]; + } + } + return Ok(output); + } + + let Some(remapped_addresses) = witness.remapped_addresses else { + return Err(Stage5KernelError::MissingKernelInput { + kernel: "jolt_stage5_batched", + input: "ram_ra.remapped_addresses", + }); + }; + require_operand_count( + "stage5.ram_ra_claim_reduction.remapped_addresses", + witness.trace_len, + remapped_addresses.len(), + )?; + remapped_addresses + .iter() + .map(|address| match address { + Some(address) => { + address_eq + .get(*address) + .copied() + .ok_or(Stage5KernelError::InvalidInputLength { + input: "stage5.ram_ra_claim_reduction.remapped_addresses", + expected: address_eq.len(), + actual: address + 1, + }) + } + None => Ok(F::zero()), + }) + .collect() +} + +fn registers_val_evaluation_state( + claim: &Stage5SumcheckClaimPlan, + inputs: &Stage5ProverInputs<'_, F>, + store: &Stage5ValueStore, + active_scale: F, +) -> Result, Stage5KernelError> { + let witness = inputs + .registers_val + .ok_or(Stage5KernelError::MissingKernelInput { + kernel: "jolt_stage5_batched", + input: "registers_val", + })?; + require_operand_count( + "stage5.registers_val_evaluation.RdInc", + witness.trace_len, + witness.rd_inc.len(), + )?; + require_operand_count( + "stage5.registers_val_evaluation.input", + log2_exact(witness.trace_len, "stage5.trace_len")?, + claim.num_rounds, + )?; + + let registers_val_point = store.point("stage5.input.stage4.registers.RegistersVal")?; + let register_rounds = log2_exact(witness.register_count, "stage5.register_count")?; + let trace_rounds = log2_exact(witness.trace_len, "stage5.trace_len")?; + require_operand_count( + "stage5.input.stage4.registers.RegistersVal", + register_rounds + trace_rounds, + registers_val_point.len(), + )?; + let (address_point, cycle_point) = registers_val_point.split_at(register_rounds); + let address_eq = EqPolynomial::::evals(address_point, None); + let rd_wa_at_address = rd_wa_at_register_address(witness, &address_eq)?; + let lt = lt_evals_big_endian(cycle_point); + require_operand_count( + "stage5.registers_val_evaluation.lt", + witness.trace_len, + lt.len(), + )?; + + Ok(DenseStage5State::new( + vec![witness.rd_inc.to_vec(), rd_wa_at_address, lt], + vec![DenseTerm { + coefficient: F::one(), + factors: vec![0, 1, 2], + }], + vec![ + FactorOutput { + name: "stage5.registers_val_evaluation.eval.RdInc", + oracle: "RdInc", + factor: 0, + }, + FactorOutput { + name: "stage5.registers_val_evaluation.eval.RdWa", + oracle: "RdWa", + factor: 1, + }, + ], + active_scale, + )) +} + +fn rd_wa_at_register_address( + witness: Stage5RegistersValWitness<'_, F>, + address_eq: &[F], +) -> Result, Stage5KernelError> { + let expected_len = witness + .register_count + .checked_mul(witness.trace_len) + .ok_or(Stage5KernelError::InvalidInputLength { + input: "stage5.registers_val_evaluation.RdWa", + expected: usize::MAX, + actual: witness.register_count, + })?; + if !witness.rd_wa.is_empty() { + require_operand_count( + "stage5.registers_val_evaluation.RdWa", + expected_len, + witness.rd_wa.len(), + )?; + let mut output = vec![F::zero(); witness.trace_len]; + for (address, &weight) in address_eq.iter().enumerate() { + let base = address * witness.trace_len; + for (cycle, output) in output.iter_mut().enumerate() { + *output += weight * witness.rd_wa[base + cycle]; + } + } + return Ok(output); + } + + let Some(rd_write_addresses) = witness.rd_write_addresses else { + return Err(Stage5KernelError::MissingKernelInput { + kernel: "jolt_stage5_batched", + input: "registers_val.rd_wa", + }); + }; + require_operand_count( + "stage5.registers_val_evaluation.rd_write_addresses", + witness.trace_len, + rd_write_addresses.len(), + )?; + rd_write_addresses + .iter() + .map(|address| match address { + Some(address) => { + address_eq + .get(*address) + .copied() + .ok_or(Stage5KernelError::InvalidInputLength { + input: "stage5.registers_val_evaluation.rd_write_addresses", + expected: address_eq.len(), + actual: address + 1, + }) + } + None => Ok(F::zero()), + }) + .collect() +} + +fn expected_batched_output_claim( + context: Stage5KernelContext<'_>, + store: &Stage5ValueStore, + evals: &[Stage5NamedEval], + point: &[F], + batching_coeffs: &[F], +) -> Result { + let mut expected = F::zero(); + for (claim, &coefficient) in context.batch_claims()?.iter().zip(batching_coeffs) { + let instance = context + .program + .instance_results + .iter() + .find(|instance| { + instance.claim == claim.symbol && instance.source == context.driver.symbol + }) + .ok_or(Stage5KernelError::MissingClaim { + batch: context.batch.symbol, + claim: claim.symbol, + })?; + let local_point = point + .get(instance.round_offset..instance.round_offset + instance.num_rounds) + .ok_or(Stage5KernelError::InvalidInputLength { + input: instance.symbol, + expected: instance.round_offset + instance.num_rounds, + actual: point.len(), + })?; + let relation = claim.relation.unwrap_or(instance.relation); + let value = match Stage5Relation::from_symbol(relation) + .ok_or(Stage5KernelError::UnknownRelation { relation })? + { + Stage5Relation::InstructionReadRaf => { + expected_instruction_read_raf(store, evals, local_point)? + } + Stage5Relation::RamRaClaimReduction => { + expected_ram_ra_claim_reduction(store, evals, local_point)? + } + Stage5Relation::RegistersValEvaluation => { + expected_registers_val_evaluation(store, evals, local_point)? + } + relation @ Stage5Relation::Batched => { + return Err(Stage5KernelError::KernelNotImplemented { + abi: relation.symbol(), + }) + } + }; + expected += coefficient * value; + } + Ok(expected) +} + +fn expected_instruction_read_raf( + store: &Stage5ValueStore, + evals: &[Stage5NamedEval], + local_point: &[F], +) -> Result { + const LOG_K: usize = 128; + const XLEN: usize = 64; + + if local_point.len() < LOG_K { + return Err(Stage5KernelError::InvalidInputLength { + input: "stage5.instruction_read_raf.point", + expected: LOG_K, + actual: local_point.len(), + }); + } + + let (r_address_prime, r_cycle) = local_point.split_at(LOG_K); + let r_cycle_prime = reverse_slice(r_cycle); + let r_reduction = store.point("stage5.input.stage2.instruction.LookupOutput")?; + let eq_eval_r_reduction = EqPolynomial::::mle(r_reduction, &r_cycle_prime); + + let left_operand_eval = operand_polynomial_eval(r_address_prime, true); + let right_operand_eval = operand_polynomial_eval(r_address_prime, false); + let identity_poly_eval = identity_polynomial_eval(r_address_prime); + + let table_values = LookupTableKind::::all() + .iter() + .map(|table| table.evaluate_mle::(r_address_prime)) + .collect::>(); + let table_flag_claims = indexed_evals_by_prefix( + evals, + "stage5.instruction_read_raf.eval.LookupTableFlag_", + table_values.len(), + )?; + let val_claim = table_values + .into_iter() + .zip(table_flag_claims) + .map(|(table_value, flag_claim)| table_value * flag_claim) + .sum::(); + + let ra_claim = + indexed_evals_by_prefix_any(evals, "stage5.instruction_read_raf.eval.InstructionRa_")? + .into_iter() + .product::(); + let raf_flag_claim = + eval_by_name(evals, "stage5.instruction_read_raf.eval.InstructionRafFlag")?; + let gamma = store.scalar("stage5.instruction_read_raf.gamma")?; + + let raf_claim = (F::one() - raf_flag_claim) * (left_operand_eval + gamma * right_operand_eval) + + raf_flag_claim * gamma * identity_poly_eval; + Ok(eq_eval_r_reduction * ra_claim * (val_claim + gamma * raf_claim)) +} + +pub fn instruction_read_raf_output_evals( + witness: Stage5InstructionReadRafWitness<'_>, + address_point: &[F], + cycle_point: &[F], +) -> Result, Stage5KernelError> { + const LOG_K: usize = 128; + const XLEN: usize = 64; + + require_operand_count( + "stage5.instruction_read_raf.address_point", + LOG_K, + address_point.len(), + )?; + let trace_len_from_point = 1usize.checked_shl(cycle_point.len() as u32).ok_or( + Stage5KernelError::InvalidInputLength { + input: "stage5.instruction_read_raf.cycle_point", + expected: usize::BITS as usize, + actual: cycle_point.len(), + }, + )?; + require_operand_count( + "stage5.instruction_read_raf.trace_len", + trace_len_from_point, + witness.trace_len, + )?; + require_operand_count( + "stage5.instruction_read_raf.lookup_indices", + witness.trace_len, + witness.lookup_indices.len(), + )?; + require_operand_count( + "stage5.instruction_read_raf.lookup_table_indices", + witness.trace_len, + witness.lookup_table_indices.len(), + )?; + require_operand_count( + "stage5.instruction_read_raf.is_interleaved_operands", + witness.trace_len, + witness.is_interleaved_operands.len(), + )?; + if witness.ra_virtual_log_k_chunk == 0 || !LOG_K.is_multiple_of(witness.ra_virtual_log_k_chunk) + { + return Err(Stage5KernelError::InvalidInputLength { + input: "stage5.instruction_read_raf.ra_virtual_log_k_chunk", + expected: LOG_K, + actual: witness.ra_virtual_log_k_chunk, + }); + } + + let table_count = LookupTableKind::::all().len(); + let ra_chunks = LOG_K / witness.ra_virtual_log_k_chunk; + let cycle_eq = EqPolynomial::::evals(cycle_point, None); + require_operand_count( + "stage5.instruction_read_raf.eq_cycle", + witness.trace_len, + cycle_eq.len(), + )?; + + let mut grouped_weights = + HashMap::<(u128, Option, bool), F>::with_capacity(witness.trace_len.min(1 << 14)); + for (((&lookup_index, table_index), is_interleaved), &weight) in witness + .lookup_indices + .iter() + .zip(witness.lookup_table_indices.iter()) + .zip(witness.is_interleaved_operands.iter()) + .zip(&cycle_eq) + { + *grouped_weights + .entry((lookup_index, *table_index, *is_interleaved)) + .or_insert_with(F::zero) += weight; + } + + let mut lookup_table_flags = vec![F::zero(); table_count]; + let mut instruction_raf_flag = F::zero(); + for ((_, table_index, is_interleaved), &weight) in &grouped_weights { + if let Some(table_index) = table_index { + let Some(flag) = lookup_table_flags.get_mut(*table_index) else { + return Err(Stage5KernelError::InvalidInputLength { + input: "stage5.instruction_read_raf.lookup_table_indices", + expected: table_count, + actual: *table_index + 1, + }); + }; + *flag += weight; + } + if !*is_interleaved { + instruction_raf_flag += weight; + } + } + + let chunk_bits = witness.ra_virtual_log_k_chunk; + let chunk_mask = if chunk_bits == 128 { + u128::MAX + } else { + (1u128 << chunk_bits) - 1 + }; + let instruction_ra = (0..ra_chunks) + .map(|chunk| { + let chunk_point = &address_point[chunk * chunk_bits..(chunk + 1) * chunk_bits]; + let eq_tables = eq_eval_bit_chunk_tables(chunk_point, 8); + let shift = LOG_K - (chunk + 1) * chunk_bits; + grouped_weights + .iter() + .map(|((lookup_index, _, _), &cycle_weight)| { + let chunk_value = (*lookup_index >> shift) & chunk_mask; + cycle_weight + * eq_eval_at_bits_from_chunk_tables(&eq_tables, chunk_value, chunk_bits, 8) + }) + .sum() + }) + .collect(); + + Ok(Stage5InstructionReadRafEvaluations { + lookup_table_flags, + instruction_ra, + instruction_raf_flag, + }) +} + +fn expected_ram_ra_claim_reduction( + store: &Stage5ValueStore, + evals: &[Stage5NamedEval], + local_point: &[F], +) -> Result { + let r_cycle_reduced = reverse_slice(local_point); + let r_cycle_raf = suffix_point( + store.point("stage5.input.stage2.ram_raf.RamRa")?, + r_cycle_reduced.len(), + "stage5.input.stage2.ram_raf.RamRa", + )?; + let r_cycle_rw = suffix_point( + store.point("stage5.input.stage2.ram_read_write.RamRa")?, + r_cycle_reduced.len(), + "stage5.input.stage2.ram_read_write.RamRa", + )?; + let r_cycle_val = suffix_point( + store.point("stage5.input.stage4.ram_val_check.RamRa")?, + r_cycle_reduced.len(), + "stage5.input.stage4.ram_val_check.RamRa", + )?; + let gamma = store.scalar("stage5.ram_ra_claim_reduction.gamma")?; + let eq_combined = EqPolynomial::::mle(r_cycle_raf, &r_cycle_reduced) + + gamma * EqPolynomial::::mle(r_cycle_rw, &r_cycle_reduced) + + gamma.square() * EqPolynomial::::mle(r_cycle_val, &r_cycle_reduced); + let ram_ra = eval_by_name(evals, "stage5.ram_ra_claim_reduction.eval.RamRa")?; + Ok(eq_combined * ram_ra) +} + +fn expected_registers_val_evaluation( + store: &Stage5ValueStore, + evals: &[Stage5NamedEval], + local_point: &[F], +) -> Result { + let registers_val_point = store.point("stage5.input.stage4.registers.RegistersVal")?; + let r_cycle = suffix_point( + registers_val_point, + local_point.len(), + "stage5.input.stage4.registers.RegistersVal", + )?; + let r_reduced = reverse_slice(local_point); + let lt_eval = lt_polynomial_eval(&r_reduced, r_cycle); + let rd_inc = eval_by_name(evals, "stage5.registers_val_evaluation.eval.RdInc")?; + let rd_wa = eval_by_name(evals, "stage5.registers_val_evaluation.eval.RdWa")?; + Ok(rd_inc * rd_wa * lt_eval) +} + +fn eval_by_name( + evals: &[Stage5NamedEval], + name: &'static str, +) -> Result { + evals + .iter() + .find(|eval| eval.name == name) + .map(|eval| eval.value) + .ok_or(Stage5KernelError::MissingValue { symbol: name }) +} + +fn named_eval(name: &'static str, oracle: &'static str, value: F) -> Stage5NamedEval { + Stage5NamedEval { + name, + oracle, + value, + } +} + +fn claim_relation( + program: &'static Stage5CpuProgramPlan, + claim: &Stage5SumcheckClaimPlan, +) -> Result { + if let Some(relation) = claim.relation { + return Stage5Relation::from_symbol(relation) + .ok_or(Stage5KernelError::UnknownRelation { relation }); + } + let kernel_symbol = claim.kernel.ok_or(Stage5KernelError::MissingKernel { + driver: claim.symbol, + kernel: "", + })?; + let kernel = find_kernel(program, kernel_symbol).ok_or(Stage5KernelError::MissingKernel { + driver: claim.symbol, + kernel: kernel_symbol, + })?; + Stage5Relation::from_symbol(kernel.relation).ok_or(Stage5KernelError::UnknownRelation { + relation: kernel.relation, + }) +} + +fn instance_round_offset( + program: &'static Stage5CpuProgramPlan, + driver: &'static str, + claim: &'static str, +) -> Result { + program + .instance_results + .iter() + .find(|instance| instance.source == driver && instance.claim == claim) + .map(|instance| instance.round_offset) + .ok_or(Stage5KernelError::MissingClaim { + batch: driver, + claim, + }) +} + +fn combine_univariate_polys( + polynomials: &[UnivariatePoly], + coefficients: &[F], +) -> UnivariatePoly { + let max_len = polynomials + .iter() + .map(|poly| poly.coefficients().len()) + .max() + .unwrap_or(0); + let mut combined = vec![F::zero(); max_len]; + for (poly, &coefficient) in polynomials.iter().zip(coefficients) { + for (combined, &term) in combined.iter_mut().zip(poly.coefficients()) { + *combined += term * coefficient; + } + } + UnivariatePoly::new(combined) +} + +fn round_poly_from_dense_terms( + factors: &[Vec], + terms: &[DenseTerm], + active_scale: F, + relation: Stage5Relation, +) -> Result, Stage5KernelError> { + let half = factors.first().map_or(0, |factor| factor.len() / 2); + for term in terms { + if term.factors.len() > 3 { + return Err(Stage5KernelError::InvalidProof { + driver: relation.symbol(), + reason: "stage5 dense term exceeds degree bound", + }); + } + if term.factors.iter().any(|factor| *factor >= factors.len()) { + return Err(Stage5KernelError::InvalidProof { + driver: relation.symbol(), + reason: "stage5 dense term references missing factor", + }); + } + } + + let accumulators = if half >= DENSE_BIND_PAR_THRESHOLD { + (0..half) + .into_par_iter() + .map(|row| dense_row_coefficients(factors, terms, row)) + .reduce( + || [F::Accumulator::default(); 4], + |mut left, right| { + for index in 0..left.len() { + left[index].merge(right[index]); + } + left + }, + ) + } else { + (0..half).fold([F::Accumulator::default(); 4], |mut total, row| { + let row_coefficients = dense_row_coefficients(factors, terms, row); + for index in 0..total.len() { + total[index].merge(row_coefficients[index]); + } + total + }) + }; + + Ok(UnivariatePoly::new( + accumulators + .into_iter() + .map(FieldAccumulator::reduce) + .map(|coefficient| coefficient * active_scale) + .collect(), + )) +} + +fn dense_row_coefficients( + factors: &[Vec], + terms: &[DenseTerm], + row: usize, +) -> [F::Accumulator; 4] { + let mut coefficients = [F::Accumulator::default(); 4]; + for term in terms { + match term.factors.as_slice() { + [] => coefficients[0].acc_add(term.coefficient), + [first] => { + let (first0, first_delta) = linear_factor_pair(&factors[*first], row); + coefficients[0].fmadd(term.coefficient, first0); + coefficients[1].fmadd(term.coefficient, first_delta); + } + [first, second] => { + let (first0, first_delta) = linear_factor_pair(&factors[*first], row); + let (second0, second_delta) = linear_factor_pair(&factors[*second], row); + accumulate_quadratic_coefficients( + &mut coefficients, + term.coefficient, + first0, + first_delta, + second0, + second_delta, + ); + } + [first, second, third] => { + let (first0, first_delta) = linear_factor_pair(&factors[*first], row); + let (second0, second_delta) = linear_factor_pair(&factors[*second], row); + let (third0, third_delta) = linear_factor_pair(&factors[*third], row); + accumulate_cubic_coefficients( + &mut coefficients, + term.coefficient, + first0, + first_delta, + second0, + second_delta, + third0, + third_delta, + ); + } + _ => unreachable!("dense terms are validated before evaluation"), + } + } + coefficients +} + +#[inline] +fn linear_factor_pair(factor: &[F], row: usize) -> (F, F) { + let low = factor[2 * row]; + (low, factor[2 * row + 1] - low) +} + +#[inline] +fn accumulate_quadratic_coefficients( + coefficients: &mut [F::Accumulator; 4], + scale: F, + first0: F, + first_delta: F, + second0: F, + second_delta: F, +) { + coefficients[0].fmadd(scale * first0, second0); + coefficients[1].fmadd(scale * first_delta, second0); + coefficients[1].fmadd(scale * first0, second_delta); + coefficients[2].fmadd(scale * first_delta, second_delta); +} + +#[inline] +fn accumulate_cubic_coefficients( + coefficients: &mut [F::Accumulator; 4], + scale: F, + first0: F, + first_delta: F, + second0: F, + second_delta: F, + third0: F, + third_delta: F, +) { + let second0_third0 = second0 * third0; + let second_delta_third0 = second_delta * third0; + let second0_third_delta = second0 * third_delta; + let second_delta_third_delta = second_delta * third_delta; + let scaled_first0 = scale * first0; + let scaled_first_delta = scale * first_delta; + + coefficients[0].fmadd(scaled_first0, second0_third0); + coefficients[1].fmadd(scaled_first_delta, second0_third0); + coefficients[1].fmadd(scaled_first0, second_delta_third0); + coefficients[1].fmadd(scaled_first0, second0_third_delta); + coefficients[2].fmadd(scaled_first_delta, second_delta_third0); + coefficients[2].fmadd(scaled_first_delta, second0_third_delta); + coefficients[2].fmadd(scaled_first0, second_delta_third_delta); + coefficients[3].fmadd(scaled_first_delta, second_delta_third_delta); +} + +fn indexed_evals_by_prefix( + evals: &[Stage5NamedEval], + prefix: &'static str, + count: usize, +) -> Result, Stage5KernelError> { + let mut values = vec![None; count]; + for eval in evals { + let Some(suffix) = eval.name.strip_prefix(prefix) else { + continue; + }; + let index = suffix + .parse::() + .map_err(|_| Stage5KernelError::InvalidProof { + driver: prefix, + reason: "invalid indexed eval suffix", + })?; + if index >= count || values[index].is_some() { + return Err(Stage5KernelError::InvalidProof { + driver: prefix, + reason: "invalid indexed eval", + }); + } + values[index] = Some(eval.value); + } + values + .into_iter() + .map(|value| value.ok_or(Stage5KernelError::MissingValue { symbol: prefix })) + .collect() +} + +fn indexed_evals_by_prefix_any( + evals: &[Stage5NamedEval], + prefix: &'static str, +) -> Result, Stage5KernelError> { + let mut indexed_values = Vec::new(); + for eval in evals { + let Some(suffix) = eval.name.strip_prefix(prefix) else { + continue; + }; + let index = suffix + .parse::() + .map_err(|_| Stage5KernelError::InvalidProof { + driver: prefix, + reason: "invalid indexed eval suffix", + })?; + if indexed_values + .iter() + .any(|(existing_index, _)| *existing_index == index) + { + return Err(Stage5KernelError::InvalidProof { + driver: prefix, + reason: "duplicate indexed eval", + }); + } + indexed_values.push((index, eval.value)); + } + if indexed_values.is_empty() { + return Err(Stage5KernelError::MissingValue { symbol: prefix }); + } + indexed_values.sort_by_key(|(index, _)| *index); + for (expected, (actual, _)) in indexed_values.iter().enumerate() { + if *actual != expected { + return Err(Stage5KernelError::InvalidProof { + driver: prefix, + reason: "non-contiguous indexed eval", + }); + } + } + Ok(indexed_values.into_iter().map(|(_, value)| value).collect()) +} + +fn append_compressed_univariate_poly( + transcript: &mut T, + label: &'static str, + poly: &UnivariatePoly, +) where + F: Field, + T: Transcript, +{ + let compressed = poly.compress(); + transcript.append(&LabelWithCount( + label.as_bytes(), + compressed.coeffs_except_linear_term().len() as u64, + )); + for coefficient in compressed.coeffs_except_linear_term() { + transcript.append(coefficient); + } +} + +fn append_labeled_scalar(transcript: &mut T, label: &'static str, scalar: &F) +where + F: Field, + T: Transcript, +{ + transcript.append(&Label(label.as_bytes())); + transcript.append(scalar); +} + +fn append_opening_claims( + program: &'static Stage5CpuProgramPlan, + store: &mut Stage5ValueStore, + transcript: &mut T, + evals: &[Stage5NamedEval], +) -> Result>, Stage5KernelError> +where + F: Field, + T: Transcript, +{ + if program.opening_batches.is_empty() { + for eval in evals { + append_labeled_scalar(transcript, "opening_claim", &eval.value); + } + return Ok(Vec::new()); + } + let _ = store.evaluate_available_points(program)?; + let mut opening_claims = Vec::new(); + let mut seen = program + .opening_inputs + .iter() + .filter_map(|input| { + store + .try_point(input.symbol) + .map(|point| (input.claim_kind, input.oracle, point.to_vec())) + }) + .collect::>(); + for batch in program.opening_batches { + for symbol in batch.claim_operands { + let claim = + find_opening_claim(program, symbol).ok_or(Stage5KernelError::MissingClaim { + batch: batch.symbol, + claim: symbol, + })?; + let point = store.point(claim.point_source)?.to_vec(); + let duplicate = seen.iter().any(|(kind, oracle, seen_point)| { + *kind == claim.claim_kind && *oracle == claim.oracle && seen_point == &point + }); + let value = store.scalar(claim.eval_source)?; + if !duplicate { + append_labeled_scalar(transcript, "opening_claim", &value); + seen.push((claim.claim_kind, claim.oracle, point.clone())); + } + opening_claims.push(Stage5OpeningClaimValue { + symbol: claim.symbol, + oracle: claim.oracle, + domain: claim.domain, + claim_kind: claim.claim_kind, + point: point.clone(), + eval: value, + }); + } + } + Ok(opening_claims) +} + +fn find_opening_claim<'a>( + program: &'a Stage5CpuProgramPlan, + symbol: &str, +) -> Option<&'a Stage5OpeningClaimPlan> { + program + .opening_claims + .iter() + .find(|claim| claim.symbol == symbol) +} + +fn polynomial_degree(poly: &UnivariatePoly) -> usize { + poly.coefficients() + .iter() + .rposition(|coefficient| *coefficient != F::zero()) + .unwrap_or(0) +} + +fn pow_field(base: F, mut exponent: usize) -> F { + let mut result = F::one(); + let mut power = base; + while exponent != 0 { + if exponent & 1 == 1 { + result *= power; + } + power = power.square(); + exponent >>= 1; + } + result +} + +fn single_operand(symbol: &'static str, operands: &[F]) -> Result { + require_operand_count(symbol, 1, operands.len())?; + Ok(operands[0]) +} + +fn require_operand_count( + input: &'static str, + expected: usize, + actual: usize, +) -> Result<(), Stage5KernelError> { + if expected == actual { + Ok(()) + } else { + Err(Stage5KernelError::InvalidInputLength { + input, + expected, + actual, + }) + } +} + +fn suffix_point<'a, F: Field>( + point: &'a [F], + length: usize, + input: &'static str, +) -> Result<&'a [F], Stage5KernelError> { + point + .get(point.len().saturating_sub(length)..) + .filter(|suffix| suffix.len() == length) + .ok_or(Stage5KernelError::InvalidInputLength { + input, + expected: length, + actual: point.len(), + }) +} + +fn reverse_slice(values: &[F]) -> Vec { + values.iter().rev().copied().collect() +} + +fn normalize_instruction_read_raf_point( + point: &[F], +) -> Result, Stage5KernelError> { + const LOG_K: usize = 128; + if point.len() < LOG_K { + return Err(Stage5KernelError::InvalidInputLength { + input: "stage5.instruction_read_raf.point", + expected: LOG_K, + actual: point.len(), + }); + } + let mut normalized = point.to_vec(); + normalized[LOG_K..].reverse(); + Ok(normalized) +} + +fn lt_polynomial_eval(x: &[F], y: &[F]) -> F { + debug_assert_eq!(x.len(), y.len()); + let mut lt_eval = F::zero(); + let mut eq_term = F::one(); + for (x_i, y_i) in x.iter().zip(y.iter()) { + lt_eval += (F::one() - *x_i) * *y_i * eq_term; + eq_term *= F::one() - *x_i - *y_i + *x_i * *y_i + *x_i * *y_i; + } + lt_eval +} + +fn lt_evals_big_endian(point: &[F]) -> Vec { + let mut evals = vec![F::zero(); 1usize << point.len()]; + for (index, r) in point.iter().rev().enumerate() { + let (left, right) = evals.split_at_mut(1usize << index); + left.iter_mut().zip(right).for_each(|(left, right)| { + *right = *left * *r; + *left += *r - *right; + }); + } + evals +} + +fn operand_polynomial_eval(point: &[F], left: bool) -> F { + let stride_offset = usize::from(!left); + let operand_bits = point.len() / 2; + (0..operand_bits) + .map(|index| point[2 * index + stride_offset].mul_pow_2(operand_bits - 1 - index)) + .sum() +} + +fn eq_eval_at_bits(point: &[F], bits: u128, num_bits: usize) -> F { + debug_assert_eq!(point.len(), num_bits); + point + .iter() + .enumerate() + .map(|(index, &challenge)| { + if ((bits >> (num_bits - 1 - index)) & 1) == 1 { + challenge + } else { + F::one() - challenge + } + }) + .product() +} + +fn eq_eval_bit_chunk_tables(point: &[F], chunk_bits: usize) -> Vec> { + point + .chunks(chunk_bits) + .map(|chunk| { + let len = chunk.len(); + (0..(1usize << len)) + .map(|bits| eq_eval_at_bits(chunk, bits as u128, len)) + .collect() + }) + .collect() +} + +fn eq_eval_at_bits_from_chunk_tables( + tables: &[Vec], + bits: u128, + num_bits: usize, + chunk_bits: usize, +) -> F { + tables + .iter() + .enumerate() + .map(|(chunk_index, table)| { + let start = chunk_index * chunk_bits; + let len = table.len().ilog2() as usize; + let shift = num_bits - start - len; + let mask = (1u128 << len) - 1; + table[((bits >> shift) & mask) as usize] + }) + .product() +} + +#[cfg(test)] +#[inline] +fn lookup_bit(lookup_index: u128, index: usize, total_bits: usize) -> bool { + ((lookup_index >> (total_bits - 1 - index)) & 1) == 1 +} + +fn identity_polynomial_eval(point: &[F]) -> F { + point + .iter() + .enumerate() + .map(|(index, value)| value.mul_pow_2(point.len() - 1 - index)) + .sum() +} + +fn log2_exact(value: usize, input: &'static str) -> Result { + if value.is_power_of_two() { + Ok(value.ilog2() as usize) + } else { + Err(Stage5KernelError::InvalidInputLength { + input, + expected: value.next_power_of_two(), + actual: value, + }) + } +} + +pub fn execute_stage5_program( + program: &'static Stage5CpuProgramPlan, + mode: Stage5ExecutionMode, + executor: &mut E, + transcript: &mut T, +) -> Result, Stage5KernelError> +where + F: Field, + T: Transcript, + E: Stage5KernelExecutor, +{ + let mut artifacts = Stage5ExecutionArtifacts::default(); + for step in program.steps { + match step.kind { + "transcript_squeeze" => { + let squeeze = + find_squeeze(program, step.symbol).ok_or(Stage5KernelError::MissingValue { + symbol: step.symbol, + })?; + let values = transcript.challenge_vector(squeeze.count); + executor.observe_challenge_vector(squeeze, &values)?; + artifacts.challenge_vectors.push(Stage5ChallengeVector { + symbol: squeeze.symbol, + values, + }); + } + "transcript_absorb_bytes" => { + let absorb = find_absorb_bytes(program, step.symbol).ok_or( + Stage5KernelError::MissingValue { + symbol: step.symbol, + }, + )?; + absorb_stage5_bytes(absorb, transcript); + } + "sumcheck_driver" => { + let driver = + find_driver(program, step.symbol).ok_or(Stage5KernelError::MissingDriver { + driver: step.symbol, + })?; + let kernel_symbol = driver.kernel.ok_or(Stage5KernelError::MissingKernel { + driver: driver.symbol, + kernel: "", + })?; + let kernel = find_kernel(program, kernel_symbol).ok_or( + Stage5KernelError::MissingKernel { + driver: driver.symbol, + kernel: kernel_symbol, + }, + )?; + let batch = + find_batch(program, driver.batch).ok_or(Stage5KernelError::MissingBatch { + driver: driver.symbol, + batch: driver.batch, + })?; + let context = Stage5KernelContext { + mode, + program, + kernel, + batch, + driver, + }; + let output = match mode { + Stage5ExecutionMode::Prover => executor.prove_sumcheck(context, transcript)?, + Stage5ExecutionMode::Verifier => { + executor.verify_sumcheck(context, transcript)? + } + }; + executor.observe_sumcheck_output(&output)?; + artifacts + .opening_claims + .extend(output.opening_claims.clone()); + artifacts.sumchecks.push(output); + } + _ => { + return Err(Stage5KernelError::InvalidProgramStep { + symbol: step.symbol, + kind: step.kind, + }); + } + } + } + artifacts + .opening_batches + .extend(program.opening_batches.iter()); + Ok(artifacts) +} + +fn absorb_stage5_bytes(absorb: &'static Stage5TranscriptAbsorbBytesPlan, transcript: &mut T) +where + T: Transcript, +{ + transcript.append(&LabelWithCount( + absorb.label.as_bytes(), + absorb.payload.len() as u64, + )); + transcript.append_bytes(absorb.payload.as_bytes()); +} + +fn find_squeeze<'a>( + program: &'a Stage5CpuProgramPlan, + symbol: &str, +) -> Option<&'a Stage5TranscriptSqueezePlan> { + program + .transcript_squeezes + .iter() + .find(|plan| plan.symbol == symbol) +} + +fn find_absorb_bytes<'a>( + program: &'a Stage5CpuProgramPlan, + symbol: &str, +) -> Option<&'a Stage5TranscriptAbsorbBytesPlan> { + program + .transcript_absorb_bytes + .iter() + .find(|plan| plan.symbol == symbol) +} + +fn find_driver<'a>( + program: &'a Stage5CpuProgramPlan, + symbol: &str, +) -> Option<&'a Stage5SumcheckDriverPlan> { + program + .drivers + .iter() + .find(|driver| driver.symbol == symbol) +} + +fn find_kernel<'a>( + program: &'a Stage5CpuProgramPlan, + symbol: &str, +) -> Option<&'a Stage5KernelPlan> { + program + .kernels + .iter() + .find(|kernel| kernel.symbol == symbol) +} + +fn find_batch<'a>( + program: &'a Stage5CpuProgramPlan, + symbol: &str, +) -> Option<&'a Stage5SumcheckBatchPlan> { + program.batches.iter().find(|batch| batch.symbol == symbol) +} + +#[cfg(test)] +#[expect( + clippy::expect_used, + reason = "tests use expect to keep failure context concise" +)] +mod tests { + use super::*; + use jolt_field::{Field, Fr}; + use jolt_sumcheck::SumcheckProof; + use jolt_transcript::Blake2bTranscript; + + const PARAMS: Stage5Params = Stage5Params { + field: "bn254_fr", + pcs: "dory", + transcript: "blake2b_transcript", + }; + const STEPS: &[Stage5ProgramStepPlan] = &[ + Stage5ProgramStepPlan { + kind: "transcript_squeeze", + symbol: "stage5.gamma", + }, + Stage5ProgramStepPlan { + kind: "sumcheck_driver", + symbol: "stage5.sumcheck", + }, + ]; + const SQUEEZES: &[Stage5TranscriptSqueezePlan] = &[Stage5TranscriptSqueezePlan { + symbol: "stage5.gamma", + label: "stage5_gamma", + kind: "challenge_scalar", + count: 1, + }]; + const KERNELS: &[Stage5KernelPlan] = &[Stage5KernelPlan { + symbol: "jolt.cpu.stage5.batched", + relation: "jolt.stage5.batched", + kind: "sumcheck", + backend: "cpu", + abi: "jolt_stage5_batched", + }]; + const CLAIM_INPUTS: &[&str] = &[]; + const CLAIMS: &[Stage5SumcheckClaimPlan] = &[Stage5SumcheckClaimPlan { + symbol: "stage5.claim", + stage: "stage5", + domain: "jolt.trace_domain", + num_rounds: 1, + degree: 1, + claim: "stage5.claim", + kernel: Some("jolt.cpu.stage5.batched"), + relation: Some("jolt.stage5.batched"), + claim_value: "stage5.gamma", + input_openings: CLAIM_INPUTS, + }]; + const ORDERED_CLAIMS: &[&str] = &["stage5.claim"]; + const ROUND_SCHEDULE: &[usize] = &[1]; + const BATCHES: &[Stage5SumcheckBatchPlan] = &[Stage5SumcheckBatchPlan { + symbol: "stage5.batch", + stage: "stage5", + proof_slot: "stage5.sumcheck", + policy: "test", + count: 1, + ordered_claims: ORDERED_CLAIMS, + claim_operands: ORDERED_CLAIMS, + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + round_schedule: ROUND_SCHEDULE, + }]; + const DRIVERS: &[Stage5SumcheckDriverPlan] = &[Stage5SumcheckDriverPlan { + symbol: "stage5.sumcheck", + stage: "stage5", + proof_slot: "stage5.sumcheck", + kernel: Some("jolt.cpu.stage5.batched"), + relation: Some("jolt.stage5.batched"), + batch: "stage5.batch", + policy: "test", + round_schedule: ROUND_SCHEDULE, + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + num_rounds: 1, + degree: 1, + }]; + const PROGRAM: Stage5CpuProgramPlan = Stage5CpuProgramPlan { + role: "prover", + params: PARAMS, + steps: STEPS, + transcript_squeezes: SQUEEZES, + transcript_absorb_bytes: &[], + opening_inputs: &[], + field_constants: &[], + field_exprs: &[], + kernels: KERNELS, + claims: CLAIMS, + batches: BATCHES, + drivers: DRIVERS, + instance_results: &[], + evals: &[], + point_slices: &[], + point_concats: &[], + opening_claims: &[], + opening_equalities: &[], + opening_batches: &[], + }; + + const REGISTERS_STEPS: &[Stage5ProgramStepPlan] = &[Stage5ProgramStepPlan { + kind: "sumcheck_driver", + symbol: "stage5.registers.sumcheck", + }]; + const REGISTERS_OPENING_INPUTS: &[Stage5OpeningInputPlan] = &[Stage5OpeningInputPlan { + symbol: "stage5.input.stage4.registers.RegistersVal", + source_stage: "stage4", + source_claim: "stage4.registers_read_write.opening.RegistersVal", + oracle: "RegistersVal", + domain: "jolt.stage4_registers_rw_domain", + point_arity: 3, + claim_kind: "virtual", + }]; + const REGISTERS_KERNELS: &[Stage5KernelPlan] = &[ + Stage5KernelPlan { + symbol: "jolt.cpu.stage5.registers_val_evaluation", + relation: "jolt.stage5.registers_val_evaluation", + kind: "sumcheck", + backend: "cpu", + abi: "jolt_stage5_registers_val_evaluation", + }, + Stage5KernelPlan { + symbol: "jolt.cpu.stage5.batched", + relation: "jolt.stage5.batched", + kind: "sumcheck", + backend: "cpu", + abi: "jolt_stage5_batched", + }, + ]; + const REGISTERS_CLAIM_INPUTS: &[&str] = &["stage5.input.stage4.registers.RegistersVal"]; + const REGISTERS_CLAIMS: &[Stage5SumcheckClaimPlan] = &[Stage5SumcheckClaimPlan { + symbol: "stage5.registers_val_evaluation.input", + stage: "stage5", + domain: "jolt.trace_domain", + num_rounds: 2, + degree: 3, + claim: "stage5.registers_val_evaluation.registers_val", + kernel: Some("jolt.cpu.stage5.registers_val_evaluation"), + relation: Some("jolt.stage5.registers_val_evaluation"), + claim_value: "stage5.input.stage4.registers.RegistersVal", + input_openings: REGISTERS_CLAIM_INPUTS, + }]; + const REGISTERS_ORDERED_CLAIMS: &[&str] = &["stage5.registers_val_evaluation.input"]; + const REGISTERS_ROUND_SCHEDULE: &[usize] = &[2]; + const REGISTERS_BATCHES: &[Stage5SumcheckBatchPlan] = &[Stage5SumcheckBatchPlan { + symbol: "stage5.registers.batch", + stage: "stage5", + proof_slot: "stage5.registers.sumcheck", + policy: "test", + count: 1, + ordered_claims: REGISTERS_ORDERED_CLAIMS, + claim_operands: REGISTERS_ORDERED_CLAIMS, + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + round_schedule: REGISTERS_ROUND_SCHEDULE, + }]; + const REGISTERS_DRIVERS: &[Stage5SumcheckDriverPlan] = &[Stage5SumcheckDriverPlan { + symbol: "stage5.registers.sumcheck", + stage: "stage5", + proof_slot: "stage5.registers.sumcheck", + kernel: Some("jolt.cpu.stage5.batched"), + relation: Some("jolt.stage5.batched"), + batch: "stage5.registers.batch", + policy: "test", + round_schedule: REGISTERS_ROUND_SCHEDULE, + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + num_rounds: 2, + degree: 3, + }]; + const REGISTERS_INSTANCES: &[Stage5SumcheckInstanceResultPlan] = + &[Stage5SumcheckInstanceResultPlan { + symbol: "stage5.registers_val_evaluation.instance", + source: "stage5.registers.sumcheck", + claim: "stage5.registers_val_evaluation.input", + relation: "jolt.stage5.registers_val_evaluation", + index: 0, + point_arity: 2, + num_rounds: 2, + round_offset: 0, + point_order: "reverse", + degree: 3, + }]; + const REGISTERS_EVALS: &[Stage5SumcheckEvalPlan] = &[ + Stage5SumcheckEvalPlan { + symbol: "stage5.registers_val_evaluation.eval.RdInc", + source: "stage5.registers.sumcheck", + name: "stage5.registers_val_evaluation.eval.RdInc", + index: 0, + oracle: "RdInc", + }, + Stage5SumcheckEvalPlan { + symbol: "stage5.registers_val_evaluation.eval.RdWa", + source: "stage5.registers.sumcheck", + name: "stage5.registers_val_evaluation.eval.RdWa", + index: 1, + oracle: "RdWa", + }, + ]; + const REGISTERS_PROGRAM: Stage5CpuProgramPlan = Stage5CpuProgramPlan { + role: "prover", + params: PARAMS, + steps: REGISTERS_STEPS, + transcript_squeezes: &[], + transcript_absorb_bytes: &[], + opening_inputs: REGISTERS_OPENING_INPUTS, + field_constants: &[], + field_exprs: &[], + kernels: REGISTERS_KERNELS, + claims: REGISTERS_CLAIMS, + batches: REGISTERS_BATCHES, + drivers: REGISTERS_DRIVERS, + instance_results: REGISTERS_INSTANCES, + evals: REGISTERS_EVALS, + point_slices: &[], + point_concats: &[], + opening_claims: &[], + opening_equalities: &[], + opening_batches: &[], + }; + + const RAM_RA_STEPS: &[Stage5ProgramStepPlan] = &[Stage5ProgramStepPlan { + kind: "sumcheck_driver", + symbol: "stage5.ram_ra.sumcheck", + }]; + const RAM_RA_OPENING_INPUTS: &[Stage5OpeningInputPlan] = &[ + Stage5OpeningInputPlan { + symbol: "stage5.input.stage2.ram_raf.RamRa", + source_stage: "stage2", + source_claim: "stage2.ram_raf.opening.RamRa", + oracle: "RamRa", + domain: "jolt.stage2_ram_rw_domain", + point_arity: 3, + claim_kind: "virtual", + }, + Stage5OpeningInputPlan { + symbol: "stage5.input.stage2.ram_read_write.RamRa", + source_stage: "stage2", + source_claim: "stage2.ram_read_write.opening.RamRa", + oracle: "RamRa", + domain: "jolt.stage2_ram_rw_domain", + point_arity: 3, + claim_kind: "virtual", + }, + Stage5OpeningInputPlan { + symbol: "stage5.input.stage4.ram_val_check.RamRa", + source_stage: "stage4", + source_claim: "stage4.ram_val_check.opening.RamRa", + oracle: "RamRa", + domain: "jolt.stage2_ram_rw_domain", + point_arity: 3, + claim_kind: "virtual", + }, + ]; + const RAM_RA_FIELD_CONSTANTS: &[Stage5FieldConstantPlan] = &[Stage5FieldConstantPlan { + symbol: "stage5.ram_ra_claim_reduction.gamma", + field: "bn254_fr", + value: 2, + }]; + const RAM_RA_GAMMA2_OPERANDS: &[&str] = &["stage5.ram_ra_claim_reduction.gamma"]; + const RAM_RA_RW_TERM_OPERANDS: &[&str] = &[ + "stage5.ram_ra_claim_reduction.gamma", + "stage5.input.stage2.ram_read_write.RamRa", + ]; + const RAM_RA_VAL_TERM_OPERANDS: &[&str] = &[ + "stage5.ram_ra_claim_reduction.gamma2", + "stage5.input.stage4.ram_val_check.RamRa", + ]; + const RAM_RA_PARTIAL_OPERANDS: &[&str] = &[ + "stage5.input.stage2.ram_raf.RamRa", + "stage5.ram_ra_claim_reduction.term.RamRaReadWrite", + ]; + const RAM_RA_CLAIM_OPERANDS_EXPR: &[&str] = &[ + "stage5.ram_ra_claim_reduction.partial.RafReadWrite", + "stage5.ram_ra_claim_reduction.term.RamRaValCheck", + ]; + const RAM_RA_FIELD_EXPRS: &[Stage5FieldExprPlan] = &[ + Stage5FieldExprPlan { + symbol: "stage5.ram_ra_claim_reduction.gamma2", + kind: "op", + formula: "field.pow:2", + operand_names: RAM_RA_GAMMA2_OPERANDS, + operands: RAM_RA_GAMMA2_OPERANDS, + }, + Stage5FieldExprPlan { + symbol: "stage5.ram_ra_claim_reduction.term.RamRaReadWrite", + kind: "op", + formula: "field.mul", + operand_names: RAM_RA_RW_TERM_OPERANDS, + operands: RAM_RA_RW_TERM_OPERANDS, + }, + Stage5FieldExprPlan { + symbol: "stage5.ram_ra_claim_reduction.term.RamRaValCheck", + kind: "op", + formula: "field.mul", + operand_names: RAM_RA_VAL_TERM_OPERANDS, + operands: RAM_RA_VAL_TERM_OPERANDS, + }, + Stage5FieldExprPlan { + symbol: "stage5.ram_ra_claim_reduction.partial.RafReadWrite", + kind: "op", + formula: "field.add", + operand_names: RAM_RA_PARTIAL_OPERANDS, + operands: RAM_RA_PARTIAL_OPERANDS, + }, + Stage5FieldExprPlan { + symbol: "stage5.ram_ra_claim_reduction.claim_expr", + kind: "op", + formula: "field.add", + operand_names: RAM_RA_CLAIM_OPERANDS_EXPR, + operands: RAM_RA_CLAIM_OPERANDS_EXPR, + }, + ]; + const RAM_RA_KERNELS: &[Stage5KernelPlan] = &[ + Stage5KernelPlan { + symbol: "jolt.cpu.stage5.ram_ra_claim_reduction", + relation: "jolt.stage5.ram_ra_claim_reduction", + kind: "sumcheck", + backend: "cpu", + abi: "jolt_stage5_ram_ra_claim_reduction", + }, + Stage5KernelPlan { + symbol: "jolt.cpu.stage5.batched", + relation: "jolt.stage5.batched", + kind: "sumcheck", + backend: "cpu", + abi: "jolt_stage5_batched", + }, + ]; + const RAM_RA_CLAIM_INPUTS: &[&str] = &[ + "stage5.input.stage2.ram_raf.RamRa", + "stage5.input.stage2.ram_read_write.RamRa", + "stage5.input.stage4.ram_val_check.RamRa", + ]; + const RAM_RA_CLAIMS: &[Stage5SumcheckClaimPlan] = &[Stage5SumcheckClaimPlan { + symbol: "stage5.ram_ra_claim_reduction.input", + stage: "stage5", + domain: "jolt.trace_domain", + num_rounds: 2, + degree: 2, + claim: "stage5.ram_ra_claim_reduction.weighted_ram_ra", + kernel: Some("jolt.cpu.stage5.ram_ra_claim_reduction"), + relation: Some("jolt.stage5.ram_ra_claim_reduction"), + claim_value: "stage5.ram_ra_claim_reduction.claim_expr", + input_openings: RAM_RA_CLAIM_INPUTS, + }]; + const RAM_RA_ORDERED_CLAIMS: &[&str] = &["stage5.ram_ra_claim_reduction.input"]; + const RAM_RA_ROUND_SCHEDULE: &[usize] = &[2]; + const RAM_RA_BATCHES: &[Stage5SumcheckBatchPlan] = &[Stage5SumcheckBatchPlan { + symbol: "stage5.ram_ra.batch", + stage: "stage5", + proof_slot: "stage5.ram_ra.sumcheck", + policy: "test", + count: 1, + ordered_claims: RAM_RA_ORDERED_CLAIMS, + claim_operands: RAM_RA_ORDERED_CLAIMS, + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + round_schedule: RAM_RA_ROUND_SCHEDULE, + }]; + const RAM_RA_DRIVERS: &[Stage5SumcheckDriverPlan] = &[Stage5SumcheckDriverPlan { + symbol: "stage5.ram_ra.sumcheck", + stage: "stage5", + proof_slot: "stage5.ram_ra.sumcheck", + kernel: Some("jolt.cpu.stage5.batched"), + relation: Some("jolt.stage5.batched"), + batch: "stage5.ram_ra.batch", + policy: "test", + round_schedule: RAM_RA_ROUND_SCHEDULE, + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + num_rounds: 2, + degree: 2, + }]; + const RAM_RA_INSTANCES: &[Stage5SumcheckInstanceResultPlan] = + &[Stage5SumcheckInstanceResultPlan { + symbol: "stage5.ram_ra_claim_reduction.instance", + source: "stage5.ram_ra.sumcheck", + claim: "stage5.ram_ra_claim_reduction.input", + relation: "jolt.stage5.ram_ra_claim_reduction", + index: 0, + point_arity: 2, + num_rounds: 2, + round_offset: 0, + point_order: "reverse", + degree: 2, + }]; + const RAM_RA_EVALS: &[Stage5SumcheckEvalPlan] = &[Stage5SumcheckEvalPlan { + symbol: "stage5.ram_ra_claim_reduction.eval.RamRa", + source: "stage5.ram_ra.sumcheck", + name: "stage5.ram_ra_claim_reduction.eval.RamRa", + index: 0, + oracle: "RamRa", + }]; + const RAM_RA_PROGRAM: Stage5CpuProgramPlan = Stage5CpuProgramPlan { + role: "prover", + params: PARAMS, + steps: RAM_RA_STEPS, + transcript_squeezes: &[], + transcript_absorb_bytes: &[], + opening_inputs: RAM_RA_OPENING_INPUTS, + field_constants: RAM_RA_FIELD_CONSTANTS, + field_exprs: RAM_RA_FIELD_EXPRS, + kernels: RAM_RA_KERNELS, + claims: RAM_RA_CLAIMS, + batches: RAM_RA_BATCHES, + drivers: RAM_RA_DRIVERS, + instance_results: RAM_RA_INSTANCES, + evals: RAM_RA_EVALS, + point_slices: &[], + point_concats: &[], + opening_claims: &[], + opening_equalities: &[], + opening_batches: &[], + }; + + #[derive(Default)] + struct RecordingExecutor { + observed_challenges: usize, + proved: bool, + } + + impl Stage5KernelExecutor for RecordingExecutor { + fn observe_challenge_vector( + &mut self, + plan: &'static Stage5TranscriptSqueezePlan, + values: &[Fr], + ) -> Result<(), Stage5KernelError> { + assert_eq!(plan.symbol, "stage5.gamma"); + assert_eq!(values.len(), 1); + self.observed_challenges += 1; + Ok(()) + } + + fn prove_sumcheck( + &mut self, + context: Stage5KernelContext<'_>, + _transcript: &mut T, + ) -> Result, Stage5KernelError> + where + T: Transcript, + { + assert_eq!(context.mode, Stage5ExecutionMode::Prover); + assert_eq!(context.abi_kind()?, Stage5KernelAbi::Batched); + assert_eq!(context.relation_kind()?, Stage5Relation::Batched); + assert_eq!(context.batch_claims()?.len(), 1); + self.proved = true; + Ok(Stage5SumcheckOutput { + driver: context.driver.symbol, + point: vec![Fr::from_u64(7)], + evals: Vec::new(), + opening_claims: Vec::new(), + proof: SumcheckProof { + round_polynomials: Vec::new(), + }, + }) + } + + fn verify_sumcheck( + &mut self, + context: Stage5KernelContext<'_>, + _transcript: &mut T, + ) -> Result, Stage5KernelError> + where + T: Transcript, + { + Err(Stage5KernelError::WrongExecutorMode { + driver: context.driver.symbol, + expected: Stage5ExecutionMode::Prover, + actual: Stage5ExecutionMode::Verifier, + }) + } + } + + #[test] + fn stage5_program_executes_with_stage5_abi_and_relation_names() { + let mut transcript = Blake2bTranscript::::new(b"Jolt"); + let mut executor = RecordingExecutor::default(); + + let artifacts = execute_stage5_program( + &PROGRAM, + Stage5ExecutionMode::Prover, + &mut executor, + &mut transcript, + ) + .expect("stage5 program executes"); + + assert_eq!(executor.observed_challenges, 1); + assert!(executor.proved); + assert_eq!(artifacts.challenge_vectors.len(), 1); + assert_eq!(artifacts.sumchecks.len(), 1); + assert_eq!(artifacts.sumchecks[0].driver, "stage5.sumcheck"); + } + + #[test] + fn stage5_registers_val_prover_produces_verifiable_sumcheck() { + let registers_point = frs(&[1, 2, 3]); + let rd_inc = frs(&[2, 3, 4, 5]); + let rd_write_addresses = [Some(0usize), Some(1usize), None, Some(1usize)]; + let input_eval = registers_val_input_claim(®isters_point, &rd_inc, &rd_write_addresses); + let opening_inputs = vec![Stage5OpeningInputValue { + symbol: "stage5.input.stage4.registers.RegistersVal", + point: registers_point, + eval: input_eval, + }]; + let prover_inputs = Stage5ProverInputs::new(&opening_inputs).with_registers_val( + Stage5RegistersValWitness { + register_count: 2, + trace_len: 4, + rd_inc: &rd_inc, + rd_wa: &[], + rd_write_addresses: Some(&rd_write_addresses), + }, + ); + let mut prover = Stage5ProverKernelExecutor::new(prover_inputs); + let mut prover_transcript = Blake2bTranscript::::new(b"Jolt"); + let artifacts = execute_stage5_program( + ®ISTERS_PROGRAM, + Stage5ExecutionMode::Prover, + &mut prover, + &mut prover_transcript, + ) + .expect("registers val prover succeeds"); + + assert_eq!(artifacts.sumchecks.len(), 1); + assert_eq!(artifacts.sumchecks[0].evals.len(), 2); + + let proof = Stage5Proof { + sumchecks: artifacts.sumchecks.clone(), + }; + let mut verifier = Stage5ProofCarryingKernelExecutor::new(&proof, &opening_inputs); + let mut verifier_transcript = Blake2bTranscript::::new(b"Jolt"); + let verified = execute_stage5_program( + ®ISTERS_PROGRAM, + Stage5ExecutionMode::Verifier, + &mut verifier, + &mut verifier_transcript, + ) + .expect("registers val verifier accepts prover output"); + + assert_eq!(artifacts.sumchecks[0].point, verified.sumchecks[0].point); + assert_eq!( + named_eval_values(&artifacts.sumchecks[0].evals), + named_eval_values(&verified.sumchecks[0].evals) + ); + } + + #[test] + fn stage5_ram_ra_prover_produces_verifiable_sumcheck() { + let ram_raf_point = frs(&[1, 2, 3]); + let ram_rw_point = frs(&[1, 5, 7]); + let ram_val_point = frs(&[1, 11, 13]); + let remapped_addresses = [Some(0usize), Some(1usize), None, Some(1usize)]; + let gamma = Fr::from_u64(2); + let claim_raf = ram_ra_input_claim(&ram_raf_point, &remapped_addresses); + let claim_rw = ram_ra_input_claim(&ram_rw_point, &remapped_addresses); + let claim_val = ram_ra_input_claim(&ram_val_point, &remapped_addresses); + let opening_inputs = vec![ + Stage5OpeningInputValue { + symbol: "stage5.input.stage2.ram_raf.RamRa", + point: ram_raf_point, + eval: claim_raf, + }, + Stage5OpeningInputValue { + symbol: "stage5.input.stage2.ram_read_write.RamRa", + point: ram_rw_point, + eval: claim_rw, + }, + Stage5OpeningInputValue { + symbol: "stage5.input.stage4.ram_val_check.RamRa", + point: ram_val_point, + eval: claim_val, + }, + ]; + let mut store = Stage5ValueStore::with_opening_inputs(&opening_inputs); + store.seed_constants(&RAM_RA_PROGRAM); + let _ = store + .evaluate_available_field_exprs(&RAM_RA_PROGRAM) + .expect("field exprs"); + assert_eq!( + claim_raf + gamma * claim_rw + gamma.square() * claim_val, + store + .scalar("stage5.ram_ra_claim_reduction.claim_expr") + .expect("claim expr") + ); + + let prover_inputs = + Stage5ProverInputs::new(&opening_inputs).with_ram_ra(Stage5RamRaWitness { + ram_k: 2, + trace_len: 4, + ram_ra: &[], + remapped_addresses: Some(&remapped_addresses), + }); + let mut prover = Stage5ProverKernelExecutor::new(prover_inputs); + let mut prover_transcript = Blake2bTranscript::::new(b"Jolt"); + let artifacts = execute_stage5_program( + &RAM_RA_PROGRAM, + Stage5ExecutionMode::Prover, + &mut prover, + &mut prover_transcript, + ) + .expect("ram ra prover succeeds"); + + assert_eq!(artifacts.sumchecks.len(), 1); + assert_eq!(artifacts.sumchecks[0].evals.len(), 1); + + let proof = Stage5Proof { + sumchecks: artifacts.sumchecks.clone(), + }; + let mut verifier = Stage5ProofCarryingKernelExecutor::new(&proof, &opening_inputs); + let mut verifier_transcript = Blake2bTranscript::::new(b"Jolt"); + let verified = execute_stage5_program( + &RAM_RA_PROGRAM, + Stage5ExecutionMode::Verifier, + &mut verifier, + &mut verifier_transcript, + ) + .expect("ram ra verifier accepts prover output"); + + assert_eq!(artifacts.sumchecks[0].point, verified.sumchecks[0].point); + assert_eq!( + named_eval_values(&artifacts.sumchecks[0].evals), + named_eval_values(&verified.sumchecks[0].evals) + ); + } + + #[test] + fn stage5_instruction_read_raf_prover_produces_verifiable_sumcheck() { + const CHUNK_BITS: usize = 64; + let r_reduction = frs(&[3, 5]); + let lookup_indices = [ + 0u128, + 1u128 << 127, + (0x1234u128 << 64) | 0xABCDu128, + (0x55AAu128 << 96) | (0xAA55u128 << 32), + ]; + let table_indices = [Some(0usize), Some(0usize), None, Some(0usize)]; + let is_interleaved = [true, false, true, false]; + let gamma = Fr::from_u64(2); + let (lookup_output_claim, left_claim, right_claim) = instruction_read_raf_input_claim( + &r_reduction, + &lookup_indices, + &table_indices, + &is_interleaved, + ); + let input_claim = lookup_output_claim + gamma * left_claim + gamma.square() * right_claim; + let opening_inputs = vec![ + Stage5OpeningInputValue { + symbol: "stage5.input.stage2.instruction.LookupOutput", + point: r_reduction.clone(), + eval: lookup_output_claim, + }, + Stage5OpeningInputValue { + symbol: "stage5.input.stage2.instruction.LeftLookupOperand", + point: r_reduction.clone(), + eval: left_claim, + }, + Stage5OpeningInputValue { + symbol: "stage5.input.stage2.instruction.RightLookupOperand", + point: r_reduction, + eval: right_claim, + }, + Stage5OpeningInputValue { + symbol: "stage5.instruction_read_raf.claim_expr", + point: Vec::new(), + eval: input_claim, + }, + ]; + let program = instruction_read_raf_test_program(2, 128 / CHUNK_BITS); + let prover_inputs = Stage5ProverInputs::new(&opening_inputs).with_instruction_read_raf( + Stage5InstructionReadRafWitness { + trace_len: 4, + lookup_indices: &lookup_indices, + lookup_table_indices: &table_indices, + is_interleaved_operands: &is_interleaved, + ra_virtual_log_k_chunk: CHUNK_BITS, + }, + ); + let mut prover = Stage5ProverKernelExecutor::new(prover_inputs); + let mut prover_transcript = Blake2bTranscript::::new(b"Jolt"); + let artifacts = execute_stage5_program( + program, + Stage5ExecutionMode::Prover, + &mut prover, + &mut prover_transcript, + ) + .expect("instruction read raf prover succeeds"); + + assert_eq!(artifacts.sumchecks.len(), 1); + assert_eq!( + artifacts.sumchecks[0].evals.len(), + LookupTableKind::<64>::all().len() + 128 / CHUNK_BITS + 1 + ); + + let proof = Stage5Proof { + sumchecks: artifacts.sumchecks.clone(), + }; + let mut verifier = Stage5ProofCarryingKernelExecutor::new(&proof, &opening_inputs); + let mut verifier_transcript = Blake2bTranscript::::new(b"Jolt"); + let verified = execute_stage5_program( + program, + Stage5ExecutionMode::Verifier, + &mut verifier, + &mut verifier_transcript, + ) + .expect("instruction read raf verifier accepts prover output"); + + assert_eq!(artifacts.sumchecks[0].point, verified.sumchecks[0].point); + assert_eq!( + named_eval_values(&artifacts.sumchecks[0].evals), + named_eval_values(&verified.sumchecks[0].evals) + ); + } + + #[test] + fn instruction_read_raf_output_evals_follow_trace_flags_and_ra_chunks() { + const CHUNK_BITS: usize = 16; + let lookup_indices = [ + 0u128, + 1u128 << 112, + 0xABCDu128 << 96, + (0x12u128 << 112) | 0x34u128, + ]; + let table_indices = [Some(0usize), Some(2usize), None, Some(0usize)]; + let is_interleaved = [true, false, true, false]; + let address_point = (0..128) + .map(|index| Fr::from_u64(index as u64 + 2)) + .collect::>(); + let cycle_point = frs(&[3, 5]); + let witness = Stage5InstructionReadRafWitness { + trace_len: 4, + lookup_indices: &lookup_indices, + lookup_table_indices: &table_indices, + is_interleaved_operands: &is_interleaved, + ra_virtual_log_k_chunk: CHUNK_BITS, + }; + + let output = instruction_read_raf_output_evals(witness, &address_point, &cycle_point) + .expect("instruction read raf evals"); + let cycle_eq = EqPolynomial::::evals(&cycle_point, None); + assert_eq!(output.lookup_table_flags[0], cycle_eq[0] + cycle_eq[3]); + assert_eq!(output.lookup_table_flags[2], cycle_eq[1]); + assert_eq!(output.instruction_raf_flag, cycle_eq[1] + cycle_eq[3]); + assert_eq!(output.instruction_ra.len(), 8); + + for chunk in 0..output.instruction_ra.len() { + let chunk_point = &address_point[chunk * CHUNK_BITS..(chunk + 1) * CHUNK_BITS]; + let shift = 128 - (chunk + 1) * CHUNK_BITS; + let expected = lookup_indices + .iter() + .zip(&cycle_eq) + .map(|(&lookup_index, &cycle_weight)| { + let chunk_value = (lookup_index >> shift) & ((1u128 << CHUNK_BITS) - 1); + cycle_weight * manual_eq_bits(chunk_point, chunk_value, CHUNK_BITS) + }) + .sum::(); + assert_eq!(output.instruction_ra[chunk], expected, "chunk={chunk}"); + } + } + + fn frs(values: &[u64]) -> Vec { + values.iter().map(|value| Fr::from_u64(*value)).collect() + } + + fn manual_eq_bits(point: &[Fr], bits: u128, num_bits: usize) -> Fr { + point + .iter() + .enumerate() + .map(|(index, &challenge)| { + if ((bits >> (num_bits - 1 - index)) & 1) == 1 { + challenge + } else { + Fr::from_u64(1) - challenge + } + }) + .product() + } + + fn registers_val_input_claim( + registers_point: &[Fr], + rd_inc: &[Fr], + rd_write_addresses: &[Option], + ) -> Fr { + let (address_point, cycle_point) = registers_point.split_at(1); + let address_eq = EqPolynomial::::evals(address_point, None); + let lt = lt_evals_big_endian(cycle_point); + rd_inc + .iter() + .zip(rd_write_addresses) + .zip(lt) + .map(|((&inc, address), lt)| { + let wa = address + .and_then(|address| address_eq.get(address)) + .copied() + .unwrap_or_else(|| Fr::from_u64(0)); + inc * wa * lt + }) + .sum() + } + + fn ram_ra_input_claim(ram_ra_point: &[Fr], remapped_addresses: &[Option]) -> Fr { + let (address_point, cycle_point) = ram_ra_point.split_at(1); + let address_eq = EqPolynomial::::evals(address_point, None); + let eq_cycle = EqPolynomial::::evals(cycle_point, None); + remapped_addresses + .iter() + .zip(eq_cycle) + .map(|(address, eq)| { + let ra = address + .and_then(|address| address_eq.get(address)) + .copied() + .unwrap_or_else(|| Fr::from_u64(0)); + ra * eq + }) + .sum() + } + + fn instruction_read_raf_input_claim( + r_reduction: &[Fr], + lookup_indices: &[u128], + table_indices: &[Option], + is_interleaved: &[bool], + ) -> (Fr, Fr, Fr) { + let tables = LookupTableKind::<64>::all(); + let eq_cycle = EqPolynomial::::evals(r_reduction, None); + let mut lookup_output_claim = Fr::from_u64(0); + let mut left_claim = Fr::from_u64(0); + let mut right_claim = Fr::from_u64(0); + for (((&lookup_index, table_index), &is_interleaved), &cycle_weight) in lookup_indices + .iter() + .zip(table_indices) + .zip(is_interleaved) + .zip(&eq_cycle) + { + let address_point = field_bit_point_128(lookup_index); + if let Some(table_index) = table_index { + lookup_output_claim += + cycle_weight * tables[*table_index].evaluate_mle::(&address_point); + } + if is_interleaved { + left_claim += cycle_weight * operand_polynomial_eval(&address_point, true); + right_claim += cycle_weight * operand_polynomial_eval(&address_point, false); + } else { + right_claim += cycle_weight * identity_polynomial_eval(&address_point); + } + } + (lookup_output_claim, left_claim, right_claim) + } + + fn field_bit_point_128(value: u128) -> Vec { + (0..128) + .map(|index| Fr::from_bool(lookup_bit(value, index, 128))) + .collect() + } + + fn instruction_read_raf_test_program( + trace_rounds: usize, + ra_chunks: usize, + ) -> &'static Stage5CpuProgramPlan { + let table_count = LookupTableKind::<64>::all().len(); + let driver_symbol = "stage5.instruction_read_raf.sumcheck"; + let claim_symbol = "stage5.instruction_read_raf.input"; + let ordered_claims = Box::leak(vec![claim_symbol].into_boxed_slice()); + let round_schedule = Box::leak(vec![128, trace_rounds].into_boxed_slice()); + let claim_inputs = Box::leak( + vec![ + "stage5.input.stage2.instruction.LookupOutput", + "stage5.input.stage2.instruction.LeftLookupOperand", + "stage5.input.stage2.instruction.RightLookupOperand", + ] + .into_boxed_slice(), + ); + let mut evals = Vec::with_capacity(table_count + ra_chunks + 1); + for index in 0..table_count { + let name = leak_test_str(format!( + "stage5.instruction_read_raf.eval.LookupTableFlag_{index}" + )); + let oracle = leak_test_str(format!("LookupTableFlag_{index}")); + evals.push(Stage5SumcheckEvalPlan { + symbol: name, + source: driver_symbol, + name, + index, + oracle, + }); + } + for index in 0..ra_chunks { + let name = leak_test_str(format!( + "stage5.instruction_read_raf.eval.InstructionRa_{index}" + )); + let oracle = leak_test_str(format!("InstructionRa_{index}")); + evals.push(Stage5SumcheckEvalPlan { + symbol: name, + source: driver_symbol, + name, + index: table_count + index, + oracle, + }); + } + evals.push(Stage5SumcheckEvalPlan { + symbol: "stage5.instruction_read_raf.eval.InstructionRafFlag", + source: driver_symbol, + name: "stage5.instruction_read_raf.eval.InstructionRafFlag", + index: table_count + ra_chunks, + oracle: "InstructionRafFlag", + }); + + Box::leak(Box::new(Stage5CpuProgramPlan { + role: "prover", + params: PARAMS, + steps: Box::leak( + vec![Stage5ProgramStepPlan { + kind: "sumcheck_driver", + symbol: driver_symbol, + }] + .into_boxed_slice(), + ), + transcript_squeezes: &[], + transcript_absorb_bytes: &[], + opening_inputs: Box::leak( + vec![ + Stage5OpeningInputPlan { + symbol: "stage5.input.stage2.instruction.LookupOutput", + source_stage: "stage2", + source_claim: + "stage2.instruction_lookup.claim_reduction.opening.LookupOutput", + oracle: "LookupOutput", + domain: "jolt.trace_domain", + point_arity: trace_rounds, + claim_kind: "virtual", + }, + Stage5OpeningInputPlan { + symbol: "stage5.input.stage2.instruction.LeftLookupOperand", + source_stage: "stage2", + source_claim: + "stage2.instruction_lookup.claim_reduction.opening.LeftLookupOperand", + oracle: "LeftLookupOperand", + domain: "jolt.trace_domain", + point_arity: trace_rounds, + claim_kind: "virtual", + }, + Stage5OpeningInputPlan { + symbol: "stage5.input.stage2.instruction.RightLookupOperand", + source_stage: "stage2", + source_claim: + "stage2.instruction_lookup.claim_reduction.opening.RightLookupOperand", + oracle: "RightLookupOperand", + domain: "jolt.trace_domain", + point_arity: trace_rounds, + claim_kind: "virtual", + }, + ] + .into_boxed_slice(), + ), + field_constants: Box::leak( + vec![Stage5FieldConstantPlan { + symbol: "stage5.instruction_read_raf.gamma", + field: "bn254_fr", + value: 2, + }] + .into_boxed_slice(), + ), + field_exprs: &[], + kernels: Box::leak( + vec![ + Stage5KernelPlan { + symbol: "jolt.cpu.stage5.instruction_read_raf", + relation: "jolt.stage5.instruction_read_raf", + kind: "sumcheck", + backend: "cpu", + abi: "jolt_stage5_instruction_read_raf", + }, + Stage5KernelPlan { + symbol: "jolt.cpu.stage5.batched", + relation: "jolt.stage5.batched", + kind: "sumcheck", + backend: "cpu", + abi: "jolt_stage5_batched", + }, + ] + .into_boxed_slice(), + ), + claims: Box::leak( + vec![Stage5SumcheckClaimPlan { + symbol: claim_symbol, + stage: "stage5", + domain: "jolt.stage5_instruction_read_raf_domain", + num_rounds: 128 + trace_rounds, + degree: ra_chunks + 2, + claim: "stage5.instruction_read_raf.weighted_lookup_values", + kernel: Some("jolt.cpu.stage5.instruction_read_raf"), + relation: Some("jolt.stage5.instruction_read_raf"), + claim_value: "stage5.instruction_read_raf.claim_expr", + input_openings: claim_inputs, + }] + .into_boxed_slice(), + ), + batches: Box::leak( + vec![Stage5SumcheckBatchPlan { + symbol: "stage5.instruction_read_raf.batch", + stage: "stage5", + proof_slot: driver_symbol, + policy: "test", + count: 1, + ordered_claims, + claim_operands: ordered_claims, + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + round_schedule, + }] + .into_boxed_slice(), + ), + drivers: Box::leak( + vec![Stage5SumcheckDriverPlan { + symbol: driver_symbol, + stage: "stage5", + proof_slot: driver_symbol, + kernel: Some("jolt.cpu.stage5.batched"), + relation: Some("jolt.stage5.batched"), + batch: "stage5.instruction_read_raf.batch", + policy: "test", + round_schedule, + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + num_rounds: 128 + trace_rounds, + degree: ra_chunks + 2, + }] + .into_boxed_slice(), + ), + instance_results: Box::leak( + vec![Stage5SumcheckInstanceResultPlan { + symbol: "stage5.instruction_read_raf.instance", + source: driver_symbol, + claim: claim_symbol, + relation: "jolt.stage5.instruction_read_raf", + index: 0, + point_arity: 128 + trace_rounds, + num_rounds: 128 + trace_rounds, + round_offset: 0, + point_order: "instruction_read_raf", + degree: ra_chunks + 2, + }] + .into_boxed_slice(), + ), + evals: Box::leak(evals.into_boxed_slice()), + point_slices: &[], + point_concats: &[], + opening_claims: &[], + opening_equalities: &[], + opening_batches: &[], + })) + } + + fn leak_test_str(value: String) -> &'static str { + Box::leak(value.into_boxed_str()) + } + + fn named_eval_values(evals: &[Stage5NamedEval]) -> Vec<(&'static str, &'static str, Fr)> { + evals + .iter() + .map(|eval| (eval.name, eval.oracle, eval.value)) + .collect() + } +} diff --git a/crates/jolt-kernels/src/stage6.rs b/crates/jolt-kernels/src/stage6.rs new file mode 100644 index 0000000000..b5cc499a41 --- /dev/null +++ b/crates/jolt-kernels/src/stage6.rs @@ -0,0 +1,7163 @@ +//! Stage 6 coarse-kernel ABI used by Bolt-generated Jolt prover code. + +use std::error::Error; +use std::fmt::{self, Display, Formatter}; + +use crate::dense::{bind_dense_evals_reuse, DENSE_BIND_PAR_THRESHOLD}; +use jolt_field::Field; +use jolt_poly::{ + BindingOrder, EqPolynomial, ExpandingTable, GruenSplitEqPolynomial, UnivariatePoly, +}; +use jolt_transcript::{Label, LabelWithCount, Transcript}; +pub use jolt_witness::Stage6WitnessParams; +use jolt_witness::{ + stage6_witness_polynomials, CycleInput, Stage6OpeningInputRef, Stage6WitnessInputs, + Stage6WitnessPolynomials, Stage6WitnessSlices, +}; +use rayon::prelude::*; + +pub use crate::stage4::{ + Stage4ChallengeVector as Stage6ChallengeVector, + Stage4ExecutionArtifacts as Stage6ExecutionArtifacts, + Stage4ExecutionMode as Stage6ExecutionMode, Stage4FieldConstantPlan as Stage6FieldConstantPlan, + Stage4FieldExprPlan as Stage6FieldExprPlan, Stage4NamedEval as Stage6NamedEval, + Stage4OpeningBatchPlan as Stage6OpeningBatchPlan, + Stage4OpeningClaimEqualityPlan as Stage6OpeningClaimEqualityPlan, + Stage4OpeningClaimPlan as Stage6OpeningClaimPlan, + Stage4OpeningClaimValue as Stage6OpeningClaimValue, + Stage4OpeningInputPlan as Stage6OpeningInputPlan, + Stage4OpeningInputValue as Stage6OpeningInputValue, Stage4Params as Stage6Params, + Stage4PointConcatPlan as Stage6PointConcatPlan, Stage4PointSlicePlan as Stage6PointSlicePlan, + Stage4ProgramStepPlan as Stage6ProgramStepPlan, Stage4Proof as Stage6Proof, + Stage4SumcheckBatchPlan as Stage6SumcheckBatchPlan, + Stage4SumcheckClaimPlan as Stage6SumcheckClaimPlan, + Stage4SumcheckDriverPlan as Stage6SumcheckDriverPlan, + Stage4SumcheckEvalPlan as Stage6SumcheckEvalPlan, + Stage4SumcheckInstanceResultPlan as Stage6SumcheckInstanceResultPlan, + Stage4SumcheckOutput as Stage6SumcheckOutput, + Stage4TranscriptAbsorbBytesPlan as Stage6TranscriptAbsorbBytesPlan, + Stage4TranscriptSqueezePlan as Stage6TranscriptSqueezePlan, +}; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage6KernelPlan { + pub symbol: &'static str, + pub relation: &'static str, + pub kind: &'static str, + pub backend: &'static str, + pub abi: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage6PointZeroPlan { + pub symbol: &'static str, + pub field: &'static str, + pub arity: usize, +} + +impl Stage6KernelPlan { + pub fn relation_kind(&self) -> Result { + Stage6Relation::from_symbol(self.relation).ok_or(Stage6KernelError::UnknownRelation { + relation: self.relation, + }) + } + + pub fn abi_kind(&self) -> Result { + Stage6KernelAbi::from_name(self.abi) + .ok_or(Stage6KernelError::UnknownKernelAbi { abi: self.abi }) + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage6CpuProgramPlan { + pub role: &'static str, + pub params: Stage6Params, + pub steps: &'static [Stage6ProgramStepPlan], + pub transcript_squeezes: &'static [Stage6TranscriptSqueezePlan], + pub transcript_absorb_bytes: &'static [Stage6TranscriptAbsorbBytesPlan], + pub opening_inputs: &'static [Stage6OpeningInputPlan], + pub field_constants: &'static [Stage6FieldConstantPlan], + pub field_exprs: &'static [Stage6FieldExprPlan], + pub kernels: &'static [Stage6KernelPlan], + pub claims: &'static [Stage6SumcheckClaimPlan], + pub batches: &'static [Stage6SumcheckBatchPlan], + pub drivers: &'static [Stage6SumcheckDriverPlan], + pub instance_results: &'static [Stage6SumcheckInstanceResultPlan], + pub evals: &'static [Stage6SumcheckEvalPlan], + pub point_zeros: &'static [Stage6PointZeroPlan], + pub point_slices: &'static [Stage6PointSlicePlan], + pub point_concats: &'static [Stage6PointConcatPlan], + pub opening_claims: &'static [Stage6OpeningClaimPlan], + pub opening_equalities: &'static [Stage6OpeningClaimEqualityPlan], + pub opening_batches: &'static [Stage6OpeningBatchPlan], +} + +impl Stage6CpuProgramPlan { + pub fn claim(&self, symbol: &str) -> Option<&Stage6SumcheckClaimPlan> { + self.claims.iter().find(|claim| claim.symbol == symbol) + } + + pub fn instance_results_for_driver( + &self, + driver: &'static str, + ) -> impl Iterator { + self.instance_results + .iter() + .filter(move |instance| instance.source == driver) + } + + pub fn evals_for_driver( + &self, + driver: &'static str, + ) -> impl Iterator { + self.evals.iter().filter(move |eval| eval.source == driver) + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Stage6Relation { + BytecodeReadRaf, + Booleanity, + HammingBooleanity, + RamRaVirtual, + InstructionRaVirtual, + IncClaimReduction, + Batched, +} + +impl Stage6Relation { + pub fn from_symbol(symbol: &str) -> Option { + match symbol { + "jolt.stage6.bytecode_read_raf" => Some(Self::BytecodeReadRaf), + "jolt.stage6.booleanity" => Some(Self::Booleanity), + "jolt.stage6.hamming_booleanity" => Some(Self::HammingBooleanity), + "jolt.stage6.ram_ra_virtual" => Some(Self::RamRaVirtual), + "jolt.stage6.instruction_ra_virtual" => Some(Self::InstructionRaVirtual), + "jolt.stage6.inc_claim_reduction" => Some(Self::IncClaimReduction), + "jolt.stage6.batched" => Some(Self::Batched), + _ => None, + } + } + + pub fn symbol(self) -> &'static str { + match self { + Self::BytecodeReadRaf => "jolt.stage6.bytecode_read_raf", + Self::Booleanity => "jolt.stage6.booleanity", + Self::HammingBooleanity => "jolt.stage6.hamming_booleanity", + Self::RamRaVirtual => "jolt.stage6.ram_ra_virtual", + Self::InstructionRaVirtual => "jolt.stage6.instruction_ra_virtual", + Self::IncClaimReduction => "jolt.stage6.inc_claim_reduction", + Self::Batched => "jolt.stage6.batched", + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Stage6KernelAbi { + BytecodeReadRaf, + Booleanity, + HammingBooleanity, + RamRaVirtual, + InstructionRaVirtual, + IncClaimReduction, + Batched, +} + +impl Stage6KernelAbi { + pub fn from_name(name: &str) -> Option { + match name { + "jolt_stage6_bytecode_read_raf" => Some(Self::BytecodeReadRaf), + "jolt_stage6_booleanity" => Some(Self::Booleanity), + "jolt_stage6_hamming_booleanity" => Some(Self::HammingBooleanity), + "jolt_stage6_ram_ra_virtual" => Some(Self::RamRaVirtual), + "jolt_stage6_instruction_ra_virtual" => Some(Self::InstructionRaVirtual), + "jolt_stage6_inc_claim_reduction" => Some(Self::IncClaimReduction), + "jolt_stage6_batched" => Some(Self::Batched), + _ => None, + } + } + + pub fn name(self) -> &'static str { + match self { + Self::BytecodeReadRaf => "jolt_stage6_bytecode_read_raf", + Self::Booleanity => "jolt_stage6_booleanity", + Self::HammingBooleanity => "jolt_stage6_hamming_booleanity", + Self::RamRaVirtual => "jolt_stage6_ram_ra_virtual", + Self::InstructionRaVirtual => "jolt_stage6_instruction_ra_virtual", + Self::IncClaimReduction => "jolt_stage6_inc_claim_reduction", + Self::Batched => "jolt_stage6_batched", + } + } +} + +const BYTECODE_READ_RAF_STAGE_COUNT: usize = 5; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum Stage6KernelError { + MissingClaim { + batch: &'static str, + claim: &'static str, + }, + MissingValue { + symbol: &'static str, + }, + MissingDriver { + driver: &'static str, + }, + MissingKernel { + driver: &'static str, + kernel: &'static str, + }, + MissingBatch { + driver: &'static str, + batch: &'static str, + }, + UnknownRelation { + relation: &'static str, + }, + UnknownKernelAbi { + abi: &'static str, + }, + PlanCountMismatch { + artifact: &'static str, + expected: usize, + actual: usize, + }, + InvalidInputLength { + input: &'static str, + expected: usize, + actual: usize, + }, + UnsupportedFieldExpr { + symbol: &'static str, + formula: &'static str, + }, + KernelNotImplemented { + abi: &'static str, + }, + WrongExecutorMode { + driver: &'static str, + expected: Stage6ExecutionMode, + actual: Stage6ExecutionMode, + }, + MissingProof { + driver: &'static str, + }, + MissingKernelInput { + kernel: &'static str, + input: &'static str, + }, + InvalidProgramStep { + symbol: &'static str, + kind: &'static str, + }, + InvalidProof { + driver: &'static str, + reason: &'static str, + }, +} + +impl Display for Stage6KernelError { + fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result { + match self { + Self::MissingClaim { batch, claim } => { + write!( + formatter, + "stage6 batch @{batch} references missing claim @{claim}" + ) + } + Self::MissingValue { symbol } => { + write!(formatter, "stage6 value @{symbol} is not available") + } + Self::MissingDriver { driver } => { + write!(formatter, "stage6 driver @{driver} is not available") + } + Self::MissingKernel { driver, kernel } => { + write!( + formatter, + "stage6 driver @{driver} references missing kernel @{kernel}" + ) + } + Self::MissingBatch { driver, batch } => { + write!( + formatter, + "stage6 driver @{driver} references missing batch @{batch}" + ) + } + Self::UnknownRelation { relation } => { + write!(formatter, "unknown stage6 relation `{relation}`") + } + Self::UnknownKernelAbi { abi } => { + write!(formatter, "unknown stage6 kernel ABI `{abi}`") + } + Self::PlanCountMismatch { + artifact, + expected, + actual, + } => { + write!( + formatter, + "stage6 {artifact} plan count mismatch: expected {expected}, got {actual}" + ) + } + Self::InvalidInputLength { + input, + expected, + actual, + } => { + write!( + formatter, + "stage6 input `{input}` has length {actual}, expected {expected}" + ) + } + Self::UnsupportedFieldExpr { symbol, formula } => { + write!( + formatter, + "stage6 field expr @{symbol} uses unsupported formula `{formula}`" + ) + } + Self::KernelNotImplemented { abi } => { + write!(formatter, "stage6 kernel ABI `{abi}` is not implemented") + } + Self::WrongExecutorMode { + driver, + expected, + actual, + } => { + write!( + formatter, + "stage6 driver @{driver} expected {expected:?} executor, got {actual:?}" + ) + } + Self::MissingProof { driver } => { + write!(formatter, "stage6 proof for driver @{driver} is missing") + } + Self::MissingKernelInput { kernel, input } => { + write!( + formatter, + "stage6 kernel `{kernel}` is missing required input `{input}`" + ) + } + Self::InvalidProgramStep { symbol, kind } => { + write!( + formatter, + "stage6 program step @{symbol} has invalid kind `{kind}`" + ) + } + Self::InvalidProof { driver, reason } => { + write!( + formatter, + "stage6 proof for driver @{driver} is invalid: {reason}" + ) + } + } + } +} + +impl Error for Stage6KernelError {} + +#[derive(Clone, Copy)] +pub struct Stage6BooleanityWitness<'a, F: Field> { + pub chunks: &'a [&'a [F]], + pub index_chunks: Option<&'a [&'a [Option]]>, +} + +#[derive(Clone, Copy, Debug)] +pub struct Stage6BytecodeEntry { + pub address: F, + pub imm: F, + pub circuit_flags: [bool; 14], + pub rd: Option, + pub rs1: Option, + pub rs2: Option, + pub lookup_table: Option, + pub is_interleaved: bool, + pub is_branch: bool, + pub left_is_rs1: bool, + pub left_is_pc: bool, + pub right_is_rs2: bool, + pub right_is_imm: bool, + pub is_noop: bool, +} + +#[derive(Clone, Copy, Debug)] +pub struct Stage6BytecodeReadRafData<'a, F: Field> { + pub entries: &'a [Stage6BytecodeEntry], + pub entry_bytecode_index: usize, + pub num_lookup_tables: usize, +} + +impl From> for Stage6BytecodeEntry { + fn from(entry: jolt_witness::Stage6BytecodeEntry) -> Self { + Self { + address: entry.address, + imm: entry.imm, + circuit_flags: entry.circuit_flags, + rd: entry.rd, + rs1: entry.rs1, + rs2: entry.rs2, + lookup_table: entry.lookup_table, + is_interleaved: entry.is_interleaved, + is_branch: entry.is_branch, + left_is_rs1: entry.left_is_rs1, + left_is_pc: entry.left_is_pc, + right_is_rs2: entry.right_is_rs2, + right_is_imm: entry.right_is_imm, + is_noop: entry.is_noop, + } + } +} + +#[derive(Clone, Debug)] +pub struct Stage6BytecodeReadRafDataStorage { + entries: Vec>, + entry_bytecode_index: usize, + num_lookup_tables: usize, +} + +impl Stage6BytecodeReadRafDataStorage { + pub fn from_witness_entries( + entries: &[jolt_witness::Stage6BytecodeEntry], + entry_bytecode_index: usize, + num_lookup_tables: usize, + ) -> Self { + Self { + entries: entries.iter().copied().map(Into::into).collect(), + entry_bytecode_index, + num_lookup_tables, + } + } + + pub fn as_input(&self) -> Stage6BytecodeReadRafData<'_, F> { + Stage6BytecodeReadRafData { + entries: &self.entries, + entry_bytecode_index: self.entry_bytecode_index, + num_lookup_tables: self.num_lookup_tables, + } + } +} + +#[derive(Clone, Copy)] +pub struct Stage6BytecodeReadRafWitness<'a, F: Field> { + pub data: Stage6BytecodeReadRafData<'a, F>, + pub bytecode_ra_chunks: &'a [&'a [F]], + pub bytecode_ra_chunk_lens: Option<&'a [usize]>, + pub bytecode_ra_index_chunks: Option<&'a [&'a [Option]]>, +} + +#[derive(Clone, Copy)] +pub struct Stage6HammingBooleanityWitness<'a, F: Field> { + pub hamming_weight: &'a [F], +} + +#[derive(Clone, Copy)] +pub struct Stage6IncClaimReductionWitness<'a, F: Field> { + pub ram_inc: &'a [F], + pub rd_inc: &'a [F], +} + +#[derive(Clone, Copy)] +pub struct Stage6RamRaVirtualWitness<'a, F: Field> { + pub ram_ra_chunks: &'a [&'a [F]], +} + +#[derive(Clone, Copy)] +pub struct Stage6InstructionRaVirtualWitness<'a, F: Field> { + pub instruction_ra_chunks: &'a [&'a [F]], + pub virtual_count: usize, +} + +pub fn stage6_witness_from_opening_inputs( + params: Stage6WitnessParams, + cycle_inputs: &[CycleInput], + opening_inputs: &[Stage6OpeningInputValue], +) -> Stage6WitnessPolynomials { + let opening_refs = opening_inputs + .iter() + .map(|input| Stage6OpeningInputRef { + symbol: input.symbol, + point: input.point.as_slice(), + }) + .collect::>(); + stage6_witness_polynomials(Stage6WitnessInputs { + params, + cycle_inputs, + opening_inputs: &opening_refs, + }) +} + +#[derive(Clone, Copy)] +pub struct Stage6ProverInputs<'a, F: Field> { + pub opening_inputs: &'a [Stage6OpeningInputValue], + pub bytecode_read_raf: Option>, + pub booleanity: Option>, + pub hamming_booleanity: Option>, + pub inc_claim_reduction: Option>, + pub ram_ra_virtual: Option>, + pub instruction_ra_virtual: Option>, +} + +impl<'a, F: Field> Stage6ProverInputs<'a, F> { + pub fn new(opening_inputs: &'a [Stage6OpeningInputValue]) -> Self { + Self { + opening_inputs, + bytecode_read_raf: None, + booleanity: None, + hamming_booleanity: None, + inc_claim_reduction: None, + ram_ra_virtual: None, + instruction_ra_virtual: None, + } + } + + pub fn empty() -> Self { + Self { + opening_inputs: &[], + bytecode_read_raf: None, + booleanity: None, + hamming_booleanity: None, + inc_claim_reduction: None, + ram_ra_virtual: None, + instruction_ra_virtual: None, + } + } + + pub fn with_hamming_booleanity( + mut self, + hamming_booleanity: Stage6HammingBooleanityWitness<'a, F>, + ) -> Self { + self.hamming_booleanity = Some(hamming_booleanity); + self + } + + pub fn with_booleanity(mut self, booleanity: Stage6BooleanityWitness<'a, F>) -> Self { + self.booleanity = Some(booleanity); + self + } + + pub fn with_bytecode_read_raf( + mut self, + bytecode_read_raf: Stage6BytecodeReadRafWitness<'a, F>, + ) -> Self { + self.bytecode_read_raf = Some(bytecode_read_raf); + self + } + + pub fn with_inc_claim_reduction( + mut self, + inc_claim_reduction: Stage6IncClaimReductionWitness<'a, F>, + ) -> Self { + self.inc_claim_reduction = Some(inc_claim_reduction); + self + } + + pub fn with_ram_ra_virtual(mut self, ram_ra_virtual: Stage6RamRaVirtualWitness<'a, F>) -> Self { + self.ram_ra_virtual = Some(ram_ra_virtual); + self + } + + pub fn with_instruction_ra_virtual( + mut self, + instruction_ra_virtual: Stage6InstructionRaVirtualWitness<'a, F>, + ) -> Self { + self.instruction_ra_virtual = Some(instruction_ra_virtual); + self + } + + pub fn with_stage6_witness( + self, + bytecode_data: Stage6BytecodeReadRafData<'a, F>, + witness: &'a Stage6WitnessPolynomials, + slices: &'a Stage6WitnessSlices<'a, F>, + instruction_ra_virtual_count: usize, + ) -> Self { + self.with_bytecode_read_raf(Stage6BytecodeReadRafWitness { + data: bytecode_data, + bytecode_ra_chunks: &slices.bytecode_ra_read_raf_chunks, + bytecode_ra_chunk_lens: Some(&slices.bytecode_ra_read_raf_chunk_lens), + bytecode_ra_index_chunks: Some(&slices.bytecode_ra_index_chunks), + }) + .with_booleanity(Stage6BooleanityWitness { + chunks: &slices.booleanity_chunks, + index_chunks: Some(&slices.booleanity_index_chunks), + }) + .with_hamming_booleanity(Stage6HammingBooleanityWitness { + hamming_weight: &witness.hamming_weight, + }) + .with_ram_ra_virtual(Stage6RamRaVirtualWitness { + ram_ra_chunks: &slices.ram_ra_virtual_chunks, + }) + .with_instruction_ra_virtual(Stage6InstructionRaVirtualWitness { + instruction_ra_chunks: &slices.instruction_ra_virtual_chunks, + virtual_count: instruction_ra_virtual_count, + }) + .with_inc_claim_reduction(Stage6IncClaimReductionWitness { + ram_inc: &witness.ram_inc, + rd_inc: &witness.rd_inc, + }) + } +} + +#[derive(Clone, Copy, Debug)] +pub struct Stage6KernelContext<'a> { + pub mode: Stage6ExecutionMode, + pub program: &'static Stage6CpuProgramPlan, + pub kernel: &'a Stage6KernelPlan, + pub batch: &'a Stage6SumcheckBatchPlan, + pub driver: &'a Stage6SumcheckDriverPlan, +} + +impl Stage6KernelContext<'_> { + pub fn relation_kind(&self) -> Result { + self.kernel.relation_kind() + } + + pub fn abi_kind(&self) -> Result { + self.kernel.abi_kind() + } + + pub fn batch_claims(&self) -> Result, Stage6KernelError> { + self.batch + .claim_operands + .iter() + .map(|symbol| { + self.program + .claim(symbol) + .ok_or(Stage6KernelError::MissingClaim { + batch: self.batch.symbol, + claim: symbol, + }) + }) + .collect() + } +} + +pub trait Stage6KernelExecutor { + fn observe_challenge_vector( + &mut self, + _plan: &'static Stage6TranscriptSqueezePlan, + _values: &[F], + ) -> Result<(), Stage6KernelError> { + Ok(()) + } + + fn observe_sumcheck_output( + &mut self, + _output: &Stage6SumcheckOutput, + ) -> Result<(), Stage6KernelError> { + Ok(()) + } + + fn opening_claim_values( + &self, + _program: &'static Stage6CpuProgramPlan, + ) -> Result>, Stage6KernelError> { + Ok(Vec::new()) + } + + fn prove_sumcheck( + &mut self, + context: Stage6KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage6KernelError> + where + T: Transcript; + + fn verify_sumcheck( + &mut self, + context: Stage6KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage6KernelError> + where + T: Transcript; +} + +#[derive(Clone, Debug, Default)] +pub struct UnsupportedStage6KernelExecutor; + +impl Stage6KernelExecutor for UnsupportedStage6KernelExecutor { + fn prove_sumcheck( + &mut self, + context: Stage6KernelContext<'_>, + _transcript: &mut T, + ) -> Result, Stage6KernelError> + where + T: Transcript, + { + let abi = context.abi_kind()?; + let _ = context.relation_kind()?; + Err(Stage6KernelError::KernelNotImplemented { abi: abi.name() }) + } + + fn verify_sumcheck( + &mut self, + context: Stage6KernelContext<'_>, + _transcript: &mut T, + ) -> Result, Stage6KernelError> + where + T: Transcript, + { + let abi = context.abi_kind()?; + let _ = context.relation_kind()?; + Err(Stage6KernelError::KernelNotImplemented { abi: abi.name() }) + } +} + +#[derive(Clone)] +pub struct Stage6ProverKernelExecutor<'a, F: Field> { + pub inputs: Stage6ProverInputs<'a, F>, + challenge_vectors: Vec>, + completed_sumchecks: Vec>, +} + +impl<'a, F: Field> Stage6ProverKernelExecutor<'a, F> { + pub fn new(inputs: Stage6ProverInputs<'a, F>) -> Self { + Self { + inputs, + challenge_vectors: Vec::new(), + completed_sumchecks: Vec::new(), + } + } + + fn value_store( + &self, + program: &'static Stage6CpuProgramPlan, + ) -> Result, Stage6KernelError> { + value_store_from_observations( + program, + self.inputs.opening_inputs, + &self.challenge_vectors, + &self.completed_sumchecks, + ) + } +} + +impl Stage6KernelExecutor for Stage6ProverKernelExecutor<'_, F> { + fn observe_challenge_vector( + &mut self, + plan: &'static Stage6TranscriptSqueezePlan, + values: &[F], + ) -> Result<(), Stage6KernelError> { + self.challenge_vectors.push(Stage6ChallengeVector { + symbol: plan.symbol, + values: values.to_vec(), + }); + Ok(()) + } + + fn observe_sumcheck_output( + &mut self, + output: &Stage6SumcheckOutput, + ) -> Result<(), Stage6KernelError> { + self.completed_sumchecks.push(output.clone()); + Ok(()) + } + + fn opening_claim_values( + &self, + program: &'static Stage6CpuProgramPlan, + ) -> Result>, Stage6KernelError> { + self.value_store(program)?.opening_claim_values(program) + } + + fn prove_sumcheck( + &mut self, + context: Stage6KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage6KernelError> + where + T: Transcript, + { + prove_stage6_kernel( + context, + &self.inputs, + self.value_store(context.program)?, + transcript, + ) + } + + fn verify_sumcheck( + &mut self, + context: Stage6KernelContext<'_>, + _transcript: &mut T, + ) -> Result, Stage6KernelError> + where + T: Transcript, + { + Err(Stage6KernelError::WrongExecutorMode { + driver: context.driver.symbol, + expected: Stage6ExecutionMode::Prover, + actual: Stage6ExecutionMode::Verifier, + }) + } +} + +#[derive(Clone)] +pub struct Stage6ProofCarryingKernelExecutor<'a, F: Field> { + pub proof: &'a Stage6Proof, + pub opening_inputs: &'a [Stage6OpeningInputValue], + pub bytecode_read_raf: Option>, + pub cursor: usize, + challenge_vectors: Vec>, + completed_sumchecks: Vec>, +} + +impl<'a, F: Field> Stage6ProofCarryingKernelExecutor<'a, F> { + pub fn new( + proof: &'a Stage6Proof, + opening_inputs: &'a [Stage6OpeningInputValue], + ) -> Self { + Self { + proof, + opening_inputs, + bytecode_read_raf: None, + cursor: 0, + challenge_vectors: Vec::new(), + completed_sumchecks: Vec::new(), + } + } + + pub fn with_bytecode_read_raf_data( + mut self, + bytecode_read_raf: Stage6BytecodeReadRafData<'a, F>, + ) -> Self { + self.bytecode_read_raf = Some(bytecode_read_raf); + self + } + + fn value_store( + &self, + program: &'static Stage6CpuProgramPlan, + ) -> Result, Stage6KernelError> { + value_store_from_observations( + program, + self.opening_inputs, + &self.challenge_vectors, + &self.completed_sumchecks, + ) + } + + fn next_proof( + &mut self, + driver: &'static str, + ) -> Result<&'a Stage6SumcheckOutput, Stage6KernelError> { + let proof = self + .proof + .sumchecks + .get(self.cursor) + .ok_or(Stage6KernelError::MissingProof { driver })?; + self.cursor += 1; + Ok(proof) + } +} + +impl Stage6KernelExecutor for Stage6ProofCarryingKernelExecutor<'_, F> { + fn observe_challenge_vector( + &mut self, + plan: &'static Stage6TranscriptSqueezePlan, + values: &[F], + ) -> Result<(), Stage6KernelError> { + self.challenge_vectors.push(Stage6ChallengeVector { + symbol: plan.symbol, + values: values.to_vec(), + }); + Ok(()) + } + + fn observe_sumcheck_output( + &mut self, + output: &Stage6SumcheckOutput, + ) -> Result<(), Stage6KernelError> { + self.completed_sumchecks.push(output.clone()); + Ok(()) + } + + fn opening_claim_values( + &self, + program: &'static Stage6CpuProgramPlan, + ) -> Result>, Stage6KernelError> { + self.value_store(program)?.opening_claim_values(program) + } + + fn prove_sumcheck( + &mut self, + context: Stage6KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage6KernelError> + where + T: Transcript, + { + let proof = self.next_proof(context.driver.symbol)?; + verify_stage6_kernel( + context, + self.value_store(context.program)?, + proof, + self.bytecode_read_raf, + transcript, + ) + } + + fn verify_sumcheck( + &mut self, + context: Stage6KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage6KernelError> + where + T: Transcript, + { + let proof = self.next_proof(context.driver.symbol)?; + verify_stage6_kernel( + context, + self.value_store(context.program)?, + proof, + self.bytecode_read_raf, + transcript, + ) + } +} + +#[derive(Clone, Debug, Default)] +struct Stage6ValueStore { + scalars: Vec<(&'static str, F)>, + points: Vec<(&'static str, Vec)>, +} + +impl Stage6ValueStore { + fn with_opening_inputs(inputs: &[Stage6OpeningInputValue]) -> Self { + let mut store = Self::default(); + for input in inputs { + store.insert_scalar(input.symbol, input.eval); + store.insert_point(input.symbol, input.point.clone()); + } + store + } + + fn seed_constants(&mut self, program: &'static Stage6CpuProgramPlan) { + for constant in program.field_constants { + self.insert_scalar(constant.symbol, F::from_u64(constant.value as u64)); + } + for zero in program.point_zeros { + self.insert_point(zero.symbol, vec![F::from_u64(0); zero.arity]); + } + } + + fn observe_challenge_vector( + &mut self, + plan: &'static Stage6TranscriptSqueezePlan, + values: &[F], + ) -> Result<(), Stage6KernelError> { + self.insert_point(plan.symbol, values.to_vec()); + if matches!(plan.kind, "challenge_scalar" | "scalar") { + require_operand_count(plan.symbol, 1, values.len())?; + self.insert_scalar(plan.symbol, values[0]); + } + Ok(()) + } + + fn observe_sumcheck_output( + &mut self, + program: &'static Stage6CpuProgramPlan, + output: &Stage6SumcheckOutput, + ) -> Result<(), Stage6KernelError> { + self.observe_sumcheck_values(program, output.driver, &output.point, &output.evals) + } + + fn observe_sumcheck_values( + &mut self, + program: &'static Stage6CpuProgramPlan, + driver: &'static str, + point: &[F], + evals: &[Stage6NamedEval], + ) -> Result<(), Stage6KernelError> { + self.insert_point(driver, point.to_vec()); + for instance in program + .instance_results + .iter() + .filter(|instance| instance.source == driver) + { + let end = instance.round_offset + instance.point_arity; + let mut point = point + .get(instance.round_offset..end) + .ok_or(Stage6KernelError::InvalidInputLength { + input: instance.symbol, + expected: end, + actual: point.len(), + })? + .to_vec(); + match instance.point_order { + "as_is" => {} + "reverse" => point.reverse(), + "bytecode_read_raf" => point = normalize_bytecode_read_raf_point(program, &point)?, + "stage6_booleanity" => point = normalize_stage6_booleanity_point(program, &point)?, + "instruction_read_raf" => point = normalize_instruction_read_raf_point(&point)?, + _ => { + return Err(Stage6KernelError::InvalidProof { + driver, + reason: "unsupported point order", + }); + } + } + self.insert_point(instance.symbol, point); + } + for eval in program.evals.iter().filter(|eval| eval.source == driver) { + let value = evals + .iter() + .find(|value| value.name == eval.name) + .or_else(|| evals.get(eval.index)) + .ok_or(Stage6KernelError::MissingValue { + symbol: eval.symbol, + })? + .value; + self.insert_scalar(eval.symbol, value); + self.insert_scalar(eval.name, value); + } + let _ = self.evaluate_available_points(program)?; + let _ = self.evaluate_available_field_exprs(program)?; + self.verify_opening_equalities(program)?; + Ok(()) + } + + fn evaluate_available_field_exprs( + &mut self, + program: &'static Stage6CpuProgramPlan, + ) -> Result { + let mut inserted = 0usize; + loop { + let mut progress = 0usize; + for expr in program.field_exprs { + if self.try_scalar(expr.symbol).is_some() { + continue; + } + let Some(operands) = self.try_expr_operands(expr) else { + continue; + }; + self.insert_scalar(expr.symbol, evaluate_stage6_field_expr(expr, &operands)?); + progress += 1; + } + inserted += progress; + if progress == 0 { + return Ok(inserted); + } + } + } + + fn evaluate_available_points( + &mut self, + program: &'static Stage6CpuProgramPlan, + ) -> Result { + let mut inserted = 0usize; + loop { + let mut progress = 0usize; + for slice in program.point_slices { + if self.try_point(slice.symbol).is_some() { + continue; + } + let Some(input) = self.try_point(slice.input) else { + continue; + }; + let end = slice.offset + slice.length; + let point = input + .get(slice.offset..end) + .ok_or(Stage6KernelError::InvalidInputLength { + input: slice.symbol, + expected: end, + actual: input.len(), + })? + .to_vec(); + self.insert_point(slice.symbol, point); + progress += 1; + } + for concat in program.point_concats { + if self.try_point(concat.symbol).is_some() { + continue; + } + let Some(point) = self.try_concat_point(concat) else { + continue; + }; + require_operand_count(concat.symbol, concat.arity, point.len())?; + self.insert_point(concat.symbol, point); + progress += 1; + } + inserted += progress; + if progress == 0 { + return Ok(inserted); + } + } + } + + fn verify_opening_equalities( + &self, + program: &'static Stage6CpuProgramPlan, + ) -> Result<(), Stage6KernelError> { + for equality in program.opening_equalities { + match equality.mode { + "point_and_eval" => { + if self.point(equality.lhs)? != self.point(equality.rhs)? + || self.scalar(equality.lhs)? != self.scalar(equality.rhs)? + { + return Err(Stage6KernelError::InvalidProof { + driver: equality.symbol, + reason: "opening claim equality failed", + }); + } + } + _ => { + return Err(Stage6KernelError::InvalidProof { + driver: equality.symbol, + reason: "unsupported opening equality mode", + }); + } + } + } + Ok(()) + } + + fn claim_value( + &mut self, + program: &'static Stage6CpuProgramPlan, + claim: &Stage6SumcheckClaimPlan, + ) -> Result { + let _ = self.evaluate_available_field_exprs(program)?; + self.scalar(claim.claim_value) + } + + fn batch_claim_values( + &mut self, + program: &'static Stage6CpuProgramPlan, + batch: &Stage6SumcheckBatchPlan, + ) -> Result, Stage6KernelError> { + batch + .claim_operands + .iter() + .map(|symbol| { + let claim = program + .claim(symbol) + .ok_or(Stage6KernelError::MissingClaim { + batch: batch.symbol, + claim: symbol, + })?; + self.claim_value(program, claim) + }) + .collect() + } + + fn insert_scalar(&mut self, symbol: &'static str, value: F) { + if let Some((_, existing)) = self + .scalars + .iter_mut() + .find(|(existing, _)| *existing == symbol) + { + *existing = value; + } else { + self.scalars.push((symbol, value)); + } + } + + fn insert_point(&mut self, symbol: &'static str, point: Vec) { + if let Some((_, existing)) = self + .points + .iter_mut() + .find(|(existing, _)| *existing == symbol) + { + *existing = point; + } else { + self.points.push((symbol, point)); + } + } + + fn scalar(&self, symbol: &'static str) -> Result { + self.try_scalar(symbol) + .ok_or(Stage6KernelError::MissingValue { symbol }) + } + + fn try_scalar(&self, symbol: &str) -> Option { + self.scalars + .iter() + .find(|(existing, _)| *existing == symbol) + .map(|(_, value)| *value) + } + + fn point(&self, symbol: &'static str) -> Result<&[F], Stage6KernelError> { + self.try_point(symbol) + .ok_or(Stage6KernelError::MissingValue { symbol }) + } + + fn try_point(&self, symbol: &str) -> Option<&[F]> { + self.points + .iter() + .find(|(existing, _)| *existing == symbol) + .map(|(_, point)| point.as_slice()) + } + + fn try_expr_operands(&self, expr: &Stage6FieldExprPlan) -> Option> { + expr.operands + .iter() + .map(|operand| self.try_scalar(operand)) + .collect() + } + + fn try_concat_point(&self, concat: &Stage6PointConcatPlan) -> Option> { + let mut point = Vec::with_capacity(concat.arity); + for input in concat.inputs { + point.extend_from_slice(self.try_point(input)?); + } + Some(point) + } + + fn opening_claim_values( + mut self, + program: &'static Stage6CpuProgramPlan, + ) -> Result>, Stage6KernelError> { + let _ = self.evaluate_available_points(program)?; + let _ = self.evaluate_available_field_exprs(program)?; + program + .opening_claims + .iter() + .map(|claim| { + Ok(Stage6OpeningClaimValue { + symbol: claim.symbol, + oracle: claim.oracle, + domain: claim.domain, + claim_kind: claim.claim_kind, + point: self.point(claim.point_source)?.to_vec(), + eval: self.scalar(claim.eval_source)?, + }) + }) + .collect() + } +} + +fn value_store_from_observations( + program: &'static Stage6CpuProgramPlan, + opening_inputs: &[Stage6OpeningInputValue], + challenge_vectors: &[Stage6ChallengeVector], + completed_sumchecks: &[Stage6SumcheckOutput], +) -> Result, Stage6KernelError> { + let mut store = Stage6ValueStore::with_opening_inputs(opening_inputs); + store.seed_constants(program); + for challenge in challenge_vectors { + let plan = + find_squeeze(program, challenge.symbol).ok_or(Stage6KernelError::MissingValue { + symbol: challenge.symbol, + })?; + store.observe_challenge_vector(plan, &challenge.values)?; + } + for output in completed_sumchecks { + store.observe_sumcheck_output(program, output)?; + } + let _ = store.evaluate_available_points(program)?; + let _ = store.evaluate_available_field_exprs(program)?; + store.verify_opening_equalities(program)?; + Ok(store) +} + +fn prove_stage6_kernel( + context: Stage6KernelContext<'_>, + inputs: &Stage6ProverInputs<'_, F>, + store: Stage6ValueStore, + transcript: &mut T, +) -> Result, Stage6KernelError> +where + F: Field, + T: Transcript, +{ + match context.abi_kind()? { + Stage6KernelAbi::Batched => prove_batched_stage6(context, inputs, store, transcript), + abi => Err(Stage6KernelError::KernelNotImplemented { abi: abi.name() }), + } +} + +fn verify_stage6_kernel( + context: Stage6KernelContext<'_>, + store: Stage6ValueStore, + proof: &Stage6SumcheckOutput, + bytecode_read_raf: Option>, + transcript: &mut T, +) -> Result, Stage6KernelError> +where + F: Field, + T: Transcript, +{ + match context.abi_kind()? { + Stage6KernelAbi::Batched => { + verify_batched_stage6(context, store, proof, bytecode_read_raf, transcript) + } + abi => Err(Stage6KernelError::KernelNotImplemented { abi: abi.name() }), + } +} + +#[tracing::instrument(skip_all, name = "Stage6::prove_batched")] +fn prove_batched_stage6( + context: Stage6KernelContext<'_>, + inputs: &Stage6ProverInputs<'_, F>, + mut store: Stage6ValueStore, + transcript: &mut T, +) -> Result, Stage6KernelError> +where + F: Field, + T: Transcript, +{ + let claims = context.batch_claims()?; + let input_claims = store.batch_claim_values(context.program, context.batch)?; + for claim in &input_claims { + append_labeled_scalar(transcript, context.batch.claim_label, claim); + } + let batching_coeffs = transcript.challenge_vector(claims.len()); + let max_rounds = context.driver.num_rounds; + let timing_enabled = std::env::var_os("JOLT_STAGE6_KERNEL_TIMINGS").is_some(); + let two_inv = F::from_u64(2) + .inverse() + .ok_or(Stage6KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "field element 2 is not invertible", + })?; + let mut instances = Vec::with_capacity(claims.len()); + let mut timing_stats = Vec::with_capacity(claims.len()); + for (index, claim) in claims.iter().enumerate() { + let offset = instance_round_offset(context.program, context.driver.symbol, claim.symbol)?; + if offset + claim.num_rounds > max_rounds { + return Err(Stage6KernelError::InvalidInputLength { + input: claim.symbol, + expected: max_rounds, + actual: offset + claim.num_rounds, + }); + } + let relation = claim_relation(context.program, claim)?; + let active_scale = F::one().mul_pow_2(max_rounds - offset - claim.num_rounds); + let init_start = timing_enabled.then(std::time::Instant::now); + let state = + Stage6ProverInstanceState::new(context.program, claim, inputs, &store, active_scale)?; + let init_nanos = init_start.map_or(0, |start| start.elapsed().as_nanos()); + instances.push(Stage6BatchedInstance { + claim, + relation, + offset, + previous_claim: input_claims[index].mul_pow_2(max_rounds - claim.num_rounds), + state, + }); + timing_stats.push((relation, init_nanos, 0u128, 0u128)); + } + + let mut point = Vec::with_capacity(max_rounds); + let mut round_polynomials = Vec::with_capacity(max_rounds); + let mut batched_claim = instances + .iter() + .zip(&batching_coeffs) + .map(|(instance, &coefficient)| instance.previous_claim * coefficient) + .sum::(); + for round in 0..max_rounds { + let mut individual_polys = Vec::with_capacity(instances.len()); + for (index, instance) in instances.iter_mut().enumerate() { + let poly = if instance.is_active(round) { + let round_start = timing_enabled.then(std::time::Instant::now); + let poly = instance + .state + .round_poly(instance.previous_claim, instance.relation)?; + if let Some(start) = round_start { + timing_stats[index].2 += start.elapsed().as_nanos(); + } + poly + } else { + UnivariatePoly::new(vec![instance.previous_claim * two_inv]) + }; + individual_polys.push(poly); + } + let batched_poly = combine_univariate_polys(&individual_polys, &batching_coeffs); + if batched_poly.evaluate(F::zero()) + batched_poly.evaluate(F::one()) != batched_claim { + return Err(Stage6KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched round claim mismatch", + }); + } + append_compressed_univariate_poly(transcript, context.driver.round_label, &batched_poly); + let challenge = transcript.challenge(); + point.push(challenge); + batched_claim = batched_poly.evaluate(challenge); + for (index, (instance, poly)) in instances.iter_mut().zip(individual_polys).enumerate() { + instance.previous_claim = poly.evaluate(challenge); + if instance.is_active(round) { + let bind_start = timing_enabled.then(std::time::Instant::now); + instance.state.ingest_challenge(challenge); + if let Some(start) = bind_start { + timing_stats[index].3 += start.elapsed().as_nanos(); + } + } + } + round_polynomials.push(batched_poly); + } + + let mut evals = Vec::new(); + let mut expected = F::zero(); + for (instance, &coefficient) in instances.iter().zip(&batching_coeffs) { + let relation_claim = instance.state.final_relation_eval(instance.relation)?; + if instance.previous_claim != relation_claim { + return Err(Stage6KernelError::InvalidProof { + driver: instance.relation.symbol(), + reason: "stage6 relation output claim mismatch", + }); + } + expected += coefficient * relation_claim; + evals.extend(instance.state.final_evals(instance.relation)?); + } + if batched_claim != expected { + return Err(Stage6KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched output claim mismatch", + }); + } + store.observe_sumcheck_values(context.program, context.driver.symbol, &point, &evals)?; + let opening_claims = append_opening_claims(context.program, &mut store, transcript, &evals)?; + if timing_enabled { + for (relation, init_nanos, round_nanos, bind_nanos) in timing_stats { + tracing::info!( + "[stage6 timings] relation={} init_ms={:.3} round_ms={:.3} bind_ms={:.3}", + relation.symbol(), + init_nanos as f64 / 1_000_000.0, + round_nanos as f64 / 1_000_000.0, + bind_nanos as f64 / 1_000_000.0, + ); + } + } + Ok(Stage6SumcheckOutput { + driver: context.driver.symbol, + point, + evals, + opening_claims, + proof: jolt_sumcheck::SumcheckProof { round_polynomials }, + }) +} + +fn verify_batched_stage6( + context: Stage6KernelContext<'_>, + mut store: Stage6ValueStore, + proof: &Stage6SumcheckOutput, + bytecode_read_raf: Option>, + transcript: &mut T, +) -> Result, Stage6KernelError> +where + F: Field, + T: Transcript, +{ + if proof.driver != context.driver.symbol { + return Err(Stage6KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "driver symbol mismatch", + }); + } + if proof.proof.round_polynomials.len() != context.driver.num_rounds { + return Err(Stage6KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "unexpected batched round count", + }); + } + + let claims = context.batch_claims()?; + let input_claims = store.batch_claim_values(context.program, context.batch)?; + for claim in &input_claims { + append_labeled_scalar(transcript, context.batch.claim_label, claim); + } + let batching_coeffs = transcript.challenge_vector(claims.len()); + let max_rounds = context.driver.num_rounds; + let mut running_claim = input_claims + .iter() + .zip(claims.iter()) + .zip(&batching_coeffs) + .map(|((claim, plan), &coefficient)| { + claim.mul_pow_2(max_rounds - plan.num_rounds) * coefficient + }) + .sum::(); + let mut point = Vec::with_capacity(max_rounds); + for poly in &proof.proof.round_polynomials { + if polynomial_degree(poly) > context.driver.degree { + return Err(Stage6KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched polynomial exceeds degree bound", + }); + } + if poly.evaluate(F::zero()) + poly.evaluate(F::one()) != running_claim { + return Err(Stage6KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched round check failed", + }); + } + append_compressed_univariate_poly(transcript, context.driver.round_label, poly); + let challenge = transcript.challenge(); + running_claim = poly.evaluate(challenge); + point.push(challenge); + } + if !proof.point.is_empty() && proof.point != point { + return Err(Stage6KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched point mismatch", + }); + } + if let Some(expected) = expected_batched_output_claim_if_supported( + context, + &store, + &proof.evals, + &point, + &batching_coeffs, + bytecode_read_raf, + )? { + if running_claim != expected { + return Err(Stage6KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched output claim mismatch", + }); + } + } + + let output = Stage6SumcheckOutput { + driver: context.driver.symbol, + point, + evals: proof.evals.clone(), + opening_claims: Vec::new(), + proof: proof.proof.clone(), + }; + store.observe_sumcheck_output(context.program, &output)?; + let opening_claims = + append_opening_claims(context.program, &mut store, transcript, &output.evals)?; + let output = Stage6SumcheckOutput { + opening_claims, + ..output + }; + Ok(output) +} + +fn expected_batched_output_claim_if_supported( + context: Stage6KernelContext<'_>, + store: &Stage6ValueStore, + evals: &[Stage6NamedEval], + point: &[F], + batching_coeffs: &[F], + bytecode_read_raf: Option>, +) -> Result, Stage6KernelError> { + let mut expected = F::zero(); + for (claim, &coefficient) in context.batch_claims()?.iter().zip(batching_coeffs) { + let Some(instance) = context.program.instance_results.iter().find(|instance| { + instance.claim == claim.symbol && instance.source == context.driver.symbol + }) else { + return Ok(None); + }; + let local_point = point + .get(instance.round_offset..instance.round_offset + instance.num_rounds) + .ok_or(Stage6KernelError::InvalidInputLength { + input: instance.symbol, + expected: instance.round_offset + instance.num_rounds, + actual: point.len(), + })?; + let value = match claim_relation(context.program, claim)? { + Stage6Relation::HammingBooleanity => { + expected_hamming_booleanity(store, evals, local_point)? + } + Stage6Relation::IncClaimReduction => { + expected_inc_claim_reduction(store, evals, local_point)? + } + Stage6Relation::RamRaVirtual => expected_ram_ra_virtual(store, evals, local_point)?, + Stage6Relation::InstructionRaVirtual => { + expected_instruction_ra_virtual(context.program, store, evals, local_point)? + } + Stage6Relation::Booleanity => { + expected_booleanity(context.program, store, evals, local_point)? + } + Stage6Relation::BytecodeReadRaf => { + let Some(data) = bytecode_read_raf else { + return Ok(None); + }; + expected_bytecode_read_raf(context.program, data, store, evals, local_point)? + } + Stage6Relation::Batched => return Ok(None), + }; + expected += coefficient * value; + } + Ok(Some(expected)) +} + +fn expected_bytecode_read_raf( + program: &'static Stage6CpuProgramPlan, + data: Stage6BytecodeReadRafData<'_, F>, + store: &Stage6ValueStore, + evals: &[Stage6NamedEval], + local_point: &[F], +) -> Result { + let log_t = stage6_trace_rounds(program)?; + let opening_point = normalize_bytecode_read_raf_point(program, local_point)?; + let log_k = opening_point.len() - log_t; + let (r_address_prime, r_cycle_prime) = opening_point.split_at(log_k); + + let gamma = store.scalar("stage6.bytecode_read_raf.gamma")?; + let gamma_powers = bytecode_gamma_powers(gamma); + let int_eval = identity_polynomial_eval(r_address_prime); + let stage_value_evals = bytecode_stage_value_evals(data, store, r_address_prime, log_t)?; + let stage_cycle_points = bytecode_stage_cycle_points(store, log_t)?; + let int_contrib = [ + gamma_powers[5] * int_eval, + F::zero(), + gamma_powers[4] * int_eval, + F::zero(), + F::zero(), + ]; + + let mut val = F::zero(); + for index in 0..stage_value_evals.len() { + val += (stage_value_evals[index] + int_contrib[index]) + * EqPolynomial::::mle(&stage_cycle_points[index], r_cycle_prime) + * gamma_powers[index]; + } + + let entry_bits = index_bits(data.entry_bytecode_index, log_k)?; + let zero_cycle = vec![F::zero(); r_cycle_prime.len()]; + let entry_contrib = gamma_powers[7] + * EqPolynomial::::mle(&entry_bits, r_address_prime) + * EqPolynomial::::mle(&zero_cycle, r_cycle_prime); + let bytecode_ra = + indexed_evals_by_prefix_any(evals, "stage6.bytecode_read_raf.eval.BytecodeRa_")? + .into_iter() + .product::(); + Ok((val + entry_contrib) * bytecode_ra) +} + +fn expected_booleanity( + program: &'static Stage6CpuProgramPlan, + store: &Stage6ValueStore, + evals: &[Stage6NamedEval], + local_point: &[F], +) -> Result { + let log_t = stage6_trace_rounds(program)?; + let log_k_chunk = + local_point + .len() + .checked_sub(log_t) + .ok_or(Stage6KernelError::InvalidInputLength { + input: "stage6.booleanity.point", + expected: log_t, + actual: local_point.len(), + })?; + let stage5_point = store.point("stage6.input.stage5.instruction_read_raf.InstructionRa_0")?; + let stage5_address_len = + stage5_point + .len() + .checked_sub(log_t) + .ok_or(Stage6KernelError::InvalidInputLength { + input: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", + expected: log_t, + actual: stage5_point.len(), + })?; + if stage5_address_len < log_k_chunk { + return Err(Stage6KernelError::InvalidInputLength { + input: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", + expected: log_k_chunk + log_t, + actual: stage5_point.len(), + }); + } + + let mut stage5_addr = stage5_point[..stage5_address_len].to_vec(); + stage5_addr.reverse(); + let mut combined_r = stage5_addr[stage5_address_len - log_k_chunk..].to_vec(); + combined_r.extend(stage5_point[stage5_address_len..].iter().rev().copied()); + require_operand_count( + "stage6.booleanity.combined_point", + local_point.len(), + combined_r.len(), + )?; + let mut verifier_point = combined_r[..log_k_chunk].to_vec(); + verifier_point.reverse(); + verifier_point.extend(combined_r[log_k_chunk..].iter().rev().copied()); + let eq_eval = EqPolynomial::::mle(local_point, &verifier_point); + + let gamma = store.scalar("stage6.booleanity.gamma")?; + let gamma_sq = gamma.square(); + let mut gamma_power = F::one(); + let mut booleanity = F::zero(); + for ra in booleanity_evals(evals)? { + booleanity += gamma_power * (ra.square() - ra); + gamma_power *= gamma_sq; + } + Ok(eq_eval * booleanity) +} + +fn expected_hamming_booleanity( + store: &Stage6ValueStore, + evals: &[Stage6NamedEval], + local_point: &[F], +) -> Result { + let hamming = eval_by_name(evals, "stage6.hamming_booleanity.eval.HammingWeight")?; + let lookup_output_point = reverse_slice(store.point("stage6.input.stage1.LookupOutput")?); + require_operand_count( + "stage6.input.stage1.LookupOutput", + local_point.len(), + lookup_output_point.len(), + )?; + let eq_eval = EqPolynomial::::mle(local_point, &lookup_output_point); + Ok((hamming.square() - hamming) * eq_eval) +} + +fn expected_inc_claim_reduction( + store: &Stage6ValueStore, + evals: &[Stage6NamedEval], + local_point: &[F], +) -> Result { + let r_cycle_reduced = reverse_slice(local_point); + let ram_inc_stage2 = suffix_point( + store.point("stage6.input.stage2.ram_read_write.RamInc")?, + r_cycle_reduced.len(), + "stage6.input.stage2.ram_read_write.RamInc", + )?; + let ram_inc_stage4 = suffix_point( + store.point("stage6.input.stage4.ram_val_check.RamInc")?, + r_cycle_reduced.len(), + "stage6.input.stage4.ram_val_check.RamInc", + )?; + let rd_inc_stage4 = suffix_point( + store.point("stage6.input.stage4.registers_read_write.RdInc")?, + r_cycle_reduced.len(), + "stage6.input.stage4.registers_read_write.RdInc", + )?; + let rd_inc_stage5 = suffix_point( + store.point("stage6.input.stage5.registers_val_evaluation.RdInc")?, + r_cycle_reduced.len(), + "stage6.input.stage5.registers_val_evaluation.RdInc", + )?; + let gamma = store.scalar("stage6.inc_claim_reduction.gamma")?; + let eq_ram_combined = EqPolynomial::::mle(ram_inc_stage2, &r_cycle_reduced) + + gamma * EqPolynomial::::mle(ram_inc_stage4, &r_cycle_reduced); + let eq_rd_combined = EqPolynomial::::mle(rd_inc_stage4, &r_cycle_reduced) + + gamma * EqPolynomial::::mle(rd_inc_stage5, &r_cycle_reduced); + let ram_inc = eval_by_name(evals, "stage6.inc_claim_reduction.eval.RamInc")?; + let rd_inc = eval_by_name(evals, "stage6.inc_claim_reduction.eval.RdInc")?; + Ok(ram_inc * eq_ram_combined + gamma.square() * rd_inc * eq_rd_combined) +} + +fn expected_ram_ra_virtual( + store: &Stage6ValueStore, + evals: &[Stage6NamedEval], + local_point: &[F], +) -> Result { + let r_cycle_reduced = reverse_slice(local_point); + let r_cycle = suffix_point( + store.point("stage6.input.stage5.ram_ra_claim_reduction.RamRa")?, + r_cycle_reduced.len(), + "stage6.input.stage5.ram_ra_claim_reduction.RamRa", + )?; + let eq_eval = EqPolynomial::::mle(r_cycle, &r_cycle_reduced); + let ram_ra = indexed_evals_by_prefix_any(evals, "stage6.ram_ra_virtual.eval.RamRa_")? + .into_iter() + .product::(); + Ok(eq_eval * ram_ra) +} + +fn expected_instruction_ra_virtual( + program: &'static Stage6CpuProgramPlan, + store: &Stage6ValueStore, + evals: &[Stage6NamedEval], + local_point: &[F], +) -> Result { + let r_cycle_reduced = reverse_slice(local_point); + let r_cycle = suffix_point( + store.point("stage6.input.stage5.instruction_read_raf.InstructionRa_0")?, + r_cycle_reduced.len(), + "stage6.input.stage5.instruction_read_raf.InstructionRa_0", + )?; + let eq_eval = EqPolynomial::::mle(r_cycle, &r_cycle_reduced); + let committed_ra = + indexed_evals_by_prefix_any(evals, "stage6.instruction_ra_virtual.eval.InstructionRa_")?; + let virtual_count = program + .opening_inputs + .iter() + .filter(|input| { + input + .symbol + .starts_with("stage6.input.stage5.instruction_read_raf.InstructionRa_") + }) + .count(); + if virtual_count == 0 || committed_ra.len() % virtual_count != 0 { + return Err(Stage6KernelError::InvalidInputLength { + input: "stage6.instruction_ra_virtual.eval.InstructionRa_", + expected: virtual_count, + actual: committed_ra.len(), + }); + } + let committed_per_virtual = committed_ra.len() / virtual_count; + let gamma = store.scalar("stage6.instruction_ra_virtual.gamma")?; + let mut gamma_power = F::one(); + let mut value = F::zero(); + for chunk in committed_ra.chunks(committed_per_virtual) { + value += gamma_power * chunk.iter().copied().product::(); + gamma_power *= gamma; + } + Ok(eq_eval * value) +} + +struct Stage6BatchedInstance<'a, F: Field> { + claim: &'a Stage6SumcheckClaimPlan, + relation: Stage6Relation, + offset: usize, + previous_claim: F, + state: Stage6ProverInstanceState, +} + +impl Stage6BatchedInstance<'_, F> { + fn is_active(&self, round: usize) -> bool { + round >= self.offset && round < self.offset + self.claim.num_rounds + } +} + +enum Stage6ProverInstanceState { + Booleanity(BooleanityStage6State), + CoreBooleanity(CoreBooleanityStage6State), + BytecodeReadRaf(BytecodeReadRafStage6State), + Dense(DenseStage6State), +} + +impl Stage6ProverInstanceState { + fn new( + program: &'static Stage6CpuProgramPlan, + claim: &Stage6SumcheckClaimPlan, + inputs: &Stage6ProverInputs<'_, F>, + store: &Stage6ValueStore, + active_scale: F, + ) -> Result { + match claim_relation(program, claim)? { + Stage6Relation::BytecodeReadRaf => { + bytecode_read_raf_state(program, claim, inputs, store, active_scale) + } + Stage6Relation::Booleanity => { + booleanity_state(program, claim, inputs, store, active_scale) + } + Stage6Relation::HammingBooleanity => { + hamming_booleanity_state(program, claim, inputs, store, active_scale) + .map(Self::Dense) + } + Stage6Relation::IncClaimReduction => { + inc_claim_reduction_state(program, claim, inputs, store, active_scale) + .map(Self::Dense) + } + Stage6Relation::RamRaVirtual => { + ram_ra_virtual_state(program, claim, inputs, store, active_scale).map(Self::Dense) + } + Stage6Relation::InstructionRaVirtual => { + instruction_ra_virtual_state(program, claim, inputs, store, active_scale) + .map(Self::Dense) + } + relation @ Stage6Relation::Batched => Err(Stage6KernelError::KernelNotImplemented { + abi: relation.symbol(), + }), + } + } + + fn round_poly( + &mut self, + previous_claim: F, + relation: Stage6Relation, + ) -> Result, Stage6KernelError> { + match self { + Self::Booleanity(state) => state.round_poly(previous_claim, relation), + Self::CoreBooleanity(state) => state.round_poly(previous_claim, relation), + Self::BytecodeReadRaf(state) => state.round_poly(previous_claim, relation), + Self::Dense(state) => state.round_poly(previous_claim, relation), + } + } + + fn ingest_challenge(&mut self, challenge: F) { + match self { + Self::Booleanity(state) => state.bind(challenge), + Self::CoreBooleanity(state) => state.bind(challenge), + Self::BytecodeReadRaf(state) => state.bind(challenge), + Self::Dense(state) => state.bind(challenge), + } + } + + fn final_relation_eval(&self, relation: Stage6Relation) -> Result { + match self { + Self::Booleanity(state) => state.final_relation_eval(relation), + Self::CoreBooleanity(state) => state.final_relation_eval(relation), + Self::BytecodeReadRaf(state) => state.final_relation_eval(relation), + Self::Dense(state) => state.final_relation_eval(relation), + } + } + + fn final_evals( + &self, + relation: Stage6Relation, + ) -> Result>, Stage6KernelError> { + match self { + Self::Booleanity(state) => state.final_evals(relation), + Self::CoreBooleanity(state) => state.final_evals(relation), + Self::BytecodeReadRaf(state) => state.final_evals(relation), + Self::Dense(state) => state.final_evals(relation), + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +enum BytecodeReadRafPhase { + Address, + Cycle, +} + +struct BytecodeReadRafStage6State { + log_k: usize, + log_t: usize, + chunk_lens: Vec, + bytecode_ra_chunks: Vec>, + bytecode_ra_indices: Option>>>, + stage_factors: [Vec; BYTECODE_READ_RAF_STAGE_COUNT], + stage_values: [Vec; BYTECODE_READ_RAF_STAGE_COUNT], + entry_trace: Vec, + entry_expected: Vec, + address_challenges: Vec, + cycle_factors: Vec>, + cycle_eqs: [Vec; BYTECODE_READ_RAF_STAGE_COUNT], + cycle_entry_eq: Vec, + bound_stage_values: Option<[F; BYTECODE_READ_RAF_STAGE_COUNT]>, + bound_entry_expected: Option, + outputs: Vec, + gamma_powers: [F; 8], + active_scale: F, + degree_bound: usize, + phase: BytecodeReadRafPhase, +} + +impl BytecodeReadRafStage6State { + #[expect(clippy::too_many_arguments)] + fn new( + data: Stage6BytecodeReadRafData<'_, F>, + bytecode_ra_chunks: &[&[F]], + bytecode_ra_index_chunks: Option<&[&[Option]]>, + bytecode_cycle_indices: Vec, + chunk_lens: Vec, + store: &Stage6ValueStore, + log_k: usize, + log_t: usize, + active_scale: F, + degree_bound: usize, + outputs: Vec, + ) -> Result { + if degree_bound < 2 || degree_bound < chunk_lens.len() + 1 { + return Err(Stage6KernelError::InvalidProof { + driver: Stage6Relation::BytecodeReadRaf.symbol(), + reason: "bytecode read RAF degree bound is too small", + }); + } + let expected_entries = + 1usize + .checked_shl(log_k as u32) + .ok_or(Stage6KernelError::InvalidInputLength { + input: "stage6.bytecode_read_raf.entries", + expected: usize::BITS as usize, + actual: log_k, + })?; + require_operand_count( + "stage6.bytecode_read_raf.entries", + expected_entries, + data.entries.len(), + )?; + require_operand_count( + "stage6.bytecode_read_raf.trace", + 1usize << log_t, + bytecode_cycle_indices.len(), + )?; + if data.entry_bytecode_index >= expected_entries { + return Err(Stage6KernelError::InvalidInputLength { + input: "stage6.bytecode_read_raf.entry_bytecode_index", + expected: expected_entries, + actual: data.entry_bytecode_index + 1, + }); + } + if bytecode_cycle_indices + .iter() + .any(|&index| index >= expected_entries) + { + return Err(Stage6KernelError::InvalidInputLength { + input: "stage6.bytecode_read_raf.BytecodeRa", + expected: expected_entries, + actual: expected_entries + 1, + }); + } + let bytecode_ra_indices = match bytecode_ra_index_chunks { + Some(chunks) if !chunks.is_empty() => { + validate_bytecode_ra_index_chunks(chunks, &chunk_lens, log_t)?; + Some(chunks.iter().map(|chunk| (*chunk).to_vec()).collect()) + } + _ => None, + }; + + let gamma = store.scalar("stage6.bytecode_read_raf.gamma")?; + let gamma_powers = bytecode_gamma_powers(gamma); + let stage_cycle_points = bytecode_stage_cycle_points(store, log_t)?; + let cycle_eqs = stage_cycle_points.each_ref().map(|point| { + let eq = EqPolynomial::::evals(point, None); + debug_assert_eq!(eq.len(), 1usize << log_t); + eq + }); + + let stage1_gamma = store.scalar("stage6.bytecode_read_raf.stage1_gamma")?; + let stage2_gamma = store.scalar("stage6.bytecode_read_raf.stage2_gamma")?; + let stage3_gamma = store.scalar("stage6.bytecode_read_raf.stage3_gamma")?; + let stage4_gamma = store.scalar("stage6.bytecode_read_raf.stage4_gamma")?; + let stage5_gamma = store.scalar("stage6.bytecode_read_raf.stage5_gamma")?; + let stage1_gamma_powers = field_powers(stage1_gamma, 16); + let stage2_gamma_powers = field_powers(stage2_gamma, 4); + let stage3_gamma_powers = field_powers(stage3_gamma, 9); + let stage4_gamma_powers = field_powers(stage4_gamma, 3); + let stage5_gamma_powers = field_powers(stage5_gamma, data.num_lookup_tables + 2); + let stage4_register_point = + register_prefix_point(store, "stage6.input.stage4.Rs1Ra", log_t)?; + let stage5_register_point = register_prefix_point( + store, + "stage6.input.stage5.registers_val_evaluation.RdWa", + log_t, + )?; + + let mut stage_values: [Vec; BYTECODE_READ_RAF_STAGE_COUNT] = + std::array::from_fn(|_| vec![F::zero(); expected_entries]); + for (index, entry) in data.entries.iter().enumerate() { + let mut values = bytecode_entry_stage_values( + entry, + data.num_lookup_tables, + stage4_register_point, + stage5_register_point, + &stage1_gamma_powers, + &stage2_gamma_powers, + &stage3_gamma_powers, + &stage4_gamma_powers, + &stage5_gamma_powers, + )?; + let int_eval = F::from_u64(index as u64); + values[0] += gamma_powers[5] * int_eval; + values[2] += gamma_powers[4] * int_eval; + for stage in 0..BYTECODE_READ_RAF_STAGE_COUNT { + stage_values[stage][index] = values[stage]; + } + } + + let mut stage_factors: [Vec; BYTECODE_READ_RAF_STAGE_COUNT] = + std::array::from_fn(|_| vec![F::zero(); expected_entries]); + for (cycle, &bytecode_index) in bytecode_cycle_indices.iter().enumerate() { + for stage in 0..BYTECODE_READ_RAF_STAGE_COUNT { + stage_factors[stage][bytecode_index] += cycle_eqs[stage][cycle]; + } + } + + let mut entry_trace = vec![F::zero(); expected_entries]; + entry_trace[bytecode_cycle_indices[0]] = F::one(); + let mut entry_expected = vec![F::zero(); expected_entries]; + entry_expected[data.entry_bytecode_index] = F::one(); + + let mut cycle_entry_eq = vec![F::zero(); 1usize << log_t]; + cycle_entry_eq[0] = F::one(); + + Ok(Self { + log_k, + log_t, + chunk_lens, + bytecode_ra_chunks: bytecode_ra_chunks + .iter() + .map(|chunk| (*chunk).to_vec()) + .collect(), + bytecode_ra_indices, + stage_factors, + stage_values, + entry_trace, + entry_expected, + address_challenges: Vec::with_capacity(log_k), + cycle_factors: Vec::new(), + cycle_eqs, + cycle_entry_eq, + bound_stage_values: None, + bound_entry_expected: None, + outputs, + gamma_powers, + active_scale, + degree_bound, + phase: BytecodeReadRafPhase::Address, + }) + } + + fn round_poly( + &self, + previous_claim: F, + relation: Stage6Relation, + ) -> Result, Stage6KernelError> { + let poly = match self.phase { + BytecodeReadRafPhase::Address => self.address_round_poly(relation)?, + BytecodeReadRafPhase::Cycle => self.cycle_round_poly(relation)?, + }; + if poly.evaluate(F::zero()) + poly.evaluate(F::one()) != previous_claim { + return Err(Stage6KernelError::InvalidProof { + driver: relation.symbol(), + reason: "stage6 relation input claim mismatch", + }); + } + Ok(poly) + } + + fn address_round_poly( + &self, + relation: Stage6Relation, + ) -> Result, Stage6KernelError> { + let first_len = self.stage_values[0].len(); + if first_len == 0 || !first_len.is_power_of_two() { + return Err(Stage6KernelError::InvalidProof { + driver: relation.symbol(), + reason: "bytecode read RAF address phase has invalid length", + }); + } + let eval_count = self.degree_bound + 1; + let mut evals = if first_len / 2 >= DENSE_BIND_PAR_THRESHOLD { + (0..first_len / 2) + .into_par_iter() + .fold( + || vec![F::zero(); eval_count], + |mut row_evals, row| { + self.accumulate_address_row(row, &mut row_evals); + row_evals + }, + ) + .reduce( + || vec![F::zero(); eval_count], + |mut left, right| { + for (left, right) in left.iter_mut().zip(right) { + *left += right; + } + left + }, + ) + } else { + let mut evals = vec![F::zero(); eval_count]; + for row in 0..first_len / 2 { + self.accumulate_address_row(row, &mut evals); + } + evals + }; + for eval in &mut evals { + *eval *= self.active_scale; + } + Ok(UnivariatePoly::from_evals(&evals)) + } + + fn accumulate_address_row(&self, row: usize, evals: &mut [F]) { + for (point_index, eval) in evals.iter_mut().enumerate() { + let point = F::from_u64(point_index as u64); + let mut value = F::zero(); + for stage in 0..BYTECODE_READ_RAF_STAGE_COUNT { + let trace_eval = pair_linear_eval(&self.stage_factors[stage], row, point); + let value_eval = pair_linear_eval(&self.stage_values[stage], row, point); + value += self.gamma_powers[stage] * trace_eval * value_eval; + } + let entry_trace = pair_linear_eval(&self.entry_trace, row, point); + let entry_expected = pair_linear_eval(&self.entry_expected, row, point); + value += self.gamma_powers[7] * entry_trace * entry_expected; + *eval += value; + } + } + + fn cycle_round_poly( + &self, + relation: Stage6Relation, + ) -> Result, Stage6KernelError> { + let Some(bound_stage_values) = self.bound_stage_values else { + return Err(Stage6KernelError::InvalidProof { + driver: relation.symbol(), + reason: "bytecode read RAF cycle phase missing bound values", + }); + }; + let Some(bound_entry_expected) = self.bound_entry_expected else { + return Err(Stage6KernelError::InvalidProof { + driver: relation.symbol(), + reason: "bytecode read RAF cycle phase missing entry value", + }); + }; + let first_len = self.cycle_factors.first().map_or(0, Vec::len); + if first_len == 0 || !first_len.is_power_of_two() { + return Err(Stage6KernelError::InvalidProof { + driver: relation.symbol(), + reason: "bytecode read RAF cycle phase has invalid length", + }); + } + let eval_count = self.degree_bound + 1; + let mut evals = if first_len / 2 >= DENSE_BIND_PAR_THRESHOLD { + (0..first_len / 2) + .into_par_iter() + .fold( + || vec![F::zero(); eval_count], + |mut row_evals, row| { + self.accumulate_cycle_row( + row, + bound_stage_values, + bound_entry_expected, + &mut row_evals, + ); + row_evals + }, + ) + .reduce( + || vec![F::zero(); eval_count], + |mut left, right| { + for (left, right) in left.iter_mut().zip(right) { + *left += right; + } + left + }, + ) + } else { + let mut evals = vec![F::zero(); eval_count]; + for row in 0..first_len / 2 { + self.accumulate_cycle_row( + row, + bound_stage_values, + bound_entry_expected, + &mut evals, + ); + } + evals + }; + for eval in &mut evals { + *eval *= self.active_scale; + } + Ok(UnivariatePoly::from_evals(&evals)) + } + + fn accumulate_cycle_row( + &self, + row: usize, + bound_stage_values: [F; BYTECODE_READ_RAF_STAGE_COUNT], + bound_entry_expected: F, + evals: &mut [F], + ) { + for (point_index, eval) in evals.iter_mut().enumerate() { + let point = F::from_u64(point_index as u64); + let mut ra_product = F::one(); + for factor in &self.cycle_factors { + ra_product *= pair_linear_eval(factor, row, point); + } + let mut weighted_value = F::zero(); + for (stage, bound_stage_value) in bound_stage_values.iter().enumerate() { + weighted_value += self.gamma_powers[stage] + * *bound_stage_value + * pair_linear_eval(&self.cycle_eqs[stage], row, point); + } + weighted_value += self.gamma_powers[7] + * bound_entry_expected + * pair_linear_eval(&self.cycle_entry_eq, row, point); + *eval += ra_product * weighted_value; + } + } + + fn bind(&mut self, challenge: F) { + match self.phase { + BytecodeReadRafPhase::Address => self.bind_address(challenge), + BytecodeReadRafPhase::Cycle => self.bind_cycle(challenge), + } + } + + fn bind_address(&mut self, challenge: F) { + for stage in 0..BYTECODE_READ_RAF_STAGE_COUNT { + bind_dense_evals_reuse(&mut self.stage_factors[stage], &mut Vec::new(), challenge); + bind_dense_evals_reuse(&mut self.stage_values[stage], &mut Vec::new(), challenge); + } + bind_dense_evals_reuse(&mut self.entry_trace, &mut Vec::new(), challenge); + bind_dense_evals_reuse(&mut self.entry_expected, &mut Vec::new(), challenge); + self.address_challenges.push(challenge); + if self.address_challenges.len() == self.log_k { + self.init_cycle_phase(); + } + } + + fn init_cycle_phase(&mut self) { + let bound_stage_values = std::array::from_fn(|stage| { + self.stage_values[stage] + .first() + .copied() + .unwrap_or(F::zero()) + }); + let bound_entry_expected = self.entry_expected.first().copied().unwrap_or(F::zero()); + let mut address_point = self.address_challenges.clone(); + address_point.reverse(); + + self.cycle_factors = if let Some(bytecode_ra_indices) = &self.bytecode_ra_indices { + self.sparse_cycle_factors(bytecode_ra_indices, &address_point) + } else { + self.dense_cycle_factors(&address_point) + }; + + self.bound_stage_values = Some(bound_stage_values); + self.bound_entry_expected = Some(bound_entry_expected); + self.stage_factors = std::array::from_fn(|_| Vec::new()); + self.stage_values = std::array::from_fn(|_| Vec::new()); + self.entry_trace.clear(); + self.entry_expected.clear(); + self.phase = BytecodeReadRafPhase::Cycle; + } + + fn sparse_cycle_factors( + &self, + bytecode_ra_indices: &[Vec>], + address_point: &[F], + ) -> Vec> { + let trace_len = 1usize << self.log_t; + bytecode_ra_indices + .iter() + .zip(&self.chunk_lens) + .scan(0usize, |offset, (indices, &chunk_len)| { + let start = *offset; + *offset += chunk_len; + Some((indices, start, chunk_len)) + }) + .map(|(indices, offset, chunk_len)| { + let eq_chunk = + EqPolynomial::::evals(&address_point[offset..offset + chunk_len], None); + indices + .iter() + .take(trace_len) + .map(|index| match index { + Some(index) => eq_chunk[usize::from(*index)], + None => F::zero(), + }) + .collect() + }) + .collect() + } + + fn dense_cycle_factors(&self, address_point: &[F]) -> Vec> { + self.bytecode_ra_chunks + .iter() + .zip(&self.chunk_lens) + .scan(0usize, |offset, (chunk, &chunk_len)| { + let start = *offset; + *offset += chunk_len; + Some((chunk, start, chunk_len)) + }) + .map(|(chunk, offset, chunk_len)| { + let eq_chunk = + EqPolynomial::::evals(&address_point[offset..offset + chunk_len], None); + let trace_len = 1usize << self.log_t; + (0..trace_len) + .map(|cycle| { + eq_chunk + .iter() + .enumerate() + .map(|(chunk_value, &eq)| chunk[chunk_value * trace_len + cycle] * eq) + .sum() + }) + .collect() + }) + .collect() + } + + fn bind_cycle(&mut self, challenge: F) { + for factor in &mut self.cycle_factors { + bind_dense_evals_reuse(factor, &mut Vec::new(), challenge); + } + for eq in &mut self.cycle_eqs { + bind_dense_evals_reuse(eq, &mut Vec::new(), challenge); + } + bind_dense_evals_reuse(&mut self.cycle_entry_eq, &mut Vec::new(), challenge); + } + + fn final_relation_eval(&self, relation: Stage6Relation) -> Result { + let Some(bound_stage_values) = self.bound_stage_values else { + return Err(Stage6KernelError::InvalidProof { + driver: relation.symbol(), + reason: "bytecode read RAF final eval missing bound values", + }); + }; + let Some(bound_entry_expected) = self.bound_entry_expected else { + return Err(Stage6KernelError::InvalidProof { + driver: relation.symbol(), + reason: "bytecode read RAF final eval missing entry value", + }); + }; + let mut ra_product = F::one(); + for factor in &self.cycle_factors { + ra_product *= factor + .first() + .copied() + .ok_or(Stage6KernelError::InvalidProof { + driver: relation.symbol(), + reason: "bytecode read RAF final eval missing RA factor", + })?; + } + let mut weighted_value = F::zero(); + for (stage, bound_stage_value) in bound_stage_values.iter().enumerate() { + weighted_value += self.gamma_powers[stage] + * *bound_stage_value + * self.cycle_eqs[stage].first().copied().ok_or( + Stage6KernelError::InvalidProof { + driver: relation.symbol(), + reason: "bytecode read RAF final eval missing cycle eq", + }, + )?; + } + weighted_value += self.gamma_powers[7] + * bound_entry_expected + * self + .cycle_entry_eq + .first() + .copied() + .ok_or(Stage6KernelError::InvalidProof { + driver: relation.symbol(), + reason: "bytecode read RAF final eval missing entry eq", + })?; + Ok(ra_product * weighted_value) + } + + fn final_evals( + &self, + relation: Stage6Relation, + ) -> Result>, Stage6KernelError> { + self.outputs + .iter() + .map(|output| { + let factor = + output + .factor + .checked_sub(1) + .ok_or(Stage6KernelError::InvalidProof { + driver: relation.symbol(), + reason: "bytecode read RAF output factor underflow", + })?; + let value = self + .cycle_factors + .get(factor) + .and_then(|values| values.first()) + .copied() + .ok_or(Stage6KernelError::InvalidProof { + driver: relation.symbol(), + reason: "bytecode read RAF final eval missing output factor", + })?; + Ok(named_eval(output.name, output.oracle, value)) + }) + .collect() + } +} + +#[inline] +fn pair_linear_eval(values: &[F], row: usize, point: F) -> F { + let low = values[row << 1]; + let high = values[(row << 1) + 1]; + low + (high - low) * point +} + +struct BooleanityStage6State { + eq: Vec, + eq_scratch: Vec, + chunks: Vec>, + chunk_scratch: Vec>, + gamma_powers: Vec, + outputs: Vec, + active_scale: F, + degree_bound: usize, +} + +impl BooleanityStage6State { + fn new( + eq: Vec, + chunks: Vec>, + gamma_powers: Vec, + outputs: Vec, + active_scale: F, + degree_bound: usize, + ) -> Result { + if degree_bound < 3 { + return Err(Stage6KernelError::InvalidProof { + driver: Stage6Relation::Booleanity.symbol(), + reason: "booleanity degree bound is too small", + }); + } + require_operand_count("stage6.booleanity.gamma", chunks.len(), gamma_powers.len())?; + if chunks.iter().any(|chunk| chunk.len() != eq.len()) { + return Err(Stage6KernelError::InvalidProof { + driver: Stage6Relation::Booleanity.symbol(), + reason: "booleanity chunks have inconsistent lengths", + }); + } + let chunk_scratch = (0..chunks.len()).map(|_| Vec::new()).collect(); + Ok(Self { + eq, + eq_scratch: Vec::new(), + chunks, + chunk_scratch, + gamma_powers, + outputs, + active_scale, + degree_bound, + }) + } + + fn round_poly( + &self, + previous_claim: F, + relation: Stage6Relation, + ) -> Result, Stage6KernelError> { + let first_len = self.eq.len(); + if first_len == 0 || !first_len.is_power_of_two() { + return Err(Stage6KernelError::InvalidProof { + driver: relation.symbol(), + reason: "booleanity factor has invalid length", + }); + } + let mut evals = if self.degree_bound == 3 { + self.round_evals_degree3(first_len / 2) + } else { + self.round_evals_generic(first_len / 2) + }; + for eval in &mut evals { + *eval *= self.active_scale; + } + let poly = UnivariatePoly::from_evals(&evals); + if poly.evaluate(F::zero()) + poly.evaluate(F::one()) != previous_claim { + return Err(Stage6KernelError::InvalidProof { + driver: relation.symbol(), + reason: "stage6 relation input claim mismatch", + }); + } + Ok(poly) + } + + fn round_evals_degree3(&self, half_len: usize) -> Vec { + let evals = if half_len >= DENSE_BIND_PAR_THRESHOLD { + (0..half_len) + .into_par_iter() + .fold( + || [F::zero(); 4], + |mut row_evals, row| { + self.accumulate_row_degree3(row, &mut row_evals); + row_evals + }, + ) + .reduce( + || [F::zero(); 4], + |left, right| { + [ + left[0] + right[0], + left[1] + right[1], + left[2] + right[2], + left[3] + right[3], + ] + }, + ) + } else { + let mut evals = [F::zero(); 4]; + for row in 0..half_len { + self.accumulate_row_degree3(row, &mut evals); + } + evals + }; + evals.to_vec() + } + + fn accumulate_row_degree3(&self, row: usize, evals: &mut [F; 4]) { + let eq_low = self.eq[row << 1]; + let eq_high = self.eq[(row << 1) + 1]; + let delta_eq = eq_high - eq_low; + let eq_at_0 = eq_low; + let eq_at_1 = eq_high; + let eq_at_2 = eq_low + delta_eq.mul_u64(2); + let eq_at_3 = eq_low + delta_eq.mul_u64(3); + for (chunk_index, chunk) in self.chunks.iter().enumerate() { + let ra_low = chunk[row << 1]; + let ra_high = chunk[(row << 1) + 1]; + if ra_low == F::zero() && ra_high == F::zero() { + continue; + } + let delta_ra = ra_high - ra_low; + let gamma_power = self.gamma_powers[chunk_index]; + let ra_at_0 = ra_low; + let ra_at_1 = ra_high; + let ra_at_2 = ra_low + delta_ra.mul_u64(2); + let ra_at_3 = ra_low + delta_ra.mul_u64(3); + evals[0] += gamma_power * eq_at_0 * (ra_at_0.square() - ra_at_0); + evals[1] += gamma_power * eq_at_1 * (ra_at_1.square() - ra_at_1); + evals[2] += gamma_power * eq_at_2 * (ra_at_2.square() - ra_at_2); + evals[3] += gamma_power * eq_at_3 * (ra_at_3.square() - ra_at_3); + } + } + + fn round_evals_generic(&self, half_len: usize) -> Vec { + let eval_count = self.degree_bound + 1; + if half_len >= DENSE_BIND_PAR_THRESHOLD { + (0..half_len) + .into_par_iter() + .fold( + || vec![F::zero(); eval_count], + |mut row_evals, row| { + self.accumulate_row_generic(row, &mut row_evals); + row_evals + }, + ) + .reduce( + || vec![F::zero(); eval_count], + |mut left, right| { + for (left, right) in left.iter_mut().zip(right) { + *left += right; + } + left + }, + ) + } else { + let mut evals = vec![F::zero(); eval_count]; + for row in 0..half_len { + self.accumulate_row_generic(row, &mut evals); + } + evals + } + } + + fn accumulate_row_generic(&self, row: usize, evals: &mut [F]) { + let eq_low = self.eq[row << 1]; + let eq_high = self.eq[(row << 1) + 1]; + let delta_eq = eq_high - eq_low; + for (chunk_index, chunk) in self.chunks.iter().enumerate() { + let ra_low = chunk[row << 1]; + let ra_high = chunk[(row << 1) + 1]; + if ra_low == F::zero() && ra_high == F::zero() { + continue; + } + let delta_ra = ra_high - ra_low; + let gamma_power = self.gamma_powers[chunk_index]; + for (point_index, eval) in evals.iter_mut().enumerate() { + let point = F::from_u64(point_index as u64); + let eq_at_point = eq_low + delta_eq * point; + let ra_at_point = ra_low + delta_ra * point; + *eval += gamma_power * eq_at_point * (ra_at_point.square() - ra_at_point); + } + } + } + + fn bind(&mut self, challenge: F) { + bind_dense_evals_reuse(&mut self.eq, &mut self.eq_scratch, challenge); + if self.eq.len() >= DENSE_BIND_PAR_THRESHOLD { + self.chunks + .par_iter_mut() + .zip(self.chunk_scratch.par_iter_mut()) + .for_each(|(chunk, scratch)| { + bind_dense_evals_reuse(chunk, scratch, challenge); + }); + } else { + for (chunk, scratch) in self.chunks.iter_mut().zip(&mut self.chunk_scratch) { + bind_dense_evals_reuse(chunk, scratch, challenge); + } + } + } + + fn factor_eval(&self, index: usize, relation: Stage6Relation) -> Result { + self.chunks + .get(index) + .and_then(|values| values.first()) + .copied() + .ok_or(Stage6KernelError::InvalidProof { + driver: relation.symbol(), + reason: "empty booleanity factor", + }) + } + + fn final_relation_eval(&self, relation: Stage6Relation) -> Result { + let eq = self + .eq + .first() + .copied() + .ok_or(Stage6KernelError::InvalidProof { + driver: relation.symbol(), + reason: "empty booleanity eq factor", + })?; + let mut booleanity = F::zero(); + for (index, &gamma_power) in self.gamma_powers.iter().enumerate() { + let ra = self.factor_eval(index, relation)?; + booleanity += gamma_power * (ra.square() - ra); + } + Ok(eq * booleanity) + } + + fn final_evals( + &self, + relation: Stage6Relation, + ) -> Result>, Stage6KernelError> { + self.outputs + .iter() + .map(|output| { + let factor = + output + .factor + .checked_sub(1) + .ok_or(Stage6KernelError::InvalidProof { + driver: relation.symbol(), + reason: "booleanity output factor underflow", + })?; + Ok(named_eval( + output.name, + output.oracle, + self.factor_eval(factor, relation)?, + )) + }) + .collect() + } +} + +struct CoreBooleanityStage6State { + log_k_chunk: usize, + address_round: usize, + b: GruenSplitEqPolynomial, + d: GruenSplitEqPolynomial, + f_table: ExpandingTable, + eq_r_r: F, + g: Vec>, + indices: Vec>>, + h: Option>>, + h_scratch: Vec>, + gamma_powers: Vec, + gamma_powers_inv: Vec, + gamma_powers_square: Vec, + outputs: Vec, + active_scale: F, +} + +impl CoreBooleanityStage6State { + fn new( + r_address: &[F], + r_cycle: &[F], + indices: Vec>>, + gamma: F, + outputs: Vec, + active_scale: F, + ) -> Result { + let log_k_chunk = r_address.len(); + let chunk_domain = 1usize << log_k_chunk; + let trace_len = 1usize << r_cycle.len(); + if indices.iter().any(|chunk| chunk.len() != trace_len) { + return Err(Stage6KernelError::InvalidProof { + driver: Stage6Relation::Booleanity.symbol(), + reason: "booleanity index chunks have inconsistent trace lengths", + }); + } + + let eq_cycle = EqPolynomial::::evals(r_cycle, None); + let mut g = (0..indices.len()) + .map(|_| vec![F::zero(); chunk_domain]) + .collect::>(); + for (chunk_index, chunk) in indices.iter().enumerate() { + for (cycle, index) in chunk.iter().enumerate() { + let Some(index) = index else { + continue; + }; + let index = usize::from(*index); + if index >= chunk_domain { + return Err(Stage6KernelError::InvalidProof { + driver: Stage6Relation::Booleanity.symbol(), + reason: "booleanity index exceeds chunk domain", + }); + } + g[chunk_index][index] += eq_cycle[cycle]; + } + } + + let mut gamma_powers = Vec::with_capacity(indices.len()); + let mut gamma_powers_inv = Vec::with_capacity(indices.len()); + let mut gamma_powers_square = Vec::with_capacity(indices.len()); + let mut gamma_power = F::one(); + let gamma_square = gamma.square(); + let mut gamma_square_power = F::one(); + for _ in 0..indices.len() { + gamma_powers.push(gamma_power); + gamma_powers_inv.push(gamma_power.inverse().ok_or( + Stage6KernelError::InvalidProof { + driver: Stage6Relation::Booleanity.symbol(), + reason: "booleanity gamma power is not invertible", + }, + )?); + gamma_powers_square.push(gamma_square_power); + gamma_power *= gamma; + gamma_square_power *= gamma_square; + } + + let mut f_table = ExpandingTable::new(chunk_domain, BindingOrder::LowToHigh); + f_table.reset(F::one()); + + Ok(Self { + log_k_chunk, + address_round: 0, + b: GruenSplitEqPolynomial::new(r_address, BindingOrder::LowToHigh), + d: GruenSplitEqPolynomial::new(r_cycle, BindingOrder::LowToHigh), + f_table, + eq_r_r: F::zero(), + g, + indices, + h: None, + h_scratch: Vec::new(), + gamma_powers, + gamma_powers_inv, + gamma_powers_square, + outputs, + active_scale, + }) + } + + fn round_poly( + &self, + previous_claim: F, + relation: Stage6Relation, + ) -> Result, Stage6KernelError> { + if relation != Stage6Relation::Booleanity { + return Err(Stage6KernelError::InvalidProof { + driver: relation.symbol(), + reason: "wrong relation for core booleanity state", + }); + } + let mut poly = if self.h.is_none() { + self.address_round_poly(previous_claim) + } else { + self.cycle_round_poly(previous_claim)? + }; + if self.active_scale != F::one() { + poly *= self.active_scale; + } + if poly.evaluate(F::zero()) + poly.evaluate(F::one()) != previous_claim { + return Err(Stage6KernelError::InvalidProof { + driver: relation.symbol(), + reason: "stage6 booleanity input claim mismatch", + }); + } + Ok(poly) + } + + fn address_round_poly(&self, previous_claim: F) -> UnivariatePoly { + let m = self.address_round + 1; + let f_values = self.f_table.values(); + let quadratic_coeffs = self.b.fold_out_in( + || [F::zero(); 2], + |inner, k_prime, _x_in, e_in| { + let block_start = k_prime << m; + let block_end = block_start + (1 << m); + for (index, g_i) in self.g.iter().enumerate() { + let mut eval_0 = F::zero(); + let mut eval_infty = F::zero(); + for (local, &g_k) in g_i[block_start..block_end].iter().enumerate() { + let k_m = local >> (m - 1); + let f_k = f_values[local & ((1 << (m - 1)) - 1)]; + let g_times_f = g_k * f_k; + let eval_inf = g_times_f * f_k; + if k_m == 0 { + eval_0 += eval_inf - g_times_f; + } + eval_infty += eval_inf; + } + inner[0] += e_in * self.gamma_powers_square[index] * eval_0; + inner[1] += e_in * self.gamma_powers_square[index] * eval_infty; + } + }, + |_x_out, e_out, inner| [e_out * inner[0], e_out * inner[1]], + |left, right| [left[0] + right[0], left[1] + right[1]], + ); + self.b + .gruen_poly_deg_3(quadratic_coeffs[0], quadratic_coeffs[1], previous_claim) + } + + fn cycle_round_poly(&self, previous_claim: F) -> Result, Stage6KernelError> { + let h = self.h.as_ref().ok_or(Stage6KernelError::InvalidProof { + driver: Stage6Relation::Booleanity.symbol(), + reason: "booleanity cycle state is missing", + })?; + let quadratic_coeffs = self.d.fold_out_in( + || [F::zero(); 2], + |inner, j_prime, _x_in, e_in| { + for (index, h_i) in h.iter().enumerate() { + let h_0 = h_i[2 * j_prime]; + let h_1 = h_i[2 * j_prime + 1]; + let delta = h_1 - h_0; + let rho = self.gamma_powers[index]; + inner[0] += e_in * h_0 * (h_0 - rho); + inner[1] += e_in * delta.square(); + } + }, + |_x_out, e_out, inner| [e_out * inner[0], e_out * inner[1]], + |left, right| [left[0] + right[0], left[1] + right[1]], + ); + let adjusted_claim = previous_claim + * self + .eq_r_r + .inverse() + .ok_or(Stage6KernelError::InvalidProof { + driver: Stage6Relation::Booleanity.symbol(), + reason: "booleanity address equality scalar is not invertible", + })?; + Ok(self + .d + .gruen_poly_deg_3(quadratic_coeffs[0], quadratic_coeffs[1], adjusted_claim) + * self.eq_r_r) + } + + fn bind(&mut self, challenge: F) { + if self.h.is_none() { + self.b.bind(challenge); + self.f_table.update(challenge); + self.address_round += 1; + if self.address_round == self.log_k_chunk { + self.eq_r_r = self.b.current_scalar(); + let base_eq = self.f_table.clone_values(); + let h = self + .indices + .iter() + .enumerate() + .map(|(chunk_index, chunk)| { + let rho = self.gamma_powers[chunk_index]; + chunk + .iter() + .map(|index| { + index.map_or(F::zero(), |index| rho * base_eq[usize::from(index)]) + }) + .collect::>() + }) + .collect::>(); + self.h_scratch = (0..h.len()).map(|_| Vec::new()).collect(); + self.h = Some(h); + } + } else { + self.d.bind(challenge); + if let Some(h) = &mut self.h { + for (chunk, scratch) in h.iter_mut().zip(&mut self.h_scratch) { + bind_dense_evals_reuse(chunk, scratch, challenge); + } + } + } + } + + fn factor_eval(&self, index: usize, relation: Stage6Relation) -> Result { + self.h + .as_ref() + .and_then(|h| h.get(index)) + .and_then(|values| values.first()) + .copied() + .map(|value| value * self.gamma_powers_inv[index]) + .ok_or(Stage6KernelError::InvalidProof { + driver: relation.symbol(), + reason: "empty core booleanity factor", + }) + } + + fn final_relation_eval(&self, relation: Stage6Relation) -> Result { + if relation != Stage6Relation::Booleanity { + return Err(Stage6KernelError::InvalidProof { + driver: relation.symbol(), + reason: "wrong relation for core booleanity state", + }); + } + let eq = self.d.current_scalar() * self.eq_r_r; + let h = self.h.as_ref().ok_or(Stage6KernelError::InvalidProof { + driver: relation.symbol(), + reason: "booleanity cycle state is missing", + })?; + let mut booleanity = F::zero(); + for (index, h_i) in h.iter().enumerate() { + let scaled = h_i + .first() + .copied() + .ok_or(Stage6KernelError::InvalidProof { + driver: relation.symbol(), + reason: "empty core booleanity factor", + })?; + booleanity += scaled * (scaled - self.gamma_powers[index]); + } + Ok(eq * booleanity) + } + + fn final_evals( + &self, + relation: Stage6Relation, + ) -> Result>, Stage6KernelError> { + self.outputs + .iter() + .map(|output| { + let factor = + output + .factor + .checked_sub(1) + .ok_or(Stage6KernelError::InvalidProof { + driver: relation.symbol(), + reason: "booleanity output factor underflow", + })?; + Ok(named_eval( + output.name, + output.oracle, + self.factor_eval(factor, relation)?, + )) + }) + .collect() + } +} + +struct DenseStage6State { + factors: Vec>, + factor_scratch: Vec>, + terms: Vec>, + outputs: Vec, + active_scale: F, + degree_bound: usize, +} + +#[derive(Clone)] +struct DenseTerm { + coefficient: F, + factors: Vec, +} + +#[derive(Clone, Copy)] +struct FactorOutput { + name: &'static str, + oracle: &'static str, + factor: usize, +} + +impl DenseStage6State { + fn new( + factors: Vec>, + terms: Vec>, + outputs: Vec, + active_scale: F, + degree_bound: usize, + ) -> Self { + let factor_scratch = (0..factors.len()).map(|_| Vec::new()).collect(); + Self { + factors, + factor_scratch, + terms, + outputs, + active_scale, + degree_bound, + } + } + + fn round_poly( + &self, + previous_claim: F, + relation: Stage6Relation, + ) -> Result, Stage6KernelError> { + let first_len = self.factors.first().map_or(0, Vec::len); + if first_len == 0 || !first_len.is_power_of_two() { + return Err(Stage6KernelError::InvalidProof { + driver: relation.symbol(), + reason: "stage6 dense factor has invalid length", + }); + } + if self.factors.iter().any(|factor| factor.len() != first_len) { + return Err(Stage6KernelError::InvalidProof { + driver: relation.symbol(), + reason: "stage6 dense factors have inconsistent lengths", + }); + } + let poly = round_poly_from_dense_terms( + &self.factors, + &self.terms, + self.active_scale, + self.degree_bound, + relation, + )?; + if poly.evaluate(F::zero()) + poly.evaluate(F::one()) != previous_claim { + return Err(Stage6KernelError::InvalidProof { + driver: relation.symbol(), + reason: "stage6 relation input claim mismatch", + }); + } + Ok(poly) + } + + fn bind(&mut self, challenge: F) { + if self.factors.first().map_or(0, Vec::len) / 2 >= DENSE_BIND_PAR_THRESHOLD { + self.factors + .par_iter_mut() + .zip(self.factor_scratch.par_iter_mut()) + .for_each(|(factor, scratch)| { + bind_dense_evals_reuse(factor, scratch, challenge); + }); + } else { + for (factor, scratch) in self.factors.iter_mut().zip(&mut self.factor_scratch) { + bind_dense_evals_reuse(factor, scratch, challenge); + } + } + } + + fn factor_eval(&self, index: usize, relation: Stage6Relation) -> Result { + self.factors + .get(index) + .and_then(|values| values.first()) + .copied() + .ok_or(Stage6KernelError::InvalidProof { + driver: relation.symbol(), + reason: "empty stage6 factor", + }) + } + + fn final_relation_eval(&self, relation: Stage6Relation) -> Result { + let mut result = F::zero(); + for term in &self.terms { + let mut value = term.coefficient; + for &factor in &term.factors { + value *= self.factor_eval(factor, relation)?; + } + result += value; + } + Ok(result) + } + + fn final_evals( + &self, + relation: Stage6Relation, + ) -> Result>, Stage6KernelError> { + self.outputs + .iter() + .map(|output| { + Ok(named_eval( + output.name, + output.oracle, + self.factor_eval(output.factor, relation)?, + )) + }) + .collect() + } +} + +fn bytecode_read_raf_state( + program: &'static Stage6CpuProgramPlan, + claim: &Stage6SumcheckClaimPlan, + inputs: &Stage6ProverInputs<'_, F>, + store: &Stage6ValueStore, + active_scale: F, +) -> Result, Stage6KernelError> { + let witness = inputs + .bytecode_read_raf + .ok_or(Stage6KernelError::MissingKernelInput { + kernel: "jolt_stage6_batched", + input: "bytecode_read_raf", + })?; + if witness.bytecode_ra_chunks.is_empty() + && matches!(witness.bytecode_ra_index_chunks, None | Some([])) + { + return Err(Stage6KernelError::InvalidInputLength { + input: "stage6.bytecode_read_raf.BytecodeRa", + expected: 1, + actual: 0, + }); + } + + let log_t = stage6_trace_rounds(program)?; + let log_k = + claim + .num_rounds + .checked_sub(log_t) + .ok_or(Stage6KernelError::InvalidInputLength { + input: "stage6.bytecode_read_raf.input", + expected: log_t, + actual: claim.num_rounds, + })?; + let domain_len = 1usize.checked_shl(claim.num_rounds as u32).ok_or( + Stage6KernelError::InvalidInputLength { + input: "stage6.bytecode_read_raf.domain", + expected: usize::BITS as usize, + actual: claim.num_rounds, + }, + )?; + let expected_entries = + 1usize + .checked_shl(log_k as u32) + .ok_or(Stage6KernelError::InvalidInputLength { + input: "stage6.bytecode_read_raf.entries", + expected: usize::BITS as usize, + actual: log_k, + })?; + require_operand_count( + "stage6.bytecode_read_raf.entries", + expected_entries, + witness.data.entries.len(), + )?; + if witness.data.entry_bytecode_index >= expected_entries { + return Err(Stage6KernelError::InvalidInputLength { + input: "stage6.bytecode_read_raf.entry_bytecode_index", + expected: expected_entries, + actual: witness.data.entry_bytecode_index + 1, + }); + } + + let chunk_lens = if witness.bytecode_ra_chunks.is_empty() { + witness + .bytecode_ra_chunk_lens + .ok_or(Stage6KernelError::InvalidInputLength { + input: "stage6.bytecode_read_raf.BytecodeRa", + expected: 1, + actual: 0, + })? + .to_vec() + } else { + let mut chunk_lens = Vec::with_capacity(witness.bytecode_ra_chunks.len()); + for chunk in witness.bytecode_ra_chunks { + let rounds = log2_exact(chunk.len(), "stage6.bytecode_read_raf.BytecodeRa")?; + let chunk_len = + rounds + .checked_sub(log_t) + .ok_or(Stage6KernelError::InvalidInputLength { + input: "stage6.bytecode_read_raf.BytecodeRa", + expected: log_t, + actual: rounds, + })?; + chunk_lens.push(chunk_len); + } + chunk_lens + }; + let covered_address_len = chunk_lens.iter().sum::(); + require_operand_count( + "stage6.bytecode_read_raf.address_chunks", + log_k, + covered_address_len, + )?; + + let sparse_cycle_indices = match witness.bytecode_ra_index_chunks { + Some(chunks) if !chunks.is_empty() => Some(bytecode_cycle_indices_from_sparse_chunks( + chunks, + &chunk_lens, + log_t, + )?), + _ => None, + }; + + if let Some(bytecode_cycle_indices) = sparse_cycle_indices.or_else(|| { + bytecode_cycle_indices_from_one_hot(witness.bytecode_ra_chunks, &chunk_lens, log_t) + }) { + let outputs = bytecode_read_raf_output_plans(program, chunk_lens.len())?; + return BytecodeReadRafStage6State::new( + witness.data, + witness.bytecode_ra_chunks, + witness.bytecode_ra_index_chunks, + bytecode_cycle_indices, + chunk_lens, + store, + log_k, + log_t, + active_scale, + claim.degree, + outputs, + ) + .map(Stage6ProverInstanceState::BytecodeReadRaf); + } + + bytecode_read_raf_dense_state( + program, + claim, + witness, + store, + active_scale, + log_k, + log_t, + domain_len, + chunk_lens, + ) + .map(Stage6ProverInstanceState::Dense) +} + +#[expect(clippy::too_many_arguments)] +fn bytecode_read_raf_dense_state( + program: &'static Stage6CpuProgramPlan, + claim: &Stage6SumcheckClaimPlan, + witness: Stage6BytecodeReadRafWitness<'_, F>, + store: &Stage6ValueStore, + active_scale: F, + log_k: usize, + log_t: usize, + domain_len: usize, + chunk_lens: Vec, +) -> Result, Stage6KernelError> { + let mut factors = Vec::with_capacity(witness.bytecode_ra_chunks.len() + 1); + factors.push(bytecode_weighted_value_factor( + witness.data, + store, + log_k, + log_t, + domain_len, + )?); + factors.extend(expanded_bytecode_ra_factors( + witness.bytecode_ra_chunks, + &chunk_lens, + log_k, + log_t, + domain_len, + )?); + let term_factors = (0..factors.len()).collect::>(); + let outputs = bytecode_read_raf_output_plans(program, witness.bytecode_ra_chunks.len())?; + + Ok(DenseStage6State::new( + factors, + vec![DenseTerm { + coefficient: F::one(), + factors: term_factors, + }], + outputs, + active_scale, + claim.degree, + )) +} + +fn booleanity_state( + program: &'static Stage6CpuProgramPlan, + claim: &Stage6SumcheckClaimPlan, + inputs: &Stage6ProverInputs<'_, F>, + store: &Stage6ValueStore, + active_scale: F, +) -> Result, Stage6KernelError> { + let witness = inputs + .booleanity + .ok_or(Stage6KernelError::MissingKernelInput { + kernel: "jolt_stage6_batched", + input: "booleanity", + })?; + let log_t = stage6_trace_rounds(program)?; + if let Some(index_chunks) = witness.index_chunks { + if index_chunks.is_empty() { + return Err(Stage6KernelError::InvalidInputLength { + input: "stage6.booleanity.index_chunks", + expected: 1, + actual: 0, + }); + } + let trace_len = 1usize << log_t; + for chunk in index_chunks { + require_operand_count("stage6.booleanity.index_chunk", trace_len, chunk.len())?; + } + let log_k_chunk = + claim + .num_rounds + .checked_sub(log_t) + .ok_or(Stage6KernelError::InvalidInputLength { + input: "stage6.booleanity.input", + expected: log_t, + actual: claim.num_rounds, + })?; + let combined_r = booleanity_combined_point(store, log_t, log_k_chunk)?; + require_operand_count( + "stage6.booleanity.combined_point", + claim.num_rounds, + combined_r.len(), + )?; + let r_address = &combined_r[..log_k_chunk]; + let r_cycle = &combined_r[log_k_chunk..]; + return CoreBooleanityStage6State::new( + r_address, + r_cycle, + index_chunks.iter().map(|chunk| (*chunk).to_vec()).collect(), + store.scalar("stage6.booleanity.gamma")?, + booleanity_output_plans(program, index_chunks.len())?, + active_scale, + ) + .map(Stage6ProverInstanceState::CoreBooleanity); + } + + if witness.chunks.is_empty() { + return Err(Stage6KernelError::InvalidInputLength { + input: "stage6.booleanity.Ra", + expected: 1, + actual: 0, + }); + } + let domain_len = witness.chunks[0].len(); + let booleanity_rounds = log2_exact(domain_len, "stage6.booleanity.trace_len")?; + require_operand_count( + "stage6.booleanity.input", + booleanity_rounds, + claim.num_rounds, + )?; + for chunk in witness.chunks { + require_operand_count("stage6.booleanity.Ra", domain_len, chunk.len())?; + } + let log_k_chunk = + booleanity_rounds + .checked_sub(log_t) + .ok_or(Stage6KernelError::InvalidInputLength { + input: "stage6.booleanity.trace_len", + expected: log_t, + actual: booleanity_rounds, + })?; + let combined_r = booleanity_combined_point(store, log_t, log_k_chunk)?; + let mut eq_point = combined_r[..log_k_chunk].to_vec(); + eq_point.reverse(); + eq_point.extend(combined_r[log_k_chunk..].iter().rev().copied()); + eq_point.reverse(); + let eq = EqPolynomial::::evals(&eq_point, None); + require_operand_count("stage6.booleanity.eq", domain_len, eq.len())?; + + let gamma = store.scalar("stage6.booleanity.gamma")?; + let gamma_sq = gamma.square(); + let mut gamma_power = F::one(); + let mut gamma_powers = Vec::with_capacity(witness.chunks.len()); + for _ in 0..witness.chunks.len() { + gamma_powers.push(gamma_power); + gamma_power *= gamma_sq; + } + + BooleanityStage6State::new( + eq, + witness + .chunks + .iter() + .map(|chunk| (*chunk).to_vec()) + .collect(), + gamma_powers, + booleanity_output_plans(program, witness.chunks.len())?, + active_scale, + claim.degree, + ) + .map(Stage6ProverInstanceState::Booleanity) +} + +fn booleanity_combined_point( + store: &Stage6ValueStore, + log_t: usize, + log_k_chunk: usize, +) -> Result, Stage6KernelError> { + let stage5_point = store.point("stage6.input.stage5.instruction_read_raf.InstructionRa_0")?; + let stage5_address_len = + stage5_point + .len() + .checked_sub(log_t) + .ok_or(Stage6KernelError::InvalidInputLength { + input: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", + expected: log_t, + actual: stage5_point.len(), + })?; + if stage5_address_len < log_k_chunk { + return Err(Stage6KernelError::InvalidInputLength { + input: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", + expected: log_k_chunk + log_t, + actual: stage5_point.len(), + }); + } + + let mut stage5_addr = stage5_point[..stage5_address_len].to_vec(); + stage5_addr.reverse(); + let mut combined_r = stage5_addr[stage5_address_len - log_k_chunk..].to_vec(); + combined_r.extend(stage5_point[stage5_address_len..].iter().rev().copied()); + require_operand_count( + "stage6.booleanity.combined_point", + log_k_chunk + log_t, + combined_r.len(), + )?; + Ok(combined_r) +} + +fn hamming_booleanity_state( + program: &'static Stage6CpuProgramPlan, + claim: &Stage6SumcheckClaimPlan, + inputs: &Stage6ProverInputs<'_, F>, + store: &Stage6ValueStore, + active_scale: F, +) -> Result, Stage6KernelError> { + let witness = inputs + .hamming_booleanity + .ok_or(Stage6KernelError::MissingKernelInput { + kernel: "jolt_stage6_batched", + input: "hamming_booleanity", + })?; + let trace_rounds = log2_exact( + witness.hamming_weight.len(), + "stage6.hamming_booleanity.trace_len", + )?; + require_operand_count( + "stage6.hamming_booleanity.input", + trace_rounds, + claim.num_rounds, + )?; + let lookup_output_point = store.point("stage6.input.stage1.LookupOutput")?.to_vec(); + require_operand_count( + "stage6.input.stage1.LookupOutput", + trace_rounds, + lookup_output_point.len(), + )?; + let eq_lookup_output = EqPolynomial::::evals(&lookup_output_point, None); + require_operand_count( + "stage6.hamming_booleanity.eq", + witness.hamming_weight.len(), + eq_lookup_output.len(), + )?; + let output = program + .evals + .iter() + .find(|eval| eval.name == "stage6.hamming_booleanity.eval.HammingWeight") + .map(|eval| FactorOutput { + name: eval.name, + oracle: eval.oracle, + factor: 1, + }) + .ok_or(Stage6KernelError::MissingValue { + symbol: "stage6.hamming_booleanity.eval.HammingWeight", + })?; + + Ok(DenseStage6State::new( + vec![eq_lookup_output, witness.hamming_weight.to_vec()], + vec![ + DenseTerm { + coefficient: F::one(), + factors: vec![0, 1, 1], + }, + DenseTerm { + coefficient: -F::one(), + factors: vec![0, 1], + }, + ], + vec![output], + active_scale, + claim.degree, + )) +} + +fn inc_claim_reduction_state( + program: &'static Stage6CpuProgramPlan, + claim: &Stage6SumcheckClaimPlan, + inputs: &Stage6ProverInputs<'_, F>, + store: &Stage6ValueStore, + active_scale: F, +) -> Result, Stage6KernelError> { + let witness = inputs + .inc_claim_reduction + .ok_or(Stage6KernelError::MissingKernelInput { + kernel: "jolt_stage6_batched", + input: "inc_claim_reduction", + })?; + let trace_rounds = log2_exact( + witness.ram_inc.len(), + "stage6.inc_claim_reduction.trace_len", + )?; + require_operand_count( + "stage6.inc_claim_reduction.RdInc", + witness.ram_inc.len(), + witness.rd_inc.len(), + )?; + require_operand_count( + "stage6.inc_claim_reduction.input", + trace_rounds, + claim.num_rounds, + )?; + + let ram_inc_stage2 = suffix_point( + store.point("stage6.input.stage2.ram_read_write.RamInc")?, + trace_rounds, + "stage6.input.stage2.ram_read_write.RamInc", + )?; + let ram_inc_stage4 = suffix_point( + store.point("stage6.input.stage4.ram_val_check.RamInc")?, + trace_rounds, + "stage6.input.stage4.ram_val_check.RamInc", + )?; + let rd_inc_stage4 = suffix_point( + store.point("stage6.input.stage4.registers_read_write.RdInc")?, + trace_rounds, + "stage6.input.stage4.registers_read_write.RdInc", + )?; + let rd_inc_stage5 = suffix_point( + store.point("stage6.input.stage5.registers_val_evaluation.RdInc")?, + trace_rounds, + "stage6.input.stage5.registers_val_evaluation.RdInc", + )?; + let gamma = store.scalar("stage6.inc_claim_reduction.gamma")?; + let gamma2 = gamma.square(); + + let mut eq_ram_combined = EqPolynomial::::evals(ram_inc_stage2, None); + let eq_ram_stage4 = EqPolynomial::::evals(ram_inc_stage4, None); + let mut eq_rd_combined = EqPolynomial::::evals(rd_inc_stage4, None); + let eq_rd_stage5 = EqPolynomial::::evals(rd_inc_stage5, None); + require_operand_count( + "stage6.inc_claim_reduction.eq_ram", + witness.ram_inc.len(), + eq_ram_combined.len(), + )?; + require_operand_count( + "stage6.inc_claim_reduction.eq_rd", + witness.rd_inc.len(), + eq_rd_combined.len(), + )?; + for (combined, stage4) in eq_ram_combined.iter_mut().zip(eq_ram_stage4) { + *combined += gamma * stage4; + } + for (combined, stage5) in eq_rd_combined.iter_mut().zip(eq_rd_stage5) { + *combined += gamma * stage5; + } + + Ok(DenseStage6State::new( + vec![ + eq_ram_combined, + witness.ram_inc.to_vec(), + eq_rd_combined, + witness.rd_inc.to_vec(), + ], + vec![ + DenseTerm { + coefficient: F::one(), + factors: vec![0, 1], + }, + DenseTerm { + coefficient: gamma2, + factors: vec![2, 3], + }, + ], + vec![ + factor_output_by_name(program, "stage6.inc_claim_reduction.eval.RamInc", 1)?, + factor_output_by_name(program, "stage6.inc_claim_reduction.eval.RdInc", 3)?, + ], + active_scale, + claim.degree, + )) +} + +fn ram_ra_virtual_state( + program: &'static Stage6CpuProgramPlan, + claim: &Stage6SumcheckClaimPlan, + inputs: &Stage6ProverInputs<'_, F>, + store: &Stage6ValueStore, + active_scale: F, +) -> Result, Stage6KernelError> { + let witness = inputs + .ram_ra_virtual + .ok_or(Stage6KernelError::MissingKernelInput { + kernel: "jolt_stage6_batched", + input: "ram_ra_virtual", + })?; + if witness.ram_ra_chunks.is_empty() { + return Err(Stage6KernelError::InvalidInputLength { + input: "stage6.ram_ra_virtual.RamRa", + expected: 1, + actual: 0, + }); + } + let trace_len = witness.ram_ra_chunks[0].len(); + let trace_rounds = log2_exact(trace_len, "stage6.ram_ra_virtual.trace_len")?; + require_operand_count( + "stage6.ram_ra_virtual.input", + trace_rounds, + claim.num_rounds, + )?; + for chunk in witness.ram_ra_chunks { + require_operand_count("stage6.ram_ra_virtual.RamRa", trace_len, chunk.len())?; + } + + let input_point = store.point("stage6.input.stage5.ram_ra_claim_reduction.RamRa")?; + let r_cycle = suffix_point( + input_point, + trace_rounds, + "stage6.input.stage5.ram_ra_claim_reduction.RamRa", + )?; + let eq_cycle = EqPolynomial::::evals(r_cycle, None); + require_operand_count("stage6.ram_ra_virtual.eq", trace_len, eq_cycle.len())?; + + let mut factors = Vec::with_capacity(witness.ram_ra_chunks.len() + 1); + factors.push(eq_cycle); + factors.extend(witness.ram_ra_chunks.iter().map(|chunk| (*chunk).to_vec())); + let term_factors = (0..factors.len()).collect::>(); + let outputs = ram_ra_virtual_output_plans(program, witness.ram_ra_chunks.len())?; + + Ok(DenseStage6State::new( + factors, + vec![DenseTerm { + coefficient: F::one(), + factors: term_factors, + }], + outputs, + active_scale, + claim.degree, + )) +} + +fn instruction_ra_virtual_state( + program: &'static Stage6CpuProgramPlan, + claim: &Stage6SumcheckClaimPlan, + inputs: &Stage6ProverInputs<'_, F>, + store: &Stage6ValueStore, + active_scale: F, +) -> Result, Stage6KernelError> { + let witness = inputs + .instruction_ra_virtual + .ok_or(Stage6KernelError::MissingKernelInput { + kernel: "jolt_stage6_batched", + input: "instruction_ra_virtual", + })?; + if witness.instruction_ra_chunks.is_empty() + || witness.virtual_count == 0 + || witness.instruction_ra_chunks.len() % witness.virtual_count != 0 + { + return Err(Stage6KernelError::InvalidInputLength { + input: "stage6.instruction_ra_virtual.InstructionRa", + expected: witness.virtual_count, + actual: witness.instruction_ra_chunks.len(), + }); + } + let trace_len = witness.instruction_ra_chunks[0].len(); + let trace_rounds = log2_exact(trace_len, "stage6.instruction_ra_virtual.trace_len")?; + require_operand_count( + "stage6.instruction_ra_virtual.input", + trace_rounds, + claim.num_rounds, + )?; + for chunk in witness.instruction_ra_chunks { + require_operand_count( + "stage6.instruction_ra_virtual.InstructionRa", + trace_len, + chunk.len(), + )?; + } + + let input_point = store.point("stage6.input.stage5.instruction_read_raf.InstructionRa_0")?; + let r_cycle = suffix_point( + input_point, + trace_rounds, + "stage6.input.stage5.instruction_read_raf.InstructionRa_0", + )?; + let eq_cycle = EqPolynomial::::evals(r_cycle, None); + require_operand_count( + "stage6.instruction_ra_virtual.eq", + trace_len, + eq_cycle.len(), + )?; + + let mut factors = Vec::with_capacity(witness.instruction_ra_chunks.len() + 1); + factors.push(eq_cycle); + factors.extend( + witness + .instruction_ra_chunks + .iter() + .map(|chunk| (*chunk).to_vec()), + ); + + let chunks_per_virtual = witness.instruction_ra_chunks.len() / witness.virtual_count; + let gamma = store.scalar("stage6.instruction_ra_virtual.gamma")?; + let mut gamma_power = F::one(); + let mut terms = Vec::with_capacity(witness.virtual_count); + for virtual_index in 0..witness.virtual_count { + let start = 1 + virtual_index * chunks_per_virtual; + let end = start + chunks_per_virtual; + let mut factors = Vec::with_capacity(chunks_per_virtual + 1); + factors.push(0); + factors.extend(start..end); + terms.push(DenseTerm { + coefficient: gamma_power, + factors, + }); + gamma_power *= gamma; + } + let outputs = + instruction_ra_virtual_output_plans(program, witness.instruction_ra_chunks.len())?; + + Ok(DenseStage6State::new( + factors, + terms, + outputs, + active_scale, + claim.degree, + )) +} + +fn evaluate_stage6_field_expr( + expr: &Stage6FieldExprPlan, + operands: &[F], +) -> Result { + match expr.formula { + "opening_eval" => single_operand(expr.symbol, operands), + "field.add" => { + require_operand_count(expr.symbol, 2, operands.len())?; + Ok(operands[0] + operands[1]) + } + "field.sub" => { + require_operand_count(expr.symbol, 2, operands.len())?; + Ok(operands[0] - operands[1]) + } + "field.mul" => { + require_operand_count(expr.symbol, 2, operands.len())?; + Ok(operands[0] * operands[1]) + } + "field.neg" => { + require_operand_count(expr.symbol, 1, operands.len())?; + Ok(-operands[0]) + } + formula => { + if let Some(exponent) = formula.strip_prefix("field.pow:") { + require_operand_count(expr.symbol, 1, operands.len())?; + let exponent = exponent.parse::().map_err(|_| { + Stage6KernelError::UnsupportedFieldExpr { + symbol: expr.symbol, + formula, + } + })?; + return Ok(pow_field(operands[0], exponent)); + } + Err(Stage6KernelError::UnsupportedFieldExpr { + symbol: expr.symbol, + formula, + }) + } + } +} + +fn pow_field(base: F, mut exponent: usize) -> F { + let mut result = F::one(); + let mut power = base; + while exponent != 0 { + if exponent & 1 == 1 { + result *= power; + } + power = power.square(); + exponent >>= 1; + } + result +} + +fn single_operand(symbol: &'static str, operands: &[F]) -> Result { + require_operand_count(symbol, 1, operands.len())?; + Ok(operands[0]) +} + +fn require_operand_count( + input: &'static str, + expected: usize, + actual: usize, +) -> Result<(), Stage6KernelError> { + if expected == actual { + Ok(()) + } else { + Err(Stage6KernelError::InvalidInputLength { + input, + expected, + actual, + }) + } +} + +fn append_opening_claims( + program: &'static Stage6CpuProgramPlan, + store: &mut Stage6ValueStore, + transcript: &mut T, + evals: &[Stage6NamedEval], +) -> Result>, Stage6KernelError> +where + F: Field, + T: Transcript, +{ + if program.opening_batches.is_empty() { + for eval in evals { + append_labeled_scalar(transcript, "opening_claim", &eval.value); + } + return Ok(Vec::new()); + } + let _ = store.evaluate_available_points(program)?; + let mut opening_claims = Vec::new(); + let mut seen = program + .opening_inputs + .iter() + .filter_map(|input| { + store + .try_point(input.symbol) + .map(|point| (input.claim_kind, input.oracle, point.to_vec())) + }) + .collect::>(); + for batch in program.opening_batches { + for symbol in batch.claim_operands { + let claim = + find_opening_claim(program, symbol).ok_or(Stage6KernelError::MissingClaim { + batch: batch.symbol, + claim: symbol, + })?; + let point = store.point(claim.point_source)?.to_vec(); + let duplicate = seen.iter().any(|(kind, oracle, seen_point)| { + *kind == claim.claim_kind && *oracle == claim.oracle && seen_point == &point + }); + let value = store.scalar(claim.eval_source)?; + if !duplicate { + append_labeled_scalar(transcript, "opening_claim", &value); + seen.push((claim.claim_kind, claim.oracle, point.clone())); + } + opening_claims.push(Stage6OpeningClaimValue { + symbol: claim.symbol, + oracle: claim.oracle, + domain: claim.domain, + claim_kind: claim.claim_kind, + point: point.clone(), + eval: value, + }); + } + } + Ok(opening_claims) +} + +fn find_opening_claim<'a>( + program: &'a Stage6CpuProgramPlan, + symbol: &str, +) -> Option<&'a Stage6OpeningClaimPlan> { + program + .opening_claims + .iter() + .find(|claim| claim.symbol == symbol) +} + +fn stage6_trace_rounds(program: &'static Stage6CpuProgramPlan) -> Result { + program + .instance_results + .iter() + .find(|instance| instance.relation == "jolt.stage6.hamming_booleanity") + .map(|instance| instance.num_rounds) + .ok_or(Stage6KernelError::MissingValue { + symbol: "stage6.hamming_booleanity.instance", + }) +} + +fn bytecode_gamma_powers(gamma: F) -> [F; 8] { + let mut powers = [F::one(); 8]; + for index in 1..powers.len() { + powers[index] = powers[index - 1] * gamma; + } + powers +} + +fn bytecode_stage_cycle_points( + store: &Stage6ValueStore, + log_t: usize, +) -> Result<[Vec; 5], Stage6KernelError> { + Ok([ + suffix_point( + store.point("stage6.input.stage1.Imm")?, + log_t, + "stage6.input.stage1.Imm", + )? + .to_vec(), + suffix_point( + store.point("stage6.input.stage2.OpFlagJump")?, + log_t, + "stage6.input.stage2.OpFlagJump", + )? + .to_vec(), + suffix_point( + store.point("stage6.input.stage3.spartan_shift.UnexpandedPC")?, + log_t, + "stage6.input.stage3.spartan_shift.UnexpandedPC", + )? + .to_vec(), + suffix_point( + store.point("stage6.input.stage4.Rs1Ra")?, + log_t, + "stage6.input.stage4.Rs1Ra", + )? + .to_vec(), + suffix_point( + store.point("stage6.input.stage5.registers_val_evaluation.RdWa")?, + log_t, + "stage6.input.stage5.registers_val_evaluation.RdWa", + )? + .to_vec(), + ]) +} + +fn bytecode_stage_value_evals( + data: Stage6BytecodeReadRafData<'_, F>, + store: &Stage6ValueStore, + r_address: &[F], + log_t: usize, +) -> Result<[F; 5], Stage6KernelError> { + let expected_len = 1usize.checked_shl(r_address.len() as u32).ok_or( + Stage6KernelError::InvalidInputLength { + input: "stage6.bytecode_read_raf.entries", + expected: usize::BITS as usize, + actual: r_address.len(), + }, + )?; + require_operand_count( + "stage6.bytecode_read_raf.entries", + expected_len, + data.entries.len(), + )?; + if data.entry_bytecode_index >= expected_len { + return Err(Stage6KernelError::InvalidInputLength { + input: "stage6.bytecode_read_raf.entry_bytecode_index", + expected: expected_len, + actual: data.entry_bytecode_index + 1, + }); + } + + let stage1_gamma = store.scalar("stage6.bytecode_read_raf.stage1_gamma")?; + let stage2_gamma = store.scalar("stage6.bytecode_read_raf.stage2_gamma")?; + let stage3_gamma = store.scalar("stage6.bytecode_read_raf.stage3_gamma")?; + let stage4_gamma = store.scalar("stage6.bytecode_read_raf.stage4_gamma")?; + let stage5_gamma = store.scalar("stage6.bytecode_read_raf.stage5_gamma")?; + let stage1_gamma_powers = field_powers(stage1_gamma, 16); + let stage2_gamma_powers = field_powers(stage2_gamma, 4); + let stage3_gamma_powers = field_powers(stage3_gamma, 9); + let stage4_gamma_powers = field_powers(stage4_gamma, 3); + let stage5_gamma_powers = field_powers(stage5_gamma, data.num_lookup_tables + 2); + + let stage4_register_point = register_prefix_point(store, "stage6.input.stage4.Rs1Ra", log_t)?; + let stage5_register_point = register_prefix_point( + store, + "stage6.input.stage5.registers_val_evaluation.RdWa", + log_t, + )?; + + let mut evals = [F::zero(); 5]; + for (index, entry) in data.entries.iter().enumerate() { + let eq = indexed_boolean_eq(index, r_address)?; + let values = bytecode_entry_stage_values( + entry, + data.num_lookup_tables, + stage4_register_point, + stage5_register_point, + &stage1_gamma_powers, + &stage2_gamma_powers, + &stage3_gamma_powers, + &stage4_gamma_powers, + &stage5_gamma_powers, + )?; + for stage in 0..evals.len() { + evals[stage] += eq * values[stage]; + } + } + Ok(evals) +} + +fn bytecode_weighted_value_factor( + data: Stage6BytecodeReadRafData<'_, F>, + store: &Stage6ValueStore, + log_k: usize, + log_t: usize, + domain_len: usize, +) -> Result, Stage6KernelError> { + let gamma = store.scalar("stage6.bytecode_read_raf.gamma")?; + let gamma_powers = bytecode_gamma_powers(gamma); + let stage_cycle_points = bytecode_stage_cycle_points(store, log_t)?; + + let stage1_gamma = store.scalar("stage6.bytecode_read_raf.stage1_gamma")?; + let stage2_gamma = store.scalar("stage6.bytecode_read_raf.stage2_gamma")?; + let stage3_gamma = store.scalar("stage6.bytecode_read_raf.stage3_gamma")?; + let stage4_gamma = store.scalar("stage6.bytecode_read_raf.stage4_gamma")?; + let stage5_gamma = store.scalar("stage6.bytecode_read_raf.stage5_gamma")?; + let stage1_gamma_powers = field_powers(stage1_gamma, 16); + let stage2_gamma_powers = field_powers(stage2_gamma, 4); + let stage3_gamma_powers = field_powers(stage3_gamma, 9); + let stage4_gamma_powers = field_powers(stage4_gamma, 3); + let stage5_gamma_powers = field_powers(stage5_gamma, data.num_lookup_tables + 2); + let stage4_register_point = register_prefix_point(store, "stage6.input.stage4.Rs1Ra", log_t)?; + let stage5_register_point = register_prefix_point( + store, + "stage6.input.stage5.registers_val_evaluation.RdWa", + log_t, + )?; + let stage_values = data + .entries + .iter() + .map(|entry| { + bytecode_entry_stage_values( + entry, + data.num_lookup_tables, + stage4_register_point, + stage5_register_point, + &stage1_gamma_powers, + &stage2_gamma_powers, + &stage3_gamma_powers, + &stage4_gamma_powers, + &stage5_gamma_powers, + ) + }) + .collect::, _>>()?; + + (0..domain_len) + .map(|row| { + let (address_bits, cycle_bits) = normalized_bytecode_row_bits::(row, log_k, log_t)?; + let address_index = bits_to_index(&address_bits); + let int_eval = identity_polynomial_eval(&address_bits); + let int_contrib = [ + gamma_powers[5] * int_eval, + F::zero(), + gamma_powers[4] * int_eval, + F::zero(), + F::zero(), + ]; + let mut value = F::zero(); + for stage in 0..stage_values[address_index].len() { + value += (stage_values[address_index][stage] + int_contrib[stage]) + * EqPolynomial::::mle(&stage_cycle_points[stage], &cycle_bits) + * gamma_powers[stage]; + } + if address_index == data.entry_bytecode_index + && cycle_bits.iter().all(|bit| *bit == F::zero()) + { + value += gamma_powers[7]; + } + Ok(value) + }) + .collect() +} + +fn expanded_bytecode_ra_factors( + chunks: &[&[F]], + chunk_lens: &[usize], + log_k: usize, + log_t: usize, + domain_len: usize, +) -> Result>, Stage6KernelError> { + let mut factors = Vec::with_capacity(chunks.len()); + let mut offset = 0usize; + for (chunk, &chunk_len) in chunks.iter().zip(chunk_lens) { + let factor = (0..domain_len) + .map(|row| { + let (address_bits, cycle_bits) = + normalized_bytecode_row_bits::(row, log_k, log_t)?; + let mut chunk_bits = address_bits[offset..offset + chunk_len].to_vec(); + chunk_bits.extend(cycle_bits); + let index = bits_to_index(&chunk_bits); + chunk + .get(index) + .copied() + .ok_or(Stage6KernelError::InvalidInputLength { + input: "stage6.bytecode_read_raf.BytecodeRa", + expected: index + 1, + actual: chunk.len(), + }) + }) + .collect::, _>>()?; + factors.push(factor); + offset += chunk_len; + } + Ok(factors) +} + +fn bytecode_cycle_indices_from_one_hot( + chunks: &[&[F]], + chunk_lens: &[usize], + log_t: usize, +) -> Option> { + let trace_len = 1usize.checked_shl(log_t as u32)?; + let mut indices = vec![0usize; trace_len]; + let mut remaining_address_bits = chunk_lens.iter().sum::(); + for (chunk, &chunk_len) in chunks.iter().zip(chunk_lens) { + remaining_address_bits = remaining_address_bits.checked_sub(chunk_len)?; + let chunk_domain = 1usize.checked_shl(chunk_len as u32)?; + if chunk.len() != chunk_domain.checked_mul(trace_len)? { + return None; + } + for cycle in 0..trace_len { + let mut selected = None; + for chunk_value in 0..chunk_domain { + let value = chunk[chunk_value * trace_len + cycle]; + if value == F::one() { + if selected.replace(chunk_value).is_some() { + return None; + } + } else if value != F::zero() { + return None; + } + } + let selected = selected?; + indices[cycle] |= selected << remaining_address_bits; + } + } + Some(indices) +} + +fn bytecode_cycle_indices_from_sparse_chunks( + chunks: &[&[Option]], + chunk_lens: &[usize], + log_t: usize, +) -> Result, Stage6KernelError> { + validate_bytecode_ra_index_chunks(chunks, chunk_lens, log_t)?; + let trace_len = + 1usize + .checked_shl(log_t as u32) + .ok_or(Stage6KernelError::InvalidInputLength { + input: "stage6.bytecode_read_raf.BytecodeRaIndex", + expected: usize::BITS as usize, + actual: log_t, + })?; + let mut indices = vec![0usize; trace_len]; + let mut remaining_address_bits = chunk_lens.iter().sum::(); + for (chunk, &chunk_len) in chunks.iter().zip(chunk_lens) { + remaining_address_bits = remaining_address_bits.checked_sub(chunk_len).ok_or( + Stage6KernelError::InvalidInputLength { + input: "stage6.bytecode_read_raf.BytecodeRaIndex", + expected: chunk_len, + actual: remaining_address_bits, + }, + )?; + for (cycle, index) in chunk.iter().enumerate() { + let Some(index) = *index else { + return Err(Stage6KernelError::InvalidProof { + driver: Stage6Relation::BytecodeReadRaf.symbol(), + reason: "bytecode read RAF sparse index is missing", + }); + }; + indices[cycle] |= usize::from(index) << remaining_address_bits; + } + } + Ok(indices) +} + +fn validate_bytecode_ra_index_chunks( + chunks: &[&[Option]], + chunk_lens: &[usize], + log_t: usize, +) -> Result<(), Stage6KernelError> { + require_operand_count( + "stage6.bytecode_read_raf.BytecodeRaIndex", + chunk_lens.len(), + chunks.len(), + )?; + let trace_len = + 1usize + .checked_shl(log_t as u32) + .ok_or(Stage6KernelError::InvalidInputLength { + input: "stage6.bytecode_read_raf.BytecodeRaIndex", + expected: usize::BITS as usize, + actual: log_t, + })?; + for (chunk, &chunk_len) in chunks.iter().zip(chunk_lens) { + require_operand_count( + "stage6.bytecode_read_raf.BytecodeRaIndex", + trace_len, + chunk.len(), + )?; + let chunk_domain = + 1usize + .checked_shl(chunk_len as u32) + .ok_or(Stage6KernelError::InvalidInputLength { + input: "stage6.bytecode_read_raf.BytecodeRaIndex", + expected: usize::BITS as usize, + actual: chunk_len, + })?; + for index in *chunk { + let Some(index) = *index else { + return Err(Stage6KernelError::InvalidProof { + driver: Stage6Relation::BytecodeReadRaf.symbol(), + reason: "bytecode read RAF sparse index is missing", + }); + }; + let index = usize::from(index); + if index >= chunk_domain { + return Err(Stage6KernelError::InvalidInputLength { + input: "stage6.bytecode_read_raf.BytecodeRaIndex", + expected: chunk_domain, + actual: index + 1, + }); + } + } + } + Ok(()) +} + +fn normalized_bytecode_row_bits( + row: usize, + log_k: usize, + log_t: usize, +) -> Result<(Vec, Vec), Stage6KernelError> { + let mut raw_bits = index_bits(row, log_k + log_t)?; + raw_bits.reverse(); + let mut cycle_bits = raw_bits.split_off(log_k); + raw_bits.reverse(); + cycle_bits.reverse(); + Ok((raw_bits, cycle_bits)) +} + +#[expect( + clippy::too_many_arguments, + reason = "bytecode stage evaluator mirrors generated stage challenge layout" +)] +fn bytecode_entry_stage_values( + entry: &Stage6BytecodeEntry, + num_lookup_tables: usize, + stage4_register_point: &[F], + stage5_register_point: &[F], + stage1_gamma_powers: &[F], + stage2_gamma_powers: &[F], + stage3_gamma_powers: &[F], + stage4_gamma_powers: &[F], + stage5_gamma_powers: &[F], +) -> Result<[F; 5], Stage6KernelError> { + let mut stage1 = entry.address + entry.imm * stage1_gamma_powers[1]; + for (flag, gamma) in entry + .circuit_flags + .iter() + .zip(stage1_gamma_powers.iter().skip(2)) + { + if *flag { + stage1 += *gamma; + } + } + + let mut stage2 = F::zero(); + if entry.circuit_flags[5] { + stage2 += stage2_gamma_powers[0]; + } + if entry.is_branch { + stage2 += stage2_gamma_powers[1]; + } + if entry.circuit_flags[6] { + stage2 += stage2_gamma_powers[2]; + } + if entry.circuit_flags[7] { + stage2 += stage2_gamma_powers[3]; + } + + let mut stage3 = entry.imm + entry.address * stage3_gamma_powers[1]; + if entry.left_is_rs1 { + stage3 += stage3_gamma_powers[2]; + } + if entry.left_is_pc { + stage3 += stage3_gamma_powers[3]; + } + if entry.right_is_rs2 { + stage3 += stage3_gamma_powers[4]; + } + if entry.right_is_imm { + stage3 += stage3_gamma_powers[5]; + } + if entry.is_noop { + stage3 += stage3_gamma_powers[6]; + } + if entry.circuit_flags[7] { + stage3 += stage3_gamma_powers[7]; + } + if entry.circuit_flags[12] { + stage3 += stage3_gamma_powers[8]; + } + + let stage4 = register_eq(entry.rd, stage4_register_point, "stage6.bytecode.entry.rd")? + * stage4_gamma_powers[0] + + register_eq( + entry.rs1, + stage4_register_point, + "stage6.bytecode.entry.rs1", + )? * stage4_gamma_powers[1] + + register_eq( + entry.rs2, + stage4_register_point, + "stage6.bytecode.entry.rs2", + )? * stage4_gamma_powers[2]; + + let mut stage5 = register_eq(entry.rd, stage5_register_point, "stage6.bytecode.entry.rd")? + * stage5_gamma_powers[0]; + if !entry.is_interleaved { + stage5 += stage5_gamma_powers[1]; + } + if let Some(table) = entry.lookup_table { + if table >= num_lookup_tables { + return Err(Stage6KernelError::InvalidInputLength { + input: "stage6.bytecode.entry.lookup_table", + expected: num_lookup_tables, + actual: table + 1, + }); + } + stage5 += stage5_gamma_powers[2 + table]; + } + + Ok([stage1, stage2, stage3, stage4, stage5]) +} + +fn register_eq( + index: Option, + point: &[F], + input: &'static str, +) -> Result { + let Some(index) = index else { + return Ok(F::zero()); + }; + let register_count = + 1usize + .checked_shl(point.len() as u32) + .ok_or(Stage6KernelError::InvalidInputLength { + input, + expected: usize::BITS as usize, + actual: point.len(), + })?; + if index >= register_count { + return Err(Stage6KernelError::InvalidInputLength { + input, + expected: register_count, + actual: index + 1, + }); + } + indexed_boolean_eq(index, point) +} + +fn indexed_boolean_eq(index: usize, point: &[F]) -> Result { + let bits = index_bits(index, point.len())?; + Ok(EqPolynomial::::mle(&bits, point)) +} + +fn index_bits(index: usize, len: usize) -> Result, Stage6KernelError> { + if len >= usize::BITS as usize { + return Err(Stage6KernelError::InvalidInputLength { + input: "stage6.index_bits", + expected: usize::BITS as usize - 1, + actual: len, + }); + } + let limit = 1usize << len; + if index >= limit { + return Err(Stage6KernelError::InvalidInputLength { + input: "stage6.index_bits.index", + expected: limit, + actual: index + 1, + }); + } + Ok((0..len) + .map(|bit| F::from_u64(((index >> (len - 1 - bit)) & 1) as u64)) + .collect()) +} + +fn bits_to_index(bits: &[F]) -> usize { + bits.iter().fold(0usize, |index, bit| { + let bit_value = usize::from(*bit != F::zero()); + (index << 1) | bit_value + }) +} + +fn field_powers(base: F, count: usize) -> Vec { + let mut powers = Vec::with_capacity(count); + let mut power = F::one(); + for _ in 0..count { + powers.push(power); + power *= base; + } + powers +} + +fn identity_polynomial_eval(point: &[F]) -> F { + point + .iter() + .enumerate() + .map(|(index, value)| value.mul_pow_2(point.len() - 1 - index)) + .sum() +} + +fn register_prefix_point<'a, F: Field>( + store: &'a Stage6ValueStore, + symbol: &'static str, + log_t: usize, +) -> Result<&'a [F], Stage6KernelError> { + let point = store.point(symbol)?; + let register_len = + point + .len() + .checked_sub(log_t) + .ok_or(Stage6KernelError::InvalidInputLength { + input: symbol, + expected: log_t, + actual: point.len(), + })?; + prefix_point(point, register_len, symbol) +} + +fn normalize_bytecode_read_raf_point( + program: &'static Stage6CpuProgramPlan, + point: &[F], +) -> Result, Stage6KernelError> { + let log_t = stage6_trace_rounds(program)?; + let log_k = point + .len() + .checked_sub(log_t) + .ok_or(Stage6KernelError::InvalidInputLength { + input: "stage6.bytecode_read_raf.point", + expected: log_t, + actual: point.len(), + })?; + let mut normalized = point.to_vec(); + normalized[..log_k].reverse(); + normalized[log_k..].reverse(); + Ok(normalized) +} + +fn normalize_stage6_booleanity_point( + program: &'static Stage6CpuProgramPlan, + point: &[F], +) -> Result, Stage6KernelError> { + let log_t = stage6_trace_rounds(program)?; + let log_k = point + .len() + .checked_sub(log_t) + .ok_or(Stage6KernelError::InvalidInputLength { + input: "stage6.booleanity.point", + expected: log_t, + actual: point.len(), + })?; + let mut normalized = point.to_vec(); + normalized[..log_k].reverse(); + normalized[log_k..].reverse(); + Ok(normalized) +} + +fn normalize_instruction_read_raf_point( + point: &[F], +) -> Result, Stage6KernelError> { + const LOG_K: usize = 128; + if point.len() < LOG_K { + return Err(Stage6KernelError::InvalidInputLength { + input: "stage6.instruction_read_raf.point", + expected: LOG_K, + actual: point.len(), + }); + } + let mut normalized = point.to_vec(); + normalized[LOG_K..].reverse(); + Ok(normalized) +} + +fn reverse_slice(values: &[F]) -> Vec { + values.iter().rev().copied().collect() +} + +fn prefix_point<'a, F: Field>( + point: &'a [F], + length: usize, + input: &'static str, +) -> Result<&'a [F], Stage6KernelError> { + point + .get(..length) + .filter(|prefix| prefix.len() == length) + .ok_or(Stage6KernelError::InvalidInputLength { + input, + expected: length, + actual: point.len(), + }) +} + +fn suffix_point<'a, F: Field>( + point: &'a [F], + length: usize, + input: &'static str, +) -> Result<&'a [F], Stage6KernelError> { + point + .get(point.len().saturating_sub(length)..) + .filter(|suffix| suffix.len() == length) + .ok_or(Stage6KernelError::InvalidInputLength { + input, + expected: length, + actual: point.len(), + }) +} + +fn log2_exact(value: usize, input: &'static str) -> Result { + if value != 0 && value.is_power_of_two() { + Ok(value.trailing_zeros() as usize) + } else { + Err(Stage6KernelError::InvalidInputLength { + input, + expected: value.next_power_of_two(), + actual: value, + }) + } +} + +fn polynomial_degree(poly: &UnivariatePoly) -> usize { + poly.coefficients() + .iter() + .rposition(|coefficient| *coefficient != F::zero()) + .unwrap_or(0) +} + +fn append_compressed_univariate_poly( + transcript: &mut T, + label: &'static str, + poly: &UnivariatePoly, +) where + F: Field, + T: Transcript, +{ + let compressed = poly.compress(); + transcript.append(&LabelWithCount( + label.as_bytes(), + compressed.coeffs_except_linear_term().len() as u64, + )); + for coefficient in compressed.coeffs_except_linear_term() { + transcript.append(coefficient); + } +} + +fn append_labeled_scalar(transcript: &mut T, label: &'static str, scalar: &F) +where + F: Field, + T: Transcript, +{ + transcript.append(&Label(label.as_bytes())); + transcript.append(scalar); +} + +fn named_eval(name: &'static str, oracle: &'static str, value: F) -> Stage6NamedEval { + Stage6NamedEval { + name, + oracle, + value, + } +} + +fn factor_output_by_name( + program: &'static Stage6CpuProgramPlan, + name: &'static str, + factor: usize, +) -> Result { + program + .evals + .iter() + .find(|eval| eval.name == name) + .map(|eval| FactorOutput { + name: eval.name, + oracle: eval.oracle, + factor, + }) + .ok_or(Stage6KernelError::MissingValue { symbol: name }) +} + +fn ram_ra_virtual_output_plans( + program: &'static Stage6CpuProgramPlan, + chunk_count: usize, +) -> Result, Stage6KernelError> { + indexed_output_plans_by_prefix(program, "stage6.ram_ra_virtual.eval.RamRa_", chunk_count, 1) +} + +fn bytecode_read_raf_output_plans( + program: &'static Stage6CpuProgramPlan, + chunk_count: usize, +) -> Result, Stage6KernelError> { + indexed_output_plans_by_prefix( + program, + "stage6.bytecode_read_raf.eval.BytecodeRa_", + chunk_count, + 1, + ) +} + +fn booleanity_output_plans( + program: &'static Stage6CpuProgramPlan, + chunk_count: usize, +) -> Result, Stage6KernelError> { + let mut evals = program + .evals + .iter() + .filter(|eval| { + eval.name + .starts_with("stage6.booleanity.eval.InstructionRa_") + || eval.name.starts_with("stage6.booleanity.eval.BytecodeRa_") + || eval.name.starts_with("stage6.booleanity.eval.RamRa_") + }) + .collect::>(); + evals.sort_by_key(|eval| eval.index); + if evals.len() != chunk_count { + return Err(Stage6KernelError::InvalidInputLength { + input: "stage6.booleanity.eval", + expected: chunk_count, + actual: evals.len(), + }); + } + evals + .into_iter() + .enumerate() + .map(|(index, eval)| { + if eval.index != index { + return Err(Stage6KernelError::InvalidProof { + driver: "stage6.booleanity.eval", + reason: "non-contiguous indexed eval", + }); + } + Ok(FactorOutput { + name: eval.name, + oracle: eval.oracle, + factor: index + 1, + }) + }) + .collect() +} + +fn instruction_ra_virtual_output_plans( + program: &'static Stage6CpuProgramPlan, + chunk_count: usize, +) -> Result, Stage6KernelError> { + indexed_output_plans_by_prefix( + program, + "stage6.instruction_ra_virtual.eval.InstructionRa_", + chunk_count, + 1, + ) +} + +fn indexed_output_plans_by_prefix( + program: &'static Stage6CpuProgramPlan, + prefix: &'static str, + count: usize, + first_factor: usize, +) -> Result, Stage6KernelError> { + let mut outputs = vec![None; count]; + for eval in program.evals { + let Some(suffix) = eval.name.strip_prefix(prefix) else { + continue; + }; + let index = suffix + .parse::() + .map_err(|_| Stage6KernelError::InvalidProof { + driver: prefix, + reason: "invalid indexed eval suffix", + })?; + if index >= count || outputs[index].is_some() { + return Err(Stage6KernelError::InvalidProof { + driver: prefix, + reason: "invalid indexed eval", + }); + } + outputs[index] = Some(FactorOutput { + name: eval.name, + oracle: eval.oracle, + factor: first_factor + index, + }); + } + outputs + .into_iter() + .map(|output| output.ok_or(Stage6KernelError::MissingValue { symbol: prefix })) + .collect() +} + +fn eval_by_name( + evals: &[Stage6NamedEval], + name: &'static str, +) -> Result { + evals + .iter() + .find(|eval| eval.name == name) + .map(|eval| eval.value) + .ok_or(Stage6KernelError::MissingValue { symbol: name }) +} + +fn indexed_evals_by_prefix_any( + evals: &[Stage6NamedEval], + prefix: &'static str, +) -> Result, Stage6KernelError> { + let mut indexed_values = Vec::new(); + for eval in evals { + let Some(suffix) = eval.name.strip_prefix(prefix) else { + continue; + }; + let index = suffix + .parse::() + .map_err(|_| Stage6KernelError::InvalidProof { + driver: prefix, + reason: "invalid indexed eval suffix", + })?; + if indexed_values + .iter() + .any(|(existing_index, _)| *existing_index == index) + { + return Err(Stage6KernelError::InvalidProof { + driver: prefix, + reason: "duplicate indexed eval", + }); + } + indexed_values.push((index, eval.value)); + } + if indexed_values.is_empty() { + return Err(Stage6KernelError::MissingValue { symbol: prefix }); + } + indexed_values.sort_by_key(|(index, _)| *index); + for (expected, (actual, _)) in indexed_values.iter().enumerate() { + if *actual != expected { + return Err(Stage6KernelError::InvalidProof { + driver: prefix, + reason: "non-contiguous indexed eval", + }); + } + } + Ok(indexed_values.into_iter().map(|(_, value)| value).collect()) +} + +fn booleanity_evals(evals: &[Stage6NamedEval]) -> Result, Stage6KernelError> { + let mut values = indexed_evals_by_prefix_any(evals, "stage6.booleanity.eval.InstructionRa_")?; + values.extend(indexed_evals_by_prefix_any( + evals, + "stage6.booleanity.eval.BytecodeRa_", + )?); + values.extend(indexed_evals_by_prefix_any( + evals, + "stage6.booleanity.eval.RamRa_", + )?); + Ok(values) +} + +fn claim_relation( + program: &'static Stage6CpuProgramPlan, + claim: &Stage6SumcheckClaimPlan, +) -> Result { + if let Some(relation) = claim.relation { + return Stage6Relation::from_symbol(relation) + .ok_or(Stage6KernelError::UnknownRelation { relation }); + } + let kernel_symbol = claim.kernel.ok_or(Stage6KernelError::MissingKernel { + driver: claim.symbol, + kernel: "", + })?; + let kernel = find_kernel(program, kernel_symbol).ok_or(Stage6KernelError::MissingKernel { + driver: claim.symbol, + kernel: kernel_symbol, + })?; + Stage6Relation::from_symbol(kernel.relation).ok_or(Stage6KernelError::UnknownRelation { + relation: kernel.relation, + }) +} + +fn instance_round_offset( + program: &'static Stage6CpuProgramPlan, + driver: &'static str, + claim: &'static str, +) -> Result { + program + .instance_results + .iter() + .find(|instance| instance.source == driver && instance.claim == claim) + .map(|instance| instance.round_offset) + .ok_or(Stage6KernelError::MissingClaim { + batch: driver, + claim, + }) +} + +fn combine_univariate_polys( + polynomials: &[UnivariatePoly], + coefficients: &[F], +) -> UnivariatePoly { + let max_len = polynomials + .iter() + .map(|poly| poly.coefficients().len()) + .max() + .unwrap_or(0); + let mut combined = vec![F::zero(); max_len]; + for (poly, &coefficient) in polynomials.iter().zip(coefficients) { + for (combined, &term) in combined.iter_mut().zip(poly.coefficients()) { + *combined += term * coefficient; + } + } + trim_trailing_zero_coefficients(&mut combined); + UnivariatePoly::new(combined) +} + +fn trim_trailing_zero_coefficients(coefficients: &mut Vec) { + while coefficients.len() > 1 && coefficients.last() == Some(&F::zero()) { + let _ = coefficients.pop(); + } +} + +fn round_poly_from_dense_terms( + factors: &[Vec], + terms: &[DenseTerm], + active_scale: F, + degree_bound: usize, + relation: Stage6Relation, +) -> Result, Stage6KernelError> { + if degree_bound > 5 { + return Err(Stage6KernelError::InvalidProof { + driver: relation.symbol(), + reason: "stage6 dense degree bound is unsupported", + }); + } + let half = factors.first().map_or(0, |factor| factor.len() / 2); + for term in terms { + if term.factors.len() > degree_bound { + return Err(Stage6KernelError::InvalidProof { + driver: relation.symbol(), + reason: "stage6 dense term exceeds degree bound", + }); + } + if term.factors.iter().any(|factor| *factor >= factors.len()) { + return Err(Stage6KernelError::InvalidProof { + driver: relation.symbol(), + reason: "stage6 dense term references missing factor", + }); + } + } + + let eval_count = degree_bound + 1; + let mut evals = if half >= DENSE_BIND_PAR_THRESHOLD { + (0..half) + .into_par_iter() + .fold( + || vec![F::zero(); eval_count], + |mut row_evals, row| { + accumulate_dense_row_evaluations(factors, terms, row, &mut row_evals); + row_evals + }, + ) + .reduce( + || vec![F::zero(); eval_count], + |mut left, right| { + for (left, right) in left.iter_mut().zip(right) { + *left += right; + } + left + }, + ) + } else { + let mut total = vec![F::zero(); eval_count]; + for row in 0..half { + accumulate_dense_row_evaluations(factors, terms, row, &mut total); + } + total + }; + for eval in &mut evals { + *eval *= active_scale; + } + Ok(UnivariatePoly::interpolate_over_integers(&evals)) +} + +fn accumulate_dense_row_evaluations( + factors: &[Vec], + terms: &[DenseTerm], + row: usize, + evals: &mut [F], +) { + for (point, eval) in evals.iter_mut().enumerate() { + let point = F::from_u64(point as u64); + for term in terms { + let mut term_eval = term.coefficient; + for &factor in &term.factors { + let low = factors[factor][2 * row]; + let high = factors[factor][2 * row + 1]; + term_eval *= low + (high - low) * point; + } + *eval += term_eval; + } + } +} + +pub fn execute_stage6_program( + program: &'static Stage6CpuProgramPlan, + mode: Stage6ExecutionMode, + executor: &mut E, + transcript: &mut T, +) -> Result, Stage6KernelError> +where + F: Field, + T: Transcript, + E: Stage6KernelExecutor, +{ + let mut artifacts = Stage6ExecutionArtifacts::default(); + for step in program.steps { + match step.kind { + "transcript_squeeze" => { + let squeeze = + find_squeeze(program, step.symbol).ok_or(Stage6KernelError::MissingValue { + symbol: step.symbol, + })?; + let values = transcript.challenge_vector(squeeze.count); + executor.observe_challenge_vector(squeeze, &values)?; + artifacts.challenge_vectors.push(Stage6ChallengeVector { + symbol: squeeze.symbol, + values, + }); + } + "transcript_absorb_bytes" => { + let absorb = find_absorb_bytes(program, step.symbol).ok_or( + Stage6KernelError::MissingValue { + symbol: step.symbol, + }, + )?; + absorb_stage6_bytes(absorb, transcript); + } + "sumcheck_driver" => { + let driver = + find_driver(program, step.symbol).ok_or(Stage6KernelError::MissingDriver { + driver: step.symbol, + })?; + let kernel_symbol = driver.kernel.ok_or(Stage6KernelError::MissingKernel { + driver: driver.symbol, + kernel: "", + })?; + let kernel = find_kernel(program, kernel_symbol).ok_or( + Stage6KernelError::MissingKernel { + driver: driver.symbol, + kernel: kernel_symbol, + }, + )?; + let batch = + find_batch(program, driver.batch).ok_or(Stage6KernelError::MissingBatch { + driver: driver.symbol, + batch: driver.batch, + })?; + let context = Stage6KernelContext { + mode, + program, + kernel, + batch, + driver, + }; + let output = match mode { + Stage6ExecutionMode::Prover => executor.prove_sumcheck(context, transcript)?, + Stage6ExecutionMode::Verifier => { + executor.verify_sumcheck(context, transcript)? + } + }; + executor.observe_sumcheck_output(&output)?; + artifacts + .opening_claims + .extend(output.opening_claims.clone()); + artifacts.sumchecks.push(output); + } + _ => { + return Err(Stage6KernelError::InvalidProgramStep { + symbol: step.symbol, + kind: step.kind, + }); + } + } + } + artifacts + .opening_batches + .extend(program.opening_batches.iter()); + artifacts.opening_claims = executor.opening_claim_values(program)?; + Ok(artifacts) +} + +fn absorb_stage6_bytes(absorb: &'static Stage6TranscriptAbsorbBytesPlan, transcript: &mut T) +where + T: Transcript, +{ + transcript.append(&LabelWithCount( + absorb.label.as_bytes(), + absorb.payload.len() as u64, + )); + transcript.append_bytes(absorb.payload.as_bytes()); +} + +fn find_squeeze( + program: &'static Stage6CpuProgramPlan, + symbol: &str, +) -> Option<&'static Stage6TranscriptSqueezePlan> { + program + .transcript_squeezes + .iter() + .find(|squeeze| squeeze.symbol == symbol) +} + +fn find_absorb_bytes( + program: &'static Stage6CpuProgramPlan, + symbol: &str, +) -> Option<&'static Stage6TranscriptAbsorbBytesPlan> { + program + .transcript_absorb_bytes + .iter() + .find(|absorb| absorb.symbol == symbol) +} + +fn find_driver( + program: &'static Stage6CpuProgramPlan, + symbol: &str, +) -> Option<&'static Stage6SumcheckDriverPlan> { + program + .drivers + .iter() + .find(|driver| driver.symbol == symbol) +} + +fn find_kernel( + program: &'static Stage6CpuProgramPlan, + symbol: &str, +) -> Option<&'static Stage6KernelPlan> { + program + .kernels + .iter() + .find(|kernel| kernel.symbol == symbol) +} + +fn find_batch( + program: &'static Stage6CpuProgramPlan, + symbol: &str, +) -> Option<&'static Stage6SumcheckBatchPlan> { + program.batches.iter().find(|batch| batch.symbol == symbol) +} + +#[cfg(test)] +#[expect( + clippy::expect_used, + clippy::unwrap_used, + reason = "tests use panic-on-error helpers to keep failure context concise" +)] +mod tests { + use super::*; + use jolt_field::Fr; + use jolt_transcript::Blake2bTranscript; + + const PARAMS: Stage6Params = Stage6Params { + field: "bn254_fr", + pcs: "dory", + transcript: "blake2b_transcript", + }; + const STEPS: &[Stage6ProgramStepPlan] = &[Stage6ProgramStepPlan { + kind: "sumcheck_driver", + symbol: "stage6.sumcheck", + }]; + const CLAIM_INPUT_OPENINGS: &[&str] = &["stage6.input.claim"]; + const CLAIMS: &[Stage6SumcheckClaimPlan] = &[Stage6SumcheckClaimPlan { + symbol: "stage6.claim", + stage: "stage6", + domain: "jolt.test_domain", + num_rounds: 1, + degree: 1, + claim: "stage6.claim", + kernel: Some("jolt.cpu.stage6.batched"), + relation: None, + claim_value: "stage6.input.claim", + input_openings: CLAIM_INPUT_OPENINGS, + }]; + const KERNELS: &[Stage6KernelPlan] = &[Stage6KernelPlan { + symbol: "jolt.cpu.stage6.batched", + relation: "jolt.stage6.batched", + kind: "sumcheck", + backend: "cpu", + abi: "jolt_stage6_batched", + }]; + const BATCHES: &[Stage6SumcheckBatchPlan] = &[Stage6SumcheckBatchPlan { + symbol: "stage6.batch", + stage: "stage6", + proof_slot: "stage6.sumcheck", + policy: "jolt_core_stage6_aligned", + count: 0, + ordered_claims: &[], + claim_operands: &[], + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + round_schedule: &[], + }]; + const DRIVERS: &[Stage6SumcheckDriverPlan] = &[Stage6SumcheckDriverPlan { + symbol: "stage6.sumcheck", + stage: "stage6", + proof_slot: "stage6.sumcheck", + kernel: Some("jolt.cpu.stage6.batched"), + relation: None, + batch: "stage6.batch", + policy: "jolt_core_stage6_aligned", + round_schedule: &[], + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + num_rounds: 0, + degree: 0, + }]; + const PROGRAM: Stage6CpuProgramPlan = Stage6CpuProgramPlan { + role: "prover", + params: PARAMS, + steps: STEPS, + transcript_squeezes: &[], + transcript_absorb_bytes: &[], + opening_inputs: &[], + field_constants: &[], + field_exprs: &[], + kernels: KERNELS, + claims: &[], + batches: BATCHES, + drivers: DRIVERS, + instance_results: &[], + evals: &[], + point_zeros: &[], + point_slices: &[], + point_concats: &[], + opening_claims: &[], + opening_equalities: &[], + opening_batches: &[], + }; + const REPLAY_BATCHES: &[Stage6SumcheckBatchPlan] = &[Stage6SumcheckBatchPlan { + symbol: "stage6.batch", + stage: "stage6", + proof_slot: "stage6.sumcheck", + policy: "jolt_core_stage6_aligned", + count: 1, + ordered_claims: &["stage6.claim"], + claim_operands: &["stage6.claim"], + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + round_schedule: &[1], + }]; + const REPLAY_DRIVERS: &[Stage6SumcheckDriverPlan] = &[Stage6SumcheckDriverPlan { + symbol: "stage6.sumcheck", + stage: "stage6", + proof_slot: "stage6.sumcheck", + kernel: Some("jolt.cpu.stage6.batched"), + relation: None, + batch: "stage6.batch", + policy: "jolt_core_stage6_aligned", + round_schedule: &[1], + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + num_rounds: 1, + degree: 1, + }]; + const REPLAY_PROGRAM: Stage6CpuProgramPlan = Stage6CpuProgramPlan { + role: "prover", + params: PARAMS, + steps: STEPS, + transcript_squeezes: &[], + transcript_absorb_bytes: &[], + opening_inputs: &[], + field_constants: &[], + field_exprs: &[], + kernels: KERNELS, + claims: CLAIMS, + batches: REPLAY_BATCHES, + drivers: REPLAY_DRIVERS, + instance_results: &[], + evals: &[], + point_zeros: &[], + point_slices: &[], + point_concats: &[], + opening_claims: &[], + opening_equalities: &[], + opening_batches: &[], + }; + const BYTECODE_FIELD_CONSTANTS: &[Stage6FieldConstantPlan] = &[ + Stage6FieldConstantPlan { + symbol: "stage6.bytecode_read_raf.gamma", + field: "bn254_fr", + value: 2, + }, + Stage6FieldConstantPlan { + symbol: "stage6.bytecode_read_raf.stage1_gamma", + field: "bn254_fr", + value: 3, + }, + Stage6FieldConstantPlan { + symbol: "stage6.bytecode_read_raf.stage2_gamma", + field: "bn254_fr", + value: 5, + }, + Stage6FieldConstantPlan { + symbol: "stage6.bytecode_read_raf.stage3_gamma", + field: "bn254_fr", + value: 7, + }, + Stage6FieldConstantPlan { + symbol: "stage6.bytecode_read_raf.stage4_gamma", + field: "bn254_fr", + value: 11, + }, + Stage6FieldConstantPlan { + symbol: "stage6.bytecode_read_raf.stage5_gamma", + field: "bn254_fr", + value: 13, + }, + ]; + const BYTECODE_CLAIM_INPUT_OPENINGS: &[&str] = &["stage6.input.bytecode_read_raf_claim"]; + const BYTECODE_CLAIMS: &[Stage6SumcheckClaimPlan] = &[Stage6SumcheckClaimPlan { + symbol: "stage6.bytecode_read_raf.input", + stage: "stage6", + domain: "jolt.stage6_bytecode_read_raf_domain", + num_rounds: 3, + degree: 3, + claim: "stage6.bytecode_read_raf.weighted_prior_stage_values", + kernel: Some("jolt.cpu.stage6.bytecode_read_raf"), + relation: None, + claim_value: "stage6.input.bytecode_read_raf_claim", + input_openings: BYTECODE_CLAIM_INPUT_OPENINGS, + }]; + const BYTECODE_KERNELS: &[Stage6KernelPlan] = &[ + Stage6KernelPlan { + symbol: "jolt.cpu.stage6.bytecode_read_raf", + relation: "jolt.stage6.bytecode_read_raf", + kind: "sumcheck", + backend: "cpu", + abi: "jolt_stage6_bytecode_read_raf", + }, + Stage6KernelPlan { + symbol: "jolt.cpu.stage6.batched", + relation: "jolt.stage6.batched", + kind: "sumcheck", + backend: "cpu", + abi: "jolt_stage6_batched", + }, + ]; + const BYTECODE_BATCHES: &[Stage6SumcheckBatchPlan] = &[Stage6SumcheckBatchPlan { + symbol: "stage6.batch", + stage: "stage6", + proof_slot: "stage6.sumcheck", + policy: "jolt_core_stage6_aligned", + count: 1, + ordered_claims: &["stage6.bytecode_read_raf.input"], + claim_operands: &["stage6.bytecode_read_raf.input"], + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + round_schedule: &[3], + }]; + const BYTECODE_DRIVERS: &[Stage6SumcheckDriverPlan] = &[Stage6SumcheckDriverPlan { + symbol: "stage6.sumcheck", + stage: "stage6", + proof_slot: "stage6.sumcheck", + kernel: Some("jolt.cpu.stage6.batched"), + relation: None, + batch: "stage6.batch", + policy: "jolt_core_stage6_aligned", + round_schedule: &[3], + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + num_rounds: 3, + degree: 3, + }]; + const BYTECODE_INSTANCE_RESULTS: &[Stage6SumcheckInstanceResultPlan] = &[ + Stage6SumcheckInstanceResultPlan { + symbol: "stage6.bytecode_read_raf.instance", + source: "stage6.sumcheck", + claim: "stage6.bytecode_read_raf.input", + relation: "jolt.stage6.bytecode_read_raf", + index: 0, + point_arity: 3, + num_rounds: 3, + round_offset: 0, + point_order: "bytecode_read_raf", + degree: 3, + }, + Stage6SumcheckInstanceResultPlan { + symbol: "stage6.hamming_booleanity.instance", + source: "stage6.sumcheck", + claim: "stage6.hamming_booleanity.input", + relation: "jolt.stage6.hamming_booleanity", + index: 1, + point_arity: 1, + num_rounds: 1, + round_offset: 0, + point_order: "reverse", + degree: 3, + }, + ]; + const BYTECODE_EVALS: &[Stage6SumcheckEvalPlan] = &[ + Stage6SumcheckEvalPlan { + symbol: "stage6.bytecode_read_raf.eval.BytecodeRa_0", + source: "stage6.sumcheck", + name: "stage6.bytecode_read_raf.eval.BytecodeRa_0", + index: 0, + oracle: "BytecodeRa_0", + }, + Stage6SumcheckEvalPlan { + symbol: "stage6.bytecode_read_raf.eval.BytecodeRa_1", + source: "stage6.sumcheck", + name: "stage6.bytecode_read_raf.eval.BytecodeRa_1", + index: 1, + oracle: "BytecodeRa_1", + }, + ]; + const BYTECODE_PROGRAM: Stage6CpuProgramPlan = Stage6CpuProgramPlan { + role: "prover", + params: PARAMS, + steps: STEPS, + transcript_squeezes: &[], + transcript_absorb_bytes: &[], + opening_inputs: &[], + field_constants: BYTECODE_FIELD_CONSTANTS, + field_exprs: &[], + kernels: BYTECODE_KERNELS, + claims: BYTECODE_CLAIMS, + batches: BYTECODE_BATCHES, + drivers: BYTECODE_DRIVERS, + instance_results: BYTECODE_INSTANCE_RESULTS, + evals: BYTECODE_EVALS, + point_zeros: &[], + point_slices: &[], + point_concats: &[], + opening_claims: &[], + opening_equalities: &[], + opening_batches: &[], + }; + const BOOLEANITY_OPENING_INPUTS: &[Stage6OpeningInputPlan] = &[Stage6OpeningInputPlan { + symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", + source_stage: "stage5", + source_claim: "stage5.instruction_read_raf.opening.InstructionRa_0", + oracle: "InstructionRa_0", + domain: "jolt.stage5_instruction_ra_chunk_domain", + point_arity: 4, + claim_kind: "virtual", + }]; + const BOOLEANITY_FIELD_CONSTANTS: &[Stage6FieldConstantPlan] = &[ + Stage6FieldConstantPlan { + symbol: "stage6.zero", + field: "bn254_fr", + value: 0, + }, + Stage6FieldConstantPlan { + symbol: "stage6.booleanity.gamma", + field: "bn254_fr", + value: 2, + }, + ]; + const BOOLEANITY_CLAIMS: &[Stage6SumcheckClaimPlan] = &[Stage6SumcheckClaimPlan { + symbol: "stage6.booleanity.input", + stage: "stage6", + domain: "jolt.stage6_booleanity_domain", + num_rounds: 3, + degree: 3, + claim: "stage6.booleanity.zero", + kernel: Some("jolt.cpu.stage6.booleanity"), + relation: None, + claim_value: "stage6.zero", + input_openings: &[], + }]; + const BOOLEANITY_KERNELS: &[Stage6KernelPlan] = &[ + Stage6KernelPlan { + symbol: "jolt.cpu.stage6.booleanity", + relation: "jolt.stage6.booleanity", + kind: "sumcheck", + backend: "cpu", + abi: "jolt_stage6_booleanity", + }, + Stage6KernelPlan { + symbol: "jolt.cpu.stage6.batched", + relation: "jolt.stage6.batched", + kind: "sumcheck", + backend: "cpu", + abi: "jolt_stage6_batched", + }, + ]; + const BOOLEANITY_BATCHES: &[Stage6SumcheckBatchPlan] = &[Stage6SumcheckBatchPlan { + symbol: "stage6.batch", + stage: "stage6", + proof_slot: "stage6.sumcheck", + policy: "jolt_core_stage6_aligned", + count: 1, + ordered_claims: &["stage6.booleanity.input"], + claim_operands: &["stage6.booleanity.input"], + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + round_schedule: &[3], + }]; + const BOOLEANITY_DRIVERS: &[Stage6SumcheckDriverPlan] = &[Stage6SumcheckDriverPlan { + symbol: "stage6.sumcheck", + stage: "stage6", + proof_slot: "stage6.sumcheck", + kernel: Some("jolt.cpu.stage6.batched"), + relation: None, + batch: "stage6.batch", + policy: "jolt_core_stage6_aligned", + round_schedule: &[3], + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + num_rounds: 3, + degree: 3, + }]; + const BOOLEANITY_INSTANCE_RESULTS: &[Stage6SumcheckInstanceResultPlan] = &[ + Stage6SumcheckInstanceResultPlan { + symbol: "stage6.booleanity.instance", + source: "stage6.sumcheck", + claim: "stage6.booleanity.input", + relation: "jolt.stage6.booleanity", + index: 0, + point_arity: 3, + num_rounds: 3, + round_offset: 0, + point_order: "stage6_booleanity", + degree: 3, + }, + Stage6SumcheckInstanceResultPlan { + symbol: "stage6.hamming_booleanity.instance", + source: "stage6.sumcheck", + claim: "stage6.hamming_booleanity.input", + relation: "jolt.stage6.hamming_booleanity", + index: 1, + point_arity: 2, + num_rounds: 2, + round_offset: 0, + point_order: "reverse", + degree: 3, + }, + ]; + const BOOLEANITY_EVALS: &[Stage6SumcheckEvalPlan] = &[ + Stage6SumcheckEvalPlan { + symbol: "stage6.booleanity.eval.InstructionRa_0", + source: "stage6.sumcheck", + name: "stage6.booleanity.eval.InstructionRa_0", + index: 0, + oracle: "InstructionRa_0", + }, + Stage6SumcheckEvalPlan { + symbol: "stage6.booleanity.eval.BytecodeRa_0", + source: "stage6.sumcheck", + name: "stage6.booleanity.eval.BytecodeRa_0", + index: 1, + oracle: "BytecodeRa_0", + }, + Stage6SumcheckEvalPlan { + symbol: "stage6.booleanity.eval.RamRa_0", + source: "stage6.sumcheck", + name: "stage6.booleanity.eval.RamRa_0", + index: 2, + oracle: "RamRa_0", + }, + ]; + const BOOLEANITY_PROGRAM: Stage6CpuProgramPlan = Stage6CpuProgramPlan { + role: "prover", + params: PARAMS, + steps: STEPS, + transcript_squeezes: &[], + transcript_absorb_bytes: &[], + opening_inputs: BOOLEANITY_OPENING_INPUTS, + field_constants: BOOLEANITY_FIELD_CONSTANTS, + field_exprs: &[], + kernels: BOOLEANITY_KERNELS, + claims: BOOLEANITY_CLAIMS, + batches: BOOLEANITY_BATCHES, + drivers: BOOLEANITY_DRIVERS, + instance_results: BOOLEANITY_INSTANCE_RESULTS, + evals: BOOLEANITY_EVALS, + point_zeros: &[], + point_slices: &[], + point_concats: &[], + opening_claims: &[], + opening_equalities: &[], + opening_batches: &[], + }; + const HAMMING_OPENING_INPUTS: &[Stage6OpeningInputPlan] = &[Stage6OpeningInputPlan { + symbol: "stage6.input.stage1.LookupOutput", + source_stage: "stage1", + source_claim: "stage1.outer_remaining.opening.LookupOutput", + oracle: "LookupOutput", + domain: "jolt.trace_domain", + point_arity: 2, + claim_kind: "virtual", + }]; + const HAMMING_FIELD_CONSTANTS: &[Stage6FieldConstantPlan] = &[Stage6FieldConstantPlan { + symbol: "stage6.zero", + field: "bn254_fr", + value: 0, + }]; + const HAMMING_CLAIM_INPUT_OPENINGS: &[&str] = &["stage6.input.stage1.LookupOutput"]; + const HAMMING_CLAIMS: &[Stage6SumcheckClaimPlan] = &[Stage6SumcheckClaimPlan { + symbol: "stage6.hamming_booleanity.input", + stage: "stage6", + domain: "jolt.trace_domain", + num_rounds: 2, + degree: 3, + claim: "stage6.hamming_booleanity.zero", + kernel: Some("jolt.cpu.stage6.hamming_booleanity"), + relation: None, + claim_value: "stage6.zero", + input_openings: HAMMING_CLAIM_INPUT_OPENINGS, + }]; + const HAMMING_KERNELS: &[Stage6KernelPlan] = &[ + Stage6KernelPlan { + symbol: "jolt.cpu.stage6.hamming_booleanity", + relation: "jolt.stage6.hamming_booleanity", + kind: "sumcheck", + backend: "cpu", + abi: "jolt_stage6_hamming_booleanity", + }, + Stage6KernelPlan { + symbol: "jolt.cpu.stage6.batched", + relation: "jolt.stage6.batched", + kind: "sumcheck", + backend: "cpu", + abi: "jolt_stage6_batched", + }, + ]; + const HAMMING_BATCHES: &[Stage6SumcheckBatchPlan] = &[Stage6SumcheckBatchPlan { + symbol: "stage6.batch", + stage: "stage6", + proof_slot: "stage6.sumcheck", + policy: "jolt_core_stage6_aligned", + count: 1, + ordered_claims: &["stage6.hamming_booleanity.input"], + claim_operands: &["stage6.hamming_booleanity.input"], + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + round_schedule: &[2], + }]; + const HAMMING_DRIVERS: &[Stage6SumcheckDriverPlan] = &[Stage6SumcheckDriverPlan { + symbol: "stage6.sumcheck", + stage: "stage6", + proof_slot: "stage6.sumcheck", + kernel: Some("jolt.cpu.stage6.batched"), + relation: None, + batch: "stage6.batch", + policy: "jolt_core_stage6_aligned", + round_schedule: &[2], + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + num_rounds: 2, + degree: 3, + }]; + const HAMMING_INSTANCE_RESULTS: &[Stage6SumcheckInstanceResultPlan] = + &[Stage6SumcheckInstanceResultPlan { + symbol: "stage6.hamming_booleanity.instance", + source: "stage6.sumcheck", + claim: "stage6.hamming_booleanity.input", + relation: "jolt.stage6.hamming_booleanity", + index: 0, + point_arity: 2, + num_rounds: 2, + round_offset: 0, + point_order: "reverse", + degree: 3, + }]; + const HAMMING_EVALS: &[Stage6SumcheckEvalPlan] = &[Stage6SumcheckEvalPlan { + symbol: "stage6.hamming_booleanity.eval.HammingWeight", + source: "stage6.sumcheck", + name: "stage6.hamming_booleanity.eval.HammingWeight", + index: 0, + oracle: "HammingWeight", + }]; + const HAMMING_PROGRAM: Stage6CpuProgramPlan = Stage6CpuProgramPlan { + role: "prover", + params: PARAMS, + steps: STEPS, + transcript_squeezes: &[], + transcript_absorb_bytes: &[], + opening_inputs: HAMMING_OPENING_INPUTS, + field_constants: HAMMING_FIELD_CONSTANTS, + field_exprs: &[], + kernels: HAMMING_KERNELS, + claims: HAMMING_CLAIMS, + batches: HAMMING_BATCHES, + drivers: HAMMING_DRIVERS, + instance_results: HAMMING_INSTANCE_RESULTS, + evals: HAMMING_EVALS, + point_zeros: &[], + point_slices: &[], + point_concats: &[], + opening_claims: &[], + opening_equalities: &[], + opening_batches: &[], + }; + const INC_FIELD_CONSTANTS: &[Stage6FieldConstantPlan] = &[Stage6FieldConstantPlan { + symbol: "stage6.inc_claim_reduction.gamma", + field: "bn254_fr", + value: 2, + }]; + const INC_CLAIM_INPUT_OPENINGS: &[&str] = &[ + "stage6.input.stage2.ram_read_write.RamInc", + "stage6.input.stage4.ram_val_check.RamInc", + "stage6.input.stage4.registers_read_write.RdInc", + "stage6.input.stage5.registers_val_evaluation.RdInc", + ]; + const INC_CLAIMS: &[Stage6SumcheckClaimPlan] = &[Stage6SumcheckClaimPlan { + symbol: "stage6.inc_claim_reduction.input", + stage: "stage6", + domain: "jolt.trace_domain", + num_rounds: 2, + degree: 2, + claim: "stage6.inc_claim_reduction.weighted_increments", + kernel: Some("jolt.cpu.stage6.inc_claim_reduction"), + relation: None, + claim_value: "stage6.input.inc_claim", + input_openings: INC_CLAIM_INPUT_OPENINGS, + }]; + const INC_KERNELS: &[Stage6KernelPlan] = &[ + Stage6KernelPlan { + symbol: "jolt.cpu.stage6.inc_claim_reduction", + relation: "jolt.stage6.inc_claim_reduction", + kind: "sumcheck", + backend: "cpu", + abi: "jolt_stage6_inc_claim_reduction", + }, + Stage6KernelPlan { + symbol: "jolt.cpu.stage6.batched", + relation: "jolt.stage6.batched", + kind: "sumcheck", + backend: "cpu", + abi: "jolt_stage6_batched", + }, + ]; + const INC_BATCHES: &[Stage6SumcheckBatchPlan] = &[Stage6SumcheckBatchPlan { + symbol: "stage6.batch", + stage: "stage6", + proof_slot: "stage6.sumcheck", + policy: "jolt_core_stage6_aligned", + count: 1, + ordered_claims: &["stage6.inc_claim_reduction.input"], + claim_operands: &["stage6.inc_claim_reduction.input"], + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + round_schedule: &[2], + }]; + const INC_DRIVERS: &[Stage6SumcheckDriverPlan] = &[Stage6SumcheckDriverPlan { + symbol: "stage6.sumcheck", + stage: "stage6", + proof_slot: "stage6.sumcheck", + kernel: Some("jolt.cpu.stage6.batched"), + relation: None, + batch: "stage6.batch", + policy: "jolt_core_stage6_aligned", + round_schedule: &[2], + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + num_rounds: 2, + degree: 2, + }]; + const INC_INSTANCE_RESULTS: &[Stage6SumcheckInstanceResultPlan] = + &[Stage6SumcheckInstanceResultPlan { + symbol: "stage6.inc_claim_reduction.instance", + source: "stage6.sumcheck", + claim: "stage6.inc_claim_reduction.input", + relation: "jolt.stage6.inc_claim_reduction", + index: 0, + point_arity: 2, + num_rounds: 2, + round_offset: 0, + point_order: "reverse", + degree: 2, + }]; + const INC_EVALS: &[Stage6SumcheckEvalPlan] = &[ + Stage6SumcheckEvalPlan { + symbol: "stage6.inc_claim_reduction.eval.RamInc", + source: "stage6.sumcheck", + name: "stage6.inc_claim_reduction.eval.RamInc", + index: 0, + oracle: "RamInc", + }, + Stage6SumcheckEvalPlan { + symbol: "stage6.inc_claim_reduction.eval.RdInc", + source: "stage6.sumcheck", + name: "stage6.inc_claim_reduction.eval.RdInc", + index: 1, + oracle: "RdInc", + }, + ]; + const INC_PROGRAM: Stage6CpuProgramPlan = Stage6CpuProgramPlan { + role: "prover", + params: PARAMS, + steps: STEPS, + transcript_squeezes: &[], + transcript_absorb_bytes: &[], + opening_inputs: &[], + field_constants: INC_FIELD_CONSTANTS, + field_exprs: &[], + kernels: INC_KERNELS, + claims: INC_CLAIMS, + batches: INC_BATCHES, + drivers: INC_DRIVERS, + instance_results: INC_INSTANCE_RESULTS, + evals: INC_EVALS, + point_zeros: &[], + point_slices: &[], + point_concats: &[], + opening_claims: &[], + opening_equalities: &[], + opening_batches: &[], + }; + const RAM_RA_CLAIM_INPUT_OPENINGS: &[&str] = + &["stage6.input.stage5.ram_ra_claim_reduction.RamRa"]; + const RAM_RA_CLAIMS: &[Stage6SumcheckClaimPlan] = &[Stage6SumcheckClaimPlan { + symbol: "stage6.ram_ra_virtual.input", + stage: "stage6", + domain: "jolt.trace_domain", + num_rounds: 2, + degree: 5, + claim: "stage6.ram_ra_virtual.weighted_ram_ra", + kernel: Some("jolt.cpu.stage6.ram_ra_virtual"), + relation: None, + claim_value: "stage6.input.ram_ra_virtual_claim", + input_openings: RAM_RA_CLAIM_INPUT_OPENINGS, + }]; + const RAM_RA_KERNELS: &[Stage6KernelPlan] = &[ + Stage6KernelPlan { + symbol: "jolt.cpu.stage6.ram_ra_virtual", + relation: "jolt.stage6.ram_ra_virtual", + kind: "sumcheck", + backend: "cpu", + abi: "jolt_stage6_ram_ra_virtual", + }, + Stage6KernelPlan { + symbol: "jolt.cpu.stage6.batched", + relation: "jolt.stage6.batched", + kind: "sumcheck", + backend: "cpu", + abi: "jolt_stage6_batched", + }, + ]; + const RAM_RA_BATCHES: &[Stage6SumcheckBatchPlan] = &[Stage6SumcheckBatchPlan { + symbol: "stage6.batch", + stage: "stage6", + proof_slot: "stage6.sumcheck", + policy: "jolt_core_stage6_aligned", + count: 1, + ordered_claims: &["stage6.ram_ra_virtual.input"], + claim_operands: &["stage6.ram_ra_virtual.input"], + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + round_schedule: &[2], + }]; + const RAM_RA_DRIVERS: &[Stage6SumcheckDriverPlan] = &[Stage6SumcheckDriverPlan { + symbol: "stage6.sumcheck", + stage: "stage6", + proof_slot: "stage6.sumcheck", + kernel: Some("jolt.cpu.stage6.batched"), + relation: None, + batch: "stage6.batch", + policy: "jolt_core_stage6_aligned", + round_schedule: &[2], + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + num_rounds: 2, + degree: 5, + }]; + const RAM_RA_INSTANCE_RESULTS: &[Stage6SumcheckInstanceResultPlan] = + &[Stage6SumcheckInstanceResultPlan { + symbol: "stage6.ram_ra_virtual.instance", + source: "stage6.sumcheck", + claim: "stage6.ram_ra_virtual.input", + relation: "jolt.stage6.ram_ra_virtual", + index: 0, + point_arity: 2, + num_rounds: 2, + round_offset: 0, + point_order: "reverse", + degree: 5, + }]; + const RAM_RA_EVALS: &[Stage6SumcheckEvalPlan] = &[ + Stage6SumcheckEvalPlan { + symbol: "stage6.ram_ra_virtual.eval.RamRa_0", + source: "stage6.sumcheck", + name: "stage6.ram_ra_virtual.eval.RamRa_0", + index: 0, + oracle: "RamRa_0", + }, + Stage6SumcheckEvalPlan { + symbol: "stage6.ram_ra_virtual.eval.RamRa_1", + source: "stage6.sumcheck", + name: "stage6.ram_ra_virtual.eval.RamRa_1", + index: 1, + oracle: "RamRa_1", + }, + Stage6SumcheckEvalPlan { + symbol: "stage6.ram_ra_virtual.eval.RamRa_2", + source: "stage6.sumcheck", + name: "stage6.ram_ra_virtual.eval.RamRa_2", + index: 2, + oracle: "RamRa_2", + }, + Stage6SumcheckEvalPlan { + symbol: "stage6.ram_ra_virtual.eval.RamRa_3", + source: "stage6.sumcheck", + name: "stage6.ram_ra_virtual.eval.RamRa_3", + index: 3, + oracle: "RamRa_3", + }, + ]; + const RAM_RA_PROGRAM: Stage6CpuProgramPlan = Stage6CpuProgramPlan { + role: "prover", + params: PARAMS, + steps: STEPS, + transcript_squeezes: &[], + transcript_absorb_bytes: &[], + opening_inputs: &[], + field_constants: &[], + field_exprs: &[], + kernels: RAM_RA_KERNELS, + claims: RAM_RA_CLAIMS, + batches: RAM_RA_BATCHES, + drivers: RAM_RA_DRIVERS, + instance_results: RAM_RA_INSTANCE_RESULTS, + evals: RAM_RA_EVALS, + point_zeros: &[], + point_slices: &[], + point_concats: &[], + opening_claims: &[], + opening_equalities: &[], + opening_batches: &[], + }; + const INSTRUCTION_RA_OPENING_INPUTS: &[Stage6OpeningInputPlan] = &[ + Stage6OpeningInputPlan { + symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", + source_stage: "stage5", + source_claim: "stage5.instruction_read_raf.opening.InstructionRa_0", + oracle: "InstructionRa_0", + domain: "jolt.stage5_instruction_ra_chunk_domain", + point_arity: 2, + claim_kind: "virtual", + }, + Stage6OpeningInputPlan { + symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_1", + source_stage: "stage5", + source_claim: "stage5.instruction_read_raf.opening.InstructionRa_1", + oracle: "InstructionRa_1", + domain: "jolt.stage5_instruction_ra_chunk_domain", + point_arity: 2, + claim_kind: "virtual", + }, + ]; + const INSTRUCTION_RA_FIELD_CONSTANTS: &[Stage6FieldConstantPlan] = &[Stage6FieldConstantPlan { + symbol: "stage6.instruction_ra_virtual.gamma", + field: "bn254_fr", + value: 3, + }]; + const INSTRUCTION_RA_CLAIM_INPUT_OPENINGS: &[&str] = &[ + "stage6.input.stage5.instruction_read_raf.InstructionRa_0", + "stage6.input.stage5.instruction_read_raf.InstructionRa_1", + ]; + const INSTRUCTION_RA_CLAIMS: &[Stage6SumcheckClaimPlan] = &[Stage6SumcheckClaimPlan { + symbol: "stage6.instruction_ra_virtual.input", + stage: "stage6", + domain: "jolt.trace_domain", + num_rounds: 2, + degree: 5, + claim: "stage6.instruction_ra_virtual.weighted_instruction_ra", + kernel: Some("jolt.cpu.stage6.instruction_ra_virtual"), + relation: None, + claim_value: "stage6.input.instruction_ra_virtual_claim", + input_openings: INSTRUCTION_RA_CLAIM_INPUT_OPENINGS, + }]; + const INSTRUCTION_RA_KERNELS: &[Stage6KernelPlan] = &[ + Stage6KernelPlan { + symbol: "jolt.cpu.stage6.instruction_ra_virtual", + relation: "jolt.stage6.instruction_ra_virtual", + kind: "sumcheck", + backend: "cpu", + abi: "jolt_stage6_instruction_ra_virtual", + }, + Stage6KernelPlan { + symbol: "jolt.cpu.stage6.batched", + relation: "jolt.stage6.batched", + kind: "sumcheck", + backend: "cpu", + abi: "jolt_stage6_batched", + }, + ]; + const INSTRUCTION_RA_BATCHES: &[Stage6SumcheckBatchPlan] = &[Stage6SumcheckBatchPlan { + symbol: "stage6.batch", + stage: "stage6", + proof_slot: "stage6.sumcheck", + policy: "jolt_core_stage6_aligned", + count: 1, + ordered_claims: &["stage6.instruction_ra_virtual.input"], + claim_operands: &["stage6.instruction_ra_virtual.input"], + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + round_schedule: &[2], + }]; + const INSTRUCTION_RA_DRIVERS: &[Stage6SumcheckDriverPlan] = &[Stage6SumcheckDriverPlan { + symbol: "stage6.sumcheck", + stage: "stage6", + proof_slot: "stage6.sumcheck", + kernel: Some("jolt.cpu.stage6.batched"), + relation: None, + batch: "stage6.batch", + policy: "jolt_core_stage6_aligned", + round_schedule: &[2], + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + num_rounds: 2, + degree: 5, + }]; + const INSTRUCTION_RA_INSTANCE_RESULTS: &[Stage6SumcheckInstanceResultPlan] = + &[Stage6SumcheckInstanceResultPlan { + symbol: "stage6.instruction_ra_virtual.instance", + source: "stage6.sumcheck", + claim: "stage6.instruction_ra_virtual.input", + relation: "jolt.stage6.instruction_ra_virtual", + index: 0, + point_arity: 2, + num_rounds: 2, + round_offset: 0, + point_order: "reverse", + degree: 5, + }]; + const INSTRUCTION_RA_EVALS: &[Stage6SumcheckEvalPlan] = &[ + Stage6SumcheckEvalPlan { + symbol: "stage6.instruction_ra_virtual.eval.InstructionRa_0", + source: "stage6.sumcheck", + name: "stage6.instruction_ra_virtual.eval.InstructionRa_0", + index: 0, + oracle: "InstructionRa_0", + }, + Stage6SumcheckEvalPlan { + symbol: "stage6.instruction_ra_virtual.eval.InstructionRa_1", + source: "stage6.sumcheck", + name: "stage6.instruction_ra_virtual.eval.InstructionRa_1", + index: 1, + oracle: "InstructionRa_1", + }, + Stage6SumcheckEvalPlan { + symbol: "stage6.instruction_ra_virtual.eval.InstructionRa_2", + source: "stage6.sumcheck", + name: "stage6.instruction_ra_virtual.eval.InstructionRa_2", + index: 2, + oracle: "InstructionRa_2", + }, + Stage6SumcheckEvalPlan { + symbol: "stage6.instruction_ra_virtual.eval.InstructionRa_3", + source: "stage6.sumcheck", + name: "stage6.instruction_ra_virtual.eval.InstructionRa_3", + index: 3, + oracle: "InstructionRa_3", + }, + Stage6SumcheckEvalPlan { + symbol: "stage6.instruction_ra_virtual.eval.InstructionRa_4", + source: "stage6.sumcheck", + name: "stage6.instruction_ra_virtual.eval.InstructionRa_4", + index: 4, + oracle: "InstructionRa_4", + }, + Stage6SumcheckEvalPlan { + symbol: "stage6.instruction_ra_virtual.eval.InstructionRa_5", + source: "stage6.sumcheck", + name: "stage6.instruction_ra_virtual.eval.InstructionRa_5", + index: 5, + oracle: "InstructionRa_5", + }, + Stage6SumcheckEvalPlan { + symbol: "stage6.instruction_ra_virtual.eval.InstructionRa_6", + source: "stage6.sumcheck", + name: "stage6.instruction_ra_virtual.eval.InstructionRa_6", + index: 6, + oracle: "InstructionRa_6", + }, + Stage6SumcheckEvalPlan { + symbol: "stage6.instruction_ra_virtual.eval.InstructionRa_7", + source: "stage6.sumcheck", + name: "stage6.instruction_ra_virtual.eval.InstructionRa_7", + index: 7, + oracle: "InstructionRa_7", + }, + ]; + const INSTRUCTION_RA_PROGRAM: Stage6CpuProgramPlan = Stage6CpuProgramPlan { + role: "prover", + params: PARAMS, + steps: STEPS, + transcript_squeezes: &[], + transcript_absorb_bytes: &[], + opening_inputs: INSTRUCTION_RA_OPENING_INPUTS, + field_constants: INSTRUCTION_RA_FIELD_CONSTANTS, + field_exprs: &[], + kernels: INSTRUCTION_RA_KERNELS, + claims: INSTRUCTION_RA_CLAIMS, + batches: INSTRUCTION_RA_BATCHES, + drivers: INSTRUCTION_RA_DRIVERS, + instance_results: INSTRUCTION_RA_INSTANCE_RESULTS, + evals: INSTRUCTION_RA_EVALS, + point_zeros: &[], + point_slices: &[], + point_concats: &[], + opening_claims: &[], + opening_equalities: &[], + opening_batches: &[], + }; + + #[test] + fn stage6_symbols_parse_as_stage6_relations_and_abis() { + assert_eq!( + Stage6Relation::from_symbol("jolt.stage6.bytecode_read_raf"), + Some(Stage6Relation::BytecodeReadRaf) + ); + assert_eq!( + Stage6Relation::from_symbol("jolt.stage6.batched"), + Some(Stage6Relation::Batched) + ); + assert_eq!( + Stage6KernelAbi::from_name("jolt_stage6_bytecode_read_raf"), + Some(Stage6KernelAbi::BytecodeReadRaf) + ); + assert_eq!( + Stage6KernelAbi::from_name("jolt_stage6_batched"), + Some(Stage6KernelAbi::Batched) + ); + assert_eq!(Stage6Relation::from_symbol("jolt.stage5.batched"), None); + assert_eq!(Stage6KernelAbi::from_name("jolt_stage5_batched"), None); + } + + #[test] + fn unsupported_executor_reaches_stage6_batched_abi() { + let mut executor = UnsupportedStage6KernelExecutor; + let mut transcript = Blake2bTranscript::::new(b"stage6_test"); + let error = execute_stage6_program( + &PROGRAM, + Stage6ExecutionMode::Prover, + &mut executor, + &mut transcript, + ) + .expect_err("stage6 kernels are not implemented yet"); + + assert_eq!( + error, + Stage6KernelError::KernelNotImplemented { + abi: "jolt_stage6_batched" + } + ); + } + + #[test] + fn proof_carrying_executor_replays_stage6_sumcheck_transcript() { + let input_claim = Fr::from_u64(3); + let (proof, opening_inputs) = replay_proof(input_claim); + let mut executor = Stage6ProofCarryingKernelExecutor::new(&proof, &opening_inputs); + let mut transcript = Blake2bTranscript::::new(b"stage6_test"); + + let artifacts = execute_stage6_program( + &REPLAY_PROGRAM, + Stage6ExecutionMode::Prover, + &mut executor, + &mut transcript, + ) + .expect("proof-carrying Stage 6 replay succeeds"); + + assert_eq!(artifacts.sumchecks.len(), 1); + assert_eq!(artifacts.sumchecks[0].point, proof.sumchecks[0].point); + } + + #[test] + fn proof_carrying_executor_rejects_bad_round_polynomial() { + let input_claim = Fr::from_u64(3); + let (mut proof, opening_inputs) = replay_proof(input_claim); + let mut coefficients = proof.sumchecks[0].proof.round_polynomials[0] + .coefficients() + .to_vec(); + coefficients[0] += Fr::from_u64(1); + proof.sumchecks[0].proof.round_polynomials[0] = UnivariatePoly::new(coefficients); + let mut executor = Stage6ProofCarryingKernelExecutor::new(&proof, &opening_inputs); + let mut transcript = Blake2bTranscript::::new(b"stage6_test"); + + let error = execute_stage6_program( + &REPLAY_PROGRAM, + Stage6ExecutionMode::Prover, + &mut executor, + &mut transcript, + ) + .expect_err("tampered Stage 6 replay is rejected"); + + assert_eq!( + error, + Stage6KernelError::InvalidProof { + driver: "stage6.sumcheck", + reason: "batched round check failed" + } + ); + } + + #[test] + fn bytecode_read_raf_prover_produces_verifiable_sumcheck() { + let entries = bytecode_entries(); + let data = Stage6BytecodeReadRafData { + entries: &entries, + entry_bytecode_index: 2, + num_lookup_tables: 2, + }; + let bytecode_ra_0 = frs(&[1, 2, 3, 4]); + let bytecode_ra_1 = frs(&[2, 1, 4, 3]); + let bytecode_ra_chunks: [&[Fr]; 2] = [&bytecode_ra_0, &bytecode_ra_1]; + let mut opening_inputs = bytecode_opening_inputs(); + let input_claim = bytecode_read_raf_claim(data, &bytecode_ra_chunks, &opening_inputs); + opening_inputs.push(Stage6OpeningInputValue { + symbol: "stage6.input.bytecode_read_raf_claim", + point: Vec::new(), + eval: input_claim, + }); + let prover_inputs = Stage6ProverInputs::new(&opening_inputs).with_bytecode_read_raf( + Stage6BytecodeReadRafWitness { + data, + bytecode_ra_chunks: &bytecode_ra_chunks, + bytecode_ra_chunk_lens: None, + bytecode_ra_index_chunks: None, + }, + ); + let mut prover = Stage6ProverKernelExecutor::new(prover_inputs); + let mut prover_transcript = Blake2bTranscript::::new(b"stage6_test"); + let artifacts = execute_stage6_program( + &BYTECODE_PROGRAM, + Stage6ExecutionMode::Prover, + &mut prover, + &mut prover_transcript, + ) + .expect("bytecode read RAF prover succeeds"); + + assert_eq!(artifacts.sumchecks.len(), 1); + assert_eq!(artifacts.sumchecks[0].evals.len(), 2); + + let proof = Stage6Proof { + sumchecks: artifacts.sumchecks.clone(), + }; + let mut verifier = Stage6ProofCarryingKernelExecutor::new(&proof, &opening_inputs) + .with_bytecode_read_raf_data(data); + let mut verifier_transcript = Blake2bTranscript::::new(b"stage6_test"); + let verified = execute_stage6_program( + &BYTECODE_PROGRAM, + Stage6ExecutionMode::Verifier, + &mut verifier, + &mut verifier_transcript, + ) + .expect("proof-carrying verifier accepts bytecode read RAF output"); + + assert_eq!(artifacts.sumchecks[0].point, verified.sumchecks[0].point); + assert_eq!( + named_eval_values(&artifacts.sumchecks[0].evals), + named_eval_values(&verified.sumchecks[0].evals) + ); + } + + #[test] + fn bytecode_read_raf_prover_accepts_sparse_index_chunks() { + let entries = bytecode_entries(); + let data = Stage6BytecodeReadRafData { + entries: &entries, + entry_bytecode_index: 2, + num_lookup_tables: 2, + }; + let bytecode_ra_0 = frs(&[0, 1, 1, 0]); + let bytecode_ra_1 = frs(&[1, 0, 0, 1]); + let bytecode_ra_chunks: [&[Fr]; 2] = [&bytecode_ra_0, &bytecode_ra_1]; + let bytecode_ra_index_0 = [Some(1u8), Some(0u8)]; + let bytecode_ra_index_1 = [Some(0u8), Some(1u8)]; + let bytecode_ra_index_chunks: [&[Option]; 2] = + [&bytecode_ra_index_0, &bytecode_ra_index_1]; + let bytecode_ra_chunk_lens = [1usize, 1usize]; + let sparse_only_bytecode_ra_chunks: [&[Fr]; 0] = []; + let mut opening_inputs = bytecode_opening_inputs(); + let input_claim = bytecode_read_raf_claim(data, &bytecode_ra_chunks, &opening_inputs); + opening_inputs.push(Stage6OpeningInputValue { + symbol: "stage6.input.bytecode_read_raf_claim", + point: Vec::new(), + eval: input_claim, + }); + let prover_inputs = Stage6ProverInputs::new(&opening_inputs).with_bytecode_read_raf( + Stage6BytecodeReadRafWitness { + data, + bytecode_ra_chunks: &sparse_only_bytecode_ra_chunks, + bytecode_ra_chunk_lens: Some(&bytecode_ra_chunk_lens), + bytecode_ra_index_chunks: Some(&bytecode_ra_index_chunks), + }, + ); + let mut prover = Stage6ProverKernelExecutor::new(prover_inputs); + let mut prover_transcript = Blake2bTranscript::::new(b"stage6_test"); + let artifacts = execute_stage6_program( + &BYTECODE_PROGRAM, + Stage6ExecutionMode::Prover, + &mut prover, + &mut prover_transcript, + ) + .expect("bytecode read RAF prover accepts sparse index chunks"); + + assert_eq!( + bytecode_cycle_indices_from_sparse_chunks(&bytecode_ra_index_chunks, &[1, 1], 1) + .expect("sparse bytecode indices are valid"), + vec![2, 1] + ); + + let proof = Stage6Proof { + sumchecks: artifacts.sumchecks.clone(), + }; + let mut verifier = Stage6ProofCarryingKernelExecutor::new(&proof, &opening_inputs) + .with_bytecode_read_raf_data(data); + let mut verifier_transcript = Blake2bTranscript::::new(b"stage6_test"); + let verified = execute_stage6_program( + &BYTECODE_PROGRAM, + Stage6ExecutionMode::Verifier, + &mut verifier, + &mut verifier_transcript, + ) + .expect("proof-carrying verifier accepts sparse bytecode read RAF output"); + + assert_eq!(artifacts.sumchecks[0].point, verified.sumchecks[0].point); + assert_eq!( + named_eval_values(&artifacts.sumchecks[0].evals), + named_eval_values(&verified.sumchecks[0].evals) + ); + } + + #[test] + fn bytecode_read_raf_verifier_rejects_bad_final_eval() { + let entries = bytecode_entries(); + let data = Stage6BytecodeReadRafData { + entries: &entries, + entry_bytecode_index: 2, + num_lookup_tables: 2, + }; + let bytecode_ra_0 = frs(&[1, 2, 3, 4]); + let bytecode_ra_1 = frs(&[2, 1, 4, 3]); + let bytecode_ra_chunks: [&[Fr]; 2] = [&bytecode_ra_0, &bytecode_ra_1]; + let mut opening_inputs = bytecode_opening_inputs(); + let input_claim = bytecode_read_raf_claim(data, &bytecode_ra_chunks, &opening_inputs); + opening_inputs.push(Stage6OpeningInputValue { + symbol: "stage6.input.bytecode_read_raf_claim", + point: Vec::new(), + eval: input_claim, + }); + let prover_inputs = Stage6ProverInputs::new(&opening_inputs).with_bytecode_read_raf( + Stage6BytecodeReadRafWitness { + data, + bytecode_ra_chunks: &bytecode_ra_chunks, + bytecode_ra_chunk_lens: None, + bytecode_ra_index_chunks: None, + }, + ); + let mut prover = Stage6ProverKernelExecutor::new(prover_inputs); + let mut prover_transcript = Blake2bTranscript::::new(b"stage6_test"); + let mut artifacts = execute_stage6_program( + &BYTECODE_PROGRAM, + Stage6ExecutionMode::Prover, + &mut prover, + &mut prover_transcript, + ) + .expect("bytecode read RAF prover succeeds"); + + artifacts.sumchecks[0].evals[0].value += Fr::from_u64(1); + let proof = Stage6Proof { + sumchecks: artifacts.sumchecks, + }; + let mut verifier = Stage6ProofCarryingKernelExecutor::new(&proof, &opening_inputs) + .with_bytecode_read_raf_data(data); + let mut verifier_transcript = Blake2bTranscript::::new(b"stage6_test"); + let error = execute_stage6_program( + &BYTECODE_PROGRAM, + Stage6ExecutionMode::Verifier, + &mut verifier, + &mut verifier_transcript, + ) + .expect_err("tampered bytecode read RAF eval is rejected"); + + assert_eq!( + error, + Stage6KernelError::InvalidProof { + driver: "stage6.sumcheck", + reason: "batched output claim mismatch" + } + ); + } + + #[test] + fn booleanity_prover_produces_verifiable_sumcheck() { + let instruction_ra = frs(&[0, 1, 0, 1, 1, 0, 1, 0]); + let bytecode_ra = frs(&[1, 0, 1, 0, 0, 1, 0, 1]); + let ram_ra = frs(&[0, 0, 1, 1, 0, 1, 1, 0]); + let chunks: [&[Fr]; 3] = [&instruction_ra, &bytecode_ra, &ram_ra]; + let stage5_point = frs(&[11, 13, 2, 3]); + let opening_inputs = vec![Stage6OpeningInputValue { + symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", + point: stage5_point, + eval: Fr::from_u64(0), + }]; + let prover_inputs = + Stage6ProverInputs::new(&opening_inputs).with_booleanity(Stage6BooleanityWitness { + chunks: &chunks, + index_chunks: None, + }); + let mut prover = Stage6ProverKernelExecutor::new(prover_inputs); + let mut prover_transcript = Blake2bTranscript::::new(b"stage6_test"); + let artifacts = execute_stage6_program( + &BOOLEANITY_PROGRAM, + Stage6ExecutionMode::Prover, + &mut prover, + &mut prover_transcript, + ) + .expect("booleanity prover succeeds"); + + assert_eq!(artifacts.sumchecks.len(), 1); + assert_eq!(artifacts.sumchecks[0].evals.len(), 3); + + let proof = Stage6Proof { + sumchecks: artifacts.sumchecks.clone(), + }; + let mut verifier = Stage6ProofCarryingKernelExecutor::new(&proof, &opening_inputs); + let mut verifier_transcript = Blake2bTranscript::::new(b"stage6_test"); + let verified = execute_stage6_program( + &BOOLEANITY_PROGRAM, + Stage6ExecutionMode::Verifier, + &mut verifier, + &mut verifier_transcript, + ) + .expect("proof-carrying verifier accepts booleanity output"); + + assert_eq!(artifacts.sumchecks[0].point, verified.sumchecks[0].point); + assert_eq!( + named_eval_values(&artifacts.sumchecks[0].evals), + named_eval_values(&verified.sumchecks[0].evals) + ); + } + + #[test] + fn booleanity_verifier_rejects_bad_final_eval() { + let instruction_ra = frs(&[0, 1, 0, 1, 1, 0, 1, 0]); + let bytecode_ra = frs(&[1, 0, 1, 0, 0, 1, 0, 1]); + let ram_ra = frs(&[0, 0, 1, 1, 0, 1, 1, 0]); + let chunks: [&[Fr]; 3] = [&instruction_ra, &bytecode_ra, &ram_ra]; + let stage5_point = frs(&[11, 13, 2, 3]); + let opening_inputs = vec![Stage6OpeningInputValue { + symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", + point: stage5_point, + eval: Fr::from_u64(0), + }]; + let prover_inputs = + Stage6ProverInputs::new(&opening_inputs).with_booleanity(Stage6BooleanityWitness { + chunks: &chunks, + index_chunks: None, + }); + let mut prover = Stage6ProverKernelExecutor::new(prover_inputs); + let mut prover_transcript = Blake2bTranscript::::new(b"stage6_test"); + let mut artifacts = execute_stage6_program( + &BOOLEANITY_PROGRAM, + Stage6ExecutionMode::Prover, + &mut prover, + &mut prover_transcript, + ) + .expect("booleanity prover succeeds"); + + artifacts.sumchecks[0].evals[0].value += Fr::from_u64(1); + let proof = Stage6Proof { + sumchecks: artifacts.sumchecks, + }; + let mut verifier = Stage6ProofCarryingKernelExecutor::new(&proof, &opening_inputs); + let mut verifier_transcript = Blake2bTranscript::::new(b"stage6_test"); + let error = execute_stage6_program( + &BOOLEANITY_PROGRAM, + Stage6ExecutionMode::Verifier, + &mut verifier, + &mut verifier_transcript, + ) + .expect_err("tampered booleanity eval is rejected"); + + assert_eq!( + error, + Stage6KernelError::InvalidProof { + driver: "stage6.sumcheck", + reason: "batched output claim mismatch" + } + ); + } + + #[test] + fn hamming_booleanity_prover_produces_verifiable_sumcheck() { + let lookup_output_point = frs(&[3, 5]); + let hamming_weight = frs(&[0, 1, 1, 0]); + let opening_inputs = vec![Stage6OpeningInputValue { + symbol: "stage6.input.stage1.LookupOutput", + point: lookup_output_point, + eval: Fr::from_u64(9), + }]; + let prover_inputs = Stage6ProverInputs::new(&opening_inputs).with_hamming_booleanity( + Stage6HammingBooleanityWitness { + hamming_weight: &hamming_weight, + }, + ); + let mut prover = Stage6ProverKernelExecutor::new(prover_inputs); + let mut prover_transcript = Blake2bTranscript::::new(b"stage6_test"); + let artifacts = execute_stage6_program( + &HAMMING_PROGRAM, + Stage6ExecutionMode::Prover, + &mut prover, + &mut prover_transcript, + ) + .expect("hamming booleanity prover succeeds"); + + assert_eq!(artifacts.sumchecks.len(), 1); + assert_eq!(artifacts.sumchecks[0].evals.len(), 1); + + let proof = Stage6Proof { + sumchecks: artifacts.sumchecks.clone(), + }; + let mut verifier = Stage6ProofCarryingKernelExecutor::new(&proof, &opening_inputs); + let mut verifier_transcript = Blake2bTranscript::::new(b"stage6_test"); + let verified = execute_stage6_program( + &HAMMING_PROGRAM, + Stage6ExecutionMode::Verifier, + &mut verifier, + &mut verifier_transcript, + ) + .expect("proof-carrying verifier accepts hamming output"); + + assert_eq!(artifacts.sumchecks[0].point, verified.sumchecks[0].point); + assert_eq!( + named_eval_values(&artifacts.sumchecks[0].evals), + named_eval_values(&verified.sumchecks[0].evals) + ); + } + + #[test] + fn stage6_witness_helper_adapts_kernel_opening_inputs() { + let params = Stage6WitnessParams { + trace_len: 2, + log_k_chunk: 1, + log_k_bytecode: 1, + log_k_ram: 1, + lookups_ra_virtual_log_k_chunk: 1, + instruction_d: 1, + instruction_ra_virtual_d: 1, + bytecode_d: 1, + ram_d: 1, + }; + let cycle_inputs = [ + CycleInput { + dense: [2, 3], + one_hot: [Some(1), Some(0), Some(1)], + }, + CycleInput::PADDING, + ]; + let opening_inputs = [ + Stage6OpeningInputValue { + symbol: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", + point: frs(&[5]), + eval: Fr::from_u64(0), + }, + Stage6OpeningInputValue { + symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", + point: frs(&[7]), + eval: Fr::from_u64(0), + }, + ]; + + let witness = stage6_witness_from_opening_inputs(params, &cycle_inputs, &opening_inputs); + + assert_eq!(witness.ram_ra_virtual.len(), 1); + assert_eq!(witness.instruction_ra_virtual.len(), 1); + assert_eq!(witness.rd_inc, vec![Fr::from_u64(2), Fr::from_u64(0)]); + assert_eq!(witness.ram_inc, vec![Fr::from_u64(3), Fr::from_u64(0)]); + } + + #[test] + fn hamming_booleanity_prover_requires_witness() { + let opening_inputs = vec![Stage6OpeningInputValue { + symbol: "stage6.input.stage1.LookupOutput", + point: frs(&[3, 5]), + eval: Fr::from_u64(9), + }]; + let mut prover = Stage6ProverKernelExecutor::new(Stage6ProverInputs::new(&opening_inputs)); + let mut transcript = Blake2bTranscript::::new(b"stage6_test"); + let error = execute_stage6_program( + &HAMMING_PROGRAM, + Stage6ExecutionMode::Prover, + &mut prover, + &mut transcript, + ) + .expect_err("hamming booleanity witness is required"); + + assert_eq!( + error, + Stage6KernelError::MissingKernelInput { + kernel: "jolt_stage6_batched", + input: "hamming_booleanity" + } + ); + } + + #[test] + fn hamming_booleanity_verifier_rejects_bad_final_eval() { + let lookup_output_point = frs(&[3, 5]); + let hamming_weight = frs(&[0, 1, 1, 0]); + let opening_inputs = vec![Stage6OpeningInputValue { + symbol: "stage6.input.stage1.LookupOutput", + point: lookup_output_point, + eval: Fr::from_u64(9), + }]; + let prover_inputs = Stage6ProverInputs::new(&opening_inputs).with_hamming_booleanity( + Stage6HammingBooleanityWitness { + hamming_weight: &hamming_weight, + }, + ); + let mut prover = Stage6ProverKernelExecutor::new(prover_inputs); + let mut prover_transcript = Blake2bTranscript::::new(b"stage6_test"); + let mut artifacts = execute_stage6_program( + &HAMMING_PROGRAM, + Stage6ExecutionMode::Prover, + &mut prover, + &mut prover_transcript, + ) + .expect("hamming booleanity prover succeeds"); + + artifacts.sumchecks[0].evals[0].value += Fr::from_u64(1); + let proof = Stage6Proof { + sumchecks: artifacts.sumchecks, + }; + let mut verifier = Stage6ProofCarryingKernelExecutor::new(&proof, &opening_inputs); + let mut verifier_transcript = Blake2bTranscript::::new(b"stage6_test"); + let error = execute_stage6_program( + &HAMMING_PROGRAM, + Stage6ExecutionMode::Verifier, + &mut verifier, + &mut verifier_transcript, + ) + .expect_err("tampered hamming eval is rejected"); + + assert_eq!( + error, + Stage6KernelError::InvalidProof { + driver: "stage6.sumcheck", + reason: "batched output claim mismatch" + } + ); + } + + #[test] + fn inc_claim_reduction_prover_produces_verifiable_sumcheck() { + let ram_inc = frs(&[1, 3, 5, 7]); + let rd_inc = frs(&[2, 4, 6, 8]); + let ram_inc_stage2_point = frs(&[2, 3]); + let ram_inc_stage4_point = frs(&[5, 7]); + let rd_inc_stage4_point = frs(&[11, 13]); + let rd_inc_stage5_point = frs(&[17, 19]); + let gamma = Fr::from_u64(2); + let input_claim = multilinear_eval(&ram_inc, &ram_inc_stage2_point) + + gamma * multilinear_eval(&ram_inc, &ram_inc_stage4_point) + + gamma.square() * multilinear_eval(&rd_inc, &rd_inc_stage4_point) + + gamma.square() * gamma * multilinear_eval(&rd_inc, &rd_inc_stage5_point); + let opening_inputs = vec![ + Stage6OpeningInputValue { + symbol: "stage6.input.stage2.ram_read_write.RamInc", + point: ram_inc_stage2_point.clone(), + eval: multilinear_eval(&ram_inc, &ram_inc_stage2_point), + }, + Stage6OpeningInputValue { + symbol: "stage6.input.stage4.ram_val_check.RamInc", + point: ram_inc_stage4_point.clone(), + eval: multilinear_eval(&ram_inc, &ram_inc_stage4_point), + }, + Stage6OpeningInputValue { + symbol: "stage6.input.stage4.registers_read_write.RdInc", + point: rd_inc_stage4_point.clone(), + eval: multilinear_eval(&rd_inc, &rd_inc_stage4_point), + }, + Stage6OpeningInputValue { + symbol: "stage6.input.stage5.registers_val_evaluation.RdInc", + point: rd_inc_stage5_point.clone(), + eval: multilinear_eval(&rd_inc, &rd_inc_stage5_point), + }, + Stage6OpeningInputValue { + symbol: "stage6.input.inc_claim", + point: Vec::new(), + eval: input_claim, + }, + ]; + let prover_inputs = Stage6ProverInputs::new(&opening_inputs).with_inc_claim_reduction( + Stage6IncClaimReductionWitness { + ram_inc: &ram_inc, + rd_inc: &rd_inc, + }, + ); + let mut prover = Stage6ProverKernelExecutor::new(prover_inputs); + let mut prover_transcript = Blake2bTranscript::::new(b"stage6_test"); + let artifacts = execute_stage6_program( + &INC_PROGRAM, + Stage6ExecutionMode::Prover, + &mut prover, + &mut prover_transcript, + ) + .expect("increment claim-reduction prover succeeds"); + + assert_eq!(artifacts.sumchecks.len(), 1); + assert_eq!(artifacts.sumchecks[0].evals.len(), 2); + + let proof = Stage6Proof { + sumchecks: artifacts.sumchecks.clone(), + }; + let mut verifier = Stage6ProofCarryingKernelExecutor::new(&proof, &opening_inputs); + let mut verifier_transcript = Blake2bTranscript::::new(b"stage6_test"); + let verified = execute_stage6_program( + &INC_PROGRAM, + Stage6ExecutionMode::Verifier, + &mut verifier, + &mut verifier_transcript, + ) + .expect("proof-carrying verifier accepts increment output"); + + assert_eq!(artifacts.sumchecks[0].point, verified.sumchecks[0].point); + assert_eq!( + named_eval_values(&artifacts.sumchecks[0].evals), + named_eval_values(&verified.sumchecks[0].evals) + ); + } + + #[test] + fn inc_claim_reduction_verifier_rejects_bad_final_eval() { + let ram_inc = frs(&[1, 3, 5, 7]); + let rd_inc = frs(&[2, 4, 6, 8]); + let ram_inc_stage2_point = frs(&[2, 3]); + let ram_inc_stage4_point = frs(&[5, 7]); + let rd_inc_stage4_point = frs(&[11, 13]); + let rd_inc_stage5_point = frs(&[17, 19]); + let gamma = Fr::from_u64(2); + let input_claim = multilinear_eval(&ram_inc, &ram_inc_stage2_point) + + gamma * multilinear_eval(&ram_inc, &ram_inc_stage4_point) + + gamma.square() * multilinear_eval(&rd_inc, &rd_inc_stage4_point) + + gamma.square() * gamma * multilinear_eval(&rd_inc, &rd_inc_stage5_point); + let opening_inputs = vec![ + Stage6OpeningInputValue { + symbol: "stage6.input.stage2.ram_read_write.RamInc", + point: ram_inc_stage2_point, + eval: Fr::from_u64(0), + }, + Stage6OpeningInputValue { + symbol: "stage6.input.stage4.ram_val_check.RamInc", + point: ram_inc_stage4_point, + eval: Fr::from_u64(0), + }, + Stage6OpeningInputValue { + symbol: "stage6.input.stage4.registers_read_write.RdInc", + point: rd_inc_stage4_point, + eval: Fr::from_u64(0), + }, + Stage6OpeningInputValue { + symbol: "stage6.input.stage5.registers_val_evaluation.RdInc", + point: rd_inc_stage5_point, + eval: Fr::from_u64(0), + }, + Stage6OpeningInputValue { + symbol: "stage6.input.inc_claim", + point: Vec::new(), + eval: input_claim, + }, + ]; + let prover_inputs = Stage6ProverInputs::new(&opening_inputs).with_inc_claim_reduction( + Stage6IncClaimReductionWitness { + ram_inc: &ram_inc, + rd_inc: &rd_inc, + }, + ); + let mut prover = Stage6ProverKernelExecutor::new(prover_inputs); + let mut prover_transcript = Blake2bTranscript::::new(b"stage6_test"); + let mut artifacts = execute_stage6_program( + &INC_PROGRAM, + Stage6ExecutionMode::Prover, + &mut prover, + &mut prover_transcript, + ) + .expect("increment claim-reduction prover succeeds"); + + artifacts.sumchecks[0].evals[0].value += Fr::from_u64(1); + let proof = Stage6Proof { + sumchecks: artifacts.sumchecks, + }; + let mut verifier = Stage6ProofCarryingKernelExecutor::new(&proof, &opening_inputs); + let mut verifier_transcript = Blake2bTranscript::::new(b"stage6_test"); + let error = execute_stage6_program( + &INC_PROGRAM, + Stage6ExecutionMode::Verifier, + &mut verifier, + &mut verifier_transcript, + ) + .expect_err("tampered increment eval is rejected"); + + assert_eq!( + error, + Stage6KernelError::InvalidProof { + driver: "stage6.sumcheck", + reason: "batched output claim mismatch" + } + ); + } + + #[test] + fn ram_ra_virtual_prover_produces_verifiable_sumcheck() { + let ram_ra_0 = frs(&[1, 2, 3, 4]); + let ram_ra_1 = frs(&[2, 3, 4, 5]); + let ram_ra_2 = frs(&[3, 4, 5, 6]); + let ram_ra_3 = frs(&[4, 5, 6, 7]); + let ram_ra_chunks: [&[Fr]; 4] = [&ram_ra_0, &ram_ra_1, &ram_ra_2, &ram_ra_3]; + let input_point = frs(&[2, 3]); + let input_claim = product_virtual_claim(&ram_ra_chunks, &input_point); + let opening_inputs = vec![ + Stage6OpeningInputValue { + symbol: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", + point: input_point, + eval: input_claim, + }, + Stage6OpeningInputValue { + symbol: "stage6.input.ram_ra_virtual_claim", + point: Vec::new(), + eval: input_claim, + }, + ]; + let prover_inputs = Stage6ProverInputs::new(&opening_inputs).with_ram_ra_virtual( + Stage6RamRaVirtualWitness { + ram_ra_chunks: &ram_ra_chunks, + }, + ); + let mut prover = Stage6ProverKernelExecutor::new(prover_inputs); + let mut prover_transcript = Blake2bTranscript::::new(b"stage6_test"); + let artifacts = execute_stage6_program( + &RAM_RA_PROGRAM, + Stage6ExecutionMode::Prover, + &mut prover, + &mut prover_transcript, + ) + .expect("RAM RA virtualization prover succeeds"); + + assert_eq!(artifacts.sumchecks.len(), 1); + assert_eq!(artifacts.sumchecks[0].evals.len(), 4); + + let proof = Stage6Proof { + sumchecks: artifacts.sumchecks.clone(), + }; + let mut verifier = Stage6ProofCarryingKernelExecutor::new(&proof, &opening_inputs); + let mut verifier_transcript = Blake2bTranscript::::new(b"stage6_test"); + let verified = execute_stage6_program( + &RAM_RA_PROGRAM, + Stage6ExecutionMode::Verifier, + &mut verifier, + &mut verifier_transcript, + ) + .expect("proof-carrying verifier accepts RAM RA virtualization output"); + + assert_eq!(artifacts.sumchecks[0].point, verified.sumchecks[0].point); + assert_eq!( + named_eval_values(&artifacts.sumchecks[0].evals), + named_eval_values(&verified.sumchecks[0].evals) + ); + } + + #[test] + fn ram_ra_virtual_verifier_rejects_bad_final_eval() { + let ram_ra_0 = frs(&[1, 2, 3, 4]); + let ram_ra_1 = frs(&[2, 3, 4, 5]); + let ram_ra_2 = frs(&[3, 4, 5, 6]); + let ram_ra_3 = frs(&[4, 5, 6, 7]); + let ram_ra_chunks: [&[Fr]; 4] = [&ram_ra_0, &ram_ra_1, &ram_ra_2, &ram_ra_3]; + let input_point = frs(&[2, 3]); + let input_claim = product_virtual_claim(&ram_ra_chunks, &input_point); + let opening_inputs = vec![ + Stage6OpeningInputValue { + symbol: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", + point: input_point, + eval: input_claim, + }, + Stage6OpeningInputValue { + symbol: "stage6.input.ram_ra_virtual_claim", + point: Vec::new(), + eval: input_claim, + }, + ]; + let prover_inputs = Stage6ProverInputs::new(&opening_inputs).with_ram_ra_virtual( + Stage6RamRaVirtualWitness { + ram_ra_chunks: &ram_ra_chunks, + }, + ); + let mut prover = Stage6ProverKernelExecutor::new(prover_inputs); + let mut prover_transcript = Blake2bTranscript::::new(b"stage6_test"); + let mut artifacts = execute_stage6_program( + &RAM_RA_PROGRAM, + Stage6ExecutionMode::Prover, + &mut prover, + &mut prover_transcript, + ) + .expect("RAM RA virtualization prover succeeds"); + + artifacts.sumchecks[0].evals[0].value += Fr::from_u64(1); + let proof = Stage6Proof { + sumchecks: artifacts.sumchecks, + }; + let mut verifier = Stage6ProofCarryingKernelExecutor::new(&proof, &opening_inputs); + let mut verifier_transcript = Blake2bTranscript::::new(b"stage6_test"); + let error = execute_stage6_program( + &RAM_RA_PROGRAM, + Stage6ExecutionMode::Verifier, + &mut verifier, + &mut verifier_transcript, + ) + .expect_err("tampered RAM RA eval is rejected"); + + assert_eq!( + error, + Stage6KernelError::InvalidProof { + driver: "stage6.sumcheck", + reason: "batched output claim mismatch" + } + ); + } + + #[test] + fn instruction_ra_virtual_prover_produces_verifiable_sumcheck() { + let instruction_ra_0 = frs(&[1, 2, 3, 4]); + let instruction_ra_1 = frs(&[2, 3, 4, 5]); + let instruction_ra_2 = frs(&[3, 4, 5, 6]); + let instruction_ra_3 = frs(&[4, 5, 6, 7]); + let instruction_ra_4 = frs(&[5, 6, 7, 8]); + let instruction_ra_5 = frs(&[6, 7, 8, 9]); + let instruction_ra_6 = frs(&[7, 8, 9, 10]); + let instruction_ra_7 = frs(&[8, 9, 10, 11]); + let instruction_ra_chunks: [&[Fr]; 8] = [ + &instruction_ra_0, + &instruction_ra_1, + &instruction_ra_2, + &instruction_ra_3, + &instruction_ra_4, + &instruction_ra_5, + &instruction_ra_6, + &instruction_ra_7, + ]; + let input_point = frs(&[2, 3]); + let gamma = Fr::from_u64(3); + let input_claim = + grouped_product_virtual_claim(&instruction_ra_chunks, 2, &input_point, gamma); + let opening_inputs = vec![ + Stage6OpeningInputValue { + symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", + point: input_point.clone(), + eval: input_claim, + }, + Stage6OpeningInputValue { + symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_1", + point: input_point, + eval: Fr::from_u64(0), + }, + Stage6OpeningInputValue { + symbol: "stage6.input.instruction_ra_virtual_claim", + point: Vec::new(), + eval: input_claim, + }, + ]; + let prover_inputs = Stage6ProverInputs::new(&opening_inputs).with_instruction_ra_virtual( + Stage6InstructionRaVirtualWitness { + instruction_ra_chunks: &instruction_ra_chunks, + virtual_count: 2, + }, + ); + let mut prover = Stage6ProverKernelExecutor::new(prover_inputs); + let mut prover_transcript = Blake2bTranscript::::new(b"stage6_test"); + let artifacts = execute_stage6_program( + &INSTRUCTION_RA_PROGRAM, + Stage6ExecutionMode::Prover, + &mut prover, + &mut prover_transcript, + ) + .expect("instruction RA virtualization prover succeeds"); + + assert_eq!(artifacts.sumchecks.len(), 1); + assert_eq!(artifacts.sumchecks[0].evals.len(), 8); + + let proof = Stage6Proof { + sumchecks: artifacts.sumchecks.clone(), + }; + let mut verifier = Stage6ProofCarryingKernelExecutor::new(&proof, &opening_inputs); + let mut verifier_transcript = Blake2bTranscript::::new(b"stage6_test"); + let verified = execute_stage6_program( + &INSTRUCTION_RA_PROGRAM, + Stage6ExecutionMode::Verifier, + &mut verifier, + &mut verifier_transcript, + ) + .expect("proof-carrying verifier accepts instruction RA virtualization output"); + + assert_eq!(artifacts.sumchecks[0].point, verified.sumchecks[0].point); + assert_eq!( + named_eval_values(&artifacts.sumchecks[0].evals), + named_eval_values(&verified.sumchecks[0].evals) + ); + } + + #[test] + fn instruction_ra_virtual_verifier_rejects_bad_final_eval() { + let instruction_ra_0 = frs(&[1, 2, 3, 4]); + let instruction_ra_1 = frs(&[2, 3, 4, 5]); + let instruction_ra_2 = frs(&[3, 4, 5, 6]); + let instruction_ra_3 = frs(&[4, 5, 6, 7]); + let instruction_ra_4 = frs(&[5, 6, 7, 8]); + let instruction_ra_5 = frs(&[6, 7, 8, 9]); + let instruction_ra_6 = frs(&[7, 8, 9, 10]); + let instruction_ra_7 = frs(&[8, 9, 10, 11]); + let instruction_ra_chunks: [&[Fr]; 8] = [ + &instruction_ra_0, + &instruction_ra_1, + &instruction_ra_2, + &instruction_ra_3, + &instruction_ra_4, + &instruction_ra_5, + &instruction_ra_6, + &instruction_ra_7, + ]; + let input_point = frs(&[2, 3]); + let gamma = Fr::from_u64(3); + let input_claim = + grouped_product_virtual_claim(&instruction_ra_chunks, 2, &input_point, gamma); + let opening_inputs = vec![ + Stage6OpeningInputValue { + symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", + point: input_point.clone(), + eval: input_claim, + }, + Stage6OpeningInputValue { + symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_1", + point: input_point, + eval: Fr::from_u64(0), + }, + Stage6OpeningInputValue { + symbol: "stage6.input.instruction_ra_virtual_claim", + point: Vec::new(), + eval: input_claim, + }, + ]; + let prover_inputs = Stage6ProverInputs::new(&opening_inputs).with_instruction_ra_virtual( + Stage6InstructionRaVirtualWitness { + instruction_ra_chunks: &instruction_ra_chunks, + virtual_count: 2, + }, + ); + let mut prover = Stage6ProverKernelExecutor::new(prover_inputs); + let mut prover_transcript = Blake2bTranscript::::new(b"stage6_test"); + let mut artifacts = execute_stage6_program( + &INSTRUCTION_RA_PROGRAM, + Stage6ExecutionMode::Prover, + &mut prover, + &mut prover_transcript, + ) + .expect("instruction RA virtualization prover succeeds"); + + artifacts.sumchecks[0].evals[0].value += Fr::from_u64(1); + let proof = Stage6Proof { + sumchecks: artifacts.sumchecks, + }; + let mut verifier = Stage6ProofCarryingKernelExecutor::new(&proof, &opening_inputs); + let mut verifier_transcript = Blake2bTranscript::::new(b"stage6_test"); + let error = execute_stage6_program( + &INSTRUCTION_RA_PROGRAM, + Stage6ExecutionMode::Verifier, + &mut verifier, + &mut verifier_transcript, + ) + .expect_err("tampered instruction RA eval is rejected"); + + assert_eq!( + error, + Stage6KernelError::InvalidProof { + driver: "stage6.sumcheck", + reason: "batched output claim mismatch" + } + ); + } + + fn replay_proof(input_claim: Fr) -> (Stage6Proof, Vec>) { + let opening_inputs = vec![Stage6OpeningInputValue { + symbol: "stage6.input.claim", + point: Vec::new(), + eval: input_claim, + }]; + let mut transcript = Blake2bTranscript::::new(b"stage6_test"); + append_labeled_scalar(&mut transcript, "sumcheck_claim", &input_claim); + let batching_coeff = transcript.challenge_vector(1)[0]; + let claimed_sum = input_claim * batching_coeff; + let round_poly = UnivariatePoly::new(vec![claimed_sum, -claimed_sum]); + append_compressed_univariate_poly(&mut transcript, "sumcheck_poly", &round_poly); + let point = vec![transcript.challenge()]; + let proof = Stage6Proof { + sumchecks: vec![Stage6SumcheckOutput { + driver: "stage6.sumcheck", + point, + evals: Vec::new(), + opening_claims: Vec::new(), + proof: jolt_sumcheck::SumcheckProof { + round_polynomials: vec![round_poly], + }, + }], + }; + (proof, opening_inputs) + } + + fn bytecode_entries() -> [Stage6BytecodeEntry; 4] { + [ + bytecode_entry(0, 3, &[0, 5, 12], Some(0), Some(1), Some(2), Some(0)), + bytecode_entry(1, 5, &[1, 6], Some(1), None, Some(3), Some(1)), + bytecode_entry(2, 7, &[2, 7, 10], Some(2), Some(0), None, None), + bytecode_entry(3, 11, &[3, 8, 13], None, Some(2), Some(1), Some(0)), + ] + } + + fn bytecode_entry( + address: u64, + imm: u64, + flags: &[usize], + rd: Option, + rs1: Option, + rs2: Option, + lookup_table: Option, + ) -> Stage6BytecodeEntry { + let mut circuit_flags = [false; 14]; + for &flag in flags { + circuit_flags[flag] = true; + } + Stage6BytecodeEntry { + address: Fr::from_u64(address), + imm: Fr::from_u64(imm), + circuit_flags, + rd, + rs1, + rs2, + lookup_table, + is_interleaved: address.is_multiple_of(2), + is_branch: address == 1, + left_is_rs1: rs1.is_some(), + left_is_pc: address == 2, + right_is_rs2: rs2.is_some(), + right_is_imm: address == 3, + is_noop: address == 0, + } + } + + fn bytecode_opening_inputs() -> Vec> { + vec![ + Stage6OpeningInputValue { + symbol: "stage6.input.stage1.Imm", + point: frs(&[17]), + eval: Fr::from_u64(0), + }, + Stage6OpeningInputValue { + symbol: "stage6.input.stage2.OpFlagJump", + point: frs(&[19]), + eval: Fr::from_u64(0), + }, + Stage6OpeningInputValue { + symbol: "stage6.input.stage3.spartan_shift.UnexpandedPC", + point: frs(&[23]), + eval: Fr::from_u64(0), + }, + Stage6OpeningInputValue { + symbol: "stage6.input.stage4.Rs1Ra", + point: frs(&[2, 3, 29]), + eval: Fr::from_u64(0), + }, + Stage6OpeningInputValue { + symbol: "stage6.input.stage5.registers_val_evaluation.RdWa", + point: frs(&[5, 7, 31]), + eval: Fr::from_u64(0), + }, + ] + } + + fn bytecode_read_raf_claim( + data: Stage6BytecodeReadRafData<'_, Fr>, + bytecode_ra_chunks: &[&[Fr]], + opening_inputs: &[Stage6OpeningInputValue], + ) -> Fr { + let mut store = Stage6ValueStore::with_opening_inputs(opening_inputs); + store.seed_constants(&BYTECODE_PROGRAM); + let log_k = 2; + let log_t = 1; + let domain_len = 1 << (log_k + log_t); + let weighted = + bytecode_weighted_value_factor(data, &store, log_k, log_t, domain_len).unwrap(); + let ra_factors = + expanded_bytecode_ra_factors(bytecode_ra_chunks, &[1, 1], log_k, log_t, domain_len) + .unwrap(); + (0..domain_len) + .map(|row| weighted[row] * ra_factors.iter().map(|factor| factor[row]).product::()) + .sum() + } + + fn frs(values: &[u64]) -> Vec { + values.iter().map(|value| Fr::from_u64(*value)).collect() + } + + fn multilinear_eval(values: &[Fr], point: &[Fr]) -> Fr { + EqPolynomial::::evals(point, None) + .into_iter() + .zip(values) + .map(|(eq, value)| eq * *value) + .sum() + } + + fn product_virtual_claim(chunks: &[&[Fr]], point: &[Fr]) -> Fr { + let eq = EqPolynomial::::evals(point, None); + (0..eq.len()) + .map(|row| eq[row] * chunks.iter().map(|chunk| chunk[row]).product::()) + .sum() + } + + fn grouped_product_virtual_claim( + chunks: &[&[Fr]], + virtual_count: usize, + point: &[Fr], + gamma: Fr, + ) -> Fr { + let eq = EqPolynomial::::evals(point, None); + let chunks_per_virtual = chunks.len() / virtual_count; + (0..eq.len()) + .map(|row| { + let mut gamma_power = Fr::from_u64(1); + let mut row_value = Fr::from_u64(0); + for group in chunks.chunks(chunks_per_virtual) { + row_value += gamma_power * group.iter().map(|chunk| chunk[row]).product::(); + gamma_power *= gamma; + } + eq[row] * row_value + }) + .sum() + } + + fn named_eval_values(evals: &[Stage6NamedEval]) -> Vec<(&'static str, &'static str, Fr)> { + evals + .iter() + .map(|eval| (eval.name, eval.oracle, eval.value)) + .collect() + } +} diff --git a/crates/jolt-kernels/src/stage7.rs b/crates/jolt-kernels/src/stage7.rs new file mode 100644 index 0000000000..32d87cb7cf --- /dev/null +++ b/crates/jolt-kernels/src/stage7.rs @@ -0,0 +1,2586 @@ +//! Stage 7 coarse-kernel ABI used by Bolt-generated Jolt prover code. +//! +//! Stage 7 fuses hamming-weight claim reduction with the address reduction for +//! all RA one-hot polynomials. This module owns the prover-side runtime behind +//! the generated `jolt.stage7.*` CPU ABI. + +use std::error::Error; +use std::fmt::{self, Display, Formatter}; + +use crate::dense::bind_dense_evals_reuse; +use jolt_field::Field; +use jolt_poly::{EqPolynomial, UnivariatePoly}; +use jolt_sumcheck::SumcheckProof; +use jolt_transcript::{Label, LabelWithCount, Transcript}; +use jolt_witness::Stage6WitnessSlices; + +pub use crate::stage6::{ + Stage6ChallengeVector as Stage7ChallengeVector, + Stage6ExecutionArtifacts as Stage7ExecutionArtifacts, + Stage6ExecutionMode as Stage7ExecutionMode, Stage6FieldConstantPlan as Stage7FieldConstantPlan, + Stage6FieldExprPlan as Stage7FieldExprPlan, Stage6NamedEval as Stage7NamedEval, + Stage6OpeningBatchPlan as Stage7OpeningBatchPlan, + Stage6OpeningClaimEqualityPlan as Stage7OpeningClaimEqualityPlan, + Stage6OpeningClaimPlan as Stage7OpeningClaimPlan, + Stage6OpeningClaimValue as Stage7OpeningClaimValue, + Stage6OpeningInputPlan as Stage7OpeningInputPlan, + Stage6OpeningInputValue as Stage7OpeningInputValue, Stage6Params as Stage7Params, + Stage6PointConcatPlan as Stage7PointConcatPlan, Stage6PointSlicePlan as Stage7PointSlicePlan, + Stage6PointZeroPlan as Stage7PointZeroPlan, Stage6ProgramStepPlan as Stage7ProgramStepPlan, + Stage6Proof as Stage7Proof, Stage6SumcheckBatchPlan as Stage7SumcheckBatchPlan, + Stage6SumcheckClaimPlan as Stage7SumcheckClaimPlan, + Stage6SumcheckDriverPlan as Stage7SumcheckDriverPlan, + Stage6SumcheckEvalPlan as Stage7SumcheckEvalPlan, + Stage6SumcheckInstanceResultPlan as Stage7SumcheckInstanceResultPlan, + Stage6SumcheckOutput as Stage7SumcheckOutput, + Stage6TranscriptAbsorbBytesPlan as Stage7TranscriptAbsorbBytesPlan, + Stage6TranscriptSqueezePlan as Stage7TranscriptSqueezePlan, +}; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage7KernelPlan { + pub symbol: &'static str, + pub relation: &'static str, + pub kind: &'static str, + pub backend: &'static str, + pub abi: &'static str, +} + +impl Stage7KernelPlan { + pub fn relation_kind(&self) -> Result { + Stage7Relation::from_symbol(self.relation).ok_or(Stage7KernelError::UnknownRelation { + relation: self.relation, + }) + } + + pub fn abi_kind(&self) -> Result { + Stage7KernelAbi::from_name(self.abi) + .ok_or(Stage7KernelError::UnknownKernelAbi { abi: self.abi }) + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage7CpuProgramPlan { + pub role: &'static str, + pub params: Stage7Params, + pub steps: &'static [Stage7ProgramStepPlan], + pub transcript_squeezes: &'static [Stage7TranscriptSqueezePlan], + pub transcript_absorb_bytes: &'static [Stage7TranscriptAbsorbBytesPlan], + pub opening_inputs: &'static [Stage7OpeningInputPlan], + pub field_constants: &'static [Stage7FieldConstantPlan], + pub field_exprs: &'static [Stage7FieldExprPlan], + pub kernels: &'static [Stage7KernelPlan], + pub claims: &'static [Stage7SumcheckClaimPlan], + pub batches: &'static [Stage7SumcheckBatchPlan], + pub drivers: &'static [Stage7SumcheckDriverPlan], + pub instance_results: &'static [Stage7SumcheckInstanceResultPlan], + pub evals: &'static [Stage7SumcheckEvalPlan], + pub point_zeros: &'static [Stage7PointZeroPlan], + pub point_slices: &'static [Stage7PointSlicePlan], + pub point_concats: &'static [Stage7PointConcatPlan], + pub opening_claims: &'static [Stage7OpeningClaimPlan], + pub opening_equalities: &'static [Stage7OpeningClaimEqualityPlan], + pub opening_batches: &'static [Stage7OpeningBatchPlan], +} + +impl Stage7CpuProgramPlan { + pub fn claim(&self, symbol: &str) -> Option<&Stage7SumcheckClaimPlan> { + self.claims.iter().find(|claim| claim.symbol == symbol) + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Stage7Relation { + HammingWeightClaimReduction, + Batched, +} + +impl Stage7Relation { + pub fn from_symbol(symbol: &str) -> Option { + match symbol { + "jolt.stage7.hamming_weight_claim_reduction" => Some(Self::HammingWeightClaimReduction), + "jolt.stage7.batched" => Some(Self::Batched), + _ => None, + } + } + + pub fn symbol(self) -> &'static str { + match self { + Self::HammingWeightClaimReduction => "jolt.stage7.hamming_weight_claim_reduction", + Self::Batched => "jolt.stage7.batched", + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Stage7KernelAbi { + HammingWeightClaimReduction, + Batched, +} + +impl Stage7KernelAbi { + pub fn from_name(name: &str) -> Option { + match name { + "jolt_stage7_hamming_weight_claim_reduction" => Some(Self::HammingWeightClaimReduction), + "jolt_stage7_batched" => Some(Self::Batched), + _ => None, + } + } + + pub fn name(self) -> &'static str { + match self { + Self::HammingWeightClaimReduction => "jolt_stage7_hamming_weight_claim_reduction", + Self::Batched => "jolt_stage7_batched", + } + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum Stage7KernelError { + MissingClaim { + batch: &'static str, + claim: &'static str, + }, + MissingValue { + symbol: &'static str, + }, + MissingDynamicValue { + symbol: String, + }, + MissingDriver { + driver: &'static str, + }, + MissingKernel { + driver: &'static str, + kernel: &'static str, + }, + MissingBatch { + driver: &'static str, + batch: &'static str, + }, + UnknownRelation { + relation: &'static str, + }, + UnknownKernelAbi { + abi: &'static str, + }, + PlanCountMismatch { + artifact: &'static str, + expected: usize, + actual: usize, + }, + InvalidInputLength { + input: &'static str, + expected: usize, + actual: usize, + }, + UnsupportedFieldExpr { + symbol: &'static str, + formula: &'static str, + }, + KernelNotImplemented { + abi: &'static str, + }, + WrongExecutorMode { + driver: &'static str, + expected: Stage7ExecutionMode, + actual: Stage7ExecutionMode, + }, + MissingProof { + driver: &'static str, + }, + MissingKernelInput { + kernel: &'static str, + input: &'static str, + }, + InvalidProgramStep { + symbol: &'static str, + kind: &'static str, + }, + InvalidProof { + driver: &'static str, + reason: &'static str, + }, +} + +impl Display for Stage7KernelError { + fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result { + match self { + Self::MissingClaim { batch, claim } => { + write!( + formatter, + "stage7 batch @{batch} references missing claim @{claim}" + ) + } + Self::MissingValue { symbol } => { + write!(formatter, "stage7 value @{symbol} is not available") + } + Self::MissingDynamicValue { symbol } => { + write!(formatter, "stage7 value @{symbol} is not available") + } + Self::MissingDriver { driver } => { + write!(formatter, "stage7 driver @{driver} is not available") + } + Self::MissingKernel { driver, kernel } => { + write!( + formatter, + "stage7 driver @{driver} references missing kernel @{kernel}" + ) + } + Self::MissingBatch { driver, batch } => { + write!( + formatter, + "stage7 driver @{driver} references missing batch @{batch}" + ) + } + Self::UnknownRelation { relation } => { + write!(formatter, "unknown stage7 relation `{relation}`") + } + Self::UnknownKernelAbi { abi } => { + write!(formatter, "unknown stage7 kernel ABI `{abi}`") + } + Self::PlanCountMismatch { + artifact, + expected, + actual, + } => { + write!( + formatter, + "stage7 {artifact} plan count mismatch: expected {expected}, got {actual}" + ) + } + Self::InvalidInputLength { + input, + expected, + actual, + } => { + write!( + formatter, + "stage7 input `{input}` has length {actual}, expected {expected}" + ) + } + Self::UnsupportedFieldExpr { symbol, formula } => { + write!( + formatter, + "stage7 field expr @{symbol} uses unsupported formula `{formula}`" + ) + } + Self::KernelNotImplemented { abi } => { + write!(formatter, "stage7 kernel ABI `{abi}` is not implemented") + } + Self::WrongExecutorMode { + driver, + expected, + actual, + } => { + write!( + formatter, + "stage7 driver @{driver} expected {expected:?} executor, got {actual:?}" + ) + } + Self::MissingProof { driver } => { + write!(formatter, "stage7 proof for driver @{driver} is missing") + } + Self::MissingKernelInput { kernel, input } => { + write!( + formatter, + "stage7 kernel `{kernel}` is missing required input `{input}`" + ) + } + Self::InvalidProgramStep { symbol, kind } => { + write!( + formatter, + "stage7 program step @{symbol} has invalid kind `{kind}`" + ) + } + Self::InvalidProof { driver, reason } => { + write!( + formatter, + "stage7 proof for driver @{driver} is invalid: {reason}" + ) + } + } + } +} + +impl Error for Stage7KernelError {} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Stage7RaChunkLayout { + CycleMajor, + AddressMajor, +} + +#[derive(Clone, Copy)] +pub struct Stage7RaChunks<'a, F: Field> { + pub chunks: &'a [&'a [F]], + pub layout: Stage7RaChunkLayout, +} + +#[derive(Clone, Copy)] +pub struct Stage7HammingWeightClaimReductionWitness<'a, F: Field> { + pub instruction_ra: Stage7RaChunks<'a, F>, + pub bytecode_ra: Stage7RaChunks<'a, F>, + pub ram_ra: Stage7RaChunks<'a, F>, +} + +#[derive(Clone, Copy)] +pub struct Stage7RaIndexChunks<'a> { + pub chunks: &'a [&'a [Option]], +} + +#[derive(Clone, Copy)] +pub struct Stage7HammingWeightClaimReductionIndexWitness<'a> { + pub instruction_ra: Stage7RaIndexChunks<'a>, + pub bytecode_ra: Stage7RaIndexChunks<'a>, + pub ram_ra: Stage7RaIndexChunks<'a>, +} + +#[derive(Clone, Copy)] +pub struct Stage7ProverInputs<'a, F: Field> { + pub opening_inputs: &'a [Stage7OpeningInputValue], + pub hamming_weight_claim_reduction: Option>, + pub hamming_weight_claim_reduction_indices: + Option>, +} + +impl<'a, F: Field> Stage7ProverInputs<'a, F> { + pub fn new(opening_inputs: &'a [Stage7OpeningInputValue]) -> Self { + Self { + opening_inputs, + hamming_weight_claim_reduction: None, + hamming_weight_claim_reduction_indices: None, + } + } + + pub fn empty() -> Self { + Self { + opening_inputs: &[], + hamming_weight_claim_reduction: None, + hamming_weight_claim_reduction_indices: None, + } + } + + pub fn with_hamming_weight_claim_reduction( + mut self, + witness: Stage7HammingWeightClaimReductionWitness<'a, F>, + ) -> Self { + self.hamming_weight_claim_reduction = Some(witness); + self + } + + pub fn with_hamming_weight_claim_reduction_indices( + mut self, + witness: Stage7HammingWeightClaimReductionIndexWitness<'a>, + ) -> Self { + self.hamming_weight_claim_reduction_indices = Some(witness); + self + } + + pub fn with_stage6_witness_indices(self, slices: &'a Stage6WitnessSlices<'a, F>) -> Self { + self.with_hamming_weight_claim_reduction_indices( + Stage7HammingWeightClaimReductionIndexWitness { + instruction_ra: Stage7RaIndexChunks { + chunks: &slices.instruction_ra_index_chunks, + }, + bytecode_ra: Stage7RaIndexChunks { + chunks: &slices.bytecode_ra_index_chunks, + }, + ram_ra: Stage7RaIndexChunks { + chunks: &slices.ram_ra_index_chunks, + }, + }, + ) + } +} + +#[derive(Clone, Copy, Debug)] +pub struct Stage7KernelContext<'a> { + pub mode: Stage7ExecutionMode, + pub program: &'static Stage7CpuProgramPlan, + pub kernel: &'a Stage7KernelPlan, + pub batch: &'a Stage7SumcheckBatchPlan, + pub driver: &'a Stage7SumcheckDriverPlan, +} + +impl Stage7KernelContext<'_> { + pub fn relation_kind(&self) -> Result { + self.kernel.relation_kind() + } + + pub fn abi_kind(&self) -> Result { + self.kernel.abi_kind() + } + + pub fn batch_claims(&self) -> Result, Stage7KernelError> { + self.batch + .claim_operands + .iter() + .map(|symbol| { + self.program + .claim(symbol) + .ok_or(Stage7KernelError::MissingClaim { + batch: self.batch.symbol, + claim: symbol, + }) + }) + .collect() + } +} + +pub trait Stage7KernelExecutor { + fn observe_challenge_vector( + &mut self, + _plan: &'static Stage7TranscriptSqueezePlan, + _values: &[F], + ) -> Result<(), Stage7KernelError> { + Ok(()) + } + + fn observe_sumcheck_output( + &mut self, + _output: &Stage7SumcheckOutput, + ) -> Result<(), Stage7KernelError> { + Ok(()) + } + + fn prove_sumcheck( + &mut self, + context: Stage7KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage7KernelError> + where + T: Transcript; + + fn verify_sumcheck( + &mut self, + context: Stage7KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage7KernelError> + where + T: Transcript; +} + +#[derive(Clone, Debug, Default)] +pub struct UnsupportedStage7KernelExecutor; + +impl Stage7KernelExecutor for UnsupportedStage7KernelExecutor { + fn prove_sumcheck( + &mut self, + context: Stage7KernelContext<'_>, + _transcript: &mut T, + ) -> Result, Stage7KernelError> + where + T: Transcript, + { + let abi = context.abi_kind()?; + let _ = context.relation_kind()?; + Err(Stage7KernelError::KernelNotImplemented { abi: abi.name() }) + } + + fn verify_sumcheck( + &mut self, + context: Stage7KernelContext<'_>, + _transcript: &mut T, + ) -> Result, Stage7KernelError> + where + T: Transcript, + { + let abi = context.abi_kind()?; + let _ = context.relation_kind()?; + Err(Stage7KernelError::KernelNotImplemented { abi: abi.name() }) + } +} + +#[derive(Clone)] +pub struct Stage7ProverKernelExecutor<'a, F: Field> { + pub inputs: Stage7ProverInputs<'a, F>, + challenge_vectors: Vec>, + completed_sumchecks: Vec>, +} + +impl<'a, F: Field> Stage7ProverKernelExecutor<'a, F> { + pub fn new(inputs: Stage7ProverInputs<'a, F>) -> Self { + Self { + inputs, + challenge_vectors: Vec::new(), + completed_sumchecks: Vec::new(), + } + } + + fn value_store( + &self, + program: &'static Stage7CpuProgramPlan, + ) -> Result, Stage7KernelError> { + value_store_from_observations( + program, + self.inputs.opening_inputs, + &self.challenge_vectors, + &self.completed_sumchecks, + ) + } +} + +impl Stage7KernelExecutor for Stage7ProverKernelExecutor<'_, F> { + fn observe_challenge_vector( + &mut self, + plan: &'static Stage7TranscriptSqueezePlan, + values: &[F], + ) -> Result<(), Stage7KernelError> { + self.challenge_vectors.push(Stage7ChallengeVector { + symbol: plan.symbol, + values: values.to_vec(), + }); + Ok(()) + } + + fn observe_sumcheck_output( + &mut self, + output: &Stage7SumcheckOutput, + ) -> Result<(), Stage7KernelError> { + self.completed_sumchecks.push(output.clone()); + Ok(()) + } + + fn prove_sumcheck( + &mut self, + context: Stage7KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage7KernelError> + where + T: Transcript, + { + prove_stage7_kernel( + context, + &self.inputs, + self.value_store(context.program)?, + transcript, + ) + } + + fn verify_sumcheck( + &mut self, + context: Stage7KernelContext<'_>, + _transcript: &mut T, + ) -> Result, Stage7KernelError> + where + T: Transcript, + { + Err(Stage7KernelError::WrongExecutorMode { + driver: context.driver.symbol, + expected: Stage7ExecutionMode::Prover, + actual: Stage7ExecutionMode::Verifier, + }) + } +} + +#[derive(Clone)] +pub struct Stage7ProofCarryingKernelExecutor<'a, F: Field> { + pub proof: &'a Stage7Proof, + pub opening_inputs: &'a [Stage7OpeningInputValue], + pub cursor: usize, + challenge_vectors: Vec>, + completed_sumchecks: Vec>, +} + +impl<'a, F: Field> Stage7ProofCarryingKernelExecutor<'a, F> { + pub fn new( + proof: &'a Stage7Proof, + opening_inputs: &'a [Stage7OpeningInputValue], + ) -> Self { + Self { + proof, + opening_inputs, + cursor: 0, + challenge_vectors: Vec::new(), + completed_sumchecks: Vec::new(), + } + } + + fn value_store( + &self, + program: &'static Stage7CpuProgramPlan, + ) -> Result, Stage7KernelError> { + value_store_from_observations( + program, + self.opening_inputs, + &self.challenge_vectors, + &self.completed_sumchecks, + ) + } + + fn next_proof( + &mut self, + driver: &'static str, + ) -> Result<&'a Stage7SumcheckOutput, Stage7KernelError> { + let proof = self + .proof + .sumchecks + .get(self.cursor) + .ok_or(Stage7KernelError::MissingProof { driver })?; + self.cursor += 1; + Ok(proof) + } +} + +impl Stage7KernelExecutor for Stage7ProofCarryingKernelExecutor<'_, F> { + fn observe_challenge_vector( + &mut self, + plan: &'static Stage7TranscriptSqueezePlan, + values: &[F], + ) -> Result<(), Stage7KernelError> { + self.challenge_vectors.push(Stage7ChallengeVector { + symbol: plan.symbol, + values: values.to_vec(), + }); + Ok(()) + } + + fn observe_sumcheck_output( + &mut self, + output: &Stage7SumcheckOutput, + ) -> Result<(), Stage7KernelError> { + self.completed_sumchecks.push(output.clone()); + Ok(()) + } + + fn prove_sumcheck( + &mut self, + context: Stage7KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage7KernelError> + where + T: Transcript, + { + let proof = self.next_proof(context.driver.symbol)?; + verify_stage7_kernel( + context, + self.value_store(context.program)?, + proof, + transcript, + ) + } + + fn verify_sumcheck( + &mut self, + context: Stage7KernelContext<'_>, + transcript: &mut T, + ) -> Result, Stage7KernelError> + where + T: Transcript, + { + let proof = self.next_proof(context.driver.symbol)?; + verify_stage7_kernel( + context, + self.value_store(context.program)?, + proof, + transcript, + ) + } +} + +#[derive(Clone, Debug, Default)] +struct Stage7ValueStore { + scalars: Vec<(&'static str, F)>, + points: Vec<(&'static str, Vec)>, +} + +impl Stage7ValueStore { + fn with_opening_inputs(inputs: &[Stage7OpeningInputValue]) -> Self { + let mut store = Self::default(); + for input in inputs { + store.insert_scalar(input.symbol, input.eval); + store.insert_point(input.symbol, input.point.clone()); + } + store + } + + fn seed_constants(&mut self, program: &'static Stage7CpuProgramPlan) { + for constant in program.field_constants { + self.insert_scalar(constant.symbol, F::from_u64(constant.value as u64)); + } + for zero in program.point_zeros { + self.insert_point(zero.symbol, vec![F::from_u64(0); zero.arity]); + } + } + + fn observe_challenge_vector( + &mut self, + plan: &'static Stage7TranscriptSqueezePlan, + values: &[F], + ) -> Result<(), Stage7KernelError> { + self.insert_point(plan.symbol, values.to_vec()); + if matches!(plan.kind, "challenge_scalar" | "scalar") { + require_operand_count(plan.symbol, 1, values.len())?; + self.insert_scalar(plan.symbol, values[0]); + } + Ok(()) + } + + fn observe_sumcheck_output( + &mut self, + program: &'static Stage7CpuProgramPlan, + output: &Stage7SumcheckOutput, + ) -> Result<(), Stage7KernelError> { + self.observe_sumcheck_values(program, output.driver, &output.point, &output.evals) + } + + fn observe_sumcheck_values( + &mut self, + program: &'static Stage7CpuProgramPlan, + driver: &'static str, + point: &[F], + evals: &[Stage7NamedEval], + ) -> Result<(), Stage7KernelError> { + self.insert_point(driver, point.to_vec()); + for instance in program + .instance_results + .iter() + .filter(|instance| instance.source == driver) + { + let end = instance.round_offset + instance.point_arity; + let mut point = point + .get(instance.round_offset..end) + .ok_or(Stage7KernelError::InvalidInputLength { + input: instance.symbol, + expected: end, + actual: point.len(), + })? + .to_vec(); + match instance.point_order { + "as_is" => {} + "reverse" => point.reverse(), + _ => { + return Err(Stage7KernelError::InvalidProof { + driver, + reason: "unsupported point order", + }); + } + } + self.insert_point(instance.symbol, point); + } + for eval in program.evals.iter().filter(|eval| eval.source == driver) { + let value = evals + .iter() + .find(|value| value.name == eval.name) + .or_else(|| evals.get(eval.index)) + .ok_or(Stage7KernelError::MissingValue { + symbol: eval.symbol, + })? + .value; + self.insert_scalar(eval.symbol, value); + self.insert_scalar(eval.name, value); + } + let _ = self.evaluate_available_points(program)?; + let _ = self.evaluate_available_field_exprs(program)?; + self.verify_opening_equalities(program)?; + Ok(()) + } + + fn evaluate_available_field_exprs( + &mut self, + program: &'static Stage7CpuProgramPlan, + ) -> Result { + let mut inserted = 0usize; + loop { + let mut progress = 0usize; + for expr in program.field_exprs { + if self.try_scalar(expr.symbol).is_some() { + continue; + } + let Some(operands) = self.try_expr_operands(expr) else { + continue; + }; + self.insert_scalar(expr.symbol, evaluate_stage7_field_expr(expr, &operands)?); + progress += 1; + } + inserted += progress; + if progress == 0 { + return Ok(inserted); + } + } + } + + fn evaluate_available_points( + &mut self, + program: &'static Stage7CpuProgramPlan, + ) -> Result { + let mut inserted = 0usize; + loop { + let mut progress = 0usize; + for slice in program.point_slices { + if self.try_point(slice.symbol).is_some() { + continue; + } + let Some(input) = self.try_point(slice.input) else { + continue; + }; + let end = slice.offset + slice.length; + let point = input + .get(slice.offset..end) + .ok_or(Stage7KernelError::InvalidInputLength { + input: slice.symbol, + expected: end, + actual: input.len(), + })? + .to_vec(); + self.insert_point(slice.symbol, point); + progress += 1; + } + for concat in program.point_concats { + if self.try_point(concat.symbol).is_some() { + continue; + } + let Some(point) = self.try_concat_point(concat) else { + continue; + }; + require_operand_count(concat.symbol, concat.arity, point.len())?; + self.insert_point(concat.symbol, point); + progress += 1; + } + inserted += progress; + if progress == 0 { + return Ok(inserted); + } + } + } + + fn verify_opening_equalities( + &self, + program: &'static Stage7CpuProgramPlan, + ) -> Result<(), Stage7KernelError> { + for equality in program.opening_equalities { + match equality.mode { + "point_and_eval" => { + if self.point(equality.lhs)? != self.point(equality.rhs)? + || self.scalar(equality.lhs)? != self.scalar(equality.rhs)? + { + return Err(Stage7KernelError::InvalidProof { + driver: equality.symbol, + reason: "opening claim equality failed", + }); + } + } + _ => { + return Err(Stage7KernelError::InvalidProof { + driver: equality.symbol, + reason: "unsupported opening equality mode", + }); + } + } + } + Ok(()) + } + + fn claim_value( + &mut self, + program: &'static Stage7CpuProgramPlan, + claim: &Stage7SumcheckClaimPlan, + ) -> Result { + let _ = self.evaluate_available_field_exprs(program)?; + self.scalar(claim.claim_value) + } + + fn batch_claim_values( + &mut self, + program: &'static Stage7CpuProgramPlan, + batch: &Stage7SumcheckBatchPlan, + ) -> Result, Stage7KernelError> { + batch + .claim_operands + .iter() + .map(|symbol| { + let claim = program + .claim(symbol) + .ok_or(Stage7KernelError::MissingClaim { + batch: batch.symbol, + claim: symbol, + })?; + self.claim_value(program, claim) + }) + .collect() + } + + fn insert_scalar(&mut self, symbol: &'static str, value: F) { + if let Some((_, existing)) = self + .scalars + .iter_mut() + .find(|(existing, _)| *existing == symbol) + { + *existing = value; + } else { + self.scalars.push((symbol, value)); + } + } + + fn insert_point(&mut self, symbol: &'static str, point: Vec) { + if let Some((_, existing)) = self + .points + .iter_mut() + .find(|(existing, _)| *existing == symbol) + { + *existing = point; + } else { + self.points.push((symbol, point)); + } + } + + fn scalar(&self, symbol: &'static str) -> Result { + self.try_scalar(symbol) + .ok_or(Stage7KernelError::MissingValue { symbol }) + } + + fn try_scalar(&self, symbol: &str) -> Option { + self.scalars + .iter() + .find(|(existing, _)| *existing == symbol) + .map(|(_, value)| *value) + } + + fn point(&self, symbol: &'static str) -> Result<&[F], Stage7KernelError> { + self.try_point(symbol) + .ok_or(Stage7KernelError::MissingValue { symbol }) + } + + fn dynamic_point(&self, symbol: String) -> Result<&[F], Stage7KernelError> { + self.try_point(&symbol) + .ok_or(Stage7KernelError::MissingDynamicValue { symbol }) + } + + fn try_point(&self, symbol: &str) -> Option<&[F]> { + self.points + .iter() + .find(|(existing, _)| *existing == symbol) + .map(|(_, point)| point.as_slice()) + } + + fn try_expr_operands(&self, expr: &Stage7FieldExprPlan) -> Option> { + expr.operands + .iter() + .map(|operand| self.try_scalar(operand)) + .collect() + } + + fn try_concat_point(&self, concat: &Stage7PointConcatPlan) -> Option> { + let mut point = Vec::with_capacity(concat.arity); + for input in concat.inputs { + point.extend_from_slice(self.try_point(input)?); + } + Some(point) + } +} + +fn value_store_from_observations( + program: &'static Stage7CpuProgramPlan, + opening_inputs: &[Stage7OpeningInputValue], + challenge_vectors: &[Stage7ChallengeVector], + completed_sumchecks: &[Stage7SumcheckOutput], +) -> Result, Stage7KernelError> { + let mut store = Stage7ValueStore::with_opening_inputs(opening_inputs); + store.seed_constants(program); + for challenge in challenge_vectors { + let plan = + find_squeeze(program, challenge.symbol).ok_or(Stage7KernelError::MissingValue { + symbol: challenge.symbol, + })?; + store.observe_challenge_vector(plan, &challenge.values)?; + } + for output in completed_sumchecks { + store.observe_sumcheck_output(program, output)?; + } + let _ = store.evaluate_available_points(program)?; + let _ = store.evaluate_available_field_exprs(program)?; + store.verify_opening_equalities(program)?; + Ok(store) +} + +fn prove_stage7_kernel( + context: Stage7KernelContext<'_>, + inputs: &Stage7ProverInputs<'_, F>, + store: Stage7ValueStore, + transcript: &mut T, +) -> Result, Stage7KernelError> +where + F: Field, + T: Transcript, +{ + match context.abi_kind()? { + Stage7KernelAbi::Batched => prove_batched_stage7(context, inputs, store, transcript), + abi @ Stage7KernelAbi::HammingWeightClaimReduction => { + Err(Stage7KernelError::KernelNotImplemented { abi: abi.name() }) + } + } +} + +fn verify_stage7_kernel( + context: Stage7KernelContext<'_>, + store: Stage7ValueStore, + proof: &Stage7SumcheckOutput, + transcript: &mut T, +) -> Result, Stage7KernelError> +where + F: Field, + T: Transcript, +{ + match context.abi_kind()? { + Stage7KernelAbi::Batched => verify_batched_stage7(context, store, proof, transcript), + abi @ Stage7KernelAbi::HammingWeightClaimReduction => { + Err(Stage7KernelError::KernelNotImplemented { abi: abi.name() }) + } + } +} + +#[tracing::instrument(skip_all, name = "Stage7::prove_batched")] +fn prove_batched_stage7( + context: Stage7KernelContext<'_>, + inputs: &Stage7ProverInputs<'_, F>, + mut store: Stage7ValueStore, + transcript: &mut T, +) -> Result, Stage7KernelError> +where + F: Field, + T: Transcript, +{ + let claims = context.batch_claims()?; + let input_claims = store.batch_claim_values(context.program, context.batch)?; + for claim in &input_claims { + append_labeled_scalar(transcript, context.batch.claim_label, claim); + } + let batching_coeffs = transcript.challenge_vector(claims.len()); + let max_rounds = context.driver.num_rounds; + let two_inv = F::from_u64(2) + .inverse() + .ok_or(Stage7KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "field element 2 is not invertible", + })?; + let mut instances = Vec::with_capacity(claims.len()); + for (index, claim) in claims.iter().enumerate() { + let offset = instance_round_offset(context.program, context.driver.symbol, claim.symbol)?; + if offset + claim.num_rounds > max_rounds { + return Err(Stage7KernelError::InvalidInputLength { + input: claim.symbol, + expected: max_rounds, + actual: offset + claim.num_rounds, + }); + } + let relation = claim_relation(context.program, claim)?; + let active_scale = F::one().mul_pow_2(max_rounds - offset - claim.num_rounds); + let state = + Stage7ProverInstanceState::new(context.program, claim, inputs, &store, active_scale)?; + instances.push(Stage7BatchedInstance { + claim, + relation, + offset, + previous_claim: input_claims[index].mul_pow_2(max_rounds - claim.num_rounds), + state, + }); + } + + let mut point = Vec::with_capacity(max_rounds); + let mut round_polynomials = Vec::with_capacity(max_rounds); + let mut batched_claim = instances + .iter() + .zip(&batching_coeffs) + .map(|(instance, &coefficient)| instance.previous_claim * coefficient) + .sum::(); + for round in 0..max_rounds { + let mut individual_polys = Vec::with_capacity(instances.len()); + for instance in &mut instances { + let poly = if instance.is_active(round) { + instance + .state + .round_poly(instance.previous_claim, instance.relation)? + } else { + UnivariatePoly::new(vec![instance.previous_claim * two_inv]) + }; + individual_polys.push(poly); + } + let batched_poly = combine_univariate_polys(&individual_polys, &batching_coeffs); + if batched_poly.evaluate(F::zero()) + batched_poly.evaluate(F::one()) != batched_claim { + return Err(Stage7KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched round claim mismatch", + }); + } + append_compressed_univariate_poly(transcript, context.driver.round_label, &batched_poly); + let challenge = transcript.challenge(); + point.push(challenge); + batched_claim = batched_poly.evaluate(challenge); + for (instance, poly) in instances.iter_mut().zip(individual_polys) { + instance.previous_claim = poly.evaluate(challenge); + if instance.is_active(round) { + instance.state.ingest_challenge(challenge); + } + } + round_polynomials.push(batched_poly); + } + + let mut evals = Vec::new(); + let mut expected = F::zero(); + for (instance, &coefficient) in instances.iter().zip(&batching_coeffs) { + let relation_claim = instance.state.final_relation_eval(instance.relation)?; + if instance.previous_claim != relation_claim { + return Err(Stage7KernelError::InvalidProof { + driver: instance.relation.symbol(), + reason: "stage7 relation output claim mismatch", + }); + } + expected += coefficient * relation_claim; + evals.extend(instance.state.final_evals(instance.relation)?); + } + if batched_claim != expected { + return Err(Stage7KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched output claim mismatch", + }); + } + store.observe_sumcheck_values(context.program, context.driver.symbol, &point, &evals)?; + let opening_claims = append_opening_claims(context.program, &mut store, transcript, &evals)?; + Ok(Stage7SumcheckOutput { + driver: context.driver.symbol, + point, + evals, + opening_claims, + proof: SumcheckProof { round_polynomials }, + }) +} + +fn verify_batched_stage7( + context: Stage7KernelContext<'_>, + mut store: Stage7ValueStore, + proof: &Stage7SumcheckOutput, + transcript: &mut T, +) -> Result, Stage7KernelError> +where + F: Field, + T: Transcript, +{ + if proof.driver != context.driver.symbol { + return Err(Stage7KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "driver symbol mismatch", + }); + } + if proof.proof.round_polynomials.len() != context.driver.num_rounds { + return Err(Stage7KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "unexpected batched round count", + }); + } + + let claims = context.batch_claims()?; + let input_claims = store.batch_claim_values(context.program, context.batch)?; + for claim in &input_claims { + append_labeled_scalar(transcript, context.batch.claim_label, claim); + } + let batching_coeffs = transcript.challenge_vector(claims.len()); + let max_rounds = context.driver.num_rounds; + let mut running_claim = input_claims + .iter() + .zip(claims.iter()) + .zip(&batching_coeffs) + .map(|((claim, plan), &coefficient)| { + claim.mul_pow_2(max_rounds - plan.num_rounds) * coefficient + }) + .sum::(); + let mut point = Vec::with_capacity(max_rounds); + for poly in &proof.proof.round_polynomials { + if polynomial_degree(poly) > context.driver.degree { + return Err(Stage7KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched polynomial exceeds degree bound", + }); + } + if poly.evaluate(F::zero()) + poly.evaluate(F::one()) != running_claim { + return Err(Stage7KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched round check failed", + }); + } + append_compressed_univariate_poly(transcript, context.driver.round_label, poly); + let challenge = transcript.challenge(); + running_claim = poly.evaluate(challenge); + point.push(challenge); + } + if !proof.point.is_empty() && proof.point != point { + return Err(Stage7KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched point mismatch", + }); + } + let expected = + expected_batched_output_claim(context, &store, &proof.evals, &point, &batching_coeffs)?; + if running_claim != expected { + return Err(Stage7KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "batched output claim mismatch", + }); + } + + let output = Stage7SumcheckOutput { + driver: context.driver.symbol, + point, + evals: proof.evals.clone(), + opening_claims: Vec::new(), + proof: proof.proof.clone(), + }; + store.observe_sumcheck_output(context.program, &output)?; + let opening_claims = + append_opening_claims(context.program, &mut store, &mut *transcript, &output.evals)?; + let output = Stage7SumcheckOutput { + opening_claims, + ..output + }; + Ok(output) +} + +fn expected_batched_output_claim( + context: Stage7KernelContext<'_>, + store: &Stage7ValueStore, + evals: &[Stage7NamedEval], + point: &[F], + batching_coeffs: &[F], +) -> Result { + let mut expected = F::zero(); + for (claim, &coefficient) in context.batch_claims()?.iter().zip(batching_coeffs) { + let Some(instance) = context.program.instance_results.iter().find(|instance| { + instance.claim == claim.symbol && instance.source == context.driver.symbol + }) else { + return Err(Stage7KernelError::MissingValue { + symbol: claim.symbol, + }); + }; + let local_point = point + .get(instance.round_offset..instance.round_offset + instance.num_rounds) + .ok_or(Stage7KernelError::InvalidInputLength { + input: instance.symbol, + expected: instance.round_offset + instance.num_rounds, + actual: point.len(), + })?; + let value = match claim_relation(context.program, claim)? { + Stage7Relation::HammingWeightClaimReduction => { + expected_hamming_weight_claim_reduction(context.program, store, evals, local_point)? + } + Stage7Relation::Batched => { + return Err(Stage7KernelError::InvalidProof { + driver: context.driver.symbol, + reason: "nested batched relation is unsupported", + }); + } + }; + expected += coefficient * value; + } + Ok(expected) +} + +fn expected_hamming_weight_claim_reduction( + program: &'static Stage7CpuProgramPlan, + store: &Stage7ValueStore, + evals: &[Stage7NamedEval], + local_point: &[F], +) -> Result { + let log_k_chunk = local_point.len(); + let booleanity_point = store.point("stage7.input.stage6.booleanity.InstructionRa_0")?; + if booleanity_point.len() < log_k_chunk { + return Err(Stage7KernelError::InvalidInputLength { + input: "stage7.input.stage6.booleanity.InstructionRa_0", + expected: log_k_chunk, + actual: booleanity_point.len(), + }); + } + let r_addr_bool = &booleanity_point[..log_k_chunk]; + let rho_rev = reverse_slice(local_point); + let eq_bool_eval = EqPolynomial::::mle(&rho_rev, r_addr_bool); + let gamma = store.scalar("stage7.hamming_weight_claim_reduction.gamma")?; + let gamma_powers = gamma_powers(gamma, 3 * ra_eval_plans(program).len()); + + let mut output_claim = F::zero(); + for (index, eval_plan) in ra_eval_plans(program).iter().enumerate() { + let g_i = eval_by_name(evals, eval_plan.name)?; + let virtual_point = + store.dynamic_point(stage7_virtualization_input_symbol(eval_plan.oracle)?)?; + if virtual_point.len() < log_k_chunk { + return Err(Stage7KernelError::InvalidInputLength { + input: "stage7.hamming_weight_claim_reduction.virtualization_point", + expected: log_k_chunk, + actual: virtual_point.len(), + }); + } + let eq_virt_eval = EqPolynomial::::mle(&rho_rev, &virtual_point[..log_k_chunk]); + output_claim += g_i + * (gamma_powers[3 * index] + + gamma_powers[3 * index + 1] * eq_bool_eval + + gamma_powers[3 * index + 2] * eq_virt_eval); + } + Ok(output_claim) +} + +struct Stage7BatchedInstance<'a, F: Field> { + claim: &'a Stage7SumcheckClaimPlan, + relation: Stage7Relation, + offset: usize, + previous_claim: F, + state: Stage7ProverInstanceState, +} + +impl Stage7BatchedInstance<'_, F> { + fn is_active(&self, round: usize) -> bool { + round >= self.offset && round < self.offset + self.claim.num_rounds + } +} + +enum Stage7ProverInstanceState { + HammingWeightClaimReduction(HammingWeightClaimReductionState), +} + +impl Stage7ProverInstanceState { + fn new( + program: &'static Stage7CpuProgramPlan, + claim: &Stage7SumcheckClaimPlan, + inputs: &Stage7ProverInputs<'_, F>, + store: &Stage7ValueStore, + active_scale: F, + ) -> Result { + match claim_relation(program, claim)? { + Stage7Relation::HammingWeightClaimReduction => { + hamming_weight_claim_reduction_state(program, claim, inputs, store, active_scale) + .map(Self::HammingWeightClaimReduction) + } + relation @ Stage7Relation::Batched => Err(Stage7KernelError::KernelNotImplemented { + abi: relation.symbol(), + }), + } + } + + fn round_poly( + &mut self, + previous_claim: F, + relation: Stage7Relation, + ) -> Result, Stage7KernelError> { + match self { + Self::HammingWeightClaimReduction(state) => state.round_poly(previous_claim, relation), + } + } + + fn ingest_challenge(&mut self, challenge: F) { + match self { + Self::HammingWeightClaimReduction(state) => state.bind(challenge), + } + } + + fn final_relation_eval(&self, relation: Stage7Relation) -> Result { + match self { + Self::HammingWeightClaimReduction(state) => state.final_relation_eval(relation), + } + } + + fn final_evals( + &self, + relation: Stage7Relation, + ) -> Result>, Stage7KernelError> { + match self { + Self::HammingWeightClaimReduction(state) => state.final_evals(relation), + } + } +} + +struct HammingWeightClaimReductionState { + g: Vec>, + eq_bool: Vec, + eq_virt: Vec>, + gamma_powers: Vec, + outputs: Vec, + active_scale: F, +} + +#[derive(Clone, Copy)] +struct Stage7RaOutputPlan { + name: &'static str, + oracle: &'static str, +} + +impl HammingWeightClaimReductionState { + fn round_poly( + &mut self, + previous_claim: F, + relation: Stage7Relation, + ) -> Result, Stage7KernelError> { + if relation != Stage7Relation::HammingWeightClaimReduction { + return Err(Stage7KernelError::InvalidProof { + driver: relation.symbol(), + reason: "wrong relation for hamming-weight claim-reduction state", + }); + } + let half_len = self + .g + .first() + .ok_or(Stage7KernelError::InvalidProof { + driver: relation.symbol(), + reason: "missing G polynomial", + })? + .len() + / 2; + let mut evals = [F::zero(); 2]; + for row in 0..half_len { + let eq_bool_evals = low_to_high_linear_evals(&self.eq_bool, row); + for index in 0..self.g.len() { + let g_evals = low_to_high_linear_evals(&self.g[index], row); + let eq_virt_evals = low_to_high_linear_evals(&self.eq_virt[index], row); + let gamma_hw = self.gamma_powers[3 * index]; + let gamma_bool = self.gamma_powers[3 * index + 1]; + let gamma_virt = self.gamma_powers[3 * index + 2]; + for eval_index in 0..2 { + evals[eval_index] += g_evals[eval_index] + * (gamma_hw + + gamma_bool * eq_bool_evals[eval_index] + + gamma_virt * eq_virt_evals[eval_index]); + } + } + } + for eval in &mut evals { + *eval *= self.active_scale; + } + Ok(UnivariatePoly::from_evals_and_hint(previous_claim, &evals)) + } + + fn bind(&mut self, challenge: F) { + let mut scratch = Vec::new(); + for g in &mut self.g { + bind_dense_evals_reuse(g, &mut scratch, challenge); + } + bind_dense_evals_reuse(&mut self.eq_bool, &mut scratch, challenge); + for eq in &mut self.eq_virt { + bind_dense_evals_reuse(eq, &mut scratch, challenge); + } + } + + fn final_relation_eval(&self, relation: Stage7Relation) -> Result { + if relation != Stage7Relation::HammingWeightClaimReduction { + return Err(Stage7KernelError::InvalidProof { + driver: relation.symbol(), + reason: "wrong relation for hamming-weight claim-reduction state", + }); + } + let eq_bool = single_final_eval(&self.eq_bool, "stage7.eq_bool")?; + let mut value = F::zero(); + for index in 0..self.g.len() { + let g = single_final_eval(&self.g[index], "stage7.G")?; + let eq_virt = single_final_eval(&self.eq_virt[index], "stage7.eq_virt")?; + value += g + * (self.gamma_powers[3 * index] + + self.gamma_powers[3 * index + 1] * eq_bool + + self.gamma_powers[3 * index + 2] * eq_virt); + } + Ok(value * self.active_scale) + } + + fn final_evals( + &self, + relation: Stage7Relation, + ) -> Result>, Stage7KernelError> { + if relation != Stage7Relation::HammingWeightClaimReduction { + return Err(Stage7KernelError::InvalidProof { + driver: relation.symbol(), + reason: "wrong relation for hamming-weight claim-reduction state", + }); + } + if self.outputs.len() != self.g.len() { + return Err(Stage7KernelError::PlanCountMismatch { + artifact: "hamming-weight claim-reduction eval outputs", + expected: self.g.len(), + actual: self.outputs.len(), + }); + } + self.g + .iter() + .zip(&self.outputs) + .map(|(g, output)| { + Ok(Stage7NamedEval { + name: output.name, + oracle: output.oracle, + value: single_final_eval(g, output.name)?, + }) + }) + .collect() + } +} + +fn hamming_weight_claim_reduction_state( + program: &'static Stage7CpuProgramPlan, + claim: &Stage7SumcheckClaimPlan, + inputs: &Stage7ProverInputs<'_, F>, + store: &Stage7ValueStore, + active_scale: F, +) -> Result, Stage7KernelError> { + let log_k_chunk = claim.num_rounds; + let booleanity_point = store.point("stage7.input.stage6.booleanity.InstructionRa_0")?; + if booleanity_point.len() < log_k_chunk { + return Err(Stage7KernelError::InvalidInputLength { + input: "stage7.input.stage6.booleanity.InstructionRa_0", + expected: log_k_chunk, + actual: booleanity_point.len(), + }); + } + let r_addr_bool = &booleanity_point[..log_k_chunk]; + let r_cycle = &booleanity_point[log_k_chunk..]; + let outputs = ra_eval_plans(program); + let eq_cycle = EqPolynomial::::evals(r_cycle, None); + let g = if let Some(index_witness) = inputs.hamming_weight_claim_reduction_indices { + let chunks = index_witness.ra_chunks_in_program_order(); + if chunks.len() != outputs.len() { + return Err(Stage7KernelError::PlanCountMismatch { + artifact: "stage7 RA index witness chunks", + expected: outputs.len(), + actual: chunks.len(), + }); + } + chunks + .iter() + .map(|chunk| pushforward_ra_indices(chunk.indices, log_k_chunk, &eq_cycle)) + .collect::, _>>()? + } else { + let witness = + inputs + .hamming_weight_claim_reduction + .ok_or(Stage7KernelError::MissingKernelInput { + kernel: "jolt_stage7_hamming_weight_claim_reduction", + input: "hamming_weight_claim_reduction", + })?; + let chunks = witness.ra_chunks_in_program_order(); + if chunks.len() != outputs.len() { + return Err(Stage7KernelError::PlanCountMismatch { + artifact: "stage7 RA witness chunks", + expected: outputs.len(), + actual: chunks.len(), + }); + } + chunks + .iter() + .map(|chunk| pushforward_ra_chunk(chunk.evals, chunk.layout, log_k_chunk, &eq_cycle)) + .collect::, _>>()? + }; + let eq_bool = EqPolynomial::::evals(r_addr_bool, None); + let mut eq_virt = Vec::with_capacity(outputs.len()); + for output in &outputs { + let virtual_point = + store.dynamic_point(stage7_virtualization_input_symbol(output.oracle)?)?; + if virtual_point.len() < log_k_chunk { + return Err(Stage7KernelError::InvalidInputLength { + input: "stage7.hamming_weight_claim_reduction.virtualization_point", + expected: log_k_chunk, + actual: virtual_point.len(), + }); + } + eq_virt.push(EqPolynomial::::evals( + &virtual_point[..log_k_chunk], + None, + )); + } + let gamma = store.scalar("stage7.hamming_weight_claim_reduction.gamma")?; + let gamma_powers = gamma_powers(gamma, 3 * outputs.len()); + Ok(HammingWeightClaimReductionState { + g, + eq_bool, + eq_virt, + gamma_powers, + outputs, + active_scale, + }) +} + +#[derive(Clone, Copy)] +struct Stage7RaChunk<'a, F: Field> { + evals: &'a [F], + layout: Stage7RaChunkLayout, +} + +#[derive(Clone, Copy)] +struct Stage7RaIndexChunk<'a> { + indices: &'a [Option], +} + +impl<'a, F: Field> Stage7HammingWeightClaimReductionWitness<'a, F> { + fn ra_chunks_in_program_order(&self) -> Vec> { + let mut chunks = Vec::with_capacity( + self.instruction_ra.chunks.len() + + self.bytecode_ra.chunks.len() + + self.ram_ra.chunks.len(), + ); + chunks.extend( + self.instruction_ra + .chunks + .iter() + .map(|chunk| Stage7RaChunk { + evals: chunk, + layout: self.instruction_ra.layout, + }), + ); + chunks.extend(self.bytecode_ra.chunks.iter().map(|chunk| Stage7RaChunk { + evals: chunk, + layout: self.bytecode_ra.layout, + })); + chunks.extend(self.ram_ra.chunks.iter().map(|chunk| Stage7RaChunk { + evals: chunk, + layout: self.ram_ra.layout, + })); + chunks + } +} + +impl<'a> Stage7HammingWeightClaimReductionIndexWitness<'a> { + fn ra_chunks_in_program_order(&self) -> Vec> { + let mut chunks = Vec::with_capacity( + self.instruction_ra.chunks.len() + + self.bytecode_ra.chunks.len() + + self.ram_ra.chunks.len(), + ); + chunks.extend( + self.instruction_ra + .chunks + .iter() + .map(|indices| Stage7RaIndexChunk { indices }), + ); + chunks.extend( + self.bytecode_ra + .chunks + .iter() + .map(|indices| Stage7RaIndexChunk { indices }), + ); + chunks.extend( + self.ram_ra + .chunks + .iter() + .map(|indices| Stage7RaIndexChunk { indices }), + ); + chunks + } +} + +fn pushforward_ra_chunk( + chunk: &[F], + layout: Stage7RaChunkLayout, + log_k_chunk: usize, + eq_cycle: &[F], +) -> Result, Stage7KernelError> { + let address_len = 1usize << log_k_chunk; + let cycle_len = eq_cycle.len(); + let expected = address_len * cycle_len; + if chunk.len() != expected { + return Err(Stage7KernelError::InvalidInputLength { + input: "stage7.ra_chunk", + expected, + actual: chunk.len(), + }); + } + let mut output = vec![F::zero(); address_len]; + match layout { + Stage7RaChunkLayout::CycleMajor => { + for (cycle, weight) in eq_cycle.iter().copied().enumerate().take(cycle_len) { + let row_start = cycle * address_len; + for address in 0..address_len { + output[address] += chunk[row_start + address] * weight; + } + } + } + Stage7RaChunkLayout::AddressMajor => { + for (address, output_value) in output.iter_mut().enumerate().take(address_len) { + let row_start = address * cycle_len; + for (cycle, weight) in eq_cycle.iter().copied().enumerate().take(cycle_len) { + *output_value += chunk[row_start + cycle] * weight; + } + } + } + } + Ok(output) +} + +fn pushforward_ra_indices( + indices: &[Option], + log_k_chunk: usize, + eq_cycle: &[F], +) -> Result, Stage7KernelError> { + let address_len = 1usize << log_k_chunk; + if indices.len() != eq_cycle.len() { + return Err(Stage7KernelError::InvalidInputLength { + input: "stage7.ra_index_chunk", + expected: eq_cycle.len(), + actual: indices.len(), + }); + } + let mut output = vec![F::zero(); address_len]; + for (cycle, index) in indices.iter().enumerate() { + if let Some(index) = index { + let index = usize::from(*index); + if index >= address_len { + return Err(Stage7KernelError::InvalidInputLength { + input: "stage7.ra_index", + expected: address_len, + actual: index + 1, + }); + } + output[index] += eq_cycle[cycle]; + } + } + Ok(output) +} + +fn low_to_high_linear_evals(evals: &[F], row: usize) -> [F; 2] { + let low = evals[2 * row]; + let high = evals[2 * row + 1]; + [low, low + (high - low) * F::from_u64(2)] +} + +fn single_final_eval(evals: &[F], symbol: &'static str) -> Result { + if evals.len() == 1 { + Ok(evals[0]) + } else { + Err(Stage7KernelError::InvalidInputLength { + input: symbol, + expected: 1, + actual: evals.len(), + }) + } +} + +fn gamma_powers(gamma: F, count: usize) -> Vec { + let mut powers = Vec::with_capacity(count); + let mut power = F::one(); + for _ in 0..count { + powers.push(power); + power *= gamma; + } + powers +} + +fn ra_eval_plans(program: &'static Stage7CpuProgramPlan) -> Vec { + let mut evals = program + .evals + .iter() + .filter(|eval| { + eval.name + .starts_with("stage7.hamming_weight_claim_reduction.eval.") + }) + .collect::>(); + evals.sort_by_key(|eval| eval.index); + evals + .into_iter() + .map(|eval| Stage7RaOutputPlan { + name: eval.name, + oracle: eval.oracle, + }) + .collect() +} + +fn stage7_virtualization_input_symbol(oracle: &str) -> Result { + if oracle.starts_with("InstructionRa_") { + Ok(format!( + "stage7.input.stage6.instruction_ra_virtual.{oracle}" + )) + } else if oracle.starts_with("BytecodeRa_") { + Ok(format!("stage7.input.stage6.bytecode_read_raf.{oracle}")) + } else if oracle.starts_with("RamRa_") { + Ok(format!("stage7.input.stage6.ram_ra_virtual.{oracle}")) + } else { + Err(Stage7KernelError::InvalidProof { + driver: "stage7.hamming_weight_claim_reduction.oracle", + reason: "unknown RA oracle family", + }) + } +} + +fn eval_by_name( + evals: &[Stage7NamedEval], + name: &'static str, +) -> Result { + evals + .iter() + .find(|eval| eval.name == name) + .map(|eval| eval.value) + .ok_or(Stage7KernelError::MissingValue { symbol: name }) +} + +fn claim_relation( + program: &'static Stage7CpuProgramPlan, + claim: &Stage7SumcheckClaimPlan, +) -> Result { + if let Some(relation) = claim.relation { + return Stage7Relation::from_symbol(relation) + .ok_or(Stage7KernelError::UnknownRelation { relation }); + } + let kernel_symbol = claim.kernel.ok_or(Stage7KernelError::MissingKernel { + driver: claim.symbol, + kernel: "", + })?; + let kernel = find_kernel(program, kernel_symbol).ok_or(Stage7KernelError::MissingKernel { + driver: claim.symbol, + kernel: kernel_symbol, + })?; + kernel.relation_kind() +} + +fn instance_round_offset( + program: &'static Stage7CpuProgramPlan, + driver: &'static str, + claim: &'static str, +) -> Result { + program + .instance_results + .iter() + .find(|instance| instance.source == driver && instance.claim == claim) + .map(|instance| instance.round_offset) + .ok_or(Stage7KernelError::MissingValue { symbol: claim }) +} + +fn evaluate_stage7_field_expr( + expr: &Stage7FieldExprPlan, + operands: &[F], +) -> Result { + match expr.formula { + "opening_eval" => single_operand(expr.symbol, operands), + "field.add" => { + require_operand_count(expr.symbol, 2, operands.len())?; + Ok(operands[0] + operands[1]) + } + "field.sub" => { + require_operand_count(expr.symbol, 2, operands.len())?; + Ok(operands[0] - operands[1]) + } + "field.mul" => { + require_operand_count(expr.symbol, 2, operands.len())?; + Ok(operands[0] * operands[1]) + } + "field.neg" => { + require_operand_count(expr.symbol, 1, operands.len())?; + Ok(-operands[0]) + } + formula => { + if let Some(exponent) = formula.strip_prefix("field.pow:") { + require_operand_count(expr.symbol, 1, operands.len())?; + let exponent = exponent.parse::().map_err(|_| { + Stage7KernelError::UnsupportedFieldExpr { + symbol: expr.symbol, + formula, + } + })?; + return Ok(pow_field(operands[0], exponent)); + } + Err(Stage7KernelError::UnsupportedFieldExpr { + symbol: expr.symbol, + formula, + }) + } + } +} + +fn pow_field(base: F, mut exponent: usize) -> F { + let mut result = F::one(); + let mut power = base; + while exponent != 0 { + if exponent & 1 == 1 { + result *= power; + } + power = power.square(); + exponent >>= 1; + } + result +} + +fn single_operand(symbol: &'static str, operands: &[F]) -> Result { + require_operand_count(symbol, 1, operands.len())?; + Ok(operands[0]) +} + +fn require_operand_count( + input: &'static str, + expected: usize, + actual: usize, +) -> Result<(), Stage7KernelError> { + if expected == actual { + Ok(()) + } else { + Err(Stage7KernelError::InvalidInputLength { + input, + expected, + actual, + }) + } +} + +fn combine_univariate_polys( + polynomials: &[UnivariatePoly], + coefficients: &[F], +) -> UnivariatePoly { + let max_len = polynomials + .iter() + .map(|poly| poly.coefficients().len()) + .max() + .unwrap_or(0); + let mut combined = vec![F::zero(); max_len]; + for (poly, &coefficient) in polynomials.iter().zip(coefficients) { + for (combined, &term) in combined.iter_mut().zip(poly.coefficients()) { + *combined += term * coefficient; + } + } + UnivariatePoly::new(combined) +} + +fn polynomial_degree(poly: &UnivariatePoly) -> usize { + poly.coefficients() + .iter() + .rposition(|coefficient| *coefficient != F::zero()) + .unwrap_or(0) +} + +fn append_compressed_univariate_poly( + transcript: &mut T, + label: &'static str, + poly: &UnivariatePoly, +) where + F: Field, + T: Transcript, +{ + let compressed = poly.compress(); + transcript.append(&LabelWithCount( + label.as_bytes(), + compressed.coeffs_except_linear_term().len() as u64, + )); + for coefficient in compressed.coeffs_except_linear_term() { + transcript.append(coefficient); + } +} + +fn append_labeled_scalar(transcript: &mut T, label: &'static str, scalar: &F) +where + F: Field, + T: Transcript, +{ + transcript.append(&Label(label.as_bytes())); + transcript.append(scalar); +} + +fn append_opening_claims( + program: &'static Stage7CpuProgramPlan, + store: &mut Stage7ValueStore, + transcript: &mut T, + evals: &[Stage7NamedEval], +) -> Result>, Stage7KernelError> +where + F: Field, + T: Transcript, +{ + if program.opening_batches.is_empty() { + for eval in evals { + append_labeled_scalar(transcript, "opening_claim", &eval.value); + } + return Ok(Vec::new()); + } + let _ = store.evaluate_available_points(program)?; + let mut opening_claims = Vec::new(); + for batch in program.opening_batches { + for symbol in batch.claim_operands { + let claim = + find_opening_claim(program, symbol).ok_or(Stage7KernelError::MissingClaim { + batch: batch.symbol, + claim: symbol, + })?; + let point = store.point(claim.point_source)?.to_vec(); + let value = store.scalar(claim.eval_source)?; + append_labeled_scalar(transcript, "opening_claim", &value); + opening_claims.push(Stage7OpeningClaimValue { + symbol: claim.symbol, + oracle: claim.oracle, + domain: claim.domain, + claim_kind: claim.claim_kind, + point, + eval: value, + }); + } + } + Ok(opening_claims) +} + +pub fn execute_stage7_program( + program: &'static Stage7CpuProgramPlan, + mode: Stage7ExecutionMode, + executor: &mut E, + transcript: &mut T, +) -> Result, Stage7KernelError> +where + F: Field, + T: Transcript, + E: Stage7KernelExecutor, +{ + let mut artifacts = Stage7ExecutionArtifacts::default(); + for step in program.steps { + match step.kind { + "transcript_squeeze" => { + let squeeze = + find_squeeze(program, step.symbol).ok_or(Stage7KernelError::MissingValue { + symbol: step.symbol, + })?; + let values = transcript.challenge_vector(squeeze.count); + executor.observe_challenge_vector(squeeze, &values)?; + artifacts.challenge_vectors.push(Stage7ChallengeVector { + symbol: squeeze.symbol, + values, + }); + } + "transcript_absorb_bytes" => { + let absorb = find_absorb_bytes(program, step.symbol).ok_or( + Stage7KernelError::MissingValue { + symbol: step.symbol, + }, + )?; + absorb_stage7_bytes(absorb, transcript); + } + "sumcheck_driver" => { + let driver = + find_driver(program, step.symbol).ok_or(Stage7KernelError::MissingDriver { + driver: step.symbol, + })?; + let kernel_symbol = driver.kernel.ok_or(Stage7KernelError::MissingKernel { + driver: driver.symbol, + kernel: "", + })?; + let kernel = find_kernel(program, kernel_symbol).ok_or( + Stage7KernelError::MissingKernel { + driver: driver.symbol, + kernel: kernel_symbol, + }, + )?; + let batch = + find_batch(program, driver.batch).ok_or(Stage7KernelError::MissingBatch { + driver: driver.symbol, + batch: driver.batch, + })?; + let context = Stage7KernelContext { + mode, + program, + kernel, + batch, + driver, + }; + let output = match mode { + Stage7ExecutionMode::Prover => executor.prove_sumcheck(context, transcript)?, + Stage7ExecutionMode::Verifier => { + executor.verify_sumcheck(context, transcript)? + } + }; + executor.observe_sumcheck_output(&output)?; + artifacts + .opening_claims + .extend(output.opening_claims.clone()); + artifacts.sumchecks.push(output); + } + _ => { + return Err(Stage7KernelError::InvalidProgramStep { + symbol: step.symbol, + kind: step.kind, + }); + } + } + } + artifacts + .opening_batches + .extend(program.opening_batches.iter()); + Ok(artifacts) +} + +fn absorb_stage7_bytes(absorb: &'static Stage7TranscriptAbsorbBytesPlan, transcript: &mut T) +where + T: Transcript, +{ + transcript.append(&LabelWithCount( + absorb.label.as_bytes(), + absorb.payload.len() as u64, + )); + transcript.append_bytes(absorb.payload.as_bytes()); +} + +fn find_squeeze( + program: &'static Stage7CpuProgramPlan, + symbol: &str, +) -> Option<&'static Stage7TranscriptSqueezePlan> { + program + .transcript_squeezes + .iter() + .find(|squeeze| squeeze.symbol == symbol) +} + +fn find_absorb_bytes( + program: &'static Stage7CpuProgramPlan, + symbol: &str, +) -> Option<&'static Stage7TranscriptAbsorbBytesPlan> { + program + .transcript_absorb_bytes + .iter() + .find(|absorb| absorb.symbol == symbol) +} + +fn find_driver( + program: &'static Stage7CpuProgramPlan, + symbol: &str, +) -> Option<&'static Stage7SumcheckDriverPlan> { + program + .drivers + .iter() + .find(|driver| driver.symbol == symbol) +} + +fn find_kernel( + program: &'static Stage7CpuProgramPlan, + symbol: &str, +) -> Option<&'static Stage7KernelPlan> { + program + .kernels + .iter() + .find(|kernel| kernel.symbol == symbol) +} + +fn find_batch( + program: &'static Stage7CpuProgramPlan, + symbol: &str, +) -> Option<&'static Stage7SumcheckBatchPlan> { + program.batches.iter().find(|batch| batch.symbol == symbol) +} + +fn find_opening_claim( + program: &'static Stage7CpuProgramPlan, + symbol: &str, +) -> Option<&'static Stage7OpeningClaimPlan> { + program + .opening_claims + .iter() + .find(|claim| claim.symbol == symbol) +} + +fn reverse_slice(slice: &[F]) -> Vec { + slice.iter().rev().copied().collect() +} + +#[cfg(test)] +#[expect( + clippy::expect_used, + reason = "tests use expect to keep failure context concise" +)] +mod tests { + use super::*; + use jolt_field::Fr; + use jolt_transcript::Blake2bTranscript; + + const PARAMS: Stage7Params = Stage7Params { + field: "bn254_fr", + pcs: "dory", + transcript: "blake2b_transcript", + }; + const STEPS: &[Stage7ProgramStepPlan] = &[Stage7ProgramStepPlan { + kind: "sumcheck_driver", + symbol: "stage7.sumcheck", + }]; + const FIELD_CONSTANTS: &[Stage7FieldConstantPlan] = &[ + Stage7FieldConstantPlan { + symbol: "stage7.field.one", + field: "bn254_fr", + value: 1, + }, + Stage7FieldConstantPlan { + symbol: "stage7.hamming_weight_claim_reduction.gamma", + field: "bn254_fr", + value: 2, + }, + ]; + const CLAIM_INPUTS: &[&str] = &["stage7.input.claim"]; + const CLAIMS: &[Stage7SumcheckClaimPlan] = &[Stage7SumcheckClaimPlan { + symbol: "stage7.hamming_weight_claim_reduction.input", + stage: "stage7", + domain: "jolt.stage7_hamming_weight_claim_reduction_domain", + num_rounds: 1, + degree: 2, + claim: "stage7.hamming_weight_claim_reduction.weighted_stage6_claims", + kernel: Some("jolt.cpu.stage7.hamming_weight_claim_reduction"), + relation: None, + claim_value: "stage7.input.claim", + input_openings: CLAIM_INPUTS, + }]; + const KERNELS: &[Stage7KernelPlan] = &[ + Stage7KernelPlan { + symbol: "jolt.cpu.stage7.hamming_weight_claim_reduction", + relation: "jolt.stage7.hamming_weight_claim_reduction", + kind: "sumcheck", + backend: "cpu", + abi: "jolt_stage7_hamming_weight_claim_reduction", + }, + Stage7KernelPlan { + symbol: "jolt.cpu.stage7.batched", + relation: "jolt.stage7.batched", + kind: "sumcheck", + backend: "cpu", + abi: "jolt_stage7_batched", + }, + ]; + const BATCHES: &[Stage7SumcheckBatchPlan] = &[Stage7SumcheckBatchPlan { + symbol: "stage7.batch", + stage: "stage7", + proof_slot: "stage7.sumcheck", + policy: "jolt_core_stage7_aligned", + count: 1, + ordered_claims: &["stage7.hamming_weight_claim_reduction.input"], + claim_operands: &["stage7.hamming_weight_claim_reduction.input"], + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + round_schedule: &[1], + }]; + const DRIVERS: &[Stage7SumcheckDriverPlan] = &[Stage7SumcheckDriverPlan { + symbol: "stage7.sumcheck", + stage: "stage7", + proof_slot: "stage7.sumcheck", + kernel: Some("jolt.cpu.stage7.batched"), + relation: Some("jolt.stage7.batched"), + batch: "stage7.batch", + policy: "jolt_core_stage7_aligned", + round_schedule: &[1], + claim_label: "sumcheck_claim", + round_label: "sumcheck_poly", + num_rounds: 1, + degree: 2, + }]; + const INSTANCE_RESULTS: &[Stage7SumcheckInstanceResultPlan] = + &[Stage7SumcheckInstanceResultPlan { + symbol: "stage7.hamming_weight_claim_reduction.instance", + source: "stage7.sumcheck", + claim: "stage7.hamming_weight_claim_reduction.input", + relation: "jolt.stage7.hamming_weight_claim_reduction", + index: 0, + point_arity: 1, + num_rounds: 1, + round_offset: 0, + point_order: "reverse", + degree: 2, + }]; + const EVALS: &[Stage7SumcheckEvalPlan] = &[ + Stage7SumcheckEvalPlan { + symbol: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_0", + source: "stage7.sumcheck", + name: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_0", + index: 0, + oracle: "InstructionRa_0", + }, + Stage7SumcheckEvalPlan { + symbol: "stage7.hamming_weight_claim_reduction.eval.RamRa_0", + source: "stage7.sumcheck", + name: "stage7.hamming_weight_claim_reduction.eval.RamRa_0", + index: 1, + oracle: "RamRa_0", + }, + ]; + const OPENING_CLAIMS: &[Stage7OpeningClaimPlan] = &[ + Stage7OpeningClaimPlan { + symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_0", + oracle: "InstructionRa_0", + domain: "jolt.main_witness_commit_domain", + point_arity: 2, + claim_kind: "committed", + point_source: "stage7.hamming_weight_claim_reduction.point", + eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_0", + }, + Stage7OpeningClaimPlan { + symbol: "stage7.hamming_weight_claim_reduction.opening.RamRa_0", + oracle: "RamRa_0", + domain: "jolt.main_witness_commit_domain", + point_arity: 2, + claim_kind: "committed", + point_source: "stage7.hamming_weight_claim_reduction.point", + eval_source: "stage7.hamming_weight_claim_reduction.eval.RamRa_0", + }, + ]; + const OPENING_BATCHES: &[Stage7OpeningBatchPlan] = &[Stage7OpeningBatchPlan { + symbol: "stage7.openings", + stage: "stage7", + proof_slot: "stage7.openings", + policy: "jolt_stage7_output_order", + count: 2, + ordered_claims: &[ + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_0", + "stage7.hamming_weight_claim_reduction.opening.RamRa_0", + ], + claim_operands: &[ + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_0", + "stage7.hamming_weight_claim_reduction.opening.RamRa_0", + ], + }]; + const POINT_SLICES: &[Stage7PointSlicePlan] = &[Stage7PointSlicePlan { + symbol: "stage7.hamming_weight_claim_reduction.point.cycle", + source: "stage7.input.stage6.booleanity.InstructionRa_0", + offset: 1, + length: 1, + input: "stage7.input.stage6.booleanity.InstructionRa_0", + }]; + const POINT_CONCAT_INPUTS: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.instance", + "stage7.hamming_weight_claim_reduction.point.cycle", + ]; + const POINT_CONCATS: &[Stage7PointConcatPlan] = &[Stage7PointConcatPlan { + symbol: "stage7.hamming_weight_claim_reduction.point", + layout: "address_chunk_then_cycle", + arity: 2, + inputs: POINT_CONCAT_INPUTS, + }]; + const PROGRAM: Stage7CpuProgramPlan = Stage7CpuProgramPlan { + role: "prover", + params: PARAMS, + steps: STEPS, + transcript_squeezes: &[], + transcript_absorb_bytes: &[], + opening_inputs: &[], + field_constants: FIELD_CONSTANTS, + field_exprs: &[], + kernels: KERNELS, + claims: CLAIMS, + batches: BATCHES, + drivers: DRIVERS, + instance_results: INSTANCE_RESULTS, + evals: EVALS, + point_zeros: &[], + point_slices: POINT_SLICES, + point_concats: POINT_CONCATS, + opening_claims: OPENING_CLAIMS, + opening_equalities: &[], + opening_batches: OPENING_BATCHES, + }; + + #[test] + fn hamming_weight_claim_reduction_prover_and_replay_agree() { + let r_bool = Fr::from_u64(5); + let r_cycle = Fr::from_u64(3); + let r_instr_virt = Fr::from_u64(7); + let r_ram_virt = Fr::from_u64(11); + let instruction_ra = vec![ + Fr::from_u64(1), + Fr::from_u64(0), + Fr::from_u64(0), + Fr::from_u64(1), + ]; + let ram_ra = vec![ + Fr::from_u64(0), + Fr::from_u64(0), + Fr::from_u64(1), + Fr::from_u64(0), + ]; + let bool_point = vec![r_bool, r_cycle]; + let instr_virt_point = vec![r_instr_virt, r_cycle]; + let ram_virt_point = vec![r_ram_virt, r_cycle]; + let instr_bool = eval_full_cycle_major(&instruction_ra, &bool_point); + let ram_bool = eval_full_cycle_major(&ram_ra, &bool_point); + let instr_virt = eval_full_cycle_major(&instruction_ra, &instr_virt_point); + let ram_virt = eval_full_cycle_major(&ram_ra, &ram_virt_point); + let ram_hw = r_cycle; + let gamma = Fr::from_u64(2); + let gamma_powers = gamma_powers(gamma, 6); + let input_claim = gamma_powers[0] * Fr::from_u64(1) + + gamma_powers[1] * instr_bool + + gamma_powers[2] * instr_virt + + gamma_powers[3] * ram_hw + + gamma_powers[4] * ram_bool + + gamma_powers[5] * ram_virt; + let openings = vec![ + Stage7OpeningInputValue { + symbol: "stage7.input.claim", + point: Vec::new(), + eval: input_claim, + }, + Stage7OpeningInputValue { + symbol: "stage7.input.stage6.hamming_booleanity.HammingWeight", + point: vec![r_cycle], + eval: ram_hw, + }, + Stage7OpeningInputValue { + symbol: "stage7.input.stage6.booleanity.InstructionRa_0", + point: bool_point.clone(), + eval: instr_bool, + }, + Stage7OpeningInputValue { + symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_0", + point: instr_virt_point, + eval: instr_virt, + }, + Stage7OpeningInputValue { + symbol: "stage7.input.stage6.booleanity.RamRa_0", + point: bool_point, + eval: ram_bool, + }, + Stage7OpeningInputValue { + symbol: "stage7.input.stage6.ram_ra_virtual.RamRa_0", + point: ram_virt_point, + eval: ram_virt, + }, + ]; + let instruction_chunks: Vec<&[Fr]> = vec![&instruction_ra]; + let ram_chunks: Vec<&[Fr]> = vec![&ram_ra]; + let inputs = Stage7ProverInputs::new(&openings).with_hamming_weight_claim_reduction( + Stage7HammingWeightClaimReductionWitness { + instruction_ra: Stage7RaChunks { + chunks: &instruction_chunks, + layout: Stage7RaChunkLayout::CycleMajor, + }, + bytecode_ra: Stage7RaChunks { + chunks: &[], + layout: Stage7RaChunkLayout::CycleMajor, + }, + ram_ra: Stage7RaChunks { + chunks: &ram_chunks, + layout: Stage7RaChunkLayout::CycleMajor, + }, + }, + ); + let mut prover = Stage7ProverKernelExecutor::new(inputs); + let mut prover_transcript = Blake2bTranscript::::new(b"stage7-test"); + let artifacts = execute_stage7_program( + &PROGRAM, + Stage7ExecutionMode::Prover, + &mut prover, + &mut prover_transcript, + ) + .expect("stage7 prover succeeds"); + assert_eq!(artifacts.sumchecks.len(), 1); + assert_eq!(artifacts.sumchecks[0].evals.len(), 2); + + let proof = Stage7Proof { + sumchecks: artifacts.sumchecks.clone(), + }; + let mut verifier = Stage7ProofCarryingKernelExecutor::new(&proof, &openings); + let mut verifier_transcript = Blake2bTranscript::::new(b"stage7-test"); + let verified = execute_stage7_program( + &PROGRAM, + Stage7ExecutionMode::Verifier, + &mut verifier, + &mut verifier_transcript, + ) + .expect("stage7 replay succeeds"); + assert_eq!(verified.sumchecks[0].point, artifacts.sumchecks[0].point); + assert_eq!(verifier_transcript.state(), prover_transcript.state()); + } + + #[test] + fn hamming_weight_claim_reduction_index_witness_matches_dense_witness() { + let r_bool = Fr::from_u64(5); + let r_cycle = Fr::from_u64(3); + let r_instr_virt = Fr::from_u64(7); + let r_ram_virt = Fr::from_u64(11); + let instruction_ra = vec![ + Fr::from_u64(1), + Fr::from_u64(0), + Fr::from_u64(0), + Fr::from_u64(1), + ]; + let ram_ra = vec![ + Fr::from_u64(0), + Fr::from_u64(0), + Fr::from_u64(1), + Fr::from_u64(0), + ]; + let bool_point = vec![r_bool, r_cycle]; + let instr_virt_point = vec![r_instr_virt, r_cycle]; + let ram_virt_point = vec![r_ram_virt, r_cycle]; + let instr_bool = eval_full_cycle_major(&instruction_ra, &bool_point); + let ram_bool = eval_full_cycle_major(&ram_ra, &bool_point); + let instr_virt = eval_full_cycle_major(&instruction_ra, &instr_virt_point); + let ram_virt = eval_full_cycle_major(&ram_ra, &ram_virt_point); + let ram_hw = r_cycle; + let gamma = Fr::from_u64(2); + let gamma_powers = gamma_powers(gamma, 6); + let input_claim = gamma_powers[0] * Fr::from_u64(1) + + gamma_powers[1] * instr_bool + + gamma_powers[2] * instr_virt + + gamma_powers[3] * ram_hw + + gamma_powers[4] * ram_bool + + gamma_powers[5] * ram_virt; + let openings = vec![ + Stage7OpeningInputValue { + symbol: "stage7.input.claim", + point: Vec::new(), + eval: input_claim, + }, + Stage7OpeningInputValue { + symbol: "stage7.input.stage6.hamming_booleanity.HammingWeight", + point: vec![r_cycle], + eval: ram_hw, + }, + Stage7OpeningInputValue { + symbol: "stage7.input.stage6.booleanity.InstructionRa_0", + point: bool_point.clone(), + eval: instr_bool, + }, + Stage7OpeningInputValue { + symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_0", + point: instr_virt_point, + eval: instr_virt, + }, + Stage7OpeningInputValue { + symbol: "stage7.input.stage6.booleanity.RamRa_0", + point: bool_point, + eval: ram_bool, + }, + Stage7OpeningInputValue { + symbol: "stage7.input.stage6.ram_ra_virtual.RamRa_0", + point: ram_virt_point, + eval: ram_virt, + }, + ]; + let instruction_indices = vec![Some(0), Some(1)]; + let ram_indices = vec![None, Some(0)]; + let instruction_chunks: Vec<&[Option]> = vec![&instruction_indices]; + let ram_chunks: Vec<&[Option]> = vec![&ram_indices]; + let inputs = Stage7ProverInputs::new(&openings) + .with_hamming_weight_claim_reduction_indices( + Stage7HammingWeightClaimReductionIndexWitness { + instruction_ra: Stage7RaIndexChunks { + chunks: &instruction_chunks, + }, + bytecode_ra: Stage7RaIndexChunks { chunks: &[] }, + ram_ra: Stage7RaIndexChunks { + chunks: &ram_chunks, + }, + }, + ); + let mut prover = Stage7ProverKernelExecutor::new(inputs); + let mut prover_transcript = Blake2bTranscript::::new(b"stage7-test"); + let artifacts = execute_stage7_program( + &PROGRAM, + Stage7ExecutionMode::Prover, + &mut prover, + &mut prover_transcript, + ) + .expect("stage7 index prover succeeds"); + assert_eq!(artifacts.sumchecks.len(), 1); + + let proof = Stage7Proof { + sumchecks: artifacts.sumchecks.clone(), + }; + let mut verifier = Stage7ProofCarryingKernelExecutor::new(&proof, &openings); + let mut verifier_transcript = Blake2bTranscript::::new(b"stage7-test"); + let verified = execute_stage7_program( + &PROGRAM, + Stage7ExecutionMode::Verifier, + &mut verifier, + &mut verifier_transcript, + ) + .expect("stage7 index replay succeeds"); + assert_eq!(verified.sumchecks[0].point, artifacts.sumchecks[0].point); + assert_eq!(verifier_transcript.state(), prover_transcript.state()); + } + + fn eval_full_cycle_major(evals: &[Fr], point: &[Fr]) -> Fr { + let address = EqPolynomial::::evals(&point[..1], None); + let cycle = EqPolynomial::::evals(&point[1..], None); + let mut value = Fr::from_u64(0); + for cycle_index in 0..2 { + for address_index in 0..2 { + value += evals[cycle_index * 2 + address_index] + * cycle[cycle_index] + * address[address_index]; + } + } + value + } +} diff --git a/crates/jolt-kernels/src/trace.rs b/crates/jolt-kernels/src/trace.rs new file mode 100644 index 0000000000..9b6ea3e839 --- /dev/null +++ b/crates/jolt-kernels/src/trace.rs @@ -0,0 +1,391 @@ +//! Trace-to-kernel witness views for Bolt-generated Jolt stages. + +use jolt_field::signed::{S128, S64}; +use jolt_field::Field; +use jolt_trace::{ + instruction_circuit_flags, instruction_instruction_flags, BytecodePreprocessing, + CircuitFlagSet, CircuitFlags, CycleRow, Instruction, InstructionFlags, InterleavedBitsMarker, + NUM_CIRCUIT_FLAGS, +}; +use jolt_witness::Stage6BytecodeEntry; + +use crate::stage1::Stage1Rv64Cycle; +use crate::stage2::{Stage2InstructionLookupCycle, Stage2ProductVirtualCycle, Stage2RamAccess}; +use crate::stage3::Stage3Cycle; +use crate::stage4::{Stage4RegisterAccess, Stage4RegisterRead, Stage4RegisterWrite}; + +pub fn stage1_rv64_cycles( + trace: &[C], + size: usize, + bytecode: &BytecodePreprocessing, +) -> Vec { + (0..size) + .map(|cycle| stage1_rv64_cycle(trace, cycle, bytecode)) + .collect() +} + +pub fn stage2_product_virtual_cycles( + trace: &[C], + size: usize, +) -> Vec { + (0..size) + .map(|index| stage2_product_virtual_cycle(trace, index)) + .collect() +} + +pub fn stage2_instruction_lookup_cycles( + trace: &[C], + size: usize, +) -> Vec { + (0..size) + .map(|index| stage2_instruction_lookup_cycle(trace.get(index).copied())) + .collect() +} + +pub fn stage2_ram_accesses( + trace: &[C], + size: usize, + mut remap_address: R, +) -> Vec +where + C: CycleRow, + R: FnMut(u64) -> Option, +{ + (0..size) + .map(|index| { + let Some(cycle) = trace.get(index) else { + return Stage2RamAccess::noop(); + }; + let Some(address) = cycle.ram_access_address() else { + return Stage2RamAccess::noop(); + }; + Stage2RamAccess { + remapped_address: remap_address(address), + read_value: cycle.ram_read_value().unwrap_or(0), + write_value: cycle.ram_write_value().unwrap_or(0), + } + }) + .collect() +} + +pub fn stage3_cycles( + trace: &[C], + size: usize, + bytecode: &BytecodePreprocessing, +) -> Vec { + (0..size) + .map(|cycle| stage3_cycle(trace.get(cycle).copied(), bytecode)) + .collect() +} + +pub fn stage4_register_accesses( + trace: &[C], + size: usize, +) -> Vec { + (0..size) + .map(|cycle| stage4_register_access(trace.get(cycle).copied())) + .collect() +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Stage5LookupTrace { + pub lookup_indices: Vec, + pub lookup_table_indices: Vec>, + pub is_interleaved_operands: Vec, +} + +pub fn stage5_lookup_trace( + trace: &[C], + size: usize, + mut lookup_table_index: L, +) -> Stage5LookupTrace +where + C: CycleRow, + L: FnMut(&C) -> Option, +{ + let mut lookup_indices = Vec::with_capacity(size); + let mut lookup_table_indices = Vec::with_capacity(size); + let mut is_interleaved_operands = Vec::with_capacity(size); + for index in 0..size { + let Some(cycle) = trace.get(index) else { + lookup_indices.push(0); + lookup_table_indices.push(None); + is_interleaved_operands.push(false); + continue; + }; + lookup_indices.push(cycle.lookup_index()); + lookup_table_indices.push(lookup_table_index(cycle)); + is_interleaved_operands.push(cycle.circuit_flags().is_interleaved_operands()); + } + Stage5LookupTrace { + lookup_indices, + lookup_table_indices, + is_interleaved_operands, + } +} + +pub fn stage6_bytecode_entries( + bytecode: &BytecodePreprocessing, + mut lookup_table_index: L, +) -> Vec> +where + F: Field, + L: FnMut(&Instruction) -> Option, +{ + bytecode + .bytecode + .iter() + .map(|instruction| { + let instr = instruction.normalize(); + let circuit_flags = instruction_circuit_flags(instruction); + let instruction_flags = instruction_instruction_flags(instruction); + Stage6BytecodeEntry { + address: F::from_u64(instr.address as u64), + imm: F::from_i128(instr.operands.imm), + circuit_flags: stage6_circuit_flags(circuit_flags), + rd: instr.operands.rd.map(usize::from), + rs1: instr.operands.rs1.map(usize::from), + rs2: instr.operands.rs2.map(usize::from), + lookup_table: lookup_table_index(instruction), + is_interleaved: circuit_flags.is_interleaved_operands(), + is_branch: instruction_flags[InstructionFlags::Branch], + left_is_rs1: instruction_flags[InstructionFlags::LeftOperandIsRs1Value], + left_is_pc: instruction_flags[InstructionFlags::LeftOperandIsPC], + right_is_rs2: instruction_flags[InstructionFlags::RightOperandIsRs2Value], + right_is_imm: instruction_flags[InstructionFlags::RightOperandIsImm], + is_noop: instruction_flags[InstructionFlags::IsNoop], + } + }) + .collect() +} + +fn stage2_product_virtual_cycle( + trace: &[C], + index: usize, +) -> Stage2ProductVirtualCycle { + let Some(cycle) = trace.get(index) else { + return Stage2ProductVirtualCycle::padding(); + }; + let (instruction_left_input, instruction_right_input) = instruction_inputs(cycle); + let flags = cycle.circuit_flags(); + let instruction_flags = cycle.instruction_flags(); + let not_next_noop = trace.get(index + 1).is_some_and(|next| !next.is_noop()); + Stage2ProductVirtualCycle { + instruction_left_input, + instruction_right_input, + should_branch_lookup_output: cycle.lookup_output(), + write_lookup_output_to_rd_flag: flags[CircuitFlags::WriteLookupOutputToRD], + jump_flag: flags[CircuitFlags::Jump], + should_branch_flag: instruction_flags[InstructionFlags::Branch], + not_next_noop, + virtual_instruction_flag: flags[CircuitFlags::VirtualInstruction], + } +} + +fn stage2_instruction_lookup_cycle(cycle: Option) -> Stage2InstructionLookupCycle { + let Some(cycle) = cycle else { + return Stage2InstructionLookupCycle::padding(); + }; + let (left_instruction_input, right_instruction_input) = instruction_inputs(&cycle); + let product = instruction_product(left_instruction_input, right_instruction_input); + let (left_lookup_operand, right_lookup_operand) = lookup_operands_raw( + left_instruction_input, + right_instruction_input, + product, + cycle.circuit_flags(), + cycle.lookup_output(), + ); + Stage2InstructionLookupCycle { + lookup_output: cycle.lookup_output(), + left_lookup_operand, + right_lookup_operand, + left_instruction_input, + right_instruction_input, + } +} + +fn stage4_register_access(cycle: Option) -> Stage4RegisterAccess { + let Some(cycle) = cycle else { + return Stage4RegisterAccess::default(); + }; + Stage4RegisterAccess { + rs1: cycle.rs1_read().map(|(address, value)| Stage4RegisterRead { + address: address as usize, + value, + }), + rs2: cycle.rs2_read().map(|(address, value)| Stage4RegisterRead { + address: address as usize, + value, + }), + rd: cycle + .rd_write() + .map(|(address, pre_value, post_value)| Stage4RegisterWrite { + address: address as usize, + pre_value, + post_value, + }), + } +} + +fn stage3_cycle(cycle: Option, bytecode: &BytecodePreprocessing) -> Stage3Cycle { + let Some(cycle) = cycle else { + return Stage3Cycle::padding(); + }; + let circuit_flags = cycle.circuit_flags(); + let instruction_flags = cycle.instruction_flags(); + Stage3Cycle { + unexpanded_pc: cycle.unexpanded_pc(), + pc: bytecode.get_cycle_pc(&cycle) as u64, + is_virtual: circuit_flags[CircuitFlags::VirtualInstruction], + is_first_in_sequence: circuit_flags[CircuitFlags::IsFirstInSequence], + is_noop: instruction_flags[InstructionFlags::IsNoop], + left_operand_is_rs1: instruction_flags[InstructionFlags::LeftOperandIsRs1Value], + rs1_value: cycle.rs1_read().map_or(0, |(_, value)| value), + left_operand_is_pc: instruction_flags[InstructionFlags::LeftOperandIsPC], + right_operand_is_rs2: instruction_flags[InstructionFlags::RightOperandIsRs2Value], + rs2_value: cycle.rs2_read().map_or(0, |(_, value)| value), + right_operand_is_imm: instruction_flags[InstructionFlags::RightOperandIsImm], + imm: cycle.imm(), + rd_write_value: cycle.rd_write().map_or(0, |(_, _, post)| post), + } +} + +fn stage1_rv64_cycle( + trace: &[C], + cycle_index: usize, + bytecode: &BytecodePreprocessing, +) -> Stage1Rv64Cycle { + let Some(cycle) = trace.get(cycle_index) else { + return Stage1Rv64Cycle::padding(); + }; + let next = trace.get(cycle_index + 1); + if cycle.is_noop() { + let mut row = Stage1Rv64Cycle::padding(); + fill_next_rv64_fields(&mut row, next, bytecode); + return row; + } + + let flags_set = cycle.circuit_flags(); + let instruction_flags = cycle.instruction_flags(); + let (left_input, right_i128) = instruction_inputs(cycle); + let right_input = s64_from_i128(right_i128); + let product = instruction_product(left_input, right_i128); + let lookup_output = cycle.lookup_output(); + let (left_lookup, right_lookup) = + lookup_operands_raw(left_input, right_i128, product, flags_set, lookup_output); + let next_is_noop = next.is_none_or(CycleRow::is_noop); + let flags = stage1_rv64_flags(flags_set); + + let mut row = Stage1Rv64Cycle { + left_input, + right_input, + product, + left_lookup, + right_lookup, + lookup_output, + rs1_read_value: cycle.rs1_read().map_or(0, |(_, value)| value), + rs2_read_value: cycle.rs2_read().map_or(0, |(_, value)| value), + rd_write_value: cycle.rd_write().map_or(0, |(_, _, post)| post), + ram_addr: cycle.ram_access_address().unwrap_or(0), + ram_read_value: cycle.ram_read_value().unwrap_or(0), + ram_write_value: cycle.ram_write_value().unwrap_or(0), + pc: bytecode.get_cycle_pc(cycle) as u64, + next_pc: 0, + unexpanded_pc: cycle.unexpanded_pc(), + next_unexpanded_pc: 0, + imm: s64_from_i128(cycle.imm()), + flags, + should_jump: flags_set[CircuitFlags::Jump] && !next_is_noop, + should_branch: instruction_flags[InstructionFlags::Branch] && lookup_output == 1, + next_is_virtual: false, + next_is_first_in_sequence: false, + }; + fill_next_rv64_fields(&mut row, next, bytecode); + row +} + +fn fill_next_rv64_fields( + row: &mut Stage1Rv64Cycle, + next: Option<&C>, + bytecode: &BytecodePreprocessing, +) { + if let Some(next_cycle) = next { + row.next_pc = bytecode.get_cycle_pc(next_cycle) as u64; + row.next_unexpanded_pc = next_cycle.unexpanded_pc(); + let next_flags = next_cycle.circuit_flags(); + row.next_is_virtual = next_flags[CircuitFlags::VirtualInstruction]; + row.next_is_first_in_sequence = next_flags[CircuitFlags::IsFirstInSequence]; + } +} + +fn instruction_inputs(cycle: &impl CycleRow) -> (u64, i128) { + let instruction_flags = cycle.instruction_flags(); + let left_input = if instruction_flags[InstructionFlags::LeftOperandIsPC] { + cycle.unexpanded_pc() + } else if instruction_flags[InstructionFlags::LeftOperandIsRs1Value] { + cycle.rs1_read().map_or(0, |(_, value)| value) + } else { + 0 + }; + let right_input = if instruction_flags[InstructionFlags::RightOperandIsImm] { + cycle.imm() + } else if instruction_flags[InstructionFlags::RightOperandIsRs2Value] { + cycle.rs2_read().map_or(0, |(_, value)| value as i128) + } else { + 0 + }; + (left_input, right_input) +} + +fn instruction_product(left: u64, right: i128) -> S128 { + S64::from_u64(left).mul_trunc::<2, 2>(&S128::from_i128(right)) +} + +fn stage1_rv64_flags(flags: CircuitFlagSet) -> [bool; NUM_CIRCUIT_FLAGS] { + [ + flags[CircuitFlags::AddOperands], + flags[CircuitFlags::SubtractOperands], + flags[CircuitFlags::MultiplyOperands], + flags[CircuitFlags::Load], + flags[CircuitFlags::Store], + flags[CircuitFlags::Jump], + flags[CircuitFlags::WriteLookupOutputToRD], + flags[CircuitFlags::VirtualInstruction], + flags[CircuitFlags::Assert], + flags[CircuitFlags::DoNotUpdateUnexpandedPC], + flags[CircuitFlags::Advice], + flags[CircuitFlags::IsCompressed], + flags[CircuitFlags::IsFirstInSequence], + flags[CircuitFlags::IsLastInSequence], + ] +} + +fn stage6_circuit_flags(flags: CircuitFlagSet) -> [bool; NUM_CIRCUIT_FLAGS] { + stage1_rv64_flags(flags) +} + +fn s64_from_i128(value: i128) -> S64 { + let magnitude = value.unsigned_abs(); + assert!(magnitude <= u64::MAX as u128, "S64 input overflow"); + S64::from_u64_with_sign(magnitude as u64, value >= 0) +} + +fn lookup_operands_raw( + left: u64, + right: i128, + product: S128, + flags: CircuitFlagSet, + lookup_output: u64, +) -> (u64, u128) { + if flags[CircuitFlags::AddOperands] { + (0, (left as i128 + right) as u128) + } else if flags[CircuitFlags::SubtractOperands] { + (0, (left as i128 - right + (1i128 << 64)) as u128) + } else if flags[CircuitFlags::MultiplyOperands] { + (0, product.magnitude_as_u128()) + } else if flags[CircuitFlags::Advice] { + (0, lookup_output as u128) + } else { + (left, right as u128) + } +} diff --git a/crates/jolt-prover/Cargo.toml b/crates/jolt-prover/Cargo.toml new file mode 100644 index 0000000000..c323cdb4c2 --- /dev/null +++ b/crates/jolt-prover/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "jolt-prover" +version = "0.0.0" +edition = "2021" +license = "MIT OR Apache-2.0" +description = "Bolt-generated Jolt prover role crate" +repository = "https://github.com/a16z/jolt" + +[lints] +workspace = true + +[dependencies] +jolt-dory.workspace = true +jolt-field.workspace = true +jolt-kernels.workspace = true +jolt-openings.workspace = true +jolt-poly.workspace = true +jolt-transcript.workspace = true +jolt-verifier.workspace = true +jolt-witness.workspace = true +rayon.workspace = true +tracing.workspace = true diff --git a/crates/jolt-prover/src/lib.rs b/crates/jolt-prover/src/lib.rs new file mode 100644 index 0000000000..a6ced62faa --- /dev/null +++ b/crates/jolt-prover/src/lib.rs @@ -0,0 +1,100 @@ +#[rustfmt::skip] +pub mod prover; +pub mod stages; + +pub use prover::{ + default_prover_programs, jolt_proof_through_stage5, jolt_proof_through_stage6, + jolt_proof_through_stage7, prove_jolt, prove_jolt_evaluation_proof, prove_jolt_with_programs, + prove_jolt_with_stage_inputs, prove_jolt_with_witness_inputs, + prove_stage1_outer_inputs_with_program, prove_stage2_inputs_with_program, + prove_stage3_inputs_with_program, prove_stage4_inputs_with_program, + prove_stage5_inputs_with_program, prove_stage6_inputs_with_program, + prove_stage7_inputs_with_program, replay_stage1_outer_proof_with_program, + replay_stage2_proof_with_program, replay_stage3_proof_with_program, + replay_stage4_proof_with_program, replay_stage5_proof_with_program, + replay_stage6_proof_with_program, replay_stage7_proof_with_program, stage1_outer_proof, + stage1_outer_proof_from_kernel_proof, stage1_outer_prover_inputs, + stage2_opening_inputs_from_artifacts, stage2_proof, stage2_prover_inputs, + stage2_verifier_ram_data, stage3_opening_inputs_from_artifacts, stage3_proof, + stage3_prover_inputs, stage4_opening_inputs_from_artifacts, stage4_proof, stage4_prover_inputs, + stage5_kernel_proof, stage5_opening_inputs_from_artifacts, stage5_proof, stage5_prover_inputs, + stage6_bytecode_read_raf_data_from_witness_entries, stage6_execution_artifacts, + stage6_kernel_proof, stage6_opening_inputs_from_artifacts, stage6_proof, stage6_prover_inputs, + stage6_witness_from_opening_inputs, stage7_execution_artifacts, stage7_kernel_proof, + stage7_opening_inputs_from_stage6_artifacts, + stage7_opening_inputs_from_stage6_artifacts_with_program, stage7_proof, stage7_prover_inputs, + verifier_opening_inputs_from_kernel, DefaultJoltTranscript, JoltEvaluationProveError, + JoltKernelOpeningInput, JoltOpeningInputError, JoltProveError, JoltProverArtifacts, + JoltProverInputs, JoltProverPrograms, JoltProverStageInputs, JoltProverWitnessInputs, + JoltStage2RamDataStorage, +}; + +pub use prover::{ + prove_stage1_outer_with_witness_inputs, prove_stage2_with_witness_inputs, + prove_stage3_with_witness_inputs, prove_stage4_with_trace_witness_inputs, + prove_stage4_with_witness_inputs, prove_stage5_with_trace_witness_inputs, + prove_stage5_with_witness_inputs, prove_stage6_with_trace_witness_inputs, + prove_stage6_with_witness_inputs, prove_stage7_with_trace_witness_inputs, + prove_stage7_with_witness_inputs, stage6_verifier_data_from_witness_entries, +}; + +pub const TRANSCRIPT_LABEL: &[u8] = b"Jolt"; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct GeneratedStage { + pub name: &'static str, + pub module: &'static str, + pub ordinal: usize, +} + +pub const GENERATED_STAGES: &[GeneratedStage] = &[ + GeneratedStage { + name: "commitment", + module: "commitment", + ordinal: 0, + }, + GeneratedStage { + name: "stage1_outer", + module: "stage1_outer", + ordinal: 1, + }, + GeneratedStage { + name: "stage2", + module: "stage2", + ordinal: 2, + }, + GeneratedStage { + name: "stage3", + module: "stage3", + ordinal: 3, + }, + GeneratedStage { + name: "stage4", + module: "stage4", + ordinal: 4, + }, + GeneratedStage { + name: "stage5", + module: "stage5", + ordinal: 5, + }, + GeneratedStage { + name: "stage6", + module: "stage6", + ordinal: 6, + }, + GeneratedStage { + name: "stage7", + module: "stage7", + ordinal: 7, + }, + GeneratedStage { + name: "stage8", + module: "stage8", + ordinal: 8, + }, +]; + +pub fn generated_stage_names() -> impl Iterator { + GENERATED_STAGES.iter().map(|stage| stage.name) +} diff --git a/crates/jolt-prover/src/prover.rs b/crates/jolt-prover/src/prover.rs new file mode 100644 index 0000000000..acd8c0475d --- /dev/null +++ b/crates/jolt-prover/src/prover.rs @@ -0,0 +1,2090 @@ +#![expect( + clippy::too_many_arguments, + reason = "generated prover helpers mirror staged protocol ABIs" +)] + +use jolt_dory::{DoryCommitment, DoryHint, DoryProverSetup, DoryScheme}; +use jolt_field::{Field, Fr}; +use jolt_kernels::{stage1, stage2, stage3, stage4, stage5, stage6, stage7}; +use jolt_openings::{AdditivelyHomomorphic, CommitmentScheme}; +use jolt_poly::{EqPolynomial, Polynomial}; +use jolt_transcript::{AppendToTranscript, Blake2bTranscript, LabelWithCount, Transcript}; +use jolt_verifier::{JoltEvaluationProof, JoltNamedEval, JoltProof, JoltStage2RamAccess, JoltStage2RamData, JoltStage2RamOutputLayout, JoltStage6BytecodeEntry, JoltStage6BytecodeReadRafData, JoltStage6VerifierData, JoltStageChallengeVector, JoltStageExecutionArtifacts, JoltStageOpeningInputValue, JoltStageProof, JoltSumcheckOutput}; +use jolt_witness::{stage4_ram_val_init_opening, CycleInput, Stage45SparseTraceWitness, Stage6BytecodeEntry as WitnessStage6BytecodeEntry, Stage6WitnessParams, Stage6WitnessPolynomials, Stage6WitnessSlices}; +use rayon::prelude::*; + +use crate::stages::{commitment as commitment_stage, stage1_outer as stage1_outer_stage, stage2 as stage2_stage, stage3 as stage3_stage, stage4 as stage4_stage, stage5 as stage5_stage, stage6 as stage6_stage, stage7 as stage7_stage, stage8 as stage8_stage}; + +pub type DefaultJoltTranscript = Blake2bTranscript; + +pub struct JoltProverInputs<'a, CommitmentInputs, Stage1OuterExecutor, Stage2Executor, Stage3Executor, Stage4Executor, Stage5Executor, Stage6Executor, Stage7Executor> { + pub commitment_inputs: &'a mut CommitmentInputs, + pub prover_setup: &'a DoryProverSetup, + pub stage1_outer_executor: &'a mut Stage1OuterExecutor, + pub stage2_executor: &'a mut Stage2Executor, + pub stage3_executor: &'a mut Stage3Executor, + pub stage4_executor: &'a mut Stage4Executor, + pub stage5_executor: &'a mut Stage5Executor, + pub stage6_executor: &'a mut Stage6Executor, + pub stage7_executor: &'a mut Stage7Executor, + pub stage7_openings: Option<&'a [stage7::Stage7OpeningInputValue]>, +} + +#[derive(Clone, Copy, Debug)] +pub struct JoltProverPrograms { + pub commitment: &'static commitment_stage::CommitmentProverProgramPlan, + pub stage1_outer: &'static stage1::Stage1CpuProgramPlan, + pub stage2: &'static stage2::Stage2CpuProgramPlan, + pub stage3: &'static stage3::Stage3CpuProgramPlan, + pub stage4: &'static stage4::Stage4CpuProgramPlan, + pub stage5: &'static stage5::Stage5CpuProgramPlan, + pub stage6: &'static stage6::Stage6CpuProgramPlan, + pub stage7: &'static stage7::Stage7CpuProgramPlan, + pub stage8: &'static stage8_stage::Stage8EvaluationProgramPlan, +} + +pub fn default_prover_programs() -> JoltProverPrograms { + JoltProverPrograms { + commitment: &commitment_stage::COMMITMENT_PROGRAM, + stage1_outer: &stage1_outer_stage::STAGE1_PROGRAM, + stage2: &stage2_stage::STAGE2_PROGRAM, + stage3: &stage3_stage::STAGE3_PROGRAM, + stage4: &stage4_stage::STAGE4_PROGRAM, + stage5: &stage5_stage::STAGE5_PROGRAM, + stage6: &stage6_stage::STAGE6_PROGRAM, + stage7: &stage7_stage::STAGE7_PROGRAM, + stage8: &stage8_stage::STAGE8_PROGRAM, + } +} + +#[derive(Clone, Debug)] +pub struct JoltProverArtifacts { + pub commitment: commitment_stage::CommitmentArtifacts, + pub stage1_outer: stage1::Stage1ExecutionArtifacts, + pub stage2: stage2::Stage2ExecutionArtifacts, + pub stage3: stage3::Stage3ExecutionArtifacts, + pub stage4: stage4::Stage4ExecutionArtifacts, + pub stage5: stage5::Stage5ExecutionArtifacts, + pub stage6: stage6::Stage6ExecutionArtifacts, + pub stage7: stage7::Stage7ExecutionArtifacts, +} + +#[derive(Debug)] +pub enum JoltProveError { + Commitment(commitment_stage::CommitmentPhaseError), + Stage1Outer(stage1::Stage1KernelError), + Stage2(stage2::Stage2KernelError), + Stage3(stage3::Stage3KernelError), + Stage4(stage4::Stage4KernelError), + Stage5(stage5::Stage5KernelError), + Stage6(stage6::Stage6KernelError), + Stage7(stage7::Stage7KernelError), + Evaluation(JoltEvaluationProveError), +} + +#[derive(Debug)] +pub enum JoltEvaluationProveError { + MissingOracle { oracle: &'static str }, + MissingOpeningHint { oracle: &'static str }, + MissingStageEval { stage: &'static str, eval: &'static str }, + MissingStage7RaEval, + MissingStage7EvaluationPoint, + InvalidPointLength { + artifact: &'static str, + expected: usize, + actual: usize, + }, + TargetSizeOverflow { num_vars: usize }, +} + +#[derive(Debug)] +pub enum JoltOpeningInputError { + MissingOpeningClaim { stage: &'static str, source_claim: &'static str }, + MissingStage6OpeningClaim { source_claim: &'static str }, + UnsupportedOpeningInputSource { stage: &'static str, symbol: &'static str, source_stage: &'static str }, + UnsupportedStage7InputSource { symbol: &'static str, source_stage: &'static str }, + InvalidPointLength { + symbol: &'static str, + expected: usize, + actual: usize, + }, +} + +impl From for JoltProveError { + fn from(error: commitment_stage::CommitmentPhaseError) -> Self { + Self::Commitment(error) + } +} + +impl From for JoltProveError { + fn from(error: stage1::Stage1KernelError) -> Self { + Self::Stage1Outer(error) + } +} + +impl From for JoltProveError { + fn from(error: stage2::Stage2KernelError) -> Self { + Self::Stage2(error) + } +} + +impl From for JoltProveError { + fn from(error: stage3::Stage3KernelError) -> Self { + Self::Stage3(error) + } +} + +impl From for JoltProveError { + fn from(error: stage4::Stage4KernelError) -> Self { + Self::Stage4(error) + } +} + +impl From for JoltProveError { + fn from(error: stage5::Stage5KernelError) -> Self { + Self::Stage5(error) + } +} + +impl From for JoltProveError { + fn from(error: stage6::Stage6KernelError) -> Self { + Self::Stage6(error) + } +} + +impl From for JoltProveError { + fn from(error: stage7::Stage7KernelError) -> Self { + Self::Stage7(error) + } +} + +impl From for JoltProveError { + fn from(error: JoltEvaluationProveError) -> Self { + Self::Evaluation(error) + } +} + +pub fn prove_jolt( + inputs: JoltProverInputs<'_, CommitmentInputs, Stage1OuterExecutor, Stage2Executor, Stage3Executor, Stage4Executor, Stage5Executor, Stage6Executor, Stage7Executor>, + transcript: &mut T, +) -> Result<(JoltProof, JoltProverArtifacts), JoltProveError> +where + CommitmentInputs: commitment_stage::CommitmentInputProvider, + Stage1OuterExecutor: stage1::Stage1KernelExecutor, + Stage2Executor: stage2::Stage2KernelExecutor, + Stage3Executor: stage3::Stage3KernelExecutor, + Stage4Executor: stage4::Stage4KernelExecutor, + Stage5Executor: stage5::Stage5KernelExecutor, + Stage6Executor: stage6::Stage6KernelExecutor, + Stage7Executor: stage7::Stage7KernelExecutor, + T: Transcript, +{ + prove_jolt_with_programs(inputs, default_prover_programs(), transcript) +} + +pub fn prove_jolt_with_programs( + inputs: JoltProverInputs<'_, CommitmentInputs, Stage1OuterExecutor, Stage2Executor, Stage3Executor, Stage4Executor, Stage5Executor, Stage6Executor, Stage7Executor>, + programs: JoltProverPrograms, + transcript: &mut T, +) -> Result<(JoltProof, JoltProverArtifacts), JoltProveError> +where + CommitmentInputs: commitment_stage::CommitmentInputProvider, + Stage1OuterExecutor: stage1::Stage1KernelExecutor, + Stage2Executor: stage2::Stage2KernelExecutor, + Stage3Executor: stage3::Stage3KernelExecutor, + Stage4Executor: stage4::Stage4KernelExecutor, + Stage5Executor: stage5::Stage5KernelExecutor, + Stage6Executor: stage6::Stage6KernelExecutor, + Stage7Executor: stage7::Stage7KernelExecutor, + T: Transcript, +{ + let _prove_span = tracing::info_span!("bolt.prove").entered(); + let _commitment_span = tracing::info_span!("bolt.commitment").entered(); + let commitment = commitment_stage::prove_commitment_phase_with_program( + programs.commitment, inputs.commitment_inputs, + inputs.prover_setup, + transcript, + )?; + drop(_commitment_span); + let _stage1_outer_span = tracing::info_span!("bolt.stage1").entered(); + let stage1_outer = stage1_outer_stage::prove_stage1_outer_with_program(programs.stage1_outer, inputs.stage1_outer_executor, transcript)?; + drop(_stage1_outer_span); + let _stage2_span = tracing::info_span!("bolt.stage2").entered(); + let stage2 = stage2_stage::execute_stage2_prover_with_program(programs.stage2, inputs.stage2_executor, transcript)?; + drop(_stage2_span); + let _stage3_span = tracing::info_span!("bolt.stage3").entered(); + let stage3 = stage3_stage::execute_stage3_prover_with_program(programs.stage3, inputs.stage3_executor, transcript)?; + drop(_stage3_span); + let _stage4_span = tracing::info_span!("bolt.stage4").entered(); + let stage4 = stage4_stage::execute_stage4_prover_with_program(programs.stage4, inputs.stage4_executor, transcript)?; + drop(_stage4_span); + let _stage5_span = tracing::info_span!("bolt.stage5").entered(); + let stage5 = stage5_stage::execute_stage5_prover_with_program(programs.stage5, inputs.stage5_executor, transcript)?; + drop(_stage5_span); + let _stage6_span = tracing::info_span!("bolt.stage6").entered(); + let stage6 = stage6_stage::execute_stage6_prover_with_program(programs.stage6, inputs.stage6_executor, transcript)?; + drop(_stage6_span); + let _stage7_span = tracing::info_span!("bolt.stage7").entered(); + let stage7 = stage7_stage::execute_stage7_prover_with_program(programs.stage7, inputs.stage7_executor, transcript)?; + drop(_stage7_span); + let evaluation = if let Some(stage7_openings) = inputs.stage7_openings { + let _stage8_span = tracing::info_span!("bolt.stage8").entered(); + let _evaluate_span = tracing::info_span!("bolt.evaluate").entered(); + Some(prove_jolt_evaluation_proof( + programs.stage8, + inputs.commitment_inputs, + inputs.prover_setup, + &commitment, + &stage6, + &stage7, + stage7_openings, + transcript, + )?) + } else { + None + }; + + let proof = JoltProof { + commitments: commitment.commitments.clone(), + stage1_outer: stage1_outer_proof(&stage1_outer), + stage2: stage2_proof(&stage2), + stage3: stage3_proof(&stage3), + stage4: stage4_proof(&stage4), + stage5: stage5_proof(&stage5), + stage6: stage6_proof(&stage6), + stage7: stage7_proof(&stage7), + evaluation, + }; + let artifacts = JoltProverArtifacts { + commitment, + stage1_outer, + stage2, + stage3, + stage4, + stage5, + stage6, + stage7, + }; + Ok((proof, artifacts)) +} + +pub fn prove_jolt_evaluation_proof( + program: &'static stage8_stage::Stage8EvaluationProgramPlan, + commitment_inputs: &mut I, + prover_setup: &DoryProverSetup, + commitments: &commitment_stage::CommitmentArtifacts, + stage6: &stage6::Stage6ExecutionArtifacts, + stage7: &stage7::Stage7ExecutionArtifacts, + stage7_openings: &[stage7::Stage7OpeningInputValue], + transcript: &mut T, +) -> Result +where + I: commitment_stage::CommitmentInputProvider, + T: Transcript, +{ + let _claims_span = tracing::info_span!("bolt.evaluate.claims").entered(); + let (sumcheck_address_point, stage7_values) = stage7_claim_values(program, stage7)?; + let address_point = reverse_point(&sumcheck_address_point); + let (opening_point, log_t) = + stage7_evaluation_opening_point(program, &address_point, stage7_openings)?; + let lagrange_factor = EqPolynomial::::zero_selector(&address_point); + let claims = evaluation_claims(program, stage6, &stage7_values, lagrange_factor)?; + drop(_claims_span); + + let _rlc_span = tracing::info_span!("bolt.evaluate.rlc_claims").entered(); + append_rlc_claims(transcript, &claims); + let gamma_powers = gamma_powers(transcript, claims.len()); + let joint_claim = claims + .iter() + .zip(&gamma_powers) + .map(|(claim, gamma)| claim.value * *gamma) + .sum(); + drop(_rlc_span); + let _materialize_span = + tracing::info_span!("bolt.evaluate.materialize_joint_polynomial").entered(); + let joint_evals = materialize_joint_polynomial( + commitment_inputs, + &claims, + &gamma_powers, + log_t, + opening_point.len(), + )?; + drop(_materialize_span); + let joint_poly = Polynomial::new(joint_evals); + let _hint_span = tracing::info_span!("bolt.evaluate.joint_opening_hint").entered(); + let joint_hint = joint_opening_hint(commitments, &claims, &gamma_powers)?; + drop(_hint_span); + let _dory_open_span = tracing::info_span!("bolt.evaluate.dory_open").entered(); + let joint_opening_proof = ::open( + &joint_poly, + &opening_point, + joint_claim, + prover_setup, + Some(joint_hint), + transcript, + ); + drop(_dory_open_span); + let _bind_span = tracing::info_span!("bolt.evaluate.bind_opening_inputs").entered(); + ::bind_opening_inputs( + transcript, + &opening_point, + &joint_claim, + ); + drop(_bind_span); + Ok(JoltEvaluationProof { joint_opening_proof }) +} + +struct EvaluationClaim { + oracle: &'static str, + source_stage: &'static str, + value: Fr, +} + +fn stage6_eval_claim( + artifacts: &stage6::Stage6ExecutionArtifacts, + eval_name: &'static str, +) -> Result { + for output in &artifacts.sumchecks { + if let Some(eval) = output.evals.iter().find(|eval| eval.name == eval_name) { + return Ok(eval.value); + } + } + Err(JoltEvaluationProveError::MissingStageEval { + stage: "stage6", + eval: eval_name, + }) +} + +fn evaluation_claims( + program: &'static stage8_stage::Stage8EvaluationProgramPlan, + stage6: &stage6::Stage6ExecutionArtifacts, + stage7_values: &std::collections::BTreeMap<&'static str, Fr>, + lagrange_factor: Fr, +) -> Result, JoltEvaluationProveError> { + let mut claims = Vec::with_capacity(program.opening_claims.len()); + for plan in program.opening_claims { + let value = match plan.source_stage { + "stage6" => stage6_eval_claim(stage6, plan.source_claim)? * lagrange_factor, + "stage7" => *stage7_values.get(plan.source_claim).ok_or( + JoltEvaluationProveError::MissingStageEval { + stage: plan.source_stage, + eval: plan.source_claim, + }, + )?, + _ => { + return Err(JoltEvaluationProveError::MissingStageEval { + stage: plan.source_stage, + eval: plan.source_claim, + }); + } + }; + claims.push(EvaluationClaim { + oracle: plan.oracle, + source_stage: plan.source_stage, + value, + }); + } + Ok(claims) +} + +fn stage7_claim_values( + program: &'static stage8_stage::Stage8EvaluationProgramPlan, + artifacts: &stage7::Stage7ExecutionArtifacts, +) -> Result<(Vec, std::collections::BTreeMap<&'static str, Fr>), JoltEvaluationProveError> { + let stage7_plans = program + .opening_claims + .iter() + .filter(|plan| plan.source_stage == "stage7") + .collect::>(); + for output in &artifacts.sumchecks { + let mut values = std::collections::BTreeMap::new(); + for plan in &stage7_plans { + if let Some(eval) = output.evals.iter().find(|eval| eval.name == plan.source_claim) { + let _ = values.insert(plan.source_claim, eval.value); + } + } + if values.len() == stage7_plans.len() { + return Ok((output.point.clone(), values)); + } + } + Err(JoltEvaluationProveError::MissingStage7RaEval) +} + +fn reverse_point(point: &[Fr]) -> Vec { + point.iter().rev().copied().collect() +} + +fn stage7_evaluation_opening_point( + program: &'static stage8_stage::Stage8EvaluationProgramPlan, + address_point: &[Fr], + stage7_openings: &[stage7::Stage7OpeningInputValue], +) -> Result<(Vec, usize), JoltEvaluationProveError> { + let cycle_source_symbol = program.evaluation_point_source.source_claim; + let cycle_source = stage7_openings + .iter() + .find(|input| input.symbol == cycle_source_symbol) + .ok_or(JoltEvaluationProveError::MissingStage7EvaluationPoint)?; + if cycle_source.point.len() < address_point.len() { + return Err(JoltEvaluationProveError::InvalidPointLength { + artifact: cycle_source_symbol, + expected: address_point.len(), + actual: cycle_source.point.len(), + }); + } + let cycle_len = cycle_source.point.len() - address_point.len(); + let mut point = Vec::with_capacity(cycle_source.point.len()); + point.extend_from_slice(address_point); + point.extend_from_slice(&cycle_source.point[address_point.len()..]); + Ok((point, cycle_len)) +} + +fn append_rlc_claims(transcript: &mut T, claims: &[EvaluationClaim]) +where + T: Transcript, +{ + transcript.append(&LabelWithCount(b"rlc_claims", claims.len() as u64)); + for claim in claims { + claim.value.append_to_transcript(transcript); + } +} + +fn gamma_powers(transcript: &mut T, count: usize) -> Vec +where + T: Transcript, +{ + let gamma = transcript.challenge(); + let mut powers = Vec::with_capacity(count); + let mut power = Fr::from_u64(1); + for _ in 0..count { + powers.push(power); + power *= gamma; + } + powers +} + +fn materialize_joint_polynomial( + commitment_inputs: &mut I, + claims: &[EvaluationClaim], + gamma_powers: &[Fr], + log_t: usize, + main_num_vars: usize, +) -> Result, JoltEvaluationProveError> +where + I: commitment_stage::CommitmentInputProvider, +{ + let trace_len = target_len(log_t)?; + let main_len = target_len(main_num_vars)?; + let mut joint = vec![Fr::from_u64(0); main_len]; + for (claim, gamma) in claims.iter().zip(gamma_powers) { + if claim.source_stage == "stage6" { + add_oracle_scaled(commitment_inputs, &mut joint, claim.oracle, log_t, trace_len, *gamma)?; + } else { + add_oracle_scaled( + commitment_inputs, + &mut joint, + claim.oracle, + main_num_vars, + main_len, + *gamma, + )?; + } + } + Ok(joint) +} + +fn add_oracle_scaled( + commitment_inputs: &mut I, + joint: &mut [Fr], + oracle: &'static str, + num_vars: usize, + limit: usize, + scalar: Fr, +) -> Result<(), JoltEvaluationProveError> +where + I: commitment_stage::CommitmentInputProvider, +{ + if commitment_inputs.add_scaled_to_joint(oracle, joint, num_vars, limit, scalar) { + return Ok(()); + } + let target_len = target_len(num_vars)?; + let data = commitment_inputs + .materialize_with_num_vars(oracle, num_vars) + .ok_or(JoltEvaluationProveError::MissingOracle { oracle })?; + if data.len() > target_len { + return Err(JoltEvaluationProveError::InvalidPointLength { + artifact: oracle, + expected: target_len, + actual: data.len(), + }); + } + let zero = Fr::from_u64(0); + let one = Fr::from_u64(1); + let len = limit.min(joint.len()).min(data.len()); + if len >= 1 << 15 { + joint[..len] + .par_iter_mut() + .zip(data[..len].par_iter()) + .for_each(|(dst, value)| { + if *value == zero { + return; + } + if *value == one { + *dst += scalar; + } else { + *dst += *value * scalar; + } + }); + } else { + for (dst, value) in joint.iter_mut().take(len).zip(data.iter()) { + if *value == zero { + continue; + } + if *value == one { + *dst += scalar; + } else { + *dst += *value * scalar; + } + } + } + Ok(()) +} + +fn joint_opening_hint( + commitments: &commitment_stage::CommitmentArtifacts, + claims: &[EvaluationClaim], + gamma_powers: &[Fr], +) -> Result { + let mut coefficients = std::collections::BTreeMap::<&'static str, Fr>::new(); + for (claim, gamma) in claims.iter().zip(gamma_powers) { + let coefficient = coefficients.entry(claim.oracle).or_insert(Fr::from_u64(0)); + *coefficient += *gamma; + } + + let mut hints = Vec::with_capacity(coefficients.len()); + let mut scalars = Vec::with_capacity(coefficients.len()); + for (oracle, coefficient) in coefficients { + hints.push(opening_hint_for_oracle(commitments, oracle)?); + scalars.push(coefficient); + } + + Ok(::combine_hints( + hints, &scalars, + )) +} + +fn opening_hint_for_oracle( + commitments: &commitment_stage::CommitmentArtifacts, + oracle: &'static str, +) -> Result { + commitments + .hints + .iter() + .find(|hint| hint.oracle == oracle) + .map(|hint| hint.hint.clone()) + .ok_or(JoltEvaluationProveError::MissingOpeningHint { oracle }) +} + +fn target_len(num_vars: usize) -> Result { + if num_vars >= usize::BITS as usize { + return Err(JoltEvaluationProveError::TargetSizeOverflow { num_vars }); + } + Ok(1usize << num_vars) +} + +pub struct JoltProverStageInputs<'a, CommitmentInputs> { + pub commitment_inputs: &'a mut CommitmentInputs, + pub prover_setup: &'a DoryProverSetup, + pub stage1_outer: stage1::Stage1ProverInputs<'a, Fr>, + pub stage2: stage2::Stage2ProverInputs<'a, Fr>, + pub stage3: stage3::Stage3ProverInputs<'a, Fr>, + pub stage4: stage4::Stage4ProverInputs<'a, Fr>, + pub stage5: stage5::Stage5ProverInputs<'a, Fr>, + pub stage6: stage6::Stage6ProverInputs<'a, Fr>, + pub stage7: stage7::Stage7ProverInputs<'a, Fr>, + pub stage7_openings: Option<&'a [stage7::Stage7OpeningInputValue]>, +} + +pub fn prove_jolt_with_stage_inputs( + inputs: JoltProverStageInputs<'_, CommitmentInputs>, + programs: JoltProverPrograms, + transcript: &mut T, +) -> Result<(JoltProof, JoltProverArtifacts), JoltProveError> +where + CommitmentInputs: commitment_stage::CommitmentInputProvider, + T: Transcript, +{ + let JoltProverStageInputs { + commitment_inputs, + prover_setup, + stage1_outer, + stage2, + stage3, + stage4, + stage5, + stage6, + stage7, + stage7_openings, + } = inputs; + let mut stage1_outer_executor = stage1::Stage1ProverKernelExecutor::new(stage1_outer); + let mut stage2_executor = stage2::Stage2ProverKernelExecutor::new(stage2); + let mut stage3_executor = stage3::Stage3ProverKernelExecutor::new(stage3); + let mut stage4_executor = stage4::Stage4ProverKernelExecutor::new(stage4); + let mut stage5_executor = stage5::Stage5ProverKernelExecutor::new(stage5); + let mut stage6_executor = stage6::Stage6ProverKernelExecutor::new(stage6); + let mut stage7_executor = stage7::Stage7ProverKernelExecutor::new(stage7); + prove_jolt_with_programs( + JoltProverInputs { + commitment_inputs, + prover_setup, + stage1_outer_executor: &mut stage1_outer_executor, + stage2_executor: &mut stage2_executor, + stage3_executor: &mut stage3_executor, + stage4_executor: &mut stage4_executor, + stage5_executor: &mut stage5_executor, + stage6_executor: &mut stage6_executor, + stage7_executor: &mut stage7_executor, + stage7_openings, + }, + programs, + transcript, + ) +} + +pub struct JoltProverWitnessInputs<'a, CommitmentInputs> { + pub commitment_inputs: &'a mut CommitmentInputs, + pub prover_setup: &'a DoryProverSetup, + pub stage1_trace_num_vars: usize, + pub stage1_outer_evaluator: &'a dyn stage1::Stage1OuterRemainingEvaluator, + pub stage2_openings: &'a [stage2::Stage2OpeningInputValue], + pub product_virtual_cycles: &'a [stage2::Stage2ProductVirtualCycle], + pub instruction_lookup_cycles: &'a [stage2::Stage2InstructionLookupCycle], + pub ram: &'a stage2::Stage2RamData<'a>, + pub stage3_openings: &'a [stage3::Stage3OpeningInputValue], + pub stage3_cycles: &'a [stage3::Stage3Cycle], + pub stage4_openings: &'a [stage4::Stage4OpeningInputValue], + pub register_count: usize, + pub trace_len: usize, + pub ram_k: usize, + pub register_accesses: &'a [stage4::Stage4RegisterAccess], + pub stage5_openings: &'a [stage5::Stage5OpeningInputValue], + pub lookup_indices: &'a [u128], + pub lookup_table_indices: &'a [Option], + pub is_interleaved_operands: &'a [bool], + pub ra_virtual_log_k_chunk: usize, + pub stage6_openings: &'a [stage6::Stage6OpeningInputValue], + pub stage6_bytecode_data: stage6::Stage6BytecodeReadRafData<'a, Fr>, + pub stage6_witness_params: Stage6WitnessParams, + pub cycle_inputs: &'a [CycleInput], + pub instruction_ra_virtual_d: usize, + pub stage7_openings: &'a [stage7::Stage7OpeningInputValue], + pub evaluation_openings: Option<&'a [stage7::Stage7OpeningInputValue]>, +} + +pub fn prove_jolt_with_witness_inputs( + inputs: JoltProverWitnessInputs<'_, CommitmentInputs>, + programs: JoltProverPrograms, + transcript: &mut T, +) -> Result<(JoltProof, JoltProverArtifacts), JoltProveError> +where + CommitmentInputs: commitment_stage::CommitmentInputProvider, + T: Transcript, +{ + let _input_span = tracing::info_span!("bolt.prove.inputs").entered(); + let _stage1_input_span = tracing::info_span!("bolt.prove.inputs.stage1").entered(); + let stage1_outer = + stage1_outer_prover_inputs(inputs.stage1_trace_num_vars, inputs.stage1_outer_evaluator); + drop(_stage1_input_span); + let _stage2_input_span = tracing::info_span!("bolt.prove.inputs.stage2").entered(); + let stage2 = stage2_prover_inputs( + inputs.stage2_openings, + inputs.product_virtual_cycles, + inputs.instruction_lookup_cycles, + inputs.ram, + )?; + drop(_stage2_input_span); + let _stage3_input_span = tracing::info_span!("bolt.prove.inputs.stage3").entered(); + let stage3 = stage3_prover_inputs(inputs.stage3_openings, inputs.stage3_cycles); + drop(_stage3_input_span); + let _stage45_witness_span = tracing::info_span!("bolt.prove.inputs.stage45_witness").entered(); + let stage45_witness = stage4::stage4_5_sparse_trace_witness_from_accesses( + inputs.register_accesses, + inputs.ram.accesses, + ); + drop(_stage45_witness_span); + let _stage4_input_span = tracing::info_span!("bolt.prove.inputs.stage4").entered(); + let stage4 = stage4_prover_inputs( + inputs.stage4_openings, + inputs.register_count, + inputs.trace_len, + inputs.ram_k, + inputs.register_accesses, + &stage45_witness, + ); + drop(_stage4_input_span); + let _stage5_input_span = tracing::info_span!("bolt.prove.inputs.stage5").entered(); + let stage5 = stage5_prover_inputs( + inputs.stage5_openings, + inputs.trace_len, + inputs.ram_k, + inputs.register_count, + inputs.lookup_indices, + inputs.lookup_table_indices, + inputs.is_interleaved_operands, + inputs.ra_virtual_log_k_chunk, + &stage45_witness, + ); + drop(_stage5_input_span); + let _stage6_witness_span = tracing::info_span!("bolt.prove.inputs.stage6_witness").entered(); + let stage6_witness = stage6_witness_from_opening_inputs( + inputs.stage6_witness_params, + inputs.cycle_inputs, + inputs.stage6_openings, + ); + let stage6_witness_slices = stage6_witness.slices(); + drop(_stage6_witness_span); + let _stage6_input_span = tracing::info_span!("bolt.prove.inputs.stage6").entered(); + let stage6 = stage6_prover_inputs( + inputs.stage6_openings, + inputs.stage6_bytecode_data, + &stage6_witness, + &stage6_witness_slices, + inputs.instruction_ra_virtual_d, + ); + drop(_stage6_input_span); + let _stage7_input_span = tracing::info_span!("bolt.prove.inputs.stage7").entered(); + let stage7 = stage7_prover_inputs(inputs.stage7_openings, &stage6_witness_slices); + drop(_stage7_input_span); + drop(_input_span); + prove_jolt_with_stage_inputs( + JoltProverStageInputs { + commitment_inputs: inputs.commitment_inputs, + prover_setup: inputs.prover_setup, + stage1_outer, + stage2, + stage3, + stage4, + stage5, + stage6, + stage7, + stage7_openings: inputs.evaluation_openings, + }, + programs, + transcript, + ) +} + +pub fn stage1_outer_prover_inputs( + trace_num_vars: usize, + evaluator: &dyn stage1::Stage1OuterRemainingEvaluator, +) -> stage1::Stage1ProverInputs<'_, Fr> { + stage1::Stage1ProverInputs::empty(trace_num_vars).with_outer_remaining_evaluator(evaluator) +} + +pub fn prove_stage1_outer_inputs_with_program( + program: &'static stage1::Stage1CpuProgramPlan, + inputs: stage1::Stage1ProverInputs<'_, Fr>, + transcript: &mut T, +) -> Result, stage1::Stage1KernelError> +where + T: Transcript, +{ + let mut executor = stage1::Stage1ProverKernelExecutor::new(inputs); + stage1_outer_stage::prove_stage1_outer_with_program(program, &mut executor, transcript) +} + +pub fn prove_stage1_outer_with_witness_inputs( + program: &'static stage1::Stage1CpuProgramPlan, + trace_num_vars: usize, + evaluator: &dyn stage1::Stage1OuterRemainingEvaluator, + transcript: &mut T, +) -> Result, stage1::Stage1KernelError> +where + T: Transcript, +{ + let inputs = stage1_outer_prover_inputs(trace_num_vars, evaluator); + prove_stage1_outer_inputs_with_program(program, inputs, transcript) +} + +pub fn replay_stage1_outer_proof_with_program( + program: &'static stage1::Stage1CpuProgramPlan, + proof: &stage1::Stage1Proof, + transcript: &mut T, +) -> Result, stage1::Stage1KernelError> +where + T: Transcript, +{ + let mut executor = stage1::Stage1VerifierKernelExecutor::new(proof); + stage1::execute_stage1_program( + program, + stage1::Stage1ExecutionMode::Verifier, + &mut executor, + transcript, + ) +} + +pub fn stage1_outer_proof_from_kernel_proof( + proof: &stage1::Stage1Proof, +) -> JoltStageProof { + JoltStageProof { + sumchecks: proof + .sumchecks + .iter() + .map(stage1_outer_sumcheck) + .collect(), + } +} + +pub fn stage2_prover_inputs<'a>( + opening_inputs: &'a [stage2::Stage2OpeningInputValue], + product_virtual_cycles: &'a [stage2::Stage2ProductVirtualCycle], + instruction_lookup_cycles: &'a [stage2::Stage2InstructionLookupCycle], + ram: &'a stage2::Stage2RamData<'a>, +) -> Result, stage2::Stage2KernelError> { + Ok(stage2::Stage2ProverInputs::new(opening_inputs) + .with_product_virtual_witness(product_virtual_cycles)? + .with_instruction_lookup_cycles(instruction_lookup_cycles) + .with_ram_data(ram)) +} + +pub struct JoltStage2RamDataStorage<'a> { + log_k: usize, + start_address: u64, + initial_ram: &'a [u64], + final_ram: &'a [u64], + accesses: Vec, + output_layout: Option, +} + +impl<'a> JoltStage2RamDataStorage<'a> { + pub fn from_kernel(ram: &stage2::Stage2RamData<'a>) -> Self { + Self { + log_k: ram.log_k, + start_address: ram.start_address, + initial_ram: ram.initial_ram, + final_ram: ram.final_ram, + accesses: ram + .accesses + .iter() + .map(|access| JoltStage2RamAccess { + remapped_address: access.remapped_address, + read_value: access.read_value, + write_value: access.write_value, + }) + .collect(), + output_layout: ram.output_layout.map(|layout| JoltStage2RamOutputLayout { + io_start: layout.io_start, + io_end: layout.io_end, + }), + } + } + + pub fn as_input(&self) -> JoltStage2RamData<'_> { + JoltStage2RamData { + log_k: self.log_k, + start_address: self.start_address, + initial_ram: self.initial_ram, + final_ram: self.final_ram, + accesses: &self.accesses, + output_layout: self.output_layout, + } + } +} + +pub fn stage2_verifier_ram_data<'a>( + ram: &stage2::Stage2RamData<'a>, +) -> JoltStage2RamDataStorage<'a> { + JoltStage2RamDataStorage::from_kernel(ram) +} + +pub trait JoltKernelOpeningInput { + fn symbol(&self) -> &'static str; + fn point(&self) -> &[Fr]; + fn eval(&self) -> Fr; +} + +macro_rules! impl_jolt_kernel_opening_input { + ($opening:ty) => { + impl JoltKernelOpeningInput for $opening { + fn symbol(&self) -> &'static str { + self.symbol + } + + fn point(&self) -> &[Fr] { + &self.point + } + + fn eval(&self) -> Fr { + self.eval + } + } + }; +} + +impl_jolt_kernel_opening_input!(stage2::Stage2OpeningInputValue); +impl_jolt_kernel_opening_input!(stage3::Stage3OpeningInputValue); +impl_jolt_kernel_opening_input!(stage4::Stage4OpeningInputValue); + +pub fn verifier_opening_inputs_from_kernel(inputs: &[I]) -> Vec +where + I: JoltKernelOpeningInput, +{ + inputs + .iter() + .map(|input| JoltStageOpeningInputValue { + symbol: input.symbol(), + point: input.point().to_vec(), + eval: input.eval(), + }) + .collect() +} + +pub fn prove_stage2_inputs_with_program( + program: &'static stage2::Stage2CpuProgramPlan, + inputs: stage2::Stage2ProverInputs<'_, Fr>, + transcript: &mut T, +) -> Result, stage2::Stage2KernelError> +where + T: Transcript, +{ + let mut executor = stage2::Stage2ProverKernelExecutor::new(inputs); + stage2_stage::execute_stage2_prover_with_program(program, &mut executor, transcript) +} + +pub fn prove_stage2_with_witness_inputs<'a, T>( + program: &'static stage2::Stage2CpuProgramPlan, + opening_inputs: &'a [stage2::Stage2OpeningInputValue], + product_virtual_cycles: &'a [stage2::Stage2ProductVirtualCycle], + instruction_lookup_cycles: &'a [stage2::Stage2InstructionLookupCycle], + ram: &'a stage2::Stage2RamData<'a>, + transcript: &mut T, +) -> Result, stage2::Stage2KernelError> +where + T: Transcript, +{ + let inputs = stage2_prover_inputs( + opening_inputs, + product_virtual_cycles, + instruction_lookup_cycles, + ram, + )?; + prove_stage2_inputs_with_program(program, inputs, transcript) +} + +pub fn stage2_opening_inputs_from_artifacts( + program: &'static stage2::Stage2CpuProgramPlan, + stage1_artifacts: &stage1::Stage1ExecutionArtifacts, +) -> Result>, JoltOpeningInputError> { + program + .opening_inputs + .iter() + .map(|input| { + let (point, eval) = match input.source_stage { + "stage1" => stage1_opening_claim(stage1_artifacts, input.source_claim)?, + source_stage => { + return Err(JoltOpeningInputError::UnsupportedOpeningInputSource { + stage: "stage2", + symbol: input.symbol, + source_stage, + }); + } + }; + validate_point_len(input.symbol, input.point_arity, point.len())?; + Ok(stage2::Stage2OpeningInputValue { + symbol: input.symbol, + point, + eval, + }) + }) + .collect() +} + +pub fn replay_stage2_proof_with_program<'a, T>( + program: &'static stage2::Stage2CpuProgramPlan, + proof: &'a stage2::Stage2Proof, + opening_inputs: &'a [stage2::Stage2OpeningInputValue], + ram: Option<&'a stage2::Stage2RamData<'a>>, + transcript: &mut T, +) -> Result, stage2::Stage2KernelError> +where + T: Transcript, +{ + let mut executor = stage2::Stage2VerifierKernelExecutor::new(proof, opening_inputs); + if let Some(ram) = ram { + executor = executor.with_ram_data(ram); + } + stage2::execute_stage2_program( + program, + stage2::Stage2ExecutionMode::Verifier, + &mut executor, + transcript, + ) +} + +pub fn stage3_prover_inputs<'a>( + opening_inputs: &'a [stage3::Stage3OpeningInputValue], + cycles: &'a [stage3::Stage3Cycle], +) -> stage3::Stage3ProverInputs<'a, Fr> { + stage3::Stage3ProverInputs::new(opening_inputs).with_cycles(cycles) +} + +pub fn prove_stage3_inputs_with_program( + program: &'static stage3::Stage3CpuProgramPlan, + inputs: stage3::Stage3ProverInputs<'_, Fr>, + transcript: &mut T, +) -> Result, stage3::Stage3KernelError> +where + T: Transcript, +{ + let mut executor = stage3::Stage3ProverKernelExecutor::new(inputs); + stage3_stage::execute_stage3_prover_with_program(program, &mut executor, transcript) +} + +pub fn prove_stage3_with_witness_inputs( + program: &'static stage3::Stage3CpuProgramPlan, + opening_inputs: &[stage3::Stage3OpeningInputValue], + cycles: &[stage3::Stage3Cycle], + transcript: &mut T, +) -> Result, stage3::Stage3KernelError> +where + T: Transcript, +{ + let inputs = stage3_prover_inputs(opening_inputs, cycles); + prove_stage3_inputs_with_program(program, inputs, transcript) +} + +pub fn stage3_opening_inputs_from_artifacts( + program: &'static stage3::Stage3CpuProgramPlan, + stage1_artifacts: &stage1::Stage1ExecutionArtifacts, + stage2_artifacts: &stage2::Stage2ExecutionArtifacts, +) -> Result>, JoltOpeningInputError> { + program + .opening_inputs + .iter() + .map(|input| { + let (point, eval) = match input.source_stage { + "stage1" => stage1_opening_claim(stage1_artifacts, input.source_claim)?, + "stage2" => stage2_opening_claim(stage2_artifacts, input.source_claim)?, + source_stage => { + return Err(JoltOpeningInputError::UnsupportedOpeningInputSource { + stage: "stage3", + symbol: input.symbol, + source_stage, + }); + } + }; + validate_point_len(input.symbol, input.point_arity, point.len())?; + Ok(stage3::Stage3OpeningInputValue { + symbol: input.symbol, + point, + eval, + }) + }) + .collect() +} + +pub fn replay_stage3_proof_with_program( + program: &'static stage3::Stage3CpuProgramPlan, + proof: &stage3::Stage3Proof, + opening_inputs: &[stage3::Stage3OpeningInputValue], + transcript: &mut T, +) -> Result, stage3::Stage3KernelError> +where + T: Transcript, +{ + let mut executor = stage3::Stage3VerifierKernelExecutor::new(proof, opening_inputs); + stage3::execute_stage3_program( + program, + stage3::Stage3ExecutionMode::Verifier, + &mut executor, + transcript, + ) +} + +pub fn stage4_prover_inputs<'a>( + opening_inputs: &'a [stage4::Stage4OpeningInputValue], + register_count: usize, + trace_len: usize, + ram_k: usize, + register_accesses: &'a [stage4::Stage4RegisterAccess], + witness: &'a Stage45SparseTraceWitness, +) -> stage4::Stage4ProverInputs<'a, Fr> { + stage4::Stage4ProverInputs::new(opening_inputs).with_stage45_sparse_trace_witness( + register_count, + trace_len, + ram_k, + register_accesses, + witness, + ) +} + +pub fn prove_stage4_inputs_with_program( + program: &'static stage4::Stage4CpuProgramPlan, + inputs: stage4::Stage4ProverInputs<'_, Fr>, + transcript: &mut T, +) -> Result, stage4::Stage4KernelError> +where + T: Transcript, +{ + let mut executor = stage4::Stage4ProverKernelExecutor::new(inputs); + stage4_stage::execute_stage4_prover_with_program(program, &mut executor, transcript) +} + +pub fn prove_stage4_with_witness_inputs( + program: &'static stage4::Stage4CpuProgramPlan, + opening_inputs: &[stage4::Stage4OpeningInputValue], + register_count: usize, + trace_len: usize, + ram_k: usize, + register_accesses: &[stage4::Stage4RegisterAccess], + witness: &Stage45SparseTraceWitness, + transcript: &mut T, +) -> Result, stage4::Stage4KernelError> +where + T: Transcript, +{ + let inputs = stage4_prover_inputs( + opening_inputs, + register_count, + trace_len, + ram_k, + register_accesses, + witness, + ); + prove_stage4_inputs_with_program(program, inputs, transcript) +} + +pub fn prove_stage4_with_trace_witness_inputs( + program: &'static stage4::Stage4CpuProgramPlan, + opening_inputs: &[stage4::Stage4OpeningInputValue], + register_count: usize, + trace_len: usize, + ram_k: usize, + register_accesses: &[stage4::Stage4RegisterAccess], + ram_accesses: &[stage2::Stage2RamAccess], + transcript: &mut T, +) -> Result, stage4::Stage4KernelError> +where + T: Transcript, +{ + let witness = stage4::stage4_5_sparse_trace_witness_from_accesses( + register_accesses, + ram_accesses, + ); + prove_stage4_with_witness_inputs( + program, + opening_inputs, + register_count, + trace_len, + ram_k, + register_accesses, + &witness, + transcript, + ) +} + +pub fn stage4_opening_inputs_from_artifacts( + program: &'static stage4::Stage4CpuProgramPlan, + initial_ram_state: &[u64], + stage2_artifacts: &stage2::Stage2ExecutionArtifacts, + stage3_artifacts: &stage3::Stage3ExecutionArtifacts, +) -> Result>, JoltOpeningInputError> { + program + .opening_inputs + .iter() + .map(|input| { + let (point, eval) = match input.source_stage { + "stage2" => stage2_opening_claim(stage2_artifacts, input.source_claim)?, + "stage3" => stage3_opening_claim(stage3_artifacts, input.source_claim)?, + "stage4_precomputed" => { + let (point, _) = stage2_opening_claim( + stage2_artifacts, + "stage2.ram_output.opening.RamValFinal", + )?; + stage4_ram_val_init_opening(initial_ram_state, &point) + } + source_stage => { + return Err(JoltOpeningInputError::UnsupportedOpeningInputSource { + stage: "stage4", + symbol: input.symbol, + source_stage, + }); + } + }; + opening_input_value(input.symbol, input.point_arity, point, eval) + }) + .collect() +} + +pub fn replay_stage4_proof_with_program( + program: &'static stage4::Stage4CpuProgramPlan, + proof: &stage4::Stage4Proof, + opening_inputs: &[stage4::Stage4OpeningInputValue], + transcript: &mut T, +) -> Result, stage4::Stage4KernelError> +where + T: Transcript, +{ + let mut executor = stage4::Stage4VerifierKernelExecutor::new(proof, opening_inputs); + stage4::execute_stage4_program( + program, + stage4::Stage4ExecutionMode::Verifier, + &mut executor, + transcript, + ) +} + +pub fn stage5_prover_inputs<'a>( + opening_inputs: &'a [stage5::Stage5OpeningInputValue], + trace_len: usize, + ram_k: usize, + register_count: usize, + lookup_indices: &'a [u128], + lookup_table_indices: &'a [Option], + is_interleaved_operands: &'a [bool], + ra_virtual_log_k_chunk: usize, + witness: &'a Stage45SparseTraceWitness, +) -> stage5::Stage5ProverInputs<'a, Fr> { + stage5::Stage5ProverInputs::new(opening_inputs).with_stage45_sparse_trace_witness( + trace_len, + ram_k, + register_count, + lookup_indices, + lookup_table_indices, + is_interleaved_operands, + ra_virtual_log_k_chunk, + witness, + ) +} + +pub fn prove_stage5_inputs_with_program( + program: &'static stage5::Stage5CpuProgramPlan, + inputs: stage5::Stage5ProverInputs<'_, Fr>, + transcript: &mut T, +) -> Result, stage5::Stage5KernelError> +where + T: Transcript, +{ + let mut executor = stage5::Stage5ProverKernelExecutor::new(inputs); + stage5_stage::execute_stage5_prover_with_program(program, &mut executor, transcript) +} + +pub fn prove_stage5_with_witness_inputs( + program: &'static stage5::Stage5CpuProgramPlan, + opening_inputs: &[stage5::Stage5OpeningInputValue], + trace_len: usize, + ram_k: usize, + register_count: usize, + lookup_indices: &[u128], + lookup_table_indices: &[Option], + is_interleaved_operands: &[bool], + ra_virtual_log_k_chunk: usize, + witness: &Stage45SparseTraceWitness, + transcript: &mut T, +) -> Result, stage5::Stage5KernelError> +where + T: Transcript, +{ + let inputs = stage5_prover_inputs( + opening_inputs, + trace_len, + ram_k, + register_count, + lookup_indices, + lookup_table_indices, + is_interleaved_operands, + ra_virtual_log_k_chunk, + witness, + ); + prove_stage5_inputs_with_program(program, inputs, transcript) +} + +pub fn prove_stage5_with_trace_witness_inputs( + program: &'static stage5::Stage5CpuProgramPlan, + opening_inputs: &[stage5::Stage5OpeningInputValue], + trace_len: usize, + ram_k: usize, + register_count: usize, + lookup_indices: &[u128], + lookup_table_indices: &[Option], + is_interleaved_operands: &[bool], + ra_virtual_log_k_chunk: usize, + register_accesses: &[stage4::Stage4RegisterAccess], + ram_accesses: &[stage2::Stage2RamAccess], + transcript: &mut T, +) -> Result, stage5::Stage5KernelError> +where + T: Transcript, +{ + let witness = stage4::stage4_5_sparse_trace_witness_from_accesses( + register_accesses, + ram_accesses, + ); + prove_stage5_with_witness_inputs( + program, + opening_inputs, + trace_len, + ram_k, + register_count, + lookup_indices, + lookup_table_indices, + is_interleaved_operands, + ra_virtual_log_k_chunk, + &witness, + transcript, + ) +} + +pub fn stage5_opening_inputs_from_artifacts( + program: &'static stage5::Stage5CpuProgramPlan, + stage2_artifacts: &stage2::Stage2ExecutionArtifacts, + stage4_artifacts: &stage4::Stage4ExecutionArtifacts, +) -> Result>, JoltOpeningInputError> { + program + .opening_inputs + .iter() + .map(|input| { + let (point, eval) = match input.source_stage { + "stage2" => stage2_opening_claim(stage2_artifacts, input.source_claim)?, + "stage4" => stage4_opening_claim(stage4_artifacts, input.source_claim)?, + source_stage => { + return Err(JoltOpeningInputError::UnsupportedOpeningInputSource { + stage: "stage5", + symbol: input.symbol, + source_stage, + }); + } + }; + opening_input_value(input.symbol, input.point_arity, point, eval) + }) + .collect() +} + +pub fn stage5_kernel_proof( + artifacts: &stage5::Stage5ExecutionArtifacts, +) -> stage5::Stage5Proof { + stage5::Stage5Proof { + sumchecks: artifacts.sumchecks.clone(), + } +} + +pub fn jolt_proof_through_stage5( + commitments: &[Option], + stage1_artifacts: &stage1::Stage1ExecutionArtifacts, + stage2_artifacts: &stage2::Stage2ExecutionArtifacts, + stage3_artifacts: &stage3::Stage3ExecutionArtifacts, + stage4_artifacts: &stage4::Stage4ExecutionArtifacts, + stage5_proof: &JoltStageProof, +) -> JoltProof { + JoltProof { + commitments: commitments.to_vec(), + stage1_outer: stage1_outer_proof(stage1_artifacts), + stage2: stage2_proof(stage2_artifacts), + stage3: stage3_proof(stage3_artifacts), + stage4: stage4_proof(stage4_artifacts), + stage5: stage5_proof.clone(), + stage6: JoltStageProof::default(), + stage7: JoltStageProof::default(), + evaluation: None, + } +} + +pub fn jolt_proof_through_stage6( + commitments: &[Option], + stage1_artifacts: &stage1::Stage1ExecutionArtifacts, + stage2_artifacts: &stage2::Stage2ExecutionArtifacts, + stage3_artifacts: &stage3::Stage3ExecutionArtifacts, + stage4_artifacts: &stage4::Stage4ExecutionArtifacts, + stage5_proof: &JoltStageProof, + stage6_proof: &JoltStageProof, +) -> JoltProof { + let mut proof = jolt_proof_through_stage5( + commitments, + stage1_artifacts, + stage2_artifacts, + stage3_artifacts, + stage4_artifacts, + stage5_proof, + ); + proof.stage6 = stage6_proof.clone(); + proof +} + +pub fn jolt_proof_through_stage7( + commitments: &[Option], + stage1_artifacts: &stage1::Stage1ExecutionArtifacts, + stage2_artifacts: &stage2::Stage2ExecutionArtifacts, + stage3_artifacts: &stage3::Stage3ExecutionArtifacts, + stage4_artifacts: &stage4::Stage4ExecutionArtifacts, + stage5_proof: &JoltStageProof, + stage6_proof: &JoltStageProof, + stage7_proof: &JoltStageProof, +) -> JoltProof { + let mut proof = jolt_proof_through_stage6( + commitments, + stage1_artifacts, + stage2_artifacts, + stage3_artifacts, + stage4_artifacts, + stage5_proof, + stage6_proof, + ); + proof.stage7 = stage7_proof.clone(); + proof +} + +pub fn replay_stage5_proof_with_program( + program: &'static stage5::Stage5CpuProgramPlan, + proof: &stage5::Stage5Proof, + opening_inputs: &[stage5::Stage5OpeningInputValue], + transcript: &mut T, +) -> Result, stage5::Stage5KernelError> +where + T: Transcript, +{ + let mut executor = stage5::Stage5ProofCarryingKernelExecutor::new(proof, opening_inputs); + stage5_stage::execute_stage5_prover_with_program(program, &mut executor, transcript) +} + +pub fn stage6_witness_from_opening_inputs( + params: Stage6WitnessParams, + cycle_inputs: &[CycleInput], + opening_inputs: &[stage6::Stage6OpeningInputValue], +) -> Stage6WitnessPolynomials { + stage6::stage6_witness_from_opening_inputs(params, cycle_inputs, opening_inputs) +} + +pub fn stage6_bytecode_read_raf_data_from_witness_entries( + entries: &[WitnessStage6BytecodeEntry], + entry_bytecode_index: usize, + num_lookup_tables: usize, +) -> stage6::Stage6BytecodeReadRafDataStorage { + stage6::Stage6BytecodeReadRafDataStorage::from_witness_entries( + entries, + entry_bytecode_index, + num_lookup_tables, + ) +} + +pub fn stage6_verifier_data_from_witness_entries( + entries: &[WitnessStage6BytecodeEntry], + entry_bytecode_index: usize, + num_lookup_tables: usize, +) -> JoltStage6VerifierData { + JoltStage6VerifierData { + bytecode_read_raf: Some(JoltStage6BytecodeReadRafData { + entries: entries + .iter() + .map(|entry| JoltStage6BytecodeEntry { + address: entry.address, + imm: entry.imm, + circuit_flags: entry.circuit_flags, + rd: entry.rd, + rs1: entry.rs1, + rs2: entry.rs2, + lookup_table: entry.lookup_table, + is_interleaved: entry.is_interleaved, + is_branch: entry.is_branch, + left_is_rs1: entry.left_is_rs1, + left_is_pc: entry.left_is_pc, + right_is_rs2: entry.right_is_rs2, + right_is_imm: entry.right_is_imm, + is_noop: entry.is_noop, + }) + .collect(), + entry_bytecode_index, + num_lookup_tables, + }), + } +} + +pub fn stage6_prover_inputs<'a>( + opening_inputs: &'a [stage6::Stage6OpeningInputValue], + bytecode_data: stage6::Stage6BytecodeReadRafData<'a, Fr>, + witness: &'a Stage6WitnessPolynomials, + slices: &'a Stage6WitnessSlices<'a, Fr>, + instruction_ra_virtual_d: usize, +) -> stage6::Stage6ProverInputs<'a, Fr> { + stage6::Stage6ProverInputs::new(opening_inputs).with_stage6_witness( + bytecode_data, + witness, + slices, + instruction_ra_virtual_d, + ) +} + +pub fn prove_stage6_inputs_with_program( + program: &'static stage6::Stage6CpuProgramPlan, + inputs: stage6::Stage6ProverInputs<'_, Fr>, + transcript: &mut T, +) -> Result, stage6::Stage6KernelError> +where + T: Transcript, +{ + let mut executor = stage6::Stage6ProverKernelExecutor::new(inputs); + stage6_stage::execute_stage6_prover_with_program(program, &mut executor, transcript) +} + +pub fn prove_stage6_with_witness_inputs( + program: &'static stage6::Stage6CpuProgramPlan, + opening_inputs: &[stage6::Stage6OpeningInputValue], + bytecode_data: stage6::Stage6BytecodeReadRafData<'_, Fr>, + witness: &Stage6WitnessPolynomials, + slices: &Stage6WitnessSlices<'_, Fr>, + instruction_ra_virtual_d: usize, + transcript: &mut T, +) -> Result, stage6::Stage6KernelError> +where + T: Transcript, +{ + let inputs = stage6_prover_inputs( + opening_inputs, + bytecode_data, + witness, + slices, + instruction_ra_virtual_d, + ); + prove_stage6_inputs_with_program(program, inputs, transcript) +} + +pub fn prove_stage6_with_trace_witness_inputs( + program: &'static stage6::Stage6CpuProgramPlan, + opening_inputs: &[stage6::Stage6OpeningInputValue], + bytecode_data: stage6::Stage6BytecodeReadRafData<'_, Fr>, + witness_params: Stage6WitnessParams, + cycle_inputs: &[CycleInput], + instruction_ra_virtual_d: usize, + transcript: &mut T, +) -> Result, stage6::Stage6KernelError> +where + T: Transcript, +{ + let witness = stage6_witness_from_opening_inputs(witness_params, cycle_inputs, opening_inputs); + let slices = witness.slices(); + prove_stage6_with_witness_inputs( + program, + opening_inputs, + bytecode_data, + &witness, + &slices, + instruction_ra_virtual_d, + transcript, + ) +} + +pub fn stage6_opening_inputs_from_artifacts( + program: &'static stage6::Stage6CpuProgramPlan, + stage1_artifacts: &stage1::Stage1ExecutionArtifacts, + stage2_artifacts: &stage2::Stage2ExecutionArtifacts, + stage3_artifacts: &stage3::Stage3ExecutionArtifacts, + stage4_artifacts: &stage4::Stage4ExecutionArtifacts, + stage5_artifacts: &stage5::Stage5ExecutionArtifacts, +) -> Result>, JoltOpeningInputError> { + program + .opening_inputs + .iter() + .map(|input| { + let (point, eval) = match input.source_stage { + "stage1" => stage1_opening_claim(stage1_artifacts, input.source_claim)?, + "stage2" => stage2_opening_claim(stage2_artifacts, input.source_claim)?, + "stage3" => stage3_opening_claim(stage3_artifacts, input.source_claim)?, + "stage4" => stage4_opening_claim(stage4_artifacts, input.source_claim)?, + "stage5" => stage5_opening_claim(stage5_artifacts, input.source_claim)?, + source_stage => { + return Err(JoltOpeningInputError::UnsupportedOpeningInputSource { + stage: "stage6", + symbol: input.symbol, + source_stage, + }); + } + }; + opening_input_value(input.symbol, input.point_arity, point, eval) + }) + .collect() +} + +pub fn stage6_kernel_proof(proof: &JoltStageProof) -> stage6::Stage6Proof { + stage6::Stage6Proof { + sumchecks: proof + .sumchecks + .iter() + .map(stage6_kernel_sumcheck_output) + .collect(), + } +} + +fn stage6_kernel_sumcheck_output( + output: &JoltSumcheckOutput, +) -> stage6::Stage6SumcheckOutput { + stage6::Stage6SumcheckOutput { + driver: output.driver, + point: output.point.clone(), + evals: output.evals.iter().map(stage6_kernel_eval).collect(), + opening_claims: Vec::new(), + proof: output.proof.clone(), + } +} + +fn stage6_kernel_eval(eval: &JoltNamedEval) -> stage6::Stage6NamedEval { + stage6::Stage6NamedEval { + name: eval.name, + oracle: eval.oracle, + value: eval.value, + } +} + +pub fn stage6_execution_artifacts( + artifacts: &stage6::Stage6ExecutionArtifacts, +) -> JoltStageExecutionArtifacts { + JoltStageExecutionArtifacts { + challenge_vectors: artifacts + .challenge_vectors + .iter() + .map(|challenge| JoltStageChallengeVector { + symbol: challenge.symbol, + values: challenge.values.clone(), + }) + .collect(), + sumchecks: stage6_proof(artifacts).sumchecks, + opening_batches: Vec::new(), + } +} + +pub fn replay_stage6_proof_with_program<'a, T>( + program: &'static stage6::Stage6CpuProgramPlan, + proof: &'a stage6::Stage6Proof, + opening_inputs: &'a [stage6::Stage6OpeningInputValue], + bytecode_data: Option>, + transcript: &mut T, +) -> Result, stage6::Stage6KernelError> +where + T: Transcript, +{ + let mut executor = stage6::Stage6ProofCarryingKernelExecutor::new(proof, opening_inputs); + if let Some(bytecode_data) = bytecode_data { + executor = executor.with_bytecode_read_raf_data(bytecode_data); + } + stage6_stage::execute_stage6_prover_with_program(program, &mut executor, transcript) +} + +pub fn stage7_prover_inputs<'a>( + opening_inputs: &'a [stage7::Stage7OpeningInputValue], + slices: &'a Stage6WitnessSlices<'a, Fr>, +) -> stage7::Stage7ProverInputs<'a, Fr> { + stage7::Stage7ProverInputs::new(opening_inputs).with_stage6_witness_indices(slices) +} + +pub fn prove_stage7_inputs_with_program( + program: &'static stage7::Stage7CpuProgramPlan, + inputs: stage7::Stage7ProverInputs<'_, Fr>, + transcript: &mut T, +) -> Result, stage7::Stage7KernelError> +where + T: Transcript, +{ + let mut executor = stage7::Stage7ProverKernelExecutor::new(inputs); + stage7_stage::execute_stage7_prover_with_program(program, &mut executor, transcript) +} + +pub fn prove_stage7_with_witness_inputs( + program: &'static stage7::Stage7CpuProgramPlan, + opening_inputs: &[stage7::Stage7OpeningInputValue], + slices: &Stage6WitnessSlices<'_, Fr>, + transcript: &mut T, +) -> Result, stage7::Stage7KernelError> +where + T: Transcript, +{ + let inputs = stage7_prover_inputs(opening_inputs, slices); + prove_stage7_inputs_with_program(program, inputs, transcript) +} + +pub fn prove_stage7_with_trace_witness_inputs( + program: &'static stage7::Stage7CpuProgramPlan, + opening_inputs: &[stage7::Stage7OpeningInputValue], + witness_params: Stage6WitnessParams, + cycle_inputs: &[CycleInput], + stage6_openings: &[stage6::Stage6OpeningInputValue], + transcript: &mut T, +) -> Result, stage7::Stage7KernelError> +where + T: Transcript, +{ + let witness = stage6_witness_from_opening_inputs(witness_params, cycle_inputs, stage6_openings); + let slices = witness.slices(); + prove_stage7_with_witness_inputs(program, opening_inputs, &slices, transcript) +} + +pub fn stage7_kernel_proof(proof: &JoltStageProof) -> stage7::Stage7Proof { + stage7::Stage7Proof { + sumchecks: proof + .sumchecks + .iter() + .map(stage7_kernel_sumcheck_output) + .collect(), + } +} + +fn stage7_kernel_sumcheck_output( + output: &JoltSumcheckOutput, +) -> stage7::Stage7SumcheckOutput { + stage7::Stage7SumcheckOutput { + driver: output.driver, + point: output.point.clone(), + evals: output.evals.iter().map(stage7_kernel_eval).collect(), + opening_claims: Vec::new(), + proof: output.proof.clone(), + } +} + +fn stage7_kernel_eval(eval: &JoltNamedEval) -> stage7::Stage7NamedEval { + stage7::Stage7NamedEval { + name: eval.name, + oracle: eval.oracle, + value: eval.value, + } +} + +pub fn stage7_execution_artifacts( + artifacts: &stage7::Stage7ExecutionArtifacts, +) -> JoltStageExecutionArtifacts { + JoltStageExecutionArtifacts { + challenge_vectors: artifacts + .challenge_vectors + .iter() + .map(|challenge| JoltStageChallengeVector { + symbol: challenge.symbol, + values: challenge.values.clone(), + }) + .collect(), + sumchecks: stage7_proof(artifacts).sumchecks, + opening_batches: Vec::new(), + } +} + +pub fn replay_stage7_proof_with_program( + program: &'static stage7::Stage7CpuProgramPlan, + proof: &stage7::Stage7Proof, + opening_inputs: &[stage7::Stage7OpeningInputValue], + transcript: &mut T, +) -> Result, stage7::Stage7KernelError> +where + T: Transcript, +{ + let mut executor = stage7::Stage7ProofCarryingKernelExecutor::new(proof, opening_inputs); + stage7_stage::execute_stage7_prover_with_program(program, &mut executor, transcript) +} + +pub fn stage7_opening_inputs_from_stage6_artifacts( + artifacts: &stage6::Stage6ExecutionArtifacts, +) -> Result>, JoltOpeningInputError> { + stage7_opening_inputs_from_stage6_artifacts_with_program(&stage7_stage::STAGE7_PROGRAM, artifacts) +} + +pub fn stage7_opening_inputs_from_stage6_artifacts_with_program( + program: &'static stage7::Stage7CpuProgramPlan, + artifacts: &stage6::Stage6ExecutionArtifacts, +) -> Result>, JoltOpeningInputError> { + program + .opening_inputs + .iter() + .map(|input| { + let (point, eval) = stage6_opening_claim(artifacts, input.symbol, input.source_stage, input.source_claim, input.point_arity)?; + Ok(stage7::Stage7OpeningInputValue { + symbol: input.symbol, + point, + eval, + }) + }) + .collect() +} + +fn stage6_opening_claim( + artifacts: &stage6::Stage6ExecutionArtifacts, + symbol: &'static str, + source_stage: &'static str, + source_claim: &'static str, + point_arity: usize, +) -> Result<(Vec, Fr), JoltOpeningInputError> { + if source_stage != "stage6" { + return Err(JoltOpeningInputError::UnsupportedStage7InputSource { + symbol, + source_stage, + }); + } + let opening = artifacts + .opening_claims + .iter() + .find(|opening| opening.symbol == source_claim) + .ok_or(JoltOpeningInputError::MissingStage6OpeningClaim { source_claim })?; + if opening.point.len() != point_arity { + return Err(JoltOpeningInputError::InvalidPointLength { + symbol, + expected: point_arity, + actual: opening.point.len(), + }); + } + Ok((opening.point.clone(), opening.eval)) +} + +fn opening_input_value( + symbol: &'static str, + point_arity: usize, + point: Vec, + eval: Fr, +) -> Result, JoltOpeningInputError> { + validate_point_len(symbol, point_arity, point.len())?; + Ok(stage4::Stage4OpeningInputValue { + symbol, + point, + eval, + }) +} + +fn validate_point_len( + symbol: &'static str, + expected: usize, + actual: usize, +) -> Result<(), JoltOpeningInputError> { + if actual != expected { + return Err(JoltOpeningInputError::InvalidPointLength { + symbol, + expected, + actual, + }); + } + Ok(()) +} + +fn stage1_opening_claim( + artifacts: &stage1::Stage1ExecutionArtifacts, + source_claim: &'static str, +) -> Result<(Vec, Fr), JoltOpeningInputError> { + let opening = artifacts.opening_value(source_claim).ok_or( + JoltOpeningInputError::MissingOpeningClaim { + stage: "stage1", + source_claim, + }, + )?; + Ok((opening.point.clone(), opening.eval)) +} + +fn stage2_opening_claim( + artifacts: &stage2::Stage2ExecutionArtifacts, + source_claim: &'static str, +) -> Result<(Vec, Fr), JoltOpeningInputError> { + artifacts + .opening_claims + .iter() + .find(|opening| opening.symbol == source_claim) + .map(|opening| (opening.point.clone(), opening.eval)) + .ok_or(JoltOpeningInputError::MissingOpeningClaim { + stage: "stage2", + source_claim, + }) +} + +fn stage3_opening_claim( + artifacts: &stage3::Stage3ExecutionArtifacts, + source_claim: &'static str, +) -> Result<(Vec, Fr), JoltOpeningInputError> { + artifacts + .opening_claims + .iter() + .find(|opening| opening.symbol == source_claim) + .map(|opening| (opening.point.clone(), opening.eval)) + .ok_or(JoltOpeningInputError::MissingOpeningClaim { + stage: "stage3", + source_claim, + }) +} + +fn stage4_opening_claim( + artifacts: &stage4::Stage4ExecutionArtifacts, + source_claim: &'static str, +) -> Result<(Vec, Fr), JoltOpeningInputError> { + artifacts + .opening_claims + .iter() + .find(|opening| opening.symbol == source_claim) + .map(|opening| (opening.point.clone(), opening.eval)) + .ok_or(JoltOpeningInputError::MissingOpeningClaim { + stage: "stage4", + source_claim, + }) +} + +fn stage5_opening_claim( + artifacts: &stage5::Stage5ExecutionArtifacts, + source_claim: &'static str, +) -> Result<(Vec, Fr), JoltOpeningInputError> { + artifacts + .opening_claims + .iter() + .find(|opening| opening.symbol == source_claim) + .map(|opening| (opening.point.clone(), opening.eval)) + .ok_or(JoltOpeningInputError::MissingOpeningClaim { + stage: "stage5", + source_claim, + }) +} + +pub fn stage1_outer_proof(artifacts: &stage1::Stage1ExecutionArtifacts) -> JoltStageProof { + JoltStageProof { + sumchecks: artifacts.sumchecks.iter().map(stage1_outer_sumcheck).collect(), + } +} + +fn stage1_outer_sumcheck(output: &stage1::Stage1SumcheckOutput) -> JoltSumcheckOutput { + JoltSumcheckOutput { + driver: output.driver, + point: output.point.clone(), + evals: output.evals.iter().map(stage1_outer_eval).collect(), + proof: output.proof.clone(), + } +} + +fn stage1_outer_eval(eval: &stage1::Stage1NamedEval) -> JoltNamedEval { + JoltNamedEval { + name: eval.name, + oracle: eval.oracle, + value: eval.value, + } +} + +pub fn stage2_proof(artifacts: &stage2::Stage2ExecutionArtifacts) -> JoltStageProof { + JoltStageProof { + sumchecks: artifacts.sumchecks.iter().map(stage2_sumcheck).collect(), + } +} + +fn stage2_sumcheck(output: &stage2::Stage2SumcheckOutput) -> JoltSumcheckOutput { + JoltSumcheckOutput { + driver: output.driver, + point: output.point.clone(), + evals: output.evals.iter().map(stage2_eval).collect(), + proof: output.proof.clone(), + } +} + +fn stage2_eval(eval: &stage2::Stage2NamedEval) -> JoltNamedEval { + JoltNamedEval { + name: eval.name, + oracle: eval.oracle, + value: eval.value, + } +} + +pub fn stage3_proof(artifacts: &stage3::Stage3ExecutionArtifacts) -> JoltStageProof { + JoltStageProof { + sumchecks: artifacts.sumchecks.iter().map(stage3_sumcheck).collect(), + } +} + +fn stage3_sumcheck(output: &stage3::Stage3SumcheckOutput) -> JoltSumcheckOutput { + JoltSumcheckOutput { + driver: output.driver, + point: output.point.clone(), + evals: output.evals.iter().map(stage3_eval).collect(), + proof: output.proof.clone(), + } +} + +fn stage3_eval(eval: &stage3::Stage3NamedEval) -> JoltNamedEval { + JoltNamedEval { + name: eval.name, + oracle: eval.oracle, + value: eval.value, + } +} + +pub fn stage4_proof(artifacts: &stage4::Stage4ExecutionArtifacts) -> JoltStageProof { + JoltStageProof { + sumchecks: artifacts.sumchecks.iter().map(stage4_sumcheck).collect(), + } +} + +fn stage4_sumcheck(output: &stage4::Stage4SumcheckOutput) -> JoltSumcheckOutput { + JoltSumcheckOutput { + driver: output.driver, + point: output.point.clone(), + evals: output.evals.iter().map(stage4_eval).collect(), + proof: output.proof.clone(), + } +} + +fn stage4_eval(eval: &stage4::Stage4NamedEval) -> JoltNamedEval { + JoltNamedEval { + name: eval.name, + oracle: eval.oracle, + value: eval.value, + } +} + +pub fn stage5_proof(artifacts: &stage5::Stage5ExecutionArtifacts) -> JoltStageProof { + JoltStageProof { + sumchecks: artifacts.sumchecks.iter().map(stage5_sumcheck).collect(), + } +} + +fn stage5_sumcheck(output: &stage5::Stage5SumcheckOutput) -> JoltSumcheckOutput { + JoltSumcheckOutput { + driver: output.driver, + point: output.point.clone(), + evals: output.evals.iter().map(stage5_eval).collect(), + proof: output.proof.clone(), + } +} + +fn stage5_eval(eval: &stage5::Stage5NamedEval) -> JoltNamedEval { + JoltNamedEval { + name: eval.name, + oracle: eval.oracle, + value: eval.value, + } +} + +pub fn stage6_proof(artifacts: &stage6::Stage6ExecutionArtifacts) -> JoltStageProof { + JoltStageProof { + sumchecks: artifacts.sumchecks.iter().map(stage6_sumcheck).collect(), + } +} + +fn stage6_sumcheck(output: &stage6::Stage6SumcheckOutput) -> JoltSumcheckOutput { + JoltSumcheckOutput { + driver: output.driver, + point: output.point.clone(), + evals: output.evals.iter().map(stage6_eval).collect(), + proof: output.proof.clone(), + } +} + +fn stage6_eval(eval: &stage6::Stage6NamedEval) -> JoltNamedEval { + JoltNamedEval { + name: eval.name, + oracle: eval.oracle, + value: eval.value, + } +} + +pub fn stage7_proof(artifacts: &stage7::Stage7ExecutionArtifacts) -> JoltStageProof { + JoltStageProof { + sumchecks: artifacts.sumchecks.iter().map(stage7_sumcheck).collect(), + } +} + +fn stage7_sumcheck(output: &stage7::Stage7SumcheckOutput) -> JoltSumcheckOutput { + JoltSumcheckOutput { + driver: output.driver, + point: output.point.clone(), + evals: output.evals.iter().map(stage7_eval).collect(), + proof: output.proof.clone(), + } +} + +fn stage7_eval(eval: &stage7::Stage7NamedEval) -> JoltNamedEval { + JoltNamedEval { + name: eval.name, + oracle: eval.oracle, + value: eval.value, + } +} diff --git a/crates/jolt-prover/src/stages/commitment.rs b/crates/jolt-prover/src/stages/commitment.rs new file mode 100644 index 0000000000..7378d2bd39 --- /dev/null +++ b/crates/jolt-prover/src/stages/commitment.rs @@ -0,0 +1,1075 @@ +#![allow(dead_code)] + +use std::borrow::Cow; + +use jolt_dory::{DoryCommitment, DoryHint, DoryProverSetup, DoryScheme}; +use jolt_field::{Field, Fr}; +use jolt_openings::CommitmentScheme as _; +use jolt_poly::{EqPolynomial, MultilinearPoly}; +use jolt_transcript::{AppendToTranscript, Blake2bTranscript, LabelWithCount, Transcript}; +use jolt_witness::{dense_i128_column_to_field, one_hot_chunk_address_major, one_hot_chunk_indices, optional_field_oracle, CommitmentTraceSources}; +use rayon::prelude::*; + +pub type DefaultCommitmentTranscript = Blake2bTranscript; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct CommitmentParams { + pub field: &'static str, + pub pcs: &'static str, + pub transcript: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct OraclePlan { + pub oracle: &'static str, + pub domain: &'static str, + pub num_vars: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct CommitmentBatchPlan { + pub artifact: &'static str, + pub pcs: &'static str, + pub oracle_family: &'static str, + pub label: &'static str, + pub oracles: &'static [&'static str], + pub count: usize, + pub domain: &'static str, + pub num_vars: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum OptionalSkipPolicy { + MissingOrZero, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct OptionalCommitmentPlan { + pub artifact: &'static str, + pub pcs: &'static str, + pub oracle: &'static str, + pub label: &'static str, + pub domain: &'static str, + pub num_vars: usize, + pub skip_policy: OptionalSkipPolicy, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct TranscriptStep { + pub label: &'static str, + pub source: &'static str, + pub optional: bool, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct CommitmentProverProgramPlan { + pub params: CommitmentParams, + pub oracle_plans: &'static [OraclePlan], + pub batch_plans: &'static [CommitmentBatchPlan], + pub optional_plans: &'static [OptionalCommitmentPlan], + pub transcript_steps: &'static [TranscriptStep], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct CommitmentRecord { + pub artifact: &'static str, + pub oracle: &'static str, + pub label: &'static str, + pub num_vars: usize, +} + +#[derive(Clone, Debug)] +pub struct OracleOpeningHint { + pub oracle: &'static str, + pub hint: DoryHint, +} + +#[derive(Clone, Debug)] +pub struct CommittedOracle { + pub commitment: Option, + pub record: CommitmentRecord, + pub hint: Option, +} + +#[derive(Clone, Debug, Default)] +pub struct CommitmentArtifacts { + pub commitments: Vec>, + pub records: Vec, + pub hints: Vec, +} + +pub trait CommitmentInputProvider { + fn materialize(&mut self, oracle: &'static str) -> Option>; + + fn materialize_with_num_vars( + &mut self, + oracle: &'static str, + _num_vars: usize, + ) -> Option> { + self.materialize(oracle) + } + + fn commit_batch( + &mut self, + _program: &CommitmentProverProgramPlan, + _plan: &CommitmentBatchPlan, + _prover_setup: &DoryProverSetup, + ) -> Option, CommitmentPhaseError>> { + None + } + + fn add_scaled_to_joint( + &mut self, + _oracle: &'static str, + _joint: &mut [Fr], + _num_vars: usize, + _limit: usize, + _scalar: Fr, + ) -> bool { + false + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum CommitmentPhaseError { + MissingOracle { oracle: &'static str }, + MissingTranscriptSource { source: &'static str }, + PlanCountMismatch { artifact: &'static str, expected: usize, actual: usize }, + OracleTooLarge { oracle: &'static str, len: usize, target_len: usize }, + TargetSizeOverflow { num_vars: usize }, +} + +pub struct CommitmentOracleInputs<'a> { + pub rd_inc: &'a [i128], + pub ram_inc: &'a [i128], + pub instruction_keys: &'a [Option], + pub ram_addresses: &'a [Option], + pub bytecode_indices: &'a [Option], + pub untrusted_advice: Option<&'a [Fr]>, + pub trusted_advice: Option<&'a [Fr]>, +} + +impl<'a> CommitmentOracleInputs<'a> { + pub fn from_trace_sources( + sources: &'a CommitmentTraceSources, + untrusted_advice: Option<&'a [Fr]>, + trusted_advice: Option<&'a [Fr]>, + ) -> Self { + Self { + rd_inc: &sources.rd_inc, + ram_inc: &sources.ram_inc, + instruction_keys: &sources.instruction_keys, + ram_addresses: &sources.ram_addresses, + bytecode_indices: &sources.bytecode_indices, + untrusted_advice, + trusted_advice, + } + } +} + + +struct AddressMajorOneHotPolynomial { + trace_len: usize, + chunk_domain: usize, + indices: Vec>, + num_vars: usize, +} + +impl AddressMajorOneHotPolynomial { + fn new( + trace_len: usize, + chunk_domain: usize, + indices: Vec>, + num_vars: usize, + ) -> Result { + let active_len = trace_len + .checked_mul(chunk_domain) + .ok_or(CommitmentPhaseError::TargetSizeOverflow { num_vars })?; + let target_len = target_len(num_vars)?; + if active_len > target_len { + return Err(CommitmentPhaseError::OracleTooLarge { + oracle: "one_hot", + len: active_len, + target_len, + }); + } + Ok(Self { + trace_len, + chunk_domain, + indices, + num_vars, + }) + } + + fn nonzero_flat_indices(&self) -> impl Iterator + '_ { + self.indices + .iter() + .enumerate() + .filter_map(|(cycle, &index)| { + index.map(|index| { + let index = index as usize; + assert!( + index < self.chunk_domain, + "one-hot index {index} exceeds domain {}", + self.chunk_domain + ); + index * self.trace_len + cycle + }) + }) + } +} + +impl MultilinearPoly for AddressMajorOneHotPolynomial { + fn num_vars(&self) -> usize { + self.num_vars + } + + fn evaluate(&self, point: &[Fr]) -> Fr { + assert_eq!(point.len(), self.num_vars); + let eq_evals = EqPolynomial::new(point.to_vec()).evaluations(); + self.nonzero_flat_indices() + .fold(Fr::from_u64(0), |acc, flat| acc + eq_evals[flat]) + } + + fn for_each_row(&self, sigma: usize, f: &mut dyn FnMut(usize, &[Fr])) { + let num_cols = 1usize << sigma; + let num_rows = 1usize << (self.num_vars - sigma); + let mut entries = Vec::with_capacity(self.indices.len()); + for flat in self.nonzero_flat_indices() { + entries.push((flat / num_cols, flat % num_cols)); + } + entries.sort_unstable_by_key(|(row, _)| *row); + + let mut cursor = 0; + let mut row = vec![Fr::from_u64(0); num_cols]; + for row_index in 0..num_rows { + row.fill(Fr::from_u64(0)); + while cursor < entries.len() && entries[cursor].0 == row_index { + row[entries[cursor].1] = Fr::from_u64(1); + cursor += 1; + } + f(row_index, &row); + } + } + + fn fold_rows(&self, left: &[Fr], sigma: usize) -> Vec { + let num_cols = 1usize << sigma; + let num_rows = 1usize << (self.num_vars - sigma); + assert_eq!(left.len(), num_rows); + let mut result = vec![Fr::from_u64(0); num_cols]; + for flat in self.nonzero_flat_indices() { + result[flat % num_cols] += left[flat / num_cols]; + } + result + } + + fn is_sparse(&self) -> bool { + true + } + + fn for_each_nonzero(&self, f: &mut dyn FnMut(usize, Fr)) { + for flat in self.nonzero_flat_indices() { + f(flat, Fr::from_u64(1)); + } + } +} + +pub struct SparseCommitmentInputs<'a> { + pub inputs: CommitmentOracleInputs<'a>, + cache: std::collections::BTreeMap<(&'static str, usize), Option>>, + chunk_counts: OneHotChunkCounts, +} + +impl<'a> SparseCommitmentInputs<'a> { + pub fn new(inputs: CommitmentOracleInputs<'a>) -> Self { + Self { + inputs, + cache: std::collections::BTreeMap::new(), + chunk_counts: OneHotChunkCounts::default(), + } + } + + fn update_chunk_counts(&mut self, program: &CommitmentProverProgramPlan) { + let mut counts = OneHotChunkCounts::default(); + let mut instruction = 0; + let mut ram = 0; + let mut bytecode = 0; + for plan in program.oracle_plans { + if plan.oracle.strip_prefix("InstructionRa_").is_some() { + instruction += 1; + } else if plan.oracle.strip_prefix("RamRa_").is_some() { + ram += 1; + } else if plan.oracle.strip_prefix("BytecodeRa_").is_some() { + bytecode += 1; + } + } + if instruction > 0 { + counts.instruction = instruction; + } + if ram > 0 { + counts.ram = ram; + } + if bytecode > 0 { + counts.bytecode = bytecode; + } + self.chunk_counts = counts; + } + + fn one_hot_spec(&self, oracle: &'static str) -> Option { + let (prefix, num_chunks, values, padding) = + if let Some(suffix) = oracle.strip_prefix("InstructionRa_") { + ( + suffix, + self.chunk_counts.instruction, + OneHotSource::InstructionKeys, + Some(0), + ) + } else if let Some(suffix) = oracle.strip_prefix("RamRa_") { + ( + suffix, + self.chunk_counts.ram, + OneHotSource::RamAddresses, + None, + ) + } else if let Some(suffix) = oracle.strip_prefix("BytecodeRa_") { + ( + suffix, + self.chunk_counts.bytecode, + OneHotSource::BytecodeIndices, + Some(0), + ) + } else { + return None; + }; + let chunk = prefix.parse::().ok()?; + if chunk >= num_chunks { + return None; + } + Some(OneHotSpec { + source: values, + chunk, + num_chunks, + chunk_bits: 4, + padding, + }) + } + + fn source_values(&self, source: OneHotSource) -> &'a [Option] { + match source { + OneHotSource::InstructionKeys => self.inputs.instruction_keys, + OneHotSource::RamAddresses => self.inputs.ram_addresses, + OneHotSource::BytecodeIndices => self.inputs.bytecode_indices, + } + } + + fn one_hot_indices( + &self, + oracle: &'static str, + trace_len: usize, + ) -> Option>> { + let spec = self.one_hot_spec(oracle)?; + let values = self.source_values(spec.source); + Some(one_hot_chunk_indices( + values, + spec.chunk, + spec.num_chunks, + spec.chunk_bits, + trace_len, + spec.padding, + )) + } + + #[expect( + clippy::option_option, + reason = "distinguishes missing oracle from present optional oracle" + )] + fn materialize_oracle( + &self, + oracle: &'static str, + num_vars: usize, + ) -> Option>> { + let materialized = match oracle { + "RdInc" => Some(dense_i128_column_to_field( + self.inputs.rd_inc, + target_len(num_vars).ok()?, + )), + "RamInc" => Some(dense_i128_column_to_field( + self.inputs.ram_inc, + target_len(num_vars).ok()?, + )), + "UntrustedAdvice" => optional_field_oracle( + self.inputs.untrusted_advice, + target_len(num_vars).ok()?, + ), + "TrustedAdvice" => { + optional_field_oracle(self.inputs.trusted_advice, target_len(num_vars).ok()?) + } + _ => { + let spec = self.one_hot_spec(oracle)?; + let trace_len = target_len(num_vars.checked_sub(spec.chunk_bits)?).ok()?; + let values = self.source_values(spec.source); + Some(one_hot_chunk_address_major( + values, + spec.chunk, + spec.num_chunks, + spec.chunk_bits, + trace_len, + spec.padding, + )) + } + }; + Some(materialized) + } + + fn commit_oracle( + &self, + program: &CommitmentProverProgramPlan, + oracle: &'static str, + layout_num_vars: usize, + prover_setup: &DoryProverSetup, + ) -> Result<(DoryCommitment, DoryHint), CommitmentPhaseError> { + let oracle_num_vars = oracle_num_vars(program, oracle, layout_num_vars); + if let Some(spec) = self.one_hot_spec(oracle) { + let trace_len = target_len(oracle_num_vars - spec.chunk_bits)?; + let chunk_domain = target_len(spec.chunk_bits)?; + let indices = self + .one_hot_indices(oracle, trace_len) + .ok_or(CommitmentPhaseError::MissingOracle { oracle })?; + let poly = AddressMajorOneHotPolynomial::new( + trace_len, + chunk_domain, + indices, + layout_num_vars, + )?; + let _dory_commit_span = tracing::info_span!("bolt.commitment.dory_commit").entered(); + Ok(DoryScheme::commit(&poly, prover_setup)) + } else { + let data = self + .materialize_oracle(oracle, oracle_num_vars) + .flatten() + .ok_or(CommitmentPhaseError::MissingOracle { oracle })?; + let data = into_padded_oracle(oracle, oracle_num_vars, Cow::Owned(data))?; + commit_with_layout(&data, layout_num_vars, prover_setup) + } + } +} + +impl CommitmentInputProvider for SparseCommitmentInputs<'_> { + fn materialize(&mut self, oracle: &'static str) -> Option> { + let num_vars = match oracle { + "RdInc" | "RamInc" | "UntrustedAdvice" | "TrustedAdvice" => 16, + _ if self.one_hot_spec(oracle).is_some() => 20, + _ => return None, + }; + self.materialize_with_num_vars(oracle, num_vars) + } + + fn materialize_with_num_vars( + &mut self, + oracle: &'static str, + num_vars: usize, + ) -> Option> { + if !self.cache.contains_key(&(oracle, num_vars)) { + let materialized = self.materialize_oracle(oracle, num_vars).flatten(); + let _ = self.cache.insert((oracle, num_vars), materialized); + } + self.cache + .get(&(oracle, num_vars)) + .and_then(|values| values.as_ref()) + .map(|values| Cow::Borrowed(values.as_slice())) + } + + fn commit_batch( + &mut self, + program: &CommitmentProverProgramPlan, + plan: &CommitmentBatchPlan, + prover_setup: &DoryProverSetup, + ) -> Option, CommitmentPhaseError>> { + self.update_chunk_counts(program); + Some( + plan.oracles + .par_iter() + .map(|&oracle| { + let oracle_num_vars = oracle_num_vars(program, oracle, plan.num_vars); + let (commitment, hint) = + self.commit_oracle(program, oracle, plan.num_vars, prover_setup)?; + Ok(CommittedOracle { + commitment: Some(commitment), + record: CommitmentRecord { + artifact: plan.artifact, + oracle, + label: plan.label, + num_vars: oracle_num_vars, + }, + hint: Some(OracleOpeningHint { oracle, hint }), + }) + }) + .collect(), + ) + } + + fn add_scaled_to_joint( + &mut self, + oracle: &'static str, + joint: &mut [Fr], + num_vars: usize, + limit: usize, + scalar: Fr, + ) -> bool { + let dense = match oracle { + "RdInc" => Some(self.inputs.rd_inc), + "RamInc" => Some(self.inputs.ram_inc), + _ => None, + }; + if let Some(values) = dense { + let Ok(target_len) = target_len(num_vars) else { + return false; + }; + let len = limit.min(joint.len()).min(values.len()).min(target_len); + for (dst, &value) in joint.iter_mut().take(len).zip(values.iter()) { + if value != 0 { + *dst += Fr::from_i128(value) * scalar; + } + } + return true; + } + + let Some(spec) = self.one_hot_spec(oracle) else { + return false; + }; + let Some(trace_num_vars) = num_vars.checked_sub(spec.chunk_bits) else { + return false; + }; + let Ok(trace_len) = target_len(trace_num_vars) else { + return false; + }; + let Ok(chunk_domain) = target_len(spec.chunk_bits) else { + return false; + }; + let Some(active_len) = trace_len.checked_mul(chunk_domain) else { + return false; + }; + let max_flat = limit.min(joint.len()).min(active_len); + let Some(indices) = self.one_hot_indices(oracle, trace_len) else { + return false; + }; + for (cycle, index) in indices.into_iter().enumerate() { + let Some(index) = index else { + continue; + }; + let flat = index as usize * trace_len + cycle; + if flat < max_flat { + joint[flat] += scalar; + } + } + true + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +enum OneHotSource { + InstructionKeys, + RamAddresses, + BytecodeIndices, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +struct OneHotSpec { + source: OneHotSource, + chunk: usize, + num_chunks: usize, + chunk_bits: usize, + padding: Option, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +struct OneHotChunkCounts { + instruction: usize, + ram: usize, + bytecode: usize, +} + +impl Default for OneHotChunkCounts { + fn default() -> Self { + Self { + instruction: 32, + ram: 4, + bytecode: 3, + } + } +} + +#[derive(Clone, Debug, Default)] +pub struct CommitmentOracles { + pub rd_inc: Vec, + pub ram_inc: Vec, + pub instruction_ra_0: Vec, + pub instruction_ra_1: Vec, + pub instruction_ra_2: Vec, + pub instruction_ra_3: Vec, + pub instruction_ra_4: Vec, + pub instruction_ra_5: Vec, + pub instruction_ra_6: Vec, + pub instruction_ra_7: Vec, + pub instruction_ra_8: Vec, + pub instruction_ra_9: Vec, + pub instruction_ra_10: Vec, + pub instruction_ra_11: Vec, + pub instruction_ra_12: Vec, + pub instruction_ra_13: Vec, + pub instruction_ra_14: Vec, + pub instruction_ra_15: Vec, + pub instruction_ra_16: Vec, + pub instruction_ra_17: Vec, + pub instruction_ra_18: Vec, + pub instruction_ra_19: Vec, + pub instruction_ra_20: Vec, + pub instruction_ra_21: Vec, + pub instruction_ra_22: Vec, + pub instruction_ra_23: Vec, + pub instruction_ra_24: Vec, + pub instruction_ra_25: Vec, + pub instruction_ra_26: Vec, + pub instruction_ra_27: Vec, + pub instruction_ra_28: Vec, + pub instruction_ra_29: Vec, + pub instruction_ra_30: Vec, + pub instruction_ra_31: Vec, + pub ram_ra_0: Vec, + pub ram_ra_1: Vec, + pub ram_ra_2: Vec, + pub ram_ra_3: Vec, + pub bytecode_ra_0: Vec, + pub bytecode_ra_1: Vec, + pub bytecode_ra_2: Vec, + pub untrusted_advice: Option>, + pub trusted_advice: Option>, +} + +impl CommitmentInputProvider for CommitmentOracles { + fn materialize(&mut self, oracle: &'static str) -> Option> { + match oracle { + "RdInc" => Some(Cow::Borrowed(&self.rd_inc)), + "RamInc" => Some(Cow::Borrowed(&self.ram_inc)), + "InstructionRa_0" => Some(Cow::Borrowed(&self.instruction_ra_0)), + "InstructionRa_1" => Some(Cow::Borrowed(&self.instruction_ra_1)), + "InstructionRa_2" => Some(Cow::Borrowed(&self.instruction_ra_2)), + "InstructionRa_3" => Some(Cow::Borrowed(&self.instruction_ra_3)), + "InstructionRa_4" => Some(Cow::Borrowed(&self.instruction_ra_4)), + "InstructionRa_5" => Some(Cow::Borrowed(&self.instruction_ra_5)), + "InstructionRa_6" => Some(Cow::Borrowed(&self.instruction_ra_6)), + "InstructionRa_7" => Some(Cow::Borrowed(&self.instruction_ra_7)), + "InstructionRa_8" => Some(Cow::Borrowed(&self.instruction_ra_8)), + "InstructionRa_9" => Some(Cow::Borrowed(&self.instruction_ra_9)), + "InstructionRa_10" => Some(Cow::Borrowed(&self.instruction_ra_10)), + "InstructionRa_11" => Some(Cow::Borrowed(&self.instruction_ra_11)), + "InstructionRa_12" => Some(Cow::Borrowed(&self.instruction_ra_12)), + "InstructionRa_13" => Some(Cow::Borrowed(&self.instruction_ra_13)), + "InstructionRa_14" => Some(Cow::Borrowed(&self.instruction_ra_14)), + "InstructionRa_15" => Some(Cow::Borrowed(&self.instruction_ra_15)), + "InstructionRa_16" => Some(Cow::Borrowed(&self.instruction_ra_16)), + "InstructionRa_17" => Some(Cow::Borrowed(&self.instruction_ra_17)), + "InstructionRa_18" => Some(Cow::Borrowed(&self.instruction_ra_18)), + "InstructionRa_19" => Some(Cow::Borrowed(&self.instruction_ra_19)), + "InstructionRa_20" => Some(Cow::Borrowed(&self.instruction_ra_20)), + "InstructionRa_21" => Some(Cow::Borrowed(&self.instruction_ra_21)), + "InstructionRa_22" => Some(Cow::Borrowed(&self.instruction_ra_22)), + "InstructionRa_23" => Some(Cow::Borrowed(&self.instruction_ra_23)), + "InstructionRa_24" => Some(Cow::Borrowed(&self.instruction_ra_24)), + "InstructionRa_25" => Some(Cow::Borrowed(&self.instruction_ra_25)), + "InstructionRa_26" => Some(Cow::Borrowed(&self.instruction_ra_26)), + "InstructionRa_27" => Some(Cow::Borrowed(&self.instruction_ra_27)), + "InstructionRa_28" => Some(Cow::Borrowed(&self.instruction_ra_28)), + "InstructionRa_29" => Some(Cow::Borrowed(&self.instruction_ra_29)), + "InstructionRa_30" => Some(Cow::Borrowed(&self.instruction_ra_30)), + "InstructionRa_31" => Some(Cow::Borrowed(&self.instruction_ra_31)), + "RamRa_0" => Some(Cow::Borrowed(&self.ram_ra_0)), + "RamRa_1" => Some(Cow::Borrowed(&self.ram_ra_1)), + "RamRa_2" => Some(Cow::Borrowed(&self.ram_ra_2)), + "RamRa_3" => Some(Cow::Borrowed(&self.ram_ra_3)), + "BytecodeRa_0" => Some(Cow::Borrowed(&self.bytecode_ra_0)), + "BytecodeRa_1" => Some(Cow::Borrowed(&self.bytecode_ra_1)), + "BytecodeRa_2" => Some(Cow::Borrowed(&self.bytecode_ra_2)), + "UntrustedAdvice" => self.untrusted_advice.as_deref().map(Cow::Borrowed), + "TrustedAdvice" => self.trusted_advice.as_deref().map(Cow::Borrowed), + _ => None, + } + } +} + +pub fn build_commitment_oracles( + inputs: &CommitmentOracleInputs<'_>, +) -> Result { + Ok(CommitmentOracles { + rd_inc: dense_i128_column_to_field(inputs.rd_inc, target_len(16)?), + ram_inc: dense_i128_column_to_field(inputs.ram_inc, target_len(16)?), + instruction_ra_0: one_hot_chunk_address_major(inputs.instruction_keys, 0, 32, 4, target_len(16)?, Some(0)), + instruction_ra_1: one_hot_chunk_address_major(inputs.instruction_keys, 1, 32, 4, target_len(16)?, Some(0)), + instruction_ra_2: one_hot_chunk_address_major(inputs.instruction_keys, 2, 32, 4, target_len(16)?, Some(0)), + instruction_ra_3: one_hot_chunk_address_major(inputs.instruction_keys, 3, 32, 4, target_len(16)?, Some(0)), + instruction_ra_4: one_hot_chunk_address_major(inputs.instruction_keys, 4, 32, 4, target_len(16)?, Some(0)), + instruction_ra_5: one_hot_chunk_address_major(inputs.instruction_keys, 5, 32, 4, target_len(16)?, Some(0)), + instruction_ra_6: one_hot_chunk_address_major(inputs.instruction_keys, 6, 32, 4, target_len(16)?, Some(0)), + instruction_ra_7: one_hot_chunk_address_major(inputs.instruction_keys, 7, 32, 4, target_len(16)?, Some(0)), + instruction_ra_8: one_hot_chunk_address_major(inputs.instruction_keys, 8, 32, 4, target_len(16)?, Some(0)), + instruction_ra_9: one_hot_chunk_address_major(inputs.instruction_keys, 9, 32, 4, target_len(16)?, Some(0)), + instruction_ra_10: one_hot_chunk_address_major(inputs.instruction_keys, 10, 32, 4, target_len(16)?, Some(0)), + instruction_ra_11: one_hot_chunk_address_major(inputs.instruction_keys, 11, 32, 4, target_len(16)?, Some(0)), + instruction_ra_12: one_hot_chunk_address_major(inputs.instruction_keys, 12, 32, 4, target_len(16)?, Some(0)), + instruction_ra_13: one_hot_chunk_address_major(inputs.instruction_keys, 13, 32, 4, target_len(16)?, Some(0)), + instruction_ra_14: one_hot_chunk_address_major(inputs.instruction_keys, 14, 32, 4, target_len(16)?, Some(0)), + instruction_ra_15: one_hot_chunk_address_major(inputs.instruction_keys, 15, 32, 4, target_len(16)?, Some(0)), + instruction_ra_16: one_hot_chunk_address_major(inputs.instruction_keys, 16, 32, 4, target_len(16)?, Some(0)), + instruction_ra_17: one_hot_chunk_address_major(inputs.instruction_keys, 17, 32, 4, target_len(16)?, Some(0)), + instruction_ra_18: one_hot_chunk_address_major(inputs.instruction_keys, 18, 32, 4, target_len(16)?, Some(0)), + instruction_ra_19: one_hot_chunk_address_major(inputs.instruction_keys, 19, 32, 4, target_len(16)?, Some(0)), + instruction_ra_20: one_hot_chunk_address_major(inputs.instruction_keys, 20, 32, 4, target_len(16)?, Some(0)), + instruction_ra_21: one_hot_chunk_address_major(inputs.instruction_keys, 21, 32, 4, target_len(16)?, Some(0)), + instruction_ra_22: one_hot_chunk_address_major(inputs.instruction_keys, 22, 32, 4, target_len(16)?, Some(0)), + instruction_ra_23: one_hot_chunk_address_major(inputs.instruction_keys, 23, 32, 4, target_len(16)?, Some(0)), + instruction_ra_24: one_hot_chunk_address_major(inputs.instruction_keys, 24, 32, 4, target_len(16)?, Some(0)), + instruction_ra_25: one_hot_chunk_address_major(inputs.instruction_keys, 25, 32, 4, target_len(16)?, Some(0)), + instruction_ra_26: one_hot_chunk_address_major(inputs.instruction_keys, 26, 32, 4, target_len(16)?, Some(0)), + instruction_ra_27: one_hot_chunk_address_major(inputs.instruction_keys, 27, 32, 4, target_len(16)?, Some(0)), + instruction_ra_28: one_hot_chunk_address_major(inputs.instruction_keys, 28, 32, 4, target_len(16)?, Some(0)), + instruction_ra_29: one_hot_chunk_address_major(inputs.instruction_keys, 29, 32, 4, target_len(16)?, Some(0)), + instruction_ra_30: one_hot_chunk_address_major(inputs.instruction_keys, 30, 32, 4, target_len(16)?, Some(0)), + instruction_ra_31: one_hot_chunk_address_major(inputs.instruction_keys, 31, 32, 4, target_len(16)?, Some(0)), + ram_ra_0: one_hot_chunk_address_major(inputs.ram_addresses, 0, 4, 4, target_len(16)?, None), + ram_ra_1: one_hot_chunk_address_major(inputs.ram_addresses, 1, 4, 4, target_len(16)?, None), + ram_ra_2: one_hot_chunk_address_major(inputs.ram_addresses, 2, 4, 4, target_len(16)?, None), + ram_ra_3: one_hot_chunk_address_major(inputs.ram_addresses, 3, 4, 4, target_len(16)?, None), + bytecode_ra_0: one_hot_chunk_address_major(inputs.bytecode_indices, 0, 3, 4, target_len(16)?, Some(0)), + bytecode_ra_1: one_hot_chunk_address_major(inputs.bytecode_indices, 1, 3, 4, target_len(16)?, Some(0)), + bytecode_ra_2: one_hot_chunk_address_major(inputs.bytecode_indices, 2, 3, 4, target_len(16)?, Some(0)), + untrusted_advice: optional_field_oracle(inputs.untrusted_advice, target_len(16)?), + trusted_advice: optional_field_oracle(inputs.trusted_advice, target_len(16)?), + }) +} + +pub const COMMITMENT_PARAMS: CommitmentParams = CommitmentParams { + field: "bn254_fr", + pcs: "dory", + transcript: "blake2b_transcript", +}; +pub const ORACLE_PLANS: &[OraclePlan] = &[ + OraclePlan { oracle: "RdInc", domain: "jolt.trace_domain", num_vars: 16 }, + OraclePlan { oracle: "RamInc", domain: "jolt.trace_domain", num_vars: 16 }, + OraclePlan { oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "UntrustedAdvice", domain: "jolt.trace_domain", num_vars: 16 }, + OraclePlan { oracle: "TrustedAdvice", domain: "jolt.trace_domain", num_vars: 16 }, +]; +pub const COMMITMENT_BATCH_0_ORACLES: &[&str] = &[ + "RdInc", + "RamInc", + "InstructionRa_0", + "InstructionRa_1", + "InstructionRa_2", + "InstructionRa_3", + "InstructionRa_4", + "InstructionRa_5", + "InstructionRa_6", + "InstructionRa_7", + "InstructionRa_8", + "InstructionRa_9", + "InstructionRa_10", + "InstructionRa_11", + "InstructionRa_12", + "InstructionRa_13", + "InstructionRa_14", + "InstructionRa_15", + "InstructionRa_16", + "InstructionRa_17", + "InstructionRa_18", + "InstructionRa_19", + "InstructionRa_20", + "InstructionRa_21", + "InstructionRa_22", + "InstructionRa_23", + "InstructionRa_24", + "InstructionRa_25", + "InstructionRa_26", + "InstructionRa_27", + "InstructionRa_28", + "InstructionRa_29", + "InstructionRa_30", + "InstructionRa_31", + "RamRa_0", + "RamRa_1", + "RamRa_2", + "RamRa_3", + "BytecodeRa_0", + "BytecodeRa_1", + "BytecodeRa_2", +]; +pub const COMMITMENT_BATCH_PLANS: &[CommitmentBatchPlan] = &[ + CommitmentBatchPlan { artifact: "jolt.main_witness_commitments", pcs: "dory", oracle_family: "jolt.main_witness_polys", label: "commitment", oracles: COMMITMENT_BATCH_0_ORACLES, count: 41, domain: "jolt.main_witness_commit_domain", num_vars: 20 }, +]; +pub const OPTIONAL_COMMITMENT_PLANS: &[OptionalCommitmentPlan] = &[ + OptionalCommitmentPlan { artifact: "jolt.untrusted_advice_commitment", pcs: "dory", oracle: "UntrustedAdvice", label: "untrusted_advice", domain: "jolt.trace_domain", num_vars: 16, skip_policy: OptionalSkipPolicy::MissingOrZero }, + OptionalCommitmentPlan { artifact: "jolt.trusted_advice_commitment", pcs: "dory", oracle: "TrustedAdvice", label: "trusted_advice", domain: "jolt.trace_domain", num_vars: 16, skip_policy: OptionalSkipPolicy::MissingOrZero }, +]; +pub const TRANSCRIPT_PLAN: &[TranscriptStep] = &[ + TranscriptStep { label: "commitment", source: "jolt.main_witness_commitments", optional: false }, + TranscriptStep { label: "untrusted_advice", source: "jolt.untrusted_advice_commitment", optional: true }, + TranscriptStep { label: "trusted_advice", source: "jolt.trusted_advice_commitment", optional: true }, +]; +pub const COMMITMENT_PROGRAM: CommitmentProverProgramPlan = CommitmentProverProgramPlan { + params: COMMITMENT_PARAMS, + oracle_plans: ORACLE_PLANS, + batch_plans: COMMITMENT_BATCH_PLANS, + optional_plans: OPTIONAL_COMMITMENT_PLANS, + transcript_steps: TRANSCRIPT_PLAN, +}; + +pub fn prove_commitment_phase( + inputs: &mut I, + prover_setup: &DoryProverSetup, + transcript: &mut T, +) -> Result +where + I: CommitmentInputProvider, + T: Transcript, +{ + prove_commitment_phase_with_program(&COMMITMENT_PROGRAM, inputs, prover_setup, transcript) +} + +pub fn prove_commitment_phase_with_program( + program: &'static CommitmentProverProgramPlan, + inputs: &mut I, + prover_setup: &DoryProverSetup, + transcript: &mut T, +) -> Result +where + I: CommitmentInputProvider, + T: Transcript, +{ + let mut artifacts = CommitmentArtifacts::default(); + for plan in program.batch_plans { + let _batch_span = tracing::info_span!("bolt.commitment.batch").entered(); + commit_batch(program, inputs, prover_setup, &mut artifacts, plan)?; + } + for plan in program.optional_plans { + let _optional_span = tracing::info_span!("bolt.commitment.optional").entered(); + commit_optional(program, inputs, prover_setup, &mut artifacts, plan)?; + } + absorb_transcript(program, &artifacts, transcript)?; + Ok(artifacts) +} + +fn commit_batch( + program: &CommitmentProverProgramPlan, + inputs: &mut I, + prover_setup: &DoryProverSetup, + artifacts: &mut CommitmentArtifacts, + plan: &CommitmentBatchPlan, +) -> Result<(), CommitmentPhaseError> +where + I: CommitmentInputProvider, +{ + if plan.count != plan.oracles.len() { + return Err(CommitmentPhaseError::PlanCountMismatch { + artifact: plan.artifact, + expected: plan.count, + actual: plan.oracles.len(), + }); + } + if let Some(committed) = inputs.commit_batch(program, plan, prover_setup) { + for committed in committed? { + artifacts.records.push(committed.record); + artifacts.commitments.push(committed.commitment); + if let Some(hint) = committed.hint { + artifacts.hints.push(hint); + } + } + return Ok(()); + } + for &oracle in plan.oracles { + let data = inputs + .materialize_with_num_vars(oracle, oracle_num_vars(program, oracle, plan.num_vars)) + .ok_or(CommitmentPhaseError::MissingOracle { oracle })?; + let oracle_num_vars = oracle_num_vars(program, oracle, plan.num_vars); + let data = into_padded_oracle(oracle, oracle_num_vars, data)?; + let (commitment, hint) = commit_with_layout(&data, plan.num_vars, prover_setup)?; + artifacts.records.push(CommitmentRecord { + artifact: plan.artifact, + oracle, + label: plan.label, + num_vars: oracle_num_vars, + }); + artifacts.commitments.push(Some(commitment)); + artifacts.hints.push(OracleOpeningHint { oracle, hint }); + } + Ok(()) +} + +fn commit_optional( + program: &CommitmentProverProgramPlan, + inputs: &mut I, + prover_setup: &DoryProverSetup, + artifacts: &mut CommitmentArtifacts, + plan: &OptionalCommitmentPlan, +) -> Result<(), CommitmentPhaseError> +where + I: CommitmentInputProvider, +{ + let Some(data) = inputs.materialize_with_num_vars(plan.oracle, plan.num_vars) else { + return push_skipped_optional(program, artifacts, plan); + }; + if should_skip_optional(plan.skip_policy, data.as_ref()) { + return push_skipped_optional(program, artifacts, plan); + } + let data = into_padded_oracle(plan.oracle, plan.num_vars, data)?; + let (commitment, hint) = commit_with_layout(&data, plan.num_vars, prover_setup)?; + artifacts.records.push(CommitmentRecord { + artifact: plan.artifact, + oracle: plan.oracle, + label: plan.label, + num_vars: oracle_num_vars(program, plan.oracle, plan.num_vars), + }); + artifacts.commitments.push(Some(commitment)); + artifacts.hints.push(OracleOpeningHint { + oracle: plan.oracle, + hint, + }); + Ok(()) +} + +fn push_skipped_optional( + program: &CommitmentProverProgramPlan, + artifacts: &mut CommitmentArtifacts, + plan: &OptionalCommitmentPlan, +) -> Result<(), CommitmentPhaseError> { + artifacts.records.push(CommitmentRecord { + artifact: plan.artifact, + oracle: plan.oracle, + label: plan.label, + num_vars: oracle_num_vars(program, plan.oracle, plan.num_vars), + }); + artifacts.commitments.push(None); + Ok(()) +} + +fn should_skip_optional(policy: OptionalSkipPolicy, data: &[Fr]) -> bool { + match policy { + OptionalSkipPolicy::MissingOrZero => data.iter().all(|value| *value == Fr::from_u64(0)), + } +} + +fn into_padded_oracle( + oracle: &'static str, + num_vars: usize, + data: Cow<'_, [Fr]>, +) -> Result, CommitmentPhaseError> { + let target_len = target_len(num_vars)?; + if data.len() > target_len { + return Err(CommitmentPhaseError::OracleTooLarge { + oracle, + len: data.len(), + target_len, + }); + } + let mut data = data.into_owned(); + data.resize(target_len, Fr::from_u64(0)); + Ok(data) +} + +fn oracle_num_vars( + program: &CommitmentProverProgramPlan, + oracle: &'static str, + fallback: usize, +) -> usize { + program + .oracle_plans + .iter() + .find(|plan| plan.oracle == oracle) + .map_or(fallback, |plan| plan.num_vars) +} + +fn commit_with_layout( + data: &[Fr], + layout_num_vars: usize, + prover_setup: &DoryProverSetup, +) -> Result<(DoryCommitment, DoryHint), CommitmentPhaseError> { + let row_len = target_len(layout_num_vars.div_ceil(2))?; + let _dory_commit_span = tracing::info_span!("bolt.commitment.dory_commit").entered(); + Ok(DoryScheme::commit_evaluations_with_row_len( + data, + row_len, + prover_setup, + )) +} + +fn target_len(num_vars: usize) -> Result { + if num_vars >= usize::BITS as usize { + return Err(CommitmentPhaseError::TargetSizeOverflow { num_vars }); + } + Ok(1usize << num_vars) +} + +fn absorb_transcript( + program: &CommitmentProverProgramPlan, + artifacts: &CommitmentArtifacts, + transcript: &mut T, +) -> Result<(), CommitmentPhaseError> +where + T: Transcript, +{ + for step in program.transcript_steps { + let mut appended = false; + for (record, commitment) in artifacts.records.iter().zip(&artifacts.commitments) { + if record.artifact != step.source { + continue; + } + if let Some(commitment) = commitment { + transcript.append(&LabelWithCount(step.label.as_bytes(), commitment.serialized_len())); + commitment.append_to_transcript(transcript); + appended = true; + } + } + if !step.optional && !appended { + return Err(CommitmentPhaseError::MissingTranscriptSource { + source: step.source, + }); + } + } + Ok(()) +} diff --git a/crates/jolt-prover/src/stages/mod.rs b/crates/jolt-prover/src/stages/mod.rs new file mode 100644 index 0000000000..c8242a4f47 --- /dev/null +++ b/crates/jolt-prover/src/stages/mod.rs @@ -0,0 +1,18 @@ +#[rustfmt::skip] +pub mod commitment; +#[rustfmt::skip] +pub mod stage1_outer; +#[rustfmt::skip] +pub mod stage2; +#[rustfmt::skip] +pub mod stage3; +#[rustfmt::skip] +pub mod stage4; +#[rustfmt::skip] +pub mod stage5; +#[rustfmt::skip] +pub mod stage6; +#[rustfmt::skip] +pub mod stage7; +#[rustfmt::skip] +pub mod stage8; diff --git a/crates/jolt-prover/src/stages/stage1_outer.rs b/crates/jolt-prover/src/stages/stage1_outer.rs new file mode 100644 index 0000000000..e31d49a81e --- /dev/null +++ b/crates/jolt-prover/src/stages/stage1_outer.rs @@ -0,0 +1,264 @@ +#![allow(dead_code)] + +use jolt_field::Fr; +use jolt_kernels::stage1::{execute_stage1_program, Stage1CpuProgramPlan, Stage1ExecutionArtifacts, Stage1ExecutionMode, Stage1KernelError, Stage1KernelExecutor, Stage1KernelPlan, Stage1OpeningBatchPlan, Stage1OpeningClaimPlan, Stage1Params, Stage1SumcheckBatchPlan, Stage1SumcheckClaimPlan, Stage1SumcheckDriverPlan, Stage1SumcheckEvalPlan, Stage1SumcheckInstanceResultPlan, Stage1TranscriptSqueezePlan}; +use jolt_transcript::{Blake2bTranscript, Transcript}; + +pub type DefaultStage1Transcript = Blake2bTranscript; + +pub const STAGE1_PARAMS: Stage1Params = Stage1Params { + field: "bn254_fr", + pcs: "dory", + transcript: "blake2b_transcript", +}; +pub const STAGE1_TRANSCRIPT_SQUEEZES: &[Stage1TranscriptSqueezePlan] = &[ + Stage1TranscriptSqueezePlan { symbol: "stage1.tau", label: "outer_tau", kind: "challenge_vector", count: 18 }, +]; + +pub const STAGE1_KERNELS: &[Stage1KernelPlan] = &[ + Stage1KernelPlan { symbol: "jolt.cpu.stage1.outer.uniskip", relation: "jolt.stage1.outer.uniskip", kind: "sumcheck", backend: "cpu", abi: "jolt_stage1_outer_uniskip" }, + Stage1KernelPlan { symbol: "jolt.cpu.stage1.outer.remaining", relation: "jolt.stage1.outer.remaining", kind: "sumcheck", backend: "cpu", abi: "jolt_stage1_outer_remaining" }, +]; + +pub const STAGE1_SUMCHECK_CLAIM_0_INPUT_OPENINGS: &[&str] = &[]; + +pub const STAGE1_SUMCHECK_CLAIM_1_INPUT_OPENINGS: &[&str] = &["stage1.uniskip.opening"]; + +pub const STAGE1_SUMCHECK_CLAIMS: &[Stage1SumcheckClaimPlan] = &[ + Stage1SumcheckClaimPlan { symbol: "stage1.uniskip.input", stage: "stage1", domain: "jolt.stage1_uniskip_domain", num_rounds: 1, degree: 27, claim: "stage1.zero", kernel: Some("jolt.cpu.stage1.outer.uniskip"), relation: None, claim_value: "stage1.zero", input_openings: STAGE1_SUMCHECK_CLAIM_0_INPUT_OPENINGS }, + Stage1SumcheckClaimPlan { symbol: "stage1.outer_remaining.input", stage: "stage1", domain: "jolt.trace_domain", num_rounds: 17, degree: 3, claim: "stage1.uniskip.eval", kernel: Some("jolt.cpu.stage1.outer.remaining"), relation: None, claim_value: "stage1.uniskip.eval", input_openings: STAGE1_SUMCHECK_CLAIM_1_INPUT_OPENINGS }, +]; +pub const STAGE1_SUMCHECK_BATCH_0_ORDERED_CLAIMS: &[&str] = &["stage1.uniskip.input"]; + +pub const STAGE1_SUMCHECK_BATCH_0_CLAIM_OPERANDS: &[&str] = &["stage1.uniskip.input"]; + +pub const STAGE1_SUMCHECK_BATCH_0_ROUND_SCHEDULE: &[usize] = &[ + 1, +]; + +pub const STAGE1_SUMCHECK_BATCH_1_ORDERED_CLAIMS: &[&str] = &["stage1.outer_remaining.input"]; + +pub const STAGE1_SUMCHECK_BATCH_1_CLAIM_OPERANDS: &[&str] = &["stage1.outer_remaining.input"]; + +pub const STAGE1_SUMCHECK_BATCH_1_ROUND_SCHEDULE: &[usize] = &[ + 17, +]; + +pub const STAGE1_SUMCHECK_BATCHES: &[Stage1SumcheckBatchPlan] = &[ + Stage1SumcheckBatchPlan { symbol: "stage1.uniskip.batch", stage: "stage1", proof_slot: "stage1.uni_skip_first_round", policy: "single_instance", count: 1, ordered_claims: STAGE1_SUMCHECK_BATCH_0_ORDERED_CLAIMS, claim_operands: STAGE1_SUMCHECK_BATCH_0_CLAIM_OPERANDS, claim_label: "uniskip_claim", round_label: "uniskip_poly", round_schedule: STAGE1_SUMCHECK_BATCH_0_ROUND_SCHEDULE }, + Stage1SumcheckBatchPlan { symbol: "stage1.outer_remaining.batch", stage: "stage1", proof_slot: "stage1.sumcheck", policy: "jolt_core_front_loaded", count: 1, ordered_claims: STAGE1_SUMCHECK_BATCH_1_ORDERED_CLAIMS, claim_operands: STAGE1_SUMCHECK_BATCH_1_CLAIM_OPERANDS, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", round_schedule: STAGE1_SUMCHECK_BATCH_1_ROUND_SCHEDULE }, +]; +pub const STAGE1_SUMCHECK_DRIVER_0_ROUND_SCHEDULE: &[usize] = &[ + 1, +]; + +pub const STAGE1_SUMCHECK_DRIVER_1_ROUND_SCHEDULE: &[usize] = &[ + 17, +]; + +pub const STAGE1_SUMCHECK_DRIVERS: &[Stage1SumcheckDriverPlan] = &[ + Stage1SumcheckDriverPlan { symbol: "stage1.uniskip.sumcheck", stage: "stage1", proof_slot: "stage1.uni_skip_first_round", kernel: Some("jolt.cpu.stage1.outer.uniskip"), relation: None, batch: "stage1.uniskip.batch", policy: "univariate_skip", round_schedule: STAGE1_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "uniskip_claim", round_label: "uniskip_poly", num_rounds: 1, degree: 27 }, + Stage1SumcheckDriverPlan { symbol: "stage1.outer_remaining.sumcheck", stage: "stage1", proof_slot: "stage1.sumcheck", kernel: Some("jolt.cpu.stage1.outer.remaining"), relation: None, batch: "stage1.outer_remaining.batch", policy: "jolt_core_front_loaded", round_schedule: STAGE1_SUMCHECK_DRIVER_1_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 17, degree: 3 }, +]; +pub const STAGE1_SUMCHECK_INSTANCE_RESULTS: &[Stage1SumcheckInstanceResultPlan] = &[ + Stage1SumcheckInstanceResultPlan { symbol: "stage1.uniskip.instance", source: "stage1.uniskip.sumcheck", claim: "stage1.uniskip.input", relation: "jolt.stage1.outer.uniskip", index: 0, point_arity: 1, num_rounds: 1, round_offset: 0, point_order: "as_is", degree: 27 }, + Stage1SumcheckInstanceResultPlan { symbol: "stage1.outer_remaining.instance", source: "stage1.outer_remaining.sumcheck", claim: "stage1.outer_remaining.input", relation: "jolt.stage1.outer.remaining", index: 0, point_arity: 16, num_rounds: 17, round_offset: 1, point_order: "reverse", degree: 3 }, +]; + +pub const STAGE1_SUMCHECK_EVALS: &[Stage1SumcheckEvalPlan] = &[ + Stage1SumcheckEvalPlan { symbol: "stage1.uniskip.eval", source: "stage1.uniskip.sumcheck", name: "stage1.uniskip.eval", index: 0, oracle: "UnivariateSkip" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.LeftInstructionInput", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.LeftInstructionInput", index: 0, oracle: "LeftInstructionInput" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.RightInstructionInput", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.RightInstructionInput", index: 1, oracle: "RightInstructionInput" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.Product", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.Product", index: 2, oracle: "Product" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.ShouldBranch", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.ShouldBranch", index: 3, oracle: "ShouldBranch" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.PC", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.PC", index: 4, oracle: "PC" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.UnexpandedPC", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.UnexpandedPC", index: 5, oracle: "UnexpandedPC" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.Imm", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.Imm", index: 6, oracle: "Imm" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.RamAddress", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.RamAddress", index: 7, oracle: "RamAddress" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.Rs1Value", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.Rs1Value", index: 8, oracle: "Rs1Value" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.Rs2Value", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.Rs2Value", index: 9, oracle: "Rs2Value" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.RdWriteValue", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.RdWriteValue", index: 10, oracle: "RdWriteValue" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.RamReadValue", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.RamReadValue", index: 11, oracle: "RamReadValue" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.RamWriteValue", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.RamWriteValue", index: 12, oracle: "RamWriteValue" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.LeftLookupOperand", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.LeftLookupOperand", index: 13, oracle: "LeftLookupOperand" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.RightLookupOperand", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.RightLookupOperand", index: 14, oracle: "RightLookupOperand" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.NextUnexpandedPC", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.NextUnexpandedPC", index: 15, oracle: "NextUnexpandedPC" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.NextPC", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.NextPC", index: 16, oracle: "NextPC" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.NextIsVirtual", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.NextIsVirtual", index: 17, oracle: "NextIsVirtual" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.NextIsFirstInSequence", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.NextIsFirstInSequence", index: 18, oracle: "NextIsFirstInSequence" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.LookupOutput", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.LookupOutput", index: 19, oracle: "LookupOutput" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.ShouldJump", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.ShouldJump", index: 20, oracle: "ShouldJump" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.OpFlagAddOperands", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.OpFlagAddOperands", index: 21, oracle: "OpFlagAddOperands" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.OpFlagSubtractOperands", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.OpFlagSubtractOperands", index: 22, oracle: "OpFlagSubtractOperands" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.OpFlagMultiplyOperands", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.OpFlagMultiplyOperands", index: 23, oracle: "OpFlagMultiplyOperands" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.OpFlagLoad", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.OpFlagLoad", index: 24, oracle: "OpFlagLoad" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.OpFlagStore", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.OpFlagStore", index: 25, oracle: "OpFlagStore" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.OpFlagJump", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.OpFlagJump", index: 26, oracle: "OpFlagJump" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.OpFlagWriteLookupOutputToRD", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.OpFlagWriteLookupOutputToRD", index: 27, oracle: "OpFlagWriteLookupOutputToRD" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.OpFlagVirtualInstruction", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.OpFlagVirtualInstruction", index: 28, oracle: "OpFlagVirtualInstruction" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.OpFlagAssert", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.OpFlagAssert", index: 29, oracle: "OpFlagAssert" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.OpFlagDoNotUpdateUnexpandedPC", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.OpFlagDoNotUpdateUnexpandedPC", index: 30, oracle: "OpFlagDoNotUpdateUnexpandedPC" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.OpFlagAdvice", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.OpFlagAdvice", index: 31, oracle: "OpFlagAdvice" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.OpFlagIsCompressed", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.OpFlagIsCompressed", index: 32, oracle: "OpFlagIsCompressed" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.OpFlagIsFirstInSequence", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.OpFlagIsFirstInSequence", index: 33, oracle: "OpFlagIsFirstInSequence" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.OpFlagIsLastInSequence", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.OpFlagIsLastInSequence", index: 34, oracle: "OpFlagIsLastInSequence" }, +]; + +pub const STAGE1_OPENING_CLAIMS: &[Stage1OpeningClaimPlan] = &[ + Stage1OpeningClaimPlan { symbol: "stage1.uniskip.opening", oracle: "UnivariateSkip", domain: "jolt.stage1_uniskip_domain", point_arity: 1, claim_kind: "virtual", point_source: "stage1.uniskip.instance", eval_source: "stage1.uniskip.eval" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.LeftInstructionInput" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RightInstructionInput" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.Product", oracle: "Product", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.Product" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.ShouldBranch", oracle: "ShouldBranch", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.ShouldBranch" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.PC", oracle: "PC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.PC" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.UnexpandedPC", oracle: "UnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.UnexpandedPC" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.Imm", oracle: "Imm", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.Imm" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RamAddress", oracle: "RamAddress", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RamAddress" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.Rs1Value" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.Rs2Value" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RdWriteValue", oracle: "RdWriteValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RdWriteValue" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RamReadValue", oracle: "RamReadValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RamReadValue" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RamWriteValue", oracle: "RamWriteValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RamWriteValue" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.LeftLookupOperand", oracle: "LeftLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.LeftLookupOperand" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RightLookupOperand", oracle: "RightLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RightLookupOperand" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.NextUnexpandedPC", oracle: "NextUnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.NextUnexpandedPC" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.NextPC", oracle: "NextPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.NextPC" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.NextIsVirtual", oracle: "NextIsVirtual", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.NextIsVirtual" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.NextIsFirstInSequence", oracle: "NextIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.NextIsFirstInSequence" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.LookupOutput" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.ShouldJump", oracle: "ShouldJump", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.ShouldJump" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagAddOperands", oracle: "OpFlagAddOperands", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagAddOperands" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagSubtractOperands", oracle: "OpFlagSubtractOperands", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagSubtractOperands" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagMultiplyOperands", oracle: "OpFlagMultiplyOperands", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagMultiplyOperands" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagLoad", oracle: "OpFlagLoad", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagLoad" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagStore", oracle: "OpFlagStore", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagStore" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagJump", oracle: "OpFlagJump", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagJump" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagWriteLookupOutputToRD", oracle: "OpFlagWriteLookupOutputToRD", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagWriteLookupOutputToRD" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagVirtualInstruction" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagAssert", oracle: "OpFlagAssert", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagAssert" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagDoNotUpdateUnexpandedPC", oracle: "OpFlagDoNotUpdateUnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagDoNotUpdateUnexpandedPC" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagAdvice", oracle: "OpFlagAdvice", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagAdvice" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagIsCompressed", oracle: "OpFlagIsCompressed", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagIsCompressed" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagIsFirstInSequence", oracle: "OpFlagIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagIsFirstInSequence" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagIsLastInSequence", oracle: "OpFlagIsLastInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagIsLastInSequence" }, +]; + +pub const STAGE1_OPENING_BATCH_0_ORDERED_CLAIMS: &[&str] = &[ + "stage1.outer_remaining.opening.LeftInstructionInput", + "stage1.outer_remaining.opening.RightInstructionInput", + "stage1.outer_remaining.opening.Product", + "stage1.outer_remaining.opening.ShouldBranch", + "stage1.outer_remaining.opening.PC", + "stage1.outer_remaining.opening.UnexpandedPC", + "stage1.outer_remaining.opening.Imm", + "stage1.outer_remaining.opening.RamAddress", + "stage1.outer_remaining.opening.Rs1Value", + "stage1.outer_remaining.opening.Rs2Value", + "stage1.outer_remaining.opening.RdWriteValue", + "stage1.outer_remaining.opening.RamReadValue", + "stage1.outer_remaining.opening.RamWriteValue", + "stage1.outer_remaining.opening.LeftLookupOperand", + "stage1.outer_remaining.opening.RightLookupOperand", + "stage1.outer_remaining.opening.NextUnexpandedPC", + "stage1.outer_remaining.opening.NextPC", + "stage1.outer_remaining.opening.NextIsVirtual", + "stage1.outer_remaining.opening.NextIsFirstInSequence", + "stage1.outer_remaining.opening.LookupOutput", + "stage1.outer_remaining.opening.ShouldJump", + "stage1.outer_remaining.opening.OpFlagAddOperands", + "stage1.outer_remaining.opening.OpFlagSubtractOperands", + "stage1.outer_remaining.opening.OpFlagMultiplyOperands", + "stage1.outer_remaining.opening.OpFlagLoad", + "stage1.outer_remaining.opening.OpFlagStore", + "stage1.outer_remaining.opening.OpFlagJump", + "stage1.outer_remaining.opening.OpFlagWriteLookupOutputToRD", + "stage1.outer_remaining.opening.OpFlagVirtualInstruction", + "stage1.outer_remaining.opening.OpFlagAssert", + "stage1.outer_remaining.opening.OpFlagDoNotUpdateUnexpandedPC", + "stage1.outer_remaining.opening.OpFlagAdvice", + "stage1.outer_remaining.opening.OpFlagIsCompressed", + "stage1.outer_remaining.opening.OpFlagIsFirstInSequence", + "stage1.outer_remaining.opening.OpFlagIsLastInSequence", +]; + +pub const STAGE1_OPENING_BATCH_0_CLAIM_OPERANDS: &[&str] = &[ + "stage1.outer_remaining.opening.LeftInstructionInput", + "stage1.outer_remaining.opening.RightInstructionInput", + "stage1.outer_remaining.opening.Product", + "stage1.outer_remaining.opening.ShouldBranch", + "stage1.outer_remaining.opening.PC", + "stage1.outer_remaining.opening.UnexpandedPC", + "stage1.outer_remaining.opening.Imm", + "stage1.outer_remaining.opening.RamAddress", + "stage1.outer_remaining.opening.Rs1Value", + "stage1.outer_remaining.opening.Rs2Value", + "stage1.outer_remaining.opening.RdWriteValue", + "stage1.outer_remaining.opening.RamReadValue", + "stage1.outer_remaining.opening.RamWriteValue", + "stage1.outer_remaining.opening.LeftLookupOperand", + "stage1.outer_remaining.opening.RightLookupOperand", + "stage1.outer_remaining.opening.NextUnexpandedPC", + "stage1.outer_remaining.opening.NextPC", + "stage1.outer_remaining.opening.NextIsVirtual", + "stage1.outer_remaining.opening.NextIsFirstInSequence", + "stage1.outer_remaining.opening.LookupOutput", + "stage1.outer_remaining.opening.ShouldJump", + "stage1.outer_remaining.opening.OpFlagAddOperands", + "stage1.outer_remaining.opening.OpFlagSubtractOperands", + "stage1.outer_remaining.opening.OpFlagMultiplyOperands", + "stage1.outer_remaining.opening.OpFlagLoad", + "stage1.outer_remaining.opening.OpFlagStore", + "stage1.outer_remaining.opening.OpFlagJump", + "stage1.outer_remaining.opening.OpFlagWriteLookupOutputToRD", + "stage1.outer_remaining.opening.OpFlagVirtualInstruction", + "stage1.outer_remaining.opening.OpFlagAssert", + "stage1.outer_remaining.opening.OpFlagDoNotUpdateUnexpandedPC", + "stage1.outer_remaining.opening.OpFlagAdvice", + "stage1.outer_remaining.opening.OpFlagIsCompressed", + "stage1.outer_remaining.opening.OpFlagIsFirstInSequence", + "stage1.outer_remaining.opening.OpFlagIsLastInSequence", +]; + +pub const STAGE1_OPENING_BATCHES: &[Stage1OpeningBatchPlan] = &[ + Stage1OpeningBatchPlan { symbol: "stage1.outer_remaining.openings", stage: "stage1", proof_slot: "stage1.virtual_openings", policy: "jolt_r1cs_input_order", count: 35, ordered_claims: STAGE1_OPENING_BATCH_0_ORDERED_CLAIMS, claim_operands: STAGE1_OPENING_BATCH_0_CLAIM_OPERANDS }, +]; +pub const STAGE1_PROGRAM: Stage1CpuProgramPlan = Stage1CpuProgramPlan { + params: STAGE1_PARAMS, + transcript_squeezes: STAGE1_TRANSCRIPT_SQUEEZES, + kernels: STAGE1_KERNELS, + claims: STAGE1_SUMCHECK_CLAIMS, + batches: STAGE1_SUMCHECK_BATCHES, + drivers: STAGE1_SUMCHECK_DRIVERS, + instance_results: STAGE1_SUMCHECK_INSTANCE_RESULTS, + evals: STAGE1_SUMCHECK_EVALS, + opening_claims: STAGE1_OPENING_CLAIMS, + opening_batches: STAGE1_OPENING_BATCHES, +}; + +pub fn prove_stage1_outer( + executor: &mut E, + transcript: &mut T, +) -> Result, Stage1KernelError> +where + E: Stage1KernelExecutor, + T: Transcript, +{ + prove_stage1_outer_with_program(&STAGE1_PROGRAM, executor, transcript) +} + +pub fn prove_stage1_outer_with_program( + program: &'static Stage1CpuProgramPlan, + executor: &mut E, + transcript: &mut T, +) -> Result, Stage1KernelError> +where + E: Stage1KernelExecutor, + T: Transcript, +{ + execute_stage1_program( + program, + Stage1ExecutionMode::Prover, + executor, + transcript, + ) +} diff --git a/crates/jolt-prover/src/stages/stage2.rs b/crates/jolt-prover/src/stages/stage2.rs new file mode 100644 index 0000000000..ece68d1c0b --- /dev/null +++ b/crates/jolt-prover/src/stages/stage2.rs @@ -0,0 +1,402 @@ +#![allow(dead_code)] + +use jolt_field::Fr; +use jolt_kernels::stage2::{execute_stage2_program, Stage2CpuProgramPlan, Stage2ExecutionArtifacts, Stage2ExecutionMode, Stage2FieldConstantPlan, Stage2FieldExprPlan, Stage2KernelError, Stage2KernelExecutor, Stage2KernelPlan, Stage2OpeningBatchPlan, Stage2OpeningClaimPlan, Stage2OpeningInputPlan, Stage2Params, Stage2PointConcatPlan, Stage2PointSlicePlan, Stage2ProgramStepPlan, Stage2SumcheckBatchPlan, Stage2SumcheckClaimPlan, Stage2SumcheckDriverPlan, Stage2SumcheckEvalPlan, Stage2SumcheckInstanceResultPlan, Stage2TranscriptSqueezePlan}; +use jolt_transcript::{Blake2bTranscript, Transcript}; + +pub type DefaultStage2Transcript = Blake2bTranscript; + +pub const STAGE2_PARAMS: Stage2Params = Stage2Params { + field: "bn254_fr", + pcs: "dory", + transcript: "blake2b_transcript", +}; +pub const STAGE2_PROGRAM_STEPS: &[Stage2ProgramStepPlan] = &[ + Stage2ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage2.product_virtual.tau_high" }, + Stage2ProgramStepPlan { kind: "sumcheck_driver", symbol: "stage2.product_virtual.uniskip.sumcheck" }, + Stage2ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage2.ram_read_write.gamma" }, + Stage2ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage2.instruction_lookup.gamma" }, + Stage2ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage2.ram_output.r_address" }, + Stage2ProgramStepPlan { kind: "sumcheck_driver", symbol: "stage2.sumcheck" }, +]; + +pub const STAGE2_TRANSCRIPT_SQUEEZES: &[Stage2TranscriptSqueezePlan] = &[ + Stage2TranscriptSqueezePlan { symbol: "stage2.product_virtual.tau_high", label: "product_virtual_tau_high", kind: "challenge_scalar", count: 1 }, + Stage2TranscriptSqueezePlan { symbol: "stage2.ram_read_write.gamma", label: "ram_read_write_gamma", kind: "challenge_scalar", count: 1 }, + Stage2TranscriptSqueezePlan { symbol: "stage2.instruction_lookup.gamma", label: "instruction_lookup_gamma", kind: "challenge_scalar", count: 1 }, + Stage2TranscriptSqueezePlan { symbol: "stage2.ram_output.r_address", label: "ram_output_r_address", kind: "challenge_vector", count: 16 }, +]; + +pub const STAGE2_OPENING_INPUTS: &[Stage2OpeningInputPlan] = &[ + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.Product", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.Product", oracle: "Product", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.ShouldBranch", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.ShouldBranch", oracle: "ShouldBranch", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.ShouldJump", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.ShouldJump", oracle: "ShouldJump", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.RamReadValue", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RamReadValue", oracle: "RamReadValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.RamWriteValue", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RamWriteValue", oracle: "RamWriteValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.LookupOutput", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.LeftLookupOperand", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.LeftLookupOperand", oracle: "LeftLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.RightLookupOperand", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RightLookupOperand", oracle: "RightLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.LeftInstructionInput", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.RightInstructionInput", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.RamAddress", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RamAddress", oracle: "RamAddress", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, +]; + +pub const STAGE2_FIELD_CONSTANTS: &[Stage2FieldConstantPlan] = &[ + Stage2FieldConstantPlan { symbol: "stage2.ram_output.zero", field: "bn254_fr", value: 0 }, +]; + +pub const STAGE2_FIELD_EXPR_OPERANDS_0: &[&str] = &["stage2.product_virtual.tau_high"]; + +pub const STAGE2_FIELD_EXPR_OPERANDS_1: &[&str] = &[ + "stage2.product_virtual.uniskip.weight.Product", + "stage2.input.stage1.Product", +]; + +pub const STAGE2_FIELD_EXPR_OPERANDS_2: &[&str] = &[ + "stage2.product_virtual.uniskip.weight.ShouldBranch", + "stage2.input.stage1.ShouldBranch", +]; + +pub const STAGE2_FIELD_EXPR_OPERANDS_3: &[&str] = &[ + "stage2.product_virtual.uniskip.weight.ShouldJump", + "stage2.input.stage1.ShouldJump", +]; + +pub const STAGE2_FIELD_EXPR_OPERANDS_4: &[&str] = &[ + "stage2.product_virtual.uniskip.term.Product", + "stage2.product_virtual.uniskip.term.ShouldBranch", +]; + +pub const STAGE2_FIELD_EXPR_OPERANDS_5: &[&str] = &[ + "stage2.product_virtual.uniskip.partial.ProductShouldBranch", + "stage2.product_virtual.uniskip.term.ShouldJump", +]; + +pub const STAGE2_FIELD_EXPR_OPERANDS_6: &[&str] = &[ + "stage2.ram_read_write.gamma", + "stage2.input.stage1.RamWriteValue", +]; + +pub const STAGE2_FIELD_EXPR_OPERANDS_7: &[&str] = &[ + "stage2.input.stage1.RamReadValue", + "stage2.ram_read_write.term.RamWriteValue", +]; + +pub const STAGE2_FIELD_EXPR_OPERANDS_8: &[&str] = &[ + "stage2.instruction_lookup.gamma", + "stage2.instruction_lookup.gamma", +]; + +pub const STAGE2_FIELD_EXPR_OPERANDS_9: &[&str] = &[ + "stage2.instruction_lookup.gamma2", + "stage2.instruction_lookup.gamma", +]; + +pub const STAGE2_FIELD_EXPR_OPERANDS_10: &[&str] = &[ + "stage2.instruction_lookup.gamma2", + "stage2.instruction_lookup.gamma2", +]; + +pub const STAGE2_FIELD_EXPR_OPERANDS_11: &[&str] = &[ + "stage2.instruction_lookup.gamma", + "stage2.input.stage1.LeftLookupOperand", +]; + +pub const STAGE2_FIELD_EXPR_OPERANDS_12: &[&str] = &[ + "stage2.instruction_lookup.gamma2", + "stage2.input.stage1.RightLookupOperand", +]; + +pub const STAGE2_FIELD_EXPR_OPERANDS_13: &[&str] = &[ + "stage2.instruction_lookup.gamma3", + "stage2.input.stage1.LeftInstructionInput", +]; + +pub const STAGE2_FIELD_EXPR_OPERANDS_14: &[&str] = &[ + "stage2.instruction_lookup.gamma4", + "stage2.input.stage1.RightInstructionInput", +]; + +pub const STAGE2_FIELD_EXPR_OPERANDS_15: &[&str] = &[ + "stage2.input.stage1.LookupOutput", + "stage2.instruction_lookup.term.LeftLookupOperand", +]; + +pub const STAGE2_FIELD_EXPR_OPERANDS_16: &[&str] = &[ + "stage2.instruction_lookup.partial.LookupOutputLeftOperand", + "stage2.instruction_lookup.term.RightLookupOperand", +]; + +pub const STAGE2_FIELD_EXPR_OPERANDS_17: &[&str] = &[ + "stage2.instruction_lookup.partial.RightOperand", + "stage2.instruction_lookup.term.LeftInstructionInput", +]; + +pub const STAGE2_FIELD_EXPR_OPERANDS_18: &[&str] = &[ + "stage2.instruction_lookup.partial.LeftInstructionInput", + "stage2.instruction_lookup.term.RightInstructionInput", +]; + +pub const STAGE2_FIELD_EXPRS: &[Stage2FieldExprPlan] = &[ + Stage2FieldExprPlan { symbol: "stage2.product_virtual.uniskip.weight.Product", kind: "op", formula: "poly.lagrange_basis_eval:-1:3:0", operand_names: STAGE2_FIELD_EXPR_OPERANDS_0, operands: STAGE2_FIELD_EXPR_OPERANDS_0 }, + Stage2FieldExprPlan { symbol: "stage2.product_virtual.uniskip.weight.ShouldBranch", kind: "op", formula: "poly.lagrange_basis_eval:-1:3:1", operand_names: STAGE2_FIELD_EXPR_OPERANDS_0, operands: STAGE2_FIELD_EXPR_OPERANDS_0 }, + Stage2FieldExprPlan { symbol: "stage2.product_virtual.uniskip.weight.ShouldJump", kind: "op", formula: "poly.lagrange_basis_eval:-1:3:2", operand_names: STAGE2_FIELD_EXPR_OPERANDS_0, operands: STAGE2_FIELD_EXPR_OPERANDS_0 }, + Stage2FieldExprPlan { symbol: "stage2.product_virtual.uniskip.term.Product", kind: "op", formula: "field.mul", operand_names: STAGE2_FIELD_EXPR_OPERANDS_1, operands: STAGE2_FIELD_EXPR_OPERANDS_1 }, + Stage2FieldExprPlan { symbol: "stage2.product_virtual.uniskip.term.ShouldBranch", kind: "op", formula: "field.mul", operand_names: STAGE2_FIELD_EXPR_OPERANDS_2, operands: STAGE2_FIELD_EXPR_OPERANDS_2 }, + Stage2FieldExprPlan { symbol: "stage2.product_virtual.uniskip.term.ShouldJump", kind: "op", formula: "field.mul", operand_names: STAGE2_FIELD_EXPR_OPERANDS_3, operands: STAGE2_FIELD_EXPR_OPERANDS_3 }, + Stage2FieldExprPlan { symbol: "stage2.product_virtual.uniskip.partial.ProductShouldBranch", kind: "op", formula: "field.add", operand_names: STAGE2_FIELD_EXPR_OPERANDS_4, operands: STAGE2_FIELD_EXPR_OPERANDS_4 }, + Stage2FieldExprPlan { symbol: "stage2.product_virtual.uniskip.claim_expr", kind: "op", formula: "field.add", operand_names: STAGE2_FIELD_EXPR_OPERANDS_5, operands: STAGE2_FIELD_EXPR_OPERANDS_5 }, + Stage2FieldExprPlan { symbol: "stage2.ram_read_write.term.RamWriteValue", kind: "op", formula: "field.mul", operand_names: STAGE2_FIELD_EXPR_OPERANDS_6, operands: STAGE2_FIELD_EXPR_OPERANDS_6 }, + Stage2FieldExprPlan { symbol: "stage2.ram_read_write.claim_expr", kind: "op", formula: "field.add", operand_names: STAGE2_FIELD_EXPR_OPERANDS_7, operands: STAGE2_FIELD_EXPR_OPERANDS_7 }, + Stage2FieldExprPlan { symbol: "stage2.instruction_lookup.gamma2", kind: "op", formula: "field.mul", operand_names: STAGE2_FIELD_EXPR_OPERANDS_8, operands: STAGE2_FIELD_EXPR_OPERANDS_8 }, + Stage2FieldExprPlan { symbol: "stage2.instruction_lookup.gamma3", kind: "op", formula: "field.mul", operand_names: STAGE2_FIELD_EXPR_OPERANDS_9, operands: STAGE2_FIELD_EXPR_OPERANDS_9 }, + Stage2FieldExprPlan { symbol: "stage2.instruction_lookup.gamma4", kind: "op", formula: "field.mul", operand_names: STAGE2_FIELD_EXPR_OPERANDS_10, operands: STAGE2_FIELD_EXPR_OPERANDS_10 }, + Stage2FieldExprPlan { symbol: "stage2.instruction_lookup.term.LeftLookupOperand", kind: "op", formula: "field.mul", operand_names: STAGE2_FIELD_EXPR_OPERANDS_11, operands: STAGE2_FIELD_EXPR_OPERANDS_11 }, + Stage2FieldExprPlan { symbol: "stage2.instruction_lookup.term.RightLookupOperand", kind: "op", formula: "field.mul", operand_names: STAGE2_FIELD_EXPR_OPERANDS_12, operands: STAGE2_FIELD_EXPR_OPERANDS_12 }, + Stage2FieldExprPlan { symbol: "stage2.instruction_lookup.term.LeftInstructionInput", kind: "op", formula: "field.mul", operand_names: STAGE2_FIELD_EXPR_OPERANDS_13, operands: STAGE2_FIELD_EXPR_OPERANDS_13 }, + Stage2FieldExprPlan { symbol: "stage2.instruction_lookup.term.RightInstructionInput", kind: "op", formula: "field.mul", operand_names: STAGE2_FIELD_EXPR_OPERANDS_14, operands: STAGE2_FIELD_EXPR_OPERANDS_14 }, + Stage2FieldExprPlan { symbol: "stage2.instruction_lookup.partial.LookupOutputLeftOperand", kind: "op", formula: "field.add", operand_names: STAGE2_FIELD_EXPR_OPERANDS_15, operands: STAGE2_FIELD_EXPR_OPERANDS_15 }, + Stage2FieldExprPlan { symbol: "stage2.instruction_lookup.partial.RightOperand", kind: "op", formula: "field.add", operand_names: STAGE2_FIELD_EXPR_OPERANDS_16, operands: STAGE2_FIELD_EXPR_OPERANDS_16 }, + Stage2FieldExprPlan { symbol: "stage2.instruction_lookup.partial.LeftInstructionInput", kind: "op", formula: "field.add", operand_names: STAGE2_FIELD_EXPR_OPERANDS_17, operands: STAGE2_FIELD_EXPR_OPERANDS_17 }, + Stage2FieldExprPlan { symbol: "stage2.instruction_lookup.claim_reduction.claim_expr", kind: "op", formula: "field.add", operand_names: STAGE2_FIELD_EXPR_OPERANDS_18, operands: STAGE2_FIELD_EXPR_OPERANDS_18 }, +]; +pub const STAGE2_KERNELS: &[Stage2KernelPlan] = &[ + Stage2KernelPlan { symbol: "jolt.cpu.stage2.product_virtual.uniskip", relation: "jolt.stage2.product_virtual.uniskip", kind: "sumcheck", backend: "cpu", abi: "jolt_stage2_product_virtual_uniskip" }, + Stage2KernelPlan { symbol: "jolt.cpu.stage2.ram.read_write", relation: "jolt.stage2.ram.read_write", kind: "sumcheck", backend: "cpu", abi: "jolt_stage2_ram_read_write" }, + Stage2KernelPlan { symbol: "jolt.cpu.stage2.product_virtual.remainder", relation: "jolt.stage2.product_virtual.remainder", kind: "sumcheck", backend: "cpu", abi: "jolt_stage2_product_virtual_remainder" }, + Stage2KernelPlan { symbol: "jolt.cpu.stage2.instruction_lookup.claim_reduction", relation: "jolt.stage2.instruction_lookup.claim_reduction", kind: "sumcheck", backend: "cpu", abi: "jolt_stage2_instruction_lookup_claim_reduction" }, + Stage2KernelPlan { symbol: "jolt.cpu.stage2.ram.raf_evaluation", relation: "jolt.stage2.ram.raf_evaluation", kind: "sumcheck", backend: "cpu", abi: "jolt_stage2_ram_raf_evaluation" }, + Stage2KernelPlan { symbol: "jolt.cpu.stage2.ram.output_check", relation: "jolt.stage2.ram.output_check", kind: "sumcheck", backend: "cpu", abi: "jolt_stage2_ram_output_check" }, + Stage2KernelPlan { symbol: "jolt.cpu.stage2.batched", relation: "jolt.stage2.batched", kind: "sumcheck", backend: "cpu", abi: "jolt_stage2_batched" }, +]; + +pub const STAGE2_SUMCHECK_CLAIM_0_INPUT_OPENINGS: &[&str] = &[ + "stage2.input.stage1.Product", + "stage2.input.stage1.ShouldBranch", + "stage2.input.stage1.ShouldJump", +]; + +pub const STAGE2_SUMCHECK_CLAIM_1_INPUT_OPENINGS: &[&str] = &[ + "stage2.input.stage1.RamReadValue", + "stage2.input.stage1.RamWriteValue", +]; + +pub const STAGE2_SUMCHECK_CLAIM_2_INPUT_OPENINGS: &[&str] = &["stage2.product_virtual.uniskip.opening.UnivariateSkip"]; + +pub const STAGE2_SUMCHECK_CLAIM_3_INPUT_OPENINGS: &[&str] = &[ + "stage2.input.stage1.LookupOutput", + "stage2.input.stage1.LeftLookupOperand", + "stage2.input.stage1.RightLookupOperand", + "stage2.input.stage1.LeftInstructionInput", + "stage2.input.stage1.RightInstructionInput", +]; + +pub const STAGE2_SUMCHECK_CLAIM_4_INPUT_OPENINGS: &[&str] = &["stage2.input.stage1.RamAddress"]; + +pub const STAGE2_SUMCHECK_CLAIM_5_INPUT_OPENINGS: &[&str] = &[]; + +pub const STAGE2_SUMCHECK_CLAIMS: &[Stage2SumcheckClaimPlan] = &[ + Stage2SumcheckClaimPlan { symbol: "stage2.product_virtual.uniskip.input", stage: "stage2", domain: "jolt.stage2_uniskip_domain", num_rounds: 1, degree: 6, claim: "stage2.product_virtual.weighted_stage1_outputs", kernel: Some("jolt.cpu.stage2.product_virtual.uniskip"), relation: None, claim_value: "stage2.product_virtual.uniskip.claim_expr", input_openings: STAGE2_SUMCHECK_CLAIM_0_INPUT_OPENINGS }, + Stage2SumcheckClaimPlan { symbol: "stage2.ram_read_write.input", stage: "stage2", domain: "jolt.stage2_ram_rw_domain", num_rounds: 32, degree: 3, claim: "stage2.ram_read_write.weighted_values", kernel: Some("jolt.cpu.stage2.ram.read_write"), relation: None, claim_value: "stage2.ram_read_write.claim_expr", input_openings: STAGE2_SUMCHECK_CLAIM_1_INPUT_OPENINGS }, + Stage2SumcheckClaimPlan { symbol: "stage2.product_virtual.remainder.input", stage: "stage2", domain: "jolt.trace_domain", num_rounds: 16, degree: 3, claim: "stage2.product_virtual.uniskip.opening", kernel: Some("jolt.cpu.stage2.product_virtual.remainder"), relation: None, claim_value: "stage2.product_virtual.uniskip.eval.UnivariateSkip", input_openings: STAGE2_SUMCHECK_CLAIM_2_INPUT_OPENINGS }, + Stage2SumcheckClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.input", stage: "stage2", domain: "jolt.trace_domain", num_rounds: 16, degree: 2, claim: "stage2.instruction_lookup.weighted_operands", kernel: Some("jolt.cpu.stage2.instruction_lookup.claim_reduction"), relation: None, claim_value: "stage2.instruction_lookup.claim_reduction.claim_expr", input_openings: STAGE2_SUMCHECK_CLAIM_3_INPUT_OPENINGS }, + Stage2SumcheckClaimPlan { symbol: "stage2.ram_raf.input", stage: "stage2", domain: "jolt.ram_address_domain", num_rounds: 16, degree: 2, claim: "stage2.ram_raf.ram_address", kernel: Some("jolt.cpu.stage2.ram.raf_evaluation"), relation: None, claim_value: "stage2.input.stage1.RamAddress", input_openings: STAGE2_SUMCHECK_CLAIM_4_INPUT_OPENINGS }, + Stage2SumcheckClaimPlan { symbol: "stage2.ram_output.input", stage: "stage2", domain: "jolt.ram_address_domain", num_rounds: 16, degree: 3, claim: "zero", kernel: Some("jolt.cpu.stage2.ram.output_check"), relation: None, claim_value: "stage2.ram_output.zero", input_openings: STAGE2_SUMCHECK_CLAIM_5_INPUT_OPENINGS }, +]; +pub const STAGE2_SUMCHECK_BATCH_0_ORDERED_CLAIMS: &[&str] = &["stage2.product_virtual.uniskip.input"]; + +pub const STAGE2_SUMCHECK_BATCH_0_CLAIM_OPERANDS: &[&str] = &["stage2.product_virtual.uniskip.input"]; + +pub const STAGE2_SUMCHECK_BATCH_0_ROUND_SCHEDULE: &[usize] = &[ + 1, +]; + +pub const STAGE2_SUMCHECK_BATCH_1_ORDERED_CLAIMS: &[&str] = &[ + "stage2.ram_read_write.input", + "stage2.product_virtual.remainder.input", + "stage2.instruction_lookup.claim_reduction.input", + "stage2.ram_raf.input", + "stage2.ram_output.input", +]; + +pub const STAGE2_SUMCHECK_BATCH_1_CLAIM_OPERANDS: &[&str] = &[ + "stage2.ram_read_write.input", + "stage2.product_virtual.remainder.input", + "stage2.instruction_lookup.claim_reduction.input", + "stage2.ram_raf.input", + "stage2.ram_output.input", +]; + +pub const STAGE2_SUMCHECK_BATCH_1_ROUND_SCHEDULE: &[usize] = &[ + 16, + 16, +]; + +pub const STAGE2_SUMCHECK_BATCHES: &[Stage2SumcheckBatchPlan] = &[ + Stage2SumcheckBatchPlan { symbol: "stage2.product_virtual.uniskip.batch", stage: "stage2", proof_slot: "stage2.product_virtual.uni_skip_first_round", policy: "single_instance", count: 1, ordered_claims: STAGE2_SUMCHECK_BATCH_0_ORDERED_CLAIMS, claim_operands: STAGE2_SUMCHECK_BATCH_0_CLAIM_OPERANDS, claim_label: "uniskip_claim", round_label: "uniskip_poly", round_schedule: STAGE2_SUMCHECK_BATCH_0_ROUND_SCHEDULE }, + Stage2SumcheckBatchPlan { symbol: "stage2.batch", stage: "stage2", proof_slot: "stage2.sumcheck", policy: "jolt_core_stage2_aligned", count: 5, ordered_claims: STAGE2_SUMCHECK_BATCH_1_ORDERED_CLAIMS, claim_operands: STAGE2_SUMCHECK_BATCH_1_CLAIM_OPERANDS, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", round_schedule: STAGE2_SUMCHECK_BATCH_1_ROUND_SCHEDULE }, +]; +pub const STAGE2_SUMCHECK_DRIVER_0_ROUND_SCHEDULE: &[usize] = &[ + 1, +]; + +pub const STAGE2_SUMCHECK_DRIVER_1_ROUND_SCHEDULE: &[usize] = &[ + 16, + 16, +]; + +pub const STAGE2_SUMCHECK_DRIVERS: &[Stage2SumcheckDriverPlan] = &[ + Stage2SumcheckDriverPlan { symbol: "stage2.product_virtual.uniskip.sumcheck", stage: "stage2", proof_slot: "stage2.product_virtual.uni_skip_first_round", kernel: Some("jolt.cpu.stage2.product_virtual.uniskip"), relation: None, batch: "stage2.product_virtual.uniskip.batch", policy: "univariate_skip", round_schedule: STAGE2_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "uniskip_claim", round_label: "uniskip_poly", num_rounds: 1, degree: 6 }, + Stage2SumcheckDriverPlan { symbol: "stage2.sumcheck", stage: "stage2", proof_slot: "stage2.sumcheck", kernel: Some("jolt.cpu.stage2.batched"), relation: None, batch: "stage2.batch", policy: "jolt_core_stage2_aligned", round_schedule: STAGE2_SUMCHECK_DRIVER_1_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 32, degree: 3 }, +]; +pub const STAGE2_SUMCHECK_INSTANCE_RESULTS: &[Stage2SumcheckInstanceResultPlan] = &[ + Stage2SumcheckInstanceResultPlan { symbol: "stage2.product_virtual.uniskip.instance", source: "stage2.product_virtual.uniskip.sumcheck", claim: "stage2.product_virtual.uniskip.input", relation: "jolt.stage2.product_virtual.uniskip", index: 0, point_arity: 1, num_rounds: 1, round_offset: 0, point_order: "as_is", degree: 6 }, + Stage2SumcheckInstanceResultPlan { symbol: "stage2.ram_read_write.instance", source: "stage2.sumcheck", claim: "stage2.ram_read_write.input", relation: "jolt.stage2.ram.read_write", index: 0, point_arity: 32, num_rounds: 32, round_offset: 0, point_order: "reverse", degree: 3 }, + Stage2SumcheckInstanceResultPlan { symbol: "stage2.product_virtual.remainder.instance", source: "stage2.sumcheck", claim: "stage2.product_virtual.remainder.input", relation: "jolt.stage2.product_virtual.remainder", index: 1, point_arity: 16, num_rounds: 16, round_offset: 16, point_order: "reverse", degree: 3 }, + Stage2SumcheckInstanceResultPlan { symbol: "stage2.instruction_lookup.claim_reduction.instance", source: "stage2.sumcheck", claim: "stage2.instruction_lookup.claim_reduction.input", relation: "jolt.stage2.instruction_lookup.claim_reduction", index: 2, point_arity: 16, num_rounds: 16, round_offset: 16, point_order: "reverse", degree: 2 }, + Stage2SumcheckInstanceResultPlan { symbol: "stage2.ram_raf.instance", source: "stage2.sumcheck", claim: "stage2.ram_raf.input", relation: "jolt.stage2.ram.raf_evaluation", index: 3, point_arity: 16, num_rounds: 16, round_offset: 16, point_order: "reverse", degree: 2 }, + Stage2SumcheckInstanceResultPlan { symbol: "stage2.ram_output.instance", source: "stage2.sumcheck", claim: "stage2.ram_output.input", relation: "jolt.stage2.ram.output_check", index: 4, point_arity: 16, num_rounds: 16, round_offset: 16, point_order: "reverse", degree: 3 }, +]; + +pub const STAGE2_SUMCHECK_EVALS: &[Stage2SumcheckEvalPlan] = &[ + Stage2SumcheckEvalPlan { symbol: "stage2.product_virtual.uniskip.eval.UnivariateSkip", source: "stage2.product_virtual.uniskip.sumcheck", name: "stage2.product_virtual.uniskip.eval.UnivariateSkip", index: 0, oracle: "UnivariateSkip" }, + Stage2SumcheckEvalPlan { symbol: "stage2.ram_read_write.eval.RamVal", source: "stage2.sumcheck", name: "stage2.ram_read_write.eval.RamVal", index: 0, oracle: "RamVal" }, + Stage2SumcheckEvalPlan { symbol: "stage2.ram_read_write.eval.RamRa", source: "stage2.sumcheck", name: "stage2.ram_read_write.eval.RamRa", index: 1, oracle: "RamRa" }, + Stage2SumcheckEvalPlan { symbol: "stage2.ram_read_write.eval.RamInc", source: "stage2.sumcheck", name: "stage2.ram_read_write.eval.RamInc", index: 2, oracle: "RamInc" }, + Stage2SumcheckEvalPlan { symbol: "stage2.product_virtual.remainder.eval.LeftInstructionInput", source: "stage2.sumcheck", name: "stage2.product_virtual.remainder.eval.LeftInstructionInput", index: 0, oracle: "LeftInstructionInput" }, + Stage2SumcheckEvalPlan { symbol: "stage2.product_virtual.remainder.eval.RightInstructionInput", source: "stage2.sumcheck", name: "stage2.product_virtual.remainder.eval.RightInstructionInput", index: 1, oracle: "RightInstructionInput" }, + Stage2SumcheckEvalPlan { symbol: "stage2.product_virtual.remainder.eval.OpFlagJump", source: "stage2.sumcheck", name: "stage2.product_virtual.remainder.eval.OpFlagJump", index: 2, oracle: "OpFlagJump" }, + Stage2SumcheckEvalPlan { symbol: "stage2.product_virtual.remainder.eval.OpFlagWriteLookupOutputToRD", source: "stage2.sumcheck", name: "stage2.product_virtual.remainder.eval.OpFlagWriteLookupOutputToRD", index: 3, oracle: "OpFlagWriteLookupOutputToRD" }, + Stage2SumcheckEvalPlan { symbol: "stage2.product_virtual.remainder.eval.LookupOutput", source: "stage2.sumcheck", name: "stage2.product_virtual.remainder.eval.LookupOutput", index: 4, oracle: "LookupOutput" }, + Stage2SumcheckEvalPlan { symbol: "stage2.product_virtual.remainder.eval.InstructionFlagBranch", source: "stage2.sumcheck", name: "stage2.product_virtual.remainder.eval.InstructionFlagBranch", index: 5, oracle: "InstructionFlagBranch" }, + Stage2SumcheckEvalPlan { symbol: "stage2.product_virtual.remainder.eval.NextIsNoop", source: "stage2.sumcheck", name: "stage2.product_virtual.remainder.eval.NextIsNoop", index: 6, oracle: "NextIsNoop" }, + Stage2SumcheckEvalPlan { symbol: "stage2.product_virtual.remainder.eval.OpFlagVirtualInstruction", source: "stage2.sumcheck", name: "stage2.product_virtual.remainder.eval.OpFlagVirtualInstruction", index: 7, oracle: "OpFlagVirtualInstruction" }, + Stage2SumcheckEvalPlan { symbol: "stage2.instruction_lookup.claim_reduction.eval.LookupOutput", source: "stage2.sumcheck", name: "stage2.instruction_lookup.claim_reduction.eval.LookupOutput", index: 0, oracle: "LookupOutput" }, + Stage2SumcheckEvalPlan { symbol: "stage2.instruction_lookup.claim_reduction.eval.LeftLookupOperand", source: "stage2.sumcheck", name: "stage2.instruction_lookup.claim_reduction.eval.LeftLookupOperand", index: 1, oracle: "LeftLookupOperand" }, + Stage2SumcheckEvalPlan { symbol: "stage2.instruction_lookup.claim_reduction.eval.RightLookupOperand", source: "stage2.sumcheck", name: "stage2.instruction_lookup.claim_reduction.eval.RightLookupOperand", index: 2, oracle: "RightLookupOperand" }, + Stage2SumcheckEvalPlan { symbol: "stage2.instruction_lookup.claim_reduction.eval.LeftInstructionInput", source: "stage2.sumcheck", name: "stage2.instruction_lookup.claim_reduction.eval.LeftInstructionInput", index: 3, oracle: "LeftInstructionInput" }, + Stage2SumcheckEvalPlan { symbol: "stage2.instruction_lookup.claim_reduction.eval.RightInstructionInput", source: "stage2.sumcheck", name: "stage2.instruction_lookup.claim_reduction.eval.RightInstructionInput", index: 4, oracle: "RightInstructionInput" }, + Stage2SumcheckEvalPlan { symbol: "stage2.ram_raf.eval.RamRa", source: "stage2.sumcheck", name: "stage2.ram_raf.eval.RamRa", index: 0, oracle: "RamRa" }, + Stage2SumcheckEvalPlan { symbol: "stage2.ram_output.eval.RamValFinal", source: "stage2.sumcheck", name: "stage2.ram_output.eval.RamValFinal", index: 0, oracle: "RamValFinal" }, +]; + +pub const STAGE2_POINT_SLICES: &[Stage2PointSlicePlan] = &[ + Stage2PointSlicePlan { symbol: "stage2.ram_read_write.point.RamInc", source: "stage2.ram_read_write.instance", offset: 16, length: 16, input: "stage2.ram_read_write.instance" }, +]; + +pub const STAGE2_POINT_CONCAT_0_INPUTS: &[&str] = &[ + "stage2.ram_raf.instance", + "stage2.input.stage1.RamAddress", +]; + +pub const STAGE2_POINT_CONCATS: &[Stage2PointConcatPlan] = &[ + Stage2PointConcatPlan { symbol: "stage2.ram_raf.point.RamRa", layout: "address_then_cycle", arity: 32, inputs: STAGE2_POINT_CONCAT_0_INPUTS }, +]; +pub const STAGE2_OPENING_CLAIMS: &[Stage2OpeningClaimPlan] = &[ + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.uniskip.opening.UnivariateSkip", oracle: "UnivariateSkip", domain: "jolt.stage2_uniskip_domain", point_arity: 1, claim_kind: "virtual", point_source: "stage2.product_virtual.uniskip.instance", eval_source: "stage2.product_virtual.uniskip.eval.UnivariateSkip" }, + Stage2OpeningClaimPlan { symbol: "stage2.ram_read_write.opening.RamVal", oracle: "RamVal", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage2.ram_read_write.instance", eval_source: "stage2.ram_read_write.eval.RamVal" }, + Stage2OpeningClaimPlan { symbol: "stage2.ram_read_write.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage2.ram_read_write.instance", eval_source: "stage2.ram_read_write.eval.RamRa" }, + Stage2OpeningClaimPlan { symbol: "stage2.ram_read_write.opening.RamInc", oracle: "RamInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed", point_source: "stage2.ram_read_write.point.RamInc", eval_source: "stage2.ram_read_write.eval.RamInc" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.LeftInstructionInput" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.RightInstructionInput" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.OpFlagJump", oracle: "OpFlagJump", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.OpFlagJump" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.OpFlagWriteLookupOutputToRD", oracle: "OpFlagWriteLookupOutputToRD", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.OpFlagWriteLookupOutputToRD" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.LookupOutput" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.InstructionFlagBranch", oracle: "InstructionFlagBranch", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.InstructionFlagBranch" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.NextIsNoop", oracle: "NextIsNoop", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.NextIsNoop" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.OpFlagVirtualInstruction" }, + Stage2OpeningClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.instruction_lookup.claim_reduction.instance", eval_source: "stage2.instruction_lookup.claim_reduction.eval.LookupOutput" }, + Stage2OpeningClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.opening.LeftLookupOperand", oracle: "LeftLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.instruction_lookup.claim_reduction.instance", eval_source: "stage2.instruction_lookup.claim_reduction.eval.LeftLookupOperand" }, + Stage2OpeningClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.opening.RightLookupOperand", oracle: "RightLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.instruction_lookup.claim_reduction.instance", eval_source: "stage2.instruction_lookup.claim_reduction.eval.RightLookupOperand" }, + Stage2OpeningClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.instruction_lookup.claim_reduction.instance", eval_source: "stage2.instruction_lookup.claim_reduction.eval.LeftInstructionInput" }, + Stage2OpeningClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.instruction_lookup.claim_reduction.instance", eval_source: "stage2.instruction_lookup.claim_reduction.eval.RightInstructionInput" }, + Stage2OpeningClaimPlan { symbol: "stage2.ram_raf.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage2.ram_raf.point.RamRa", eval_source: "stage2.ram_raf.eval.RamRa" }, + Stage2OpeningClaimPlan { symbol: "stage2.ram_output.opening.RamValFinal", oracle: "RamValFinal", domain: "jolt.ram_address_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.ram_output.instance", eval_source: "stage2.ram_output.eval.RamValFinal" }, +]; + +pub const STAGE2_OPENING_BATCH_0_ORDERED_CLAIMS: &[&str] = &[ + "stage2.ram_read_write.opening.RamVal", + "stage2.ram_read_write.opening.RamRa", + "stage2.ram_read_write.opening.RamInc", + "stage2.product_virtual.remainder.opening.LeftInstructionInput", + "stage2.product_virtual.remainder.opening.RightInstructionInput", + "stage2.product_virtual.remainder.opening.OpFlagJump", + "stage2.product_virtual.remainder.opening.OpFlagWriteLookupOutputToRD", + "stage2.product_virtual.remainder.opening.LookupOutput", + "stage2.product_virtual.remainder.opening.InstructionFlagBranch", + "stage2.product_virtual.remainder.opening.NextIsNoop", + "stage2.product_virtual.remainder.opening.OpFlagVirtualInstruction", + "stage2.instruction_lookup.claim_reduction.opening.LookupOutput", + "stage2.instruction_lookup.claim_reduction.opening.LeftLookupOperand", + "stage2.instruction_lookup.claim_reduction.opening.RightLookupOperand", + "stage2.instruction_lookup.claim_reduction.opening.LeftInstructionInput", + "stage2.instruction_lookup.claim_reduction.opening.RightInstructionInput", + "stage2.ram_raf.opening.RamRa", + "stage2.ram_output.opening.RamValFinal", +]; + +pub const STAGE2_OPENING_BATCH_0_CLAIM_OPERANDS: &[&str] = &[ + "stage2.ram_read_write.opening.RamVal", + "stage2.ram_read_write.opening.RamRa", + "stage2.ram_read_write.opening.RamInc", + "stage2.product_virtual.remainder.opening.LeftInstructionInput", + "stage2.product_virtual.remainder.opening.RightInstructionInput", + "stage2.product_virtual.remainder.opening.OpFlagJump", + "stage2.product_virtual.remainder.opening.OpFlagWriteLookupOutputToRD", + "stage2.product_virtual.remainder.opening.LookupOutput", + "stage2.product_virtual.remainder.opening.InstructionFlagBranch", + "stage2.product_virtual.remainder.opening.NextIsNoop", + "stage2.product_virtual.remainder.opening.OpFlagVirtualInstruction", + "stage2.instruction_lookup.claim_reduction.opening.LookupOutput", + "stage2.instruction_lookup.claim_reduction.opening.LeftLookupOperand", + "stage2.instruction_lookup.claim_reduction.opening.RightLookupOperand", + "stage2.instruction_lookup.claim_reduction.opening.LeftInstructionInput", + "stage2.instruction_lookup.claim_reduction.opening.RightInstructionInput", + "stage2.ram_raf.opening.RamRa", + "stage2.ram_output.opening.RamValFinal", +]; + +pub const STAGE2_OPENING_BATCHES: &[Stage2OpeningBatchPlan] = &[ + Stage2OpeningBatchPlan { symbol: "stage2.openings", stage: "stage2", proof_slot: "stage2.openings", policy: "jolt_stage2_output_order", count: 18, ordered_claims: STAGE2_OPENING_BATCH_0_ORDERED_CLAIMS, claim_operands: STAGE2_OPENING_BATCH_0_CLAIM_OPERANDS }, +]; +pub const STAGE2_PROGRAM: Stage2CpuProgramPlan = Stage2CpuProgramPlan { + params: STAGE2_PARAMS, + steps: STAGE2_PROGRAM_STEPS, + transcript_squeezes: STAGE2_TRANSCRIPT_SQUEEZES, + opening_inputs: STAGE2_OPENING_INPUTS, + field_constants: STAGE2_FIELD_CONSTANTS, + field_exprs: STAGE2_FIELD_EXPRS, + kernels: STAGE2_KERNELS, + claims: STAGE2_SUMCHECK_CLAIMS, + batches: STAGE2_SUMCHECK_BATCHES, + drivers: STAGE2_SUMCHECK_DRIVERS, + instance_results: STAGE2_SUMCHECK_INSTANCE_RESULTS, + evals: STAGE2_SUMCHECK_EVALS, + point_slices: STAGE2_POINT_SLICES, + point_concats: STAGE2_POINT_CONCATS, + opening_claims: STAGE2_OPENING_CLAIMS, + opening_batches: STAGE2_OPENING_BATCHES, +}; + +pub fn execute_stage2_prover( + executor: &mut E, + transcript: &mut T, +) -> Result, Stage2KernelError> +where + E: Stage2KernelExecutor, + T: Transcript, +{ + execute_stage2_prover_with_program(&STAGE2_PROGRAM, executor, transcript) +} + +pub fn execute_stage2_prover_with_program( + program: &'static Stage2CpuProgramPlan, + executor: &mut E, + transcript: &mut T, +) -> Result, Stage2KernelError> +where + E: Stage2KernelExecutor, + T: Transcript, +{ + execute_stage2_program(program, Stage2ExecutionMode::Prover, executor, transcript) +} diff --git a/crates/jolt-prover/src/stages/stage3.rs b/crates/jolt-prover/src/stages/stage3.rs new file mode 100644 index 0000000000..f1ca47494b --- /dev/null +++ b/crates/jolt-prover/src/stages/stage3.rs @@ -0,0 +1,351 @@ +#![allow(dead_code)] + +use jolt_field::Fr; +use jolt_kernels::stage3::{execute_stage3_program, Stage3CpuProgramPlan, Stage3ExecutionArtifacts, Stage3ExecutionMode, Stage3FieldConstantPlan, Stage3FieldExprPlan, Stage3KernelError, Stage3KernelExecutor, Stage3KernelPlan, Stage3OpeningBatchPlan, Stage3OpeningClaimEqualityPlan, Stage3OpeningClaimPlan, Stage3OpeningInputPlan, Stage3Params, Stage3PointConcatPlan, Stage3PointSlicePlan, Stage3ProgramStepPlan, Stage3SumcheckBatchPlan, Stage3SumcheckClaimPlan, Stage3SumcheckDriverPlan, Stage3SumcheckEvalPlan, Stage3SumcheckInstanceResultPlan, Stage3TranscriptSqueezePlan}; +use jolt_transcript::{Blake2bTranscript, Transcript}; + +pub type DefaultStage3Transcript = Blake2bTranscript; + +pub const STAGE3_PARAMS: Stage3Params = Stage3Params { + field: "bn254_fr", + pcs: "dory", + transcript: "blake2b_transcript", +}; +pub const STAGE3_PROGRAM_STEPS: &[Stage3ProgramStepPlan] = &[ + Stage3ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage3.spartan_shift.gamma" }, + Stage3ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage3.instruction_input.gamma" }, + Stage3ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage3.registers.gamma" }, + Stage3ProgramStepPlan { kind: "sumcheck_driver", symbol: "stage3.sumcheck" }, +]; + +pub const STAGE3_TRANSCRIPT_SQUEEZES: &[Stage3TranscriptSqueezePlan] = &[ + Stage3TranscriptSqueezePlan { symbol: "stage3.spartan_shift.gamma", label: "spartan_shift_gamma", kind: "challenge_scalar", count: 1 }, + Stage3TranscriptSqueezePlan { symbol: "stage3.instruction_input.gamma", label: "instruction_input_gamma", kind: "challenge_scalar", count: 1 }, + Stage3TranscriptSqueezePlan { symbol: "stage3.registers.gamma", label: "registers_gamma", kind: "challenge_scalar", count: 1 }, +]; + +pub const STAGE3_OPENING_INPUTS: &[Stage3OpeningInputPlan] = &[ + Stage3OpeningInputPlan { symbol: "stage3.input.stage1.NextUnexpandedPC", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.NextUnexpandedPC", oracle: "NextUnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage1.NextPC", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.NextPC", oracle: "NextPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage1.NextIsVirtual", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.NextIsVirtual", oracle: "NextIsVirtual", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage1.NextIsFirstInSequence", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.NextIsFirstInSequence", oracle: "NextIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage2.product_virtual.NextIsNoop", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.NextIsNoop", oracle: "NextIsNoop", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage2.product_virtual.LeftInstructionInput", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage2.product_virtual.RightInstructionInput", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage2.instruction_lookup.LeftInstructionInput", source_stage: "stage2", source_claim: "stage2.instruction_lookup.claim_reduction.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage2.instruction_lookup.RightInstructionInput", source_stage: "stage2", source_claim: "stage2.instruction_lookup.claim_reduction.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage1.RdWriteValue", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RdWriteValue", oracle: "RdWriteValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage1.Rs1Value", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage1.Rs2Value", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, +]; + +pub const STAGE3_FIELD_CONSTANTS: &[Stage3FieldConstantPlan] = &[ + Stage3FieldConstantPlan { symbol: "stage3.field.one", field: "bn254_fr", value: 1 }, +]; + +pub const STAGE3_FIELD_EXPR_OPERANDS_0: &[&str] = &["stage3.spartan_shift.gamma"]; + +pub const STAGE3_FIELD_EXPR_OPERANDS_1: &[&str] = &[ + "stage3.spartan_shift.gamma2", + "stage3.spartan_shift.gamma", +]; + +pub const STAGE3_FIELD_EXPR_OPERANDS_2: &[&str] = &[ + "stage3.spartan_shift.gamma2", + "stage3.spartan_shift.gamma2", +]; + +pub const STAGE3_FIELD_EXPR_OPERANDS_3: &[&str] = &[ + "stage3.spartan_shift.gamma", + "stage3.input.stage1.NextPC", +]; + +pub const STAGE3_FIELD_EXPR_OPERANDS_4: &[&str] = &[ + "stage3.spartan_shift.gamma2", + "stage3.input.stage1.NextIsVirtual", +]; + +pub const STAGE3_FIELD_EXPR_OPERANDS_5: &[&str] = &[ + "stage3.spartan_shift.gamma3", + "stage3.input.stage1.NextIsFirstInSequence", +]; + +pub const STAGE3_FIELD_EXPR_OPERANDS_6: &[&str] = &[ + "stage3.field.one", + "stage3.input.stage2.product_virtual.NextIsNoop", +]; + +pub const STAGE3_FIELD_EXPR_OPERANDS_7: &[&str] = &[ + "stage3.spartan_shift.gamma4", + "stage3.spartan_shift.one_minus.NextIsNoop", +]; + +pub const STAGE3_FIELD_EXPR_OPERANDS_8: &[&str] = &[ + "stage3.input.stage1.NextUnexpandedPC", + "stage3.spartan_shift.term.NextPC", +]; + +pub const STAGE3_FIELD_EXPR_OPERANDS_9: &[&str] = &[ + "stage3.spartan_shift.partial.NextUnexpandedPCNextPC", + "stage3.spartan_shift.term.NextIsVirtual", +]; + +pub const STAGE3_FIELD_EXPR_OPERANDS_10: &[&str] = &[ + "stage3.spartan_shift.partial.NextIsVirtual", + "stage3.spartan_shift.term.NextIsFirstInSequence", +]; + +pub const STAGE3_FIELD_EXPR_OPERANDS_11: &[&str] = &[ + "stage3.spartan_shift.partial.NextIsFirstInSequence", + "stage3.spartan_shift.term.NextIsNoop", +]; + +pub const STAGE3_FIELD_EXPR_OPERANDS_12: &[&str] = &[ + "stage3.instruction_input.gamma", + "stage3.input.stage2.product_virtual.LeftInstructionInput", +]; + +pub const STAGE3_FIELD_EXPR_OPERANDS_13: &[&str] = &[ + "stage3.input.stage2.product_virtual.RightInstructionInput", + "stage3.instruction_input.term.LeftInstructionInput", +]; + +pub const STAGE3_FIELD_EXPR_OPERANDS_14: &[&str] = &["stage3.registers.gamma"]; + +pub const STAGE3_FIELD_EXPR_OPERANDS_15: &[&str] = &[ + "stage3.registers.gamma", + "stage3.input.stage1.Rs1Value", +]; + +pub const STAGE3_FIELD_EXPR_OPERANDS_16: &[&str] = &[ + "stage3.registers.gamma2", + "stage3.input.stage1.Rs2Value", +]; + +pub const STAGE3_FIELD_EXPR_OPERANDS_17: &[&str] = &[ + "stage3.input.stage1.RdWriteValue", + "stage3.registers.term.Rs1Value", +]; + +pub const STAGE3_FIELD_EXPR_OPERANDS_18: &[&str] = &[ + "stage3.registers.partial.RdWriteValueRs1Value", + "stage3.registers.term.Rs2Value", +]; + +pub const STAGE3_FIELD_EXPRS: &[Stage3FieldExprPlan] = &[ + Stage3FieldExprPlan { symbol: "stage3.spartan_shift.gamma2", kind: "op", formula: "field.pow:2", operand_names: STAGE3_FIELD_EXPR_OPERANDS_0, operands: STAGE3_FIELD_EXPR_OPERANDS_0 }, + Stage3FieldExprPlan { symbol: "stage3.spartan_shift.gamma3", kind: "op", formula: "field.mul", operand_names: STAGE3_FIELD_EXPR_OPERANDS_1, operands: STAGE3_FIELD_EXPR_OPERANDS_1 }, + Stage3FieldExprPlan { symbol: "stage3.spartan_shift.gamma4", kind: "op", formula: "field.mul", operand_names: STAGE3_FIELD_EXPR_OPERANDS_2, operands: STAGE3_FIELD_EXPR_OPERANDS_2 }, + Stage3FieldExprPlan { symbol: "stage3.spartan_shift.term.NextPC", kind: "op", formula: "field.mul", operand_names: STAGE3_FIELD_EXPR_OPERANDS_3, operands: STAGE3_FIELD_EXPR_OPERANDS_3 }, + Stage3FieldExprPlan { symbol: "stage3.spartan_shift.term.NextIsVirtual", kind: "op", formula: "field.mul", operand_names: STAGE3_FIELD_EXPR_OPERANDS_4, operands: STAGE3_FIELD_EXPR_OPERANDS_4 }, + Stage3FieldExprPlan { symbol: "stage3.spartan_shift.term.NextIsFirstInSequence", kind: "op", formula: "field.mul", operand_names: STAGE3_FIELD_EXPR_OPERANDS_5, operands: STAGE3_FIELD_EXPR_OPERANDS_5 }, + Stage3FieldExprPlan { symbol: "stage3.spartan_shift.one_minus.NextIsNoop", kind: "op", formula: "field.sub", operand_names: STAGE3_FIELD_EXPR_OPERANDS_6, operands: STAGE3_FIELD_EXPR_OPERANDS_6 }, + Stage3FieldExprPlan { symbol: "stage3.spartan_shift.term.NextIsNoop", kind: "op", formula: "field.mul", operand_names: STAGE3_FIELD_EXPR_OPERANDS_7, operands: STAGE3_FIELD_EXPR_OPERANDS_7 }, + Stage3FieldExprPlan { symbol: "stage3.spartan_shift.partial.NextUnexpandedPCNextPC", kind: "op", formula: "field.add", operand_names: STAGE3_FIELD_EXPR_OPERANDS_8, operands: STAGE3_FIELD_EXPR_OPERANDS_8 }, + Stage3FieldExprPlan { symbol: "stage3.spartan_shift.partial.NextIsVirtual", kind: "op", formula: "field.add", operand_names: STAGE3_FIELD_EXPR_OPERANDS_9, operands: STAGE3_FIELD_EXPR_OPERANDS_9 }, + Stage3FieldExprPlan { symbol: "stage3.spartan_shift.partial.NextIsFirstInSequence", kind: "op", formula: "field.add", operand_names: STAGE3_FIELD_EXPR_OPERANDS_10, operands: STAGE3_FIELD_EXPR_OPERANDS_10 }, + Stage3FieldExprPlan { symbol: "stage3.spartan_shift.claim_expr", kind: "op", formula: "field.add", operand_names: STAGE3_FIELD_EXPR_OPERANDS_11, operands: STAGE3_FIELD_EXPR_OPERANDS_11 }, + Stage3FieldExprPlan { symbol: "stage3.instruction_input.term.LeftInstructionInput", kind: "op", formula: "field.mul", operand_names: STAGE3_FIELD_EXPR_OPERANDS_12, operands: STAGE3_FIELD_EXPR_OPERANDS_12 }, + Stage3FieldExprPlan { symbol: "stage3.instruction_input.claim_expr", kind: "op", formula: "field.add", operand_names: STAGE3_FIELD_EXPR_OPERANDS_13, operands: STAGE3_FIELD_EXPR_OPERANDS_13 }, + Stage3FieldExprPlan { symbol: "stage3.registers.gamma2", kind: "op", formula: "field.pow:2", operand_names: STAGE3_FIELD_EXPR_OPERANDS_14, operands: STAGE3_FIELD_EXPR_OPERANDS_14 }, + Stage3FieldExprPlan { symbol: "stage3.registers.term.Rs1Value", kind: "op", formula: "field.mul", operand_names: STAGE3_FIELD_EXPR_OPERANDS_15, operands: STAGE3_FIELD_EXPR_OPERANDS_15 }, + Stage3FieldExprPlan { symbol: "stage3.registers.term.Rs2Value", kind: "op", formula: "field.mul", operand_names: STAGE3_FIELD_EXPR_OPERANDS_16, operands: STAGE3_FIELD_EXPR_OPERANDS_16 }, + Stage3FieldExprPlan { symbol: "stage3.registers.partial.RdWriteValueRs1Value", kind: "op", formula: "field.add", operand_names: STAGE3_FIELD_EXPR_OPERANDS_17, operands: STAGE3_FIELD_EXPR_OPERANDS_17 }, + Stage3FieldExprPlan { symbol: "stage3.registers.claim_expr", kind: "op", formula: "field.add", operand_names: STAGE3_FIELD_EXPR_OPERANDS_18, operands: STAGE3_FIELD_EXPR_OPERANDS_18 }, +]; +pub const STAGE3_KERNELS: &[Stage3KernelPlan] = &[ + Stage3KernelPlan { symbol: "jolt.cpu.stage3.spartan_shift", relation: "jolt.stage3.spartan_shift", kind: "sumcheck", backend: "cpu", abi: "jolt_stage3_spartan_shift" }, + Stage3KernelPlan { symbol: "jolt.cpu.stage3.instruction_input", relation: "jolt.stage3.instruction_input", kind: "sumcheck", backend: "cpu", abi: "jolt_stage3_instruction_input" }, + Stage3KernelPlan { symbol: "jolt.cpu.stage3.registers_claim_reduction", relation: "jolt.stage3.registers_claim_reduction", kind: "sumcheck", backend: "cpu", abi: "jolt_stage3_registers_claim_reduction" }, + Stage3KernelPlan { symbol: "jolt.cpu.stage3.batched", relation: "jolt.stage3.batched", kind: "sumcheck", backend: "cpu", abi: "jolt_stage3_batched" }, +]; + +pub const STAGE3_SUMCHECK_CLAIM_0_INPUT_OPENINGS: &[&str] = &[ + "stage3.input.stage1.NextUnexpandedPC", + "stage3.input.stage1.NextPC", + "stage3.input.stage1.NextIsVirtual", + "stage3.input.stage1.NextIsFirstInSequence", + "stage3.input.stage2.product_virtual.NextIsNoop", +]; + +pub const STAGE3_SUMCHECK_CLAIM_1_INPUT_OPENINGS: &[&str] = &[ + "stage3.input.stage2.product_virtual.RightInstructionInput", + "stage3.input.stage2.product_virtual.LeftInstructionInput", +]; + +pub const STAGE3_SUMCHECK_CLAIM_2_INPUT_OPENINGS: &[&str] = &[ + "stage3.input.stage1.RdWriteValue", + "stage3.input.stage1.Rs1Value", + "stage3.input.stage1.Rs2Value", +]; + +pub const STAGE3_SUMCHECK_CLAIMS: &[Stage3SumcheckClaimPlan] = &[ + Stage3SumcheckClaimPlan { symbol: "stage3.spartan_shift.input", stage: "stage3", domain: "jolt.trace_domain", num_rounds: 16, degree: 2, claim: "stage3.spartan_shift.weighted_next_values", kernel: Some("jolt.cpu.stage3.spartan_shift"), relation: None, claim_value: "stage3.spartan_shift.claim_expr", input_openings: STAGE3_SUMCHECK_CLAIM_0_INPUT_OPENINGS }, + Stage3SumcheckClaimPlan { symbol: "stage3.instruction_input.input", stage: "stage3", domain: "jolt.trace_domain", num_rounds: 16, degree: 3, claim: "stage3.instruction_input.weighted_inputs", kernel: Some("jolt.cpu.stage3.instruction_input"), relation: None, claim_value: "stage3.instruction_input.claim_expr", input_openings: STAGE3_SUMCHECK_CLAIM_1_INPUT_OPENINGS }, + Stage3SumcheckClaimPlan { symbol: "stage3.registers_claim_reduction.input", stage: "stage3", domain: "jolt.trace_domain", num_rounds: 16, degree: 2, claim: "stage3.registers.weighted_register_values", kernel: Some("jolt.cpu.stage3.registers_claim_reduction"), relation: None, claim_value: "stage3.registers.claim_expr", input_openings: STAGE3_SUMCHECK_CLAIM_2_INPUT_OPENINGS }, +]; +pub const STAGE3_SUMCHECK_BATCH_0_ORDERED_CLAIMS: &[&str] = &[ + "stage3.spartan_shift.input", + "stage3.instruction_input.input", + "stage3.registers_claim_reduction.input", +]; + +pub const STAGE3_SUMCHECK_BATCH_0_CLAIM_OPERANDS: &[&str] = &[ + "stage3.spartan_shift.input", + "stage3.instruction_input.input", + "stage3.registers_claim_reduction.input", +]; + +pub const STAGE3_SUMCHECK_BATCH_0_ROUND_SCHEDULE: &[usize] = &[ + 16, +]; + +pub const STAGE3_SUMCHECK_BATCHES: &[Stage3SumcheckBatchPlan] = &[ + Stage3SumcheckBatchPlan { symbol: "stage3.batch", stage: "stage3", proof_slot: "stage3.sumcheck", policy: "jolt_core_stage3_aligned", count: 3, ordered_claims: STAGE3_SUMCHECK_BATCH_0_ORDERED_CLAIMS, claim_operands: STAGE3_SUMCHECK_BATCH_0_CLAIM_OPERANDS, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", round_schedule: STAGE3_SUMCHECK_BATCH_0_ROUND_SCHEDULE }, +]; +pub const STAGE3_SUMCHECK_DRIVER_0_ROUND_SCHEDULE: &[usize] = &[ + 16, +]; + +pub const STAGE3_SUMCHECK_DRIVERS: &[Stage3SumcheckDriverPlan] = &[ + Stage3SumcheckDriverPlan { symbol: "stage3.sumcheck", stage: "stage3", proof_slot: "stage3.sumcheck", kernel: Some("jolt.cpu.stage3.batched"), relation: None, batch: "stage3.batch", policy: "jolt_core_stage3_aligned", round_schedule: STAGE3_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 16, degree: 3 }, +]; +pub const STAGE3_SUMCHECK_INSTANCE_RESULTS: &[Stage3SumcheckInstanceResultPlan] = &[ + Stage3SumcheckInstanceResultPlan { symbol: "stage3.spartan_shift.instance", source: "stage3.sumcheck", claim: "stage3.spartan_shift.input", relation: "jolt.stage3.spartan_shift", index: 0, point_arity: 16, num_rounds: 16, round_offset: 0, point_order: "reverse", degree: 2 }, + Stage3SumcheckInstanceResultPlan { symbol: "stage3.instruction_input.instance", source: "stage3.sumcheck", claim: "stage3.instruction_input.input", relation: "jolt.stage3.instruction_input", index: 1, point_arity: 16, num_rounds: 16, round_offset: 0, point_order: "reverse", degree: 3 }, + Stage3SumcheckInstanceResultPlan { symbol: "stage3.registers_claim_reduction.instance", source: "stage3.sumcheck", claim: "stage3.registers_claim_reduction.input", relation: "jolt.stage3.registers_claim_reduction", index: 2, point_arity: 16, num_rounds: 16, round_offset: 0, point_order: "reverse", degree: 2 }, +]; + +pub const STAGE3_SUMCHECK_EVALS: &[Stage3SumcheckEvalPlan] = &[ + Stage3SumcheckEvalPlan { symbol: "stage3.spartan_shift.eval.UnexpandedPC", source: "stage3.sumcheck", name: "stage3.spartan_shift.eval.UnexpandedPC", index: 0, oracle: "UnexpandedPC" }, + Stage3SumcheckEvalPlan { symbol: "stage3.spartan_shift.eval.PC", source: "stage3.sumcheck", name: "stage3.spartan_shift.eval.PC", index: 1, oracle: "PC" }, + Stage3SumcheckEvalPlan { symbol: "stage3.spartan_shift.eval.OpFlagVirtualInstruction", source: "stage3.sumcheck", name: "stage3.spartan_shift.eval.OpFlagVirtualInstruction", index: 2, oracle: "OpFlagVirtualInstruction" }, + Stage3SumcheckEvalPlan { symbol: "stage3.spartan_shift.eval.OpFlagIsFirstInSequence", source: "stage3.sumcheck", name: "stage3.spartan_shift.eval.OpFlagIsFirstInSequence", index: 3, oracle: "OpFlagIsFirstInSequence" }, + Stage3SumcheckEvalPlan { symbol: "stage3.spartan_shift.eval.InstructionFlagIsNoop", source: "stage3.sumcheck", name: "stage3.spartan_shift.eval.InstructionFlagIsNoop", index: 4, oracle: "InstructionFlagIsNoop" }, + Stage3SumcheckEvalPlan { symbol: "stage3.instruction_input.eval.InstructionFlagLeftOperandIsRs1Value", source: "stage3.sumcheck", name: "stage3.instruction_input.eval.InstructionFlagLeftOperandIsRs1Value", index: 5, oracle: "InstructionFlagLeftOperandIsRs1Value" }, + Stage3SumcheckEvalPlan { symbol: "stage3.instruction_input.eval.Rs1Value", source: "stage3.sumcheck", name: "stage3.instruction_input.eval.Rs1Value", index: 6, oracle: "Rs1Value" }, + Stage3SumcheckEvalPlan { symbol: "stage3.instruction_input.eval.InstructionFlagLeftOperandIsPC", source: "stage3.sumcheck", name: "stage3.instruction_input.eval.InstructionFlagLeftOperandIsPC", index: 7, oracle: "InstructionFlagLeftOperandIsPC" }, + Stage3SumcheckEvalPlan { symbol: "stage3.instruction_input.eval.UnexpandedPC", source: "stage3.sumcheck", name: "stage3.instruction_input.eval.UnexpandedPC", index: 8, oracle: "UnexpandedPC" }, + Stage3SumcheckEvalPlan { symbol: "stage3.instruction_input.eval.InstructionFlagRightOperandIsRs2Value", source: "stage3.sumcheck", name: "stage3.instruction_input.eval.InstructionFlagRightOperandIsRs2Value", index: 9, oracle: "InstructionFlagRightOperandIsRs2Value" }, + Stage3SumcheckEvalPlan { symbol: "stage3.instruction_input.eval.Rs2Value", source: "stage3.sumcheck", name: "stage3.instruction_input.eval.Rs2Value", index: 10, oracle: "Rs2Value" }, + Stage3SumcheckEvalPlan { symbol: "stage3.instruction_input.eval.InstructionFlagRightOperandIsImm", source: "stage3.sumcheck", name: "stage3.instruction_input.eval.InstructionFlagRightOperandIsImm", index: 11, oracle: "InstructionFlagRightOperandIsImm" }, + Stage3SumcheckEvalPlan { symbol: "stage3.instruction_input.eval.Imm", source: "stage3.sumcheck", name: "stage3.instruction_input.eval.Imm", index: 12, oracle: "Imm" }, + Stage3SumcheckEvalPlan { symbol: "stage3.registers_claim_reduction.eval.RdWriteValue", source: "stage3.sumcheck", name: "stage3.registers_claim_reduction.eval.RdWriteValue", index: 13, oracle: "RdWriteValue" }, + Stage3SumcheckEvalPlan { symbol: "stage3.registers_claim_reduction.eval.Rs1Value", source: "stage3.sumcheck", name: "stage3.registers_claim_reduction.eval.Rs1Value", index: 14, oracle: "Rs1Value" }, + Stage3SumcheckEvalPlan { symbol: "stage3.registers_claim_reduction.eval.Rs2Value", source: "stage3.sumcheck", name: "stage3.registers_claim_reduction.eval.Rs2Value", index: 15, oracle: "Rs2Value" }, +]; + +pub const STAGE3_POINT_SLICES: &[Stage3PointSlicePlan] = &[ + +]; + +pub const STAGE3_POINT_CONCATS: &[Stage3PointConcatPlan] = &[ + +]; +pub const STAGE3_OPENING_CLAIMS: &[Stage3OpeningClaimPlan] = &[ + Stage3OpeningClaimPlan { symbol: "stage3.spartan_shift.opening.UnexpandedPC", oracle: "UnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.spartan_shift.instance", eval_source: "stage3.spartan_shift.eval.UnexpandedPC" }, + Stage3OpeningClaimPlan { symbol: "stage3.spartan_shift.opening.PC", oracle: "PC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.spartan_shift.instance", eval_source: "stage3.spartan_shift.eval.PC" }, + Stage3OpeningClaimPlan { symbol: "stage3.spartan_shift.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.spartan_shift.instance", eval_source: "stage3.spartan_shift.eval.OpFlagVirtualInstruction" }, + Stage3OpeningClaimPlan { symbol: "stage3.spartan_shift.opening.OpFlagIsFirstInSequence", oracle: "OpFlagIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.spartan_shift.instance", eval_source: "stage3.spartan_shift.eval.OpFlagIsFirstInSequence" }, + Stage3OpeningClaimPlan { symbol: "stage3.spartan_shift.opening.InstructionFlagIsNoop", oracle: "InstructionFlagIsNoop", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.spartan_shift.instance", eval_source: "stage3.spartan_shift.eval.InstructionFlagIsNoop" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.InstructionFlagLeftOperandIsRs1Value", oracle: "InstructionFlagLeftOperandIsRs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.InstructionFlagLeftOperandIsRs1Value" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.Rs1Value" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.InstructionFlagLeftOperandIsPC", oracle: "InstructionFlagLeftOperandIsPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.InstructionFlagLeftOperandIsPC" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.UnexpandedPC", oracle: "UnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.UnexpandedPC" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.InstructionFlagRightOperandIsRs2Value", oracle: "InstructionFlagRightOperandIsRs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.InstructionFlagRightOperandIsRs2Value" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.Rs2Value" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.InstructionFlagRightOperandIsImm", oracle: "InstructionFlagRightOperandIsImm", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.InstructionFlagRightOperandIsImm" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.Imm", oracle: "Imm", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.Imm" }, + Stage3OpeningClaimPlan { symbol: "stage3.registers_claim_reduction.opening.RdWriteValue", oracle: "RdWriteValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.registers_claim_reduction.instance", eval_source: "stage3.registers_claim_reduction.eval.RdWriteValue" }, + Stage3OpeningClaimPlan { symbol: "stage3.registers_claim_reduction.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.registers_claim_reduction.instance", eval_source: "stage3.registers_claim_reduction.eval.Rs1Value" }, + Stage3OpeningClaimPlan { symbol: "stage3.registers_claim_reduction.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.registers_claim_reduction.instance", eval_source: "stage3.registers_claim_reduction.eval.Rs2Value" }, +]; + +pub const STAGE3_OPENING_EQUALITIES: &[Stage3OpeningClaimEqualityPlan] = &[ + Stage3OpeningClaimEqualityPlan { symbol: "stage3.instruction_input.left_claim_consistency", mode: "point_and_eval", lhs: "stage3.input.stage2.product_virtual.LeftInstructionInput", rhs: "stage3.input.stage2.instruction_lookup.LeftInstructionInput" }, + Stage3OpeningClaimEqualityPlan { symbol: "stage3.instruction_input.right_claim_consistency", mode: "point_and_eval", lhs: "stage3.input.stage2.product_virtual.RightInstructionInput", rhs: "stage3.input.stage2.instruction_lookup.RightInstructionInput" }, +]; + +pub const STAGE3_OPENING_BATCH_0_ORDERED_CLAIMS: &[&str] = &[ + "stage3.spartan_shift.opening.UnexpandedPC", + "stage3.spartan_shift.opening.PC", + "stage3.spartan_shift.opening.OpFlagVirtualInstruction", + "stage3.spartan_shift.opening.OpFlagIsFirstInSequence", + "stage3.spartan_shift.opening.InstructionFlagIsNoop", + "stage3.instruction_input.opening.InstructionFlagLeftOperandIsRs1Value", + "stage3.instruction_input.opening.Rs1Value", + "stage3.instruction_input.opening.InstructionFlagLeftOperandIsPC", + "stage3.instruction_input.opening.UnexpandedPC", + "stage3.instruction_input.opening.InstructionFlagRightOperandIsRs2Value", + "stage3.instruction_input.opening.Rs2Value", + "stage3.instruction_input.opening.InstructionFlagRightOperandIsImm", + "stage3.instruction_input.opening.Imm", + "stage3.registers_claim_reduction.opening.RdWriteValue", + "stage3.registers_claim_reduction.opening.Rs1Value", + "stage3.registers_claim_reduction.opening.Rs2Value", +]; + +pub const STAGE3_OPENING_BATCH_0_CLAIM_OPERANDS: &[&str] = &[ + "stage3.spartan_shift.opening.UnexpandedPC", + "stage3.spartan_shift.opening.PC", + "stage3.spartan_shift.opening.OpFlagVirtualInstruction", + "stage3.spartan_shift.opening.OpFlagIsFirstInSequence", + "stage3.spartan_shift.opening.InstructionFlagIsNoop", + "stage3.instruction_input.opening.InstructionFlagLeftOperandIsRs1Value", + "stage3.instruction_input.opening.Rs1Value", + "stage3.instruction_input.opening.InstructionFlagLeftOperandIsPC", + "stage3.instruction_input.opening.UnexpandedPC", + "stage3.instruction_input.opening.InstructionFlagRightOperandIsRs2Value", + "stage3.instruction_input.opening.Rs2Value", + "stage3.instruction_input.opening.InstructionFlagRightOperandIsImm", + "stage3.instruction_input.opening.Imm", + "stage3.registers_claim_reduction.opening.RdWriteValue", + "stage3.registers_claim_reduction.opening.Rs1Value", + "stage3.registers_claim_reduction.opening.Rs2Value", +]; + +pub const STAGE3_OPENING_BATCHES: &[Stage3OpeningBatchPlan] = &[ + Stage3OpeningBatchPlan { symbol: "stage3.openings", stage: "stage3", proof_slot: "stage3.openings", policy: "jolt_stage3_output_order", count: 16, ordered_claims: STAGE3_OPENING_BATCH_0_ORDERED_CLAIMS, claim_operands: STAGE3_OPENING_BATCH_0_CLAIM_OPERANDS }, +]; +pub const STAGE3_PROGRAM: Stage3CpuProgramPlan = Stage3CpuProgramPlan { + params: STAGE3_PARAMS, + steps: STAGE3_PROGRAM_STEPS, + transcript_squeezes: STAGE3_TRANSCRIPT_SQUEEZES, + opening_inputs: STAGE3_OPENING_INPUTS, + field_constants: STAGE3_FIELD_CONSTANTS, + field_exprs: STAGE3_FIELD_EXPRS, + kernels: STAGE3_KERNELS, + claims: STAGE3_SUMCHECK_CLAIMS, + batches: STAGE3_SUMCHECK_BATCHES, + drivers: STAGE3_SUMCHECK_DRIVERS, + instance_results: STAGE3_SUMCHECK_INSTANCE_RESULTS, + evals: STAGE3_SUMCHECK_EVALS, + point_slices: STAGE3_POINT_SLICES, + point_concats: STAGE3_POINT_CONCATS, + opening_claims: STAGE3_OPENING_CLAIMS, + opening_equalities: STAGE3_OPENING_EQUALITIES, + opening_batches: STAGE3_OPENING_BATCHES, +}; + +pub fn execute_stage3_prover( + executor: &mut E, + transcript: &mut T, +) -> Result, Stage3KernelError> +where + E: Stage3KernelExecutor, + T: Transcript, +{ + execute_stage3_prover_with_program(&STAGE3_PROGRAM, executor, transcript) +} + +pub fn execute_stage3_prover_with_program( + program: &'static Stage3CpuProgramPlan, + executor: &mut E, + transcript: &mut T, +) -> Result, Stage3KernelError> +where + E: Stage3KernelExecutor, + T: Transcript, +{ + execute_stage3_program(program, Stage3ExecutionMode::Prover, executor, transcript) +} diff --git a/crates/jolt-prover/src/stages/stage4.rs b/crates/jolt-prover/src/stages/stage4.rs new file mode 100644 index 0000000000..03a8258a94 --- /dev/null +++ b/crates/jolt-prover/src/stages/stage4.rs @@ -0,0 +1,255 @@ +#![allow(dead_code)] + +use jolt_field::Fr; +use jolt_kernels::stage4::{execute_stage4_program, Stage4CpuProgramPlan, Stage4ExecutionArtifacts, Stage4ExecutionMode, Stage4FieldConstantPlan, Stage4FieldExprPlan, Stage4KernelError, Stage4KernelExecutor, Stage4KernelPlan, Stage4OpeningBatchPlan, Stage4OpeningClaimEqualityPlan, Stage4OpeningClaimPlan, Stage4OpeningInputPlan, Stage4Params, Stage4PointConcatPlan, Stage4PointSlicePlan, Stage4ProgramStepPlan, Stage4SumcheckBatchPlan, Stage4SumcheckClaimPlan, Stage4SumcheckDriverPlan, Stage4SumcheckEvalPlan, Stage4SumcheckInstanceResultPlan, Stage4TranscriptAbsorbBytesPlan, Stage4TranscriptSqueezePlan}; +use jolt_transcript::{Blake2bTranscript, Transcript}; + +pub type DefaultStage4Transcript = Blake2bTranscript; + +pub const STAGE4_PARAMS: Stage4Params = Stage4Params { + field: "bn254_fr", + pcs: "dory", + transcript: "blake2b_transcript", +}; +pub const STAGE4_PROGRAM_STEPS: &[Stage4ProgramStepPlan] = &[ + Stage4ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage4.registers_read_write.gamma" }, + Stage4ProgramStepPlan { kind: "transcript_absorb_bytes", symbol: "stage4.ram_val_check.domain_separator" }, + Stage4ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage4.ram_val_check.gamma" }, + Stage4ProgramStepPlan { kind: "sumcheck_driver", symbol: "stage4.sumcheck" }, +]; + +pub const STAGE4_TRANSCRIPT_SQUEEZES: &[Stage4TranscriptSqueezePlan] = &[ + Stage4TranscriptSqueezePlan { symbol: "stage4.registers_read_write.gamma", label: "registers_read_write_gamma", kind: "challenge_scalar", count: 1 }, + Stage4TranscriptSqueezePlan { symbol: "stage4.ram_val_check.gamma", label: "ram_val_check_gamma", kind: "challenge_scalar", count: 1 }, +]; + +pub const STAGE4_TRANSCRIPT_ABSORB_BYTES: &[Stage4TranscriptAbsorbBytesPlan] = &[ + Stage4TranscriptAbsorbBytesPlan { symbol: "stage4.ram_val_check.domain_separator", label: "ram_val_check_gamma", payload: "" }, +]; + +pub const STAGE4_OPENING_INPUTS: &[Stage4OpeningInputPlan] = &[ + Stage4OpeningInputPlan { symbol: "stage4.input.stage3.registers.RdWriteValue", source_stage: "stage3", source_claim: "stage3.registers_claim_reduction.opening.RdWriteValue", oracle: "RdWriteValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage4OpeningInputPlan { symbol: "stage4.input.stage3.registers.Rs1Value", source_stage: "stage3", source_claim: "stage3.registers_claim_reduction.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage4OpeningInputPlan { symbol: "stage4.input.stage3.registers.Rs2Value", source_stage: "stage3", source_claim: "stage3.registers_claim_reduction.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage4OpeningInputPlan { symbol: "stage4.input.stage3.instruction.Rs1Value", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage4OpeningInputPlan { symbol: "stage4.input.stage3.instruction.Rs2Value", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage4OpeningInputPlan { symbol: "stage4.input.stage2.RamVal", source_stage: "stage2", source_claim: "stage2.ram_read_write.opening.RamVal", oracle: "RamVal", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual" }, + Stage4OpeningInputPlan { symbol: "stage4.input.stage2.RamValFinal", source_stage: "stage2", source_claim: "stage2.ram_output.opening.RamValFinal", oracle: "RamValFinal", domain: "jolt.ram_address_domain", point_arity: 16, claim_kind: "virtual" }, + Stage4OpeningInputPlan { symbol: "stage4.input.initial_ram.RamValInit", source_stage: "stage4_precomputed", source_claim: "stage4.ram_val_check.initial_ram_eval", oracle: "RamValInit", domain: "jolt.ram_address_domain", point_arity: 16, claim_kind: "virtual" }, +]; + +pub const STAGE4_FIELD_CONSTANTS: &[Stage4FieldConstantPlan] = &[ + +]; + +pub const STAGE4_FIELD_EXPR_OPERANDS_0: &[&str] = &["stage4.registers_read_write.gamma"]; + +pub const STAGE4_FIELD_EXPR_OPERANDS_1: &[&str] = &[ + "stage4.registers_read_write.gamma", + "stage4.input.stage3.registers.Rs1Value", +]; + +pub const STAGE4_FIELD_EXPR_OPERANDS_2: &[&str] = &[ + "stage4.registers_read_write.gamma2", + "stage4.input.stage3.registers.Rs2Value", +]; + +pub const STAGE4_FIELD_EXPR_OPERANDS_3: &[&str] = &[ + "stage4.input.stage3.registers.RdWriteValue", + "stage4.registers_read_write.term.Rs1Value", +]; + +pub const STAGE4_FIELD_EXPR_OPERANDS_4: &[&str] = &[ + "stage4.registers_read_write.partial.RdWriteValueRs1Value", + "stage4.registers_read_write.term.Rs2Value", +]; + +pub const STAGE4_FIELD_EXPR_OPERANDS_5: &[&str] = &[ + "stage4.input.stage2.RamVal", + "stage4.input.initial_ram.RamValInit", +]; + +pub const STAGE4_FIELD_EXPR_OPERANDS_6: &[&str] = &[ + "stage4.input.stage2.RamValFinal", + "stage4.input.initial_ram.RamValInit", +]; + +pub const STAGE4_FIELD_EXPR_OPERANDS_7: &[&str] = &[ + "stage4.ram_val_check.gamma", + "stage4.ram_val_check.delta.RamValFinal", +]; + +pub const STAGE4_FIELD_EXPR_OPERANDS_8: &[&str] = &[ + "stage4.ram_val_check.delta.RamVal", + "stage4.ram_val_check.term.RamValFinal", +]; + +pub const STAGE4_FIELD_EXPRS: &[Stage4FieldExprPlan] = &[ + Stage4FieldExprPlan { symbol: "stage4.registers_read_write.gamma2", kind: "op", formula: "field.pow:2", operand_names: STAGE4_FIELD_EXPR_OPERANDS_0, operands: STAGE4_FIELD_EXPR_OPERANDS_0 }, + Stage4FieldExprPlan { symbol: "stage4.registers_read_write.term.Rs1Value", kind: "op", formula: "field.mul", operand_names: STAGE4_FIELD_EXPR_OPERANDS_1, operands: STAGE4_FIELD_EXPR_OPERANDS_1 }, + Stage4FieldExprPlan { symbol: "stage4.registers_read_write.term.Rs2Value", kind: "op", formula: "field.mul", operand_names: STAGE4_FIELD_EXPR_OPERANDS_2, operands: STAGE4_FIELD_EXPR_OPERANDS_2 }, + Stage4FieldExprPlan { symbol: "stage4.registers_read_write.partial.RdWriteValueRs1Value", kind: "op", formula: "field.add", operand_names: STAGE4_FIELD_EXPR_OPERANDS_3, operands: STAGE4_FIELD_EXPR_OPERANDS_3 }, + Stage4FieldExprPlan { symbol: "stage4.registers_read_write.claim_expr", kind: "op", formula: "field.add", operand_names: STAGE4_FIELD_EXPR_OPERANDS_4, operands: STAGE4_FIELD_EXPR_OPERANDS_4 }, + Stage4FieldExprPlan { symbol: "stage4.ram_val_check.delta.RamVal", kind: "op", formula: "field.sub", operand_names: STAGE4_FIELD_EXPR_OPERANDS_5, operands: STAGE4_FIELD_EXPR_OPERANDS_5 }, + Stage4FieldExprPlan { symbol: "stage4.ram_val_check.delta.RamValFinal", kind: "op", formula: "field.sub", operand_names: STAGE4_FIELD_EXPR_OPERANDS_6, operands: STAGE4_FIELD_EXPR_OPERANDS_6 }, + Stage4FieldExprPlan { symbol: "stage4.ram_val_check.term.RamValFinal", kind: "op", formula: "field.mul", operand_names: STAGE4_FIELD_EXPR_OPERANDS_7, operands: STAGE4_FIELD_EXPR_OPERANDS_7 }, + Stage4FieldExprPlan { symbol: "stage4.ram_val_check.claim_expr", kind: "op", formula: "field.add", operand_names: STAGE4_FIELD_EXPR_OPERANDS_8, operands: STAGE4_FIELD_EXPR_OPERANDS_8 }, +]; +pub const STAGE4_KERNELS: &[Stage4KernelPlan] = &[ + Stage4KernelPlan { symbol: "jolt.cpu.stage4.registers_read_write", relation: "jolt.stage4.registers_read_write", kind: "sumcheck", backend: "cpu", abi: "jolt_stage4_registers_read_write" }, + Stage4KernelPlan { symbol: "jolt.cpu.stage4.ram_val_check", relation: "jolt.stage4.ram_val_check", kind: "sumcheck", backend: "cpu", abi: "jolt_stage4_ram_val_check" }, + Stage4KernelPlan { symbol: "jolt.cpu.stage4.batched", relation: "jolt.stage4.batched", kind: "sumcheck", backend: "cpu", abi: "jolt_stage4_batched" }, +]; + +pub const STAGE4_SUMCHECK_CLAIM_0_INPUT_OPENINGS: &[&str] = &[ + "stage4.input.stage3.registers.RdWriteValue", + "stage4.input.stage3.registers.Rs1Value", + "stage4.input.stage3.registers.Rs2Value", +]; + +pub const STAGE4_SUMCHECK_CLAIM_1_INPUT_OPENINGS: &[&str] = &[ + "stage4.input.stage2.RamVal", + "stage4.input.stage2.RamValFinal", + "stage4.input.initial_ram.RamValInit", +]; + +pub const STAGE4_SUMCHECK_CLAIMS: &[Stage4SumcheckClaimPlan] = &[ + Stage4SumcheckClaimPlan { symbol: "stage4.registers_read_write.input", stage: "stage4", domain: "jolt.stage4_registers_rw_domain", num_rounds: 23, degree: 3, claim: "stage4.registers_read_write.weighted_values", kernel: Some("jolt.cpu.stage4.registers_read_write"), relation: None, claim_value: "stage4.registers_read_write.claim_expr", input_openings: STAGE4_SUMCHECK_CLAIM_0_INPUT_OPENINGS }, + Stage4SumcheckClaimPlan { symbol: "stage4.ram_val_check.input", stage: "stage4", domain: "jolt.trace_domain", num_rounds: 16, degree: 3, claim: "stage4.ram_val_check.weighted_values", kernel: Some("jolt.cpu.stage4.ram_val_check"), relation: None, claim_value: "stage4.ram_val_check.claim_expr", input_openings: STAGE4_SUMCHECK_CLAIM_1_INPUT_OPENINGS }, +]; +pub const STAGE4_SUMCHECK_BATCH_0_ORDERED_CLAIMS: &[&str] = &[ + "stage4.registers_read_write.input", + "stage4.ram_val_check.input", +]; + +pub const STAGE4_SUMCHECK_BATCH_0_CLAIM_OPERANDS: &[&str] = &[ + "stage4.registers_read_write.input", + "stage4.ram_val_check.input", +]; + +pub const STAGE4_SUMCHECK_BATCH_0_ROUND_SCHEDULE: &[usize] = &[ + 16, + 7, +]; + +pub const STAGE4_SUMCHECK_BATCHES: &[Stage4SumcheckBatchPlan] = &[ + Stage4SumcheckBatchPlan { symbol: "stage4.batch", stage: "stage4", proof_slot: "stage4.sumcheck", policy: "jolt_core_stage4_aligned", count: 2, ordered_claims: STAGE4_SUMCHECK_BATCH_0_ORDERED_CLAIMS, claim_operands: STAGE4_SUMCHECK_BATCH_0_CLAIM_OPERANDS, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", round_schedule: STAGE4_SUMCHECK_BATCH_0_ROUND_SCHEDULE }, +]; +pub const STAGE4_SUMCHECK_DRIVER_0_ROUND_SCHEDULE: &[usize] = &[ + 16, + 7, +]; + +pub const STAGE4_SUMCHECK_DRIVERS: &[Stage4SumcheckDriverPlan] = &[ + Stage4SumcheckDriverPlan { symbol: "stage4.sumcheck", stage: "stage4", proof_slot: "stage4.sumcheck", kernel: Some("jolt.cpu.stage4.batched"), relation: None, batch: "stage4.batch", policy: "jolt_core_stage4_aligned", round_schedule: STAGE4_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 23, degree: 3 }, +]; +pub const STAGE4_SUMCHECK_INSTANCE_RESULTS: &[Stage4SumcheckInstanceResultPlan] = &[ + Stage4SumcheckInstanceResultPlan { symbol: "stage4.registers_read_write.instance", source: "stage4.sumcheck", claim: "stage4.registers_read_write.input", relation: "jolt.stage4.registers_read_write", index: 0, point_arity: 23, num_rounds: 23, round_offset: 0, point_order: "stage4_registers_rw", degree: 3 }, + Stage4SumcheckInstanceResultPlan { symbol: "stage4.ram_val_check.instance", source: "stage4.sumcheck", claim: "stage4.ram_val_check.input", relation: "jolt.stage4.ram_val_check", index: 1, point_arity: 16, num_rounds: 16, round_offset: 7, point_order: "reverse", degree: 3 }, +]; + +pub const STAGE4_SUMCHECK_EVALS: &[Stage4SumcheckEvalPlan] = &[ + Stage4SumcheckEvalPlan { symbol: "stage4.registers_read_write.eval.RegistersVal", source: "stage4.sumcheck", name: "stage4.registers_read_write.eval.RegistersVal", index: 0, oracle: "RegistersVal" }, + Stage4SumcheckEvalPlan { symbol: "stage4.registers_read_write.eval.Rs1Ra", source: "stage4.sumcheck", name: "stage4.registers_read_write.eval.Rs1Ra", index: 1, oracle: "Rs1Ra" }, + Stage4SumcheckEvalPlan { symbol: "stage4.registers_read_write.eval.Rs2Ra", source: "stage4.sumcheck", name: "stage4.registers_read_write.eval.Rs2Ra", index: 2, oracle: "Rs2Ra" }, + Stage4SumcheckEvalPlan { symbol: "stage4.registers_read_write.eval.RdWa", source: "stage4.sumcheck", name: "stage4.registers_read_write.eval.RdWa", index: 3, oracle: "RdWa" }, + Stage4SumcheckEvalPlan { symbol: "stage4.registers_read_write.eval.RdInc", source: "stage4.sumcheck", name: "stage4.registers_read_write.eval.RdInc", index: 4, oracle: "RdInc" }, + Stage4SumcheckEvalPlan { symbol: "stage4.ram_val_check.eval.RamRa", source: "stage4.sumcheck", name: "stage4.ram_val_check.eval.RamRa", index: 0, oracle: "RamRa" }, + Stage4SumcheckEvalPlan { symbol: "stage4.ram_val_check.eval.RamInc", source: "stage4.sumcheck", name: "stage4.ram_val_check.eval.RamInc", index: 1, oracle: "RamInc" }, +]; + +pub const STAGE4_POINT_SLICES: &[Stage4PointSlicePlan] = &[ + Stage4PointSlicePlan { symbol: "stage4.registers_read_write.point.RdInc", source: "stage4.registers_read_write.instance", offset: 7, length: 16, input: "stage4.registers_read_write.instance" }, + Stage4PointSlicePlan { symbol: "stage4.ram_val_check.point.RamAddress", source: "stage4.input.stage2.RamVal", offset: 0, length: 16, input: "stage4.input.stage2.RamVal" }, +]; + +pub const STAGE4_POINT_CONCAT_0_INPUTS: &[&str] = &[ + "stage4.ram_val_check.point.RamAddress", + "stage4.ram_val_check.instance", +]; + +pub const STAGE4_POINT_CONCATS: &[Stage4PointConcatPlan] = &[ + Stage4PointConcatPlan { symbol: "stage4.ram_val_check.point.RamRa", layout: "address_then_cycle", arity: 32, inputs: STAGE4_POINT_CONCAT_0_INPUTS }, +]; +pub const STAGE4_OPENING_CLAIMS: &[Stage4OpeningClaimPlan] = &[ + Stage4OpeningClaimPlan { symbol: "stage4.registers_read_write.opening.RegistersVal", oracle: "RegistersVal", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual", point_source: "stage4.registers_read_write.instance", eval_source: "stage4.registers_read_write.eval.RegistersVal" }, + Stage4OpeningClaimPlan { symbol: "stage4.registers_read_write.opening.Rs1Ra", oracle: "Rs1Ra", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual", point_source: "stage4.registers_read_write.instance", eval_source: "stage4.registers_read_write.eval.Rs1Ra" }, + Stage4OpeningClaimPlan { symbol: "stage4.registers_read_write.opening.Rs2Ra", oracle: "Rs2Ra", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual", point_source: "stage4.registers_read_write.instance", eval_source: "stage4.registers_read_write.eval.Rs2Ra" }, + Stage4OpeningClaimPlan { symbol: "stage4.registers_read_write.opening.RdWa", oracle: "RdWa", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual", point_source: "stage4.registers_read_write.instance", eval_source: "stage4.registers_read_write.eval.RdWa" }, + Stage4OpeningClaimPlan { symbol: "stage4.registers_read_write.opening.RdInc", oracle: "RdInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed", point_source: "stage4.registers_read_write.point.RdInc", eval_source: "stage4.registers_read_write.eval.RdInc" }, + Stage4OpeningClaimPlan { symbol: "stage4.ram_val_check.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage4.ram_val_check.point.RamRa", eval_source: "stage4.ram_val_check.eval.RamRa" }, + Stage4OpeningClaimPlan { symbol: "stage4.ram_val_check.opening.RamInc", oracle: "RamInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed", point_source: "stage4.ram_val_check.instance", eval_source: "stage4.ram_val_check.eval.RamInc" }, +]; + +pub const STAGE4_OPENING_EQUALITIES: &[Stage4OpeningClaimEqualityPlan] = &[ + Stage4OpeningClaimEqualityPlan { symbol: "stage4.registers.rs1_claim_consistency", mode: "point_and_eval", lhs: "stage4.input.stage3.registers.Rs1Value", rhs: "stage4.input.stage3.instruction.Rs1Value" }, + Stage4OpeningClaimEqualityPlan { symbol: "stage4.registers.rs2_claim_consistency", mode: "point_and_eval", lhs: "stage4.input.stage3.registers.Rs2Value", rhs: "stage4.input.stage3.instruction.Rs2Value" }, +]; + +pub const STAGE4_OPENING_BATCH_0_ORDERED_CLAIMS: &[&str] = &[ + "stage4.registers_read_write.opening.RegistersVal", + "stage4.registers_read_write.opening.Rs1Ra", + "stage4.registers_read_write.opening.Rs2Ra", + "stage4.registers_read_write.opening.RdWa", + "stage4.registers_read_write.opening.RdInc", + "stage4.ram_val_check.opening.RamRa", + "stage4.ram_val_check.opening.RamInc", +]; + +pub const STAGE4_OPENING_BATCH_0_CLAIM_OPERANDS: &[&str] = &[ + "stage4.registers_read_write.opening.RegistersVal", + "stage4.registers_read_write.opening.Rs1Ra", + "stage4.registers_read_write.opening.Rs2Ra", + "stage4.registers_read_write.opening.RdWa", + "stage4.registers_read_write.opening.RdInc", + "stage4.ram_val_check.opening.RamRa", + "stage4.ram_val_check.opening.RamInc", +]; + +pub const STAGE4_OPENING_BATCHES: &[Stage4OpeningBatchPlan] = &[ + Stage4OpeningBatchPlan { symbol: "stage4.openings", stage: "stage4", proof_slot: "stage4.openings", policy: "jolt_stage4_output_order", count: 7, ordered_claims: STAGE4_OPENING_BATCH_0_ORDERED_CLAIMS, claim_operands: STAGE4_OPENING_BATCH_0_CLAIM_OPERANDS }, +]; +pub const STAGE4_PROGRAM: Stage4CpuProgramPlan = Stage4CpuProgramPlan { + role: "prover", + params: STAGE4_PARAMS, + steps: STAGE4_PROGRAM_STEPS, + transcript_squeezes: STAGE4_TRANSCRIPT_SQUEEZES, + transcript_absorb_bytes: STAGE4_TRANSCRIPT_ABSORB_BYTES, + opening_inputs: STAGE4_OPENING_INPUTS, + field_constants: STAGE4_FIELD_CONSTANTS, + field_exprs: STAGE4_FIELD_EXPRS, + kernels: STAGE4_KERNELS, + claims: STAGE4_SUMCHECK_CLAIMS, + batches: STAGE4_SUMCHECK_BATCHES, + drivers: STAGE4_SUMCHECK_DRIVERS, + instance_results: STAGE4_SUMCHECK_INSTANCE_RESULTS, + evals: STAGE4_SUMCHECK_EVALS, + point_slices: STAGE4_POINT_SLICES, + point_concats: STAGE4_POINT_CONCATS, + opening_claims: STAGE4_OPENING_CLAIMS, + opening_equalities: STAGE4_OPENING_EQUALITIES, + opening_batches: STAGE4_OPENING_BATCHES, +}; + +pub fn execute_stage4_prover( + executor: &mut E, + transcript: &mut T, +) -> Result, Stage4KernelError> +where + E: Stage4KernelExecutor, + T: Transcript, +{ + execute_stage4_prover_with_program(&STAGE4_PROGRAM, executor, transcript) +} + +pub fn execute_stage4_prover_with_program( + program: &'static Stage4CpuProgramPlan, + executor: &mut E, + transcript: &mut T, +) -> Result, Stage4KernelError> +where + E: Stage4KernelExecutor, + T: Transcript, +{ + execute_stage4_program(program, Stage4ExecutionMode::Prover, executor, transcript) +} diff --git a/crates/jolt-prover/src/stages/stage5.rs b/crates/jolt-prover/src/stages/stage5.rs new file mode 100644 index 0000000000..9febfac702 --- /dev/null +++ b/crates/jolt-prover/src/stages/stage5.rs @@ -0,0 +1,506 @@ +#![allow(dead_code)] + +use jolt_field::Fr; +use jolt_kernels::stage5::{execute_stage5_program, Stage5CpuProgramPlan, Stage5ExecutionArtifacts, Stage5ExecutionMode, Stage5FieldConstantPlan, Stage5FieldExprPlan, Stage5KernelError, Stage5KernelExecutor, Stage5KernelPlan, Stage5OpeningBatchPlan, Stage5OpeningClaimEqualityPlan, Stage5OpeningClaimPlan, Stage5OpeningInputPlan, Stage5Params, Stage5PointConcatPlan, Stage5PointSlicePlan, Stage5ProgramStepPlan, Stage5SumcheckBatchPlan, Stage5SumcheckClaimPlan, Stage5SumcheckDriverPlan, Stage5SumcheckEvalPlan, Stage5SumcheckInstanceResultPlan, Stage5TranscriptAbsorbBytesPlan, Stage5TranscriptSqueezePlan}; +use jolt_transcript::{Blake2bTranscript, Transcript}; + +pub type DefaultStage5Transcript = Blake2bTranscript; + +pub const STAGE5_PARAMS: Stage5Params = Stage5Params { + field: "bn254_fr", + pcs: "dory", + transcript: "blake2b_transcript", +}; +pub const STAGE5_PROGRAM_STEPS: &[Stage5ProgramStepPlan] = &[ + Stage5ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage5.instruction_read_raf.gamma" }, + Stage5ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage5.ram_ra_claim_reduction.gamma" }, + Stage5ProgramStepPlan { kind: "sumcheck_driver", symbol: "stage5.sumcheck" }, +]; + +pub const STAGE5_TRANSCRIPT_SQUEEZES: &[Stage5TranscriptSqueezePlan] = &[ + Stage5TranscriptSqueezePlan { symbol: "stage5.instruction_read_raf.gamma", label: "instruction_read_raf_gamma", kind: "challenge_scalar", count: 1 }, + Stage5TranscriptSqueezePlan { symbol: "stage5.ram_ra_claim_reduction.gamma", label: "ram_ra_claim_reduction_gamma", kind: "challenge_scalar", count: 1 }, +]; + +pub const STAGE5_TRANSCRIPT_ABSORB_BYTES: &[Stage5TranscriptAbsorbBytesPlan] = &[ + +]; + +pub const STAGE5_OPENING_INPUTS: &[Stage5OpeningInputPlan] = &[ + Stage5OpeningInputPlan { symbol: "stage5.input.stage2.instruction.LookupOutput", source_stage: "stage2", source_claim: "stage2.instruction_lookup.claim_reduction.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage5OpeningInputPlan { symbol: "stage5.input.stage2.product_virtual.LookupOutput", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage5OpeningInputPlan { symbol: "stage5.input.stage2.instruction.LeftLookupOperand", source_stage: "stage2", source_claim: "stage2.instruction_lookup.claim_reduction.opening.LeftLookupOperand", oracle: "LeftLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage5OpeningInputPlan { symbol: "stage5.input.stage2.instruction.RightLookupOperand", source_stage: "stage2", source_claim: "stage2.instruction_lookup.claim_reduction.opening.RightLookupOperand", oracle: "RightLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage5OpeningInputPlan { symbol: "stage5.input.stage2.ram_raf.RamRa", source_stage: "stage2", source_claim: "stage2.ram_raf.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual" }, + Stage5OpeningInputPlan { symbol: "stage5.input.stage2.ram_read_write.RamRa", source_stage: "stage2", source_claim: "stage2.ram_read_write.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual" }, + Stage5OpeningInputPlan { symbol: "stage5.input.stage4.ram_val_check.RamRa", source_stage: "stage4", source_claim: "stage4.ram_val_check.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual" }, + Stage5OpeningInputPlan { symbol: "stage5.input.stage4.registers.RegistersVal", source_stage: "stage4", source_claim: "stage4.registers_read_write.opening.RegistersVal", oracle: "RegistersVal", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual" }, +]; + +pub const STAGE5_FIELD_CONSTANTS: &[Stage5FieldConstantPlan] = &[ + +]; + +pub const STAGE5_FIELD_EXPR_OPERANDS_0: &[&str] = &["stage5.instruction_read_raf.gamma"]; + +pub const STAGE5_FIELD_EXPR_OPERANDS_1: &[&str] = &[ + "stage5.instruction_read_raf.gamma", + "stage5.input.stage2.instruction.LeftLookupOperand", +]; + +pub const STAGE5_FIELD_EXPR_OPERANDS_2: &[&str] = &[ + "stage5.instruction_read_raf.gamma2", + "stage5.input.stage2.instruction.RightLookupOperand", +]; + +pub const STAGE5_FIELD_EXPR_OPERANDS_3: &[&str] = &[ + "stage5.input.stage2.instruction.LookupOutput", + "stage5.instruction_read_raf.term.LeftLookupOperand", +]; + +pub const STAGE5_FIELD_EXPR_OPERANDS_4: &[&str] = &[ + "stage5.instruction_read_raf.partial.LookupOutputLeftOperand", + "stage5.instruction_read_raf.term.RightLookupOperand", +]; + +pub const STAGE5_FIELD_EXPR_OPERANDS_5: &[&str] = &["stage5.ram_ra_claim_reduction.gamma"]; + +pub const STAGE5_FIELD_EXPR_OPERANDS_6: &[&str] = &[ + "stage5.ram_ra_claim_reduction.gamma", + "stage5.input.stage2.ram_read_write.RamRa", +]; + +pub const STAGE5_FIELD_EXPR_OPERANDS_7: &[&str] = &[ + "stage5.ram_ra_claim_reduction.gamma2", + "stage5.input.stage4.ram_val_check.RamRa", +]; + +pub const STAGE5_FIELD_EXPR_OPERANDS_8: &[&str] = &[ + "stage5.input.stage2.ram_raf.RamRa", + "stage5.ram_ra_claim_reduction.term.RamRaReadWrite", +]; + +pub const STAGE5_FIELD_EXPR_OPERANDS_9: &[&str] = &[ + "stage5.ram_ra_claim_reduction.partial.RafReadWrite", + "stage5.ram_ra_claim_reduction.term.RamRaValCheck", +]; + +pub const STAGE5_FIELD_EXPRS: &[Stage5FieldExprPlan] = &[ + Stage5FieldExprPlan { symbol: "stage5.instruction_read_raf.gamma2", kind: "op", formula: "field.pow:2", operand_names: STAGE5_FIELD_EXPR_OPERANDS_0, operands: STAGE5_FIELD_EXPR_OPERANDS_0 }, + Stage5FieldExprPlan { symbol: "stage5.instruction_read_raf.term.LeftLookupOperand", kind: "op", formula: "field.mul", operand_names: STAGE5_FIELD_EXPR_OPERANDS_1, operands: STAGE5_FIELD_EXPR_OPERANDS_1 }, + Stage5FieldExprPlan { symbol: "stage5.instruction_read_raf.term.RightLookupOperand", kind: "op", formula: "field.mul", operand_names: STAGE5_FIELD_EXPR_OPERANDS_2, operands: STAGE5_FIELD_EXPR_OPERANDS_2 }, + Stage5FieldExprPlan { symbol: "stage5.instruction_read_raf.partial.LookupOutputLeftOperand", kind: "op", formula: "field.add", operand_names: STAGE5_FIELD_EXPR_OPERANDS_3, operands: STAGE5_FIELD_EXPR_OPERANDS_3 }, + Stage5FieldExprPlan { symbol: "stage5.instruction_read_raf.claim_expr", kind: "op", formula: "field.add", operand_names: STAGE5_FIELD_EXPR_OPERANDS_4, operands: STAGE5_FIELD_EXPR_OPERANDS_4 }, + Stage5FieldExprPlan { symbol: "stage5.ram_ra_claim_reduction.gamma2", kind: "op", formula: "field.pow:2", operand_names: STAGE5_FIELD_EXPR_OPERANDS_5, operands: STAGE5_FIELD_EXPR_OPERANDS_5 }, + Stage5FieldExprPlan { symbol: "stage5.ram_ra_claim_reduction.term.RamRaReadWrite", kind: "op", formula: "field.mul", operand_names: STAGE5_FIELD_EXPR_OPERANDS_6, operands: STAGE5_FIELD_EXPR_OPERANDS_6 }, + Stage5FieldExprPlan { symbol: "stage5.ram_ra_claim_reduction.term.RamRaValCheck", kind: "op", formula: "field.mul", operand_names: STAGE5_FIELD_EXPR_OPERANDS_7, operands: STAGE5_FIELD_EXPR_OPERANDS_7 }, + Stage5FieldExprPlan { symbol: "stage5.ram_ra_claim_reduction.partial.RafReadWrite", kind: "op", formula: "field.add", operand_names: STAGE5_FIELD_EXPR_OPERANDS_8, operands: STAGE5_FIELD_EXPR_OPERANDS_8 }, + Stage5FieldExprPlan { symbol: "stage5.ram_ra_claim_reduction.claim_expr", kind: "op", formula: "field.add", operand_names: STAGE5_FIELD_EXPR_OPERANDS_9, operands: STAGE5_FIELD_EXPR_OPERANDS_9 }, +]; +pub const STAGE5_KERNELS: &[Stage5KernelPlan] = &[ + Stage5KernelPlan { symbol: "jolt.cpu.stage5.instruction_read_raf", relation: "jolt.stage5.instruction_read_raf", kind: "sumcheck", backend: "cpu", abi: "jolt_stage5_instruction_read_raf" }, + Stage5KernelPlan { symbol: "jolt.cpu.stage5.ram_ra_claim_reduction", relation: "jolt.stage5.ram_ra_claim_reduction", kind: "sumcheck", backend: "cpu", abi: "jolt_stage5_ram_ra_claim_reduction" }, + Stage5KernelPlan { symbol: "jolt.cpu.stage5.registers_val_evaluation", relation: "jolt.stage5.registers_val_evaluation", kind: "sumcheck", backend: "cpu", abi: "jolt_stage5_registers_val_evaluation" }, + Stage5KernelPlan { symbol: "jolt.cpu.stage5.batched", relation: "jolt.stage5.batched", kind: "sumcheck", backend: "cpu", abi: "jolt_stage5_batched" }, +]; + +pub const STAGE5_SUMCHECK_CLAIM_0_INPUT_OPENINGS: &[&str] = &[ + "stage5.input.stage2.instruction.LookupOutput", + "stage5.input.stage2.instruction.LeftLookupOperand", + "stage5.input.stage2.instruction.RightLookupOperand", +]; + +pub const STAGE5_SUMCHECK_CLAIM_1_INPUT_OPENINGS: &[&str] = &[ + "stage5.input.stage2.ram_raf.RamRa", + "stage5.input.stage2.ram_read_write.RamRa", + "stage5.input.stage4.ram_val_check.RamRa", +]; + +pub const STAGE5_SUMCHECK_CLAIM_2_INPUT_OPENINGS: &[&str] = &["stage5.input.stage4.registers.RegistersVal"]; + +pub const STAGE5_SUMCHECK_CLAIMS: &[Stage5SumcheckClaimPlan] = &[ + Stage5SumcheckClaimPlan { symbol: "stage5.instruction_read_raf.input", stage: "stage5", domain: "jolt.stage5_instruction_read_raf_domain", num_rounds: 144, degree: 10, claim: "stage5.instruction_read_raf.weighted_lookup_values", kernel: Some("jolt.cpu.stage5.instruction_read_raf"), relation: None, claim_value: "stage5.instruction_read_raf.claim_expr", input_openings: STAGE5_SUMCHECK_CLAIM_0_INPUT_OPENINGS }, + Stage5SumcheckClaimPlan { symbol: "stage5.ram_ra_claim_reduction.input", stage: "stage5", domain: "jolt.trace_domain", num_rounds: 16, degree: 2, claim: "stage5.ram_ra_claim_reduction.weighted_ram_ra", kernel: Some("jolt.cpu.stage5.ram_ra_claim_reduction"), relation: None, claim_value: "stage5.ram_ra_claim_reduction.claim_expr", input_openings: STAGE5_SUMCHECK_CLAIM_1_INPUT_OPENINGS }, + Stage5SumcheckClaimPlan { symbol: "stage5.registers_val_evaluation.input", stage: "stage5", domain: "jolt.trace_domain", num_rounds: 16, degree: 3, claim: "stage5.registers_val_evaluation.registers_val", kernel: Some("jolt.cpu.stage5.registers_val_evaluation"), relation: None, claim_value: "stage5.input.stage4.registers.RegistersVal", input_openings: STAGE5_SUMCHECK_CLAIM_2_INPUT_OPENINGS }, +]; +pub const STAGE5_SUMCHECK_BATCH_0_ORDERED_CLAIMS: &[&str] = &[ + "stage5.instruction_read_raf.input", + "stage5.ram_ra_claim_reduction.input", + "stage5.registers_val_evaluation.input", +]; + +pub const STAGE5_SUMCHECK_BATCH_0_CLAIM_OPERANDS: &[&str] = &[ + "stage5.instruction_read_raf.input", + "stage5.ram_ra_claim_reduction.input", + "stage5.registers_val_evaluation.input", +]; + +pub const STAGE5_SUMCHECK_BATCH_0_ROUND_SCHEDULE: &[usize] = &[ + 128, + 16, +]; + +pub const STAGE5_SUMCHECK_BATCHES: &[Stage5SumcheckBatchPlan] = &[ + Stage5SumcheckBatchPlan { symbol: "stage5.batch", stage: "stage5", proof_slot: "stage5.sumcheck", policy: "jolt_core_stage5_aligned", count: 3, ordered_claims: STAGE5_SUMCHECK_BATCH_0_ORDERED_CLAIMS, claim_operands: STAGE5_SUMCHECK_BATCH_0_CLAIM_OPERANDS, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", round_schedule: STAGE5_SUMCHECK_BATCH_0_ROUND_SCHEDULE }, +]; +pub const STAGE5_SUMCHECK_DRIVER_0_ROUND_SCHEDULE: &[usize] = &[ + 128, + 16, +]; + +pub const STAGE5_SUMCHECK_DRIVERS: &[Stage5SumcheckDriverPlan] = &[ + Stage5SumcheckDriverPlan { symbol: "stage5.sumcheck", stage: "stage5", proof_slot: "stage5.sumcheck", kernel: Some("jolt.cpu.stage5.batched"), relation: None, batch: "stage5.batch", policy: "jolt_core_stage5_aligned", round_schedule: STAGE5_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 144, degree: 10 }, +]; +pub const STAGE5_SUMCHECK_INSTANCE_RESULTS: &[Stage5SumcheckInstanceResultPlan] = &[ + Stage5SumcheckInstanceResultPlan { symbol: "stage5.instruction_read_raf.instance", source: "stage5.sumcheck", claim: "stage5.instruction_read_raf.input", relation: "jolt.stage5.instruction_read_raf", index: 0, point_arity: 144, num_rounds: 144, round_offset: 0, point_order: "instruction_read_raf", degree: 10 }, + Stage5SumcheckInstanceResultPlan { symbol: "stage5.ram_ra_claim_reduction.instance", source: "stage5.sumcheck", claim: "stage5.ram_ra_claim_reduction.input", relation: "jolt.stage5.ram_ra_claim_reduction", index: 1, point_arity: 16, num_rounds: 16, round_offset: 128, point_order: "reverse", degree: 2 }, + Stage5SumcheckInstanceResultPlan { symbol: "stage5.registers_val_evaluation.instance", source: "stage5.sumcheck", claim: "stage5.registers_val_evaluation.input", relation: "jolt.stage5.registers_val_evaluation", index: 2, point_arity: 16, num_rounds: 16, round_offset: 128, point_order: "reverse", degree: 3 }, +]; + +pub const STAGE5_SUMCHECK_EVALS: &[Stage5SumcheckEvalPlan] = &[ + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_0", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_0", index: 0, oracle: "LookupTableFlag_0" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_1", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_1", index: 1, oracle: "LookupTableFlag_1" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_2", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_2", index: 2, oracle: "LookupTableFlag_2" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_3", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_3", index: 3, oracle: "LookupTableFlag_3" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_4", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_4", index: 4, oracle: "LookupTableFlag_4" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_5", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_5", index: 5, oracle: "LookupTableFlag_5" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_6", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_6", index: 6, oracle: "LookupTableFlag_6" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_7", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_7", index: 7, oracle: "LookupTableFlag_7" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_8", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_8", index: 8, oracle: "LookupTableFlag_8" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_9", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_9", index: 9, oracle: "LookupTableFlag_9" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_10", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_10", index: 10, oracle: "LookupTableFlag_10" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_11", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_11", index: 11, oracle: "LookupTableFlag_11" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_12", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_12", index: 12, oracle: "LookupTableFlag_12" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_13", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_13", index: 13, oracle: "LookupTableFlag_13" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_14", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_14", index: 14, oracle: "LookupTableFlag_14" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_15", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_15", index: 15, oracle: "LookupTableFlag_15" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_16", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_16", index: 16, oracle: "LookupTableFlag_16" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_17", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_17", index: 17, oracle: "LookupTableFlag_17" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_18", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_18", index: 18, oracle: "LookupTableFlag_18" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_19", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_19", index: 19, oracle: "LookupTableFlag_19" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_20", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_20", index: 20, oracle: "LookupTableFlag_20" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_21", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_21", index: 21, oracle: "LookupTableFlag_21" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_22", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_22", index: 22, oracle: "LookupTableFlag_22" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_23", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_23", index: 23, oracle: "LookupTableFlag_23" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_24", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_24", index: 24, oracle: "LookupTableFlag_24" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_25", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_25", index: 25, oracle: "LookupTableFlag_25" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_26", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_26", index: 26, oracle: "LookupTableFlag_26" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_27", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_27", index: 27, oracle: "LookupTableFlag_27" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_28", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_28", index: 28, oracle: "LookupTableFlag_28" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_29", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_29", index: 29, oracle: "LookupTableFlag_29" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_30", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_30", index: 30, oracle: "LookupTableFlag_30" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_31", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_31", index: 31, oracle: "LookupTableFlag_31" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_32", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_32", index: 32, oracle: "LookupTableFlag_32" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_33", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_33", index: 33, oracle: "LookupTableFlag_33" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_34", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_34", index: 34, oracle: "LookupTableFlag_34" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_35", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_35", index: 35, oracle: "LookupTableFlag_35" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_36", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_36", index: 36, oracle: "LookupTableFlag_36" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_37", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_37", index: 37, oracle: "LookupTableFlag_37" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_38", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_38", index: 38, oracle: "LookupTableFlag_38" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_39", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_39", index: 39, oracle: "LookupTableFlag_39" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.InstructionRa_0", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.InstructionRa_0", index: 40, oracle: "InstructionRa_0" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.InstructionRa_1", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.InstructionRa_1", index: 41, oracle: "InstructionRa_1" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.InstructionRa_2", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.InstructionRa_2", index: 42, oracle: "InstructionRa_2" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.InstructionRa_3", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.InstructionRa_3", index: 43, oracle: "InstructionRa_3" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.InstructionRa_4", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.InstructionRa_4", index: 44, oracle: "InstructionRa_4" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.InstructionRa_5", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.InstructionRa_5", index: 45, oracle: "InstructionRa_5" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.InstructionRa_6", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.InstructionRa_6", index: 46, oracle: "InstructionRa_6" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.InstructionRa_7", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.InstructionRa_7", index: 47, oracle: "InstructionRa_7" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.InstructionRafFlag", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.InstructionRafFlag", index: 48, oracle: "InstructionRafFlag" }, + Stage5SumcheckEvalPlan { symbol: "stage5.ram_ra_claim_reduction.eval.RamRa", source: "stage5.sumcheck", name: "stage5.ram_ra_claim_reduction.eval.RamRa", index: 0, oracle: "RamRa" }, + Stage5SumcheckEvalPlan { symbol: "stage5.registers_val_evaluation.eval.RdInc", source: "stage5.sumcheck", name: "stage5.registers_val_evaluation.eval.RdInc", index: 0, oracle: "RdInc" }, + Stage5SumcheckEvalPlan { symbol: "stage5.registers_val_evaluation.eval.RdWa", source: "stage5.sumcheck", name: "stage5.registers_val_evaluation.eval.RdWa", index: 1, oracle: "RdWa" }, +]; + +pub const STAGE5_POINT_SLICES: &[Stage5PointSlicePlan] = &[ + Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.Cycle", source: "stage5.instruction_read_raf.instance", offset: 128, length: 16, input: "stage5.instruction_read_raf.instance" }, + Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_0.address", source: "stage5.instruction_read_raf.instance", offset: 0, length: 16, input: "stage5.instruction_read_raf.instance" }, + Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_1.address", source: "stage5.instruction_read_raf.instance", offset: 16, length: 16, input: "stage5.instruction_read_raf.instance" }, + Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_2.address", source: "stage5.instruction_read_raf.instance", offset: 32, length: 16, input: "stage5.instruction_read_raf.instance" }, + Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_3.address", source: "stage5.instruction_read_raf.instance", offset: 48, length: 16, input: "stage5.instruction_read_raf.instance" }, + Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_4.address", source: "stage5.instruction_read_raf.instance", offset: 64, length: 16, input: "stage5.instruction_read_raf.instance" }, + Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_5.address", source: "stage5.instruction_read_raf.instance", offset: 80, length: 16, input: "stage5.instruction_read_raf.instance" }, + Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_6.address", source: "stage5.instruction_read_raf.instance", offset: 96, length: 16, input: "stage5.instruction_read_raf.instance" }, + Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_7.address", source: "stage5.instruction_read_raf.instance", offset: 112, length: 16, input: "stage5.instruction_read_raf.instance" }, + Stage5PointSlicePlan { symbol: "stage5.ram_ra_claim_reduction.point.RamAddress", source: "stage5.input.stage2.ram_raf.RamRa", offset: 0, length: 16, input: "stage5.input.stage2.ram_raf.RamRa" }, + Stage5PointSlicePlan { symbol: "stage5.registers_val_evaluation.point.RegisterAddress", source: "stage5.input.stage4.registers.RegistersVal", offset: 0, length: 7, input: "stage5.input.stage4.registers.RegistersVal" }, +]; + +pub const STAGE5_POINT_CONCAT_0_INPUTS: &[&str] = &[ + "stage5.instruction_read_raf.point.InstructionRa_0.address", + "stage5.instruction_read_raf.point.Cycle", +]; + +pub const STAGE5_POINT_CONCAT_1_INPUTS: &[&str] = &[ + "stage5.instruction_read_raf.point.InstructionRa_1.address", + "stage5.instruction_read_raf.point.Cycle", +]; + +pub const STAGE5_POINT_CONCAT_2_INPUTS: &[&str] = &[ + "stage5.instruction_read_raf.point.InstructionRa_2.address", + "stage5.instruction_read_raf.point.Cycle", +]; + +pub const STAGE5_POINT_CONCAT_3_INPUTS: &[&str] = &[ + "stage5.instruction_read_raf.point.InstructionRa_3.address", + "stage5.instruction_read_raf.point.Cycle", +]; + +pub const STAGE5_POINT_CONCAT_4_INPUTS: &[&str] = &[ + "stage5.instruction_read_raf.point.InstructionRa_4.address", + "stage5.instruction_read_raf.point.Cycle", +]; + +pub const STAGE5_POINT_CONCAT_5_INPUTS: &[&str] = &[ + "stage5.instruction_read_raf.point.InstructionRa_5.address", + "stage5.instruction_read_raf.point.Cycle", +]; + +pub const STAGE5_POINT_CONCAT_6_INPUTS: &[&str] = &[ + "stage5.instruction_read_raf.point.InstructionRa_6.address", + "stage5.instruction_read_raf.point.Cycle", +]; + +pub const STAGE5_POINT_CONCAT_7_INPUTS: &[&str] = &[ + "stage5.instruction_read_raf.point.InstructionRa_7.address", + "stage5.instruction_read_raf.point.Cycle", +]; + +pub const STAGE5_POINT_CONCAT_8_INPUTS: &[&str] = &[ + "stage5.ram_ra_claim_reduction.point.RamAddress", + "stage5.ram_ra_claim_reduction.instance", +]; + +pub const STAGE5_POINT_CONCAT_9_INPUTS: &[&str] = &[ + "stage5.registers_val_evaluation.point.RegisterAddress", + "stage5.registers_val_evaluation.instance", +]; + +pub const STAGE5_POINT_CONCATS: &[Stage5PointConcatPlan] = &[ + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_0", layout: "address_chunk_then_cycle", arity: 32, inputs: STAGE5_POINT_CONCAT_0_INPUTS }, + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_1", layout: "address_chunk_then_cycle", arity: 32, inputs: STAGE5_POINT_CONCAT_1_INPUTS }, + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_2", layout: "address_chunk_then_cycle", arity: 32, inputs: STAGE5_POINT_CONCAT_2_INPUTS }, + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_3", layout: "address_chunk_then_cycle", arity: 32, inputs: STAGE5_POINT_CONCAT_3_INPUTS }, + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_4", layout: "address_chunk_then_cycle", arity: 32, inputs: STAGE5_POINT_CONCAT_4_INPUTS }, + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_5", layout: "address_chunk_then_cycle", arity: 32, inputs: STAGE5_POINT_CONCAT_5_INPUTS }, + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_6", layout: "address_chunk_then_cycle", arity: 32, inputs: STAGE5_POINT_CONCAT_6_INPUTS }, + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_7", layout: "address_chunk_then_cycle", arity: 32, inputs: STAGE5_POINT_CONCAT_7_INPUTS }, + Stage5PointConcatPlan { symbol: "stage5.ram_ra_claim_reduction.point.RamRa", layout: "address_then_cycle", arity: 32, inputs: STAGE5_POINT_CONCAT_8_INPUTS }, + Stage5PointConcatPlan { symbol: "stage5.registers_val_evaluation.point.RdWa", layout: "register_address_then_cycle", arity: 23, inputs: STAGE5_POINT_CONCAT_9_INPUTS }, +]; +pub const STAGE5_OPENING_CLAIMS: &[Stage5OpeningClaimPlan] = &[ + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_0", oracle: "LookupTableFlag_0", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_0" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_1", oracle: "LookupTableFlag_1", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_1" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_2", oracle: "LookupTableFlag_2", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_2" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_3", oracle: "LookupTableFlag_3", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_3" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_4", oracle: "LookupTableFlag_4", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_4" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_5", oracle: "LookupTableFlag_5", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_5" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_6", oracle: "LookupTableFlag_6", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_6" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_7", oracle: "LookupTableFlag_7", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_7" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_8", oracle: "LookupTableFlag_8", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_8" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_9", oracle: "LookupTableFlag_9", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_9" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_10", oracle: "LookupTableFlag_10", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_10" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_11", oracle: "LookupTableFlag_11", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_11" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_12", oracle: "LookupTableFlag_12", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_12" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_13", oracle: "LookupTableFlag_13", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_13" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_14", oracle: "LookupTableFlag_14", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_14" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_15", oracle: "LookupTableFlag_15", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_15" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_16", oracle: "LookupTableFlag_16", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_16" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_17", oracle: "LookupTableFlag_17", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_17" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_18", oracle: "LookupTableFlag_18", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_18" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_19", oracle: "LookupTableFlag_19", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_19" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_20", oracle: "LookupTableFlag_20", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_20" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_21", oracle: "LookupTableFlag_21", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_21" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_22", oracle: "LookupTableFlag_22", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_22" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_23", oracle: "LookupTableFlag_23", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_23" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_24", oracle: "LookupTableFlag_24", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_24" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_25", oracle: "LookupTableFlag_25", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_25" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_26", oracle: "LookupTableFlag_26", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_26" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_27", oracle: "LookupTableFlag_27", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_27" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_28", oracle: "LookupTableFlag_28", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_28" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_29", oracle: "LookupTableFlag_29", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_29" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_30", oracle: "LookupTableFlag_30", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_30" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_31", oracle: "LookupTableFlag_31", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_31" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_32", oracle: "LookupTableFlag_32", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_32" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_33", oracle: "LookupTableFlag_33", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_33" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_34", oracle: "LookupTableFlag_34", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_34" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_35", oracle: "LookupTableFlag_35", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_35" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_36", oracle: "LookupTableFlag_36", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_36" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_37", oracle: "LookupTableFlag_37", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_37" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_38", oracle: "LookupTableFlag_38", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_38" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_39", oracle: "LookupTableFlag_39", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_39" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_0", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_0" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_1", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_1" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_2", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_2" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_3", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_3" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_4", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_4" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_5", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_5" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_6", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_6" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_7", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_7" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRafFlag", oracle: "InstructionRafFlag", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.InstructionRafFlag" }, + Stage5OpeningClaimPlan { symbol: "stage5.ram_ra_claim_reduction.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.ram_ra_claim_reduction.point.RamRa", eval_source: "stage5.ram_ra_claim_reduction.eval.RamRa" }, + Stage5OpeningClaimPlan { symbol: "stage5.registers_val_evaluation.opening.RdInc", oracle: "RdInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed", point_source: "stage5.registers_val_evaluation.instance", eval_source: "stage5.registers_val_evaluation.eval.RdInc" }, + Stage5OpeningClaimPlan { symbol: "stage5.registers_val_evaluation.opening.RdWa", oracle: "RdWa", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual", point_source: "stage5.registers_val_evaluation.point.RdWa", eval_source: "stage5.registers_val_evaluation.eval.RdWa" }, +]; + +pub const STAGE5_OPENING_EQUALITIES: &[Stage5OpeningClaimEqualityPlan] = &[ + Stage5OpeningClaimEqualityPlan { symbol: "stage5.instruction.lookup_output_claim_consistency", mode: "point_and_eval", lhs: "stage5.input.stage2.instruction.LookupOutput", rhs: "stage5.input.stage2.product_virtual.LookupOutput" }, +]; + +pub const STAGE5_OPENING_BATCH_0_ORDERED_CLAIMS: &[&str] = &[ + "stage5.instruction_read_raf.opening.LookupTableFlag_0", + "stage5.instruction_read_raf.opening.LookupTableFlag_1", + "stage5.instruction_read_raf.opening.LookupTableFlag_2", + "stage5.instruction_read_raf.opening.LookupTableFlag_3", + "stage5.instruction_read_raf.opening.LookupTableFlag_4", + "stage5.instruction_read_raf.opening.LookupTableFlag_5", + "stage5.instruction_read_raf.opening.LookupTableFlag_6", + "stage5.instruction_read_raf.opening.LookupTableFlag_7", + "stage5.instruction_read_raf.opening.LookupTableFlag_8", + "stage5.instruction_read_raf.opening.LookupTableFlag_9", + "stage5.instruction_read_raf.opening.LookupTableFlag_10", + "stage5.instruction_read_raf.opening.LookupTableFlag_11", + "stage5.instruction_read_raf.opening.LookupTableFlag_12", + "stage5.instruction_read_raf.opening.LookupTableFlag_13", + "stage5.instruction_read_raf.opening.LookupTableFlag_14", + "stage5.instruction_read_raf.opening.LookupTableFlag_15", + "stage5.instruction_read_raf.opening.LookupTableFlag_16", + "stage5.instruction_read_raf.opening.LookupTableFlag_17", + "stage5.instruction_read_raf.opening.LookupTableFlag_18", + "stage5.instruction_read_raf.opening.LookupTableFlag_19", + "stage5.instruction_read_raf.opening.LookupTableFlag_20", + "stage5.instruction_read_raf.opening.LookupTableFlag_21", + "stage5.instruction_read_raf.opening.LookupTableFlag_22", + "stage5.instruction_read_raf.opening.LookupTableFlag_23", + "stage5.instruction_read_raf.opening.LookupTableFlag_24", + "stage5.instruction_read_raf.opening.LookupTableFlag_25", + "stage5.instruction_read_raf.opening.LookupTableFlag_26", + "stage5.instruction_read_raf.opening.LookupTableFlag_27", + "stage5.instruction_read_raf.opening.LookupTableFlag_28", + "stage5.instruction_read_raf.opening.LookupTableFlag_29", + "stage5.instruction_read_raf.opening.LookupTableFlag_30", + "stage5.instruction_read_raf.opening.LookupTableFlag_31", + "stage5.instruction_read_raf.opening.LookupTableFlag_32", + "stage5.instruction_read_raf.opening.LookupTableFlag_33", + "stage5.instruction_read_raf.opening.LookupTableFlag_34", + "stage5.instruction_read_raf.opening.LookupTableFlag_35", + "stage5.instruction_read_raf.opening.LookupTableFlag_36", + "stage5.instruction_read_raf.opening.LookupTableFlag_37", + "stage5.instruction_read_raf.opening.LookupTableFlag_38", + "stage5.instruction_read_raf.opening.LookupTableFlag_39", + "stage5.instruction_read_raf.opening.InstructionRa_0", + "stage5.instruction_read_raf.opening.InstructionRa_1", + "stage5.instruction_read_raf.opening.InstructionRa_2", + "stage5.instruction_read_raf.opening.InstructionRa_3", + "stage5.instruction_read_raf.opening.InstructionRa_4", + "stage5.instruction_read_raf.opening.InstructionRa_5", + "stage5.instruction_read_raf.opening.InstructionRa_6", + "stage5.instruction_read_raf.opening.InstructionRa_7", + "stage5.instruction_read_raf.opening.InstructionRafFlag", + "stage5.ram_ra_claim_reduction.opening.RamRa", + "stage5.registers_val_evaluation.opening.RdInc", + "stage5.registers_val_evaluation.opening.RdWa", +]; + +pub const STAGE5_OPENING_BATCH_0_CLAIM_OPERANDS: &[&str] = &[ + "stage5.instruction_read_raf.opening.LookupTableFlag_0", + "stage5.instruction_read_raf.opening.LookupTableFlag_1", + "stage5.instruction_read_raf.opening.LookupTableFlag_2", + "stage5.instruction_read_raf.opening.LookupTableFlag_3", + "stage5.instruction_read_raf.opening.LookupTableFlag_4", + "stage5.instruction_read_raf.opening.LookupTableFlag_5", + "stage5.instruction_read_raf.opening.LookupTableFlag_6", + "stage5.instruction_read_raf.opening.LookupTableFlag_7", + "stage5.instruction_read_raf.opening.LookupTableFlag_8", + "stage5.instruction_read_raf.opening.LookupTableFlag_9", + "stage5.instruction_read_raf.opening.LookupTableFlag_10", + "stage5.instruction_read_raf.opening.LookupTableFlag_11", + "stage5.instruction_read_raf.opening.LookupTableFlag_12", + "stage5.instruction_read_raf.opening.LookupTableFlag_13", + "stage5.instruction_read_raf.opening.LookupTableFlag_14", + "stage5.instruction_read_raf.opening.LookupTableFlag_15", + "stage5.instruction_read_raf.opening.LookupTableFlag_16", + "stage5.instruction_read_raf.opening.LookupTableFlag_17", + "stage5.instruction_read_raf.opening.LookupTableFlag_18", + "stage5.instruction_read_raf.opening.LookupTableFlag_19", + "stage5.instruction_read_raf.opening.LookupTableFlag_20", + "stage5.instruction_read_raf.opening.LookupTableFlag_21", + "stage5.instruction_read_raf.opening.LookupTableFlag_22", + "stage5.instruction_read_raf.opening.LookupTableFlag_23", + "stage5.instruction_read_raf.opening.LookupTableFlag_24", + "stage5.instruction_read_raf.opening.LookupTableFlag_25", + "stage5.instruction_read_raf.opening.LookupTableFlag_26", + "stage5.instruction_read_raf.opening.LookupTableFlag_27", + "stage5.instruction_read_raf.opening.LookupTableFlag_28", + "stage5.instruction_read_raf.opening.LookupTableFlag_29", + "stage5.instruction_read_raf.opening.LookupTableFlag_30", + "stage5.instruction_read_raf.opening.LookupTableFlag_31", + "stage5.instruction_read_raf.opening.LookupTableFlag_32", + "stage5.instruction_read_raf.opening.LookupTableFlag_33", + "stage5.instruction_read_raf.opening.LookupTableFlag_34", + "stage5.instruction_read_raf.opening.LookupTableFlag_35", + "stage5.instruction_read_raf.opening.LookupTableFlag_36", + "stage5.instruction_read_raf.opening.LookupTableFlag_37", + "stage5.instruction_read_raf.opening.LookupTableFlag_38", + "stage5.instruction_read_raf.opening.LookupTableFlag_39", + "stage5.instruction_read_raf.opening.InstructionRa_0", + "stage5.instruction_read_raf.opening.InstructionRa_1", + "stage5.instruction_read_raf.opening.InstructionRa_2", + "stage5.instruction_read_raf.opening.InstructionRa_3", + "stage5.instruction_read_raf.opening.InstructionRa_4", + "stage5.instruction_read_raf.opening.InstructionRa_5", + "stage5.instruction_read_raf.opening.InstructionRa_6", + "stage5.instruction_read_raf.opening.InstructionRa_7", + "stage5.instruction_read_raf.opening.InstructionRafFlag", + "stage5.ram_ra_claim_reduction.opening.RamRa", + "stage5.registers_val_evaluation.opening.RdInc", + "stage5.registers_val_evaluation.opening.RdWa", +]; + +pub const STAGE5_OPENING_BATCHES: &[Stage5OpeningBatchPlan] = &[ + Stage5OpeningBatchPlan { symbol: "stage5.openings", stage: "stage5", proof_slot: "stage5.openings", policy: "jolt_stage5_output_order", count: 52, ordered_claims: STAGE5_OPENING_BATCH_0_ORDERED_CLAIMS, claim_operands: STAGE5_OPENING_BATCH_0_CLAIM_OPERANDS }, +]; +pub const STAGE5_PROGRAM: Stage5CpuProgramPlan = Stage5CpuProgramPlan { + role: "prover", + params: STAGE5_PARAMS, + steps: STAGE5_PROGRAM_STEPS, + transcript_squeezes: STAGE5_TRANSCRIPT_SQUEEZES, + transcript_absorb_bytes: STAGE5_TRANSCRIPT_ABSORB_BYTES, + opening_inputs: STAGE5_OPENING_INPUTS, + field_constants: STAGE5_FIELD_CONSTANTS, + field_exprs: STAGE5_FIELD_EXPRS, + kernels: STAGE5_KERNELS, + claims: STAGE5_SUMCHECK_CLAIMS, + batches: STAGE5_SUMCHECK_BATCHES, + drivers: STAGE5_SUMCHECK_DRIVERS, + instance_results: STAGE5_SUMCHECK_INSTANCE_RESULTS, + evals: STAGE5_SUMCHECK_EVALS, + point_slices: STAGE5_POINT_SLICES, + point_concats: STAGE5_POINT_CONCATS, + opening_claims: STAGE5_OPENING_CLAIMS, + opening_equalities: STAGE5_OPENING_EQUALITIES, + opening_batches: STAGE5_OPENING_BATCHES, +}; + +pub fn execute_stage5_prover( + executor: &mut E, + transcript: &mut T, +) -> Result, Stage5KernelError> +where + E: Stage5KernelExecutor, + T: Transcript, +{ + execute_stage5_prover_with_program(&STAGE5_PROGRAM, executor, transcript) +} + +pub fn execute_stage5_prover_with_program( + program: &'static Stage5CpuProgramPlan, + executor: &mut E, + transcript: &mut T, +) -> Result, Stage5KernelError> +where + E: Stage5KernelExecutor, + T: Transcript, +{ + execute_stage5_program(program, Stage5ExecutionMode::Prover, executor, transcript) +} diff --git a/crates/jolt-prover/src/stages/stage6.rs b/crates/jolt-prover/src/stages/stage6.rs new file mode 100644 index 0000000000..bf0d368c7b --- /dev/null +++ b/crates/jolt-prover/src/stages/stage6.rs @@ -0,0 +1,2515 @@ +#![allow(dead_code)] + +use jolt_field::Fr; +use jolt_kernels::stage6::{execute_stage6_program, Stage6CpuProgramPlan, Stage6ExecutionArtifacts, Stage6ExecutionMode, Stage6FieldConstantPlan, Stage6FieldExprPlan, Stage6KernelError, Stage6KernelExecutor, Stage6KernelPlan, Stage6OpeningBatchPlan, Stage6OpeningClaimEqualityPlan, Stage6OpeningClaimPlan, Stage6OpeningInputPlan, Stage6Params, Stage6PointConcatPlan, Stage6PointSlicePlan, Stage6PointZeroPlan, Stage6ProgramStepPlan, Stage6SumcheckBatchPlan, Stage6SumcheckClaimPlan, Stage6SumcheckDriverPlan, Stage6SumcheckEvalPlan, Stage6SumcheckInstanceResultPlan, Stage6TranscriptAbsorbBytesPlan, Stage6TranscriptSqueezePlan}; +use jolt_transcript::{Blake2bTranscript, Transcript}; + +pub type DefaultStage6Transcript = Blake2bTranscript; + +pub const STAGE6_PARAMS: Stage6Params = Stage6Params { + field: "bn254_fr", + pcs: "dory", + transcript: "blake2b_transcript", +}; +pub const STAGE6_PROGRAM_STEPS: &[Stage6ProgramStepPlan] = &[ + Stage6ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage6.bytecode_read_raf.gamma" }, + Stage6ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage6.bytecode_read_raf.stage1_gamma" }, + Stage6ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage6.bytecode_read_raf.stage2_gamma" }, + Stage6ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage6.bytecode_read_raf.stage3_gamma" }, + Stage6ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage6.bytecode_read_raf.stage4_gamma" }, + Stage6ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage6.bytecode_read_raf.stage5_gamma" }, + Stage6ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage6.booleanity.gamma" }, + Stage6ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage6.instruction_ra_virtual.gamma" }, + Stage6ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage6.inc_claim_reduction.gamma" }, + Stage6ProgramStepPlan { kind: "sumcheck_driver", symbol: "stage6.sumcheck" }, +]; + +pub const STAGE6_TRANSCRIPT_SQUEEZES: &[Stage6TranscriptSqueezePlan] = &[ + Stage6TranscriptSqueezePlan { symbol: "stage6.bytecode_read_raf.gamma", label: "bc_raf_gamma", kind: "challenge_scalar", count: 1 }, + Stage6TranscriptSqueezePlan { symbol: "stage6.bytecode_read_raf.stage1_gamma", label: "bc_raf_stage1_gamma", kind: "challenge_scalar", count: 1 }, + Stage6TranscriptSqueezePlan { symbol: "stage6.bytecode_read_raf.stage2_gamma", label: "bc_raf_stage2_gamma", kind: "challenge_scalar", count: 1 }, + Stage6TranscriptSqueezePlan { symbol: "stage6.bytecode_read_raf.stage3_gamma", label: "bc_raf_stage3_gamma", kind: "challenge_scalar", count: 1 }, + Stage6TranscriptSqueezePlan { symbol: "stage6.bytecode_read_raf.stage4_gamma", label: "bc_raf_stage4_gamma", kind: "challenge_scalar", count: 1 }, + Stage6TranscriptSqueezePlan { symbol: "stage6.bytecode_read_raf.stage5_gamma", label: "bc_raf_stage5_gamma", kind: "challenge_scalar", count: 1 }, + Stage6TranscriptSqueezePlan { symbol: "stage6.booleanity.gamma", label: "booleanity_gamma", kind: "challenge_scalar", count: 1 }, + Stage6TranscriptSqueezePlan { symbol: "stage6.instruction_ra_virtual.gamma", label: "inst_ra_virtual_gamma", kind: "challenge_scalar", count: 1 }, + Stage6TranscriptSqueezePlan { symbol: "stage6.inc_claim_reduction.gamma", label: "inc_reduction_gamma", kind: "challenge_scalar", count: 1 }, +]; + +pub const STAGE6_TRANSCRIPT_ABSORB_BYTES: &[Stage6TranscriptAbsorbBytesPlan] = &[ + +]; + +pub const STAGE6_OPENING_INPUTS: &[Stage6OpeningInputPlan] = &[ + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.UnexpandedPC", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.UnexpandedPC", oracle: "UnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.Imm", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.Imm", oracle: "Imm", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagAddOperands", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagAddOperands", oracle: "OpFlagAddOperands", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagSubtractOperands", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagSubtractOperands", oracle: "OpFlagSubtractOperands", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagMultiplyOperands", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagMultiplyOperands", oracle: "OpFlagMultiplyOperands", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagLoad", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagLoad", oracle: "OpFlagLoad", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagStore", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagStore", oracle: "OpFlagStore", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagJump", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagJump", oracle: "OpFlagJump", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagWriteLookupOutputToRD", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagWriteLookupOutputToRD", oracle: "OpFlagWriteLookupOutputToRD", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagVirtualInstruction", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagAssert", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagAssert", oracle: "OpFlagAssert", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagDoNotUpdateUnexpandedPC", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagDoNotUpdateUnexpandedPC", oracle: "OpFlagDoNotUpdateUnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagAdvice", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagAdvice", oracle: "OpFlagAdvice", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagIsCompressed", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagIsCompressed", oracle: "OpFlagIsCompressed", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagIsFirstInSequence", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagIsFirstInSequence", oracle: "OpFlagIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagIsLastInSequence", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagIsLastInSequence", oracle: "OpFlagIsLastInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage2.OpFlagJump", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.OpFlagJump", oracle: "OpFlagJump", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage2.InstructionFlagBranch", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.InstructionFlagBranch", oracle: "InstructionFlagBranch", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage2.OpFlagWriteLookupOutputToRD", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.OpFlagWriteLookupOutputToRD", oracle: "OpFlagWriteLookupOutputToRD", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage2.OpFlagVirtualInstruction", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.instruction_input.Imm", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.Imm", oracle: "Imm", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.spartan_shift.UnexpandedPC", source_stage: "stage3", source_claim: "stage3.spartan_shift.opening.UnexpandedPC", oracle: "UnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.instruction_input.InstructionFlagLeftOperandIsRs1Value", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.InstructionFlagLeftOperandIsRs1Value", oracle: "InstructionFlagLeftOperandIsRs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.instruction_input.InstructionFlagLeftOperandIsPC", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.InstructionFlagLeftOperandIsPC", oracle: "InstructionFlagLeftOperandIsPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.instruction_input.InstructionFlagRightOperandIsRs2Value", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.InstructionFlagRightOperandIsRs2Value", oracle: "InstructionFlagRightOperandIsRs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.instruction_input.InstructionFlagRightOperandIsImm", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.InstructionFlagRightOperandIsImm", oracle: "InstructionFlagRightOperandIsImm", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.spartan_shift.InstructionFlagIsNoop", source_stage: "stage3", source_claim: "stage3.spartan_shift.opening.InstructionFlagIsNoop", oracle: "InstructionFlagIsNoop", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.spartan_shift.OpFlagVirtualInstruction", source_stage: "stage3", source_claim: "stage3.spartan_shift.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.spartan_shift.OpFlagIsFirstInSequence", source_stage: "stage3", source_claim: "stage3.spartan_shift.opening.OpFlagIsFirstInSequence", oracle: "OpFlagIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage4.RdWa", source_stage: "stage4", source_claim: "stage4.registers_read_write.opening.RdWa", oracle: "RdWa", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage4.Rs1Ra", source_stage: "stage4", source_claim: "stage4.registers_read_write.opening.Rs1Ra", oracle: "Rs1Ra", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage4.Rs2Ra", source_stage: "stage4", source_claim: "stage4.registers_read_write.opening.Rs2Ra", oracle: "Rs2Ra", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.registers_val_evaluation.RdWa", source_stage: "stage5", source_claim: "stage5.registers_val_evaluation.opening.RdWa", oracle: "RdWa", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.InstructionRafFlag", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRafFlag", oracle: "InstructionRafFlag", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_0", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_0", oracle: "LookupTableFlag_0", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_1", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_1", oracle: "LookupTableFlag_1", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_2", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_2", oracle: "LookupTableFlag_2", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_3", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_3", oracle: "LookupTableFlag_3", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_4", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_4", oracle: "LookupTableFlag_4", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_5", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_5", oracle: "LookupTableFlag_5", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_6", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_6", oracle: "LookupTableFlag_6", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_7", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_7", oracle: "LookupTableFlag_7", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_8", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_8", oracle: "LookupTableFlag_8", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_9", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_9", oracle: "LookupTableFlag_9", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_10", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_10", oracle: "LookupTableFlag_10", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_11", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_11", oracle: "LookupTableFlag_11", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_12", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_12", oracle: "LookupTableFlag_12", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_13", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_13", oracle: "LookupTableFlag_13", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_14", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_14", oracle: "LookupTableFlag_14", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_15", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_15", oracle: "LookupTableFlag_15", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_16", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_16", oracle: "LookupTableFlag_16", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_17", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_17", oracle: "LookupTableFlag_17", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_18", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_18", oracle: "LookupTableFlag_18", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_19", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_19", oracle: "LookupTableFlag_19", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_20", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_20", oracle: "LookupTableFlag_20", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_21", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_21", oracle: "LookupTableFlag_21", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_22", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_22", oracle: "LookupTableFlag_22", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_23", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_23", oracle: "LookupTableFlag_23", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_24", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_24", oracle: "LookupTableFlag_24", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_25", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_25", oracle: "LookupTableFlag_25", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_26", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_26", oracle: "LookupTableFlag_26", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_27", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_27", oracle: "LookupTableFlag_27", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_28", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_28", oracle: "LookupTableFlag_28", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_29", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_29", oracle: "LookupTableFlag_29", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_30", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_30", oracle: "LookupTableFlag_30", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_31", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_31", oracle: "LookupTableFlag_31", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_32", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_32", oracle: "LookupTableFlag_32", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_33", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_33", oracle: "LookupTableFlag_33", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_34", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_34", oracle: "LookupTableFlag_34", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_35", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_35", oracle: "LookupTableFlag_35", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_36", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_36", oracle: "LookupTableFlag_36", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_37", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_37", oracle: "LookupTableFlag_37", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_38", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_38", oracle: "LookupTableFlag_38", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_39", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_39", oracle: "LookupTableFlag_39", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.PC", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.PC", oracle: "PC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.spartan_shift.PC", source_stage: "stage3", source_claim: "stage3.spartan_shift.opening.PC", oracle: "PC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", source_stage: "stage5", source_claim: "stage5.ram_ra_claim_reduction.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_1", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_2", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_3", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_4", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_5", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_6", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_7", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.LookupOutput", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage2.ram_read_write.RamInc", source_stage: "stage2", source_claim: "stage2.ram_read_write.opening.RamInc", oracle: "RamInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage4.ram_val_check.RamInc", source_stage: "stage4", source_claim: "stage4.ram_val_check.opening.RamInc", oracle: "RamInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage4.registers_read_write.RdInc", source_stage: "stage4", source_claim: "stage4.registers_read_write.opening.RdInc", oracle: "RdInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.registers_val_evaluation.RdInc", source_stage: "stage5", source_claim: "stage5.registers_val_evaluation.opening.RdInc", oracle: "RdInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed" }, +]; + +pub const STAGE6_FIELD_CONSTANTS: &[Stage6FieldConstantPlan] = &[ + Stage6FieldConstantPlan { symbol: "stage6.zero", field: "bn254_fr", value: 0 }, +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_0: &[&str] = &["stage6.booleanity.gamma"]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_1: &[&str] = &["stage6.bytecode_read_raf.stage1_gamma"]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_2: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term1.stage_gamma_pow", + "stage6.input.stage1.Imm", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_3: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term2.stage_gamma_pow", + "stage6.input.stage1.OpFlagAddOperands", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_4: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term3.stage_gamma_pow", + "stage6.input.stage1.OpFlagSubtractOperands", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_5: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term4.stage_gamma_pow", + "stage6.input.stage1.OpFlagMultiplyOperands", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_6: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term5.stage_gamma_pow", + "stage6.input.stage1.OpFlagLoad", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_7: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term6.stage_gamma_pow", + "stage6.input.stage1.OpFlagStore", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_8: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term7.stage_gamma_pow", + "stage6.input.stage1.OpFlagJump", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_9: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term8.stage_gamma_pow", + "stage6.input.stage1.OpFlagWriteLookupOutputToRD", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_10: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term9.stage_gamma_pow", + "stage6.input.stage1.OpFlagVirtualInstruction", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_11: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term10.stage_gamma_pow", + "stage6.input.stage1.OpFlagAssert", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_12: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term11.stage_gamma_pow", + "stage6.input.stage1.OpFlagDoNotUpdateUnexpandedPC", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_13: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term12.stage_gamma_pow", + "stage6.input.stage1.OpFlagAdvice", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_14: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term13.stage_gamma_pow", + "stage6.input.stage1.OpFlagIsCompressed", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_15: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term14.stage_gamma_pow", + "stage6.input.stage1.OpFlagIsFirstInSequence", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_16: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term15.stage_gamma_pow", + "stage6.input.stage1.OpFlagIsLastInSequence", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_17: &[&str] = &["stage6.bytecode_read_raf.gamma"]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_18: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term16.gamma_pow", + "stage6.input.stage2.OpFlagJump", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_19: &[&str] = &["stage6.bytecode_read_raf.stage2_gamma"]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_20: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term17.stage_gamma_pow", + "stage6.input.stage2.InstructionFlagBranch", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_21: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term17.gamma_pow", + "stage6.bytecode_read_raf.claim.term17.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_22: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term18.stage_gamma_pow", + "stage6.input.stage2.OpFlagWriteLookupOutputToRD", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_23: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term18.gamma_pow", + "stage6.bytecode_read_raf.claim.term18.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_24: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term19.stage_gamma_pow", + "stage6.input.stage2.OpFlagVirtualInstruction", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_25: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term19.gamma_pow", + "stage6.bytecode_read_raf.claim.term19.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_26: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term20.gamma_pow", + "stage6.input.stage3.instruction_input.Imm", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_27: &[&str] = &["stage6.bytecode_read_raf.stage3_gamma"]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_28: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term21.stage_gamma_pow", + "stage6.input.stage3.spartan_shift.UnexpandedPC", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_29: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term21.gamma_pow", + "stage6.bytecode_read_raf.claim.term21.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_30: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term22.stage_gamma_pow", + "stage6.input.stage3.instruction_input.InstructionFlagLeftOperandIsRs1Value", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_31: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term22.gamma_pow", + "stage6.bytecode_read_raf.claim.term22.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_32: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term23.stage_gamma_pow", + "stage6.input.stage3.instruction_input.InstructionFlagLeftOperandIsPC", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_33: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term23.gamma_pow", + "stage6.bytecode_read_raf.claim.term23.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_34: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term24.stage_gamma_pow", + "stage6.input.stage3.instruction_input.InstructionFlagRightOperandIsRs2Value", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_35: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term24.gamma_pow", + "stage6.bytecode_read_raf.claim.term24.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_36: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term25.stage_gamma_pow", + "stage6.input.stage3.instruction_input.InstructionFlagRightOperandIsImm", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_37: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term25.gamma_pow", + "stage6.bytecode_read_raf.claim.term25.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_38: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term26.stage_gamma_pow", + "stage6.input.stage3.spartan_shift.InstructionFlagIsNoop", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_39: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term26.gamma_pow", + "stage6.bytecode_read_raf.claim.term26.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_40: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term27.stage_gamma_pow", + "stage6.input.stage3.spartan_shift.OpFlagVirtualInstruction", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_41: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term27.gamma_pow", + "stage6.bytecode_read_raf.claim.term27.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_42: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term28.stage_gamma_pow", + "stage6.input.stage3.spartan_shift.OpFlagIsFirstInSequence", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_43: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term28.gamma_pow", + "stage6.bytecode_read_raf.claim.term28.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_44: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term29.gamma_pow", + "stage6.input.stage4.RdWa", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_45: &[&str] = &["stage6.bytecode_read_raf.stage4_gamma"]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_46: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term30.stage_gamma_pow", + "stage6.input.stage4.Rs1Ra", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_47: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term30.gamma_pow", + "stage6.bytecode_read_raf.claim.term30.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_48: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term31.stage_gamma_pow", + "stage6.input.stage4.Rs2Ra", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_49: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term31.gamma_pow", + "stage6.bytecode_read_raf.claim.term31.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_50: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term32.gamma_pow", + "stage6.input.stage5.registers_val_evaluation.RdWa", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_51: &[&str] = &["stage6.bytecode_read_raf.stage5_gamma"]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_52: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term33.stage_gamma_pow", + "stage6.input.stage5.InstructionRafFlag", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_53: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term33.gamma_pow", + "stage6.bytecode_read_raf.claim.term33.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_54: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term34.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_0", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_55: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term34.gamma_pow", + "stage6.bytecode_read_raf.claim.term34.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_56: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term35.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_1", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_57: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term35.gamma_pow", + "stage6.bytecode_read_raf.claim.term35.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_58: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term36.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_2", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_59: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term36.gamma_pow", + "stage6.bytecode_read_raf.claim.term36.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_60: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term37.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_3", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_61: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term37.gamma_pow", + "stage6.bytecode_read_raf.claim.term37.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_62: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term38.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_4", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_63: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term38.gamma_pow", + "stage6.bytecode_read_raf.claim.term38.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_64: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term39.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_5", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_65: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term39.gamma_pow", + "stage6.bytecode_read_raf.claim.term39.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_66: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term40.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_6", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_67: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term40.gamma_pow", + "stage6.bytecode_read_raf.claim.term40.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_68: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term41.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_7", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_69: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term41.gamma_pow", + "stage6.bytecode_read_raf.claim.term41.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_70: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term42.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_8", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_71: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term42.gamma_pow", + "stage6.bytecode_read_raf.claim.term42.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_72: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term43.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_9", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_73: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term43.gamma_pow", + "stage6.bytecode_read_raf.claim.term43.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_74: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term44.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_10", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_75: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term44.gamma_pow", + "stage6.bytecode_read_raf.claim.term44.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_76: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term45.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_11", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_77: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term45.gamma_pow", + "stage6.bytecode_read_raf.claim.term45.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_78: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term46.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_12", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_79: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term46.gamma_pow", + "stage6.bytecode_read_raf.claim.term46.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_80: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term47.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_13", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_81: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term47.gamma_pow", + "stage6.bytecode_read_raf.claim.term47.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_82: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term48.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_14", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_83: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term48.gamma_pow", + "stage6.bytecode_read_raf.claim.term48.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_84: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term49.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_15", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_85: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term49.gamma_pow", + "stage6.bytecode_read_raf.claim.term49.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_86: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term50.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_16", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_87: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term50.gamma_pow", + "stage6.bytecode_read_raf.claim.term50.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_88: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term51.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_17", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_89: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term51.gamma_pow", + "stage6.bytecode_read_raf.claim.term51.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_90: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term52.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_18", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_91: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term52.gamma_pow", + "stage6.bytecode_read_raf.claim.term52.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_92: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term53.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_19", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_93: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term53.gamma_pow", + "stage6.bytecode_read_raf.claim.term53.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_94: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term54.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_20", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_95: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term54.gamma_pow", + "stage6.bytecode_read_raf.claim.term54.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_96: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term55.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_21", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_97: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term55.gamma_pow", + "stage6.bytecode_read_raf.claim.term55.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_98: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term56.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_22", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_99: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term56.gamma_pow", + "stage6.bytecode_read_raf.claim.term56.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_100: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term57.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_23", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_101: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term57.gamma_pow", + "stage6.bytecode_read_raf.claim.term57.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_102: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term58.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_24", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_103: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term58.gamma_pow", + "stage6.bytecode_read_raf.claim.term58.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_104: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term59.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_25", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_105: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term59.gamma_pow", + "stage6.bytecode_read_raf.claim.term59.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_106: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term60.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_26", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_107: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term60.gamma_pow", + "stage6.bytecode_read_raf.claim.term60.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_108: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term61.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_27", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_109: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term61.gamma_pow", + "stage6.bytecode_read_raf.claim.term61.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_110: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term62.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_28", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_111: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term62.gamma_pow", + "stage6.bytecode_read_raf.claim.term62.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_112: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term63.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_29", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_113: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term63.gamma_pow", + "stage6.bytecode_read_raf.claim.term63.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_114: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term64.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_30", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_115: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term64.gamma_pow", + "stage6.bytecode_read_raf.claim.term64.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_116: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term65.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_31", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_117: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term65.gamma_pow", + "stage6.bytecode_read_raf.claim.term65.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_118: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term66.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_32", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_119: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term66.gamma_pow", + "stage6.bytecode_read_raf.claim.term66.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_120: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term67.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_33", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_121: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term67.gamma_pow", + "stage6.bytecode_read_raf.claim.term67.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_122: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term68.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_34", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_123: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term68.gamma_pow", + "stage6.bytecode_read_raf.claim.term68.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_124: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term69.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_35", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_125: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term69.gamma_pow", + "stage6.bytecode_read_raf.claim.term69.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_126: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term70.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_36", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_127: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term70.gamma_pow", + "stage6.bytecode_read_raf.claim.term70.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_128: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term71.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_37", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_129: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term71.gamma_pow", + "stage6.bytecode_read_raf.claim.term71.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_130: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term72.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_38", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_131: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term72.gamma_pow", + "stage6.bytecode_read_raf.claim.term72.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_132: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term73.stage_gamma_pow", + "stage6.input.stage5.LookupTableFlag_39", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_133: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term73.gamma_pow", + "stage6.bytecode_read_raf.claim.term73.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_134: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term74.gamma_pow", + "stage6.input.stage1.PC", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_135: &[&str] = &[ + "stage6.bytecode_read_raf.claim.term75.gamma_pow", + "stage6.input.stage3.spartan_shift.PC", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_136: &[&str] = &[ + "stage6.input.stage1.UnexpandedPC", + "stage6.bytecode_read_raf.claim.term1.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_137: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial0", + "stage6.bytecode_read_raf.claim.term2.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_138: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial1", + "stage6.bytecode_read_raf.claim.term3.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_139: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial2", + "stage6.bytecode_read_raf.claim.term4.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_140: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial3", + "stage6.bytecode_read_raf.claim.term5.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_141: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial4", + "stage6.bytecode_read_raf.claim.term6.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_142: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial5", + "stage6.bytecode_read_raf.claim.term7.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_143: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial6", + "stage6.bytecode_read_raf.claim.term8.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_144: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial7", + "stage6.bytecode_read_raf.claim.term9.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_145: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial8", + "stage6.bytecode_read_raf.claim.term10.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_146: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial9", + "stage6.bytecode_read_raf.claim.term11.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_147: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial10", + "stage6.bytecode_read_raf.claim.term12.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_148: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial11", + "stage6.bytecode_read_raf.claim.term13.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_149: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial12", + "stage6.bytecode_read_raf.claim.term14.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_150: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial13", + "stage6.bytecode_read_raf.claim.term15.stage_gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_151: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial14", + "stage6.bytecode_read_raf.claim.term16.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_152: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial15", + "stage6.bytecode_read_raf.claim.term17.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_153: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial16", + "stage6.bytecode_read_raf.claim.term18.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_154: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial17", + "stage6.bytecode_read_raf.claim.term19.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_155: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial18", + "stage6.bytecode_read_raf.claim.term20.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_156: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial19", + "stage6.bytecode_read_raf.claim.term21.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_157: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial20", + "stage6.bytecode_read_raf.claim.term22.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_158: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial21", + "stage6.bytecode_read_raf.claim.term23.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_159: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial22", + "stage6.bytecode_read_raf.claim.term24.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_160: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial23", + "stage6.bytecode_read_raf.claim.term25.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_161: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial24", + "stage6.bytecode_read_raf.claim.term26.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_162: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial25", + "stage6.bytecode_read_raf.claim.term27.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_163: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial26", + "stage6.bytecode_read_raf.claim.term28.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_164: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial27", + "stage6.bytecode_read_raf.claim.term29.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_165: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial28", + "stage6.bytecode_read_raf.claim.term30.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_166: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial29", + "stage6.bytecode_read_raf.claim.term31.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_167: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial30", + "stage6.bytecode_read_raf.claim.term32.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_168: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial31", + "stage6.bytecode_read_raf.claim.term33.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_169: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial32", + "stage6.bytecode_read_raf.claim.term34.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_170: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial33", + "stage6.bytecode_read_raf.claim.term35.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_171: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial34", + "stage6.bytecode_read_raf.claim.term36.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_172: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial35", + "stage6.bytecode_read_raf.claim.term37.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_173: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial36", + "stage6.bytecode_read_raf.claim.term38.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_174: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial37", + "stage6.bytecode_read_raf.claim.term39.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_175: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial38", + "stage6.bytecode_read_raf.claim.term40.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_176: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial39", + "stage6.bytecode_read_raf.claim.term41.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_177: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial40", + "stage6.bytecode_read_raf.claim.term42.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_178: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial41", + "stage6.bytecode_read_raf.claim.term43.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_179: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial42", + "stage6.bytecode_read_raf.claim.term44.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_180: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial43", + "stage6.bytecode_read_raf.claim.term45.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_181: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial44", + "stage6.bytecode_read_raf.claim.term46.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_182: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial45", + "stage6.bytecode_read_raf.claim.term47.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_183: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial46", + "stage6.bytecode_read_raf.claim.term48.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_184: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial47", + "stage6.bytecode_read_raf.claim.term49.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_185: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial48", + "stage6.bytecode_read_raf.claim.term50.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_186: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial49", + "stage6.bytecode_read_raf.claim.term51.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_187: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial50", + "stage6.bytecode_read_raf.claim.term52.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_188: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial51", + "stage6.bytecode_read_raf.claim.term53.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_189: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial52", + "stage6.bytecode_read_raf.claim.term54.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_190: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial53", + "stage6.bytecode_read_raf.claim.term55.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_191: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial54", + "stage6.bytecode_read_raf.claim.term56.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_192: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial55", + "stage6.bytecode_read_raf.claim.term57.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_193: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial56", + "stage6.bytecode_read_raf.claim.term58.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_194: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial57", + "stage6.bytecode_read_raf.claim.term59.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_195: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial58", + "stage6.bytecode_read_raf.claim.term60.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_196: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial59", + "stage6.bytecode_read_raf.claim.term61.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_197: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial60", + "stage6.bytecode_read_raf.claim.term62.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_198: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial61", + "stage6.bytecode_read_raf.claim.term63.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_199: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial62", + "stage6.bytecode_read_raf.claim.term64.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_200: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial63", + "stage6.bytecode_read_raf.claim.term65.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_201: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial64", + "stage6.bytecode_read_raf.claim.term66.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_202: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial65", + "stage6.bytecode_read_raf.claim.term67.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_203: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial66", + "stage6.bytecode_read_raf.claim.term68.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_204: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial67", + "stage6.bytecode_read_raf.claim.term69.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_205: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial68", + "stage6.bytecode_read_raf.claim.term70.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_206: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial69", + "stage6.bytecode_read_raf.claim.term71.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_207: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial70", + "stage6.bytecode_read_raf.claim.term72.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_208: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial71", + "stage6.bytecode_read_raf.claim.term73.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_209: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial72", + "stage6.bytecode_read_raf.claim.term74.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_210: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial73", + "stage6.bytecode_read_raf.claim.term75.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_211: &[&str] = &[ + "stage6.bytecode_read_raf.claim_expr.partial74", + "stage6.bytecode_read_raf.claim.entry_constant", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_212: &[&str] = &["stage6.instruction_ra_virtual.gamma"]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_213: &[&str] = &[ + "stage6.instruction_ra_virtual.claim.term1.gamma_pow", + "stage6.input.stage5.instruction_read_raf.InstructionRa_1", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_214: &[&str] = &[ + "stage6.instruction_ra_virtual.claim.term2.gamma_pow", + "stage6.input.stage5.instruction_read_raf.InstructionRa_2", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_215: &[&str] = &[ + "stage6.instruction_ra_virtual.claim.term3.gamma_pow", + "stage6.input.stage5.instruction_read_raf.InstructionRa_3", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_216: &[&str] = &[ + "stage6.instruction_ra_virtual.claim.term4.gamma_pow", + "stage6.input.stage5.instruction_read_raf.InstructionRa_4", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_217: &[&str] = &[ + "stage6.instruction_ra_virtual.claim.term5.gamma_pow", + "stage6.input.stage5.instruction_read_raf.InstructionRa_5", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_218: &[&str] = &[ + "stage6.instruction_ra_virtual.claim.term6.gamma_pow", + "stage6.input.stage5.instruction_read_raf.InstructionRa_6", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_219: &[&str] = &[ + "stage6.instruction_ra_virtual.claim.term7.gamma_pow", + "stage6.input.stage5.instruction_read_raf.InstructionRa_7", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_220: &[&str] = &[ + "stage6.input.stage5.instruction_read_raf.InstructionRa_0", + "stage6.instruction_ra_virtual.claim.term1.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_221: &[&str] = &[ + "stage6.instruction_ra_virtual.claim_expr.partial0", + "stage6.instruction_ra_virtual.claim.term2.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_222: &[&str] = &[ + "stage6.instruction_ra_virtual.claim_expr.partial1", + "stage6.instruction_ra_virtual.claim.term3.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_223: &[&str] = &[ + "stage6.instruction_ra_virtual.claim_expr.partial2", + "stage6.instruction_ra_virtual.claim.term4.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_224: &[&str] = &[ + "stage6.instruction_ra_virtual.claim_expr.partial3", + "stage6.instruction_ra_virtual.claim.term5.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_225: &[&str] = &[ + "stage6.instruction_ra_virtual.claim_expr.partial4", + "stage6.instruction_ra_virtual.claim.term6.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_226: &[&str] = &[ + "stage6.instruction_ra_virtual.claim_expr.partial5", + "stage6.instruction_ra_virtual.claim.term7.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_227: &[&str] = &["stage6.inc_claim_reduction.gamma"]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_228: &[&str] = &[ + "stage6.inc_claim_reduction.claim.ram_inc_stage4.gamma_pow", + "stage6.input.stage4.ram_val_check.RamInc", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_229: &[&str] = &[ + "stage6.inc_claim_reduction.claim.rd_inc_stage4.gamma_pow", + "stage6.input.stage4.registers_read_write.RdInc", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_230: &[&str] = &[ + "stage6.inc_claim_reduction.claim.rd_inc_stage5.gamma_pow", + "stage6.input.stage5.registers_val_evaluation.RdInc", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_231: &[&str] = &[ + "stage6.input.stage2.ram_read_write.RamInc", + "stage6.inc_claim_reduction.claim.ram_inc_stage4.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_232: &[&str] = &[ + "stage6.inc_claim_reduction.claim_expr.partial0", + "stage6.inc_claim_reduction.claim.rd_inc_stage4.gamma_term", +]; + +pub const STAGE6_FIELD_EXPR_OPERANDS_233: &[&str] = &[ + "stage6.inc_claim_reduction.claim_expr.partial1", + "stage6.inc_claim_reduction.claim.rd_inc_stage5.gamma_term", +]; + +pub const STAGE6_FIELD_EXPRS: &[Stage6FieldExprPlan] = &[ + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_0", kind: "op", formula: "field.pow:0", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_1", kind: "op", formula: "field.pow:2", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_2", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_3", kind: "op", formula: "field.pow:6", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_4", kind: "op", formula: "field.pow:8", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_5", kind: "op", formula: "field.pow:10", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_6", kind: "op", formula: "field.pow:12", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_7", kind: "op", formula: "field.pow:14", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_8", kind: "op", formula: "field.pow:16", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_9", kind: "op", formula: "field.pow:18", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_10", kind: "op", formula: "field.pow:20", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_11", kind: "op", formula: "field.pow:22", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_12", kind: "op", formula: "field.pow:24", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_13", kind: "op", formula: "field.pow:26", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_14", kind: "op", formula: "field.pow:28", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_15", kind: "op", formula: "field.pow:30", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_16", kind: "op", formula: "field.pow:32", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_17", kind: "op", formula: "field.pow:34", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_18", kind: "op", formula: "field.pow:36", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_19", kind: "op", formula: "field.pow:38", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_20", kind: "op", formula: "field.pow:40", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_21", kind: "op", formula: "field.pow:42", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_22", kind: "op", formula: "field.pow:44", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_23", kind: "op", formula: "field.pow:46", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_24", kind: "op", formula: "field.pow:48", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_25", kind: "op", formula: "field.pow:50", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_26", kind: "op", formula: "field.pow:52", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_27", kind: "op", formula: "field.pow:54", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_28", kind: "op", formula: "field.pow:56", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_29", kind: "op", formula: "field.pow:58", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_30", kind: "op", formula: "field.pow:60", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_31", kind: "op", formula: "field.pow:62", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_32", kind: "op", formula: "field.pow:64", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_33", kind: "op", formula: "field.pow:66", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_34", kind: "op", formula: "field.pow:68", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_35", kind: "op", formula: "field.pow:70", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_36", kind: "op", formula: "field.pow:72", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_37", kind: "op", formula: "field.pow:74", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_38", kind: "op", formula: "field.pow:76", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_0", kind: "op", formula: "field.pow:0", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_1", kind: "op", formula: "field.pow:1", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_2", kind: "op", formula: "field.pow:2", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_3", kind: "op", formula: "field.pow:3", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_4", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_5", kind: "op", formula: "field.pow:5", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_6", kind: "op", formula: "field.pow:6", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_7", kind: "op", formula: "field.pow:7", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_8", kind: "op", formula: "field.pow:8", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_9", kind: "op", formula: "field.pow:9", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_10", kind: "op", formula: "field.pow:10", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_11", kind: "op", formula: "field.pow:11", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_12", kind: "op", formula: "field.pow:12", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_13", kind: "op", formula: "field.pow:13", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_14", kind: "op", formula: "field.pow:14", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_15", kind: "op", formula: "field.pow:15", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_16", kind: "op", formula: "field.pow:16", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_17", kind: "op", formula: "field.pow:17", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_18", kind: "op", formula: "field.pow:18", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_19", kind: "op", formula: "field.pow:19", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_20", kind: "op", formula: "field.pow:20", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_21", kind: "op", formula: "field.pow:21", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_22", kind: "op", formula: "field.pow:22", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_23", kind: "op", formula: "field.pow:23", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_24", kind: "op", formula: "field.pow:24", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_25", kind: "op", formula: "field.pow:25", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_26", kind: "op", formula: "field.pow:26", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_27", kind: "op", formula: "field.pow:27", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_28", kind: "op", formula: "field.pow:28", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_29", kind: "op", formula: "field.pow:29", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_30", kind: "op", formula: "field.pow:30", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_31", kind: "op", formula: "field.pow:31", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_32", kind: "op", formula: "field.pow:32", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_33", kind: "op", formula: "field.pow:33", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_34", kind: "op", formula: "field.pow:34", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_35", kind: "op", formula: "field.pow:35", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_36", kind: "op", formula: "field.pow:36", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_37", kind: "op", formula: "field.pow:37", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_38", kind: "op", formula: "field.pow:38", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term1.stage_gamma_pow", kind: "op", formula: "field.pow:1", operand_names: STAGE6_FIELD_EXPR_OPERANDS_1, operands: STAGE6_FIELD_EXPR_OPERANDS_1 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term1.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_2, operands: STAGE6_FIELD_EXPR_OPERANDS_2 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term2.stage_gamma_pow", kind: "op", formula: "field.pow:2", operand_names: STAGE6_FIELD_EXPR_OPERANDS_1, operands: STAGE6_FIELD_EXPR_OPERANDS_1 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term2.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_3, operands: STAGE6_FIELD_EXPR_OPERANDS_3 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term3.stage_gamma_pow", kind: "op", formula: "field.pow:3", operand_names: STAGE6_FIELD_EXPR_OPERANDS_1, operands: STAGE6_FIELD_EXPR_OPERANDS_1 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term3.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_4, operands: STAGE6_FIELD_EXPR_OPERANDS_4 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term4.stage_gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_1, operands: STAGE6_FIELD_EXPR_OPERANDS_1 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term4.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_5, operands: STAGE6_FIELD_EXPR_OPERANDS_5 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term5.stage_gamma_pow", kind: "op", formula: "field.pow:5", operand_names: STAGE6_FIELD_EXPR_OPERANDS_1, operands: STAGE6_FIELD_EXPR_OPERANDS_1 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term5.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_6, operands: STAGE6_FIELD_EXPR_OPERANDS_6 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term6.stage_gamma_pow", kind: "op", formula: "field.pow:6", operand_names: STAGE6_FIELD_EXPR_OPERANDS_1, operands: STAGE6_FIELD_EXPR_OPERANDS_1 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term6.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_7, operands: STAGE6_FIELD_EXPR_OPERANDS_7 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term7.stage_gamma_pow", kind: "op", formula: "field.pow:7", operand_names: STAGE6_FIELD_EXPR_OPERANDS_1, operands: STAGE6_FIELD_EXPR_OPERANDS_1 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term7.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_8, operands: STAGE6_FIELD_EXPR_OPERANDS_8 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term8.stage_gamma_pow", kind: "op", formula: "field.pow:8", operand_names: STAGE6_FIELD_EXPR_OPERANDS_1, operands: STAGE6_FIELD_EXPR_OPERANDS_1 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term8.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_9, operands: STAGE6_FIELD_EXPR_OPERANDS_9 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term9.stage_gamma_pow", kind: "op", formula: "field.pow:9", operand_names: STAGE6_FIELD_EXPR_OPERANDS_1, operands: STAGE6_FIELD_EXPR_OPERANDS_1 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term9.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_10, operands: STAGE6_FIELD_EXPR_OPERANDS_10 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term10.stage_gamma_pow", kind: "op", formula: "field.pow:10", operand_names: STAGE6_FIELD_EXPR_OPERANDS_1, operands: STAGE6_FIELD_EXPR_OPERANDS_1 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term10.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_11, operands: STAGE6_FIELD_EXPR_OPERANDS_11 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term11.stage_gamma_pow", kind: "op", formula: "field.pow:11", operand_names: STAGE6_FIELD_EXPR_OPERANDS_1, operands: STAGE6_FIELD_EXPR_OPERANDS_1 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term11.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_12, operands: STAGE6_FIELD_EXPR_OPERANDS_12 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term12.stage_gamma_pow", kind: "op", formula: "field.pow:12", operand_names: STAGE6_FIELD_EXPR_OPERANDS_1, operands: STAGE6_FIELD_EXPR_OPERANDS_1 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term12.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_13, operands: STAGE6_FIELD_EXPR_OPERANDS_13 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term13.stage_gamma_pow", kind: "op", formula: "field.pow:13", operand_names: STAGE6_FIELD_EXPR_OPERANDS_1, operands: STAGE6_FIELD_EXPR_OPERANDS_1 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term13.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_14, operands: STAGE6_FIELD_EXPR_OPERANDS_14 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term14.stage_gamma_pow", kind: "op", formula: "field.pow:14", operand_names: STAGE6_FIELD_EXPR_OPERANDS_1, operands: STAGE6_FIELD_EXPR_OPERANDS_1 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term14.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_15, operands: STAGE6_FIELD_EXPR_OPERANDS_15 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term15.stage_gamma_pow", kind: "op", formula: "field.pow:15", operand_names: STAGE6_FIELD_EXPR_OPERANDS_1, operands: STAGE6_FIELD_EXPR_OPERANDS_1 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term15.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_16, operands: STAGE6_FIELD_EXPR_OPERANDS_16 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term16.gamma_pow", kind: "op", formula: "field.pow:1", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term16.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_18, operands: STAGE6_FIELD_EXPR_OPERANDS_18 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term17.stage_gamma_pow", kind: "op", formula: "field.pow:1", operand_names: STAGE6_FIELD_EXPR_OPERANDS_19, operands: STAGE6_FIELD_EXPR_OPERANDS_19 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term17.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_20, operands: STAGE6_FIELD_EXPR_OPERANDS_20 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term17.gamma_pow", kind: "op", formula: "field.pow:1", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term17.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_21, operands: STAGE6_FIELD_EXPR_OPERANDS_21 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term18.stage_gamma_pow", kind: "op", formula: "field.pow:2", operand_names: STAGE6_FIELD_EXPR_OPERANDS_19, operands: STAGE6_FIELD_EXPR_OPERANDS_19 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term18.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_22, operands: STAGE6_FIELD_EXPR_OPERANDS_22 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term18.gamma_pow", kind: "op", formula: "field.pow:1", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term18.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_23, operands: STAGE6_FIELD_EXPR_OPERANDS_23 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term19.stage_gamma_pow", kind: "op", formula: "field.pow:3", operand_names: STAGE6_FIELD_EXPR_OPERANDS_19, operands: STAGE6_FIELD_EXPR_OPERANDS_19 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term19.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_24, operands: STAGE6_FIELD_EXPR_OPERANDS_24 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term19.gamma_pow", kind: "op", formula: "field.pow:1", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term19.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_25, operands: STAGE6_FIELD_EXPR_OPERANDS_25 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term20.gamma_pow", kind: "op", formula: "field.pow:2", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term20.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_26, operands: STAGE6_FIELD_EXPR_OPERANDS_26 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term21.stage_gamma_pow", kind: "op", formula: "field.pow:1", operand_names: STAGE6_FIELD_EXPR_OPERANDS_27, operands: STAGE6_FIELD_EXPR_OPERANDS_27 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term21.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_28, operands: STAGE6_FIELD_EXPR_OPERANDS_28 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term21.gamma_pow", kind: "op", formula: "field.pow:2", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term21.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_29, operands: STAGE6_FIELD_EXPR_OPERANDS_29 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term22.stage_gamma_pow", kind: "op", formula: "field.pow:2", operand_names: STAGE6_FIELD_EXPR_OPERANDS_27, operands: STAGE6_FIELD_EXPR_OPERANDS_27 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term22.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_30, operands: STAGE6_FIELD_EXPR_OPERANDS_30 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term22.gamma_pow", kind: "op", formula: "field.pow:2", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term22.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_31, operands: STAGE6_FIELD_EXPR_OPERANDS_31 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term23.stage_gamma_pow", kind: "op", formula: "field.pow:3", operand_names: STAGE6_FIELD_EXPR_OPERANDS_27, operands: STAGE6_FIELD_EXPR_OPERANDS_27 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term23.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_32, operands: STAGE6_FIELD_EXPR_OPERANDS_32 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term23.gamma_pow", kind: "op", formula: "field.pow:2", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term23.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_33, operands: STAGE6_FIELD_EXPR_OPERANDS_33 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term24.stage_gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_27, operands: STAGE6_FIELD_EXPR_OPERANDS_27 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term24.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_34, operands: STAGE6_FIELD_EXPR_OPERANDS_34 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term24.gamma_pow", kind: "op", formula: "field.pow:2", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term24.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_35, operands: STAGE6_FIELD_EXPR_OPERANDS_35 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term25.stage_gamma_pow", kind: "op", formula: "field.pow:5", operand_names: STAGE6_FIELD_EXPR_OPERANDS_27, operands: STAGE6_FIELD_EXPR_OPERANDS_27 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term25.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_36, operands: STAGE6_FIELD_EXPR_OPERANDS_36 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term25.gamma_pow", kind: "op", formula: "field.pow:2", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term25.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_37, operands: STAGE6_FIELD_EXPR_OPERANDS_37 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term26.stage_gamma_pow", kind: "op", formula: "field.pow:6", operand_names: STAGE6_FIELD_EXPR_OPERANDS_27, operands: STAGE6_FIELD_EXPR_OPERANDS_27 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term26.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_38, operands: STAGE6_FIELD_EXPR_OPERANDS_38 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term26.gamma_pow", kind: "op", formula: "field.pow:2", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term26.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_39, operands: STAGE6_FIELD_EXPR_OPERANDS_39 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term27.stage_gamma_pow", kind: "op", formula: "field.pow:7", operand_names: STAGE6_FIELD_EXPR_OPERANDS_27, operands: STAGE6_FIELD_EXPR_OPERANDS_27 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term27.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_40, operands: STAGE6_FIELD_EXPR_OPERANDS_40 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term27.gamma_pow", kind: "op", formula: "field.pow:2", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term27.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_41, operands: STAGE6_FIELD_EXPR_OPERANDS_41 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term28.stage_gamma_pow", kind: "op", formula: "field.pow:8", operand_names: STAGE6_FIELD_EXPR_OPERANDS_27, operands: STAGE6_FIELD_EXPR_OPERANDS_27 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term28.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_42, operands: STAGE6_FIELD_EXPR_OPERANDS_42 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term28.gamma_pow", kind: "op", formula: "field.pow:2", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term28.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_43, operands: STAGE6_FIELD_EXPR_OPERANDS_43 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term29.gamma_pow", kind: "op", formula: "field.pow:3", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term29.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_44, operands: STAGE6_FIELD_EXPR_OPERANDS_44 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term30.stage_gamma_pow", kind: "op", formula: "field.pow:1", operand_names: STAGE6_FIELD_EXPR_OPERANDS_45, operands: STAGE6_FIELD_EXPR_OPERANDS_45 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term30.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_46, operands: STAGE6_FIELD_EXPR_OPERANDS_46 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term30.gamma_pow", kind: "op", formula: "field.pow:3", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term30.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_47, operands: STAGE6_FIELD_EXPR_OPERANDS_47 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term31.stage_gamma_pow", kind: "op", formula: "field.pow:2", operand_names: STAGE6_FIELD_EXPR_OPERANDS_45, operands: STAGE6_FIELD_EXPR_OPERANDS_45 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term31.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_48, operands: STAGE6_FIELD_EXPR_OPERANDS_48 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term31.gamma_pow", kind: "op", formula: "field.pow:3", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term31.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_49, operands: STAGE6_FIELD_EXPR_OPERANDS_49 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term32.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term32.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_50, operands: STAGE6_FIELD_EXPR_OPERANDS_50 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term33.stage_gamma_pow", kind: "op", formula: "field.pow:1", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term33.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_52, operands: STAGE6_FIELD_EXPR_OPERANDS_52 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term33.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term33.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_53, operands: STAGE6_FIELD_EXPR_OPERANDS_53 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term34.stage_gamma_pow", kind: "op", formula: "field.pow:2", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term34.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_54, operands: STAGE6_FIELD_EXPR_OPERANDS_54 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term34.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term34.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_55, operands: STAGE6_FIELD_EXPR_OPERANDS_55 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term35.stage_gamma_pow", kind: "op", formula: "field.pow:3", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term35.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_56, operands: STAGE6_FIELD_EXPR_OPERANDS_56 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term35.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term35.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_57, operands: STAGE6_FIELD_EXPR_OPERANDS_57 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term36.stage_gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term36.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_58, operands: STAGE6_FIELD_EXPR_OPERANDS_58 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term36.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term36.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_59, operands: STAGE6_FIELD_EXPR_OPERANDS_59 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term37.stage_gamma_pow", kind: "op", formula: "field.pow:5", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term37.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_60, operands: STAGE6_FIELD_EXPR_OPERANDS_60 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term37.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term37.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_61, operands: STAGE6_FIELD_EXPR_OPERANDS_61 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term38.stage_gamma_pow", kind: "op", formula: "field.pow:6", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term38.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_62, operands: STAGE6_FIELD_EXPR_OPERANDS_62 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term38.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term38.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_63, operands: STAGE6_FIELD_EXPR_OPERANDS_63 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term39.stage_gamma_pow", kind: "op", formula: "field.pow:7", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term39.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_64, operands: STAGE6_FIELD_EXPR_OPERANDS_64 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term39.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term39.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_65, operands: STAGE6_FIELD_EXPR_OPERANDS_65 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term40.stage_gamma_pow", kind: "op", formula: "field.pow:8", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term40.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_66, operands: STAGE6_FIELD_EXPR_OPERANDS_66 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term40.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term40.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_67, operands: STAGE6_FIELD_EXPR_OPERANDS_67 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term41.stage_gamma_pow", kind: "op", formula: "field.pow:9", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term41.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_68, operands: STAGE6_FIELD_EXPR_OPERANDS_68 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term41.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term41.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_69, operands: STAGE6_FIELD_EXPR_OPERANDS_69 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term42.stage_gamma_pow", kind: "op", formula: "field.pow:10", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term42.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_70, operands: STAGE6_FIELD_EXPR_OPERANDS_70 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term42.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term42.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_71, operands: STAGE6_FIELD_EXPR_OPERANDS_71 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term43.stage_gamma_pow", kind: "op", formula: "field.pow:11", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term43.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_72, operands: STAGE6_FIELD_EXPR_OPERANDS_72 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term43.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term43.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_73, operands: STAGE6_FIELD_EXPR_OPERANDS_73 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term44.stage_gamma_pow", kind: "op", formula: "field.pow:12", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term44.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_74, operands: STAGE6_FIELD_EXPR_OPERANDS_74 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term44.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term44.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_75, operands: STAGE6_FIELD_EXPR_OPERANDS_75 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term45.stage_gamma_pow", kind: "op", formula: "field.pow:13", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term45.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_76, operands: STAGE6_FIELD_EXPR_OPERANDS_76 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term45.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term45.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_77, operands: STAGE6_FIELD_EXPR_OPERANDS_77 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term46.stage_gamma_pow", kind: "op", formula: "field.pow:14", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term46.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_78, operands: STAGE6_FIELD_EXPR_OPERANDS_78 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term46.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term46.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_79, operands: STAGE6_FIELD_EXPR_OPERANDS_79 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term47.stage_gamma_pow", kind: "op", formula: "field.pow:15", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term47.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_80, operands: STAGE6_FIELD_EXPR_OPERANDS_80 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term47.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term47.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_81, operands: STAGE6_FIELD_EXPR_OPERANDS_81 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term48.stage_gamma_pow", kind: "op", formula: "field.pow:16", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term48.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_82, operands: STAGE6_FIELD_EXPR_OPERANDS_82 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term48.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term48.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_83, operands: STAGE6_FIELD_EXPR_OPERANDS_83 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term49.stage_gamma_pow", kind: "op", formula: "field.pow:17", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term49.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_84, operands: STAGE6_FIELD_EXPR_OPERANDS_84 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term49.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term49.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_85, operands: STAGE6_FIELD_EXPR_OPERANDS_85 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term50.stage_gamma_pow", kind: "op", formula: "field.pow:18", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term50.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_86, operands: STAGE6_FIELD_EXPR_OPERANDS_86 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term50.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term50.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_87, operands: STAGE6_FIELD_EXPR_OPERANDS_87 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term51.stage_gamma_pow", kind: "op", formula: "field.pow:19", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term51.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_88, operands: STAGE6_FIELD_EXPR_OPERANDS_88 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term51.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term51.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_89, operands: STAGE6_FIELD_EXPR_OPERANDS_89 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term52.stage_gamma_pow", kind: "op", formula: "field.pow:20", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term52.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_90, operands: STAGE6_FIELD_EXPR_OPERANDS_90 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term52.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term52.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_91, operands: STAGE6_FIELD_EXPR_OPERANDS_91 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term53.stage_gamma_pow", kind: "op", formula: "field.pow:21", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term53.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_92, operands: STAGE6_FIELD_EXPR_OPERANDS_92 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term53.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term53.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_93, operands: STAGE6_FIELD_EXPR_OPERANDS_93 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term54.stage_gamma_pow", kind: "op", formula: "field.pow:22", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term54.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_94, operands: STAGE6_FIELD_EXPR_OPERANDS_94 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term54.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term54.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_95, operands: STAGE6_FIELD_EXPR_OPERANDS_95 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term55.stage_gamma_pow", kind: "op", formula: "field.pow:23", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term55.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_96, operands: STAGE6_FIELD_EXPR_OPERANDS_96 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term55.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term55.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_97, operands: STAGE6_FIELD_EXPR_OPERANDS_97 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term56.stage_gamma_pow", kind: "op", formula: "field.pow:24", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term56.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_98, operands: STAGE6_FIELD_EXPR_OPERANDS_98 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term56.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term56.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_99, operands: STAGE6_FIELD_EXPR_OPERANDS_99 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term57.stage_gamma_pow", kind: "op", formula: "field.pow:25", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term57.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_100, operands: STAGE6_FIELD_EXPR_OPERANDS_100 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term57.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term57.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_101, operands: STAGE6_FIELD_EXPR_OPERANDS_101 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term58.stage_gamma_pow", kind: "op", formula: "field.pow:26", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term58.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_102, operands: STAGE6_FIELD_EXPR_OPERANDS_102 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term58.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term58.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_103, operands: STAGE6_FIELD_EXPR_OPERANDS_103 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term59.stage_gamma_pow", kind: "op", formula: "field.pow:27", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term59.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_104, operands: STAGE6_FIELD_EXPR_OPERANDS_104 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term59.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term59.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_105, operands: STAGE6_FIELD_EXPR_OPERANDS_105 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term60.stage_gamma_pow", kind: "op", formula: "field.pow:28", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term60.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_106, operands: STAGE6_FIELD_EXPR_OPERANDS_106 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term60.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term60.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_107, operands: STAGE6_FIELD_EXPR_OPERANDS_107 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term61.stage_gamma_pow", kind: "op", formula: "field.pow:29", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term61.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_108, operands: STAGE6_FIELD_EXPR_OPERANDS_108 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term61.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term61.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_109, operands: STAGE6_FIELD_EXPR_OPERANDS_109 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term62.stage_gamma_pow", kind: "op", formula: "field.pow:30", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term62.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_110, operands: STAGE6_FIELD_EXPR_OPERANDS_110 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term62.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term62.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_111, operands: STAGE6_FIELD_EXPR_OPERANDS_111 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term63.stage_gamma_pow", kind: "op", formula: "field.pow:31", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term63.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_112, operands: STAGE6_FIELD_EXPR_OPERANDS_112 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term63.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term63.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_113, operands: STAGE6_FIELD_EXPR_OPERANDS_113 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term64.stage_gamma_pow", kind: "op", formula: "field.pow:32", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term64.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_114, operands: STAGE6_FIELD_EXPR_OPERANDS_114 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term64.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term64.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_115, operands: STAGE6_FIELD_EXPR_OPERANDS_115 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term65.stage_gamma_pow", kind: "op", formula: "field.pow:33", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term65.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_116, operands: STAGE6_FIELD_EXPR_OPERANDS_116 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term65.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term65.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_117, operands: STAGE6_FIELD_EXPR_OPERANDS_117 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term66.stage_gamma_pow", kind: "op", formula: "field.pow:34", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term66.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_118, operands: STAGE6_FIELD_EXPR_OPERANDS_118 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term66.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term66.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_119, operands: STAGE6_FIELD_EXPR_OPERANDS_119 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term67.stage_gamma_pow", kind: "op", formula: "field.pow:35", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term67.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_120, operands: STAGE6_FIELD_EXPR_OPERANDS_120 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term67.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term67.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_121, operands: STAGE6_FIELD_EXPR_OPERANDS_121 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term68.stage_gamma_pow", kind: "op", formula: "field.pow:36", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term68.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_122, operands: STAGE6_FIELD_EXPR_OPERANDS_122 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term68.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term68.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_123, operands: STAGE6_FIELD_EXPR_OPERANDS_123 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term69.stage_gamma_pow", kind: "op", formula: "field.pow:37", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term69.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_124, operands: STAGE6_FIELD_EXPR_OPERANDS_124 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term69.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term69.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_125, operands: STAGE6_FIELD_EXPR_OPERANDS_125 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term70.stage_gamma_pow", kind: "op", formula: "field.pow:38", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term70.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_126, operands: STAGE6_FIELD_EXPR_OPERANDS_126 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term70.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term70.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_127, operands: STAGE6_FIELD_EXPR_OPERANDS_127 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term71.stage_gamma_pow", kind: "op", formula: "field.pow:39", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term71.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_128, operands: STAGE6_FIELD_EXPR_OPERANDS_128 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term71.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term71.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_129, operands: STAGE6_FIELD_EXPR_OPERANDS_129 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term72.stage_gamma_pow", kind: "op", formula: "field.pow:40", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term72.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_130, operands: STAGE6_FIELD_EXPR_OPERANDS_130 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term72.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term72.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_131, operands: STAGE6_FIELD_EXPR_OPERANDS_131 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term73.stage_gamma_pow", kind: "op", formula: "field.pow:41", operand_names: STAGE6_FIELD_EXPR_OPERANDS_51, operands: STAGE6_FIELD_EXPR_OPERANDS_51 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term73.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_132, operands: STAGE6_FIELD_EXPR_OPERANDS_132 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term73.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term73.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_133, operands: STAGE6_FIELD_EXPR_OPERANDS_133 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term74.gamma_pow", kind: "op", formula: "field.pow:5", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term74.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_134, operands: STAGE6_FIELD_EXPR_OPERANDS_134 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term75.gamma_pow", kind: "op", formula: "field.pow:6", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term75.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_135, operands: STAGE6_FIELD_EXPR_OPERANDS_135 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.entry_constant", kind: "op", formula: "field.pow:7", operand_names: STAGE6_FIELD_EXPR_OPERANDS_17, operands: STAGE6_FIELD_EXPR_OPERANDS_17 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial0", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_136, operands: STAGE6_FIELD_EXPR_OPERANDS_136 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial1", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_137, operands: STAGE6_FIELD_EXPR_OPERANDS_137 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial2", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_138, operands: STAGE6_FIELD_EXPR_OPERANDS_138 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial3", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_139, operands: STAGE6_FIELD_EXPR_OPERANDS_139 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial4", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_140, operands: STAGE6_FIELD_EXPR_OPERANDS_140 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial5", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_141, operands: STAGE6_FIELD_EXPR_OPERANDS_141 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial6", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_142, operands: STAGE6_FIELD_EXPR_OPERANDS_142 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial7", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_143, operands: STAGE6_FIELD_EXPR_OPERANDS_143 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial8", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_144, operands: STAGE6_FIELD_EXPR_OPERANDS_144 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial9", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_145, operands: STAGE6_FIELD_EXPR_OPERANDS_145 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial10", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_146, operands: STAGE6_FIELD_EXPR_OPERANDS_146 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial11", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_147, operands: STAGE6_FIELD_EXPR_OPERANDS_147 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial12", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_148, operands: STAGE6_FIELD_EXPR_OPERANDS_148 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial13", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_149, operands: STAGE6_FIELD_EXPR_OPERANDS_149 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial14", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_150, operands: STAGE6_FIELD_EXPR_OPERANDS_150 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial15", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_151, operands: STAGE6_FIELD_EXPR_OPERANDS_151 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial16", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_152, operands: STAGE6_FIELD_EXPR_OPERANDS_152 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial17", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_153, operands: STAGE6_FIELD_EXPR_OPERANDS_153 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial18", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_154, operands: STAGE6_FIELD_EXPR_OPERANDS_154 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial19", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_155, operands: STAGE6_FIELD_EXPR_OPERANDS_155 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial20", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_156, operands: STAGE6_FIELD_EXPR_OPERANDS_156 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial21", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_157, operands: STAGE6_FIELD_EXPR_OPERANDS_157 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial22", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_158, operands: STAGE6_FIELD_EXPR_OPERANDS_158 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial23", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_159, operands: STAGE6_FIELD_EXPR_OPERANDS_159 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial24", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_160, operands: STAGE6_FIELD_EXPR_OPERANDS_160 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial25", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_161, operands: STAGE6_FIELD_EXPR_OPERANDS_161 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial26", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_162, operands: STAGE6_FIELD_EXPR_OPERANDS_162 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial27", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_163, operands: STAGE6_FIELD_EXPR_OPERANDS_163 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial28", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_164, operands: STAGE6_FIELD_EXPR_OPERANDS_164 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial29", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_165, operands: STAGE6_FIELD_EXPR_OPERANDS_165 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial30", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_166, operands: STAGE6_FIELD_EXPR_OPERANDS_166 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial31", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_167, operands: STAGE6_FIELD_EXPR_OPERANDS_167 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial32", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_168, operands: STAGE6_FIELD_EXPR_OPERANDS_168 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial33", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_169, operands: STAGE6_FIELD_EXPR_OPERANDS_169 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial34", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_170, operands: STAGE6_FIELD_EXPR_OPERANDS_170 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial35", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_171, operands: STAGE6_FIELD_EXPR_OPERANDS_171 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial36", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_172, operands: STAGE6_FIELD_EXPR_OPERANDS_172 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial37", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_173, operands: STAGE6_FIELD_EXPR_OPERANDS_173 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial38", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_174, operands: STAGE6_FIELD_EXPR_OPERANDS_174 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial39", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_175, operands: STAGE6_FIELD_EXPR_OPERANDS_175 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial40", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_176, operands: STAGE6_FIELD_EXPR_OPERANDS_176 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial41", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_177, operands: STAGE6_FIELD_EXPR_OPERANDS_177 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial42", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_178, operands: STAGE6_FIELD_EXPR_OPERANDS_178 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial43", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_179, operands: STAGE6_FIELD_EXPR_OPERANDS_179 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial44", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_180, operands: STAGE6_FIELD_EXPR_OPERANDS_180 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial45", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_181, operands: STAGE6_FIELD_EXPR_OPERANDS_181 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial46", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_182, operands: STAGE6_FIELD_EXPR_OPERANDS_182 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial47", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_183, operands: STAGE6_FIELD_EXPR_OPERANDS_183 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial48", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_184, operands: STAGE6_FIELD_EXPR_OPERANDS_184 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial49", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_185, operands: STAGE6_FIELD_EXPR_OPERANDS_185 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial50", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_186, operands: STAGE6_FIELD_EXPR_OPERANDS_186 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial51", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_187, operands: STAGE6_FIELD_EXPR_OPERANDS_187 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial52", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_188, operands: STAGE6_FIELD_EXPR_OPERANDS_188 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial53", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_189, operands: STAGE6_FIELD_EXPR_OPERANDS_189 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial54", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_190, operands: STAGE6_FIELD_EXPR_OPERANDS_190 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial55", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_191, operands: STAGE6_FIELD_EXPR_OPERANDS_191 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial56", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_192, operands: STAGE6_FIELD_EXPR_OPERANDS_192 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial57", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_193, operands: STAGE6_FIELD_EXPR_OPERANDS_193 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial58", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_194, operands: STAGE6_FIELD_EXPR_OPERANDS_194 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial59", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_195, operands: STAGE6_FIELD_EXPR_OPERANDS_195 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial60", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_196, operands: STAGE6_FIELD_EXPR_OPERANDS_196 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial61", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_197, operands: STAGE6_FIELD_EXPR_OPERANDS_197 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial62", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_198, operands: STAGE6_FIELD_EXPR_OPERANDS_198 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial63", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_199, operands: STAGE6_FIELD_EXPR_OPERANDS_199 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial64", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_200, operands: STAGE6_FIELD_EXPR_OPERANDS_200 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial65", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_201, operands: STAGE6_FIELD_EXPR_OPERANDS_201 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial66", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_202, operands: STAGE6_FIELD_EXPR_OPERANDS_202 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial67", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_203, operands: STAGE6_FIELD_EXPR_OPERANDS_203 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial68", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_204, operands: STAGE6_FIELD_EXPR_OPERANDS_204 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial69", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_205, operands: STAGE6_FIELD_EXPR_OPERANDS_205 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial70", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_206, operands: STAGE6_FIELD_EXPR_OPERANDS_206 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial71", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_207, operands: STAGE6_FIELD_EXPR_OPERANDS_207 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial72", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_208, operands: STAGE6_FIELD_EXPR_OPERANDS_208 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial73", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_209, operands: STAGE6_FIELD_EXPR_OPERANDS_209 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial74", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_210, operands: STAGE6_FIELD_EXPR_OPERANDS_210 }, + Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim_expr.partial75", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_211, operands: STAGE6_FIELD_EXPR_OPERANDS_211 }, + Stage6FieldExprPlan { symbol: "stage6.instruction_ra_virtual.claim.term1.gamma_pow", kind: "op", formula: "field.pow:1", operand_names: STAGE6_FIELD_EXPR_OPERANDS_212, operands: STAGE6_FIELD_EXPR_OPERANDS_212 }, + Stage6FieldExprPlan { symbol: "stage6.instruction_ra_virtual.claim.term1.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_213, operands: STAGE6_FIELD_EXPR_OPERANDS_213 }, + Stage6FieldExprPlan { symbol: "stage6.instruction_ra_virtual.claim.term2.gamma_pow", kind: "op", formula: "field.pow:2", operand_names: STAGE6_FIELD_EXPR_OPERANDS_212, operands: STAGE6_FIELD_EXPR_OPERANDS_212 }, + Stage6FieldExprPlan { symbol: "stage6.instruction_ra_virtual.claim.term2.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_214, operands: STAGE6_FIELD_EXPR_OPERANDS_214 }, + Stage6FieldExprPlan { symbol: "stage6.instruction_ra_virtual.claim.term3.gamma_pow", kind: "op", formula: "field.pow:3", operand_names: STAGE6_FIELD_EXPR_OPERANDS_212, operands: STAGE6_FIELD_EXPR_OPERANDS_212 }, + Stage6FieldExprPlan { symbol: "stage6.instruction_ra_virtual.claim.term3.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_215, operands: STAGE6_FIELD_EXPR_OPERANDS_215 }, + Stage6FieldExprPlan { symbol: "stage6.instruction_ra_virtual.claim.term4.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE6_FIELD_EXPR_OPERANDS_212, operands: STAGE6_FIELD_EXPR_OPERANDS_212 }, + Stage6FieldExprPlan { symbol: "stage6.instruction_ra_virtual.claim.term4.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_216, operands: STAGE6_FIELD_EXPR_OPERANDS_216 }, + Stage6FieldExprPlan { symbol: "stage6.instruction_ra_virtual.claim.term5.gamma_pow", kind: "op", formula: "field.pow:5", operand_names: STAGE6_FIELD_EXPR_OPERANDS_212, operands: STAGE6_FIELD_EXPR_OPERANDS_212 }, + Stage6FieldExprPlan { symbol: "stage6.instruction_ra_virtual.claim.term5.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_217, operands: STAGE6_FIELD_EXPR_OPERANDS_217 }, + Stage6FieldExprPlan { symbol: "stage6.instruction_ra_virtual.claim.term6.gamma_pow", kind: "op", formula: "field.pow:6", operand_names: STAGE6_FIELD_EXPR_OPERANDS_212, operands: STAGE6_FIELD_EXPR_OPERANDS_212 }, + Stage6FieldExprPlan { symbol: "stage6.instruction_ra_virtual.claim.term6.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_218, operands: STAGE6_FIELD_EXPR_OPERANDS_218 }, + Stage6FieldExprPlan { symbol: "stage6.instruction_ra_virtual.claim.term7.gamma_pow", kind: "op", formula: "field.pow:7", operand_names: STAGE6_FIELD_EXPR_OPERANDS_212, operands: STAGE6_FIELD_EXPR_OPERANDS_212 }, + Stage6FieldExprPlan { symbol: "stage6.instruction_ra_virtual.claim.term7.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_219, operands: STAGE6_FIELD_EXPR_OPERANDS_219 }, + Stage6FieldExprPlan { symbol: "stage6.instruction_ra_virtual.claim_expr.partial0", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_220, operands: STAGE6_FIELD_EXPR_OPERANDS_220 }, + Stage6FieldExprPlan { symbol: "stage6.instruction_ra_virtual.claim_expr.partial1", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_221, operands: STAGE6_FIELD_EXPR_OPERANDS_221 }, + Stage6FieldExprPlan { symbol: "stage6.instruction_ra_virtual.claim_expr.partial2", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_222, operands: STAGE6_FIELD_EXPR_OPERANDS_222 }, + Stage6FieldExprPlan { symbol: "stage6.instruction_ra_virtual.claim_expr.partial3", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_223, operands: STAGE6_FIELD_EXPR_OPERANDS_223 }, + Stage6FieldExprPlan { symbol: "stage6.instruction_ra_virtual.claim_expr.partial4", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_224, operands: STAGE6_FIELD_EXPR_OPERANDS_224 }, + Stage6FieldExprPlan { symbol: "stage6.instruction_ra_virtual.claim_expr.partial5", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_225, operands: STAGE6_FIELD_EXPR_OPERANDS_225 }, + Stage6FieldExprPlan { symbol: "stage6.instruction_ra_virtual.claim_expr.partial6", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_226, operands: STAGE6_FIELD_EXPR_OPERANDS_226 }, + Stage6FieldExprPlan { symbol: "stage6.inc_claim_reduction.claim.ram_inc_stage4.gamma_pow", kind: "op", formula: "field.pow:1", operand_names: STAGE6_FIELD_EXPR_OPERANDS_227, operands: STAGE6_FIELD_EXPR_OPERANDS_227 }, + Stage6FieldExprPlan { symbol: "stage6.inc_claim_reduction.claim.ram_inc_stage4.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_228, operands: STAGE6_FIELD_EXPR_OPERANDS_228 }, + Stage6FieldExprPlan { symbol: "stage6.inc_claim_reduction.claim.rd_inc_stage4.gamma_pow", kind: "op", formula: "field.pow:2", operand_names: STAGE6_FIELD_EXPR_OPERANDS_227, operands: STAGE6_FIELD_EXPR_OPERANDS_227 }, + Stage6FieldExprPlan { symbol: "stage6.inc_claim_reduction.claim.rd_inc_stage4.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_229, operands: STAGE6_FIELD_EXPR_OPERANDS_229 }, + Stage6FieldExprPlan { symbol: "stage6.inc_claim_reduction.claim.rd_inc_stage5.gamma_pow", kind: "op", formula: "field.pow:3", operand_names: STAGE6_FIELD_EXPR_OPERANDS_227, operands: STAGE6_FIELD_EXPR_OPERANDS_227 }, + Stage6FieldExprPlan { symbol: "stage6.inc_claim_reduction.claim.rd_inc_stage5.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_230, operands: STAGE6_FIELD_EXPR_OPERANDS_230 }, + Stage6FieldExprPlan { symbol: "stage6.inc_claim_reduction.claim_expr.partial0", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_231, operands: STAGE6_FIELD_EXPR_OPERANDS_231 }, + Stage6FieldExprPlan { symbol: "stage6.inc_claim_reduction.claim_expr.partial1", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_232, operands: STAGE6_FIELD_EXPR_OPERANDS_232 }, + Stage6FieldExprPlan { symbol: "stage6.inc_claim_reduction.claim_expr.partial2", kind: "op", formula: "field.add", operand_names: STAGE6_FIELD_EXPR_OPERANDS_233, operands: STAGE6_FIELD_EXPR_OPERANDS_233 }, +]; +pub const STAGE6_KERNELS: &[Stage6KernelPlan] = &[ + Stage6KernelPlan { symbol: "jolt.cpu.stage6.bytecode_read_raf", relation: "jolt.stage6.bytecode_read_raf", kind: "sumcheck", backend: "cpu", abi: "jolt_stage6_bytecode_read_raf" }, + Stage6KernelPlan { symbol: "jolt.cpu.stage6.booleanity", relation: "jolt.stage6.booleanity", kind: "sumcheck", backend: "cpu", abi: "jolt_stage6_booleanity" }, + Stage6KernelPlan { symbol: "jolt.cpu.stage6.hamming_booleanity", relation: "jolt.stage6.hamming_booleanity", kind: "sumcheck", backend: "cpu", abi: "jolt_stage6_hamming_booleanity" }, + Stage6KernelPlan { symbol: "jolt.cpu.stage6.ram_ra_virtual", relation: "jolt.stage6.ram_ra_virtual", kind: "sumcheck", backend: "cpu", abi: "jolt_stage6_ram_ra_virtual" }, + Stage6KernelPlan { symbol: "jolt.cpu.stage6.instruction_ra_virtual", relation: "jolt.stage6.instruction_ra_virtual", kind: "sumcheck", backend: "cpu", abi: "jolt_stage6_instruction_ra_virtual" }, + Stage6KernelPlan { symbol: "jolt.cpu.stage6.inc_claim_reduction", relation: "jolt.stage6.inc_claim_reduction", kind: "sumcheck", backend: "cpu", abi: "jolt_stage6_inc_claim_reduction" }, + Stage6KernelPlan { symbol: "jolt.cpu.stage6.batched", relation: "jolt.stage6.batched", kind: "sumcheck", backend: "cpu", abi: "jolt_stage6_batched" }, +]; + +pub const STAGE6_SUMCHECK_CLAIM_0_INPUT_OPENINGS: &[&str] = &[ + "stage6.input.stage1.UnexpandedPC", + "stage6.input.stage1.Imm", + "stage6.input.stage1.OpFlagAddOperands", + "stage6.input.stage1.OpFlagSubtractOperands", + "stage6.input.stage1.OpFlagMultiplyOperands", + "stage6.input.stage1.OpFlagLoad", + "stage6.input.stage1.OpFlagStore", + "stage6.input.stage1.OpFlagJump", + "stage6.input.stage1.OpFlagWriteLookupOutputToRD", + "stage6.input.stage1.OpFlagVirtualInstruction", + "stage6.input.stage1.OpFlagAssert", + "stage6.input.stage1.OpFlagDoNotUpdateUnexpandedPC", + "stage6.input.stage1.OpFlagAdvice", + "stage6.input.stage1.OpFlagIsCompressed", + "stage6.input.stage1.OpFlagIsFirstInSequence", + "stage6.input.stage1.OpFlagIsLastInSequence", + "stage6.input.stage2.OpFlagJump", + "stage6.input.stage2.InstructionFlagBranch", + "stage6.input.stage2.OpFlagWriteLookupOutputToRD", + "stage6.input.stage2.OpFlagVirtualInstruction", + "stage6.input.stage3.instruction_input.Imm", + "stage6.input.stage3.spartan_shift.UnexpandedPC", + "stage6.input.stage3.instruction_input.InstructionFlagLeftOperandIsRs1Value", + "stage6.input.stage3.instruction_input.InstructionFlagLeftOperandIsPC", + "stage6.input.stage3.instruction_input.InstructionFlagRightOperandIsRs2Value", + "stage6.input.stage3.instruction_input.InstructionFlagRightOperandIsImm", + "stage6.input.stage3.spartan_shift.InstructionFlagIsNoop", + "stage6.input.stage3.spartan_shift.OpFlagVirtualInstruction", + "stage6.input.stage3.spartan_shift.OpFlagIsFirstInSequence", + "stage6.input.stage4.RdWa", + "stage6.input.stage4.Rs1Ra", + "stage6.input.stage4.Rs2Ra", + "stage6.input.stage5.registers_val_evaluation.RdWa", + "stage6.input.stage5.InstructionRafFlag", + "stage6.input.stage5.LookupTableFlag_0", + "stage6.input.stage5.LookupTableFlag_1", + "stage6.input.stage5.LookupTableFlag_2", + "stage6.input.stage5.LookupTableFlag_3", + "stage6.input.stage5.LookupTableFlag_4", + "stage6.input.stage5.LookupTableFlag_5", + "stage6.input.stage5.LookupTableFlag_6", + "stage6.input.stage5.LookupTableFlag_7", + "stage6.input.stage5.LookupTableFlag_8", + "stage6.input.stage5.LookupTableFlag_9", + "stage6.input.stage5.LookupTableFlag_10", + "stage6.input.stage5.LookupTableFlag_11", + "stage6.input.stage5.LookupTableFlag_12", + "stage6.input.stage5.LookupTableFlag_13", + "stage6.input.stage5.LookupTableFlag_14", + "stage6.input.stage5.LookupTableFlag_15", + "stage6.input.stage5.LookupTableFlag_16", + "stage6.input.stage5.LookupTableFlag_17", + "stage6.input.stage5.LookupTableFlag_18", + "stage6.input.stage5.LookupTableFlag_19", + "stage6.input.stage5.LookupTableFlag_20", + "stage6.input.stage5.LookupTableFlag_21", + "stage6.input.stage5.LookupTableFlag_22", + "stage6.input.stage5.LookupTableFlag_23", + "stage6.input.stage5.LookupTableFlag_24", + "stage6.input.stage5.LookupTableFlag_25", + "stage6.input.stage5.LookupTableFlag_26", + "stage6.input.stage5.LookupTableFlag_27", + "stage6.input.stage5.LookupTableFlag_28", + "stage6.input.stage5.LookupTableFlag_29", + "stage6.input.stage5.LookupTableFlag_30", + "stage6.input.stage5.LookupTableFlag_31", + "stage6.input.stage5.LookupTableFlag_32", + "stage6.input.stage5.LookupTableFlag_33", + "stage6.input.stage5.LookupTableFlag_34", + "stage6.input.stage5.LookupTableFlag_35", + "stage6.input.stage5.LookupTableFlag_36", + "stage6.input.stage5.LookupTableFlag_37", + "stage6.input.stage5.LookupTableFlag_38", + "stage6.input.stage5.LookupTableFlag_39", + "stage6.input.stage1.PC", + "stage6.input.stage3.spartan_shift.PC", +]; + +pub const STAGE6_SUMCHECK_CLAIM_1_INPUT_OPENINGS: &[&str] = &[]; + +pub const STAGE6_SUMCHECK_CLAIM_2_INPUT_OPENINGS: &[&str] = &["stage6.input.stage1.LookupOutput"]; + +pub const STAGE6_SUMCHECK_CLAIM_3_INPUT_OPENINGS: &[&str] = &["stage6.input.stage5.ram_ra_claim_reduction.RamRa"]; + +pub const STAGE6_SUMCHECK_CLAIM_4_INPUT_OPENINGS: &[&str] = &[ + "stage6.input.stage5.instruction_read_raf.InstructionRa_0", + "stage6.input.stage5.instruction_read_raf.InstructionRa_1", + "stage6.input.stage5.instruction_read_raf.InstructionRa_2", + "stage6.input.stage5.instruction_read_raf.InstructionRa_3", + "stage6.input.stage5.instruction_read_raf.InstructionRa_4", + "stage6.input.stage5.instruction_read_raf.InstructionRa_5", + "stage6.input.stage5.instruction_read_raf.InstructionRa_6", + "stage6.input.stage5.instruction_read_raf.InstructionRa_7", +]; + +pub const STAGE6_SUMCHECK_CLAIM_5_INPUT_OPENINGS: &[&str] = &[ + "stage6.input.stage2.ram_read_write.RamInc", + "stage6.input.stage4.ram_val_check.RamInc", + "stage6.input.stage4.registers_read_write.RdInc", + "stage6.input.stage5.registers_val_evaluation.RdInc", +]; + +pub const STAGE6_SUMCHECK_CLAIMS: &[Stage6SumcheckClaimPlan] = &[ + Stage6SumcheckClaimPlan { symbol: "stage6.bytecode_read_raf.input", stage: "stage6", domain: "jolt.stage6_bytecode_read_raf_domain", num_rounds: 26, degree: 4, claim: "stage6.bytecode_read_raf.weighted_prior_stage_values", kernel: Some("jolt.cpu.stage6.bytecode_read_raf"), relation: None, claim_value: "stage6.bytecode_read_raf.claim_expr.partial75", input_openings: STAGE6_SUMCHECK_CLAIM_0_INPUT_OPENINGS }, + Stage6SumcheckClaimPlan { symbol: "stage6.booleanity.input", stage: "stage6", domain: "jolt.stage6_booleanity_domain", num_rounds: 20, degree: 3, claim: "stage6.booleanity.zero", kernel: Some("jolt.cpu.stage6.booleanity"), relation: None, claim_value: "stage6.zero", input_openings: STAGE6_SUMCHECK_CLAIM_1_INPUT_OPENINGS }, + Stage6SumcheckClaimPlan { symbol: "stage6.hamming_booleanity.input", stage: "stage6", domain: "jolt.trace_domain", num_rounds: 16, degree: 3, claim: "stage6.hamming_booleanity.zero", kernel: Some("jolt.cpu.stage6.hamming_booleanity"), relation: None, claim_value: "stage6.zero", input_openings: STAGE6_SUMCHECK_CLAIM_2_INPUT_OPENINGS }, + Stage6SumcheckClaimPlan { symbol: "stage6.ram_ra_virtual.input", stage: "stage6", domain: "jolt.trace_domain", num_rounds: 16, degree: 5, claim: "stage6.ram_ra_virtual.weighted_ram_ra", kernel: Some("jolt.cpu.stage6.ram_ra_virtual"), relation: None, claim_value: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", input_openings: STAGE6_SUMCHECK_CLAIM_3_INPUT_OPENINGS }, + Stage6SumcheckClaimPlan { symbol: "stage6.instruction_ra_virtual.input", stage: "stage6", domain: "jolt.trace_domain", num_rounds: 16, degree: 5, claim: "stage6.instruction_ra_virtual.weighted_instruction_ra", kernel: Some("jolt.cpu.stage6.instruction_ra_virtual"), relation: None, claim_value: "stage6.instruction_ra_virtual.claim_expr.partial6", input_openings: STAGE6_SUMCHECK_CLAIM_4_INPUT_OPENINGS }, + Stage6SumcheckClaimPlan { symbol: "stage6.inc_claim_reduction.input", stage: "stage6", domain: "jolt.trace_domain", num_rounds: 16, degree: 2, claim: "stage6.inc_claim_reduction.weighted_increments", kernel: Some("jolt.cpu.stage6.inc_claim_reduction"), relation: None, claim_value: "stage6.inc_claim_reduction.claim_expr.partial2", input_openings: STAGE6_SUMCHECK_CLAIM_5_INPUT_OPENINGS }, +]; +pub const STAGE6_SUMCHECK_BATCH_0_ORDERED_CLAIMS: &[&str] = &[ + "stage6.bytecode_read_raf.input", + "stage6.booleanity.input", + "stage6.hamming_booleanity.input", + "stage6.ram_ra_virtual.input", + "stage6.instruction_ra_virtual.input", + "stage6.inc_claim_reduction.input", +]; + +pub const STAGE6_SUMCHECK_BATCH_0_CLAIM_OPERANDS: &[&str] = &[ + "stage6.bytecode_read_raf.input", + "stage6.booleanity.input", + "stage6.hamming_booleanity.input", + "stage6.ram_ra_virtual.input", + "stage6.instruction_ra_virtual.input", + "stage6.inc_claim_reduction.input", +]; + +pub const STAGE6_SUMCHECK_BATCH_0_ROUND_SCHEDULE: &[usize] = &[ + 10, + 16, +]; + +pub const STAGE6_SUMCHECK_BATCHES: &[Stage6SumcheckBatchPlan] = &[ + Stage6SumcheckBatchPlan { symbol: "stage6.batch", stage: "stage6", proof_slot: "stage6.sumcheck", policy: "jolt_core_stage6_aligned", count: 6, ordered_claims: STAGE6_SUMCHECK_BATCH_0_ORDERED_CLAIMS, claim_operands: STAGE6_SUMCHECK_BATCH_0_CLAIM_OPERANDS, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", round_schedule: STAGE6_SUMCHECK_BATCH_0_ROUND_SCHEDULE }, +]; +pub const STAGE6_SUMCHECK_DRIVER_0_ROUND_SCHEDULE: &[usize] = &[ + 10, + 16, +]; + +pub const STAGE6_SUMCHECK_DRIVERS: &[Stage6SumcheckDriverPlan] = &[ + Stage6SumcheckDriverPlan { symbol: "stage6.sumcheck", stage: "stage6", proof_slot: "stage6.sumcheck", kernel: Some("jolt.cpu.stage6.batched"), relation: None, batch: "stage6.batch", policy: "jolt_core_stage6_aligned", round_schedule: STAGE6_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 26, degree: 5 }, +]; +pub const STAGE6_SUMCHECK_INSTANCE_RESULTS: &[Stage6SumcheckInstanceResultPlan] = &[ + Stage6SumcheckInstanceResultPlan { symbol: "stage6.bytecode_read_raf.instance", source: "stage6.sumcheck", claim: "stage6.bytecode_read_raf.input", relation: "jolt.stage6.bytecode_read_raf", index: 0, point_arity: 26, num_rounds: 26, round_offset: 0, point_order: "bytecode_read_raf", degree: 4 }, + Stage6SumcheckInstanceResultPlan { symbol: "stage6.booleanity.instance", source: "stage6.sumcheck", claim: "stage6.booleanity.input", relation: "jolt.stage6.booleanity", index: 1, point_arity: 20, num_rounds: 20, round_offset: 6, point_order: "stage6_booleanity", degree: 3 }, + Stage6SumcheckInstanceResultPlan { symbol: "stage6.hamming_booleanity.instance", source: "stage6.sumcheck", claim: "stage6.hamming_booleanity.input", relation: "jolt.stage6.hamming_booleanity", index: 2, point_arity: 16, num_rounds: 16, round_offset: 10, point_order: "reverse", degree: 3 }, + Stage6SumcheckInstanceResultPlan { symbol: "stage6.ram_ra_virtual.instance", source: "stage6.sumcheck", claim: "stage6.ram_ra_virtual.input", relation: "jolt.stage6.ram_ra_virtual", index: 3, point_arity: 16, num_rounds: 16, round_offset: 10, point_order: "reverse", degree: 5 }, + Stage6SumcheckInstanceResultPlan { symbol: "stage6.instruction_ra_virtual.instance", source: "stage6.sumcheck", claim: "stage6.instruction_ra_virtual.input", relation: "jolt.stage6.instruction_ra_virtual", index: 4, point_arity: 16, num_rounds: 16, round_offset: 10, point_order: "reverse", degree: 5 }, + Stage6SumcheckInstanceResultPlan { symbol: "stage6.inc_claim_reduction.instance", source: "stage6.sumcheck", claim: "stage6.inc_claim_reduction.input", relation: "jolt.stage6.inc_claim_reduction", index: 5, point_arity: 16, num_rounds: 16, round_offset: 10, point_order: "reverse", degree: 2 }, +]; + +macro_rules! stage6_sumcheck_eval { + ($symbol:literal, $source:literal, $name:literal, $index:literal, $oracle:literal) => { + Stage6SumcheckEvalPlan { symbol: $symbol, source: $source, name: $name, index: $index, oracle: $oracle } + }; +} + +#[rustfmt::skip] +pub const STAGE6_SUMCHECK_EVALS: &[Stage6SumcheckEvalPlan] = &[ + stage6_sumcheck_eval!("stage6.bytecode_read_raf.eval.BytecodeRa_0", "stage6.sumcheck", "stage6.bytecode_read_raf.eval.BytecodeRa_0", 0, "BytecodeRa_0"), stage6_sumcheck_eval!("stage6.bytecode_read_raf.eval.BytecodeRa_1", "stage6.sumcheck", "stage6.bytecode_read_raf.eval.BytecodeRa_1", 1, "BytecodeRa_1"), stage6_sumcheck_eval!("stage6.bytecode_read_raf.eval.BytecodeRa_2", "stage6.sumcheck", "stage6.bytecode_read_raf.eval.BytecodeRa_2", 2, "BytecodeRa_2"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_0", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_0", 0, "InstructionRa_0"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_1", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_1", 1, "InstructionRa_1"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_2", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_2", 2, "InstructionRa_2"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_3", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_3", 3, "InstructionRa_3"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_4", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_4", 4, "InstructionRa_4"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_5", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_5", 5, "InstructionRa_5"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_6", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_6", 6, "InstructionRa_6"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_7", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_7", 7, "InstructionRa_7"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_8", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_8", 8, "InstructionRa_8"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_9", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_9", 9, "InstructionRa_9"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_10", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_10", 10, "InstructionRa_10"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_11", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_11", 11, "InstructionRa_11"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_12", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_12", 12, "InstructionRa_12"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_13", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_13", 13, "InstructionRa_13"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_14", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_14", 14, "InstructionRa_14"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_15", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_15", 15, "InstructionRa_15"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_16", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_16", 16, "InstructionRa_16"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_17", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_17", 17, "InstructionRa_17"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_18", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_18", 18, "InstructionRa_18"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_19", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_19", 19, "InstructionRa_19"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_20", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_20", 20, "InstructionRa_20"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_21", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_21", 21, "InstructionRa_21"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_22", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_22", 22, "InstructionRa_22"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_23", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_23", 23, "InstructionRa_23"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_24", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_24", 24, "InstructionRa_24"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_25", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_25", 25, "InstructionRa_25"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_26", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_26", 26, "InstructionRa_26"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_27", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_27", 27, "InstructionRa_27"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_28", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_28", 28, "InstructionRa_28"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_29", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_29", 29, "InstructionRa_29"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_30", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_30", 30, "InstructionRa_30"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_31", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_31", 31, "InstructionRa_31"), stage6_sumcheck_eval!("stage6.booleanity.eval.BytecodeRa_0", "stage6.sumcheck", "stage6.booleanity.eval.BytecodeRa_0", 32, "BytecodeRa_0"), + stage6_sumcheck_eval!("stage6.booleanity.eval.BytecodeRa_1", "stage6.sumcheck", "stage6.booleanity.eval.BytecodeRa_1", 33, "BytecodeRa_1"), stage6_sumcheck_eval!("stage6.booleanity.eval.BytecodeRa_2", "stage6.sumcheck", "stage6.booleanity.eval.BytecodeRa_2", 34, "BytecodeRa_2"), stage6_sumcheck_eval!("stage6.booleanity.eval.RamRa_0", "stage6.sumcheck", "stage6.booleanity.eval.RamRa_0", 35, "RamRa_0"), stage6_sumcheck_eval!("stage6.booleanity.eval.RamRa_1", "stage6.sumcheck", "stage6.booleanity.eval.RamRa_1", 36, "RamRa_1"), + stage6_sumcheck_eval!("stage6.booleanity.eval.RamRa_2", "stage6.sumcheck", "stage6.booleanity.eval.RamRa_2", 37, "RamRa_2"), stage6_sumcheck_eval!("stage6.booleanity.eval.RamRa_3", "stage6.sumcheck", "stage6.booleanity.eval.RamRa_3", 38, "RamRa_3"), stage6_sumcheck_eval!("stage6.hamming_booleanity.eval.HammingWeight", "stage6.sumcheck", "stage6.hamming_booleanity.eval.HammingWeight", 0, "HammingWeight"), stage6_sumcheck_eval!("stage6.ram_ra_virtual.eval.RamRa_0", "stage6.sumcheck", "stage6.ram_ra_virtual.eval.RamRa_0", 0, "RamRa_0"), + stage6_sumcheck_eval!("stage6.ram_ra_virtual.eval.RamRa_1", "stage6.sumcheck", "stage6.ram_ra_virtual.eval.RamRa_1", 1, "RamRa_1"), stage6_sumcheck_eval!("stage6.ram_ra_virtual.eval.RamRa_2", "stage6.sumcheck", "stage6.ram_ra_virtual.eval.RamRa_2", 2, "RamRa_2"), stage6_sumcheck_eval!("stage6.ram_ra_virtual.eval.RamRa_3", "stage6.sumcheck", "stage6.ram_ra_virtual.eval.RamRa_3", 3, "RamRa_3"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_0", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_0", 0, "InstructionRa_0"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_1", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_1", 1, "InstructionRa_1"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_2", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_2", 2, "InstructionRa_2"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_3", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_3", 3, "InstructionRa_3"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_4", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_4", 4, "InstructionRa_4"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_5", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_5", 5, "InstructionRa_5"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_6", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_6", 6, "InstructionRa_6"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_7", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_7", 7, "InstructionRa_7"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_8", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_8", 8, "InstructionRa_8"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_9", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_9", 9, "InstructionRa_9"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_10", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_10", 10, "InstructionRa_10"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_11", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_11", 11, "InstructionRa_11"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_12", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_12", 12, "InstructionRa_12"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_13", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_13", 13, "InstructionRa_13"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_14", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_14", 14, "InstructionRa_14"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_15", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_15", 15, "InstructionRa_15"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_16", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_16", 16, "InstructionRa_16"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_17", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_17", 17, "InstructionRa_17"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_18", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_18", 18, "InstructionRa_18"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_19", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_19", 19, "InstructionRa_19"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_20", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_20", 20, "InstructionRa_20"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_21", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_21", 21, "InstructionRa_21"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_22", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_22", 22, "InstructionRa_22"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_23", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_23", 23, "InstructionRa_23"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_24", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_24", 24, "InstructionRa_24"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_25", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_25", 25, "InstructionRa_25"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_26", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_26", 26, "InstructionRa_26"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_27", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_27", 27, "InstructionRa_27"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_28", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_28", 28, "InstructionRa_28"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_29", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_29", 29, "InstructionRa_29"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_30", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_30", 30, "InstructionRa_30"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_31", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_31", 31, "InstructionRa_31"), stage6_sumcheck_eval!("stage6.inc_claim_reduction.eval.RamInc", "stage6.sumcheck", "stage6.inc_claim_reduction.eval.RamInc", 0, "RamInc"), + stage6_sumcheck_eval!("stage6.inc_claim_reduction.eval.RdInc", "stage6.sumcheck", "stage6.inc_claim_reduction.eval.RdInc", 1, "RdInc"), +]; + +pub const STAGE6_POINT_ZEROS: &[Stage6PointZeroPlan] = &[ + Stage6PointZeroPlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_0.address.zero_pad", field: "bn254_fr", arity: 2 }, +]; + +pub const STAGE6_POINT_SLICES: &[Stage6PointSlicePlan] = &[ + Stage6PointSlicePlan { symbol: "stage6.bytecode_read_raf.point.Cycle", source: "stage6.bytecode_read_raf.instance", offset: 10, length: 16, input: "stage6.bytecode_read_raf.instance" }, + Stage6PointSlicePlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_0.address.source", source: "stage6.bytecode_read_raf.instance", offset: 0, length: 2, input: "stage6.bytecode_read_raf.instance" }, + Stage6PointSlicePlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_1.address", source: "stage6.bytecode_read_raf.instance", offset: 2, length: 4, input: "stage6.bytecode_read_raf.instance" }, + Stage6PointSlicePlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_2.address", source: "stage6.bytecode_read_raf.instance", offset: 6, length: 4, input: "stage6.bytecode_read_raf.instance" }, + Stage6PointSlicePlan { symbol: "stage6.ram_ra_virtual.point.RamRa_0.address", source: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", offset: 0, length: 4, input: "stage6.input.stage5.ram_ra_claim_reduction.RamRa" }, + Stage6PointSlicePlan { symbol: "stage6.ram_ra_virtual.point.RamRa_1.address", source: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", offset: 4, length: 4, input: "stage6.input.stage5.ram_ra_claim_reduction.RamRa" }, + Stage6PointSlicePlan { symbol: "stage6.ram_ra_virtual.point.RamRa_2.address", source: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", offset: 8, length: 4, input: "stage6.input.stage5.ram_ra_claim_reduction.RamRa" }, + Stage6PointSlicePlan { symbol: "stage6.ram_ra_virtual.point.RamRa_3.address", source: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", offset: 12, length: 4, input: "stage6.input.stage5.ram_ra_claim_reduction.RamRa" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_0.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", offset: 0, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_0" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_1.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", offset: 4, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_0" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_2.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", offset: 8, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_0" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_3.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", offset: 12, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_0" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_4.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_1", offset: 0, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_1" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_5.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_1", offset: 4, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_1" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_6.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_1", offset: 8, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_1" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_7.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_1", offset: 12, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_1" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_8.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_2", offset: 0, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_2" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_9.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_2", offset: 4, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_2" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_10.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_2", offset: 8, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_2" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_11.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_2", offset: 12, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_2" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_12.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_3", offset: 0, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_3" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_13.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_3", offset: 4, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_3" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_14.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_3", offset: 8, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_3" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_15.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_3", offset: 12, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_3" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_16.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_4", offset: 0, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_4" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_17.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_4", offset: 4, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_4" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_18.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_4", offset: 8, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_4" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_19.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_4", offset: 12, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_4" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_20.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_5", offset: 0, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_5" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_21.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_5", offset: 4, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_5" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_22.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_5", offset: 8, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_5" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_23.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_5", offset: 12, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_5" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_24.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_6", offset: 0, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_6" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_25.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_6", offset: 4, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_6" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_26.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_6", offset: 8, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_6" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_27.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_6", offset: 12, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_6" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_28.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_7", offset: 0, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_7" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_29.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_7", offset: 4, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_7" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_30.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_7", offset: 8, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_7" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_31.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_7", offset: 12, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_7" }, +]; + +pub const STAGE6_POINT_CONCAT_0_INPUTS: &[&str] = &[ + "stage6.bytecode_read_raf.point.BytecodeRa_0.address.zero_pad", + "stage6.bytecode_read_raf.point.BytecodeRa_0.address.source", +]; + +pub const STAGE6_POINT_CONCAT_1_INPUTS: &[&str] = &[ + "stage6.bytecode_read_raf.point.BytecodeRa_0.address", + "stage6.bytecode_read_raf.point.Cycle", +]; + +pub const STAGE6_POINT_CONCAT_2_INPUTS: &[&str] = &[ + "stage6.bytecode_read_raf.point.BytecodeRa_1.address", + "stage6.bytecode_read_raf.point.Cycle", +]; + +pub const STAGE6_POINT_CONCAT_3_INPUTS: &[&str] = &[ + "stage6.bytecode_read_raf.point.BytecodeRa_2.address", + "stage6.bytecode_read_raf.point.Cycle", +]; + +pub const STAGE6_POINT_CONCAT_4_INPUTS: &[&str] = &[ + "stage6.ram_ra_virtual.point.RamRa_0.address", + "stage6.ram_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_5_INPUTS: &[&str] = &[ + "stage6.ram_ra_virtual.point.RamRa_1.address", + "stage6.ram_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_6_INPUTS: &[&str] = &[ + "stage6.ram_ra_virtual.point.RamRa_2.address", + "stage6.ram_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_7_INPUTS: &[&str] = &[ + "stage6.ram_ra_virtual.point.RamRa_3.address", + "stage6.ram_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_8_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_0.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_9_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_1.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_10_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_2.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_11_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_3.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_12_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_4.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_13_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_5.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_14_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_6.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_15_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_7.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_16_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_8.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_17_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_9.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_18_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_10.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_19_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_11.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_20_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_12.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_21_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_13.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_22_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_14.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_23_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_15.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_24_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_16.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_25_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_17.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_26_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_18.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_27_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_19.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_28_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_20.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_29_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_21.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_30_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_22.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_31_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_23.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_32_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_24.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_33_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_25.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_34_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_26.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_35_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_27.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_36_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_28.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_37_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_29.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_38_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_30.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCAT_39_INPUTS: &[&str] = &[ + "stage6.instruction_ra_virtual.point.InstructionRa_31.address", + "stage6.instruction_ra_virtual.instance", +]; + +pub const STAGE6_POINT_CONCATS: &[Stage6PointConcatPlan] = &[ + Stage6PointConcatPlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_0.address", layout: "left_zero_padded_address_chunk", arity: 4, inputs: STAGE6_POINT_CONCAT_0_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_0", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_1_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_1", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_2_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_2", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_3_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.ram_ra_virtual.point.RamRa_0", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_4_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.ram_ra_virtual.point.RamRa_1", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_5_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.ram_ra_virtual.point.RamRa_2", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_6_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.ram_ra_virtual.point.RamRa_3", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_7_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_0", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_8_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_1", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_9_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_2", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_10_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_3", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_11_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_4", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_12_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_5", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_13_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_6", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_14_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_7", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_15_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_8", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_16_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_9", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_17_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_10", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_18_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_11", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_19_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_12", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_20_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_13", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_21_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_14", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_22_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_15", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_23_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_16", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_24_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_17", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_25_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_18", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_26_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_19", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_27_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_20", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_28_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_21", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_29_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_22", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_30_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_23", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_31_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_24", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_32_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_25", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_33_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_26", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_34_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_27", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_35_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_28", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_36_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_29", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_37_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_30", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_38_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_31", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_39_INPUTS }, +]; +pub const STAGE6_OPENING_CLAIMS: &[Stage6OpeningClaimPlan] = &[ + Stage6OpeningClaimPlan { symbol: "stage6.bytecode_read_raf.opening.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.bytecode_read_raf.point.BytecodeRa_0", eval_source: "stage6.bytecode_read_raf.eval.BytecodeRa_0" }, + Stage6OpeningClaimPlan { symbol: "stage6.bytecode_read_raf.opening.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.bytecode_read_raf.point.BytecodeRa_1", eval_source: "stage6.bytecode_read_raf.eval.BytecodeRa_1" }, + Stage6OpeningClaimPlan { symbol: "stage6.bytecode_read_raf.opening.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.bytecode_read_raf.point.BytecodeRa_2", eval_source: "stage6.bytecode_read_raf.eval.BytecodeRa_2" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_0" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_1" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_2" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_3" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_4" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_5" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_6" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_7" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_8" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_9" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_10" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_11" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_12" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_13" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_14" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_15" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_16" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_17" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_18" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_19" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_20" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_21" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_22" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_23" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_24" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_25" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_26" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_27" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_28" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_29" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_30" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_31" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.BytecodeRa_0" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.BytecodeRa_1" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.BytecodeRa_2" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.RamRa_0" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.RamRa_1" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.RamRa_2" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.RamRa_3" }, + Stage6OpeningClaimPlan { symbol: "stage6.hamming_booleanity.opening.HammingWeight", oracle: "HammingWeight", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage6.hamming_booleanity.instance", eval_source: "stage6.hamming_booleanity.eval.HammingWeight" }, + Stage6OpeningClaimPlan { symbol: "stage6.ram_ra_virtual.opening.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.ram_ra_virtual.point.RamRa_0", eval_source: "stage6.ram_ra_virtual.eval.RamRa_0" }, + Stage6OpeningClaimPlan { symbol: "stage6.ram_ra_virtual.opening.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.ram_ra_virtual.point.RamRa_1", eval_source: "stage6.ram_ra_virtual.eval.RamRa_1" }, + Stage6OpeningClaimPlan { symbol: "stage6.ram_ra_virtual.opening.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.ram_ra_virtual.point.RamRa_2", eval_source: "stage6.ram_ra_virtual.eval.RamRa_2" }, + Stage6OpeningClaimPlan { symbol: "stage6.ram_ra_virtual.opening.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.ram_ra_virtual.point.RamRa_3", eval_source: "stage6.ram_ra_virtual.eval.RamRa_3" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_0", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_0" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_1", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_1" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_2", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_2" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_3", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_3" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_4", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_4" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_5", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_5" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_6", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_6" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_7", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_7" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_8", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_8" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_9", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_9" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_10", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_10" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_11", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_11" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_12", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_12" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_13", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_13" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_14", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_14" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_15", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_15" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_16", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_16" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_17", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_17" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_18", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_18" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_19", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_19" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_20", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_20" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_21", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_21" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_22", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_22" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_23", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_23" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_24", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_24" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_25", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_25" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_26", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_26" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_27", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_27" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_28", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_28" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_29", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_29" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_30", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_30" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_31", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_31" }, + Stage6OpeningClaimPlan { symbol: "stage6.inc_claim_reduction.opening.RamInc", oracle: "RamInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed", point_source: "stage6.inc_claim_reduction.instance", eval_source: "stage6.inc_claim_reduction.eval.RamInc" }, + Stage6OpeningClaimPlan { symbol: "stage6.inc_claim_reduction.opening.RdInc", oracle: "RdInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed", point_source: "stage6.inc_claim_reduction.instance", eval_source: "stage6.inc_claim_reduction.eval.RdInc" }, +]; + +pub const STAGE6_OPENING_EQUALITIES: &[Stage6OpeningClaimEqualityPlan] = &[ + +]; + +pub const STAGE6_OPENING_BATCH_0_ORDERED_CLAIMS: &[&str] = &[ + "stage6.bytecode_read_raf.opening.BytecodeRa_0", + "stage6.bytecode_read_raf.opening.BytecodeRa_1", + "stage6.bytecode_read_raf.opening.BytecodeRa_2", + "stage6.booleanity.opening.InstructionRa_0", + "stage6.booleanity.opening.InstructionRa_1", + "stage6.booleanity.opening.InstructionRa_2", + "stage6.booleanity.opening.InstructionRa_3", + "stage6.booleanity.opening.InstructionRa_4", + "stage6.booleanity.opening.InstructionRa_5", + "stage6.booleanity.opening.InstructionRa_6", + "stage6.booleanity.opening.InstructionRa_7", + "stage6.booleanity.opening.InstructionRa_8", + "stage6.booleanity.opening.InstructionRa_9", + "stage6.booleanity.opening.InstructionRa_10", + "stage6.booleanity.opening.InstructionRa_11", + "stage6.booleanity.opening.InstructionRa_12", + "stage6.booleanity.opening.InstructionRa_13", + "stage6.booleanity.opening.InstructionRa_14", + "stage6.booleanity.opening.InstructionRa_15", + "stage6.booleanity.opening.InstructionRa_16", + "stage6.booleanity.opening.InstructionRa_17", + "stage6.booleanity.opening.InstructionRa_18", + "stage6.booleanity.opening.InstructionRa_19", + "stage6.booleanity.opening.InstructionRa_20", + "stage6.booleanity.opening.InstructionRa_21", + "stage6.booleanity.opening.InstructionRa_22", + "stage6.booleanity.opening.InstructionRa_23", + "stage6.booleanity.opening.InstructionRa_24", + "stage6.booleanity.opening.InstructionRa_25", + "stage6.booleanity.opening.InstructionRa_26", + "stage6.booleanity.opening.InstructionRa_27", + "stage6.booleanity.opening.InstructionRa_28", + "stage6.booleanity.opening.InstructionRa_29", + "stage6.booleanity.opening.InstructionRa_30", + "stage6.booleanity.opening.InstructionRa_31", + "stage6.booleanity.opening.BytecodeRa_0", + "stage6.booleanity.opening.BytecodeRa_1", + "stage6.booleanity.opening.BytecodeRa_2", + "stage6.booleanity.opening.RamRa_0", + "stage6.booleanity.opening.RamRa_1", + "stage6.booleanity.opening.RamRa_2", + "stage6.booleanity.opening.RamRa_3", + "stage6.hamming_booleanity.opening.HammingWeight", + "stage6.ram_ra_virtual.opening.RamRa_0", + "stage6.ram_ra_virtual.opening.RamRa_1", + "stage6.ram_ra_virtual.opening.RamRa_2", + "stage6.ram_ra_virtual.opening.RamRa_3", + "stage6.instruction_ra_virtual.opening.InstructionRa_0", + "stage6.instruction_ra_virtual.opening.InstructionRa_1", + "stage6.instruction_ra_virtual.opening.InstructionRa_2", + "stage6.instruction_ra_virtual.opening.InstructionRa_3", + "stage6.instruction_ra_virtual.opening.InstructionRa_4", + "stage6.instruction_ra_virtual.opening.InstructionRa_5", + "stage6.instruction_ra_virtual.opening.InstructionRa_6", + "stage6.instruction_ra_virtual.opening.InstructionRa_7", + "stage6.instruction_ra_virtual.opening.InstructionRa_8", + "stage6.instruction_ra_virtual.opening.InstructionRa_9", + "stage6.instruction_ra_virtual.opening.InstructionRa_10", + "stage6.instruction_ra_virtual.opening.InstructionRa_11", + "stage6.instruction_ra_virtual.opening.InstructionRa_12", + "stage6.instruction_ra_virtual.opening.InstructionRa_13", + "stage6.instruction_ra_virtual.opening.InstructionRa_14", + "stage6.instruction_ra_virtual.opening.InstructionRa_15", + "stage6.instruction_ra_virtual.opening.InstructionRa_16", + "stage6.instruction_ra_virtual.opening.InstructionRa_17", + "stage6.instruction_ra_virtual.opening.InstructionRa_18", + "stage6.instruction_ra_virtual.opening.InstructionRa_19", + "stage6.instruction_ra_virtual.opening.InstructionRa_20", + "stage6.instruction_ra_virtual.opening.InstructionRa_21", + "stage6.instruction_ra_virtual.opening.InstructionRa_22", + "stage6.instruction_ra_virtual.opening.InstructionRa_23", + "stage6.instruction_ra_virtual.opening.InstructionRa_24", + "stage6.instruction_ra_virtual.opening.InstructionRa_25", + "stage6.instruction_ra_virtual.opening.InstructionRa_26", + "stage6.instruction_ra_virtual.opening.InstructionRa_27", + "stage6.instruction_ra_virtual.opening.InstructionRa_28", + "stage6.instruction_ra_virtual.opening.InstructionRa_29", + "stage6.instruction_ra_virtual.opening.InstructionRa_30", + "stage6.instruction_ra_virtual.opening.InstructionRa_31", + "stage6.inc_claim_reduction.opening.RamInc", + "stage6.inc_claim_reduction.opening.RdInc", +]; + +pub const STAGE6_OPENING_BATCH_0_CLAIM_OPERANDS: &[&str] = &[ + "stage6.bytecode_read_raf.opening.BytecodeRa_0", + "stage6.bytecode_read_raf.opening.BytecodeRa_1", + "stage6.bytecode_read_raf.opening.BytecodeRa_2", + "stage6.booleanity.opening.InstructionRa_0", + "stage6.booleanity.opening.InstructionRa_1", + "stage6.booleanity.opening.InstructionRa_2", + "stage6.booleanity.opening.InstructionRa_3", + "stage6.booleanity.opening.InstructionRa_4", + "stage6.booleanity.opening.InstructionRa_5", + "stage6.booleanity.opening.InstructionRa_6", + "stage6.booleanity.opening.InstructionRa_7", + "stage6.booleanity.opening.InstructionRa_8", + "stage6.booleanity.opening.InstructionRa_9", + "stage6.booleanity.opening.InstructionRa_10", + "stage6.booleanity.opening.InstructionRa_11", + "stage6.booleanity.opening.InstructionRa_12", + "stage6.booleanity.opening.InstructionRa_13", + "stage6.booleanity.opening.InstructionRa_14", + "stage6.booleanity.opening.InstructionRa_15", + "stage6.booleanity.opening.InstructionRa_16", + "stage6.booleanity.opening.InstructionRa_17", + "stage6.booleanity.opening.InstructionRa_18", + "stage6.booleanity.opening.InstructionRa_19", + "stage6.booleanity.opening.InstructionRa_20", + "stage6.booleanity.opening.InstructionRa_21", + "stage6.booleanity.opening.InstructionRa_22", + "stage6.booleanity.opening.InstructionRa_23", + "stage6.booleanity.opening.InstructionRa_24", + "stage6.booleanity.opening.InstructionRa_25", + "stage6.booleanity.opening.InstructionRa_26", + "stage6.booleanity.opening.InstructionRa_27", + "stage6.booleanity.opening.InstructionRa_28", + "stage6.booleanity.opening.InstructionRa_29", + "stage6.booleanity.opening.InstructionRa_30", + "stage6.booleanity.opening.InstructionRa_31", + "stage6.booleanity.opening.BytecodeRa_0", + "stage6.booleanity.opening.BytecodeRa_1", + "stage6.booleanity.opening.BytecodeRa_2", + "stage6.booleanity.opening.RamRa_0", + "stage6.booleanity.opening.RamRa_1", + "stage6.booleanity.opening.RamRa_2", + "stage6.booleanity.opening.RamRa_3", + "stage6.hamming_booleanity.opening.HammingWeight", + "stage6.ram_ra_virtual.opening.RamRa_0", + "stage6.ram_ra_virtual.opening.RamRa_1", + "stage6.ram_ra_virtual.opening.RamRa_2", + "stage6.ram_ra_virtual.opening.RamRa_3", + "stage6.instruction_ra_virtual.opening.InstructionRa_0", + "stage6.instruction_ra_virtual.opening.InstructionRa_1", + "stage6.instruction_ra_virtual.opening.InstructionRa_2", + "stage6.instruction_ra_virtual.opening.InstructionRa_3", + "stage6.instruction_ra_virtual.opening.InstructionRa_4", + "stage6.instruction_ra_virtual.opening.InstructionRa_5", + "stage6.instruction_ra_virtual.opening.InstructionRa_6", + "stage6.instruction_ra_virtual.opening.InstructionRa_7", + "stage6.instruction_ra_virtual.opening.InstructionRa_8", + "stage6.instruction_ra_virtual.opening.InstructionRa_9", + "stage6.instruction_ra_virtual.opening.InstructionRa_10", + "stage6.instruction_ra_virtual.opening.InstructionRa_11", + "stage6.instruction_ra_virtual.opening.InstructionRa_12", + "stage6.instruction_ra_virtual.opening.InstructionRa_13", + "stage6.instruction_ra_virtual.opening.InstructionRa_14", + "stage6.instruction_ra_virtual.opening.InstructionRa_15", + "stage6.instruction_ra_virtual.opening.InstructionRa_16", + "stage6.instruction_ra_virtual.opening.InstructionRa_17", + "stage6.instruction_ra_virtual.opening.InstructionRa_18", + "stage6.instruction_ra_virtual.opening.InstructionRa_19", + "stage6.instruction_ra_virtual.opening.InstructionRa_20", + "stage6.instruction_ra_virtual.opening.InstructionRa_21", + "stage6.instruction_ra_virtual.opening.InstructionRa_22", + "stage6.instruction_ra_virtual.opening.InstructionRa_23", + "stage6.instruction_ra_virtual.opening.InstructionRa_24", + "stage6.instruction_ra_virtual.opening.InstructionRa_25", + "stage6.instruction_ra_virtual.opening.InstructionRa_26", + "stage6.instruction_ra_virtual.opening.InstructionRa_27", + "stage6.instruction_ra_virtual.opening.InstructionRa_28", + "stage6.instruction_ra_virtual.opening.InstructionRa_29", + "stage6.instruction_ra_virtual.opening.InstructionRa_30", + "stage6.instruction_ra_virtual.opening.InstructionRa_31", + "stage6.inc_claim_reduction.opening.RamInc", + "stage6.inc_claim_reduction.opening.RdInc", +]; + +pub const STAGE6_OPENING_BATCHES: &[Stage6OpeningBatchPlan] = &[ + Stage6OpeningBatchPlan { symbol: "stage6.openings", stage: "stage6", proof_slot: "stage6.openings", policy: "jolt_stage6_output_order", count: 81, ordered_claims: STAGE6_OPENING_BATCH_0_ORDERED_CLAIMS, claim_operands: STAGE6_OPENING_BATCH_0_CLAIM_OPERANDS }, +]; +pub const STAGE6_PROGRAM: Stage6CpuProgramPlan = Stage6CpuProgramPlan { + role: "prover", + params: STAGE6_PARAMS, + steps: STAGE6_PROGRAM_STEPS, + transcript_squeezes: STAGE6_TRANSCRIPT_SQUEEZES, + transcript_absorb_bytes: STAGE6_TRANSCRIPT_ABSORB_BYTES, + opening_inputs: STAGE6_OPENING_INPUTS, + field_constants: STAGE6_FIELD_CONSTANTS, + field_exprs: STAGE6_FIELD_EXPRS, + kernels: STAGE6_KERNELS, + claims: STAGE6_SUMCHECK_CLAIMS, + batches: STAGE6_SUMCHECK_BATCHES, + drivers: STAGE6_SUMCHECK_DRIVERS, + instance_results: STAGE6_SUMCHECK_INSTANCE_RESULTS, + evals: STAGE6_SUMCHECK_EVALS, + point_zeros: STAGE6_POINT_ZEROS, + point_slices: STAGE6_POINT_SLICES, + point_concats: STAGE6_POINT_CONCATS, + opening_claims: STAGE6_OPENING_CLAIMS, + opening_equalities: STAGE6_OPENING_EQUALITIES, + opening_batches: STAGE6_OPENING_BATCHES, +}; + +pub fn execute_stage6_prover( + executor: &mut E, + transcript: &mut T, +) -> Result, Stage6KernelError> +where + E: Stage6KernelExecutor, + T: Transcript, +{ + execute_stage6_prover_with_program(&STAGE6_PROGRAM, executor, transcript) +} + +pub fn execute_stage6_prover_with_program( + program: &'static Stage6CpuProgramPlan, + executor: &mut E, + transcript: &mut T, +) -> Result, Stage6KernelError> +where + E: Stage6KernelExecutor, + T: Transcript, +{ + execute_stage6_program(program, Stage6ExecutionMode::Prover, executor, transcript) +} diff --git a/crates/jolt-prover/src/stages/stage7.rs b/crates/jolt-prover/src/stages/stage7.rs new file mode 100644 index 0000000000..831534a4b9 --- /dev/null +++ b/crates/jolt-prover/src/stages/stage7.rs @@ -0,0 +1,1950 @@ +#![allow(dead_code)] + +use jolt_field::Fr; +use jolt_kernels::stage7::{execute_stage7_program, Stage7CpuProgramPlan, Stage7ExecutionArtifacts, Stage7ExecutionMode, Stage7FieldConstantPlan, Stage7FieldExprPlan, Stage7KernelError, Stage7KernelExecutor, Stage7KernelPlan, Stage7OpeningBatchPlan, Stage7OpeningClaimEqualityPlan, Stage7OpeningClaimPlan, Stage7OpeningInputPlan, Stage7Params, Stage7PointConcatPlan, Stage7PointSlicePlan, Stage7PointZeroPlan, Stage7ProgramStepPlan, Stage7SumcheckBatchPlan, Stage7SumcheckClaimPlan, Stage7SumcheckDriverPlan, Stage7SumcheckEvalPlan, Stage7SumcheckInstanceResultPlan, Stage7TranscriptAbsorbBytesPlan, Stage7TranscriptSqueezePlan}; +use jolt_transcript::{Blake2bTranscript, Transcript}; + +pub type DefaultStage7Transcript = Blake2bTranscript; + +pub const STAGE7_PARAMS: Stage7Params = Stage7Params { + field: "bn254_fr", + pcs: "dory", + transcript: "blake2b_transcript", +}; +pub const STAGE7_PROGRAM_STEPS: &[Stage7ProgramStepPlan] = &[ + Stage7ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage7.hamming_weight_claim_reduction.gamma" }, + Stage7ProgramStepPlan { kind: "sumcheck_driver", symbol: "stage7.sumcheck" }, +]; + +pub const STAGE7_TRANSCRIPT_SQUEEZES: &[Stage7TranscriptSqueezePlan] = &[ + Stage7TranscriptSqueezePlan { symbol: "stage7.hamming_weight_claim_reduction.gamma", label: "hamming_weight_claim_reduction_gamma", kind: "challenge_scalar", count: 1 }, +]; + +pub const STAGE7_TRANSCRIPT_ABSORB_BYTES: &[Stage7TranscriptAbsorbBytesPlan] = &[ + +]; + +pub const STAGE7_OPENING_INPUTS: &[Stage7OpeningInputPlan] = &[ + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.hamming_booleanity.HammingWeight", source_stage: "stage6", source_claim: "stage6.hamming_booleanity.opening.HammingWeight", oracle: "HammingWeight", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_0", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_0", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_1", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_1", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_2", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_2", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_3", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_3", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_4", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_4", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_5", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_5", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_6", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_6", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_7", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_7", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_8", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_8", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_9", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_9", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_10", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_10", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_11", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_11", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_12", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_12", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_13", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_13", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_14", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_14", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_15", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_15", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_16", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_16", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_17", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_17", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_18", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_18", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_19", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_19", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_20", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_20", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_21", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_21", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_22", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_22", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_23", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_23", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_24", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_24", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_25", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_25", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_26", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_26", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_27", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_27", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_28", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_28", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_29", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_29", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_30", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_30", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_31", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_31", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.BytecodeRa_0", source_stage: "stage6", source_claim: "stage6.booleanity.opening.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.bytecode_read_raf.BytecodeRa_0", source_stage: "stage6", source_claim: "stage6.bytecode_read_raf.opening.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.BytecodeRa_1", source_stage: "stage6", source_claim: "stage6.booleanity.opening.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.bytecode_read_raf.BytecodeRa_1", source_stage: "stage6", source_claim: "stage6.bytecode_read_raf.opening.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.BytecodeRa_2", source_stage: "stage6", source_claim: "stage6.booleanity.opening.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.bytecode_read_raf.BytecodeRa_2", source_stage: "stage6", source_claim: "stage6.bytecode_read_raf.opening.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.RamRa_0", source_stage: "stage6", source_claim: "stage6.booleanity.opening.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.ram_ra_virtual.RamRa_0", source_stage: "stage6", source_claim: "stage6.ram_ra_virtual.opening.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.RamRa_1", source_stage: "stage6", source_claim: "stage6.booleanity.opening.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.ram_ra_virtual.RamRa_1", source_stage: "stage6", source_claim: "stage6.ram_ra_virtual.opening.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.RamRa_2", source_stage: "stage6", source_claim: "stage6.booleanity.opening.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.ram_ra_virtual.RamRa_2", source_stage: "stage6", source_claim: "stage6.ram_ra_virtual.opening.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.RamRa_3", source_stage: "stage6", source_claim: "stage6.booleanity.opening.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.ram_ra_virtual.RamRa_3", source_stage: "stage6", source_claim: "stage6.ram_ra_virtual.opening.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, +]; + +pub const STAGE7_FIELD_CONSTANTS: &[Stage7FieldConstantPlan] = &[ + Stage7FieldConstantPlan { symbol: "stage7.field.one", field: "bn254_fr", value: 1 }, +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_0: &[&str] = &["stage7.hamming_weight_claim_reduction.gamma"]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_1: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.0.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_0", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_2: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.0.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_0", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_3: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.1.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_4: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.1.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_1", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_5: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.1.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_1", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_6: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.2.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_7: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.2.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_2", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_8: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.2.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_2", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_9: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.3.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_10: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.3.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_3", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_11: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.3.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_3", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_12: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.4.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_13: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.4.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_4", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_14: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.4.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_4", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_15: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.5.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_16: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.5.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_5", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_17: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.5.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_5", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_18: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.6.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_19: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.6.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_6", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_20: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.6.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_6", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_21: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.7.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_22: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.7.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_7", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_23: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.7.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_7", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_24: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.8.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_25: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.8.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_8", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_26: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.8.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_8", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_27: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.9.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_28: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.9.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_9", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_29: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.9.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_9", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_30: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.10.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_31: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.10.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_10", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_32: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.10.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_10", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_33: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.11.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_34: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.11.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_11", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_35: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.11.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_11", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_36: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.12.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_37: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.12.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_12", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_38: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.12.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_12", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_39: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.13.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_40: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.13.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_13", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_41: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.13.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_13", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_42: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.14.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_43: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.14.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_14", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_44: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.14.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_14", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_45: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.15.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_46: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.15.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_15", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_47: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.15.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_15", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_48: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.16.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_49: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.16.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_16", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_50: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.16.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_16", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_51: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.17.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_52: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.17.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_17", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_53: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.17.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_17", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_54: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.18.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_55: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.18.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_18", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_56: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.18.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_18", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_57: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.19.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_58: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.19.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_19", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_59: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.19.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_19", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_60: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.20.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_61: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.20.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_20", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_62: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.20.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_20", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_63: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.21.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_64: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.21.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_21", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_65: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.21.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_21", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_66: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.22.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_67: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.22.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_22", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_68: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.22.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_22", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_69: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.23.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_70: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.23.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_23", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_71: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.23.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_23", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_72: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.24.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_73: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.24.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_24", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_74: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.24.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_24", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_75: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.25.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_76: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.25.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_25", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_77: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.25.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_25", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_78: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.26.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_79: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.26.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_26", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_80: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.26.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_26", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_81: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.27.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_82: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.27.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_27", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_83: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.27.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_27", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_84: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.28.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_85: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.28.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_28", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_86: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.28.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_28", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_87: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.29.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_88: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.29.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_29", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_89: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.29.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_29", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_90: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.30.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_91: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.30.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_30", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_92: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.30.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_30", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_93: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.31.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_94: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.31.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.InstructionRa_31", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_95: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.31.virtualization.gamma_pow", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_31", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_96: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.32.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_97: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.32.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.BytecodeRa_0", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_98: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.32.virtualization.gamma_pow", + "stage7.input.stage6.bytecode_read_raf.BytecodeRa_0", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_99: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.33.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_100: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.33.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.BytecodeRa_1", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_101: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.33.virtualization.gamma_pow", + "stage7.input.stage6.bytecode_read_raf.BytecodeRa_1", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_102: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.34.hw.gamma_pow", + "stage7.field.one", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_103: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.34.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.BytecodeRa_2", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_104: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.34.virtualization.gamma_pow", + "stage7.input.stage6.bytecode_read_raf.BytecodeRa_2", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_105: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.35.hw.gamma_pow", + "stage7.input.stage6.hamming_booleanity.HammingWeight", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_106: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.35.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.RamRa_0", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_107: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.35.virtualization.gamma_pow", + "stage7.input.stage6.ram_ra_virtual.RamRa_0", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_108: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.36.hw.gamma_pow", + "stage7.input.stage6.hamming_booleanity.HammingWeight", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_109: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.36.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.RamRa_1", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_110: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.36.virtualization.gamma_pow", + "stage7.input.stage6.ram_ra_virtual.RamRa_1", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_111: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.37.hw.gamma_pow", + "stage7.input.stage6.hamming_booleanity.HammingWeight", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_112: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.37.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.RamRa_2", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_113: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.37.virtualization.gamma_pow", + "stage7.input.stage6.ram_ra_virtual.RamRa_2", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_114: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.38.hw.gamma_pow", + "stage7.input.stage6.hamming_booleanity.HammingWeight", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_115: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.38.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.RamRa_3", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_116: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.38.virtualization.gamma_pow", + "stage7.input.stage6.ram_ra_virtual.RamRa_3", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_117: &[&str] = &[ + "stage7.field.one", + "stage7.hamming_weight_claim_reduction.claim.0.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_118: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial0", + "stage7.hamming_weight_claim_reduction.claim.0.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_119: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial1", + "stage7.hamming_weight_claim_reduction.claim.1.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_120: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial2", + "stage7.hamming_weight_claim_reduction.claim.1.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_121: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial3", + "stage7.hamming_weight_claim_reduction.claim.1.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_122: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial4", + "stage7.hamming_weight_claim_reduction.claim.2.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_123: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial5", + "stage7.hamming_weight_claim_reduction.claim.2.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_124: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial6", + "stage7.hamming_weight_claim_reduction.claim.2.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_125: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial7", + "stage7.hamming_weight_claim_reduction.claim.3.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_126: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial8", + "stage7.hamming_weight_claim_reduction.claim.3.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_127: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial9", + "stage7.hamming_weight_claim_reduction.claim.3.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_128: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial10", + "stage7.hamming_weight_claim_reduction.claim.4.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_129: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial11", + "stage7.hamming_weight_claim_reduction.claim.4.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_130: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial12", + "stage7.hamming_weight_claim_reduction.claim.4.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_131: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial13", + "stage7.hamming_weight_claim_reduction.claim.5.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_132: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial14", + "stage7.hamming_weight_claim_reduction.claim.5.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_133: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial15", + "stage7.hamming_weight_claim_reduction.claim.5.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_134: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial16", + "stage7.hamming_weight_claim_reduction.claim.6.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_135: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial17", + "stage7.hamming_weight_claim_reduction.claim.6.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_136: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial18", + "stage7.hamming_weight_claim_reduction.claim.6.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_137: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial19", + "stage7.hamming_weight_claim_reduction.claim.7.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_138: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial20", + "stage7.hamming_weight_claim_reduction.claim.7.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_139: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial21", + "stage7.hamming_weight_claim_reduction.claim.7.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_140: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial22", + "stage7.hamming_weight_claim_reduction.claim.8.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_141: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial23", + "stage7.hamming_weight_claim_reduction.claim.8.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_142: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial24", + "stage7.hamming_weight_claim_reduction.claim.8.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_143: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial25", + "stage7.hamming_weight_claim_reduction.claim.9.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_144: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial26", + "stage7.hamming_weight_claim_reduction.claim.9.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_145: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial27", + "stage7.hamming_weight_claim_reduction.claim.9.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_146: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial28", + "stage7.hamming_weight_claim_reduction.claim.10.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_147: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial29", + "stage7.hamming_weight_claim_reduction.claim.10.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_148: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial30", + "stage7.hamming_weight_claim_reduction.claim.10.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_149: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial31", + "stage7.hamming_weight_claim_reduction.claim.11.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_150: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial32", + "stage7.hamming_weight_claim_reduction.claim.11.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_151: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial33", + "stage7.hamming_weight_claim_reduction.claim.11.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_152: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial34", + "stage7.hamming_weight_claim_reduction.claim.12.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_153: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial35", + "stage7.hamming_weight_claim_reduction.claim.12.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_154: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial36", + "stage7.hamming_weight_claim_reduction.claim.12.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_155: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial37", + "stage7.hamming_weight_claim_reduction.claim.13.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_156: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial38", + "stage7.hamming_weight_claim_reduction.claim.13.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_157: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial39", + "stage7.hamming_weight_claim_reduction.claim.13.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_158: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial40", + "stage7.hamming_weight_claim_reduction.claim.14.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_159: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial41", + "stage7.hamming_weight_claim_reduction.claim.14.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_160: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial42", + "stage7.hamming_weight_claim_reduction.claim.14.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_161: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial43", + "stage7.hamming_weight_claim_reduction.claim.15.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_162: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial44", + "stage7.hamming_weight_claim_reduction.claim.15.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_163: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial45", + "stage7.hamming_weight_claim_reduction.claim.15.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_164: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial46", + "stage7.hamming_weight_claim_reduction.claim.16.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_165: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial47", + "stage7.hamming_weight_claim_reduction.claim.16.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_166: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial48", + "stage7.hamming_weight_claim_reduction.claim.16.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_167: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial49", + "stage7.hamming_weight_claim_reduction.claim.17.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_168: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial50", + "stage7.hamming_weight_claim_reduction.claim.17.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_169: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial51", + "stage7.hamming_weight_claim_reduction.claim.17.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_170: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial52", + "stage7.hamming_weight_claim_reduction.claim.18.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_171: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial53", + "stage7.hamming_weight_claim_reduction.claim.18.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_172: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial54", + "stage7.hamming_weight_claim_reduction.claim.18.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_173: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial55", + "stage7.hamming_weight_claim_reduction.claim.19.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_174: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial56", + "stage7.hamming_weight_claim_reduction.claim.19.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_175: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial57", + "stage7.hamming_weight_claim_reduction.claim.19.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_176: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial58", + "stage7.hamming_weight_claim_reduction.claim.20.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_177: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial59", + "stage7.hamming_weight_claim_reduction.claim.20.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_178: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial60", + "stage7.hamming_weight_claim_reduction.claim.20.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_179: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial61", + "stage7.hamming_weight_claim_reduction.claim.21.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_180: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial62", + "stage7.hamming_weight_claim_reduction.claim.21.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_181: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial63", + "stage7.hamming_weight_claim_reduction.claim.21.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_182: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial64", + "stage7.hamming_weight_claim_reduction.claim.22.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_183: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial65", + "stage7.hamming_weight_claim_reduction.claim.22.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_184: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial66", + "stage7.hamming_weight_claim_reduction.claim.22.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_185: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial67", + "stage7.hamming_weight_claim_reduction.claim.23.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_186: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial68", + "stage7.hamming_weight_claim_reduction.claim.23.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_187: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial69", + "stage7.hamming_weight_claim_reduction.claim.23.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_188: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial70", + "stage7.hamming_weight_claim_reduction.claim.24.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_189: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial71", + "stage7.hamming_weight_claim_reduction.claim.24.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_190: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial72", + "stage7.hamming_weight_claim_reduction.claim.24.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_191: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial73", + "stage7.hamming_weight_claim_reduction.claim.25.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_192: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial74", + "stage7.hamming_weight_claim_reduction.claim.25.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_193: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial75", + "stage7.hamming_weight_claim_reduction.claim.25.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_194: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial76", + "stage7.hamming_weight_claim_reduction.claim.26.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_195: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial77", + "stage7.hamming_weight_claim_reduction.claim.26.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_196: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial78", + "stage7.hamming_weight_claim_reduction.claim.26.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_197: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial79", + "stage7.hamming_weight_claim_reduction.claim.27.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_198: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial80", + "stage7.hamming_weight_claim_reduction.claim.27.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_199: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial81", + "stage7.hamming_weight_claim_reduction.claim.27.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_200: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial82", + "stage7.hamming_weight_claim_reduction.claim.28.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_201: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial83", + "stage7.hamming_weight_claim_reduction.claim.28.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_202: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial84", + "stage7.hamming_weight_claim_reduction.claim.28.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_203: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial85", + "stage7.hamming_weight_claim_reduction.claim.29.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_204: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial86", + "stage7.hamming_weight_claim_reduction.claim.29.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_205: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial87", + "stage7.hamming_weight_claim_reduction.claim.29.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_206: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial88", + "stage7.hamming_weight_claim_reduction.claim.30.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_207: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial89", + "stage7.hamming_weight_claim_reduction.claim.30.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_208: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial90", + "stage7.hamming_weight_claim_reduction.claim.30.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_209: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial91", + "stage7.hamming_weight_claim_reduction.claim.31.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_210: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial92", + "stage7.hamming_weight_claim_reduction.claim.31.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_211: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial93", + "stage7.hamming_weight_claim_reduction.claim.31.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_212: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial94", + "stage7.hamming_weight_claim_reduction.claim.32.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_213: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial95", + "stage7.hamming_weight_claim_reduction.claim.32.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_214: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial96", + "stage7.hamming_weight_claim_reduction.claim.32.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_215: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial97", + "stage7.hamming_weight_claim_reduction.claim.33.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_216: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial98", + "stage7.hamming_weight_claim_reduction.claim.33.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_217: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial99", + "stage7.hamming_weight_claim_reduction.claim.33.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_218: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial100", + "stage7.hamming_weight_claim_reduction.claim.34.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_219: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial101", + "stage7.hamming_weight_claim_reduction.claim.34.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_220: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial102", + "stage7.hamming_weight_claim_reduction.claim.34.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_221: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial103", + "stage7.hamming_weight_claim_reduction.claim.35.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_222: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial104", + "stage7.hamming_weight_claim_reduction.claim.35.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_223: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial105", + "stage7.hamming_weight_claim_reduction.claim.35.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_224: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial106", + "stage7.hamming_weight_claim_reduction.claim.36.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_225: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial107", + "stage7.hamming_weight_claim_reduction.claim.36.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_226: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial108", + "stage7.hamming_weight_claim_reduction.claim.36.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_227: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial109", + "stage7.hamming_weight_claim_reduction.claim.37.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_228: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial110", + "stage7.hamming_weight_claim_reduction.claim.37.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_229: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial111", + "stage7.hamming_weight_claim_reduction.claim.37.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_230: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial112", + "stage7.hamming_weight_claim_reduction.claim.38.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_231: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial113", + "stage7.hamming_weight_claim_reduction.claim.38.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_232: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial114", + "stage7.hamming_weight_claim_reduction.claim.38.virtualization.gamma_term", +]; + +pub const STAGE7_FIELD_EXPRS: &[Stage7FieldExprPlan] = &[ + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.0.booleanity.gamma_pow", kind: "op", formula: "field.pow:1", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.0.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_1, operands: STAGE7_FIELD_EXPR_OPERANDS_1 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.0.virtualization.gamma_pow", kind: "op", formula: "field.pow:2", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.0.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_2, operands: STAGE7_FIELD_EXPR_OPERANDS_2 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.1.hw.gamma_pow", kind: "op", formula: "field.pow:3", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.1.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_3, operands: STAGE7_FIELD_EXPR_OPERANDS_3 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.1.booleanity.gamma_pow", kind: "op", formula: "field.pow:4", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.1.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_4, operands: STAGE7_FIELD_EXPR_OPERANDS_4 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.1.virtualization.gamma_pow", kind: "op", formula: "field.pow:5", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.1.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_5, operands: STAGE7_FIELD_EXPR_OPERANDS_5 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.2.hw.gamma_pow", kind: "op", formula: "field.pow:6", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.2.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_6, operands: STAGE7_FIELD_EXPR_OPERANDS_6 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.2.booleanity.gamma_pow", kind: "op", formula: "field.pow:7", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.2.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_7, operands: STAGE7_FIELD_EXPR_OPERANDS_7 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.2.virtualization.gamma_pow", kind: "op", formula: "field.pow:8", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.2.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_8, operands: STAGE7_FIELD_EXPR_OPERANDS_8 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.3.hw.gamma_pow", kind: "op", formula: "field.pow:9", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.3.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_9, operands: STAGE7_FIELD_EXPR_OPERANDS_9 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.3.booleanity.gamma_pow", kind: "op", formula: "field.pow:10", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.3.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_10, operands: STAGE7_FIELD_EXPR_OPERANDS_10 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.3.virtualization.gamma_pow", kind: "op", formula: "field.pow:11", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.3.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_11, operands: STAGE7_FIELD_EXPR_OPERANDS_11 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.4.hw.gamma_pow", kind: "op", formula: "field.pow:12", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.4.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_12, operands: STAGE7_FIELD_EXPR_OPERANDS_12 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.4.booleanity.gamma_pow", kind: "op", formula: "field.pow:13", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.4.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_13, operands: STAGE7_FIELD_EXPR_OPERANDS_13 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.4.virtualization.gamma_pow", kind: "op", formula: "field.pow:14", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.4.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_14, operands: STAGE7_FIELD_EXPR_OPERANDS_14 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.5.hw.gamma_pow", kind: "op", formula: "field.pow:15", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.5.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_15, operands: STAGE7_FIELD_EXPR_OPERANDS_15 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.5.booleanity.gamma_pow", kind: "op", formula: "field.pow:16", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.5.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_16, operands: STAGE7_FIELD_EXPR_OPERANDS_16 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.5.virtualization.gamma_pow", kind: "op", formula: "field.pow:17", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.5.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_17, operands: STAGE7_FIELD_EXPR_OPERANDS_17 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.6.hw.gamma_pow", kind: "op", formula: "field.pow:18", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.6.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_18, operands: STAGE7_FIELD_EXPR_OPERANDS_18 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.6.booleanity.gamma_pow", kind: "op", formula: "field.pow:19", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.6.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_19, operands: STAGE7_FIELD_EXPR_OPERANDS_19 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.6.virtualization.gamma_pow", kind: "op", formula: "field.pow:20", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.6.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_20, operands: STAGE7_FIELD_EXPR_OPERANDS_20 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.7.hw.gamma_pow", kind: "op", formula: "field.pow:21", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.7.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_21, operands: STAGE7_FIELD_EXPR_OPERANDS_21 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.7.booleanity.gamma_pow", kind: "op", formula: "field.pow:22", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.7.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_22, operands: STAGE7_FIELD_EXPR_OPERANDS_22 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.7.virtualization.gamma_pow", kind: "op", formula: "field.pow:23", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.7.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_23, operands: STAGE7_FIELD_EXPR_OPERANDS_23 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.8.hw.gamma_pow", kind: "op", formula: "field.pow:24", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.8.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_24, operands: STAGE7_FIELD_EXPR_OPERANDS_24 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.8.booleanity.gamma_pow", kind: "op", formula: "field.pow:25", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.8.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_25, operands: STAGE7_FIELD_EXPR_OPERANDS_25 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.8.virtualization.gamma_pow", kind: "op", formula: "field.pow:26", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.8.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_26, operands: STAGE7_FIELD_EXPR_OPERANDS_26 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.9.hw.gamma_pow", kind: "op", formula: "field.pow:27", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.9.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_27, operands: STAGE7_FIELD_EXPR_OPERANDS_27 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.9.booleanity.gamma_pow", kind: "op", formula: "field.pow:28", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.9.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_28, operands: STAGE7_FIELD_EXPR_OPERANDS_28 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.9.virtualization.gamma_pow", kind: "op", formula: "field.pow:29", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.9.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_29, operands: STAGE7_FIELD_EXPR_OPERANDS_29 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.10.hw.gamma_pow", kind: "op", formula: "field.pow:30", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.10.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_30, operands: STAGE7_FIELD_EXPR_OPERANDS_30 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.10.booleanity.gamma_pow", kind: "op", formula: "field.pow:31", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.10.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_31, operands: STAGE7_FIELD_EXPR_OPERANDS_31 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.10.virtualization.gamma_pow", kind: "op", formula: "field.pow:32", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.10.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_32, operands: STAGE7_FIELD_EXPR_OPERANDS_32 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.11.hw.gamma_pow", kind: "op", formula: "field.pow:33", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.11.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_33, operands: STAGE7_FIELD_EXPR_OPERANDS_33 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.11.booleanity.gamma_pow", kind: "op", formula: "field.pow:34", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.11.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_34, operands: STAGE7_FIELD_EXPR_OPERANDS_34 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.11.virtualization.gamma_pow", kind: "op", formula: "field.pow:35", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.11.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_35, operands: STAGE7_FIELD_EXPR_OPERANDS_35 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.12.hw.gamma_pow", kind: "op", formula: "field.pow:36", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.12.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_36, operands: STAGE7_FIELD_EXPR_OPERANDS_36 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.12.booleanity.gamma_pow", kind: "op", formula: "field.pow:37", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.12.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_37, operands: STAGE7_FIELD_EXPR_OPERANDS_37 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.12.virtualization.gamma_pow", kind: "op", formula: "field.pow:38", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.12.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_38, operands: STAGE7_FIELD_EXPR_OPERANDS_38 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.13.hw.gamma_pow", kind: "op", formula: "field.pow:39", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.13.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_39, operands: STAGE7_FIELD_EXPR_OPERANDS_39 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.13.booleanity.gamma_pow", kind: "op", formula: "field.pow:40", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.13.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_40, operands: STAGE7_FIELD_EXPR_OPERANDS_40 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.13.virtualization.gamma_pow", kind: "op", formula: "field.pow:41", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.13.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_41, operands: STAGE7_FIELD_EXPR_OPERANDS_41 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.14.hw.gamma_pow", kind: "op", formula: "field.pow:42", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.14.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_42, operands: STAGE7_FIELD_EXPR_OPERANDS_42 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.14.booleanity.gamma_pow", kind: "op", formula: "field.pow:43", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.14.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_43, operands: STAGE7_FIELD_EXPR_OPERANDS_43 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.14.virtualization.gamma_pow", kind: "op", formula: "field.pow:44", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.14.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_44, operands: STAGE7_FIELD_EXPR_OPERANDS_44 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.15.hw.gamma_pow", kind: "op", formula: "field.pow:45", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.15.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_45, operands: STAGE7_FIELD_EXPR_OPERANDS_45 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.15.booleanity.gamma_pow", kind: "op", formula: "field.pow:46", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.15.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_46, operands: STAGE7_FIELD_EXPR_OPERANDS_46 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.15.virtualization.gamma_pow", kind: "op", formula: "field.pow:47", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.15.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_47, operands: STAGE7_FIELD_EXPR_OPERANDS_47 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.16.hw.gamma_pow", kind: "op", formula: "field.pow:48", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.16.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_48, operands: STAGE7_FIELD_EXPR_OPERANDS_48 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.16.booleanity.gamma_pow", kind: "op", formula: "field.pow:49", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.16.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_49, operands: STAGE7_FIELD_EXPR_OPERANDS_49 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.16.virtualization.gamma_pow", kind: "op", formula: "field.pow:50", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.16.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_50, operands: STAGE7_FIELD_EXPR_OPERANDS_50 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.17.hw.gamma_pow", kind: "op", formula: "field.pow:51", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.17.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_51, operands: STAGE7_FIELD_EXPR_OPERANDS_51 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.17.booleanity.gamma_pow", kind: "op", formula: "field.pow:52", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.17.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_52, operands: STAGE7_FIELD_EXPR_OPERANDS_52 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.17.virtualization.gamma_pow", kind: "op", formula: "field.pow:53", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.17.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_53, operands: STAGE7_FIELD_EXPR_OPERANDS_53 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.18.hw.gamma_pow", kind: "op", formula: "field.pow:54", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.18.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_54, operands: STAGE7_FIELD_EXPR_OPERANDS_54 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.18.booleanity.gamma_pow", kind: "op", formula: "field.pow:55", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.18.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_55, operands: STAGE7_FIELD_EXPR_OPERANDS_55 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.18.virtualization.gamma_pow", kind: "op", formula: "field.pow:56", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.18.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_56, operands: STAGE7_FIELD_EXPR_OPERANDS_56 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.19.hw.gamma_pow", kind: "op", formula: "field.pow:57", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.19.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_57, operands: STAGE7_FIELD_EXPR_OPERANDS_57 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.19.booleanity.gamma_pow", kind: "op", formula: "field.pow:58", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.19.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_58, operands: STAGE7_FIELD_EXPR_OPERANDS_58 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.19.virtualization.gamma_pow", kind: "op", formula: "field.pow:59", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.19.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_59, operands: STAGE7_FIELD_EXPR_OPERANDS_59 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.20.hw.gamma_pow", kind: "op", formula: "field.pow:60", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.20.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_60, operands: STAGE7_FIELD_EXPR_OPERANDS_60 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.20.booleanity.gamma_pow", kind: "op", formula: "field.pow:61", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.20.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_61, operands: STAGE7_FIELD_EXPR_OPERANDS_61 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.20.virtualization.gamma_pow", kind: "op", formula: "field.pow:62", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.20.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_62, operands: STAGE7_FIELD_EXPR_OPERANDS_62 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.21.hw.gamma_pow", kind: "op", formula: "field.pow:63", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.21.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_63, operands: STAGE7_FIELD_EXPR_OPERANDS_63 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.21.booleanity.gamma_pow", kind: "op", formula: "field.pow:64", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.21.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_64, operands: STAGE7_FIELD_EXPR_OPERANDS_64 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.21.virtualization.gamma_pow", kind: "op", formula: "field.pow:65", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.21.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_65, operands: STAGE7_FIELD_EXPR_OPERANDS_65 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.22.hw.gamma_pow", kind: "op", formula: "field.pow:66", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.22.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_66, operands: STAGE7_FIELD_EXPR_OPERANDS_66 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.22.booleanity.gamma_pow", kind: "op", formula: "field.pow:67", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.22.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_67, operands: STAGE7_FIELD_EXPR_OPERANDS_67 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.22.virtualization.gamma_pow", kind: "op", formula: "field.pow:68", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.22.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_68, operands: STAGE7_FIELD_EXPR_OPERANDS_68 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.23.hw.gamma_pow", kind: "op", formula: "field.pow:69", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.23.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_69, operands: STAGE7_FIELD_EXPR_OPERANDS_69 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.23.booleanity.gamma_pow", kind: "op", formula: "field.pow:70", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.23.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_70, operands: STAGE7_FIELD_EXPR_OPERANDS_70 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.23.virtualization.gamma_pow", kind: "op", formula: "field.pow:71", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.23.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_71, operands: STAGE7_FIELD_EXPR_OPERANDS_71 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.24.hw.gamma_pow", kind: "op", formula: "field.pow:72", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.24.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_72, operands: STAGE7_FIELD_EXPR_OPERANDS_72 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.24.booleanity.gamma_pow", kind: "op", formula: "field.pow:73", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.24.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_73, operands: STAGE7_FIELD_EXPR_OPERANDS_73 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.24.virtualization.gamma_pow", kind: "op", formula: "field.pow:74", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.24.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_74, operands: STAGE7_FIELD_EXPR_OPERANDS_74 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.25.hw.gamma_pow", kind: "op", formula: "field.pow:75", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.25.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_75, operands: STAGE7_FIELD_EXPR_OPERANDS_75 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.25.booleanity.gamma_pow", kind: "op", formula: "field.pow:76", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.25.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_76, operands: STAGE7_FIELD_EXPR_OPERANDS_76 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.25.virtualization.gamma_pow", kind: "op", formula: "field.pow:77", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.25.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_77, operands: STAGE7_FIELD_EXPR_OPERANDS_77 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.26.hw.gamma_pow", kind: "op", formula: "field.pow:78", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.26.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_78, operands: STAGE7_FIELD_EXPR_OPERANDS_78 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.26.booleanity.gamma_pow", kind: "op", formula: "field.pow:79", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.26.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_79, operands: STAGE7_FIELD_EXPR_OPERANDS_79 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.26.virtualization.gamma_pow", kind: "op", formula: "field.pow:80", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.26.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_80, operands: STAGE7_FIELD_EXPR_OPERANDS_80 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.27.hw.gamma_pow", kind: "op", formula: "field.pow:81", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.27.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_81, operands: STAGE7_FIELD_EXPR_OPERANDS_81 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.27.booleanity.gamma_pow", kind: "op", formula: "field.pow:82", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.27.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_82, operands: STAGE7_FIELD_EXPR_OPERANDS_82 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.27.virtualization.gamma_pow", kind: "op", formula: "field.pow:83", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.27.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_83, operands: STAGE7_FIELD_EXPR_OPERANDS_83 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.28.hw.gamma_pow", kind: "op", formula: "field.pow:84", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.28.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_84, operands: STAGE7_FIELD_EXPR_OPERANDS_84 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.28.booleanity.gamma_pow", kind: "op", formula: "field.pow:85", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.28.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_85, operands: STAGE7_FIELD_EXPR_OPERANDS_85 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.28.virtualization.gamma_pow", kind: "op", formula: "field.pow:86", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.28.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_86, operands: STAGE7_FIELD_EXPR_OPERANDS_86 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.29.hw.gamma_pow", kind: "op", formula: "field.pow:87", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.29.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_87, operands: STAGE7_FIELD_EXPR_OPERANDS_87 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.29.booleanity.gamma_pow", kind: "op", formula: "field.pow:88", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.29.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_88, operands: STAGE7_FIELD_EXPR_OPERANDS_88 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.29.virtualization.gamma_pow", kind: "op", formula: "field.pow:89", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.29.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_89, operands: STAGE7_FIELD_EXPR_OPERANDS_89 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.30.hw.gamma_pow", kind: "op", formula: "field.pow:90", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.30.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_90, operands: STAGE7_FIELD_EXPR_OPERANDS_90 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.30.booleanity.gamma_pow", kind: "op", formula: "field.pow:91", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.30.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_91, operands: STAGE7_FIELD_EXPR_OPERANDS_91 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.30.virtualization.gamma_pow", kind: "op", formula: "field.pow:92", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.30.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_92, operands: STAGE7_FIELD_EXPR_OPERANDS_92 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.31.hw.gamma_pow", kind: "op", formula: "field.pow:93", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.31.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_93, operands: STAGE7_FIELD_EXPR_OPERANDS_93 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.31.booleanity.gamma_pow", kind: "op", formula: "field.pow:94", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.31.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_94, operands: STAGE7_FIELD_EXPR_OPERANDS_94 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.31.virtualization.gamma_pow", kind: "op", formula: "field.pow:95", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.31.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_95, operands: STAGE7_FIELD_EXPR_OPERANDS_95 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.32.hw.gamma_pow", kind: "op", formula: "field.pow:96", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.32.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_96, operands: STAGE7_FIELD_EXPR_OPERANDS_96 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.32.booleanity.gamma_pow", kind: "op", formula: "field.pow:97", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.32.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_97, operands: STAGE7_FIELD_EXPR_OPERANDS_97 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.32.virtualization.gamma_pow", kind: "op", formula: "field.pow:98", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.32.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_98, operands: STAGE7_FIELD_EXPR_OPERANDS_98 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.33.hw.gamma_pow", kind: "op", formula: "field.pow:99", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.33.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_99, operands: STAGE7_FIELD_EXPR_OPERANDS_99 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.33.booleanity.gamma_pow", kind: "op", formula: "field.pow:100", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.33.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_100, operands: STAGE7_FIELD_EXPR_OPERANDS_100 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.33.virtualization.gamma_pow", kind: "op", formula: "field.pow:101", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.33.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_101, operands: STAGE7_FIELD_EXPR_OPERANDS_101 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.34.hw.gamma_pow", kind: "op", formula: "field.pow:102", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.34.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_102, operands: STAGE7_FIELD_EXPR_OPERANDS_102 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.34.booleanity.gamma_pow", kind: "op", formula: "field.pow:103", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.34.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_103, operands: STAGE7_FIELD_EXPR_OPERANDS_103 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.34.virtualization.gamma_pow", kind: "op", formula: "field.pow:104", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.34.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_104, operands: STAGE7_FIELD_EXPR_OPERANDS_104 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.35.hw.gamma_pow", kind: "op", formula: "field.pow:105", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.35.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_105, operands: STAGE7_FIELD_EXPR_OPERANDS_105 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.35.booleanity.gamma_pow", kind: "op", formula: "field.pow:106", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.35.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_106, operands: STAGE7_FIELD_EXPR_OPERANDS_106 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.35.virtualization.gamma_pow", kind: "op", formula: "field.pow:107", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.35.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_107, operands: STAGE7_FIELD_EXPR_OPERANDS_107 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.36.hw.gamma_pow", kind: "op", formula: "field.pow:108", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.36.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_108, operands: STAGE7_FIELD_EXPR_OPERANDS_108 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.36.booleanity.gamma_pow", kind: "op", formula: "field.pow:109", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.36.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_109, operands: STAGE7_FIELD_EXPR_OPERANDS_109 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.36.virtualization.gamma_pow", kind: "op", formula: "field.pow:110", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.36.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_110, operands: STAGE7_FIELD_EXPR_OPERANDS_110 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.37.hw.gamma_pow", kind: "op", formula: "field.pow:111", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.37.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_111, operands: STAGE7_FIELD_EXPR_OPERANDS_111 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.37.booleanity.gamma_pow", kind: "op", formula: "field.pow:112", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.37.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_112, operands: STAGE7_FIELD_EXPR_OPERANDS_112 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.37.virtualization.gamma_pow", kind: "op", formula: "field.pow:113", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.37.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_113, operands: STAGE7_FIELD_EXPR_OPERANDS_113 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.38.hw.gamma_pow", kind: "op", formula: "field.pow:114", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.38.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_114, operands: STAGE7_FIELD_EXPR_OPERANDS_114 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.38.booleanity.gamma_pow", kind: "op", formula: "field.pow:115", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.38.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_115, operands: STAGE7_FIELD_EXPR_OPERANDS_115 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.38.virtualization.gamma_pow", kind: "op", formula: "field.pow:116", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.38.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_116, operands: STAGE7_FIELD_EXPR_OPERANDS_116 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial0", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_117, operands: STAGE7_FIELD_EXPR_OPERANDS_117 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial1", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_118, operands: STAGE7_FIELD_EXPR_OPERANDS_118 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial2", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_119, operands: STAGE7_FIELD_EXPR_OPERANDS_119 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial3", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_120, operands: STAGE7_FIELD_EXPR_OPERANDS_120 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial4", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_121, operands: STAGE7_FIELD_EXPR_OPERANDS_121 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial5", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_122, operands: STAGE7_FIELD_EXPR_OPERANDS_122 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial6", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_123, operands: STAGE7_FIELD_EXPR_OPERANDS_123 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial7", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_124, operands: STAGE7_FIELD_EXPR_OPERANDS_124 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial8", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_125, operands: STAGE7_FIELD_EXPR_OPERANDS_125 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial9", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_126, operands: STAGE7_FIELD_EXPR_OPERANDS_126 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial10", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_127, operands: STAGE7_FIELD_EXPR_OPERANDS_127 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial11", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_128, operands: STAGE7_FIELD_EXPR_OPERANDS_128 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial12", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_129, operands: STAGE7_FIELD_EXPR_OPERANDS_129 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial13", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_130, operands: STAGE7_FIELD_EXPR_OPERANDS_130 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial14", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_131, operands: STAGE7_FIELD_EXPR_OPERANDS_131 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial15", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_132, operands: STAGE7_FIELD_EXPR_OPERANDS_132 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial16", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_133, operands: STAGE7_FIELD_EXPR_OPERANDS_133 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial17", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_134, operands: STAGE7_FIELD_EXPR_OPERANDS_134 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial18", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_135, operands: STAGE7_FIELD_EXPR_OPERANDS_135 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial19", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_136, operands: STAGE7_FIELD_EXPR_OPERANDS_136 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial20", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_137, operands: STAGE7_FIELD_EXPR_OPERANDS_137 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial21", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_138, operands: STAGE7_FIELD_EXPR_OPERANDS_138 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial22", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_139, operands: STAGE7_FIELD_EXPR_OPERANDS_139 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial23", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_140, operands: STAGE7_FIELD_EXPR_OPERANDS_140 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial24", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_141, operands: STAGE7_FIELD_EXPR_OPERANDS_141 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial25", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_142, operands: STAGE7_FIELD_EXPR_OPERANDS_142 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial26", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_143, operands: STAGE7_FIELD_EXPR_OPERANDS_143 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial27", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_144, operands: STAGE7_FIELD_EXPR_OPERANDS_144 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial28", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_145, operands: STAGE7_FIELD_EXPR_OPERANDS_145 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial29", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_146, operands: STAGE7_FIELD_EXPR_OPERANDS_146 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial30", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_147, operands: STAGE7_FIELD_EXPR_OPERANDS_147 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial31", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_148, operands: STAGE7_FIELD_EXPR_OPERANDS_148 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial32", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_149, operands: STAGE7_FIELD_EXPR_OPERANDS_149 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial33", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_150, operands: STAGE7_FIELD_EXPR_OPERANDS_150 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial34", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_151, operands: STAGE7_FIELD_EXPR_OPERANDS_151 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial35", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_152, operands: STAGE7_FIELD_EXPR_OPERANDS_152 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial36", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_153, operands: STAGE7_FIELD_EXPR_OPERANDS_153 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial37", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_154, operands: STAGE7_FIELD_EXPR_OPERANDS_154 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial38", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_155, operands: STAGE7_FIELD_EXPR_OPERANDS_155 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial39", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_156, operands: STAGE7_FIELD_EXPR_OPERANDS_156 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial40", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_157, operands: STAGE7_FIELD_EXPR_OPERANDS_157 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial41", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_158, operands: STAGE7_FIELD_EXPR_OPERANDS_158 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial42", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_159, operands: STAGE7_FIELD_EXPR_OPERANDS_159 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial43", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_160, operands: STAGE7_FIELD_EXPR_OPERANDS_160 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial44", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_161, operands: STAGE7_FIELD_EXPR_OPERANDS_161 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial45", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_162, operands: STAGE7_FIELD_EXPR_OPERANDS_162 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial46", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_163, operands: STAGE7_FIELD_EXPR_OPERANDS_163 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial47", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_164, operands: STAGE7_FIELD_EXPR_OPERANDS_164 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial48", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_165, operands: STAGE7_FIELD_EXPR_OPERANDS_165 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial49", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_166, operands: STAGE7_FIELD_EXPR_OPERANDS_166 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial50", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_167, operands: STAGE7_FIELD_EXPR_OPERANDS_167 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial51", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_168, operands: STAGE7_FIELD_EXPR_OPERANDS_168 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial52", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_169, operands: STAGE7_FIELD_EXPR_OPERANDS_169 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial53", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_170, operands: STAGE7_FIELD_EXPR_OPERANDS_170 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial54", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_171, operands: STAGE7_FIELD_EXPR_OPERANDS_171 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial55", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_172, operands: STAGE7_FIELD_EXPR_OPERANDS_172 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial56", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_173, operands: STAGE7_FIELD_EXPR_OPERANDS_173 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial57", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_174, operands: STAGE7_FIELD_EXPR_OPERANDS_174 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial58", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_175, operands: STAGE7_FIELD_EXPR_OPERANDS_175 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial59", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_176, operands: STAGE7_FIELD_EXPR_OPERANDS_176 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial60", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_177, operands: STAGE7_FIELD_EXPR_OPERANDS_177 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial61", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_178, operands: STAGE7_FIELD_EXPR_OPERANDS_178 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial62", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_179, operands: STAGE7_FIELD_EXPR_OPERANDS_179 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial63", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_180, operands: STAGE7_FIELD_EXPR_OPERANDS_180 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial64", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_181, operands: STAGE7_FIELD_EXPR_OPERANDS_181 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial65", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_182, operands: STAGE7_FIELD_EXPR_OPERANDS_182 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial66", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_183, operands: STAGE7_FIELD_EXPR_OPERANDS_183 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial67", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_184, operands: STAGE7_FIELD_EXPR_OPERANDS_184 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial68", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_185, operands: STAGE7_FIELD_EXPR_OPERANDS_185 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial69", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_186, operands: STAGE7_FIELD_EXPR_OPERANDS_186 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial70", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_187, operands: STAGE7_FIELD_EXPR_OPERANDS_187 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial71", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_188, operands: STAGE7_FIELD_EXPR_OPERANDS_188 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial72", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_189, operands: STAGE7_FIELD_EXPR_OPERANDS_189 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial73", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_190, operands: STAGE7_FIELD_EXPR_OPERANDS_190 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial74", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_191, operands: STAGE7_FIELD_EXPR_OPERANDS_191 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial75", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_192, operands: STAGE7_FIELD_EXPR_OPERANDS_192 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial76", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_193, operands: STAGE7_FIELD_EXPR_OPERANDS_193 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial77", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_194, operands: STAGE7_FIELD_EXPR_OPERANDS_194 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial78", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_195, operands: STAGE7_FIELD_EXPR_OPERANDS_195 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial79", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_196, operands: STAGE7_FIELD_EXPR_OPERANDS_196 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial80", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_197, operands: STAGE7_FIELD_EXPR_OPERANDS_197 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial81", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_198, operands: STAGE7_FIELD_EXPR_OPERANDS_198 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial82", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_199, operands: STAGE7_FIELD_EXPR_OPERANDS_199 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial83", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_200, operands: STAGE7_FIELD_EXPR_OPERANDS_200 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial84", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_201, operands: STAGE7_FIELD_EXPR_OPERANDS_201 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial85", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_202, operands: STAGE7_FIELD_EXPR_OPERANDS_202 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial86", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_203, operands: STAGE7_FIELD_EXPR_OPERANDS_203 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial87", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_204, operands: STAGE7_FIELD_EXPR_OPERANDS_204 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial88", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_205, operands: STAGE7_FIELD_EXPR_OPERANDS_205 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial89", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_206, operands: STAGE7_FIELD_EXPR_OPERANDS_206 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial90", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_207, operands: STAGE7_FIELD_EXPR_OPERANDS_207 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial91", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_208, operands: STAGE7_FIELD_EXPR_OPERANDS_208 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial92", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_209, operands: STAGE7_FIELD_EXPR_OPERANDS_209 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial93", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_210, operands: STAGE7_FIELD_EXPR_OPERANDS_210 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial94", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_211, operands: STAGE7_FIELD_EXPR_OPERANDS_211 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial95", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_212, operands: STAGE7_FIELD_EXPR_OPERANDS_212 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial96", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_213, operands: STAGE7_FIELD_EXPR_OPERANDS_213 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial97", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_214, operands: STAGE7_FIELD_EXPR_OPERANDS_214 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial98", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_215, operands: STAGE7_FIELD_EXPR_OPERANDS_215 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial99", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_216, operands: STAGE7_FIELD_EXPR_OPERANDS_216 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial100", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_217, operands: STAGE7_FIELD_EXPR_OPERANDS_217 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial101", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_218, operands: STAGE7_FIELD_EXPR_OPERANDS_218 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial102", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_219, operands: STAGE7_FIELD_EXPR_OPERANDS_219 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial103", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_220, operands: STAGE7_FIELD_EXPR_OPERANDS_220 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial104", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_221, operands: STAGE7_FIELD_EXPR_OPERANDS_221 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial105", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_222, operands: STAGE7_FIELD_EXPR_OPERANDS_222 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial106", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_223, operands: STAGE7_FIELD_EXPR_OPERANDS_223 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial107", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_224, operands: STAGE7_FIELD_EXPR_OPERANDS_224 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial108", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_225, operands: STAGE7_FIELD_EXPR_OPERANDS_225 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial109", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_226, operands: STAGE7_FIELD_EXPR_OPERANDS_226 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial110", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_227, operands: STAGE7_FIELD_EXPR_OPERANDS_227 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial111", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_228, operands: STAGE7_FIELD_EXPR_OPERANDS_228 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial112", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_229, operands: STAGE7_FIELD_EXPR_OPERANDS_229 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial113", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_230, operands: STAGE7_FIELD_EXPR_OPERANDS_230 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial114", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_231, operands: STAGE7_FIELD_EXPR_OPERANDS_231 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial115", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_232, operands: STAGE7_FIELD_EXPR_OPERANDS_232 }, +]; +pub const STAGE7_KERNELS: &[Stage7KernelPlan] = &[ + Stage7KernelPlan { symbol: "jolt.cpu.stage7.hamming_weight_claim_reduction", relation: "jolt.stage7.hamming_weight_claim_reduction", kind: "sumcheck", backend: "cpu", abi: "jolt_stage7_hamming_weight_claim_reduction" }, + Stage7KernelPlan { symbol: "jolt.cpu.stage7.batched", relation: "jolt.stage7.batched", kind: "sumcheck", backend: "cpu", abi: "jolt_stage7_batched" }, +]; + +pub const STAGE7_SUMCHECK_CLAIM_0_INPUT_OPENINGS: &[&str] = &[ + "stage7.input.stage6.hamming_booleanity.HammingWeight", + "stage7.input.stage6.booleanity.InstructionRa_0", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_0", + "stage7.input.stage6.booleanity.InstructionRa_1", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_1", + "stage7.input.stage6.booleanity.InstructionRa_2", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_2", + "stage7.input.stage6.booleanity.InstructionRa_3", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_3", + "stage7.input.stage6.booleanity.InstructionRa_4", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_4", + "stage7.input.stage6.booleanity.InstructionRa_5", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_5", + "stage7.input.stage6.booleanity.InstructionRa_6", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_6", + "stage7.input.stage6.booleanity.InstructionRa_7", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_7", + "stage7.input.stage6.booleanity.InstructionRa_8", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_8", + "stage7.input.stage6.booleanity.InstructionRa_9", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_9", + "stage7.input.stage6.booleanity.InstructionRa_10", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_10", + "stage7.input.stage6.booleanity.InstructionRa_11", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_11", + "stage7.input.stage6.booleanity.InstructionRa_12", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_12", + "stage7.input.stage6.booleanity.InstructionRa_13", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_13", + "stage7.input.stage6.booleanity.InstructionRa_14", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_14", + "stage7.input.stage6.booleanity.InstructionRa_15", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_15", + "stage7.input.stage6.booleanity.InstructionRa_16", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_16", + "stage7.input.stage6.booleanity.InstructionRa_17", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_17", + "stage7.input.stage6.booleanity.InstructionRa_18", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_18", + "stage7.input.stage6.booleanity.InstructionRa_19", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_19", + "stage7.input.stage6.booleanity.InstructionRa_20", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_20", + "stage7.input.stage6.booleanity.InstructionRa_21", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_21", + "stage7.input.stage6.booleanity.InstructionRa_22", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_22", + "stage7.input.stage6.booleanity.InstructionRa_23", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_23", + "stage7.input.stage6.booleanity.InstructionRa_24", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_24", + "stage7.input.stage6.booleanity.InstructionRa_25", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_25", + "stage7.input.stage6.booleanity.InstructionRa_26", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_26", + "stage7.input.stage6.booleanity.InstructionRa_27", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_27", + "stage7.input.stage6.booleanity.InstructionRa_28", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_28", + "stage7.input.stage6.booleanity.InstructionRa_29", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_29", + "stage7.input.stage6.booleanity.InstructionRa_30", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_30", + "stage7.input.stage6.booleanity.InstructionRa_31", + "stage7.input.stage6.instruction_ra_virtual.InstructionRa_31", + "stage7.input.stage6.booleanity.BytecodeRa_0", + "stage7.input.stage6.bytecode_read_raf.BytecodeRa_0", + "stage7.input.stage6.booleanity.BytecodeRa_1", + "stage7.input.stage6.bytecode_read_raf.BytecodeRa_1", + "stage7.input.stage6.booleanity.BytecodeRa_2", + "stage7.input.stage6.bytecode_read_raf.BytecodeRa_2", + "stage7.input.stage6.booleanity.RamRa_0", + "stage7.input.stage6.ram_ra_virtual.RamRa_0", + "stage7.input.stage6.booleanity.RamRa_1", + "stage7.input.stage6.ram_ra_virtual.RamRa_1", + "stage7.input.stage6.booleanity.RamRa_2", + "stage7.input.stage6.ram_ra_virtual.RamRa_2", + "stage7.input.stage6.booleanity.RamRa_3", + "stage7.input.stage6.ram_ra_virtual.RamRa_3", +]; + +pub const STAGE7_SUMCHECK_CLAIMS: &[Stage7SumcheckClaimPlan] = &[ + Stage7SumcheckClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.input", stage: "stage7", domain: "jolt.stage7_hamming_weight_claim_reduction_domain", num_rounds: 4, degree: 2, claim: "stage7.hamming_weight_claim_reduction.weighted_stage6_claims", kernel: Some("jolt.cpu.stage7.hamming_weight_claim_reduction"), relation: None, claim_value: "stage7.hamming_weight_claim_reduction.claim_expr.partial115", input_openings: STAGE7_SUMCHECK_CLAIM_0_INPUT_OPENINGS }, +]; +pub const STAGE7_SUMCHECK_BATCH_0_ORDERED_CLAIMS: &[&str] = &["stage7.hamming_weight_claim_reduction.input"]; + +pub const STAGE7_SUMCHECK_BATCH_0_CLAIM_OPERANDS: &[&str] = &["stage7.hamming_weight_claim_reduction.input"]; + +pub const STAGE7_SUMCHECK_BATCH_0_ROUND_SCHEDULE: &[usize] = &[ + 4, +]; + +pub const STAGE7_SUMCHECK_BATCHES: &[Stage7SumcheckBatchPlan] = &[ + Stage7SumcheckBatchPlan { symbol: "stage7.batch", stage: "stage7", proof_slot: "stage7.sumcheck", policy: "jolt_core_stage7_aligned", count: 1, ordered_claims: STAGE7_SUMCHECK_BATCH_0_ORDERED_CLAIMS, claim_operands: STAGE7_SUMCHECK_BATCH_0_CLAIM_OPERANDS, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", round_schedule: STAGE7_SUMCHECK_BATCH_0_ROUND_SCHEDULE }, +]; +pub const STAGE7_SUMCHECK_DRIVER_0_ROUND_SCHEDULE: &[usize] = &[ + 4, +]; + +pub const STAGE7_SUMCHECK_DRIVERS: &[Stage7SumcheckDriverPlan] = &[ + Stage7SumcheckDriverPlan { symbol: "stage7.sumcheck", stage: "stage7", proof_slot: "stage7.sumcheck", kernel: Some("jolt.cpu.stage7.batched"), relation: None, batch: "stage7.batch", policy: "jolt_core_stage7_aligned", round_schedule: STAGE7_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 4, degree: 2 }, +]; +pub const STAGE7_SUMCHECK_INSTANCE_RESULTS: &[Stage7SumcheckInstanceResultPlan] = &[ + Stage7SumcheckInstanceResultPlan { symbol: "stage7.hamming_weight_claim_reduction.instance", source: "stage7.sumcheck", claim: "stage7.hamming_weight_claim_reduction.input", relation: "jolt.stage7.hamming_weight_claim_reduction", index: 0, point_arity: 4, num_rounds: 4, round_offset: 0, point_order: "reverse", degree: 2 }, +]; + +macro_rules! stage7_sumcheck_eval { + ($symbol:literal, $source:literal, $name:literal, $index:literal, $oracle:literal) => { + Stage7SumcheckEvalPlan { symbol: $symbol, source: $source, name: $name, index: $index, oracle: $oracle } + }; +} + +#[rustfmt::skip] +pub const STAGE7_SUMCHECK_EVALS: &[Stage7SumcheckEvalPlan] = &[ + stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_0", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_0", 0, "InstructionRa_0"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_1", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_1", 1, "InstructionRa_1"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_2", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_2", 2, "InstructionRa_2"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_3", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_3", 3, "InstructionRa_3"), + stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_4", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_4", 4, "InstructionRa_4"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_5", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_5", 5, "InstructionRa_5"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_6", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_6", 6, "InstructionRa_6"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_7", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_7", 7, "InstructionRa_7"), + stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_8", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_8", 8, "InstructionRa_8"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_9", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_9", 9, "InstructionRa_9"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_10", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_10", 10, "InstructionRa_10"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_11", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_11", 11, "InstructionRa_11"), + stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_12", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_12", 12, "InstructionRa_12"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_13", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_13", 13, "InstructionRa_13"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_14", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_14", 14, "InstructionRa_14"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_15", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_15", 15, "InstructionRa_15"), + stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_16", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_16", 16, "InstructionRa_16"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_17", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_17", 17, "InstructionRa_17"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_18", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_18", 18, "InstructionRa_18"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_19", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_19", 19, "InstructionRa_19"), + stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_20", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_20", 20, "InstructionRa_20"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_21", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_21", 21, "InstructionRa_21"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_22", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_22", 22, "InstructionRa_22"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_23", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_23", 23, "InstructionRa_23"), + stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_24", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_24", 24, "InstructionRa_24"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_25", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_25", 25, "InstructionRa_25"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_26", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_26", 26, "InstructionRa_26"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_27", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_27", 27, "InstructionRa_27"), + stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_28", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_28", 28, "InstructionRa_28"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_29", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_29", 29, "InstructionRa_29"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_30", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_30", 30, "InstructionRa_30"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_31", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_31", 31, "InstructionRa_31"), + stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.BytecodeRa_0", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_0", 32, "BytecodeRa_0"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.BytecodeRa_1", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_1", 33, "BytecodeRa_1"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.BytecodeRa_2", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_2", 34, "BytecodeRa_2"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.RamRa_0", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.RamRa_0", 35, "RamRa_0"), + stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.RamRa_1", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.RamRa_1", 36, "RamRa_1"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.RamRa_2", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.RamRa_2", 37, "RamRa_2"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.RamRa_3", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.RamRa_3", 38, "RamRa_3"), +]; + +pub const STAGE7_POINT_ZEROS: &[Stage7PointZeroPlan] = &[ + +]; + +pub const STAGE7_POINT_SLICES: &[Stage7PointSlicePlan] = &[ + Stage7PointSlicePlan { symbol: "stage7.hamming_weight_claim_reduction.point.cycle", source: "stage7.input.stage6.booleanity.InstructionRa_0", offset: 4, length: 16, input: "stage7.input.stage6.booleanity.InstructionRa_0" }, +]; + +pub const STAGE7_POINT_CONCAT_0_INPUTS: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.instance", + "stage7.hamming_weight_claim_reduction.point.cycle", +]; + +pub const STAGE7_POINT_CONCATS: &[Stage7PointConcatPlan] = &[ + Stage7PointConcatPlan { symbol: "stage7.hamming_weight_claim_reduction.point", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE7_POINT_CONCAT_0_INPUTS }, +]; +pub const STAGE7_OPENING_CLAIMS: &[Stage7OpeningClaimPlan] = &[ + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_0" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_1" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_2" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_3" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_4" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_5" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_6" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_7" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_8" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_9" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_10" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_11" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_12" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_13" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_14" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_15" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_16" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_17" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_18" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_19" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_20" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_21" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_22" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_23" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_24" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_25" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_26" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_27" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_28" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_29" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_30" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_31" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_0" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_1" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_2" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.RamRa_0" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.RamRa_1" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.RamRa_2" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.RamRa_3" }, +]; + +pub const STAGE7_OPENING_EQUALITIES: &[Stage7OpeningClaimEqualityPlan] = &[ + +]; + +pub const STAGE7_OPENING_BATCH_0_ORDERED_CLAIMS: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_0", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_1", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_2", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_3", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_4", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_5", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_6", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_7", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_8", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_9", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_10", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_11", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_12", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_13", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_14", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_15", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_16", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_17", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_18", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_19", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_20", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_21", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_22", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_23", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_24", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_25", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_26", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_27", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_28", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_29", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_30", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_31", + "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_0", + "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_1", + "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_2", + "stage7.hamming_weight_claim_reduction.opening.RamRa_0", + "stage7.hamming_weight_claim_reduction.opening.RamRa_1", + "stage7.hamming_weight_claim_reduction.opening.RamRa_2", + "stage7.hamming_weight_claim_reduction.opening.RamRa_3", +]; + +pub const STAGE7_OPENING_BATCH_0_CLAIM_OPERANDS: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_0", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_1", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_2", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_3", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_4", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_5", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_6", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_7", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_8", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_9", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_10", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_11", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_12", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_13", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_14", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_15", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_16", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_17", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_18", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_19", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_20", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_21", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_22", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_23", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_24", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_25", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_26", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_27", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_28", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_29", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_30", + "stage7.hamming_weight_claim_reduction.opening.InstructionRa_31", + "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_0", + "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_1", + "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_2", + "stage7.hamming_weight_claim_reduction.opening.RamRa_0", + "stage7.hamming_weight_claim_reduction.opening.RamRa_1", + "stage7.hamming_weight_claim_reduction.opening.RamRa_2", + "stage7.hamming_weight_claim_reduction.opening.RamRa_3", +]; + +pub const STAGE7_OPENING_BATCHES: &[Stage7OpeningBatchPlan] = &[ + Stage7OpeningBatchPlan { symbol: "stage7.openings", stage: "stage7", proof_slot: "stage7.openings", policy: "jolt_stage7_output_order", count: 39, ordered_claims: STAGE7_OPENING_BATCH_0_ORDERED_CLAIMS, claim_operands: STAGE7_OPENING_BATCH_0_CLAIM_OPERANDS }, +]; +pub const STAGE7_PROGRAM: Stage7CpuProgramPlan = Stage7CpuProgramPlan { + role: "prover", + params: STAGE7_PARAMS, + steps: STAGE7_PROGRAM_STEPS, + transcript_squeezes: STAGE7_TRANSCRIPT_SQUEEZES, + transcript_absorb_bytes: STAGE7_TRANSCRIPT_ABSORB_BYTES, + opening_inputs: STAGE7_OPENING_INPUTS, + field_constants: STAGE7_FIELD_CONSTANTS, + field_exprs: STAGE7_FIELD_EXPRS, + kernels: STAGE7_KERNELS, + claims: STAGE7_SUMCHECK_CLAIMS, + batches: STAGE7_SUMCHECK_BATCHES, + drivers: STAGE7_SUMCHECK_DRIVERS, + instance_results: STAGE7_SUMCHECK_INSTANCE_RESULTS, + evals: STAGE7_SUMCHECK_EVALS, + point_zeros: STAGE7_POINT_ZEROS, + point_slices: STAGE7_POINT_SLICES, + point_concats: STAGE7_POINT_CONCATS, + opening_claims: STAGE7_OPENING_CLAIMS, + opening_equalities: STAGE7_OPENING_EQUALITIES, + opening_batches: STAGE7_OPENING_BATCHES, +}; + +pub fn execute_stage7_prover( + executor: &mut E, + transcript: &mut T, +) -> Result, Stage7KernelError> +where + E: Stage7KernelExecutor, + T: Transcript, +{ + execute_stage7_prover_with_program(&STAGE7_PROGRAM, executor, transcript) +} + +pub fn execute_stage7_prover_with_program( + program: &'static Stage7CpuProgramPlan, + executor: &mut E, + transcript: &mut T, +) -> Result, Stage7KernelError> +where + E: Stage7KernelExecutor, + T: Transcript, +{ + execute_stage7_program(program, Stage7ExecutionMode::Prover, executor, transcript) +} diff --git a/crates/jolt-prover/src/stages/stage8.rs b/crates/jolt-prover/src/stages/stage8.rs new file mode 100644 index 0000000000..632dbe3925 --- /dev/null +++ b/crates/jolt-prover/src/stages/stage8.rs @@ -0,0 +1,173 @@ +#![allow(clippy::too_many_lines)] + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage8Params { + pub field: &'static str, + pub pcs: &'static str, + pub transcript: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage8OpeningInputPlan { + pub symbol: &'static str, + pub source_stage: &'static str, + pub source_claim: &'static str, + pub oracle: &'static str, + pub domain: &'static str, + pub point_arity: usize, + pub claim_kind: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage8OpeningClaimPlan { + pub symbol: &'static str, + pub oracle: &'static str, + pub family: &'static str, + pub domain: &'static str, + pub point_arity: usize, + pub point_source: &'static str, + pub eval_source: &'static str, + pub source_stage: &'static str, + pub source_claim: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage8OpeningBatchPlan { + pub symbol: &'static str, + pub proof_slot: &'static str, + pub policy: &'static str, + pub count: usize, + pub ordered_claims: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage8PcsProofPlan { + pub symbol: &'static str, + pub mode: &'static str, + pub pcs: &'static str, + pub proof_slot: &'static str, + pub transcript_label: &'static str, + pub batch: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage8EvaluationProgramPlan { + pub role: &'static str, + pub function: &'static str, + pub params: Stage8Params, + pub evaluation_point_source: Stage8OpeningInputPlan, + pub opening_inputs: &'static [Stage8OpeningInputPlan], + pub opening_claims: &'static [Stage8OpeningClaimPlan], + pub opening_batch: Stage8OpeningBatchPlan, + pub pcs_proof: Stage8PcsProofPlan, +} + +pub const STAGE8_PARAMS: Stage8Params = Stage8Params { field: "bn254_fr", pcs: "dory", transcript: "blake2b_transcript" }; + +pub const STAGE8_EVALUATION_POINT_SOURCE: Stage8OpeningInputPlan = Stage8OpeningInputPlan { symbol: "stage8.evaluation.point_source", source_stage: "stage7", source_claim: "stage7.input.stage6.booleanity.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }; + +pub const STAGE8_OPENING_INPUTS: &[Stage8OpeningInputPlan] = &[ + Stage8OpeningInputPlan { symbol: "stage8.evaluation.point_source", source_stage: "stage7", source_claim: "stage7.input.stage6.booleanity.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage6.RamInc", source_stage: "stage6", source_claim: "stage6.inc_claim_reduction.eval.RamInc", oracle: "RamInc", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage6.RdInc", source_stage: "stage6", source_claim: "stage6.inc_claim_reduction.eval.RdInc", oracle: "RdInc", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_3", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_4", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_5", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_6", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_7", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_8", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_9", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_10", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_11", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_12", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_13", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_14", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_15", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_16", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_17", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_18", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_19", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_20", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_21", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_22", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_23", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_24", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_25", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_26", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_27", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_28", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_29", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_30", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_31", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.BytecodeRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.BytecodeRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.BytecodeRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.RamRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.RamRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.RamRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.RamRa_3", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, +]; + +pub const STAGE8_OPENING_CLAIMS: &[Stage8OpeningClaimPlan] = &[ + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RamInc", oracle: "RamInc", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage6.RamInc", eval_source: "stage8.input.stage6.RamInc", source_stage: "stage6", source_claim: "stage6.inc_claim_reduction.eval.RamInc" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RdInc", oracle: "RdInc", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage6.RdInc", eval_source: "stage8.input.stage6.RdInc", source_stage: "stage6", source_claim: "stage6.inc_claim_reduction.eval.RdInc" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_0", oracle: "InstructionRa_0", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_0", eval_source: "stage8.input.stage7.InstructionRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_0" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_1", oracle: "InstructionRa_1", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_1", eval_source: "stage8.input.stage7.InstructionRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_1" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_2", oracle: "InstructionRa_2", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_2", eval_source: "stage8.input.stage7.InstructionRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_2" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_3", oracle: "InstructionRa_3", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_3", eval_source: "stage8.input.stage7.InstructionRa_3", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_3" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_4", oracle: "InstructionRa_4", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_4", eval_source: "stage8.input.stage7.InstructionRa_4", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_4" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_5", oracle: "InstructionRa_5", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_5", eval_source: "stage8.input.stage7.InstructionRa_5", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_5" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_6", oracle: "InstructionRa_6", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_6", eval_source: "stage8.input.stage7.InstructionRa_6", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_6" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_7", oracle: "InstructionRa_7", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_7", eval_source: "stage8.input.stage7.InstructionRa_7", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_7" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_8", oracle: "InstructionRa_8", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_8", eval_source: "stage8.input.stage7.InstructionRa_8", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_8" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_9", oracle: "InstructionRa_9", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_9", eval_source: "stage8.input.stage7.InstructionRa_9", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_9" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_10", oracle: "InstructionRa_10", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_10", eval_source: "stage8.input.stage7.InstructionRa_10", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_10" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_11", oracle: "InstructionRa_11", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_11", eval_source: "stage8.input.stage7.InstructionRa_11", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_11" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_12", oracle: "InstructionRa_12", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_12", eval_source: "stage8.input.stage7.InstructionRa_12", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_12" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_13", oracle: "InstructionRa_13", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_13", eval_source: "stage8.input.stage7.InstructionRa_13", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_13" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_14", oracle: "InstructionRa_14", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_14", eval_source: "stage8.input.stage7.InstructionRa_14", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_14" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_15", oracle: "InstructionRa_15", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_15", eval_source: "stage8.input.stage7.InstructionRa_15", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_15" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_16", oracle: "InstructionRa_16", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_16", eval_source: "stage8.input.stage7.InstructionRa_16", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_16" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_17", oracle: "InstructionRa_17", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_17", eval_source: "stage8.input.stage7.InstructionRa_17", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_17" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_18", oracle: "InstructionRa_18", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_18", eval_source: "stage8.input.stage7.InstructionRa_18", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_18" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_19", oracle: "InstructionRa_19", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_19", eval_source: "stage8.input.stage7.InstructionRa_19", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_19" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_20", oracle: "InstructionRa_20", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_20", eval_source: "stage8.input.stage7.InstructionRa_20", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_20" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_21", oracle: "InstructionRa_21", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_21", eval_source: "stage8.input.stage7.InstructionRa_21", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_21" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_22", oracle: "InstructionRa_22", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_22", eval_source: "stage8.input.stage7.InstructionRa_22", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_22" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_23", oracle: "InstructionRa_23", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_23", eval_source: "stage8.input.stage7.InstructionRa_23", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_23" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_24", oracle: "InstructionRa_24", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_24", eval_source: "stage8.input.stage7.InstructionRa_24", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_24" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_25", oracle: "InstructionRa_25", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_25", eval_source: "stage8.input.stage7.InstructionRa_25", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_25" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_26", oracle: "InstructionRa_26", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_26", eval_source: "stage8.input.stage7.InstructionRa_26", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_26" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_27", oracle: "InstructionRa_27", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_27", eval_source: "stage8.input.stage7.InstructionRa_27", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_27" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_28", oracle: "InstructionRa_28", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_28", eval_source: "stage8.input.stage7.InstructionRa_28", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_28" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_29", oracle: "InstructionRa_29", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_29", eval_source: "stage8.input.stage7.InstructionRa_29", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_29" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_30", oracle: "InstructionRa_30", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_30", eval_source: "stage8.input.stage7.InstructionRa_30", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_30" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_31", oracle: "InstructionRa_31", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_31", eval_source: "stage8.input.stage7.InstructionRa_31", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_31" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.BytecodeRa_0", oracle: "BytecodeRa_0", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.BytecodeRa_0", eval_source: "stage8.input.stage7.BytecodeRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_0" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.BytecodeRa_1", oracle: "BytecodeRa_1", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.BytecodeRa_1", eval_source: "stage8.input.stage7.BytecodeRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_1" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.BytecodeRa_2", oracle: "BytecodeRa_2", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.BytecodeRa_2", eval_source: "stage8.input.stage7.BytecodeRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_2" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RamRa_0", oracle: "RamRa_0", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.RamRa_0", eval_source: "stage8.input.stage7.RamRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_0" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RamRa_1", oracle: "RamRa_1", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.RamRa_1", eval_source: "stage8.input.stage7.RamRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_1" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RamRa_2", oracle: "RamRa_2", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.RamRa_2", eval_source: "stage8.input.stage7.RamRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_2" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RamRa_3", oracle: "RamRa_3", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.RamRa_3", eval_source: "stage8.input.stage7.RamRa_3", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_3" }, +]; + +pub const STAGE8_OPENING_BATCH_ORDERED_CLAIMS: &[&str] = &["stage8.evaluation.opening.RamInc", "stage8.evaluation.opening.RdInc", "stage8.evaluation.opening.InstructionRa_0", "stage8.evaluation.opening.InstructionRa_1", "stage8.evaluation.opening.InstructionRa_2", "stage8.evaluation.opening.InstructionRa_3", "stage8.evaluation.opening.InstructionRa_4", "stage8.evaluation.opening.InstructionRa_5", "stage8.evaluation.opening.InstructionRa_6", "stage8.evaluation.opening.InstructionRa_7", "stage8.evaluation.opening.InstructionRa_8", "stage8.evaluation.opening.InstructionRa_9", "stage8.evaluation.opening.InstructionRa_10", "stage8.evaluation.opening.InstructionRa_11", "stage8.evaluation.opening.InstructionRa_12", "stage8.evaluation.opening.InstructionRa_13", "stage8.evaluation.opening.InstructionRa_14", "stage8.evaluation.opening.InstructionRa_15", "stage8.evaluation.opening.InstructionRa_16", "stage8.evaluation.opening.InstructionRa_17", "stage8.evaluation.opening.InstructionRa_18", "stage8.evaluation.opening.InstructionRa_19", "stage8.evaluation.opening.InstructionRa_20", "stage8.evaluation.opening.InstructionRa_21", "stage8.evaluation.opening.InstructionRa_22", "stage8.evaluation.opening.InstructionRa_23", "stage8.evaluation.opening.InstructionRa_24", "stage8.evaluation.opening.InstructionRa_25", "stage8.evaluation.opening.InstructionRa_26", "stage8.evaluation.opening.InstructionRa_27", "stage8.evaluation.opening.InstructionRa_28", "stage8.evaluation.opening.InstructionRa_29", "stage8.evaluation.opening.InstructionRa_30", "stage8.evaluation.opening.InstructionRa_31", "stage8.evaluation.opening.BytecodeRa_0", "stage8.evaluation.opening.BytecodeRa_1", "stage8.evaluation.opening.BytecodeRa_2", "stage8.evaluation.opening.RamRa_0", "stage8.evaluation.opening.RamRa_1", "stage8.evaluation.opening.RamRa_2", "stage8.evaluation.opening.RamRa_3"]; + +pub const STAGE8_OPENING_BATCH: Stage8OpeningBatchPlan = Stage8OpeningBatchPlan { symbol: "stage8.evaluation.openings", proof_slot: "stage8.evaluation", policy: "jolt_stage8_joint_rlc", count: 41, ordered_claims: STAGE8_OPENING_BATCH_ORDERED_CLAIMS }; + +pub const STAGE8_PCS_PROOF: Stage8PcsProofPlan = Stage8PcsProofPlan { symbol: "stage8.evaluation.proof", mode: "open", pcs: "dory", proof_slot: "stage8.evaluation", transcript_label: "rlc_claims", batch: "stage8.evaluation.openings" }; + +pub const STAGE8_PROGRAM: Stage8EvaluationProgramPlan = Stage8EvaluationProgramPlan { + role: "prover", + function: "jolt.stage8", + params: STAGE8_PARAMS, + evaluation_point_source: STAGE8_EVALUATION_POINT_SOURCE, + opening_inputs: STAGE8_OPENING_INPUTS, + opening_claims: STAGE8_OPENING_CLAIMS, + opening_batch: STAGE8_OPENING_BATCH, + pcs_proof: STAGE8_PCS_PROOF, +}; diff --git a/crates/jolt-verifier/Cargo.toml b/crates/jolt-verifier/Cargo.toml new file mode 100644 index 0000000000..3b6ecdafd5 --- /dev/null +++ b/crates/jolt-verifier/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "jolt-verifier" +version = "0.0.0" +edition = "2021" +license = "MIT OR Apache-2.0" +description = "Bolt-generated Jolt verifier role crate" +repository = "https://github.com/a16z/jolt" + +[lints] +workspace = true + +[dependencies] +jolt-dory.workspace = true +jolt-field.workspace = true +jolt-lookup-tables.workspace = true +jolt-openings.workspace = true +jolt-poly.workspace = true +jolt-sumcheck.workspace = true +jolt-transcript.workspace = true +serde.workspace = true +tracing.workspace = true diff --git a/crates/jolt-verifier/src/lib.rs b/crates/jolt-verifier/src/lib.rs new file mode 100644 index 0000000000..c9dfdffc26 --- /dev/null +++ b/crates/jolt-verifier/src/lib.rs @@ -0,0 +1,87 @@ +pub mod stages; +#[rustfmt::skip] +pub mod verifier; + +pub use stages::{ + stage1_outer::{verify_stage1_outer_with_program, Stage1VerifierProgramPlan}, + stage2::{verify_stage2_with_program, Stage2VerifierProgramPlan}, + stage3::{verify_stage3_with_program, Stage3VerifierProgramPlan}, + stage4::{verify_stage4_with_program, Stage4VerifierProgramPlan}, + stage5::{verify_stage5_with_program, Stage5VerifierProgramPlan}, + stage6::{verify_stage6_with_program, Stage6VerifierProgramPlan}, + stage7::{verify_stage7_with_program, Stage7VerifierProgramPlan}, +}; + +pub use verifier::{ + default_verifier_programs, verify_jolt, verify_jolt_evaluation_proof, verify_jolt_prefix, + verify_jolt_prefix_with_programs, verify_jolt_through_stage5, + verify_jolt_through_stage5_with_programs, verify_jolt_through_stage6, + verify_jolt_through_stage6_with_programs, verify_jolt_through_stage7, + verify_jolt_through_stage7_with_programs, verify_jolt_with_programs, JoltEvaluationProof, + JoltEvaluationProofError, JoltNamedEval, JoltProof, JoltStage2RamAccess, JoltStage2RamData, + JoltStage2RamOutputLayout, JoltStage6BytecodeEntry, JoltStage6BytecodeReadRafData, + JoltStage6VerifierData, JoltStageChallengeVector, JoltStageExecutionArtifacts, + JoltStageOpeningInputValue, JoltStageProof, JoltSumcheckOutput, JoltVerificationArtifacts, + JoltVerifierInputs, JoltVerifierPrograms, JoltVerifierTarget, JoltVerifyError, +}; + +pub const TRANSCRIPT_LABEL: &[u8] = b"Jolt"; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct GeneratedStage { + pub name: &'static str, + pub module: &'static str, + pub ordinal: usize, +} + +pub const GENERATED_STAGES: &[GeneratedStage] = &[ + GeneratedStage { + name: "commitment", + module: "commitment", + ordinal: 0, + }, + GeneratedStage { + name: "stage1_outer", + module: "stage1_outer", + ordinal: 1, + }, + GeneratedStage { + name: "stage2", + module: "stage2", + ordinal: 2, + }, + GeneratedStage { + name: "stage3", + module: "stage3", + ordinal: 3, + }, + GeneratedStage { + name: "stage4", + module: "stage4", + ordinal: 4, + }, + GeneratedStage { + name: "stage5", + module: "stage5", + ordinal: 5, + }, + GeneratedStage { + name: "stage6", + module: "stage6", + ordinal: 6, + }, + GeneratedStage { + name: "stage7", + module: "stage7", + ordinal: 7, + }, + GeneratedStage { + name: "stage8", + module: "stage8", + ordinal: 8, + }, +]; + +pub fn generated_stage_names() -> impl Iterator { + GENERATED_STAGES.iter().map(|stage| stage.name) +} diff --git a/crates/jolt-verifier/src/stages/commitment.rs b/crates/jolt-verifier/src/stages/commitment.rs new file mode 100644 index 0000000000..ea31591867 --- /dev/null +++ b/crates/jolt-verifier/src/stages/commitment.rs @@ -0,0 +1,343 @@ +#![allow(dead_code)] + +use jolt_dory::DoryCommitment; +use jolt_field::Fr; +use jolt_transcript::{AppendToTranscript, Blake2bTranscript, LabelWithCount, Transcript}; + +pub type DefaultCommitmentTranscript = Blake2bTranscript; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct CommitmentParams { + pub field: &'static str, + pub pcs: &'static str, + pub transcript: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct OraclePlan { + pub oracle: &'static str, + pub domain: &'static str, + pub num_vars: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct CommitmentBatchPlan { + pub artifact: &'static str, + pub pcs: &'static str, + pub oracle_family: &'static str, + pub label: &'static str, + pub oracles: &'static [&'static str], + pub count: usize, + pub domain: &'static str, + pub num_vars: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum OptionalSkipPolicy { + MissingOrZero, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct OptionalCommitmentPlan { + pub artifact: &'static str, + pub pcs: &'static str, + pub oracle: &'static str, + pub label: &'static str, + pub domain: &'static str, + pub num_vars: usize, + pub skip_policy: OptionalSkipPolicy, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct TranscriptStep { + pub label: &'static str, + pub source: &'static str, + pub optional: bool, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct CommitmentVerifierProgramPlan { + pub params: CommitmentParams, + pub oracle_plans: &'static [OraclePlan], + pub batch_plans: &'static [CommitmentBatchPlan], + pub optional_plans: &'static [OptionalCommitmentPlan], + pub transcript_steps: &'static [TranscriptStep], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct CommitmentRecord { + pub artifact: &'static str, + pub oracle: &'static str, + pub label: &'static str, + pub num_vars: usize, +} + +#[derive(Clone, Debug, Default)] +pub struct CommitmentArtifacts { + pub commitments: Vec>, + pub records: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum CommitmentPhaseError { + MissingProofCommitment { oracle: &'static str }, + MissingProofCommitmentSlot { artifact: &'static str, oracle: &'static str }, + MissingTranscriptSource { source: &'static str }, + PlanCountMismatch { artifact: &'static str, expected: usize, actual: usize }, + ProofCommitmentCountMismatch { expected: usize, actual: usize }, +} +pub const COMMITMENT_PARAMS: CommitmentParams = CommitmentParams { + field: "bn254_fr", + pcs: "dory", + transcript: "blake2b_transcript", +}; +pub const ORACLE_PLANS: &[OraclePlan] = &[ + OraclePlan { oracle: "RdInc", domain: "jolt.trace_domain", num_vars: 16 }, + OraclePlan { oracle: "RamInc", domain: "jolt.trace_domain", num_vars: 16 }, + OraclePlan { oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + OraclePlan { oracle: "UntrustedAdvice", domain: "jolt.trace_domain", num_vars: 16 }, + OraclePlan { oracle: "TrustedAdvice", domain: "jolt.trace_domain", num_vars: 16 }, +]; +pub const COMMITMENT_BATCH_0_ORACLES: &[&str] = &[ + "RdInc", + "RamInc", + "InstructionRa_0", + "InstructionRa_1", + "InstructionRa_2", + "InstructionRa_3", + "InstructionRa_4", + "InstructionRa_5", + "InstructionRa_6", + "InstructionRa_7", + "InstructionRa_8", + "InstructionRa_9", + "InstructionRa_10", + "InstructionRa_11", + "InstructionRa_12", + "InstructionRa_13", + "InstructionRa_14", + "InstructionRa_15", + "InstructionRa_16", + "InstructionRa_17", + "InstructionRa_18", + "InstructionRa_19", + "InstructionRa_20", + "InstructionRa_21", + "InstructionRa_22", + "InstructionRa_23", + "InstructionRa_24", + "InstructionRa_25", + "InstructionRa_26", + "InstructionRa_27", + "InstructionRa_28", + "InstructionRa_29", + "InstructionRa_30", + "InstructionRa_31", + "RamRa_0", + "RamRa_1", + "RamRa_2", + "RamRa_3", + "BytecodeRa_0", + "BytecodeRa_1", + "BytecodeRa_2", +]; +pub const COMMITMENT_BATCH_PLANS: &[CommitmentBatchPlan] = &[ + CommitmentBatchPlan { artifact: "jolt.main_witness_commitments", pcs: "dory", oracle_family: "jolt.main_witness_polys", label: "commitment", oracles: COMMITMENT_BATCH_0_ORACLES, count: 41, domain: "jolt.main_witness_commit_domain", num_vars: 20 }, +]; +pub const OPTIONAL_COMMITMENT_PLANS: &[OptionalCommitmentPlan] = &[ + OptionalCommitmentPlan { artifact: "jolt.untrusted_advice_commitment", pcs: "dory", oracle: "UntrustedAdvice", label: "untrusted_advice", domain: "jolt.trace_domain", num_vars: 16, skip_policy: OptionalSkipPolicy::MissingOrZero }, + OptionalCommitmentPlan { artifact: "jolt.trusted_advice_commitment", pcs: "dory", oracle: "TrustedAdvice", label: "trusted_advice", domain: "jolt.trace_domain", num_vars: 16, skip_policy: OptionalSkipPolicy::MissingOrZero }, +]; +pub const TRANSCRIPT_PLAN: &[TranscriptStep] = &[ + TranscriptStep { label: "commitment", source: "jolt.main_witness_commitments", optional: false }, + TranscriptStep { label: "untrusted_advice", source: "jolt.untrusted_advice_commitment", optional: true }, + TranscriptStep { label: "trusted_advice", source: "jolt.trusted_advice_commitment", optional: true }, +]; +pub const COMMITMENT_PROGRAM: CommitmentVerifierProgramPlan = CommitmentVerifierProgramPlan { + params: COMMITMENT_PARAMS, + oracle_plans: ORACLE_PLANS, + batch_plans: COMMITMENT_BATCH_PLANS, + optional_plans: OPTIONAL_COMMITMENT_PLANS, + transcript_steps: TRANSCRIPT_PLAN, +}; + +pub fn verify_commitment_phase( + proof_commitments: &[Option], + transcript: &mut T, +) -> Result +where + T: Transcript, +{ + verify_commitment_phase_with_program(&COMMITMENT_PROGRAM, proof_commitments, transcript) +} + +pub fn verify_commitment_phase_with_program( + program: &'static CommitmentVerifierProgramPlan, + proof_commitments: &[Option], + transcript: &mut T, +) -> Result +where + T: Transcript, +{ + let mut artifacts = CommitmentArtifacts::default(); + let mut cursor = 0usize; + for plan in program.batch_plans { + receive_batch(program, proof_commitments, &mut cursor, &mut artifacts, plan)?; + } + for plan in program.optional_plans { + receive_optional(program, proof_commitments, &mut cursor, &mut artifacts, plan)?; + } + if cursor != proof_commitments.len() { + return Err(CommitmentPhaseError::ProofCommitmentCountMismatch { + expected: cursor, + actual: proof_commitments.len(), + }); + } + absorb_transcript(program, &artifacts, transcript)?; + Ok(artifacts) +} + +fn receive_batch( + program: &'static CommitmentVerifierProgramPlan, + proof_commitments: &[Option], + cursor: &mut usize, + artifacts: &mut CommitmentArtifacts, + plan: &CommitmentBatchPlan, +) -> Result<(), CommitmentPhaseError> { + if plan.count != plan.oracles.len() { + return Err(CommitmentPhaseError::PlanCountMismatch { + artifact: plan.artifact, + expected: plan.count, + actual: plan.oracles.len(), + }); + } + for &oracle in plan.oracles { + let commitment = proof_commitments + .get(*cursor) + .ok_or(CommitmentPhaseError::MissingProofCommitmentSlot { + artifact: plan.artifact, + oracle, + })? + .as_ref() + .ok_or(CommitmentPhaseError::MissingProofCommitment { oracle })? + .clone(); + *cursor += 1; + let oracle_num_vars = oracle_num_vars(program, oracle, plan.num_vars); + artifacts.records.push(CommitmentRecord { + artifact: plan.artifact, + oracle, + label: plan.label, + num_vars: oracle_num_vars, + }); + artifacts.commitments.push(Some(commitment)); + } + Ok(()) +} + +fn receive_optional( + program: &'static CommitmentVerifierProgramPlan, + proof_commitments: &[Option], + cursor: &mut usize, + artifacts: &mut CommitmentArtifacts, + plan: &OptionalCommitmentPlan, +) -> Result<(), CommitmentPhaseError> { + let commitment = proof_commitments + .get(*cursor) + .ok_or(CommitmentPhaseError::MissingProofCommitmentSlot { + artifact: plan.artifact, + oracle: plan.oracle, + })? + .clone(); + *cursor += 1; + artifacts.records.push(CommitmentRecord { + artifact: plan.artifact, + oracle: plan.oracle, + label: plan.label, + num_vars: oracle_num_vars(program, plan.oracle, plan.num_vars), + }); + artifacts.commitments.push(commitment); + Ok(()) +} + +pub fn commitment_verifier_program() -> &'static CommitmentVerifierProgramPlan { + &COMMITMENT_PROGRAM +} + +fn oracle_num_vars( + program: &'static CommitmentVerifierProgramPlan, + oracle: &'static str, + fallback: usize, +) -> usize { + program + .oracle_plans + .iter() + .find(|plan| plan.oracle == oracle) + .map_or(fallback, |plan| plan.num_vars) +} + +fn absorb_transcript( + program: &'static CommitmentVerifierProgramPlan, + artifacts: &CommitmentArtifacts, + transcript: &mut T, +) -> Result<(), CommitmentPhaseError> +where + T: Transcript, +{ + for step in program.transcript_steps { + let mut appended = false; + for (record, commitment) in artifacts.records.iter().zip(&artifacts.commitments) { + if record.artifact != step.source { + continue; + } + if let Some(commitment) = commitment { + transcript.append(&LabelWithCount(step.label.as_bytes(), commitment.serialized_len())); + commitment.append_to_transcript(transcript); + appended = true; + } + } + if !step.optional && !appended { + return Err(CommitmentPhaseError::MissingTranscriptSource { + source: step.source, + }); + } + } + Ok(()) +} diff --git a/crates/jolt-verifier/src/stages/common.rs b/crates/jolt-verifier/src/stages/common.rs new file mode 100644 index 0000000000..5c31bfa6ef --- /dev/null +++ b/crates/jolt-verifier/src/stages/common.rs @@ -0,0 +1,1789 @@ +#![expect( + clippy::too_many_arguments, + reason = "generated verifier helpers mirror staged protocol ABIs" +)] + +use jolt_field::{Field, Fr}; +use jolt_poly::EqPolynomial; +use jolt_sumcheck::{ + CompressedLabeledRoundPoly, SumcheckClaim, SumcheckError, SumcheckProof, SumcheckVerifier, +}; +use jolt_transcript::{Label, Transcript}; +use serde::Serialize; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct StageParams { + pub field: &'static str, + pub pcs: &'static str, + pub transcript: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct KernelPlan { + pub symbol: &'static str, + pub relation: &'static str, + pub kind: &'static str, + pub backend: &'static str, + pub abi: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct TranscriptSqueezePlan { + pub symbol: &'static str, + pub label: &'static str, + pub kind: &'static str, + pub count: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct TranscriptAbsorbBytesPlan { + pub symbol: &'static str, + pub label: &'static str, + pub payload: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct ProgramStepPlan { + pub kind: &'static str, + pub symbol: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct OpeningInputPlan { + pub symbol: &'static str, + pub source_stage: &'static str, + pub source_claim: &'static str, + pub oracle: &'static str, + pub domain: &'static str, + pub point_arity: usize, + pub claim_kind: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct FieldConstantPlan { + pub symbol: &'static str, + pub field: &'static str, + pub value: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct FieldExprPlan { + pub symbol: &'static str, + pub kind: &'static str, + pub formula: &'static str, + pub operands: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct SumcheckClaimPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub domain: &'static str, + pub num_rounds: usize, + pub degree: usize, + pub claim: &'static str, + pub kernel: Option<&'static str>, + pub relation: Option<&'static str>, + pub claim_value: &'static str, + pub input_openings: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct SumcheckBatchPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub proof_slot: &'static str, + pub policy: &'static str, + pub count: usize, + pub ordered_claims: &'static str, + pub claim_operands: &'static str, + pub claim_label: &'static str, + pub round_label: &'static str, + pub round_schedule: &'static [usize], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct SumcheckDriverPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub proof_slot: &'static str, + pub kernel: Option<&'static str>, + pub relation: Option<&'static str>, + pub batch: &'static str, + pub policy: &'static str, + pub round_schedule: &'static [usize], + pub claim_label: &'static str, + pub round_label: &'static str, + pub num_rounds: usize, + pub degree: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct SumcheckInstanceResultPlan { + pub symbol: &'static str, + pub source: &'static str, + pub claim: &'static str, + pub relation: &'static str, + pub index: usize, + pub point_arity: usize, + pub num_rounds: usize, + pub round_offset: usize, + pub point_order: &'static str, + pub degree: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct SumcheckEvalPlan { + pub symbol: &'static str, + pub source: &'static str, + pub name: &'static str, + pub index: usize, + pub oracle: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct PointZeroPlan { + pub symbol: &'static str, + pub field: &'static str, + pub arity: usize, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct PointSlicePlan { + pub symbol: &'static str, + pub source: &'static str, + pub offset: usize, + pub length: usize, + pub input: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct PointConcatPlan { + pub symbol: &'static str, + pub layout: &'static str, + pub arity: usize, + pub inputs: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct OpeningClaimPlan { + pub symbol: &'static str, + pub oracle: &'static str, + pub domain: &'static str, + pub point_arity: usize, + pub claim_kind: &'static str, + pub point_source: &'static str, + pub eval_source: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct OpeningClaimEqualityPlan { + pub symbol: &'static str, + pub mode: &'static str, + pub lhs: &'static str, + pub rhs: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct OpeningBatchPlan { + pub symbol: &'static str, + pub stage: &'static str, + pub proof_slot: &'static str, + pub policy: &'static str, + pub count: usize, + pub ordered_claims: &'static str, + pub claim_operands: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct StageProgramPlan { + pub role: &'static str, + pub params: StageParams, + pub steps: &'static [ProgramStepPlan], + pub transcript_squeezes: &'static [TranscriptSqueezePlan], + pub transcript_absorb_bytes: &'static [TranscriptAbsorbBytesPlan], + pub opening_inputs: &'static [OpeningInputPlan], + pub field_constants: &'static [FieldConstantPlan], + pub field_exprs: &'static [FieldExprPlan], + pub kernels: &'static [KernelPlan], + pub claims: &'static [SumcheckClaimPlan], + pub batches: &'static [SumcheckBatchPlan], + pub drivers: &'static [SumcheckDriverPlan], + pub instance_results: &'static [SumcheckInstanceResultPlan], + pub evals: &'static [SumcheckEvalPlan], + pub point_zeros: &'static [PointZeroPlan], + pub point_slices: &'static [PointSlicePlan], + pub point_concats: &'static [PointConcatPlan], + pub opening_claims: &'static [OpeningClaimPlan], + pub opening_equalities: &'static [OpeningClaimEqualityPlan], + pub opening_batches: &'static [OpeningBatchPlan], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct StageProgramPlanNoPointZeros { + pub role: &'static str, + pub params: StageParams, + pub steps: &'static [ProgramStepPlan], + pub transcript_squeezes: &'static [TranscriptSqueezePlan], + pub transcript_absorb_bytes: &'static [TranscriptAbsorbBytesPlan], + pub opening_inputs: &'static [OpeningInputPlan], + pub field_constants: &'static [FieldConstantPlan], + pub field_exprs: &'static [FieldExprPlan], + pub kernels: &'static [KernelPlan], + pub claims: &'static [SumcheckClaimPlan], + pub batches: &'static [SumcheckBatchPlan], + pub drivers: &'static [SumcheckDriverPlan], + pub instance_results: &'static [SumcheckInstanceResultPlan], + pub evals: &'static [SumcheckEvalPlan], + pub point_slices: &'static [PointSlicePlan], + pub point_concats: &'static [PointConcatPlan], + pub opening_claims: &'static [OpeningClaimPlan], + pub opening_equalities: &'static [OpeningClaimEqualityPlan], + pub opening_batches: &'static [OpeningBatchPlan], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct StageVerifierProgramPlan { + pub params: StageParams, + pub steps: &'static [ProgramStepPlan], + pub transcript_squeezes: &'static [TranscriptSqueezePlan], + pub opening_inputs: &'static [OpeningInputPlan], + pub field_constants: &'static [FieldConstantPlan], + pub field_exprs: &'static [FieldExprPlan], + pub claims: &'static [SumcheckClaimPlan], + pub batches: &'static [SumcheckBatchPlan], + pub drivers: &'static [SumcheckDriverPlan], + pub instance_results: &'static [SumcheckInstanceResultPlan], + pub evals: &'static [SumcheckEvalPlan], + pub point_slices: &'static [PointSlicePlan], + pub point_concats: &'static [PointConcatPlan], + pub opening_claims: &'static [OpeningClaimPlan], + pub opening_equalities: &'static [OpeningClaimEqualityPlan], + pub opening_batches: &'static [OpeningBatchPlan], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct StageVerifierProgramPlanNoEqualities { + pub params: StageParams, + pub steps: &'static [ProgramStepPlan], + pub transcript_squeezes: &'static [TranscriptSqueezePlan], + pub opening_inputs: &'static [OpeningInputPlan], + pub field_constants: &'static [FieldConstantPlan], + pub field_exprs: &'static [FieldExprPlan], + pub claims: &'static [SumcheckClaimPlan], + pub batches: &'static [SumcheckBatchPlan], + pub drivers: &'static [SumcheckDriverPlan], + pub instance_results: &'static [SumcheckInstanceResultPlan], + pub evals: &'static [SumcheckEvalPlan], + pub point_slices: &'static [PointSlicePlan], + pub point_concats: &'static [PointConcatPlan], + pub opening_claims: &'static [OpeningClaimPlan], + pub opening_batches: &'static [OpeningBatchPlan], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct VerifierProgramPlanMinimal { + pub params: StageParams, + pub transcript_squeezes: &'static [TranscriptSqueezePlan], + pub claims: &'static [SumcheckClaimPlan], + pub batches: &'static [SumcheckBatchPlan], + pub drivers: &'static [SumcheckDriverPlan], + pub instance_results: &'static [SumcheckInstanceResultPlan], + pub evals: &'static [SumcheckEvalPlan], + pub opening_claims: &'static [OpeningClaimPlan], + pub opening_batches: &'static [OpeningBatchPlan], +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize)] +pub struct StageNamedEval { + pub name: &'static str, + pub oracle: &'static str, + pub value: F, +} + +#[derive(Clone, Debug, Serialize)] +pub struct StageSumcheckOutput { + pub driver: &'static str, + pub point: Vec, + pub evals: Vec>, + pub proof: SumcheckProof, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct StageChallengeVector { + pub symbol: &'static str, + pub values: Vec, +} + +#[derive(Clone, Debug)] +pub struct StageExecutionArtifacts { + pub challenge_vectors: Vec>, + pub sumchecks: Vec>, + pub opening_batches: Vec<&'static OpeningBatchPlan>, +} + +impl Default for StageExecutionArtifacts { + fn default() -> Self { + Self { + challenge_vectors: Vec::new(), + sumchecks: Vec::new(), + opening_batches: Vec::new(), + } + } +} + +#[derive(Clone, Debug, Default, Serialize)] +pub struct StageProof { + pub sumchecks: Vec>, +} + +#[derive(Clone, Debug)] +pub struct StageOpeningInputValue { + pub symbol: &'static str, + pub point: Vec, + pub eval: F, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum RuntimePlanError { + MissingBatch { + driver: &'static str, + batch: &'static str, + }, + MissingClaim { + batch: &'static str, + claim: &'static str, + }, + MissingValue { + symbol: &'static str, + }, + InvalidInputLength { + input: &'static str, + expected: usize, + actual: usize, + }, + InvalidProof { + driver: &'static str, + reason: &'static str, + }, + UnsupportedFieldExpr { + symbol: &'static str, + formula: &'static str, + }, +} + +macro_rules! impl_runtime_plan_error_conversion { + ($error:ident) => { + impl From for $error { + fn from(error: super::common::RuntimePlanError) -> Self { + match error { + super::common::RuntimePlanError::MissingBatch { driver, batch } => { + Self::MissingBatch { driver, batch } + } + super::common::RuntimePlanError::MissingClaim { batch, claim } => { + Self::MissingClaim { batch, claim } + } + super::common::RuntimePlanError::MissingValue { symbol } => { + Self::MissingValue { symbol } + } + super::common::RuntimePlanError::InvalidInputLength { + input, + expected, + actual, + } => Self::InvalidInputLength { + input, + expected, + actual, + }, + super::common::RuntimePlanError::InvalidProof { driver, reason } => { + Self::InvalidProof { driver, reason } + } + super::common::RuntimePlanError::UnsupportedFieldExpr { symbol, formula } => { + Self::UnsupportedFieldExpr { symbol, formula } + } + } + } + } + }; +} + +pub(crate) use impl_runtime_plan_error_conversion; + +pub trait SymbolPlan { + fn symbol(&self) -> &'static str; +} + +impl SymbolPlan for TranscriptSqueezePlan { + fn symbol(&self) -> &'static str { + self.symbol + } +} + +impl SymbolPlan for TranscriptAbsorbBytesPlan { + fn symbol(&self) -> &'static str { + self.symbol + } +} + +impl SymbolPlan for SumcheckBatchPlan { + fn symbol(&self) -> &'static str { + self.symbol + } +} + +impl SymbolPlan for SumcheckClaimPlan { + fn symbol(&self) -> &'static str { + self.symbol + } +} + +impl SymbolPlan for SumcheckDriverPlan { + fn symbol(&self) -> &'static str { + self.symbol + } +} + +impl SymbolPlan for OpeningClaimPlan { + fn symbol(&self) -> &'static str { + self.symbol + } +} + +pub trait SumcheckClaimInfo: SymbolPlan { + fn num_rounds(&self) -> usize; + fn claim_value(&self) -> &'static str; +} + +impl SumcheckClaimInfo for SumcheckClaimPlan { + fn num_rounds(&self) -> usize { + self.num_rounds + } + + fn claim_value(&self) -> &'static str { + self.claim_value + } +} + +pub trait SumcheckDriverInfo: SymbolPlan { + fn batch(&self) -> &'static str; + fn num_rounds(&self) -> usize; + fn degree(&self) -> usize; + fn round_label(&self) -> &'static str; +} + +impl SumcheckDriverInfo for SumcheckDriverPlan { + fn batch(&self) -> &'static str { + self.batch + } + + fn num_rounds(&self) -> usize { + self.num_rounds + } + + fn degree(&self) -> usize { + self.degree + } + + fn round_label(&self) -> &'static str { + self.round_label + } +} + +#[derive(Clone, Debug, Default)] +pub struct ValueStore { + scalars: Vec<(&'static str, F)>, + points: Vec<(&'static str, Vec)>, +} + +impl ValueStore { + pub fn with_opening_inputs( + inputs: &[StageOpeningInputValue], + expected_inputs: &[OpeningInputPlan], + ) -> Result { + if inputs.len() != expected_inputs.len() { + return Err(RuntimePlanError::InvalidInputLength { + input: "opening_inputs", + expected: expected_inputs.len(), + actual: inputs.len(), + }); + } + for expected in expected_inputs { + let matching_count = inputs + .iter() + .filter(|input| input.symbol == expected.symbol) + .count(); + if matching_count != 1 { + return Err(RuntimePlanError::InvalidInputLength { + input: expected.symbol, + expected: 1, + actual: matching_count, + }); + } + if let Some(input) = inputs.iter().find(|input| input.symbol == expected.symbol) { + if input.point.len() != expected.point_arity { + return Err(RuntimePlanError::InvalidInputLength { + input: expected.symbol, + expected: expected.point_arity, + actual: input.point.len(), + }); + } + } + } + let mut store = Self::default(); + for input in inputs { + store.insert_scalar(input.symbol, input.eval); + store.insert_point(input.symbol, input.point.clone()); + } + Ok(store) + } + + pub fn seed_constants(&mut self, constants: &[FieldConstantPlan]) { + for constant in constants { + self.insert_scalar(constant.symbol, F::from_u64(constant.value as u64)); + } + } + + pub fn seed_point_zeros(&mut self, point_zeros: &[PointZeroPlan]) { + for zero in point_zeros { + self.insert_point(zero.symbol, vec![F::from_u64(0); zero.arity]); + } + } + + pub fn observe_challenge_vector( + &mut self, + plan: &TranscriptSqueezePlan, + values: &[F], + invalid_input_length: impl Fn(&'static str, usize, usize) -> E, + ) -> Result<(), E> { + self.insert_point(plan.symbol, values.to_vec()); + if matches!(plan.kind, "challenge_scalar" | "scalar") { + if values.len() != 1 { + return Err(invalid_input_length(plan.symbol, 1, values.len())); + } + self.insert_scalar(plan.symbol, values[0]); + } + Ok(()) + } + + pub fn observe_sumcheck_output( + &mut self, + instance_results: &[SumcheckInstanceResultPlan], + evals: &[SumcheckEvalPlan], + output: &StageSumcheckOutput, + normalize_point: impl Fn(&SumcheckInstanceResultPlan, Vec) -> Result, E>, + invalid_input_length: impl Fn(&'static str, usize, usize) -> E, + missing_value: impl Fn(&'static str) -> E, + ) -> Result<(), E> { + self.insert_point(output.driver, output.point.clone()); + for instance in instance_results + .iter() + .filter(|instance| instance.source == output.driver) + { + let end = instance.round_offset + instance.point_arity; + let point = output + .point + .get(instance.round_offset..end) + .ok_or_else(|| invalid_input_length(instance.symbol, end, output.point.len()))? + .to_vec(); + self.insert_point(instance.symbol, normalize_point(instance, point)?); + } + for eval in evals.iter().filter(|eval| eval.source == output.driver) { + let value = output + .evals + .iter() + .find(|value| value.name == eval.name) + .or_else(|| output.evals.get(eval.index)) + .ok_or_else(|| missing_value(eval.symbol))? + .value; + self.insert_scalar(eval.symbol, value); + self.insert_scalar(eval.name, value); + } + Ok(()) + } + + pub fn evaluate_available_points( + &mut self, + point_slices: &[PointSlicePlan], + point_concats: &[PointConcatPlan], + invalid_input_length: impl Fn(&'static str, usize, usize) -> E, + ) -> Result<(), E> { + loop { + let mut progress = 0usize; + for slice in point_slices { + if self.try_point(slice.symbol).is_some() { + continue; + } + let Some(input) = self.try_point(slice.input) else { + continue; + }; + let end = slice.offset + slice.length; + let point = input + .get(slice.offset..end) + .ok_or_else(|| invalid_input_length(slice.symbol, end, input.len()))? + .to_vec(); + self.insert_point(slice.symbol, point); + progress += 1; + } + for concat in point_concats { + if self.try_point(concat.symbol).is_some() { + continue; + } + let Some(point) = self.try_concat_point(concat) else { + continue; + }; + if point.len() != concat.arity { + return Err(invalid_input_length( + concat.symbol, + concat.arity, + point.len(), + )); + } + self.insert_point(concat.symbol, point); + progress += 1; + } + if progress == 0 { + return Ok(()); + } + } + } + + pub fn evaluate_available_field_exprs( + &mut self, + field_exprs: &[FieldExprPlan], + evaluate: impl Fn(&FieldExprPlan, &[F]) -> Result, + ) -> Result<(), E> { + loop { + let mut progress = 0usize; + for expr in field_exprs { + if self.try_scalar(expr.symbol).is_some() { + continue; + } + let Some(operands) = self.try_expr_operands(expr) else { + continue; + }; + self.insert_scalar(expr.symbol, evaluate(expr, &operands)?); + progress += 1; + } + if progress == 0 { + return Ok(()); + } + } + } + + pub fn verify_opening_equalities( + &self, + opening_equalities: &[OpeningClaimEqualityPlan], + invalid_proof: impl Fn(&'static str, &'static str) -> E, + missing_value: impl Fn(&'static str) -> E, + ) -> Result<(), E> { + for equality in opening_equalities { + match equality.mode { + "point_and_eval" => { + if self.point_or(equality.lhs, &missing_value)? + != self.point_or(equality.rhs, &missing_value)? + || self.scalar_or(equality.lhs, &missing_value)? + != self.scalar_or(equality.rhs, &missing_value)? + { + return Err(invalid_proof( + equality.symbol, + "opening claim equality failed", + )); + } + } + _ => { + return Err(invalid_proof( + equality.symbol, + "unsupported opening equality mode", + )); + } + } + } + Ok(()) + } + + pub fn insert_scalar(&mut self, symbol: &'static str, value: F) { + if let Some((_, existing)) = self.scalars.iter_mut().find(|(name, _)| *name == symbol) { + *existing = value; + } else { + self.scalars.push((symbol, value)); + } + } + + pub fn insert_point(&mut self, symbol: &'static str, point: Vec) { + if let Some((_, existing)) = self.points.iter_mut().find(|(name, _)| *name == symbol) { + *existing = point; + } else { + self.points.push((symbol, point)); + } + } + + pub fn scalar_or( + &self, + symbol: &'static str, + missing_value: impl FnOnce(&'static str) -> E, + ) -> Result { + self.try_scalar(symbol).ok_or_else(|| missing_value(symbol)) + } + + pub fn try_scalar(&self, symbol: &str) -> Option { + self.scalars + .iter() + .find(|(name, _)| *name == symbol) + .map(|(_, value)| *value) + } + + pub fn point_or( + &self, + symbol: &'static str, + missing_value: impl FnOnce(&'static str) -> E, + ) -> Result<&[F], E> { + self.try_point(symbol).ok_or_else(|| missing_value(symbol)) + } + + pub fn try_point(&self, symbol: &str) -> Option<&[F]> { + self.points + .iter() + .find(|(name, _)| *name == symbol) + .map(|(_, point)| point.as_slice()) + } + + fn try_expr_operands(&self, expr: &FieldExprPlan) -> Option> { + if expr.operands.is_empty() { + return Some(Vec::new()); + } + expr.operands + .split('|') + .map(|operand| self.try_scalar(operand)) + .collect() + } + + fn try_concat_point(&self, concat: &PointConcatPlan) -> Option> { + let mut point = Vec::with_capacity(concat.arity); + for input in symbol_list(concat.inputs) { + point.extend_from_slice(self.try_point(input)?); + } + Some(point) + } +} + +pub fn symbol_list(symbols: &'static str) -> impl Iterator { + symbols.split('|').filter(|symbol| !symbol.is_empty()) +} + +pub fn find_plan<'a, T: SymbolPlan>(plans: &'a [T], symbol: &str) -> Option<&'a T> { + plans.iter().find(|plan| plan.symbol() == symbol) +} + +pub fn find_batch<'a>( + batches: &'a [SumcheckBatchPlan], + driver: &'static str, + batch: &'static str, +) -> Result<&'a SumcheckBatchPlan, RuntimePlanError> { + find_plan(batches, batch).ok_or(RuntimePlanError::MissingBatch { driver, batch }) +} + +pub fn batch_claims<'a, C: SymbolPlan>( + claims: &'a [C], + batch: &SumcheckBatchPlan, +) -> Result, RuntimePlanError> { + symbol_list(batch.claim_operands) + .map(|symbol| { + find_plan(claims, symbol).ok_or(RuntimePlanError::MissingClaim { + batch: batch.symbol, + claim: symbol, + }) + }) + .collect() +} + +pub fn batch_claim_values( + claims: &[&C], + field_exprs: &[FieldExprPlan], + store: &mut ValueStore, +) -> Result, RuntimePlanError> { + claims + .iter() + .map(|claim| { + store.evaluate_available_field_exprs(field_exprs, evaluate_field_expr)?; + store.scalar_or(claim.claim_value(), |symbol| { + RuntimePlanError::MissingValue { symbol } + }) + }) + .collect() +} + +pub fn verify_batched_sumcheck( + driver: &'static D, + proof: &StageSumcheckOutput, + claims: &'static [C], + batches: &'static [SumcheckBatchPlan], + field_exprs: &'static [FieldExprPlan], + opening_inputs: &'static [OpeningInputPlan], + opening_claims: &'static [OpeningClaimPlan], + opening_batches: &'static [OpeningBatchPlan], + store: &mut ValueStore, + transcript: &mut T, + expected_output: Expected, + observe_output: Observe, + map_sumcheck: MapSumcheck, +) -> Result, E> +where + T: Transcript, + E: From, + C: SumcheckClaimInfo, + D: SumcheckDriverInfo, + Expected: FnOnce(&ValueStore, &[StageNamedEval], &[Fr], &[Fr]) -> Result, + Observe: FnOnce(&mut ValueStore, &StageSumcheckOutput) -> Result<(), E>, + MapSumcheck: FnOnce(&'static str, SumcheckError) -> E, +{ + if proof.driver != driver.symbol() { + return Err(RuntimePlanError::InvalidProof { + driver: driver.symbol(), + reason: "driver symbol mismatch", + } + .into()); + } + let batch = find_batch(batches, driver.symbol(), driver.batch())?; + let claims = batch_claims(claims, batch)?; + let input_claims = batch_claim_values(&claims, field_exprs, store)?; + for claim in &input_claims { + append_labeled_scalar(transcript, batch.claim_label, claim); + } + let batching_coeffs = transcript.challenge_vector(claims.len()); + let claimed_sum = input_claims + .iter() + .zip(claims.iter()) + .zip(&batching_coeffs) + .map(|((claim, plan), coefficient)| { + claim.mul_pow_2(driver.num_rounds() - plan.num_rounds()) * *coefficient + }) + .sum::(); + let claim = SumcheckClaim::new(driver.num_rounds(), driver.degree(), claimed_sum); + let round_proofs = proof + .proof + .round_polynomials + .iter() + .map(|poly| CompressedLabeledRoundPoly::new(poly, driver.round_label().as_bytes())) + .collect::>(); + let output = SumcheckVerifier::verify(&claim, &round_proofs, transcript) + .map_err(|error| map_sumcheck(driver.symbol(), error))?; + if !proof.point.is_empty() && proof.point != output.point { + return Err(RuntimePlanError::InvalidProof { + driver: driver.symbol(), + reason: "batched point mismatch", + } + .into()); + } + let expected = expected_output(store, &proof.evals, &output.point, &batching_coeffs)?; + if output.value != expected { + return Err(RuntimePlanError::InvalidProof { + driver: driver.symbol(), + reason: "batched output claim mismatch", + } + .into()); + } + let verified = StageSumcheckOutput { + driver: driver.symbol(), + point: output.point, + evals: proof.evals.clone(), + proof: proof.proof.clone(), + }; + observe_output(store, &verified)?; + append_opening_claims( + opening_inputs, + opening_claims, + opening_batches, + store, + transcript, + &verified.evals, + |batch, claim| RuntimePlanError::MissingClaim { batch, claim }, + |symbol| RuntimePlanError::MissingValue { symbol }, + )?; + Ok(verified) +} + +pub fn eval_by_name( + evals: &[StageNamedEval], + name: &'static str, +) -> Result { + evals + .iter() + .find(|eval| eval.name == name) + .map(|eval| eval.value) + .ok_or(RuntimePlanError::MissingValue { symbol: name }) +} + +pub fn indexed_evals_by_prefix( + evals: &[StageNamedEval], + prefix: &'static str, + count: usize, +) -> Result, RuntimePlanError> { + let mut values = vec![None; count]; + for eval in evals { + let Some(suffix) = eval.name.strip_prefix(prefix) else { + continue; + }; + let index = suffix + .parse::() + .map_err(|_| RuntimePlanError::InvalidProof { + driver: prefix, + reason: "invalid indexed eval suffix", + })?; + if index >= count || values[index].is_some() { + return Err(RuntimePlanError::InvalidProof { + driver: prefix, + reason: "invalid indexed eval", + }); + } + values[index] = Some(eval.value); + } + values + .into_iter() + .map(|value| value.ok_or(RuntimePlanError::MissingValue { symbol: prefix })) + .collect() +} + +pub fn indexed_evals_by_prefix_any( + evals: &[StageNamedEval], + prefix: &'static str, +) -> Result, RuntimePlanError> { + let mut indexed_values = Vec::new(); + for eval in evals { + let Some(suffix) = eval.name.strip_prefix(prefix) else { + continue; + }; + let index = suffix + .parse::() + .map_err(|_| RuntimePlanError::InvalidProof { + driver: prefix, + reason: "invalid indexed eval suffix", + })?; + if indexed_values + .iter() + .any(|(existing_index, _)| *existing_index == index) + { + return Err(RuntimePlanError::InvalidProof { + driver: prefix, + reason: "duplicate indexed eval", + }); + } + indexed_values.push((index, eval.value)); + } + if indexed_values.is_empty() { + return Err(RuntimePlanError::MissingValue { symbol: prefix }); + } + indexed_values.sort_by_key(|(index, _)| *index); + for (expected, (actual, _)) in indexed_values.iter().enumerate() { + if *actual != expected { + return Err(RuntimePlanError::InvalidProof { + driver: prefix, + reason: "non-contiguous indexed eval", + }); + } + } + Ok(indexed_values.into_iter().map(|(_, value)| value).collect()) +} + +pub fn single_operand( + symbol: &'static str, + operands: &[F], +) -> Result { + require_operand_count(symbol, 1, operands.len())?; + Ok(operands[0]) +} + +pub fn require_operand_count( + input: &'static str, + expected: usize, + actual: usize, +) -> Result<(), RuntimePlanError> { + if expected == actual { + Ok(()) + } else { + Err(RuntimePlanError::InvalidInputLength { + input, + expected, + actual, + }) + } +} + +pub fn evaluate_field_expr( + expr: &FieldExprPlan, + operands: &[F], +) -> Result { + match expr.formula { + "opening_eval" => Ok(single_operand(expr.symbol, operands)?), + "field.add" => { + require_operand_count(expr.symbol, 2, operands.len())?; + Ok(operands[0] + operands[1]) + } + "field.sub" => { + require_operand_count(expr.symbol, 2, operands.len())?; + Ok(operands[0] - operands[1]) + } + "field.mul" => { + require_operand_count(expr.symbol, 2, operands.len())?; + Ok(operands[0] * operands[1]) + } + "field.neg" => { + require_operand_count(expr.symbol, 1, operands.len())?; + Ok(-operands[0]) + } + formula => { + if let Some(exponent) = formula.strip_prefix("field.pow:") { + require_operand_count(expr.symbol, 1, operands.len())?; + let exponent = exponent.parse::().map_err(|_| { + RuntimePlanError::UnsupportedFieldExpr { + symbol: expr.symbol, + formula, + } + })?; + return Ok(pow_field(operands[0], exponent)); + } + Err(RuntimePlanError::UnsupportedFieldExpr { + symbol: expr.symbol, + formula, + }) + } + } +} + +pub fn bytecode_gamma_powers(gamma: Fr) -> [Fr; 8] { + let mut powers = [Fr::from_u64(1); 8]; + for index in 1..powers.len() { + powers[index] = powers[index - 1] * gamma; + } + powers +} + +pub fn indexed_boolean_eq(index: usize, point: &[Fr]) -> Fr { + point + .iter() + .enumerate() + .map(|(bit, value)| { + if (index >> (point.len() - 1 - bit)) & 1 == 1 { + *value + } else { + Fr::from_u64(1) - *value + } + }) + .product() +} + +pub fn field_powers(base: Fr, count: usize) -> Vec { + let mut powers = Vec::with_capacity(count); + let mut power = Fr::from_u64(1); + for _ in 0..count { + powers.push(power); + power *= base; + } + powers +} + +pub fn prefix_point<'a, F: Field>( + point: &'a [F], + length: usize, + input: &'static str, +) -> Result<&'a [F], RuntimePlanError> { + point + .get(..length) + .filter(|prefix| prefix.len() == length) + .ok_or(RuntimePlanError::InvalidInputLength { + input, + expected: length, + actual: point.len(), + }) +} + +pub fn suffix_point<'a, F: Field>( + point: &'a [F], + length: usize, + input: &'static str, +) -> Result<&'a [F], RuntimePlanError> { + point + .get(point.len().saturating_sub(length)..) + .filter(|suffix| suffix.len() == length) + .ok_or(RuntimePlanError::InvalidInputLength { + input, + expected: length, + actual: point.len(), + }) +} + +pub fn normalize_bytecode_read_raf_point( + point: &[F], + log_t: usize, + input: &'static str, +) -> Result, RuntimePlanError> { + let log_k = point + .len() + .checked_sub(log_t) + .ok_or(RuntimePlanError::InvalidInputLength { + input, + expected: log_t, + actual: point.len(), + })?; + let mut normalized = point.to_vec(); + normalized[..log_k].reverse(); + normalized[log_k..].reverse(); + Ok(normalized) +} + +pub fn normalize_instruction_read_raf_point( + point: &[F], + input: &'static str, +) -> Result, RuntimePlanError> { + const LOG_K: usize = 128; + if point.len() < LOG_K { + return Err(RuntimePlanError::InvalidInputLength { + input, + expected: LOG_K, + actual: point.len(), + }); + } + let mut normalized = point.to_vec(); + normalized[LOG_K..].reverse(); + Ok(normalized) +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage67RelationSymbols { + pub hamming_booleanity_relation: &'static str, + pub hamming_booleanity_instance: &'static str, + pub booleanity_point: &'static str, + pub stage5_instruction_ra0: &'static str, + pub booleanity_combined_point: &'static str, + pub booleanity_gamma: &'static str, + pub booleanity_instruction_ra_prefix: &'static str, + pub booleanity_bytecode_ra_prefix: &'static str, + pub booleanity_ram_ra_prefix: &'static str, + pub hamming_weight_eval: &'static str, + pub hamming_lookup_output: &'static str, + pub ram_ra_virtual_cycle: &'static str, + pub ram_ra_virtual_eval_prefix: &'static str, + pub instruction_ra_virtual_cycle: &'static str, + pub instruction_ra_virtual_eval_prefix: &'static str, + pub instruction_ra_virtual_input_prefix: &'static str, + pub instruction_ra_virtual_gamma: &'static str, + pub inc_ram_stage2: &'static str, + pub inc_ram_stage4: &'static str, + pub inc_rd_stage4: &'static str, + pub inc_rd_stage5: &'static str, + pub inc_gamma: &'static str, + pub inc_ram_eval: &'static str, + pub inc_rd_eval: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage67BytecodeSymbols { + pub point: &'static str, + pub gamma: &'static str, + pub bytecode_ra_eval_prefix: &'static str, + pub entries: &'static str, + pub entry_bytecode_index: &'static str, + pub stage_gammas: [&'static str; 5], + pub stage_cycle_points: [&'static str; 5], + pub stage4_register_point: &'static str, + pub stage5_register_point: &'static str, + pub entry_rd: &'static str, + pub entry_rs1: &'static str, + pub entry_rs2: &'static str, + pub entry_lookup_table: &'static str, +} + +pub trait Stage67BytecodeEntry { + fn address(&self) -> Fr; + fn imm(&self) -> Fr; + fn circuit_flags(&self) -> &[bool; 14]; + fn rd(&self) -> Option; + fn rs1(&self) -> Option; + fn rs2(&self) -> Option; + fn lookup_table(&self) -> Option; + fn is_interleaved(&self) -> bool; + fn is_branch(&self) -> bool; + fn left_is_rs1(&self) -> bool; + fn left_is_pc(&self) -> bool; + fn right_is_rs2(&self) -> bool; + fn right_is_imm(&self) -> bool; + fn is_noop(&self) -> bool; +} + +pub fn store_scalar(store: &ValueStore, symbol: &'static str) -> Result { + store.scalar_or(symbol, |symbol| RuntimePlanError::MissingValue { symbol }) +} + +pub fn store_point<'a>( + store: &'a ValueStore, + symbol: &'static str, +) -> Result<&'a [Fr], RuntimePlanError> { + store.point_or(symbol, |symbol| RuntimePlanError::MissingValue { symbol }) +} + +pub fn stage67_trace_rounds( + instance_results: &[SumcheckInstanceResultPlan], + symbols: &Stage67RelationSymbols, +) -> Result { + instance_results + .iter() + .find(|instance| instance.relation == symbols.hamming_booleanity_relation) + .map(|instance| instance.num_rounds) + .ok_or(RuntimePlanError::MissingValue { + symbol: symbols.hamming_booleanity_instance, + }) +} + +pub fn expected_stage67_bytecode_read_raf( + entries: &[E], + entry_bytecode_index: usize, + num_lookup_tables: usize, + store: &ValueStore, + evals: &[StageNamedEval], + local_point: &[Fr], + log_t: usize, + symbols: &Stage67BytecodeSymbols, +) -> Result { + let opening_point = normalize_bytecode_read_raf_point(local_point, log_t, symbols.point)?; + let log_k = opening_point.len() - log_t; + let (r_address_prime, r_cycle_prime) = opening_point.split_at(log_k); + + let gamma = store_scalar(store, symbols.gamma)?; + let gamma_powers = bytecode_gamma_powers(gamma); + let int_eval = identity_polynomial_eval(r_address_prime); + let stage_value_evals = stage67_bytecode_stage_value_evals( + entries, + entry_bytecode_index, + num_lookup_tables, + store, + r_address_prime, + r_cycle_prime.len(), + symbols, + )?; + let stage_cycle_points = + stage67_bytecode_stage_cycle_points(store, r_cycle_prime.len(), symbols)?; + let int_contrib = [ + gamma_powers[5] * int_eval, + Fr::from_u64(0), + gamma_powers[4] * int_eval, + Fr::from_u64(0), + Fr::from_u64(0), + ]; + + let mut val = Fr::from_u64(0); + for index in 0..stage_value_evals.len() { + val += (stage_value_evals[index] + int_contrib[index]) + * EqPolynomial::::mle(&stage_cycle_points[index], r_cycle_prime) + * gamma_powers[index]; + } + + let entry_bits = (0..log_k) + .map(|index| Fr::from_u64(((entry_bytecode_index >> (log_k - 1 - index)) & 1) as u64)) + .collect::>(); + let zero_cycle = vec![Fr::from_u64(0); r_cycle_prime.len()]; + let entry_contrib = gamma_powers[7] + * EqPolynomial::::mle(&entry_bits, r_address_prime) + * EqPolynomial::::mle(&zero_cycle, r_cycle_prime); + let bytecode_ra = indexed_evals_by_prefix_any(evals, symbols.bytecode_ra_eval_prefix)? + .into_iter() + .product::(); + Ok((val + entry_contrib) * bytecode_ra) +} + +pub fn expected_stage67_booleanity( + store: &ValueStore, + evals: &[StageNamedEval], + local_point: &[Fr], + log_t: usize, + symbols: &Stage67RelationSymbols, +) -> Result { + let log_k_chunk = + local_point + .len() + .checked_sub(log_t) + .ok_or(RuntimePlanError::InvalidInputLength { + input: symbols.booleanity_point, + expected: log_t, + actual: local_point.len(), + })?; + let stage5_point = store_point(store, symbols.stage5_instruction_ra0)?; + let stage5_address_len = + stage5_point + .len() + .checked_sub(log_t) + .ok_or(RuntimePlanError::InvalidInputLength { + input: symbols.stage5_instruction_ra0, + expected: log_t, + actual: stage5_point.len(), + })?; + if stage5_address_len < log_k_chunk { + return Err(RuntimePlanError::InvalidInputLength { + input: symbols.stage5_instruction_ra0, + expected: log_k_chunk + log_t, + actual: stage5_point.len(), + }); + } + + let mut stage5_addr = stage5_point[..stage5_address_len].to_vec(); + stage5_addr.reverse(); + let mut combined_r = stage5_addr[stage5_address_len - log_k_chunk..].to_vec(); + combined_r.extend(stage5_point[stage5_address_len..].iter().rev().copied()); + if combined_r.len() != local_point.len() { + return Err(RuntimePlanError::InvalidInputLength { + input: symbols.booleanity_combined_point, + expected: local_point.len(), + actual: combined_r.len(), + }); + } + let mut verifier_point = combined_r[..log_k_chunk].to_vec(); + verifier_point.reverse(); + verifier_point.extend(combined_r[log_k_chunk..].iter().rev().copied()); + let eq_eval = EqPolynomial::::mle(local_point, &verifier_point); + + let gamma = store_scalar(store, symbols.booleanity_gamma)?; + let gamma_sq = gamma.square(); + let mut gamma_power = Fr::from_u64(1); + let mut booleanity = Fr::from_u64(0); + for ra in stage67_booleanity_evals(evals, symbols)? { + booleanity += gamma_power * (ra.square() - ra); + gamma_power *= gamma_sq; + } + Ok(eq_eval * booleanity) +} + +pub fn expected_stage67_hamming_booleanity( + store: &ValueStore, + evals: &[StageNamedEval], + local_point: &[Fr], + symbols: &Stage67RelationSymbols, +) -> Result { + let hamming = eval_by_name(evals, symbols.hamming_weight_eval)?; + let lookup_output_point = reverse_slice(store_point(store, symbols.hamming_lookup_output)?); + if lookup_output_point.len() != local_point.len() { + return Err(RuntimePlanError::InvalidInputLength { + input: symbols.hamming_lookup_output, + expected: local_point.len(), + actual: lookup_output_point.len(), + }); + } + let eq_eval = EqPolynomial::::mle(local_point, &lookup_output_point); + Ok((hamming.square() - hamming) * eq_eval) +} + +pub fn expected_stage67_ram_ra_virtual( + store: &ValueStore, + evals: &[StageNamedEval], + local_point: &[Fr], + symbols: &Stage67RelationSymbols, +) -> Result { + let r_cycle_reduced = reverse_slice(local_point); + let r_cycle = suffix_point( + store_point(store, symbols.ram_ra_virtual_cycle)?, + r_cycle_reduced.len(), + symbols.ram_ra_virtual_cycle, + )?; + let eq_eval = EqPolynomial::::mle(r_cycle, &r_cycle_reduced); + let ram_ra = indexed_evals_by_prefix_any(evals, symbols.ram_ra_virtual_eval_prefix)? + .into_iter() + .product::(); + Ok(eq_eval * ram_ra) +} + +pub fn expected_stage67_instruction_ra_virtual( + opening_inputs: &[OpeningInputPlan], + store: &ValueStore, + evals: &[StageNamedEval], + local_point: &[Fr], + symbols: &Stage67RelationSymbols, +) -> Result { + let r_cycle_reduced = reverse_slice(local_point); + let r_cycle = suffix_point( + store_point(store, symbols.instruction_ra_virtual_cycle)?, + r_cycle_reduced.len(), + symbols.instruction_ra_virtual_cycle, + )?; + let eq_eval = EqPolynomial::::mle(r_cycle, &r_cycle_reduced); + let committed_ra = + indexed_evals_by_prefix_any(evals, symbols.instruction_ra_virtual_eval_prefix)?; + let virtual_count = opening_inputs + .iter() + .filter(|input| { + input + .symbol + .starts_with(symbols.instruction_ra_virtual_input_prefix) + }) + .count(); + if virtual_count == 0 || committed_ra.len() % virtual_count != 0 { + return Err(RuntimePlanError::InvalidInputLength { + input: symbols.instruction_ra_virtual_eval_prefix, + expected: virtual_count, + actual: committed_ra.len(), + }); + } + let committed_per_virtual = committed_ra.len() / virtual_count; + let gamma = store_scalar(store, symbols.instruction_ra_virtual_gamma)?; + let mut gamma_power = Fr::from_u64(1); + let mut value = Fr::from_u64(0); + for chunk in committed_ra.chunks(committed_per_virtual) { + value += gamma_power * chunk.iter().copied().product::(); + gamma_power *= gamma; + } + Ok(eq_eval * value) +} + +pub fn expected_stage67_inc_claim_reduction( + store: &ValueStore, + evals: &[StageNamedEval], + local_point: &[Fr], + symbols: &Stage67RelationSymbols, +) -> Result { + let r_cycle_reduced = reverse_slice(local_point); + let ram_inc_stage2 = suffix_point( + store_point(store, symbols.inc_ram_stage2)?, + r_cycle_reduced.len(), + symbols.inc_ram_stage2, + )?; + let ram_inc_stage4 = suffix_point( + store_point(store, symbols.inc_ram_stage4)?, + r_cycle_reduced.len(), + symbols.inc_ram_stage4, + )?; + let rd_inc_stage4 = suffix_point( + store_point(store, symbols.inc_rd_stage4)?, + r_cycle_reduced.len(), + symbols.inc_rd_stage4, + )?; + let rd_inc_stage5 = suffix_point( + store_point(store, symbols.inc_rd_stage5)?, + r_cycle_reduced.len(), + symbols.inc_rd_stage5, + )?; + let gamma = store_scalar(store, symbols.inc_gamma)?; + let eq_ram_combined = EqPolynomial::::mle(ram_inc_stage2, &r_cycle_reduced) + + gamma * EqPolynomial::::mle(ram_inc_stage4, &r_cycle_reduced); + let eq_rd_combined = EqPolynomial::::mle(rd_inc_stage4, &r_cycle_reduced) + + gamma * EqPolynomial::::mle(rd_inc_stage5, &r_cycle_reduced); + let ram_inc = eval_by_name(evals, symbols.inc_ram_eval)?; + let rd_inc = eval_by_name(evals, symbols.inc_rd_eval)?; + Ok(ram_inc * eq_ram_combined + gamma.square() * rd_inc * eq_rd_combined) +} + +fn stage67_booleanity_evals( + evals: &[StageNamedEval], + symbols: &Stage67RelationSymbols, +) -> Result, RuntimePlanError> { + let mut values = indexed_evals_by_prefix_any(evals, symbols.booleanity_instruction_ra_prefix)?; + values.extend(indexed_evals_by_prefix_any( + evals, + symbols.booleanity_bytecode_ra_prefix, + )?); + values.extend(indexed_evals_by_prefix_any( + evals, + symbols.booleanity_ram_ra_prefix, + )?); + Ok(values) +} + +fn stage67_bytecode_stage_cycle_points( + store: &ValueStore, + log_t: usize, + symbols: &Stage67BytecodeSymbols, +) -> Result<[Vec; 5], RuntimePlanError> { + let point = |index| { + let symbol = symbols.stage_cycle_points[index]; + suffix_point(store_point(store, symbol)?, log_t, symbol).map(|point| point.to_vec()) + }; + Ok([point(0)?, point(1)?, point(2)?, point(3)?, point(4)?]) +} + +fn stage67_bytecode_stage_value_evals( + entries: &[E], + entry_bytecode_index: usize, + num_lookup_tables: usize, + store: &ValueStore, + r_address: &[Fr], + log_t: usize, + symbols: &Stage67BytecodeSymbols, +) -> Result<[Fr; 5], RuntimePlanError> { + let expected_len = + 1usize + .checked_shl(r_address.len() as u32) + .ok_or(RuntimePlanError::InvalidInputLength { + input: symbols.entries, + expected: usize::BITS as usize, + actual: r_address.len(), + })?; + if entries.len() != expected_len { + return Err(RuntimePlanError::InvalidInputLength { + input: symbols.entries, + expected: expected_len, + actual: entries.len(), + }); + } + if entry_bytecode_index >= expected_len { + return Err(RuntimePlanError::InvalidInputLength { + input: symbols.entry_bytecode_index, + expected: expected_len, + actual: entry_bytecode_index + 1, + }); + } + + let stage1_gamma_powers = field_powers(store_scalar(store, symbols.stage_gammas[0])?, 16); + let stage2_gamma_powers = field_powers(store_scalar(store, symbols.stage_gammas[1])?, 4); + let stage3_gamma_powers = field_powers(store_scalar(store, symbols.stage_gammas[2])?, 9); + let stage4_gamma_powers = field_powers(store_scalar(store, symbols.stage_gammas[3])?, 3); + let stage5_gamma_powers = field_powers( + store_scalar(store, symbols.stage_gammas[4])?, + num_lookup_tables + 2, + ); + + let stage4_register_point = + stage67_register_prefix_point(store, symbols.stage4_register_point, log_t)?; + let stage5_register_point = + stage67_register_prefix_point(store, symbols.stage5_register_point, log_t)?; + + let mut evals = [Fr::from_u64(0); 5]; + for (index, entry) in entries.iter().enumerate() { + let eq = indexed_boolean_eq(index, r_address); + let values = stage67_bytecode_entry_stage_values( + entry, + num_lookup_tables, + stage4_register_point, + stage5_register_point, + &stage1_gamma_powers, + &stage2_gamma_powers, + &stage3_gamma_powers, + &stage4_gamma_powers, + &stage5_gamma_powers, + symbols, + )?; + for stage in 0..evals.len() { + evals[stage] += eq * values[stage]; + } + } + Ok(evals) +} + +fn stage67_bytecode_entry_stage_values( + entry: &E, + num_lookup_tables: usize, + stage4_register_point: &[Fr], + stage5_register_point: &[Fr], + stage1_gamma_powers: &[Fr], + stage2_gamma_powers: &[Fr], + stage3_gamma_powers: &[Fr], + stage4_gamma_powers: &[Fr], + stage5_gamma_powers: &[Fr], + symbols: &Stage67BytecodeSymbols, +) -> Result<[Fr; 5], RuntimePlanError> { + let flags = entry.circuit_flags(); + let mut stage1 = entry.address() + entry.imm() * stage1_gamma_powers[1]; + for (flag, gamma) in flags.iter().zip(stage1_gamma_powers.iter().skip(2)) { + if *flag { + stage1 += *gamma; + } + } + + let mut stage2 = Fr::from_u64(0); + if flags[5] { + stage2 += stage2_gamma_powers[0]; + } + if entry.is_branch() { + stage2 += stage2_gamma_powers[1]; + } + if flags[6] { + stage2 += stage2_gamma_powers[2]; + } + if flags[7] { + stage2 += stage2_gamma_powers[3]; + } + + let mut stage3 = entry.imm() + entry.address() * stage3_gamma_powers[1]; + if entry.left_is_rs1() { + stage3 += stage3_gamma_powers[2]; + } + if entry.left_is_pc() { + stage3 += stage3_gamma_powers[3]; + } + if entry.right_is_rs2() { + stage3 += stage3_gamma_powers[4]; + } + if entry.right_is_imm() { + stage3 += stage3_gamma_powers[5]; + } + if entry.is_noop() { + stage3 += stage3_gamma_powers[6]; + } + if flags[7] { + stage3 += stage3_gamma_powers[7]; + } + if flags[12] { + stage3 += stage3_gamma_powers[8]; + } + + let stage4 = stage67_register_eq(entry.rd(), stage4_register_point, symbols.entry_rd)? + * stage4_gamma_powers[0] + + stage67_register_eq(entry.rs1(), stage4_register_point, symbols.entry_rs1)? + * stage4_gamma_powers[1] + + stage67_register_eq(entry.rs2(), stage4_register_point, symbols.entry_rs2)? + * stage4_gamma_powers[2]; + + let mut stage5 = stage67_register_eq(entry.rd(), stage5_register_point, symbols.entry_rd)? + * stage5_gamma_powers[0]; + if !entry.is_interleaved() { + stage5 += stage5_gamma_powers[1]; + } + if let Some(table) = entry.lookup_table() { + if table >= num_lookup_tables { + return Err(RuntimePlanError::InvalidInputLength { + input: symbols.entry_lookup_table, + expected: num_lookup_tables, + actual: table + 1, + }); + } + stage5 += stage5_gamma_powers[2 + table]; + } + + Ok([stage1, stage2, stage3, stage4, stage5]) +} + +fn stage67_register_eq( + index: Option, + point: &[Fr], + input: &'static str, +) -> Result { + let Some(index) = index else { + return Ok(Fr::from_u64(0)); + }; + let register_count = + 1usize + .checked_shl(point.len() as u32) + .ok_or(RuntimePlanError::InvalidInputLength { + input, + expected: usize::BITS as usize, + actual: point.len(), + })?; + if index >= register_count { + return Err(RuntimePlanError::InvalidInputLength { + input, + expected: register_count, + actual: index + 1, + }); + } + Ok(indexed_boolean_eq(index, point)) +} + +fn stage67_register_prefix_point<'a>( + store: &'a ValueStore, + symbol: &'static str, + log_t: usize, +) -> Result<&'a [Fr], RuntimePlanError> { + let point = store_point(store, symbol)?; + let register_len = + point + .len() + .checked_sub(log_t) + .ok_or(RuntimePlanError::InvalidInputLength { + input: symbol, + expected: log_t, + actual: point.len(), + })?; + prefix_point(point, register_len, symbol) +} + +pub fn operand_polynomial_eval(point: &[Fr], left: bool) -> Fr { + let stride_offset = usize::from(!left); + let operand_bits = point.len() / 2; + (0..operand_bits) + .map(|index| point[2 * index + stride_offset].mul_pow_2(operand_bits - 1 - index)) + .sum() +} + +pub fn identity_polynomial_eval(point: &[Fr]) -> Fr { + point + .iter() + .enumerate() + .map(|(index, value)| value.mul_pow_2(point.len() - 1 - index)) + .sum() +} + +pub fn append_labeled_scalar(transcript: &mut T, label: &'static str, scalar: &Fr) +where + T: Transcript, +{ + transcript.append(&Label(label.as_bytes())); + transcript.append(scalar); +} + +pub fn append_opening_claims( + opening_inputs: &[OpeningInputPlan], + opening_claims: &[OpeningClaimPlan], + opening_batches: &[OpeningBatchPlan], + store: &mut ValueStore, + transcript: &mut T, + evals: &[StageNamedEval], + missing_claim: impl Fn(&'static str, &'static str) -> E, + missing_value: impl Fn(&'static str) -> E, +) -> Result<(), E> +where + T: Transcript, +{ + if opening_batches.is_empty() { + for eval in evals { + append_labeled_scalar(transcript, "opening_claim", &eval.value); + } + return Ok(()); + } + let mut seen = opening_inputs + .iter() + .filter_map(|input| { + store + .try_point(input.symbol) + .map(|point| (input.claim_kind, input.oracle, point.to_vec())) + }) + .collect::>(); + for batch in opening_batches { + for symbol in symbol_list(batch.claim_operands) { + let claim = opening_claims + .iter() + .find(|claim| claim.symbol == symbol) + .ok_or_else(|| missing_claim(batch.symbol, symbol))?; + let point = store.point_or(claim.point_source, &missing_value)?.to_vec(); + if seen.iter().any(|(kind, oracle, seen_point)| { + *kind == claim.claim_kind && *oracle == claim.oracle && seen_point == &point + }) { + continue; + } + let value = store.scalar_or(claim.eval_source, &missing_value)?; + append_labeled_scalar(transcript, "opening_claim", &value); + seen.push((claim.claim_kind, claim.oracle, point)); + } + } + Ok(()) +} + +pub fn lt_polynomial_eval(x: &[Fr], y: &[Fr]) -> Fr { + let mut lt_eval = Fr::from_u64(0); + let mut eq_term = Fr::from_u64(1); + for (x_i, y_i) in x.iter().zip(y.iter()) { + lt_eval += (Fr::from_u64(1) - *x_i) * *y_i * eq_term; + eq_term *= Fr::from_u64(1) - *x_i - *y_i + *x_i * *y_i + *x_i * *y_i; + } + lt_eval +} + +pub fn pow_field(base: F, mut exponent: usize) -> F { + let mut result = F::one(); + let mut power = base; + while exponent != 0 { + if exponent & 1 == 1 { + result *= power; + } + power = power.square(); + exponent >>= 1; + } + result +} + +pub fn reverse_slice(values: &[Fr]) -> Vec { + values.iter().rev().copied().collect() +} diff --git a/crates/jolt-verifier/src/stages/mod.rs b/crates/jolt-verifier/src/stages/mod.rs new file mode 100644 index 0000000000..14f741edaa --- /dev/null +++ b/crates/jolt-verifier/src/stages/mod.rs @@ -0,0 +1,19 @@ +pub mod common; +#[rustfmt::skip] +pub mod commitment; +#[rustfmt::skip] +pub mod stage1_outer; +#[rustfmt::skip] +pub mod stage2; +#[rustfmt::skip] +pub mod stage3; +#[rustfmt::skip] +pub mod stage4; +#[rustfmt::skip] +pub mod stage5; +#[rustfmt::skip] +pub mod stage6; +#[rustfmt::skip] +pub mod stage7; +#[rustfmt::skip] +pub mod stage8; diff --git a/crates/jolt-verifier/src/stages/stage1_outer.rs b/crates/jolt-verifier/src/stages/stage1_outer.rs new file mode 100644 index 0000000000..bd9b946c10 --- /dev/null +++ b/crates/jolt-verifier/src/stages/stage1_outer.rs @@ -0,0 +1,406 @@ +#![allow(dead_code)] + +use super::common::append_labeled_scalar; +use jolt_field::{Field, Fr}; +use jolt_sumcheck::{CompressedLabeledRoundPoly, LabeledRoundPoly, SumcheckClaim, SumcheckError, SumcheckVerifier}; +use jolt_transcript::{Blake2bTranscript, Transcript}; + +pub type DefaultStage1Transcript = Blake2bTranscript; + +pub type Stage1Params = super::common::StageParams; +pub type Stage1NamedEval = super::common::StageNamedEval; +pub type Stage1SumcheckOutput = super::common::StageSumcheckOutput; +pub type Stage1ChallengeVector = super::common::StageChallengeVector; +pub type Stage1ExecutionArtifacts = super::common::StageExecutionArtifacts; +pub type Stage1Proof = super::common::StageProof; +pub type Stage1VerifierProgramPlan = super::common::VerifierProgramPlanMinimal; + +pub use super::common::{ + OpeningBatchPlan as Stage1OpeningBatchPlan, OpeningClaimPlan as Stage1OpeningClaimPlan, + SumcheckBatchPlan as Stage1SumcheckBatchPlan, SumcheckEvalPlan as Stage1SumcheckEvalPlan, + SumcheckInstanceResultPlan as Stage1SumcheckInstanceResultPlan, + TranscriptSqueezePlan as Stage1TranscriptSqueezePlan, + SumcheckClaimPlan as Stage1SumcheckClaimPlan, + SumcheckDriverPlan as Stage1SumcheckDriverPlan, +}; + +#[derive(Debug)] +pub enum VerifyStage1Error { + UnexpectedProofCount { expected: usize, got: usize }, + MissingProof { driver: &'static str }, + MissingBatch { driver: &'static str, batch: &'static str }, + MissingClaim { driver: &'static str, claim: &'static str }, + MissingDependency { driver: &'static str, dependency: &'static str }, + InvalidProof { driver: &'static str, reason: &'static str }, + UnsupportedRelation { relation: &'static str }, + Sumcheck { driver: &'static str, error: SumcheckError }, +} + +pub const STAGE1_PARAMS: Stage1Params = Stage1Params { + field: "bn254_fr", + pcs: "dory", + transcript: "blake2b_transcript", +}; +pub const STAGE1_TRANSCRIPT_SQUEEZES: &[Stage1TranscriptSqueezePlan] = &[ + Stage1TranscriptSqueezePlan { symbol: "stage1.tau", label: "outer_tau", kind: "challenge_vector", count: 18 }, +]; + +pub const STAGE1_SUMCHECK_CLAIMS: &[Stage1SumcheckClaimPlan] = &[ + Stage1SumcheckClaimPlan { symbol: "stage1.uniskip.input", stage: "stage1", domain: "jolt.stage1_uniskip_domain", num_rounds: 1, degree: 27, claim: "stage1.zero", kernel: None, relation: Some("jolt.stage1.outer.uniskip"), claim_value: "stage1.zero", input_openings: "" }, + Stage1SumcheckClaimPlan { symbol: "stage1.outer_remaining.input", stage: "stage1", domain: "jolt.trace_domain", num_rounds: 17, degree: 3, claim: "stage1.uniskip.eval", kernel: None, relation: Some("jolt.stage1.outer.remaining"), claim_value: "stage1.uniskip.eval", input_openings: "stage1.uniskip.opening" }, +]; +pub const STAGE1_SUMCHECK_BATCH_0_ROUND_SCHEDULE: &[usize] = &[ + 1, +]; + +pub const STAGE1_SUMCHECK_BATCH_1_ROUND_SCHEDULE: &[usize] = &[ + 17, +]; + +pub const STAGE1_SUMCHECK_BATCHES: &[Stage1SumcheckBatchPlan] = &[ + Stage1SumcheckBatchPlan { symbol: "stage1.uniskip.batch", stage: "stage1", proof_slot: "stage1.uni_skip_first_round", policy: "single_instance", count: 1, ordered_claims: "stage1.uniskip.input", claim_operands: "stage1.uniskip.input", claim_label: "uniskip_claim", round_label: "uniskip_poly", round_schedule: STAGE1_SUMCHECK_BATCH_0_ROUND_SCHEDULE }, + Stage1SumcheckBatchPlan { symbol: "stage1.outer_remaining.batch", stage: "stage1", proof_slot: "stage1.sumcheck", policy: "jolt_core_front_loaded", count: 1, ordered_claims: "stage1.outer_remaining.input", claim_operands: "stage1.outer_remaining.input", claim_label: "sumcheck_claim", round_label: "sumcheck_poly", round_schedule: STAGE1_SUMCHECK_BATCH_1_ROUND_SCHEDULE }, +]; +pub const STAGE1_SUMCHECK_DRIVER_0_ROUND_SCHEDULE: &[usize] = &[ + 1, +]; + +pub const STAGE1_SUMCHECK_DRIVER_1_ROUND_SCHEDULE: &[usize] = &[ + 17, +]; + +pub const STAGE1_SUMCHECK_DRIVERS: &[Stage1SumcheckDriverPlan] = &[ + Stage1SumcheckDriverPlan { symbol: "stage1.uniskip.sumcheck", stage: "stage1", proof_slot: "stage1.uni_skip_first_round", kernel: None, relation: Some("jolt.stage1.outer.uniskip"), batch: "stage1.uniskip.batch", policy: "univariate_skip", round_schedule: STAGE1_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "uniskip_claim", round_label: "uniskip_poly", num_rounds: 1, degree: 27 }, + Stage1SumcheckDriverPlan { symbol: "stage1.outer_remaining.sumcheck", stage: "stage1", proof_slot: "stage1.sumcheck", kernel: None, relation: Some("jolt.stage1.outer.remaining"), batch: "stage1.outer_remaining.batch", policy: "jolt_core_front_loaded", round_schedule: STAGE1_SUMCHECK_DRIVER_1_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 17, degree: 3 }, +]; +pub const STAGE1_SUMCHECK_INSTANCE_RESULTS: &[Stage1SumcheckInstanceResultPlan] = &[ + Stage1SumcheckInstanceResultPlan { symbol: "stage1.uniskip.instance", source: "stage1.uniskip.sumcheck", claim: "stage1.uniskip.input", relation: "jolt.stage1.outer.uniskip", index: 0, point_arity: 1, num_rounds: 1, round_offset: 0, point_order: "as_is", degree: 27 }, + Stage1SumcheckInstanceResultPlan { symbol: "stage1.outer_remaining.instance", source: "stage1.outer_remaining.sumcheck", claim: "stage1.outer_remaining.input", relation: "jolt.stage1.outer.remaining", index: 0, point_arity: 16, num_rounds: 17, round_offset: 1, point_order: "reverse", degree: 3 }, +]; + +pub const STAGE1_SUMCHECK_EVALS: &[Stage1SumcheckEvalPlan] = &[ + Stage1SumcheckEvalPlan { symbol: "stage1.uniskip.eval", source: "stage1.uniskip.sumcheck", name: "stage1.uniskip.eval", index: 0, oracle: "UnivariateSkip" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.LeftInstructionInput", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.LeftInstructionInput", index: 0, oracle: "LeftInstructionInput" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.RightInstructionInput", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.RightInstructionInput", index: 1, oracle: "RightInstructionInput" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.Product", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.Product", index: 2, oracle: "Product" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.ShouldBranch", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.ShouldBranch", index: 3, oracle: "ShouldBranch" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.PC", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.PC", index: 4, oracle: "PC" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.UnexpandedPC", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.UnexpandedPC", index: 5, oracle: "UnexpandedPC" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.Imm", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.Imm", index: 6, oracle: "Imm" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.RamAddress", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.RamAddress", index: 7, oracle: "RamAddress" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.Rs1Value", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.Rs1Value", index: 8, oracle: "Rs1Value" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.Rs2Value", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.Rs2Value", index: 9, oracle: "Rs2Value" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.RdWriteValue", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.RdWriteValue", index: 10, oracle: "RdWriteValue" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.RamReadValue", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.RamReadValue", index: 11, oracle: "RamReadValue" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.RamWriteValue", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.RamWriteValue", index: 12, oracle: "RamWriteValue" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.LeftLookupOperand", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.LeftLookupOperand", index: 13, oracle: "LeftLookupOperand" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.RightLookupOperand", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.RightLookupOperand", index: 14, oracle: "RightLookupOperand" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.NextUnexpandedPC", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.NextUnexpandedPC", index: 15, oracle: "NextUnexpandedPC" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.NextPC", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.NextPC", index: 16, oracle: "NextPC" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.NextIsVirtual", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.NextIsVirtual", index: 17, oracle: "NextIsVirtual" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.NextIsFirstInSequence", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.NextIsFirstInSequence", index: 18, oracle: "NextIsFirstInSequence" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.LookupOutput", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.LookupOutput", index: 19, oracle: "LookupOutput" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.ShouldJump", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.ShouldJump", index: 20, oracle: "ShouldJump" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.OpFlagAddOperands", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.OpFlagAddOperands", index: 21, oracle: "OpFlagAddOperands" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.OpFlagSubtractOperands", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.OpFlagSubtractOperands", index: 22, oracle: "OpFlagSubtractOperands" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.OpFlagMultiplyOperands", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.OpFlagMultiplyOperands", index: 23, oracle: "OpFlagMultiplyOperands" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.OpFlagLoad", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.OpFlagLoad", index: 24, oracle: "OpFlagLoad" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.OpFlagStore", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.OpFlagStore", index: 25, oracle: "OpFlagStore" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.OpFlagJump", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.OpFlagJump", index: 26, oracle: "OpFlagJump" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.OpFlagWriteLookupOutputToRD", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.OpFlagWriteLookupOutputToRD", index: 27, oracle: "OpFlagWriteLookupOutputToRD" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.OpFlagVirtualInstruction", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.OpFlagVirtualInstruction", index: 28, oracle: "OpFlagVirtualInstruction" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.OpFlagAssert", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.OpFlagAssert", index: 29, oracle: "OpFlagAssert" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.OpFlagDoNotUpdateUnexpandedPC", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.OpFlagDoNotUpdateUnexpandedPC", index: 30, oracle: "OpFlagDoNotUpdateUnexpandedPC" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.OpFlagAdvice", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.OpFlagAdvice", index: 31, oracle: "OpFlagAdvice" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.OpFlagIsCompressed", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.OpFlagIsCompressed", index: 32, oracle: "OpFlagIsCompressed" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.OpFlagIsFirstInSequence", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.OpFlagIsFirstInSequence", index: 33, oracle: "OpFlagIsFirstInSequence" }, + Stage1SumcheckEvalPlan { symbol: "stage1.outer_remaining.eval.OpFlagIsLastInSequence", source: "stage1.outer_remaining.sumcheck", name: "stage1.outer_remaining.eval.OpFlagIsLastInSequence", index: 34, oracle: "OpFlagIsLastInSequence" }, +]; + +pub const STAGE1_OPENING_CLAIMS: &[Stage1OpeningClaimPlan] = &[ + Stage1OpeningClaimPlan { symbol: "stage1.uniskip.opening", oracle: "UnivariateSkip", domain: "jolt.stage1_uniskip_domain", point_arity: 1, claim_kind: "virtual", point_source: "stage1.uniskip.instance", eval_source: "stage1.uniskip.eval" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.LeftInstructionInput" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RightInstructionInput" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.Product", oracle: "Product", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.Product" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.ShouldBranch", oracle: "ShouldBranch", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.ShouldBranch" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.PC", oracle: "PC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.PC" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.UnexpandedPC", oracle: "UnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.UnexpandedPC" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.Imm", oracle: "Imm", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.Imm" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RamAddress", oracle: "RamAddress", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RamAddress" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.Rs1Value" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.Rs2Value" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RdWriteValue", oracle: "RdWriteValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RdWriteValue" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RamReadValue", oracle: "RamReadValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RamReadValue" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RamWriteValue", oracle: "RamWriteValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RamWriteValue" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.LeftLookupOperand", oracle: "LeftLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.LeftLookupOperand" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RightLookupOperand", oracle: "RightLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RightLookupOperand" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.NextUnexpandedPC", oracle: "NextUnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.NextUnexpandedPC" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.NextPC", oracle: "NextPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.NextPC" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.NextIsVirtual", oracle: "NextIsVirtual", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.NextIsVirtual" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.NextIsFirstInSequence", oracle: "NextIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.NextIsFirstInSequence" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.LookupOutput" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.ShouldJump", oracle: "ShouldJump", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.ShouldJump" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagAddOperands", oracle: "OpFlagAddOperands", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagAddOperands" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagSubtractOperands", oracle: "OpFlagSubtractOperands", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagSubtractOperands" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagMultiplyOperands", oracle: "OpFlagMultiplyOperands", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagMultiplyOperands" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagLoad", oracle: "OpFlagLoad", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagLoad" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagStore", oracle: "OpFlagStore", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagStore" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagJump", oracle: "OpFlagJump", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagJump" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagWriteLookupOutputToRD", oracle: "OpFlagWriteLookupOutputToRD", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagWriteLookupOutputToRD" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagVirtualInstruction" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagAssert", oracle: "OpFlagAssert", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagAssert" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagDoNotUpdateUnexpandedPC", oracle: "OpFlagDoNotUpdateUnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagDoNotUpdateUnexpandedPC" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagAdvice", oracle: "OpFlagAdvice", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagAdvice" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagIsCompressed", oracle: "OpFlagIsCompressed", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagIsCompressed" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagIsFirstInSequence", oracle: "OpFlagIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagIsFirstInSequence" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagIsLastInSequence", oracle: "OpFlagIsLastInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagIsLastInSequence" }, +]; + +pub const STAGE1_OPENING_BATCHES: &[Stage1OpeningBatchPlan] = &[ + Stage1OpeningBatchPlan { symbol: "stage1.outer_remaining.openings", stage: "stage1", proof_slot: "stage1.virtual_openings", policy: "jolt_r1cs_input_order", count: 35, ordered_claims: "stage1.outer_remaining.opening.LeftInstructionInput|stage1.outer_remaining.opening.RightInstructionInput|stage1.outer_remaining.opening.Product|stage1.outer_remaining.opening.ShouldBranch|stage1.outer_remaining.opening.PC|stage1.outer_remaining.opening.UnexpandedPC|stage1.outer_remaining.opening.Imm|stage1.outer_remaining.opening.RamAddress|stage1.outer_remaining.opening.Rs1Value|stage1.outer_remaining.opening.Rs2Value|stage1.outer_remaining.opening.RdWriteValue|stage1.outer_remaining.opening.RamReadValue|stage1.outer_remaining.opening.RamWriteValue|stage1.outer_remaining.opening.LeftLookupOperand|stage1.outer_remaining.opening.RightLookupOperand|stage1.outer_remaining.opening.NextUnexpandedPC|stage1.outer_remaining.opening.NextPC|stage1.outer_remaining.opening.NextIsVirtual|stage1.outer_remaining.opening.NextIsFirstInSequence|stage1.outer_remaining.opening.LookupOutput|stage1.outer_remaining.opening.ShouldJump|stage1.outer_remaining.opening.OpFlagAddOperands|stage1.outer_remaining.opening.OpFlagSubtractOperands|stage1.outer_remaining.opening.OpFlagMultiplyOperands|stage1.outer_remaining.opening.OpFlagLoad|stage1.outer_remaining.opening.OpFlagStore|stage1.outer_remaining.opening.OpFlagJump|stage1.outer_remaining.opening.OpFlagWriteLookupOutputToRD|stage1.outer_remaining.opening.OpFlagVirtualInstruction|stage1.outer_remaining.opening.OpFlagAssert|stage1.outer_remaining.opening.OpFlagDoNotUpdateUnexpandedPC|stage1.outer_remaining.opening.OpFlagAdvice|stage1.outer_remaining.opening.OpFlagIsCompressed|stage1.outer_remaining.opening.OpFlagIsFirstInSequence|stage1.outer_remaining.opening.OpFlagIsLastInSequence", claim_operands: "stage1.outer_remaining.opening.LeftInstructionInput|stage1.outer_remaining.opening.RightInstructionInput|stage1.outer_remaining.opening.Product|stage1.outer_remaining.opening.ShouldBranch|stage1.outer_remaining.opening.PC|stage1.outer_remaining.opening.UnexpandedPC|stage1.outer_remaining.opening.Imm|stage1.outer_remaining.opening.RamAddress|stage1.outer_remaining.opening.Rs1Value|stage1.outer_remaining.opening.Rs2Value|stage1.outer_remaining.opening.RdWriteValue|stage1.outer_remaining.opening.RamReadValue|stage1.outer_remaining.opening.RamWriteValue|stage1.outer_remaining.opening.LeftLookupOperand|stage1.outer_remaining.opening.RightLookupOperand|stage1.outer_remaining.opening.NextUnexpandedPC|stage1.outer_remaining.opening.NextPC|stage1.outer_remaining.opening.NextIsVirtual|stage1.outer_remaining.opening.NextIsFirstInSequence|stage1.outer_remaining.opening.LookupOutput|stage1.outer_remaining.opening.ShouldJump|stage1.outer_remaining.opening.OpFlagAddOperands|stage1.outer_remaining.opening.OpFlagSubtractOperands|stage1.outer_remaining.opening.OpFlagMultiplyOperands|stage1.outer_remaining.opening.OpFlagLoad|stage1.outer_remaining.opening.OpFlagStore|stage1.outer_remaining.opening.OpFlagJump|stage1.outer_remaining.opening.OpFlagWriteLookupOutputToRD|stage1.outer_remaining.opening.OpFlagVirtualInstruction|stage1.outer_remaining.opening.OpFlagAssert|stage1.outer_remaining.opening.OpFlagDoNotUpdateUnexpandedPC|stage1.outer_remaining.opening.OpFlagAdvice|stage1.outer_remaining.opening.OpFlagIsCompressed|stage1.outer_remaining.opening.OpFlagIsFirstInSequence|stage1.outer_remaining.opening.OpFlagIsLastInSequence" }, +]; +pub const STAGE1_PROGRAM: Stage1VerifierProgramPlan = Stage1VerifierProgramPlan { + params: STAGE1_PARAMS, + transcript_squeezes: STAGE1_TRANSCRIPT_SQUEEZES, + claims: STAGE1_SUMCHECK_CLAIMS, + batches: STAGE1_SUMCHECK_BATCHES, + drivers: STAGE1_SUMCHECK_DRIVERS, + instance_results: STAGE1_SUMCHECK_INSTANCE_RESULTS, + evals: STAGE1_SUMCHECK_EVALS, + opening_claims: STAGE1_OPENING_CLAIMS, + opening_batches: STAGE1_OPENING_BATCHES, +}; + +pub fn verify_stage1_outer( + proof: &Stage1Proof, + transcript: &mut T, +) -> Result, VerifyStage1Error> +where + T: Transcript, +{ + verify_stage1_outer_with_program(&STAGE1_PROGRAM, proof, transcript) +} + +pub fn verify_stage1_outer_with_program( + program: &'static Stage1VerifierProgramPlan, + proof: &Stage1Proof, + transcript: &mut T, +) -> Result, VerifyStage1Error> +where + T: Transcript, +{ + if proof.sumchecks.len() != program.drivers.len() { + return Err(VerifyStage1Error::UnexpectedProofCount { + expected: program.drivers.len(), + got: proof.sumchecks.len(), + }); + } + let mut artifacts = Stage1ExecutionArtifacts::default(); + for squeeze in program.transcript_squeezes { + let values = transcript.challenge_vector(squeeze.count); + artifacts.challenge_vectors.push(Stage1ChallengeVector { + symbol: squeeze.symbol, + values, + }); + } + for (index, driver) in program.drivers.iter().enumerate() { + let proof = proof.sumchecks.get(index).ok_or(VerifyStage1Error::MissingProof { + driver: driver.symbol, + })?; + let output = verify_stage1_driver(program, driver, proof, &artifacts.sumchecks, transcript)?; + artifacts.sumchecks.push(output); + } + artifacts + .opening_batches + .extend(program.opening_batches.iter()); + Ok(artifacts) +} + +pub fn stage1_outer_verifier_program() -> &'static Stage1VerifierProgramPlan { + &STAGE1_PROGRAM +} + +fn verify_stage1_driver( + program: &'static Stage1VerifierProgramPlan, + driver: &'static Stage1SumcheckDriverPlan, + proof: &Stage1SumcheckOutput, + completed: &[Stage1SumcheckOutput], + transcript: &mut T, +) -> Result, VerifyStage1Error> +where + T: Transcript, +{ + if proof.driver != driver.symbol { + return Err(VerifyStage1Error::InvalidProof { + driver: driver.symbol, + reason: "driver symbol mismatch", + }); + } + let relation = driver.relation.unwrap_or(""); + match relation { + "jolt.stage1.outer.uniskip" => verify_outer_uniskip(program, driver, proof, transcript), + "jolt.stage1.outer.remaining" => { + verify_outer_remaining(program, driver, proof, completed, transcript) + } + relation => Err(VerifyStage1Error::UnsupportedRelation { relation }), + } +} + +fn verify_outer_uniskip( + program: &'static Stage1VerifierProgramPlan, + driver: &'static Stage1SumcheckDriverPlan, + proof: &Stage1SumcheckOutput, + transcript: &mut T, +) -> Result, VerifyStage1Error> +where + T: Transcript, +{ + let claim = SumcheckClaim::new(driver.num_rounds, driver.degree, Fr::from_u64(0)); + let round_proofs = proof + .proof + .round_polynomials + .iter() + .map(|poly| LabeledRoundPoly::new(poly, driver.round_label.as_bytes())) + .collect::>(); + let output = SumcheckVerifier::verify(&claim, &round_proofs, transcript) + .map_err(|error| VerifyStage1Error::Sumcheck { + driver: driver.symbol, + error, + })?; + let eval = output.value; + let point = output.point; + if !proof.point.is_empty() && proof.point != point { + return Err(VerifyStage1Error::InvalidProof { + driver: driver.symbol, + reason: "uniskip point mismatch", + }); + } + validate_eval_shape(program, driver, &proof.evals, Some(eval))?; + append_labeled_scalar(transcript, "opening_claim", &eval); + Ok(Stage1SumcheckOutput { + driver: driver.symbol, + point, + evals: driver_evals(program, driver.symbol, eval), + proof: proof.proof.clone(), + }) +} + +fn verify_outer_remaining( + program: &'static Stage1VerifierProgramPlan, + driver: &'static Stage1SumcheckDriverPlan, + proof: &Stage1SumcheckOutput, + completed: &[Stage1SumcheckOutput], + transcript: &mut T, +) -> Result, VerifyStage1Error> +where + T: Transcript, +{ + let input_claim = completed + .iter() + .find(|output| output.driver == "stage1.uniskip.sumcheck") + .and_then(|output| output.evals.first()) + .map(|eval| eval.value) + .ok_or(VerifyStage1Error::MissingDependency { + driver: driver.symbol, + dependency: "stage1.uniskip.eval", + })?; + append_labeled_scalar(transcript, driver.claim_label, &input_claim); + let batching_coeff = transcript.challenge(); + let claim = SumcheckClaim::new( + driver.num_rounds, + driver.degree, + input_claim * batching_coeff, + ); + let round_proofs = proof + .proof + .round_polynomials + .iter() + .map(|poly| CompressedLabeledRoundPoly::new(poly, driver.round_label.as_bytes())) + .collect::>(); + let output = SumcheckVerifier::verify(&claim, &round_proofs, transcript) + .map_err(|error| VerifyStage1Error::Sumcheck { + driver: driver.symbol, + error, + })?; + let point = output.point; + if !proof.point.is_empty() && proof.point != point { + return Err(VerifyStage1Error::InvalidProof { + driver: driver.symbol, + reason: "outer remaining point mismatch", + }); + } + validate_eval_shape(program, driver, &proof.evals, None)?; + append_opening_claims(transcript, &proof.evals); + Ok(Stage1SumcheckOutput { + driver: driver.symbol, + point, + evals: proof.evals.clone(), + proof: proof.proof.clone(), + }) +} + +fn driver_evals( + program: &'static Stage1VerifierProgramPlan, + driver: &'static str, + value: Fr, +) -> Vec> { + program + .evals + .iter() + .filter(|eval| eval.source == driver) + .map(|eval| Stage1NamedEval { + name: eval.name, + oracle: eval.oracle, + value, + }) + .collect() +} + +fn validate_eval_shape( + program: &'static Stage1VerifierProgramPlan, + driver: &'static Stage1SumcheckDriverPlan, + actual: &[Stage1NamedEval], + expected_value: Option, +) -> Result<(), VerifyStage1Error> { + let expected = program + .evals + .iter() + .filter(|eval| eval.source == driver.symbol) + .collect::>(); + if actual.len() != expected.len() { + return Err(VerifyStage1Error::InvalidProof { + driver: driver.symbol, + reason: "eval count mismatch", + }); + } + for (actual, expected) in actual.iter().zip(expected) { + if actual.name != expected.name { + return Err(VerifyStage1Error::InvalidProof { + driver: driver.symbol, + reason: "eval name mismatch", + }); + } + if actual.oracle != expected.oracle { + return Err(VerifyStage1Error::InvalidProof { + driver: driver.symbol, + reason: "eval oracle mismatch", + }); + } + if expected_value.is_some_and(|value| actual.value != value) { + return Err(VerifyStage1Error::InvalidProof { + driver: driver.symbol, + reason: "eval value mismatch", + }); + } + } + Ok(()) +} + +fn append_opening_claims(transcript: &mut T, evals: &[Stage1NamedEval]) +where + T: Transcript, +{ + for eval in evals { + append_labeled_scalar(transcript, "opening_claim", &eval.value); + } +} diff --git a/crates/jolt-verifier/src/stages/stage2.rs b/crates/jolt-verifier/src/stages/stage2.rs new file mode 100644 index 0000000000..568fcfb71a --- /dev/null +++ b/crates/jolt-verifier/src/stages/stage2.rs @@ -0,0 +1,1050 @@ +#![allow(dead_code)] + +use super::common::{append_labeled_scalar, batch_claims, eval_by_name, find_batch, find_plan, pow_field, require_operand_count, reverse_slice, single_operand}; +use jolt_field::{Field, Fr}; +use jolt_poly::lagrange::{lagrange_evals, lagrange_kernel_eval}; +use jolt_poly::{EqPolynomial, UnivariatePoly}; +use jolt_sumcheck::{CompressedLabeledRoundPoly, SumcheckClaim, SumcheckError, SumcheckVerifier}; +use jolt_transcript::{Blake2bTranscript, LabelWithCount, Transcript}; + +pub type DefaultStage2Transcript = Blake2bTranscript; + +pub type Stage2NamedEval = super::common::StageNamedEval; +pub type Stage2SumcheckOutput = super::common::StageSumcheckOutput; +pub type Stage2ChallengeVector = super::common::StageChallengeVector; +pub type Stage2ExecutionArtifacts = super::common::StageExecutionArtifacts; +pub type Stage2Proof = super::common::StageProof; +pub type Stage2OpeningInputValue = super::common::StageOpeningInputValue; +pub type Stage2VerifierProgramPlan = super::common::StageVerifierProgramPlanNoEqualities; + +pub use super::common::{ + FieldConstantPlan as Stage2FieldConstantPlan, FieldExprPlan as Stage2FieldExprPlan, + OpeningBatchPlan as Stage2OpeningBatchPlan, OpeningClaimPlan as Stage2OpeningClaimPlan, + OpeningInputPlan as Stage2OpeningInputPlan, PointConcatPlan as Stage2PointConcatPlan, + PointSlicePlan as Stage2PointSlicePlan, ProgramStepPlan as Stage2ProgramStepPlan, + StageParams as Stage2Params, SumcheckBatchPlan as Stage2SumcheckBatchPlan, + SumcheckEvalPlan as Stage2SumcheckEvalPlan, + SumcheckInstanceResultPlan as Stage2SumcheckInstanceResultPlan, + TranscriptSqueezePlan as Stage2TranscriptSqueezePlan, + SumcheckClaimPlan as Stage2SumcheckClaimPlan, + SumcheckDriverPlan as Stage2SumcheckDriverPlan, +}; + +#[derive(Clone, Copy, Debug)] +pub struct Stage2RamAccess { + pub remapped_address: Option, + pub read_value: u64, + pub write_value: u64, +} + +#[derive(Clone, Copy, Debug)] +pub struct Stage2RamOutputLayout { + pub io_start: usize, + pub io_end: usize, +} + +#[derive(Clone, Copy, Debug)] +pub struct Stage2RamData<'a> { + pub log_k: usize, + pub start_address: u64, + pub initial_ram: &'a [u64], + pub final_ram: &'a [u64], + pub accesses: &'a [Stage2RamAccess], + pub output_layout: Option, +} + +#[derive(Clone, Debug, Default)] +struct Stage2ValueStore(super::common::ValueStore); + +#[derive(Debug)] +pub enum VerifyStage2Error { + UnexpectedProofCount { expected: usize, got: usize }, + MissingProof { driver: &'static str }, + MissingBatch { driver: &'static str, batch: &'static str }, + MissingClaim { batch: &'static str, claim: &'static str }, + MissingValue { symbol: &'static str }, + InvalidInputLength { input: &'static str, expected: usize, actual: usize }, + InvalidProof { driver: &'static str, reason: &'static str }, + UnsupportedFieldExpr { symbol: &'static str, formula: &'static str }, + UnsupportedRelation { relation: &'static str }, + MissingRam { relation: &'static str }, + Sumcheck { driver: &'static str, error: SumcheckError }, +} + +super::common::impl_runtime_plan_error_conversion!(VerifyStage2Error); + +pub const STAGE2_PARAMS: Stage2Params = Stage2Params { + field: "bn254_fr", + pcs: "dory", + transcript: "blake2b_transcript", +}; +pub const STAGE2_PROGRAM_STEPS: &[Stage2ProgramStepPlan] = &[ + Stage2ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage2.product_virtual.tau_high" }, + Stage2ProgramStepPlan { kind: "sumcheck_driver", symbol: "stage2.product_virtual.uniskip.sumcheck" }, + Stage2ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage2.ram_read_write.gamma" }, + Stage2ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage2.instruction_lookup.gamma" }, + Stage2ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage2.ram_output.r_address" }, + Stage2ProgramStepPlan { kind: "sumcheck_driver", symbol: "stage2.sumcheck" }, +]; + +pub const STAGE2_TRANSCRIPT_SQUEEZES: &[Stage2TranscriptSqueezePlan] = &[ + Stage2TranscriptSqueezePlan { symbol: "stage2.product_virtual.tau_high", label: "product_virtual_tau_high", kind: "challenge_scalar", count: 1 }, + Stage2TranscriptSqueezePlan { symbol: "stage2.ram_read_write.gamma", label: "ram_read_write_gamma", kind: "challenge_scalar", count: 1 }, + Stage2TranscriptSqueezePlan { symbol: "stage2.instruction_lookup.gamma", label: "instruction_lookup_gamma", kind: "challenge_scalar", count: 1 }, + Stage2TranscriptSqueezePlan { symbol: "stage2.ram_output.r_address", label: "ram_output_r_address", kind: "challenge_vector", count: 16 }, +]; + +pub const STAGE2_OPENING_INPUTS: &[Stage2OpeningInputPlan] = &[ + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.Product", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.Product", oracle: "Product", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.ShouldBranch", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.ShouldBranch", oracle: "ShouldBranch", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.ShouldJump", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.ShouldJump", oracle: "ShouldJump", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.RamReadValue", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RamReadValue", oracle: "RamReadValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.RamWriteValue", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RamWriteValue", oracle: "RamWriteValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.LookupOutput", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.LeftLookupOperand", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.LeftLookupOperand", oracle: "LeftLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.RightLookupOperand", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RightLookupOperand", oracle: "RightLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.LeftInstructionInput", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.RightInstructionInput", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.RamAddress", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RamAddress", oracle: "RamAddress", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, +]; + +pub const STAGE2_FIELD_CONSTANTS: &[Stage2FieldConstantPlan] = &[ + Stage2FieldConstantPlan { symbol: "stage2.ram_output.zero", field: "bn254_fr", value: 0 }, +]; + +pub const STAGE2_FIELD_EXPRS: &[Stage2FieldExprPlan] = &[ + Stage2FieldExprPlan { symbol: "stage2.product_virtual.uniskip.weight.Product", kind: "op", formula: "poly.lagrange_basis_eval:-1:3:0", operands: "stage2.product_virtual.tau_high" }, + Stage2FieldExprPlan { symbol: "stage2.product_virtual.uniskip.weight.ShouldBranch", kind: "op", formula: "poly.lagrange_basis_eval:-1:3:1", operands: "stage2.product_virtual.tau_high" }, + Stage2FieldExprPlan { symbol: "stage2.product_virtual.uniskip.weight.ShouldJump", kind: "op", formula: "poly.lagrange_basis_eval:-1:3:2", operands: "stage2.product_virtual.tau_high" }, + Stage2FieldExprPlan { symbol: "stage2.product_virtual.uniskip.term.Product", kind: "op", formula: "field.mul", operands: "stage2.product_virtual.uniskip.weight.Product|stage2.input.stage1.Product" }, + Stage2FieldExprPlan { symbol: "stage2.product_virtual.uniskip.term.ShouldBranch", kind: "op", formula: "field.mul", operands: "stage2.product_virtual.uniskip.weight.ShouldBranch|stage2.input.stage1.ShouldBranch" }, + Stage2FieldExprPlan { symbol: "stage2.product_virtual.uniskip.term.ShouldJump", kind: "op", formula: "field.mul", operands: "stage2.product_virtual.uniskip.weight.ShouldJump|stage2.input.stage1.ShouldJump" }, + Stage2FieldExprPlan { symbol: "stage2.product_virtual.uniskip.partial.ProductShouldBranch", kind: "op", formula: "field.add", operands: "stage2.product_virtual.uniskip.term.Product|stage2.product_virtual.uniskip.term.ShouldBranch" }, + Stage2FieldExprPlan { symbol: "stage2.product_virtual.uniskip.claim_expr", kind: "op", formula: "field.add", operands: "stage2.product_virtual.uniskip.partial.ProductShouldBranch|stage2.product_virtual.uniskip.term.ShouldJump" }, + Stage2FieldExprPlan { symbol: "stage2.ram_read_write.term.RamWriteValue", kind: "op", formula: "field.mul", operands: "stage2.ram_read_write.gamma|stage2.input.stage1.RamWriteValue" }, + Stage2FieldExprPlan { symbol: "stage2.ram_read_write.claim_expr", kind: "op", formula: "field.add", operands: "stage2.input.stage1.RamReadValue|stage2.ram_read_write.term.RamWriteValue" }, + Stage2FieldExprPlan { symbol: "stage2.instruction_lookup.gamma2", kind: "op", formula: "field.mul", operands: "stage2.instruction_lookup.gamma|stage2.instruction_lookup.gamma" }, + Stage2FieldExprPlan { symbol: "stage2.instruction_lookup.gamma3", kind: "op", formula: "field.mul", operands: "stage2.instruction_lookup.gamma2|stage2.instruction_lookup.gamma" }, + Stage2FieldExprPlan { symbol: "stage2.instruction_lookup.gamma4", kind: "op", formula: "field.mul", operands: "stage2.instruction_lookup.gamma2|stage2.instruction_lookup.gamma2" }, + Stage2FieldExprPlan { symbol: "stage2.instruction_lookup.term.LeftLookupOperand", kind: "op", formula: "field.mul", operands: "stage2.instruction_lookup.gamma|stage2.input.stage1.LeftLookupOperand" }, + Stage2FieldExprPlan { symbol: "stage2.instruction_lookup.term.RightLookupOperand", kind: "op", formula: "field.mul", operands: "stage2.instruction_lookup.gamma2|stage2.input.stage1.RightLookupOperand" }, + Stage2FieldExprPlan { symbol: "stage2.instruction_lookup.term.LeftInstructionInput", kind: "op", formula: "field.mul", operands: "stage2.instruction_lookup.gamma3|stage2.input.stage1.LeftInstructionInput" }, + Stage2FieldExprPlan { symbol: "stage2.instruction_lookup.term.RightInstructionInput", kind: "op", formula: "field.mul", operands: "stage2.instruction_lookup.gamma4|stage2.input.stage1.RightInstructionInput" }, + Stage2FieldExprPlan { symbol: "stage2.instruction_lookup.partial.LookupOutputLeftOperand", kind: "op", formula: "field.add", operands: "stage2.input.stage1.LookupOutput|stage2.instruction_lookup.term.LeftLookupOperand" }, + Stage2FieldExprPlan { symbol: "stage2.instruction_lookup.partial.RightOperand", kind: "op", formula: "field.add", operands: "stage2.instruction_lookup.partial.LookupOutputLeftOperand|stage2.instruction_lookup.term.RightLookupOperand" }, + Stage2FieldExprPlan { symbol: "stage2.instruction_lookup.partial.LeftInstructionInput", kind: "op", formula: "field.add", operands: "stage2.instruction_lookup.partial.RightOperand|stage2.instruction_lookup.term.LeftInstructionInput" }, + Stage2FieldExprPlan { symbol: "stage2.instruction_lookup.claim_reduction.claim_expr", kind: "op", formula: "field.add", operands: "stage2.instruction_lookup.partial.LeftInstructionInput|stage2.instruction_lookup.term.RightInstructionInput" }, +]; +pub const STAGE2_SUMCHECK_CLAIMS: &[Stage2SumcheckClaimPlan] = &[ + Stage2SumcheckClaimPlan { symbol: "stage2.product_virtual.uniskip.input", stage: "stage2", domain: "jolt.stage2_uniskip_domain", num_rounds: 1, degree: 6, claim: "stage2.product_virtual.weighted_stage1_outputs", kernel: None, relation: Some("jolt.stage2.product_virtual.uniskip"), claim_value: "stage2.product_virtual.uniskip.claim_expr", input_openings: "stage2.input.stage1.Product|stage2.input.stage1.ShouldBranch|stage2.input.stage1.ShouldJump" }, + Stage2SumcheckClaimPlan { symbol: "stage2.ram_read_write.input", stage: "stage2", domain: "jolt.stage2_ram_rw_domain", num_rounds: 32, degree: 3, claim: "stage2.ram_read_write.weighted_values", kernel: None, relation: Some("jolt.stage2.ram.read_write"), claim_value: "stage2.ram_read_write.claim_expr", input_openings: "stage2.input.stage1.RamReadValue|stage2.input.stage1.RamWriteValue" }, + Stage2SumcheckClaimPlan { symbol: "stage2.product_virtual.remainder.input", stage: "stage2", domain: "jolt.trace_domain", num_rounds: 16, degree: 3, claim: "stage2.product_virtual.uniskip.opening", kernel: None, relation: Some("jolt.stage2.product_virtual.remainder"), claim_value: "stage2.product_virtual.uniskip.eval.UnivariateSkip", input_openings: "stage2.product_virtual.uniskip.opening.UnivariateSkip" }, + Stage2SumcheckClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.input", stage: "stage2", domain: "jolt.trace_domain", num_rounds: 16, degree: 2, claim: "stage2.instruction_lookup.weighted_operands", kernel: None, relation: Some("jolt.stage2.instruction_lookup.claim_reduction"), claim_value: "stage2.instruction_lookup.claim_reduction.claim_expr", input_openings: "stage2.input.stage1.LookupOutput|stage2.input.stage1.LeftLookupOperand|stage2.input.stage1.RightLookupOperand|stage2.input.stage1.LeftInstructionInput|stage2.input.stage1.RightInstructionInput" }, + Stage2SumcheckClaimPlan { symbol: "stage2.ram_raf.input", stage: "stage2", domain: "jolt.ram_address_domain", num_rounds: 16, degree: 2, claim: "stage2.ram_raf.ram_address", kernel: None, relation: Some("jolt.stage2.ram.raf_evaluation"), claim_value: "stage2.input.stage1.RamAddress", input_openings: "stage2.input.stage1.RamAddress" }, + Stage2SumcheckClaimPlan { symbol: "stage2.ram_output.input", stage: "stage2", domain: "jolt.ram_address_domain", num_rounds: 16, degree: 3, claim: "zero", kernel: None, relation: Some("jolt.stage2.ram.output_check"), claim_value: "stage2.ram_output.zero", input_openings: "" }, +]; +pub const STAGE2_SUMCHECK_BATCH_0_ROUND_SCHEDULE: &[usize] = &[ + 1, +]; + +pub const STAGE2_SUMCHECK_BATCH_1_ROUND_SCHEDULE: &[usize] = &[ + 16, + 16, +]; + +pub const STAGE2_SUMCHECK_BATCHES: &[Stage2SumcheckBatchPlan] = &[ + Stage2SumcheckBatchPlan { symbol: "stage2.product_virtual.uniskip.batch", stage: "stage2", proof_slot: "stage2.product_virtual.uni_skip_first_round", policy: "single_instance", count: 1, ordered_claims: "stage2.product_virtual.uniskip.input", claim_operands: "stage2.product_virtual.uniskip.input", claim_label: "uniskip_claim", round_label: "uniskip_poly", round_schedule: STAGE2_SUMCHECK_BATCH_0_ROUND_SCHEDULE }, + Stage2SumcheckBatchPlan { symbol: "stage2.batch", stage: "stage2", proof_slot: "stage2.sumcheck", policy: "jolt_core_stage2_aligned", count: 5, ordered_claims: "stage2.ram_read_write.input|stage2.product_virtual.remainder.input|stage2.instruction_lookup.claim_reduction.input|stage2.ram_raf.input|stage2.ram_output.input", claim_operands: "stage2.ram_read_write.input|stage2.product_virtual.remainder.input|stage2.instruction_lookup.claim_reduction.input|stage2.ram_raf.input|stage2.ram_output.input", claim_label: "sumcheck_claim", round_label: "sumcheck_poly", round_schedule: STAGE2_SUMCHECK_BATCH_1_ROUND_SCHEDULE }, +]; +pub const STAGE2_SUMCHECK_DRIVER_0_ROUND_SCHEDULE: &[usize] = &[ + 1, +]; + +pub const STAGE2_SUMCHECK_DRIVER_1_ROUND_SCHEDULE: &[usize] = &[ + 16, + 16, +]; + +pub const STAGE2_SUMCHECK_DRIVERS: &[Stage2SumcheckDriverPlan] = &[ + Stage2SumcheckDriverPlan { symbol: "stage2.product_virtual.uniskip.sumcheck", stage: "stage2", proof_slot: "stage2.product_virtual.uni_skip_first_round", kernel: None, relation: Some("jolt.stage2.product_virtual.uniskip"), batch: "stage2.product_virtual.uniskip.batch", policy: "univariate_skip", round_schedule: STAGE2_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "uniskip_claim", round_label: "uniskip_poly", num_rounds: 1, degree: 6 }, + Stage2SumcheckDriverPlan { symbol: "stage2.sumcheck", stage: "stage2", proof_slot: "stage2.sumcheck", kernel: None, relation: Some("jolt.stage2.batched"), batch: "stage2.batch", policy: "jolt_core_stage2_aligned", round_schedule: STAGE2_SUMCHECK_DRIVER_1_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 32, degree: 3 }, +]; +pub const STAGE2_SUMCHECK_INSTANCE_RESULTS: &[Stage2SumcheckInstanceResultPlan] = &[ + Stage2SumcheckInstanceResultPlan { symbol: "stage2.product_virtual.uniskip.instance", source: "stage2.product_virtual.uniskip.sumcheck", claim: "stage2.product_virtual.uniskip.input", relation: "jolt.stage2.product_virtual.uniskip", index: 0, point_arity: 1, num_rounds: 1, round_offset: 0, point_order: "as_is", degree: 6 }, + Stage2SumcheckInstanceResultPlan { symbol: "stage2.ram_read_write.instance", source: "stage2.sumcheck", claim: "stage2.ram_read_write.input", relation: "jolt.stage2.ram.read_write", index: 0, point_arity: 32, num_rounds: 32, round_offset: 0, point_order: "reverse", degree: 3 }, + Stage2SumcheckInstanceResultPlan { symbol: "stage2.product_virtual.remainder.instance", source: "stage2.sumcheck", claim: "stage2.product_virtual.remainder.input", relation: "jolt.stage2.product_virtual.remainder", index: 1, point_arity: 16, num_rounds: 16, round_offset: 16, point_order: "reverse", degree: 3 }, + Stage2SumcheckInstanceResultPlan { symbol: "stage2.instruction_lookup.claim_reduction.instance", source: "stage2.sumcheck", claim: "stage2.instruction_lookup.claim_reduction.input", relation: "jolt.stage2.instruction_lookup.claim_reduction", index: 2, point_arity: 16, num_rounds: 16, round_offset: 16, point_order: "reverse", degree: 2 }, + Stage2SumcheckInstanceResultPlan { symbol: "stage2.ram_raf.instance", source: "stage2.sumcheck", claim: "stage2.ram_raf.input", relation: "jolt.stage2.ram.raf_evaluation", index: 3, point_arity: 16, num_rounds: 16, round_offset: 16, point_order: "reverse", degree: 2 }, + Stage2SumcheckInstanceResultPlan { symbol: "stage2.ram_output.instance", source: "stage2.sumcheck", claim: "stage2.ram_output.input", relation: "jolt.stage2.ram.output_check", index: 4, point_arity: 16, num_rounds: 16, round_offset: 16, point_order: "reverse", degree: 3 }, +]; + +pub const STAGE2_SUMCHECK_EVALS: &[Stage2SumcheckEvalPlan] = &[ + Stage2SumcheckEvalPlan { symbol: "stage2.product_virtual.uniskip.eval.UnivariateSkip", source: "stage2.product_virtual.uniskip.sumcheck", name: "stage2.product_virtual.uniskip.eval.UnivariateSkip", index: 0, oracle: "UnivariateSkip" }, + Stage2SumcheckEvalPlan { symbol: "stage2.ram_read_write.eval.RamVal", source: "stage2.sumcheck", name: "stage2.ram_read_write.eval.RamVal", index: 0, oracle: "RamVal" }, + Stage2SumcheckEvalPlan { symbol: "stage2.ram_read_write.eval.RamRa", source: "stage2.sumcheck", name: "stage2.ram_read_write.eval.RamRa", index: 1, oracle: "RamRa" }, + Stage2SumcheckEvalPlan { symbol: "stage2.ram_read_write.eval.RamInc", source: "stage2.sumcheck", name: "stage2.ram_read_write.eval.RamInc", index: 2, oracle: "RamInc" }, + Stage2SumcheckEvalPlan { symbol: "stage2.product_virtual.remainder.eval.LeftInstructionInput", source: "stage2.sumcheck", name: "stage2.product_virtual.remainder.eval.LeftInstructionInput", index: 0, oracle: "LeftInstructionInput" }, + Stage2SumcheckEvalPlan { symbol: "stage2.product_virtual.remainder.eval.RightInstructionInput", source: "stage2.sumcheck", name: "stage2.product_virtual.remainder.eval.RightInstructionInput", index: 1, oracle: "RightInstructionInput" }, + Stage2SumcheckEvalPlan { symbol: "stage2.product_virtual.remainder.eval.OpFlagJump", source: "stage2.sumcheck", name: "stage2.product_virtual.remainder.eval.OpFlagJump", index: 2, oracle: "OpFlagJump" }, + Stage2SumcheckEvalPlan { symbol: "stage2.product_virtual.remainder.eval.OpFlagWriteLookupOutputToRD", source: "stage2.sumcheck", name: "stage2.product_virtual.remainder.eval.OpFlagWriteLookupOutputToRD", index: 3, oracle: "OpFlagWriteLookupOutputToRD" }, + Stage2SumcheckEvalPlan { symbol: "stage2.product_virtual.remainder.eval.LookupOutput", source: "stage2.sumcheck", name: "stage2.product_virtual.remainder.eval.LookupOutput", index: 4, oracle: "LookupOutput" }, + Stage2SumcheckEvalPlan { symbol: "stage2.product_virtual.remainder.eval.InstructionFlagBranch", source: "stage2.sumcheck", name: "stage2.product_virtual.remainder.eval.InstructionFlagBranch", index: 5, oracle: "InstructionFlagBranch" }, + Stage2SumcheckEvalPlan { symbol: "stage2.product_virtual.remainder.eval.NextIsNoop", source: "stage2.sumcheck", name: "stage2.product_virtual.remainder.eval.NextIsNoop", index: 6, oracle: "NextIsNoop" }, + Stage2SumcheckEvalPlan { symbol: "stage2.product_virtual.remainder.eval.OpFlagVirtualInstruction", source: "stage2.sumcheck", name: "stage2.product_virtual.remainder.eval.OpFlagVirtualInstruction", index: 7, oracle: "OpFlagVirtualInstruction" }, + Stage2SumcheckEvalPlan { symbol: "stage2.instruction_lookup.claim_reduction.eval.LookupOutput", source: "stage2.sumcheck", name: "stage2.instruction_lookup.claim_reduction.eval.LookupOutput", index: 0, oracle: "LookupOutput" }, + Stage2SumcheckEvalPlan { symbol: "stage2.instruction_lookup.claim_reduction.eval.LeftLookupOperand", source: "stage2.sumcheck", name: "stage2.instruction_lookup.claim_reduction.eval.LeftLookupOperand", index: 1, oracle: "LeftLookupOperand" }, + Stage2SumcheckEvalPlan { symbol: "stage2.instruction_lookup.claim_reduction.eval.RightLookupOperand", source: "stage2.sumcheck", name: "stage2.instruction_lookup.claim_reduction.eval.RightLookupOperand", index: 2, oracle: "RightLookupOperand" }, + Stage2SumcheckEvalPlan { symbol: "stage2.instruction_lookup.claim_reduction.eval.LeftInstructionInput", source: "stage2.sumcheck", name: "stage2.instruction_lookup.claim_reduction.eval.LeftInstructionInput", index: 3, oracle: "LeftInstructionInput" }, + Stage2SumcheckEvalPlan { symbol: "stage2.instruction_lookup.claim_reduction.eval.RightInstructionInput", source: "stage2.sumcheck", name: "stage2.instruction_lookup.claim_reduction.eval.RightInstructionInput", index: 4, oracle: "RightInstructionInput" }, + Stage2SumcheckEvalPlan { symbol: "stage2.ram_raf.eval.RamRa", source: "stage2.sumcheck", name: "stage2.ram_raf.eval.RamRa", index: 0, oracle: "RamRa" }, + Stage2SumcheckEvalPlan { symbol: "stage2.ram_output.eval.RamValFinal", source: "stage2.sumcheck", name: "stage2.ram_output.eval.RamValFinal", index: 0, oracle: "RamValFinal" }, +]; + +pub const STAGE2_POINT_SLICES: &[Stage2PointSlicePlan] = &[ + Stage2PointSlicePlan { symbol: "stage2.ram_read_write.point.RamInc", source: "stage2.ram_read_write.instance", offset: 16, length: 16, input: "stage2.ram_read_write.instance" }, +]; + +pub const STAGE2_POINT_CONCATS: &[Stage2PointConcatPlan] = &[ + Stage2PointConcatPlan { symbol: "stage2.ram_raf.point.RamRa", layout: "address_then_cycle", arity: 32, inputs: "stage2.ram_raf.instance|stage2.input.stage1.RamAddress" }, +]; +pub const STAGE2_OPENING_CLAIMS: &[Stage2OpeningClaimPlan] = &[ + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.uniskip.opening.UnivariateSkip", oracle: "UnivariateSkip", domain: "jolt.stage2_uniskip_domain", point_arity: 1, claim_kind: "virtual", point_source: "stage2.product_virtual.uniskip.instance", eval_source: "stage2.product_virtual.uniskip.eval.UnivariateSkip" }, + Stage2OpeningClaimPlan { symbol: "stage2.ram_read_write.opening.RamVal", oracle: "RamVal", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage2.ram_read_write.instance", eval_source: "stage2.ram_read_write.eval.RamVal" }, + Stage2OpeningClaimPlan { symbol: "stage2.ram_read_write.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage2.ram_read_write.instance", eval_source: "stage2.ram_read_write.eval.RamRa" }, + Stage2OpeningClaimPlan { symbol: "stage2.ram_read_write.opening.RamInc", oracle: "RamInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed", point_source: "stage2.ram_read_write.point.RamInc", eval_source: "stage2.ram_read_write.eval.RamInc" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.LeftInstructionInput" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.RightInstructionInput" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.OpFlagJump", oracle: "OpFlagJump", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.OpFlagJump" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.OpFlagWriteLookupOutputToRD", oracle: "OpFlagWriteLookupOutputToRD", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.OpFlagWriteLookupOutputToRD" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.LookupOutput" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.InstructionFlagBranch", oracle: "InstructionFlagBranch", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.InstructionFlagBranch" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.NextIsNoop", oracle: "NextIsNoop", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.NextIsNoop" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.OpFlagVirtualInstruction" }, + Stage2OpeningClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.instruction_lookup.claim_reduction.instance", eval_source: "stage2.instruction_lookup.claim_reduction.eval.LookupOutput" }, + Stage2OpeningClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.opening.LeftLookupOperand", oracle: "LeftLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.instruction_lookup.claim_reduction.instance", eval_source: "stage2.instruction_lookup.claim_reduction.eval.LeftLookupOperand" }, + Stage2OpeningClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.opening.RightLookupOperand", oracle: "RightLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.instruction_lookup.claim_reduction.instance", eval_source: "stage2.instruction_lookup.claim_reduction.eval.RightLookupOperand" }, + Stage2OpeningClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.instruction_lookup.claim_reduction.instance", eval_source: "stage2.instruction_lookup.claim_reduction.eval.LeftInstructionInput" }, + Stage2OpeningClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.instruction_lookup.claim_reduction.instance", eval_source: "stage2.instruction_lookup.claim_reduction.eval.RightInstructionInput" }, + Stage2OpeningClaimPlan { symbol: "stage2.ram_raf.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage2.ram_raf.point.RamRa", eval_source: "stage2.ram_raf.eval.RamRa" }, + Stage2OpeningClaimPlan { symbol: "stage2.ram_output.opening.RamValFinal", oracle: "RamValFinal", domain: "jolt.ram_address_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.ram_output.instance", eval_source: "stage2.ram_output.eval.RamValFinal" }, +]; + +pub const STAGE2_OPENING_BATCHES: &[Stage2OpeningBatchPlan] = &[ + Stage2OpeningBatchPlan { symbol: "stage2.openings", stage: "stage2", proof_slot: "stage2.openings", policy: "jolt_stage2_output_order", count: 18, ordered_claims: "stage2.ram_read_write.opening.RamVal|stage2.ram_read_write.opening.RamRa|stage2.ram_read_write.opening.RamInc|stage2.product_virtual.remainder.opening.LeftInstructionInput|stage2.product_virtual.remainder.opening.RightInstructionInput|stage2.product_virtual.remainder.opening.OpFlagJump|stage2.product_virtual.remainder.opening.OpFlagWriteLookupOutputToRD|stage2.product_virtual.remainder.opening.LookupOutput|stage2.product_virtual.remainder.opening.InstructionFlagBranch|stage2.product_virtual.remainder.opening.NextIsNoop|stage2.product_virtual.remainder.opening.OpFlagVirtualInstruction|stage2.instruction_lookup.claim_reduction.opening.LookupOutput|stage2.instruction_lookup.claim_reduction.opening.LeftLookupOperand|stage2.instruction_lookup.claim_reduction.opening.RightLookupOperand|stage2.instruction_lookup.claim_reduction.opening.LeftInstructionInput|stage2.instruction_lookup.claim_reduction.opening.RightInstructionInput|stage2.ram_raf.opening.RamRa|stage2.ram_output.opening.RamValFinal", claim_operands: "stage2.ram_read_write.opening.RamVal|stage2.ram_read_write.opening.RamRa|stage2.ram_read_write.opening.RamInc|stage2.product_virtual.remainder.opening.LeftInstructionInput|stage2.product_virtual.remainder.opening.RightInstructionInput|stage2.product_virtual.remainder.opening.OpFlagJump|stage2.product_virtual.remainder.opening.OpFlagWriteLookupOutputToRD|stage2.product_virtual.remainder.opening.LookupOutput|stage2.product_virtual.remainder.opening.InstructionFlagBranch|stage2.product_virtual.remainder.opening.NextIsNoop|stage2.product_virtual.remainder.opening.OpFlagVirtualInstruction|stage2.instruction_lookup.claim_reduction.opening.LookupOutput|stage2.instruction_lookup.claim_reduction.opening.LeftLookupOperand|stage2.instruction_lookup.claim_reduction.opening.RightLookupOperand|stage2.instruction_lookup.claim_reduction.opening.LeftInstructionInput|stage2.instruction_lookup.claim_reduction.opening.RightInstructionInput|stage2.ram_raf.opening.RamRa|stage2.ram_output.opening.RamValFinal" }, +]; +pub const STAGE2_PROGRAM: Stage2VerifierProgramPlan = Stage2VerifierProgramPlan { + params: STAGE2_PARAMS, + steps: STAGE2_PROGRAM_STEPS, + transcript_squeezes: STAGE2_TRANSCRIPT_SQUEEZES, + opening_inputs: STAGE2_OPENING_INPUTS, + field_constants: STAGE2_FIELD_CONSTANTS, + field_exprs: STAGE2_FIELD_EXPRS, + claims: STAGE2_SUMCHECK_CLAIMS, + batches: STAGE2_SUMCHECK_BATCHES, + drivers: STAGE2_SUMCHECK_DRIVERS, + instance_results: STAGE2_SUMCHECK_INSTANCE_RESULTS, + evals: STAGE2_SUMCHECK_EVALS, + point_slices: STAGE2_POINT_SLICES, + point_concats: STAGE2_POINT_CONCATS, + opening_claims: STAGE2_OPENING_CLAIMS, + opening_batches: STAGE2_OPENING_BATCHES, +}; + +const PRODUCT_VIRTUAL_UNISKIP_DOMAIN_START: i64 = -1; +const PRODUCT_VIRTUAL_UNISKIP_DOMAIN_SIZE: usize = 3; + +pub fn verify_stage2( + proof: &Stage2Proof, + opening_inputs: &[Stage2OpeningInputValue], + ram: Option<&Stage2RamData<'_>>, + transcript: &mut T, +) -> Result, VerifyStage2Error> +where + T: Transcript, +{ + verify_stage2_with_program(&STAGE2_PROGRAM, proof, opening_inputs, ram, transcript) +} + +pub fn verify_stage2_with_program( + program: &'static Stage2VerifierProgramPlan, + proof: &Stage2Proof, + opening_inputs: &[Stage2OpeningInputValue], + ram: Option<&Stage2RamData<'_>>, + transcript: &mut T, +) -> Result, VerifyStage2Error> +where + T: Transcript, +{ + if proof.sumchecks.len() != program.drivers.len() { + return Err(VerifyStage2Error::UnexpectedProofCount { + expected: program.drivers.len(), + got: proof.sumchecks.len(), + }); + } + let mut store = Stage2ValueStore::with_opening_inputs(program, opening_inputs)?; + store.seed_constants(program); + let mut artifacts = Stage2ExecutionArtifacts::default(); + if program.steps.is_empty() { + for squeeze in program.transcript_squeezes { + verify_stage2_squeeze(program, squeeze, &mut store, transcript, &mut artifacts)?; + } + for driver in program.drivers { + verify_stage2_driver(program, driver, proof, ram, &mut store, transcript, &mut artifacts)?; + } + } else { + for step in program.steps { + match step.kind { + "transcript_squeeze" => { + let squeeze = find_plan(program.transcript_squeezes, step.symbol).ok_or(VerifyStage2Error::MissingValue { + symbol: step.symbol, + })?; + verify_stage2_squeeze(program, squeeze, &mut store, transcript, &mut artifacts)?; + } + "sumcheck_driver" => { + let driver = find_plan(program.drivers, step.symbol).ok_or(VerifyStage2Error::MissingProof { + driver: step.symbol, + })?; + verify_stage2_driver(program, driver, proof, ram, &mut store, transcript, &mut artifacts)?; + } + _ => { + return Err(VerifyStage2Error::InvalidProof { + driver: step.symbol, + reason: "unsupported stage2 program step", + }); + } + } + } + } + artifacts + .opening_batches + .extend(program.opening_batches.iter()); + Ok(artifacts) +} + +pub fn stage2_verifier_program() -> &'static Stage2VerifierProgramPlan { + &STAGE2_PROGRAM +} + +fn verify_stage2_squeeze( + program: &'static Stage2VerifierProgramPlan, + squeeze: &'static Stage2TranscriptSqueezePlan, + store: &mut Stage2ValueStore, + transcript: &mut T, + artifacts: &mut Stage2ExecutionArtifacts, +) -> Result<(), VerifyStage2Error> +where + T: Transcript, +{ + let values = transcript.challenge_vector(squeeze.count); + store.observe_challenge_vector(program, squeeze, &values)?; + artifacts.challenge_vectors.push(Stage2ChallengeVector { + symbol: squeeze.symbol, + values, + }); + Ok(()) +} + +fn verify_stage2_driver( + program: &'static Stage2VerifierProgramPlan, + driver: &'static Stage2SumcheckDriverPlan, + proof: &Stage2Proof, + ram: Option<&Stage2RamData<'_>>, + store: &mut Stage2ValueStore, + transcript: &mut T, + artifacts: &mut Stage2ExecutionArtifacts, +) -> Result<(), VerifyStage2Error> +where + T: Transcript, +{ + let proof = proof + .sumchecks + .get(artifacts.sumchecks.len()) + .ok_or(VerifyStage2Error::MissingProof { + driver: driver.symbol, + })?; + let relation = driver.relation.unwrap_or(""); + let output = match relation { + "jolt.stage2.product_virtual.uniskip" => { + verify_product_virtual_uniskip(program, driver, proof, store, transcript)? + } + "jolt.stage2.batched" => verify_batched_stage2(program, driver, proof, ram, store, transcript)?, + relation => return Err(VerifyStage2Error::UnsupportedRelation { relation }), + }; + artifacts.sumchecks.push(output); + Ok(()) +} + +fn verify_product_virtual_uniskip( + program: &'static Stage2VerifierProgramPlan, + driver: &'static Stage2SumcheckDriverPlan, + proof: &Stage2SumcheckOutput, + store: &mut Stage2ValueStore, + transcript: &mut T, +) -> Result, VerifyStage2Error> +where + T: Transcript, +{ + validate_driver_symbol(driver, proof)?; + let [poly] = proof.proof.round_polynomials.as_slice() else { + return Err(VerifyStage2Error::InvalidProof { + driver: driver.symbol, + reason: "unexpected product uniskip round count", + }); + }; + if polynomial_degree(poly) > driver.degree { + return Err(VerifyStage2Error::InvalidProof { + driver: driver.symbol, + reason: "product uniskip polynomial exceeds degree bound", + }); + } + let batch = find_batch(program.batches, driver.symbol, driver.batch)?; + let claim = batch_claims(program.claims, batch)? + .into_iter() + .next() + .ok_or(VerifyStage2Error::MissingClaim { + batch: batch.symbol, + claim: "stage2.product_virtual.uniskip.input", + })?; + let input_claim = store.claim_value(program, claim)?; + if !product_uniskip_sum_matches(poly, input_claim) { + return Err(VerifyStage2Error::InvalidProof { + driver: driver.symbol, + reason: "product uniskip input claim mismatch", + }); + } + append_univariate_poly(transcript, driver.round_label, poly); + let r0 = transcript.challenge(); + if !proof.point.is_empty() && proof.point != [r0] { + return Err(VerifyStage2Error::InvalidProof { + driver: driver.symbol, + reason: "product uniskip point mismatch", + }); + } + let eval = poly.evaluate(r0); + append_labeled_scalar(transcript, "opening_claim", &eval); + let output = Stage2SumcheckOutput { + driver: driver.symbol, + point: vec![r0], + evals: driver_evals(program, driver.symbol, eval), + proof: proof.proof.clone(), + }; + verify_named_evals(driver.symbol, &output.evals, &proof.evals)?; + store.observe_sumcheck_output(program, &output)?; + Ok(output) +} + +fn verify_batched_stage2( + program: &'static Stage2VerifierProgramPlan, + driver: &'static Stage2SumcheckDriverPlan, + proof: &Stage2SumcheckOutput, + ram: Option<&Stage2RamData<'_>>, + store: &mut Stage2ValueStore, + transcript: &mut T, +) -> Result, VerifyStage2Error> +where + T: Transcript, +{ + validate_driver_symbol(driver, proof)?; + let batch = find_batch(program.batches, driver.symbol, driver.batch)?; + let claims = batch_claims(program.claims, batch)?; + let input_claims = store.batch_claim_values(program, batch)?; + for claim in &input_claims { + append_labeled_scalar(transcript, batch.claim_label, claim); + } + let batching_coeffs = transcript.challenge_vector(claims.len()); + let claimed_sum = input_claims + .iter() + .zip(claims.iter()) + .zip(&batching_coeffs) + .map(|((claim, plan), coefficient)| { + claim.mul_pow_2(driver.num_rounds - plan.num_rounds) * *coefficient + }) + .sum::(); + let claim = SumcheckClaim::new(driver.num_rounds, driver.degree, claimed_sum); + let round_proofs = proof + .proof + .round_polynomials + .iter() + .map(|poly| CompressedLabeledRoundPoly::new(poly, driver.round_label.as_bytes())) + .collect::>(); + let output = SumcheckVerifier::verify(&claim, &round_proofs, transcript) + .map_err(|error| VerifyStage2Error::Sumcheck { + driver: driver.symbol, + error, + })?; + if !proof.point.is_empty() && proof.point != output.point { + return Err(VerifyStage2Error::InvalidProof { + driver: driver.symbol, + reason: "batched point mismatch", + }); + } + let expected = + expected_batched_output_claim(program, driver, &*store, &proof.evals, &output.point, &batching_coeffs, ram)?; + if output.value != expected { + return Err(VerifyStage2Error::InvalidProof { + driver: driver.symbol, + reason: "batched output claim mismatch", + }); + } + let verified = Stage2SumcheckOutput { + driver: driver.symbol, + point: output.point, + evals: proof.evals.clone(), + proof: proof.proof.clone(), + }; + store.observe_sumcheck_output(program, &verified)?; + super::common::append_opening_claims( + program.opening_inputs, + program.opening_claims, + program.opening_batches, + &mut store.0, + transcript, + &verified.evals, + |batch, claim| VerifyStage2Error::MissingClaim { batch, claim }, + |symbol| VerifyStage2Error::MissingValue { symbol }, + )?; + Ok(verified) +} + +impl Stage2ValueStore { + fn with_opening_inputs( + program: &'static Stage2VerifierProgramPlan, + inputs: &[Stage2OpeningInputValue], + ) -> Result { + Ok(Self(super::common::ValueStore::with_opening_inputs( + inputs, + program.opening_inputs, + )?)) + } + + fn seed_constants(&mut self, program: &'static Stage2VerifierProgramPlan) { + self.0.seed_constants(program.field_constants); + } + + fn observe_challenge_vector( + &mut self, + program: &'static Stage2VerifierProgramPlan, + plan: &'static Stage2TranscriptSqueezePlan, + values: &[F], + ) -> Result<(), VerifyStage2Error> { + self.0.observe_challenge_vector(plan, values, |input, expected, actual| { + VerifyStage2Error::InvalidInputLength { input, expected, actual } + })?; + self.evaluate_available_points(program)?; + self.evaluate_available_field_exprs(program)?; + Ok(()) + } + + fn observe_sumcheck_output( + &mut self, + program: &'static Stage2VerifierProgramPlan, + output: &Stage2SumcheckOutput, + ) -> Result<(), VerifyStage2Error> { + self.0.observe_sumcheck_output( + program.instance_results, + program.evals, + output, + |instance, mut point| { + match instance.point_order { + "as_is" => {} + "reverse" => point.reverse(), + _ => { + return Err(VerifyStage2Error::InvalidProof { + driver: output.driver, + reason: "unsupported point order", + }); + } + } + Ok(point) + }, + |input, expected, actual| VerifyStage2Error::InvalidInputLength { + input, + expected, + actual, + }, + |symbol| VerifyStage2Error::MissingValue { symbol }, + )?; + self.evaluate_available_points(program)?; + self.evaluate_available_field_exprs(program)?; + Ok(()) + } + + fn claim_value( + &mut self, + program: &'static Stage2VerifierProgramPlan, + claim: &Stage2SumcheckClaimPlan, + ) -> Result { + self.evaluate_available_field_exprs(program)?; + self.scalar(claim.claim_value) + } + + fn batch_claim_values( + &mut self, + program: &'static Stage2VerifierProgramPlan, + batch: &Stage2SumcheckBatchPlan, + ) -> Result, VerifyStage2Error> { + super::common::symbol_list(batch.claim_operands) + .map(|symbol| { + let claim = find_plan(program.claims, symbol).ok_or(VerifyStage2Error::MissingClaim { + batch: batch.symbol, + claim: symbol, + })?; + self.claim_value(program, claim) + }) + .collect() + } + + fn evaluate_available_points( + &mut self, + program: &'static Stage2VerifierProgramPlan, + ) -> Result<(), VerifyStage2Error> { + self.0.evaluate_available_points( + program.point_slices, + program.point_concats, + |input, expected, actual| VerifyStage2Error::InvalidInputLength { + input, + expected, + actual, + }, + ) + } + + fn evaluate_available_field_exprs( + &mut self, + program: &'static Stage2VerifierProgramPlan, + ) -> Result<(), VerifyStage2Error> { + self.0 + .evaluate_available_field_exprs(program.field_exprs, evaluate_stage2_field_expr) + } + + fn scalar(&self, symbol: &'static str) -> Result { + self.0 + .scalar_or(symbol, |symbol| VerifyStage2Error::MissingValue { symbol }) + } + + fn point(&self, symbol: &'static str) -> Result<&[F], VerifyStage2Error> { + self.0 + .point_or(symbol, |symbol| VerifyStage2Error::MissingValue { symbol }) + } + + fn try_point(&self, symbol: &str) -> Option<&[F]> { + self.0.try_point(symbol) + } +} + +fn evaluate_stage2_field_expr( + expr: &Stage2FieldExprPlan, + operands: &[F], +) -> Result { + match expr.formula { + "opening_eval" => Ok(single_operand(expr.symbol, operands)?), + "jolt_stage2_product_virtual_uniskip_input" => { + require_operand_count(expr.symbol, 4, operands.len())?; + let weights = lagrange_evals( + PRODUCT_VIRTUAL_UNISKIP_DOMAIN_START, + PRODUCT_VIRTUAL_UNISKIP_DOMAIN_SIZE, + operands[0], + ); + Ok(weights[0] * operands[1] + weights[1] * operands[2] + weights[2] * operands[3]) + } + "jolt_stage2_ram_read_write_input" => { + require_operand_count(expr.symbol, 3, operands.len())?; + Ok(operands[1] + operands[0] * operands[2]) + } + "jolt_stage2_instruction_lookup_input" => { + require_operand_count(expr.symbol, 6, operands.len())?; + let gamma = operands[0]; + let gamma2 = gamma.square(); + let gamma3 = gamma2 * gamma; + let gamma4 = gamma2.square(); + Ok(operands[1] + + gamma * operands[2] + + gamma2 * operands[3] + + gamma3 * operands[4] + + gamma4 * operands[5]) + } + "field.add" => { + require_operand_count(expr.symbol, 2, operands.len())?; + Ok(operands[0] + operands[1]) + } + "field.sub" => { + require_operand_count(expr.symbol, 2, operands.len())?; + Ok(operands[0] - operands[1]) + } + "field.mul" => { + require_operand_count(expr.symbol, 2, operands.len())?; + Ok(operands[0] * operands[1]) + } + "field.neg" => { + require_operand_count(expr.symbol, 1, operands.len())?; + Ok(-operands[0]) + } + formula => { + if let Some(exponent) = formula.strip_prefix("field.pow:") { + require_operand_count(expr.symbol, 1, operands.len())?; + let exponent = exponent.parse::().map_err(|_| { + VerifyStage2Error::UnsupportedFieldExpr { + symbol: expr.symbol, + formula, + } + })?; + return Ok(pow_field(operands[0], exponent)); + } + if let Some(spec) = formula.strip_prefix("poly.lagrange_basis_eval:") { + require_operand_count(expr.symbol, 1, operands.len())?; + let parts = spec.split(':').collect::>(); + if parts.len() != 3 { + return Err(VerifyStage2Error::UnsupportedFieldExpr { + symbol: expr.symbol, + formula, + }); + } + let domain_start = parts[0].parse::().map_err(|_| { + VerifyStage2Error::UnsupportedFieldExpr { + symbol: expr.symbol, + formula, + } + })?; + let domain_size = parts[1].parse::().map_err(|_| { + VerifyStage2Error::UnsupportedFieldExpr { + symbol: expr.symbol, + formula, + } + })?; + let index = parts[2].parse::().map_err(|_| { + VerifyStage2Error::UnsupportedFieldExpr { + symbol: expr.symbol, + formula, + } + })?; + let weights = lagrange_evals(domain_start, domain_size, operands[0]); + return weights + .get(index) + .copied() + .ok_or(VerifyStage2Error::InvalidInputLength { + input: expr.symbol, + expected: index + 1, + actual: weights.len(), + }); + } + Err(VerifyStage2Error::UnsupportedFieldExpr { + symbol: expr.symbol, + formula, + }) + } + } +} + +fn expected_batched_output_claim( + program: &'static Stage2VerifierProgramPlan, + driver: &'static Stage2SumcheckDriverPlan, + store: &Stage2ValueStore, + evals: &[Stage2NamedEval], + point: &[Fr], + batching_coeffs: &[Fr], + ram: Option<&Stage2RamData<'_>>, +) -> Result { + let batch = find_batch(program.batches, driver.symbol, driver.batch)?; + let claims = batch_claims(program.claims, batch)?; + let mut expected = Fr::from_u64(0); + for (claim, coefficient) in claims.iter().zip(batching_coeffs) { + let instance = program + .instance_results + .iter() + .find(|instance| instance.claim == claim.symbol && instance.source == driver.symbol) + .ok_or(VerifyStage2Error::MissingClaim { + batch: batch.symbol, + claim: claim.symbol, + })?; + let local_point = point + .get(instance.round_offset..instance.round_offset + instance.num_rounds) + .ok_or(VerifyStage2Error::InvalidInputLength { + input: instance.symbol, + expected: instance.round_offset + instance.num_rounds, + actual: point.len(), + })?; + let value = match instance.relation { + "jolt.stage2.ram.read_write" => expected_ram_read_write(store, evals, local_point)?, + "jolt.stage2.product_virtual.remainder" => { + expected_product_remainder(store, evals, local_point)? + } + "jolt.stage2.instruction_lookup.claim_reduction" => { + expected_instruction_lookup(store, evals, local_point)? + } + "jolt.stage2.ram.raf_evaluation" => expected_ram_raf(evals, local_point, ram)?, + "jolt.stage2.ram.output_check" => expected_ram_output(store, evals, local_point, ram)?, + relation => return Err(VerifyStage2Error::UnsupportedRelation { relation }), + }; + expected += *coefficient * value; + } + Ok(expected) +} + +fn expected_ram_read_write( + store: &Stage2ValueStore, + evals: &[Stage2NamedEval], + local_point: &[Fr], +) -> Result { + let r_cycle_stage1 = store.point("stage2.input.stage1.RamReadValue")?; + let log_t = r_cycle_stage1.len(); + let r_cycle = reverse_slice(&local_point[..log_t]); + let eq_eval = EqPolynomial::::mle(r_cycle_stage1, &r_cycle); + let gamma = store.scalar("stage2.ram_read_write.gamma")?; + let val = eval_by_name(evals, "stage2.ram_read_write.eval.RamVal")?; + let ra = eval_by_name(evals, "stage2.ram_read_write.eval.RamRa")?; + let inc = eval_by_name(evals, "stage2.ram_read_write.eval.RamInc")?; + Ok(eq_eval * ra * (val + gamma * (val + inc))) +} + +fn expected_product_remainder( + store: &Stage2ValueStore, + evals: &[Stage2NamedEval], + local_point: &[Fr], +) -> Result { + let tau_low = store.point("stage2.input.stage1.Product")?; + let tau_high = store.scalar("stage2.product_virtual.tau_high")?; + let r0 = *store + .point("stage2.product_virtual.uniskip.sumcheck")? + .first() + .ok_or(VerifyStage2Error::MissingValue { + symbol: "stage2.product_virtual.uniskip.sumcheck", + })?; + let r_tail = reverse_slice(local_point); + let low = EqPolynomial::::mle(tau_low, &r_tail); + let high = lagrange_kernel_eval( + PRODUCT_VIRTUAL_UNISKIP_DOMAIN_START, + PRODUCT_VIRTUAL_UNISKIP_DOMAIN_SIZE, + tau_high, + r0, + ); + let weights = lagrange_evals( + PRODUCT_VIRTUAL_UNISKIP_DOMAIN_START, + PRODUCT_VIRTUAL_UNISKIP_DOMAIN_SIZE, + r0, + ); + let left = weights[0] + * eval_by_name(evals, "stage2.product_virtual.remainder.eval.LeftInstructionInput")? + + weights[1] * eval_by_name(evals, "stage2.product_virtual.remainder.eval.LookupOutput")? + + weights[2] * eval_by_name(evals, "stage2.product_virtual.remainder.eval.OpFlagJump")?; + let right = weights[0] + * eval_by_name(evals, "stage2.product_virtual.remainder.eval.RightInstructionInput")? + + weights[1] + * eval_by_name(evals, "stage2.product_virtual.remainder.eval.InstructionFlagBranch")? + + weights[2] + * (Fr::from_u64(1) + - eval_by_name(evals, "stage2.product_virtual.remainder.eval.NextIsNoop")?); + Ok(high * low * left * right) +} + +fn expected_instruction_lookup( + store: &Stage2ValueStore, + evals: &[Stage2NamedEval], + local_point: &[Fr], +) -> Result { + let opening_point = reverse_slice(local_point); + let r_spartan = store.point("stage2.input.stage1.LookupOutput")?; + let eq_eval = EqPolynomial::::mle(&opening_point, r_spartan); + let gamma = store.scalar("stage2.instruction_lookup.gamma")?; + let gamma2 = gamma.square(); + let gamma3 = gamma2 * gamma; + let gamma4 = gamma2.square(); + let weighted = eval_by_name( + evals, + "stage2.instruction_lookup.claim_reduction.eval.LookupOutput", + )? + gamma + * eval_by_name( + evals, + "stage2.instruction_lookup.claim_reduction.eval.LeftLookupOperand", + )? + + gamma2 + * eval_by_name( + evals, + "stage2.instruction_lookup.claim_reduction.eval.RightLookupOperand", + )? + + gamma3 + * eval_by_name( + evals, + "stage2.instruction_lookup.claim_reduction.eval.LeftInstructionInput", + )? + + gamma4 + * eval_by_name( + evals, + "stage2.instruction_lookup.claim_reduction.eval.RightInstructionInput", + )?; + Ok(eq_eval * weighted) +} + +fn expected_ram_raf( + evals: &[Stage2NamedEval], + local_point: &[Fr], + ram: Option<&Stage2RamData<'_>>, +) -> Result { + let ram = ram.ok_or(VerifyStage2Error::MissingRam { + relation: "jolt.stage2.ram.raf_evaluation", + })?; + let address = reverse_slice(local_point); + let unmap = unmap_eval(ram.log_k, ram.start_address, &address); + Ok(unmap * eval_by_name(evals, "stage2.ram_raf.eval.RamRa")?) +} + +fn expected_ram_output( + store: &Stage2ValueStore, + evals: &[Stage2NamedEval], + local_point: &[Fr], + ram: Option<&Stage2RamData<'_>>, +) -> Result { + let ram = ram.ok_or(VerifyStage2Error::MissingRam { + relation: "jolt.stage2.ram.output_check", + })?; + let layout = ram.output_layout.ok_or(VerifyStage2Error::MissingRam { + relation: "jolt.stage2.ram.output_check.layout", + })?; + let r_address = store.point("stage2.ram_output.r_address")?; + let opening_point = reverse_slice(local_point); + let eq_eval = EqPolynomial::::mle(r_address, &opening_point); + let io_mask = range_mask_eval(layout.io_start, layout.io_end, &opening_point); + let val_io = sparse_final_ram_eval( + ram.final_ram, + layout.io_start, + layout.io_end, + &opening_point, + ); + let val_final = eval_by_name(evals, "stage2.ram_output.eval.RamValFinal")?; + Ok(eq_eval * io_mask * (val_final - val_io)) +} + +fn driver_evals( + program: &'static Stage2VerifierProgramPlan, + driver: &'static str, + value: Fr, +) -> Vec> { + program + .evals + .iter() + .filter(|eval| eval.source == driver) + .map(|eval| Stage2NamedEval { + name: eval.name, + oracle: eval.oracle, + value, + }) + .collect() +} + +fn verify_named_evals( + driver: &'static str, + expected: &[Stage2NamedEval], + actual: &[Stage2NamedEval], +) -> Result<(), VerifyStage2Error> { + if expected.len() != actual.len() { + return Err(VerifyStage2Error::InvalidProof { + driver, + reason: "eval count mismatch", + }); + } + for (expected, actual) in expected.iter().zip(actual) { + if expected.name != actual.name || expected.oracle != actual.oracle || expected.value != actual.value { + return Err(VerifyStage2Error::InvalidProof { + driver, + reason: "eval mismatch", + }); + } + } + Ok(()) +} + +fn validate_driver_symbol( + driver: &'static Stage2SumcheckDriverPlan, + proof: &Stage2SumcheckOutput, +) -> Result<(), VerifyStage2Error> { + if proof.driver == driver.symbol { + Ok(()) + } else { + Err(VerifyStage2Error::InvalidProof { + driver: driver.symbol, + reason: "driver symbol mismatch", + }) + } +} + +fn append_univariate_poly(transcript: &mut T, label: &'static str, poly: &UnivariatePoly) +where + T: Transcript, +{ + transcript.append(&LabelWithCount( + label.as_bytes(), + poly.coefficients().len() as u64, + )); + for coefficient in poly.coefficients() { + transcript.append(coefficient); + } +} + +fn product_uniskip_sum_matches(poly: &UnivariatePoly, claim: Fr) -> bool { + (0..PRODUCT_VIRTUAL_UNISKIP_DOMAIN_SIZE) + .map(|index| { + poly.evaluate(Fr::from_i64( + PRODUCT_VIRTUAL_UNISKIP_DOMAIN_START + index as i64, + )) + }) + .sum::() + == claim +} + +fn polynomial_degree(poly: &UnivariatePoly) -> usize { + poly.coefficients() + .iter() + .rposition(|coefficient| *coefficient != Fr::from_u64(0)) + .unwrap_or(0) +} + +fn unmap_eval(log_k: usize, start_address: u64, point: &[Fr]) -> Fr { + point + .iter() + .enumerate() + .fold(Fr::from_u64(start_address), |acc, (index, value)| { + acc + value.mul_pow_2(log_k - 1 - index).mul_u64(8) + }) +} + +fn range_mask_eval(start: usize, end: usize, point: &[Fr]) -> Fr { + eq_prefix_sum(end, point) - eq_prefix_sum(start, point) +} + +fn sparse_final_ram_eval(values: &[u64], start: usize, end: usize, point: &[Fr]) -> Fr { + values[start..end] + .iter() + .enumerate() + .filter(|(_, value)| **value != 0) + .map(|(offset, value)| Fr::from_u64(*value) * eq_eval_at_index(start + offset, point)) + .sum() +} + +fn eq_prefix_sum(end: usize, point: &[Fr]) -> Fr { + let domain_len = 1usize << point.len(); + if end >= domain_len { + return Fr::from_u64(1); + } + let mut sum = Fr::from_u64(0); + let mut prefix = Fr::from_u64(1); + for (bit, r) in point.iter().enumerate() { + let mask = 1usize << (point.len() - 1 - bit); + if end & mask == 0 { + prefix *= Fr::from_u64(1) - *r; + } else { + sum += prefix * (Fr::from_u64(1) - *r); + prefix *= *r; + } + } + sum +} + +fn eq_eval_at_index(index: usize, point: &[Fr]) -> Fr { + point.iter().enumerate().fold(Fr::from_u64(1), |acc, (bit, r)| { + let mask = 1usize << (point.len() - 1 - bit); + if index & mask == 0 { + acc * (Fr::from_u64(1) - *r) + } else { + acc * *r + } + }) +} diff --git a/crates/jolt-verifier/src/stages/stage3.rs b/crates/jolt-verifier/src/stages/stage3.rs new file mode 100644 index 0000000000..d22851483a --- /dev/null +++ b/crates/jolt-verifier/src/stages/stage3.rs @@ -0,0 +1,526 @@ +#![allow(dead_code)] + +use super::common::{batch_claims, eval_by_name, find_batch, find_plan, reverse_slice}; +use jolt_field::{Field, Fr}; +use jolt_poly::{EqPlusOnePolynomial, EqPolynomial}; +use jolt_sumcheck::SumcheckError; +use jolt_transcript::{Blake2bTranscript, Transcript}; + +pub type DefaultStage3Transcript = Blake2bTranscript; + +pub type Stage3NamedEval = super::common::StageNamedEval; +pub type Stage3SumcheckOutput = super::common::StageSumcheckOutput; +pub type Stage3ChallengeVector = super::common::StageChallengeVector; +pub type Stage3ExecutionArtifacts = super::common::StageExecutionArtifacts; +pub type Stage3Proof = super::common::StageProof; +pub type Stage3OpeningInputValue = super::common::StageOpeningInputValue; +pub type Stage3VerifierProgramPlan = super::common::StageVerifierProgramPlan; + +pub use super::common::{ + FieldConstantPlan as Stage3FieldConstantPlan, FieldExprPlan as Stage3FieldExprPlan, + OpeningBatchPlan as Stage3OpeningBatchPlan, + OpeningClaimEqualityPlan as Stage3OpeningClaimEqualityPlan, + OpeningClaimPlan as Stage3OpeningClaimPlan, OpeningInputPlan as Stage3OpeningInputPlan, + PointConcatPlan as Stage3PointConcatPlan, PointSlicePlan as Stage3PointSlicePlan, + ProgramStepPlan as Stage3ProgramStepPlan, StageParams as Stage3Params, + SumcheckBatchPlan as Stage3SumcheckBatchPlan, SumcheckEvalPlan as Stage3SumcheckEvalPlan, + SumcheckInstanceResultPlan as Stage3SumcheckInstanceResultPlan, + TranscriptSqueezePlan as Stage3TranscriptSqueezePlan, + SumcheckClaimPlan as Stage3SumcheckClaimPlan, + SumcheckDriverPlan as Stage3SumcheckDriverPlan, +}; + +#[derive(Debug)] +pub enum VerifyStage3Error { + UnexpectedProofCount { expected: usize, got: usize }, + MissingProof { driver: &'static str }, + MissingBatch { driver: &'static str, batch: &'static str }, + MissingClaim { batch: &'static str, claim: &'static str }, + MissingValue { symbol: &'static str }, + InvalidInputLength { input: &'static str, expected: usize, actual: usize }, + InvalidProof { driver: &'static str, reason: &'static str }, + UnsupportedFieldExpr { symbol: &'static str, formula: &'static str }, + UnsupportedRelation { relation: &'static str }, + Sumcheck { driver: &'static str, error: SumcheckError }, +} + +super::common::impl_runtime_plan_error_conversion!(VerifyStage3Error); + +pub const STAGE3_PARAMS: Stage3Params = Stage3Params { + field: "bn254_fr", + pcs: "dory", + transcript: "blake2b_transcript", +}; +pub const STAGE3_PROGRAM_STEPS: &[Stage3ProgramStepPlan] = &[ + Stage3ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage3.spartan_shift.gamma" }, + Stage3ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage3.instruction_input.gamma" }, + Stage3ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage3.registers.gamma" }, + Stage3ProgramStepPlan { kind: "sumcheck_driver", symbol: "stage3.sumcheck" }, +]; + +pub const STAGE3_TRANSCRIPT_SQUEEZES: &[Stage3TranscriptSqueezePlan] = &[ + Stage3TranscriptSqueezePlan { symbol: "stage3.spartan_shift.gamma", label: "spartan_shift_gamma", kind: "challenge_scalar", count: 1 }, + Stage3TranscriptSqueezePlan { symbol: "stage3.instruction_input.gamma", label: "instruction_input_gamma", kind: "challenge_scalar", count: 1 }, + Stage3TranscriptSqueezePlan { symbol: "stage3.registers.gamma", label: "registers_gamma", kind: "challenge_scalar", count: 1 }, +]; + +pub const STAGE3_OPENING_INPUTS: &[Stage3OpeningInputPlan] = &[ + Stage3OpeningInputPlan { symbol: "stage3.input.stage1.NextUnexpandedPC", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.NextUnexpandedPC", oracle: "NextUnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage1.NextPC", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.NextPC", oracle: "NextPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage1.NextIsVirtual", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.NextIsVirtual", oracle: "NextIsVirtual", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage1.NextIsFirstInSequence", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.NextIsFirstInSequence", oracle: "NextIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage2.product_virtual.NextIsNoop", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.NextIsNoop", oracle: "NextIsNoop", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage2.product_virtual.LeftInstructionInput", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage2.product_virtual.RightInstructionInput", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage2.instruction_lookup.LeftInstructionInput", source_stage: "stage2", source_claim: "stage2.instruction_lookup.claim_reduction.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage2.instruction_lookup.RightInstructionInput", source_stage: "stage2", source_claim: "stage2.instruction_lookup.claim_reduction.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage1.RdWriteValue", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RdWriteValue", oracle: "RdWriteValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage1.Rs1Value", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage1.Rs2Value", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, +]; + +pub const STAGE3_FIELD_CONSTANTS: &[Stage3FieldConstantPlan] = &[ + Stage3FieldConstantPlan { symbol: "stage3.field.one", field: "bn254_fr", value: 1 }, +]; + +pub const STAGE3_FIELD_EXPRS: &[Stage3FieldExprPlan] = &[ + Stage3FieldExprPlan { symbol: "stage3.spartan_shift.gamma2", kind: "op", formula: "field.pow:2", operands: "stage3.spartan_shift.gamma" }, + Stage3FieldExprPlan { symbol: "stage3.spartan_shift.gamma3", kind: "op", formula: "field.mul", operands: "stage3.spartan_shift.gamma2|stage3.spartan_shift.gamma" }, + Stage3FieldExprPlan { symbol: "stage3.spartan_shift.gamma4", kind: "op", formula: "field.mul", operands: "stage3.spartan_shift.gamma2|stage3.spartan_shift.gamma2" }, + Stage3FieldExprPlan { symbol: "stage3.spartan_shift.term.NextPC", kind: "op", formula: "field.mul", operands: "stage3.spartan_shift.gamma|stage3.input.stage1.NextPC" }, + Stage3FieldExprPlan { symbol: "stage3.spartan_shift.term.NextIsVirtual", kind: "op", formula: "field.mul", operands: "stage3.spartan_shift.gamma2|stage3.input.stage1.NextIsVirtual" }, + Stage3FieldExprPlan { symbol: "stage3.spartan_shift.term.NextIsFirstInSequence", kind: "op", formula: "field.mul", operands: "stage3.spartan_shift.gamma3|stage3.input.stage1.NextIsFirstInSequence" }, + Stage3FieldExprPlan { symbol: "stage3.spartan_shift.one_minus.NextIsNoop", kind: "op", formula: "field.sub", operands: "stage3.field.one|stage3.input.stage2.product_virtual.NextIsNoop" }, + Stage3FieldExprPlan { symbol: "stage3.spartan_shift.term.NextIsNoop", kind: "op", formula: "field.mul", operands: "stage3.spartan_shift.gamma4|stage3.spartan_shift.one_minus.NextIsNoop" }, + Stage3FieldExprPlan { symbol: "stage3.spartan_shift.partial.NextUnexpandedPCNextPC", kind: "op", formula: "field.add", operands: "stage3.input.stage1.NextUnexpandedPC|stage3.spartan_shift.term.NextPC" }, + Stage3FieldExprPlan { symbol: "stage3.spartan_shift.partial.NextIsVirtual", kind: "op", formula: "field.add", operands: "stage3.spartan_shift.partial.NextUnexpandedPCNextPC|stage3.spartan_shift.term.NextIsVirtual" }, + Stage3FieldExprPlan { symbol: "stage3.spartan_shift.partial.NextIsFirstInSequence", kind: "op", formula: "field.add", operands: "stage3.spartan_shift.partial.NextIsVirtual|stage3.spartan_shift.term.NextIsFirstInSequence" }, + Stage3FieldExprPlan { symbol: "stage3.spartan_shift.claim_expr", kind: "op", formula: "field.add", operands: "stage3.spartan_shift.partial.NextIsFirstInSequence|stage3.spartan_shift.term.NextIsNoop" }, + Stage3FieldExprPlan { symbol: "stage3.instruction_input.term.LeftInstructionInput", kind: "op", formula: "field.mul", operands: "stage3.instruction_input.gamma|stage3.input.stage2.product_virtual.LeftInstructionInput" }, + Stage3FieldExprPlan { symbol: "stage3.instruction_input.claim_expr", kind: "op", formula: "field.add", operands: "stage3.input.stage2.product_virtual.RightInstructionInput|stage3.instruction_input.term.LeftInstructionInput" }, + Stage3FieldExprPlan { symbol: "stage3.registers.gamma2", kind: "op", formula: "field.pow:2", operands: "stage3.registers.gamma" }, + Stage3FieldExprPlan { symbol: "stage3.registers.term.Rs1Value", kind: "op", formula: "field.mul", operands: "stage3.registers.gamma|stage3.input.stage1.Rs1Value" }, + Stage3FieldExprPlan { symbol: "stage3.registers.term.Rs2Value", kind: "op", formula: "field.mul", operands: "stage3.registers.gamma2|stage3.input.stage1.Rs2Value" }, + Stage3FieldExprPlan { symbol: "stage3.registers.partial.RdWriteValueRs1Value", kind: "op", formula: "field.add", operands: "stage3.input.stage1.RdWriteValue|stage3.registers.term.Rs1Value" }, + Stage3FieldExprPlan { symbol: "stage3.registers.claim_expr", kind: "op", formula: "field.add", operands: "stage3.registers.partial.RdWriteValueRs1Value|stage3.registers.term.Rs2Value" }, +]; +pub const STAGE3_SUMCHECK_CLAIMS: &[Stage3SumcheckClaimPlan] = &[ + Stage3SumcheckClaimPlan { symbol: "stage3.spartan_shift.input", stage: "stage3", domain: "jolt.trace_domain", num_rounds: 16, degree: 2, claim: "stage3.spartan_shift.weighted_next_values", kernel: None, relation: Some("jolt.stage3.spartan_shift"), claim_value: "stage3.spartan_shift.claim_expr", input_openings: "stage3.input.stage1.NextUnexpandedPC|stage3.input.stage1.NextPC|stage3.input.stage1.NextIsVirtual|stage3.input.stage1.NextIsFirstInSequence|stage3.input.stage2.product_virtual.NextIsNoop" }, + Stage3SumcheckClaimPlan { symbol: "stage3.instruction_input.input", stage: "stage3", domain: "jolt.trace_domain", num_rounds: 16, degree: 3, claim: "stage3.instruction_input.weighted_inputs", kernel: None, relation: Some("jolt.stage3.instruction_input"), claim_value: "stage3.instruction_input.claim_expr", input_openings: "stage3.input.stage2.product_virtual.RightInstructionInput|stage3.input.stage2.product_virtual.LeftInstructionInput" }, + Stage3SumcheckClaimPlan { symbol: "stage3.registers_claim_reduction.input", stage: "stage3", domain: "jolt.trace_domain", num_rounds: 16, degree: 2, claim: "stage3.registers.weighted_register_values", kernel: None, relation: Some("jolt.stage3.registers_claim_reduction"), claim_value: "stage3.registers.claim_expr", input_openings: "stage3.input.stage1.RdWriteValue|stage3.input.stage1.Rs1Value|stage3.input.stage1.Rs2Value" }, +]; +pub const STAGE3_SUMCHECK_BATCH_0_ROUND_SCHEDULE: &[usize] = &[ + 16, +]; + +pub const STAGE3_SUMCHECK_BATCHES: &[Stage3SumcheckBatchPlan] = &[ + Stage3SumcheckBatchPlan { symbol: "stage3.batch", stage: "stage3", proof_slot: "stage3.sumcheck", policy: "jolt_core_stage3_aligned", count: 3, ordered_claims: "stage3.spartan_shift.input|stage3.instruction_input.input|stage3.registers_claim_reduction.input", claim_operands: "stage3.spartan_shift.input|stage3.instruction_input.input|stage3.registers_claim_reduction.input", claim_label: "sumcheck_claim", round_label: "sumcheck_poly", round_schedule: STAGE3_SUMCHECK_BATCH_0_ROUND_SCHEDULE }, +]; +pub const STAGE3_SUMCHECK_DRIVER_0_ROUND_SCHEDULE: &[usize] = &[ + 16, +]; + +pub const STAGE3_SUMCHECK_DRIVERS: &[Stage3SumcheckDriverPlan] = &[ + Stage3SumcheckDriverPlan { symbol: "stage3.sumcheck", stage: "stage3", proof_slot: "stage3.sumcheck", kernel: None, relation: Some("jolt.stage3.batched"), batch: "stage3.batch", policy: "jolt_core_stage3_aligned", round_schedule: STAGE3_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 16, degree: 3 }, +]; +pub const STAGE3_SUMCHECK_INSTANCE_RESULTS: &[Stage3SumcheckInstanceResultPlan] = &[ + Stage3SumcheckInstanceResultPlan { symbol: "stage3.spartan_shift.instance", source: "stage3.sumcheck", claim: "stage3.spartan_shift.input", relation: "jolt.stage3.spartan_shift", index: 0, point_arity: 16, num_rounds: 16, round_offset: 0, point_order: "reverse", degree: 2 }, + Stage3SumcheckInstanceResultPlan { symbol: "stage3.instruction_input.instance", source: "stage3.sumcheck", claim: "stage3.instruction_input.input", relation: "jolt.stage3.instruction_input", index: 1, point_arity: 16, num_rounds: 16, round_offset: 0, point_order: "reverse", degree: 3 }, + Stage3SumcheckInstanceResultPlan { symbol: "stage3.registers_claim_reduction.instance", source: "stage3.sumcheck", claim: "stage3.registers_claim_reduction.input", relation: "jolt.stage3.registers_claim_reduction", index: 2, point_arity: 16, num_rounds: 16, round_offset: 0, point_order: "reverse", degree: 2 }, +]; + +pub const STAGE3_SUMCHECK_EVALS: &[Stage3SumcheckEvalPlan] = &[ + Stage3SumcheckEvalPlan { symbol: "stage3.spartan_shift.eval.UnexpandedPC", source: "stage3.sumcheck", name: "stage3.spartan_shift.eval.UnexpandedPC", index: 0, oracle: "UnexpandedPC" }, + Stage3SumcheckEvalPlan { symbol: "stage3.spartan_shift.eval.PC", source: "stage3.sumcheck", name: "stage3.spartan_shift.eval.PC", index: 1, oracle: "PC" }, + Stage3SumcheckEvalPlan { symbol: "stage3.spartan_shift.eval.OpFlagVirtualInstruction", source: "stage3.sumcheck", name: "stage3.spartan_shift.eval.OpFlagVirtualInstruction", index: 2, oracle: "OpFlagVirtualInstruction" }, + Stage3SumcheckEvalPlan { symbol: "stage3.spartan_shift.eval.OpFlagIsFirstInSequence", source: "stage3.sumcheck", name: "stage3.spartan_shift.eval.OpFlagIsFirstInSequence", index: 3, oracle: "OpFlagIsFirstInSequence" }, + Stage3SumcheckEvalPlan { symbol: "stage3.spartan_shift.eval.InstructionFlagIsNoop", source: "stage3.sumcheck", name: "stage3.spartan_shift.eval.InstructionFlagIsNoop", index: 4, oracle: "InstructionFlagIsNoop" }, + Stage3SumcheckEvalPlan { symbol: "stage3.instruction_input.eval.InstructionFlagLeftOperandIsRs1Value", source: "stage3.sumcheck", name: "stage3.instruction_input.eval.InstructionFlagLeftOperandIsRs1Value", index: 5, oracle: "InstructionFlagLeftOperandIsRs1Value" }, + Stage3SumcheckEvalPlan { symbol: "stage3.instruction_input.eval.Rs1Value", source: "stage3.sumcheck", name: "stage3.instruction_input.eval.Rs1Value", index: 6, oracle: "Rs1Value" }, + Stage3SumcheckEvalPlan { symbol: "stage3.instruction_input.eval.InstructionFlagLeftOperandIsPC", source: "stage3.sumcheck", name: "stage3.instruction_input.eval.InstructionFlagLeftOperandIsPC", index: 7, oracle: "InstructionFlagLeftOperandIsPC" }, + Stage3SumcheckEvalPlan { symbol: "stage3.instruction_input.eval.UnexpandedPC", source: "stage3.sumcheck", name: "stage3.instruction_input.eval.UnexpandedPC", index: 8, oracle: "UnexpandedPC" }, + Stage3SumcheckEvalPlan { symbol: "stage3.instruction_input.eval.InstructionFlagRightOperandIsRs2Value", source: "stage3.sumcheck", name: "stage3.instruction_input.eval.InstructionFlagRightOperandIsRs2Value", index: 9, oracle: "InstructionFlagRightOperandIsRs2Value" }, + Stage3SumcheckEvalPlan { symbol: "stage3.instruction_input.eval.Rs2Value", source: "stage3.sumcheck", name: "stage3.instruction_input.eval.Rs2Value", index: 10, oracle: "Rs2Value" }, + Stage3SumcheckEvalPlan { symbol: "stage3.instruction_input.eval.InstructionFlagRightOperandIsImm", source: "stage3.sumcheck", name: "stage3.instruction_input.eval.InstructionFlagRightOperandIsImm", index: 11, oracle: "InstructionFlagRightOperandIsImm" }, + Stage3SumcheckEvalPlan { symbol: "stage3.instruction_input.eval.Imm", source: "stage3.sumcheck", name: "stage3.instruction_input.eval.Imm", index: 12, oracle: "Imm" }, + Stage3SumcheckEvalPlan { symbol: "stage3.registers_claim_reduction.eval.RdWriteValue", source: "stage3.sumcheck", name: "stage3.registers_claim_reduction.eval.RdWriteValue", index: 13, oracle: "RdWriteValue" }, + Stage3SumcheckEvalPlan { symbol: "stage3.registers_claim_reduction.eval.Rs1Value", source: "stage3.sumcheck", name: "stage3.registers_claim_reduction.eval.Rs1Value", index: 14, oracle: "Rs1Value" }, + Stage3SumcheckEvalPlan { symbol: "stage3.registers_claim_reduction.eval.Rs2Value", source: "stage3.sumcheck", name: "stage3.registers_claim_reduction.eval.Rs2Value", index: 15, oracle: "Rs2Value" }, +]; + +pub const STAGE3_POINT_SLICES: &[Stage3PointSlicePlan] = &[ + +]; + +pub const STAGE3_POINT_CONCATS: &[Stage3PointConcatPlan] = &[ + +]; +pub const STAGE3_OPENING_CLAIMS: &[Stage3OpeningClaimPlan] = &[ + Stage3OpeningClaimPlan { symbol: "stage3.spartan_shift.opening.UnexpandedPC", oracle: "UnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.spartan_shift.instance", eval_source: "stage3.spartan_shift.eval.UnexpandedPC" }, + Stage3OpeningClaimPlan { symbol: "stage3.spartan_shift.opening.PC", oracle: "PC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.spartan_shift.instance", eval_source: "stage3.spartan_shift.eval.PC" }, + Stage3OpeningClaimPlan { symbol: "stage3.spartan_shift.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.spartan_shift.instance", eval_source: "stage3.spartan_shift.eval.OpFlagVirtualInstruction" }, + Stage3OpeningClaimPlan { symbol: "stage3.spartan_shift.opening.OpFlagIsFirstInSequence", oracle: "OpFlagIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.spartan_shift.instance", eval_source: "stage3.spartan_shift.eval.OpFlagIsFirstInSequence" }, + Stage3OpeningClaimPlan { symbol: "stage3.spartan_shift.opening.InstructionFlagIsNoop", oracle: "InstructionFlagIsNoop", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.spartan_shift.instance", eval_source: "stage3.spartan_shift.eval.InstructionFlagIsNoop" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.InstructionFlagLeftOperandIsRs1Value", oracle: "InstructionFlagLeftOperandIsRs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.InstructionFlagLeftOperandIsRs1Value" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.Rs1Value" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.InstructionFlagLeftOperandIsPC", oracle: "InstructionFlagLeftOperandIsPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.InstructionFlagLeftOperandIsPC" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.UnexpandedPC", oracle: "UnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.UnexpandedPC" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.InstructionFlagRightOperandIsRs2Value", oracle: "InstructionFlagRightOperandIsRs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.InstructionFlagRightOperandIsRs2Value" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.Rs2Value" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.InstructionFlagRightOperandIsImm", oracle: "InstructionFlagRightOperandIsImm", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.InstructionFlagRightOperandIsImm" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.Imm", oracle: "Imm", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.Imm" }, + Stage3OpeningClaimPlan { symbol: "stage3.registers_claim_reduction.opening.RdWriteValue", oracle: "RdWriteValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.registers_claim_reduction.instance", eval_source: "stage3.registers_claim_reduction.eval.RdWriteValue" }, + Stage3OpeningClaimPlan { symbol: "stage3.registers_claim_reduction.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.registers_claim_reduction.instance", eval_source: "stage3.registers_claim_reduction.eval.Rs1Value" }, + Stage3OpeningClaimPlan { symbol: "stage3.registers_claim_reduction.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.registers_claim_reduction.instance", eval_source: "stage3.registers_claim_reduction.eval.Rs2Value" }, +]; + +pub const STAGE3_OPENING_EQUALITIES: &[Stage3OpeningClaimEqualityPlan] = &[ + Stage3OpeningClaimEqualityPlan { symbol: "stage3.instruction_input.left_claim_consistency", mode: "point_and_eval", lhs: "stage3.input.stage2.product_virtual.LeftInstructionInput", rhs: "stage3.input.stage2.instruction_lookup.LeftInstructionInput" }, + Stage3OpeningClaimEqualityPlan { symbol: "stage3.instruction_input.right_claim_consistency", mode: "point_and_eval", lhs: "stage3.input.stage2.product_virtual.RightInstructionInput", rhs: "stage3.input.stage2.instruction_lookup.RightInstructionInput" }, +]; + +pub const STAGE3_OPENING_BATCHES: &[Stage3OpeningBatchPlan] = &[ + Stage3OpeningBatchPlan { symbol: "stage3.openings", stage: "stage3", proof_slot: "stage3.openings", policy: "jolt_stage3_output_order", count: 16, ordered_claims: "stage3.spartan_shift.opening.UnexpandedPC|stage3.spartan_shift.opening.PC|stage3.spartan_shift.opening.OpFlagVirtualInstruction|stage3.spartan_shift.opening.OpFlagIsFirstInSequence|stage3.spartan_shift.opening.InstructionFlagIsNoop|stage3.instruction_input.opening.InstructionFlagLeftOperandIsRs1Value|stage3.instruction_input.opening.Rs1Value|stage3.instruction_input.opening.InstructionFlagLeftOperandIsPC|stage3.instruction_input.opening.UnexpandedPC|stage3.instruction_input.opening.InstructionFlagRightOperandIsRs2Value|stage3.instruction_input.opening.Rs2Value|stage3.instruction_input.opening.InstructionFlagRightOperandIsImm|stage3.instruction_input.opening.Imm|stage3.registers_claim_reduction.opening.RdWriteValue|stage3.registers_claim_reduction.opening.Rs1Value|stage3.registers_claim_reduction.opening.Rs2Value", claim_operands: "stage3.spartan_shift.opening.UnexpandedPC|stage3.spartan_shift.opening.PC|stage3.spartan_shift.opening.OpFlagVirtualInstruction|stage3.spartan_shift.opening.OpFlagIsFirstInSequence|stage3.spartan_shift.opening.InstructionFlagIsNoop|stage3.instruction_input.opening.InstructionFlagLeftOperandIsRs1Value|stage3.instruction_input.opening.Rs1Value|stage3.instruction_input.opening.InstructionFlagLeftOperandIsPC|stage3.instruction_input.opening.UnexpandedPC|stage3.instruction_input.opening.InstructionFlagRightOperandIsRs2Value|stage3.instruction_input.opening.Rs2Value|stage3.instruction_input.opening.InstructionFlagRightOperandIsImm|stage3.instruction_input.opening.Imm|stage3.registers_claim_reduction.opening.RdWriteValue|stage3.registers_claim_reduction.opening.Rs1Value|stage3.registers_claim_reduction.opening.Rs2Value" }, +]; +pub const STAGE3_PROGRAM: Stage3VerifierProgramPlan = Stage3VerifierProgramPlan { + params: STAGE3_PARAMS, + steps: STAGE3_PROGRAM_STEPS, + transcript_squeezes: STAGE3_TRANSCRIPT_SQUEEZES, + opening_inputs: STAGE3_OPENING_INPUTS, + field_constants: STAGE3_FIELD_CONSTANTS, + field_exprs: STAGE3_FIELD_EXPRS, + claims: STAGE3_SUMCHECK_CLAIMS, + batches: STAGE3_SUMCHECK_BATCHES, + drivers: STAGE3_SUMCHECK_DRIVERS, + instance_results: STAGE3_SUMCHECK_INSTANCE_RESULTS, + evals: STAGE3_SUMCHECK_EVALS, + point_slices: STAGE3_POINT_SLICES, + point_concats: STAGE3_POINT_CONCATS, + opening_claims: STAGE3_OPENING_CLAIMS, + opening_equalities: STAGE3_OPENING_EQUALITIES, + opening_batches: STAGE3_OPENING_BATCHES, +}; + +pub fn verify_stage3( + proof: &Stage3Proof, + opening_inputs: &[Stage3OpeningInputValue], + transcript: &mut T, +) -> Result, VerifyStage3Error> +where + T: Transcript, +{ + verify_stage3_with_program(&STAGE3_PROGRAM, proof, opening_inputs, transcript) +} + +pub fn verify_stage3_with_program( + program: &'static Stage3VerifierProgramPlan, + proof: &Stage3Proof, + opening_inputs: &[Stage3OpeningInputValue], + transcript: &mut T, +) -> Result, VerifyStage3Error> +where + T: Transcript, +{ + if proof.sumchecks.len() != program.drivers.len() { + return Err(VerifyStage3Error::UnexpectedProofCount { + expected: program.drivers.len(), + got: proof.sumchecks.len(), + }); + } + let mut store = + super::common::ValueStore::with_opening_inputs(opening_inputs, program.opening_inputs)?; + store.seed_constants(program.field_constants); + let mut artifacts = Stage3ExecutionArtifacts::default(); + for step in program.steps { + match step.kind { + "transcript_squeeze" => { + let squeeze = + find_plan(program.transcript_squeezes, step.symbol).ok_or(VerifyStage3Error::MissingValue { + symbol: step.symbol, + })?; + verify_stage3_squeeze(program, squeeze, &mut store, transcript, &mut artifacts)?; + } + "sumcheck_driver" => { + let driver = + find_plan(program.drivers, step.symbol).ok_or(VerifyStage3Error::MissingProof { + driver: step.symbol, + })?; + verify_stage3_driver(program, driver, proof, &mut store, transcript, &mut artifacts)?; + } + _ => { + return Err(VerifyStage3Error::InvalidProof { + driver: step.symbol, + reason: "unsupported stage3 program step", + }); + } + } + } + artifacts + .opening_batches + .extend(program.opening_batches.iter()); + Ok(artifacts) +} + +pub fn stage3_verifier_program() -> &'static Stage3VerifierProgramPlan { + &STAGE3_PROGRAM +} + +fn verify_stage3_squeeze( + program: &'static Stage3VerifierProgramPlan, + squeeze: &'static Stage3TranscriptSqueezePlan, + store: &mut super::common::ValueStore, + transcript: &mut T, + artifacts: &mut Stage3ExecutionArtifacts, +) -> Result<(), VerifyStage3Error> +where + T: Transcript, +{ + let values = transcript.challenge_vector(squeeze.count); + store.observe_challenge_vector(squeeze, &values, |input, expected, actual| { + VerifyStage3Error::InvalidInputLength { + input, + expected, + actual, + } + })?; + store + .evaluate_available_field_exprs(program.field_exprs, super::common::evaluate_field_expr) + .map_err(VerifyStage3Error::from)?; + artifacts.challenge_vectors.push(Stage3ChallengeVector { + symbol: squeeze.symbol, + values, + }); + Ok(()) +} + +fn verify_stage3_driver( + program: &'static Stage3VerifierProgramPlan, + driver: &'static Stage3SumcheckDriverPlan, + proof: &Stage3Proof, + store: &mut super::common::ValueStore, + transcript: &mut T, + artifacts: &mut Stage3ExecutionArtifacts, +) -> Result<(), VerifyStage3Error> +where + T: Transcript, +{ + let proof = proof + .sumchecks + .get(artifacts.sumchecks.len()) + .ok_or(VerifyStage3Error::MissingProof { + driver: driver.symbol, + })?; + let relation = driver.relation.unwrap_or(""); + let output = match relation { + "jolt.stage3.batched" => { + verify_batched_stage3(program, driver, proof, store, transcript)? + } + _ => { + return Err(VerifyStage3Error::UnsupportedRelation { + relation, + }); + } + }; + artifacts.sumchecks.push(output); + Ok(()) +} + +fn verify_batched_stage3( + program: &'static Stage3VerifierProgramPlan, + driver: &'static Stage3SumcheckDriverPlan, + proof: &Stage3SumcheckOutput, + store: &mut super::common::ValueStore, + transcript: &mut T, +) -> Result, VerifyStage3Error> +where + T: Transcript, +{ + super::common::verify_batched_sumcheck( + driver, + proof, + program.claims, + program.batches, + program.field_exprs, + program.opening_inputs, + program.opening_claims, + program.opening_batches, + store, + transcript, + |store, evals, point, batching_coeffs| { + expected_batched_output_claim(program, driver, store, evals, point, batching_coeffs) + }, + |store, verified| observe_stage3_sumcheck_output(program, store, verified), + |driver, error| VerifyStage3Error::Sumcheck { driver, error }, + ) +} + +fn observe_stage3_sumcheck_output( + program: &'static Stage3VerifierProgramPlan, + store: &mut super::common::ValueStore, + output: &Stage3SumcheckOutput, +) -> Result<(), VerifyStage3Error> { + store.observe_sumcheck_output( + program.instance_results, + program.evals, + output, + |instance, mut point| { + match instance.point_order { + "as_is" => {} + "reverse" => point.reverse(), + _ => { + return Err(VerifyStage3Error::InvalidProof { + driver: output.driver, + reason: "unsupported point order", + }); + } + } + Ok(point) + }, + |input, expected, actual| VerifyStage3Error::InvalidInputLength { + input, + expected, + actual, + }, + |symbol| VerifyStage3Error::MissingValue { symbol }, + )?; + store.evaluate_available_points( + program.point_slices, + program.point_concats, + |input, expected, actual| VerifyStage3Error::InvalidInputLength { + input, + expected, + actual, + }, + )?; + store + .evaluate_available_field_exprs(program.field_exprs, super::common::evaluate_field_expr) + .map_err(VerifyStage3Error::from)?; + store.verify_opening_equalities( + program.opening_equalities, + |driver, reason| VerifyStage3Error::InvalidProof { driver, reason }, + |symbol| VerifyStage3Error::MissingValue { symbol }, + ) +} + +fn expected_batched_output_claim( + program: &'static Stage3VerifierProgramPlan, + driver: &'static Stage3SumcheckDriverPlan, + store: &super::common::ValueStore, + evals: &[Stage3NamedEval], + point: &[Fr], + batching_coeffs: &[Fr], +) -> Result { + let batch = find_batch(program.batches, driver.symbol, driver.batch)?; + let claims = batch_claims(program.claims, batch)?; + let mut expected = Fr::from_u64(0); + for (claim, coefficient) in claims.iter().zip(batching_coeffs) { + let instance = program + .instance_results + .iter() + .find(|instance| instance.claim == claim.symbol && instance.source == driver.symbol) + .ok_or(VerifyStage3Error::MissingClaim { + batch: batch.symbol, + claim: claim.symbol, + })?; + let local_point = point + .get(instance.round_offset..instance.round_offset + instance.num_rounds) + .ok_or(VerifyStage3Error::InvalidInputLength { + input: instance.symbol, + expected: instance.round_offset + instance.num_rounds, + actual: point.len(), + })?; + let value = match instance.relation { + "jolt.stage3.spartan_shift" => { + expected_spartan_shift(store, evals, local_point)? + } + "jolt.stage3.instruction_input" => { + expected_instruction_input(store, evals, local_point)? + } + "jolt.stage3.registers_claim_reduction" => { + expected_registers(store, evals, local_point)? + } + _ => { + return Err(VerifyStage3Error::UnsupportedRelation { + relation: instance.relation, + }); + } + }; + expected += *coefficient * value; + } + Ok(expected) +} + +fn expected_spartan_shift( + store: &super::common::ValueStore, + evals: &[Stage3NamedEval], + local_point: &[Fr], +) -> Result { + let opening_point = reverse_slice(local_point); + let eq_outer = + EqPlusOnePolynomial::::new(super::common::store_point(store, "stage3.input.stage1.NextPC")?.to_vec()) + .evaluate(&opening_point); + let eq_product = EqPlusOnePolynomial::::new( + super::common::store_point(store, "stage3.input.stage2.product_virtual.NextIsNoop")? + .to_vec(), + ) + .evaluate(&opening_point); + let weighted_outer = eval_by_name(evals, "stage3.spartan_shift.eval.UnexpandedPC")? + + super::common::store_scalar(store, "stage3.spartan_shift.gamma")? + * eval_by_name(evals, "stage3.spartan_shift.eval.PC")? + + super::common::store_scalar(store, "stage3.spartan_shift.gamma2")? + * eval_by_name(evals, "stage3.spartan_shift.eval.OpFlagVirtualInstruction")? + + super::common::store_scalar(store, "stage3.spartan_shift.gamma3")? + * eval_by_name(evals, "stage3.spartan_shift.eval.OpFlagIsFirstInSequence")?; + Ok(eq_outer * weighted_outer + + super::common::store_scalar(store, "stage3.spartan_shift.gamma4")? + * eq_product + * (Fr::from_u64(1) + - eval_by_name(evals, "stage3.spartan_shift.eval.InstructionFlagIsNoop")?)) +} + +fn expected_instruction_input( + store: &super::common::ValueStore, + evals: &[Stage3NamedEval], + local_point: &[Fr], +) -> Result { + let opening_point = reverse_slice(local_point); + let eq_eval = EqPolynomial::::mle( + &opening_point, + super::common::store_point(store, "stage3.input.stage2.product_virtual.LeftInstructionInput")?, + ); + let left = eval_by_name( + evals, + "stage3.instruction_input.eval.InstructionFlagLeftOperandIsRs1Value", + )? * eval_by_name(evals, "stage3.instruction_input.eval.Rs1Value")? + + eval_by_name( + evals, + "stage3.instruction_input.eval.InstructionFlagLeftOperandIsPC", + )? * eval_by_name(evals, "stage3.instruction_input.eval.UnexpandedPC")?; + let right = eval_by_name( + evals, + "stage3.instruction_input.eval.InstructionFlagRightOperandIsRs2Value", + )? * eval_by_name(evals, "stage3.instruction_input.eval.Rs2Value")? + + eval_by_name( + evals, + "stage3.instruction_input.eval.InstructionFlagRightOperandIsImm", + )? * eval_by_name(evals, "stage3.instruction_input.eval.Imm")?; + Ok(eq_eval * (right + super::common::store_scalar(store, "stage3.instruction_input.gamma")? * left)) +} + +fn expected_registers( + store: &super::common::ValueStore, + evals: &[Stage3NamedEval], + local_point: &[Fr], +) -> Result { + let opening_point = reverse_slice(local_point); + let eq_eval = EqPolynomial::::mle( + &opening_point, + super::common::store_point(store, "stage3.input.stage1.RdWriteValue")?, + ); + Ok(eq_eval + * (eval_by_name(evals, "stage3.registers_claim_reduction.eval.RdWriteValue")? + + super::common::store_scalar(store, "stage3.registers.gamma")? + * eval_by_name(evals, "stage3.registers_claim_reduction.eval.Rs1Value")? + + super::common::store_scalar(store, "stage3.registers.gamma2")? + * eval_by_name(evals, "stage3.registers_claim_reduction.eval.Rs2Value")?)) +} diff --git a/crates/jolt-verifier/src/stages/stage4.rs b/crates/jolt-verifier/src/stages/stage4.rs new file mode 100644 index 0000000000..3367e34d96 --- /dev/null +++ b/crates/jolt-verifier/src/stages/stage4.rs @@ -0,0 +1,552 @@ +#![allow(dead_code)] + +use super::common::{batch_claims, eval_by_name, find_batch, find_plan, lt_polynomial_eval, reverse_slice}; +use jolt_field::{Field, Fr}; +use jolt_poly::EqPolynomial; +use jolt_sumcheck::SumcheckError; +use jolt_transcript::{Blake2bTranscript, LabelWithCount, Transcript}; + +pub type Stage4NamedEval = super::common::StageNamedEval; +pub type Stage4SumcheckOutput = super::common::StageSumcheckOutput; +pub type Stage4ChallengeVector = super::common::StageChallengeVector; +pub type Stage4ExecutionArtifacts = super::common::StageExecutionArtifacts; +pub type Stage4Proof = super::common::StageProof; +pub type Stage4OpeningInputValue = super::common::StageOpeningInputValue; + +pub use super::common::{ + FieldConstantPlan as Stage4FieldConstantPlan, FieldExprPlan as Stage4FieldExprPlan, + KernelPlan as Stage4KernelPlan, OpeningBatchPlan as Stage4OpeningBatchPlan, + OpeningClaimEqualityPlan as Stage4OpeningClaimEqualityPlan, + OpeningClaimPlan as Stage4OpeningClaimPlan, OpeningInputPlan as Stage4OpeningInputPlan, + PointConcatPlan as Stage4PointConcatPlan, PointSlicePlan as Stage4PointSlicePlan, + ProgramStepPlan as Stage4ProgramStepPlan, StageParams as Stage4Params, + StageProgramPlanNoPointZeros as Stage4CpuProgramPlan, + SumcheckBatchPlan as Stage4SumcheckBatchPlan, + SumcheckClaimPlan as Stage4SumcheckClaimPlan, SumcheckDriverPlan as Stage4SumcheckDriverPlan, + SumcheckEvalPlan as Stage4SumcheckEvalPlan, + SumcheckInstanceResultPlan as Stage4SumcheckInstanceResultPlan, + TranscriptAbsorbBytesPlan as Stage4TranscriptAbsorbBytesPlan, + TranscriptSqueezePlan as Stage4TranscriptSqueezePlan, +}; + +pub type DefaultStage4Transcript = Blake2bTranscript; +pub type Stage4VerifierProgramPlan = Stage4CpuProgramPlan; + +#[derive(Debug)] +pub enum VerifyStage4Error { + UnexpectedProofCount { expected: usize, got: usize }, + MissingProof { driver: &'static str }, + MissingBatch { driver: &'static str, batch: &'static str }, + MissingClaim { batch: &'static str, claim: &'static str }, + MissingValue { symbol: &'static str }, + InvalidInputLength { input: &'static str, expected: usize, actual: usize }, + InvalidProof { driver: &'static str, reason: &'static str }, + UnsupportedFieldExpr { symbol: &'static str, formula: &'static str }, + UnsupportedRelation { relation: &'static str }, + Sumcheck { driver: &'static str, error: SumcheckError }, +} + +super::common::impl_runtime_plan_error_conversion!(VerifyStage4Error); + +pub const STAGE4_PARAMS: Stage4Params = Stage4Params { + field: "bn254_fr", + pcs: "dory", + transcript: "blake2b_transcript", +}; +pub const STAGE4_PROGRAM_STEPS: &[Stage4ProgramStepPlan] = &[ + Stage4ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage4.registers_read_write.gamma" }, + Stage4ProgramStepPlan { kind: "transcript_absorb_bytes", symbol: "stage4.ram_val_check.domain_separator" }, + Stage4ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage4.ram_val_check.gamma" }, + Stage4ProgramStepPlan { kind: "sumcheck_driver", symbol: "stage4.sumcheck" }, +]; + +pub const STAGE4_TRANSCRIPT_SQUEEZES: &[Stage4TranscriptSqueezePlan] = &[ + Stage4TranscriptSqueezePlan { symbol: "stage4.registers_read_write.gamma", label: "registers_read_write_gamma", kind: "challenge_scalar", count: 1 }, + Stage4TranscriptSqueezePlan { symbol: "stage4.ram_val_check.gamma", label: "ram_val_check_gamma", kind: "challenge_scalar", count: 1 }, +]; + +pub const STAGE4_TRANSCRIPT_ABSORB_BYTES: &[Stage4TranscriptAbsorbBytesPlan] = &[ + Stage4TranscriptAbsorbBytesPlan { symbol: "stage4.ram_val_check.domain_separator", label: "ram_val_check_gamma", payload: "" }, +]; + +pub const STAGE4_OPENING_INPUTS: &[Stage4OpeningInputPlan] = &[ + Stage4OpeningInputPlan { symbol: "stage4.input.stage3.registers.RdWriteValue", source_stage: "stage3", source_claim: "stage3.registers_claim_reduction.opening.RdWriteValue", oracle: "RdWriteValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage4OpeningInputPlan { symbol: "stage4.input.stage3.registers.Rs1Value", source_stage: "stage3", source_claim: "stage3.registers_claim_reduction.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage4OpeningInputPlan { symbol: "stage4.input.stage3.registers.Rs2Value", source_stage: "stage3", source_claim: "stage3.registers_claim_reduction.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage4OpeningInputPlan { symbol: "stage4.input.stage3.instruction.Rs1Value", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage4OpeningInputPlan { symbol: "stage4.input.stage3.instruction.Rs2Value", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage4OpeningInputPlan { symbol: "stage4.input.stage2.RamVal", source_stage: "stage2", source_claim: "stage2.ram_read_write.opening.RamVal", oracle: "RamVal", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual" }, + Stage4OpeningInputPlan { symbol: "stage4.input.stage2.RamValFinal", source_stage: "stage2", source_claim: "stage2.ram_output.opening.RamValFinal", oracle: "RamValFinal", domain: "jolt.ram_address_domain", point_arity: 16, claim_kind: "virtual" }, + Stage4OpeningInputPlan { symbol: "stage4.input.initial_ram.RamValInit", source_stage: "stage4_precomputed", source_claim: "stage4.ram_val_check.initial_ram_eval", oracle: "RamValInit", domain: "jolt.ram_address_domain", point_arity: 16, claim_kind: "virtual" }, +]; + +pub const STAGE4_FIELD_CONSTANTS: &[Stage4FieldConstantPlan] = &[ + +]; + +pub const STAGE4_FIELD_EXPRS: &[Stage4FieldExprPlan] = &[ + Stage4FieldExprPlan { symbol: "stage4.registers_read_write.gamma2", kind: "op", formula: "field.pow:2", operands: "stage4.registers_read_write.gamma" }, + Stage4FieldExprPlan { symbol: "stage4.registers_read_write.term.Rs1Value", kind: "op", formula: "field.mul", operands: "stage4.registers_read_write.gamma|stage4.input.stage3.registers.Rs1Value" }, + Stage4FieldExprPlan { symbol: "stage4.registers_read_write.term.Rs2Value", kind: "op", formula: "field.mul", operands: "stage4.registers_read_write.gamma2|stage4.input.stage3.registers.Rs2Value" }, + Stage4FieldExprPlan { symbol: "stage4.registers_read_write.partial.RdWriteValueRs1Value", kind: "op", formula: "field.add", operands: "stage4.input.stage3.registers.RdWriteValue|stage4.registers_read_write.term.Rs1Value" }, + Stage4FieldExprPlan { symbol: "stage4.registers_read_write.claim_expr", kind: "op", formula: "field.add", operands: "stage4.registers_read_write.partial.RdWriteValueRs1Value|stage4.registers_read_write.term.Rs2Value" }, + Stage4FieldExprPlan { symbol: "stage4.ram_val_check.delta.RamVal", kind: "op", formula: "field.sub", operands: "stage4.input.stage2.RamVal|stage4.input.initial_ram.RamValInit" }, + Stage4FieldExprPlan { symbol: "stage4.ram_val_check.delta.RamValFinal", kind: "op", formula: "field.sub", operands: "stage4.input.stage2.RamValFinal|stage4.input.initial_ram.RamValInit" }, + Stage4FieldExprPlan { symbol: "stage4.ram_val_check.term.RamValFinal", kind: "op", formula: "field.mul", operands: "stage4.ram_val_check.gamma|stage4.ram_val_check.delta.RamValFinal" }, + Stage4FieldExprPlan { symbol: "stage4.ram_val_check.claim_expr", kind: "op", formula: "field.add", operands: "stage4.ram_val_check.delta.RamVal|stage4.ram_val_check.term.RamValFinal" }, +]; +pub const STAGE4_KERNELS: &[Stage4KernelPlan] = &[ + +]; + +pub const STAGE4_SUMCHECK_CLAIMS: &[Stage4SumcheckClaimPlan] = &[ + Stage4SumcheckClaimPlan { symbol: "stage4.registers_read_write.input", stage: "stage4", domain: "jolt.stage4_registers_rw_domain", num_rounds: 23, degree: 3, claim: "stage4.registers_read_write.weighted_values", kernel: None, relation: Some("jolt.stage4.registers_read_write"), claim_value: "stage4.registers_read_write.claim_expr", input_openings: "stage4.input.stage3.registers.RdWriteValue|stage4.input.stage3.registers.Rs1Value|stage4.input.stage3.registers.Rs2Value" }, + Stage4SumcheckClaimPlan { symbol: "stage4.ram_val_check.input", stage: "stage4", domain: "jolt.trace_domain", num_rounds: 16, degree: 3, claim: "stage4.ram_val_check.weighted_values", kernel: None, relation: Some("jolt.stage4.ram_val_check"), claim_value: "stage4.ram_val_check.claim_expr", input_openings: "stage4.input.stage2.RamVal|stage4.input.stage2.RamValFinal|stage4.input.initial_ram.RamValInit" }, +]; +pub const STAGE4_SUMCHECK_BATCH_0_ROUND_SCHEDULE: &[usize] = &[ + 16, + 7, +]; + +pub const STAGE4_SUMCHECK_BATCHES: &[Stage4SumcheckBatchPlan] = &[ + Stage4SumcheckBatchPlan { symbol: "stage4.batch", stage: "stage4", proof_slot: "stage4.sumcheck", policy: "jolt_core_stage4_aligned", count: 2, ordered_claims: "stage4.registers_read_write.input|stage4.ram_val_check.input", claim_operands: "stage4.registers_read_write.input|stage4.ram_val_check.input", claim_label: "sumcheck_claim", round_label: "sumcheck_poly", round_schedule: STAGE4_SUMCHECK_BATCH_0_ROUND_SCHEDULE }, +]; +pub const STAGE4_SUMCHECK_DRIVER_0_ROUND_SCHEDULE: &[usize] = &[ + 16, + 7, +]; + +pub const STAGE4_SUMCHECK_DRIVERS: &[Stage4SumcheckDriverPlan] = &[ + Stage4SumcheckDriverPlan { symbol: "stage4.sumcheck", stage: "stage4", proof_slot: "stage4.sumcheck", kernel: None, relation: Some("jolt.stage4.batched"), batch: "stage4.batch", policy: "jolt_core_stage4_aligned", round_schedule: STAGE4_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 23, degree: 3 }, +]; +pub const STAGE4_SUMCHECK_INSTANCE_RESULTS: &[Stage4SumcheckInstanceResultPlan] = &[ + Stage4SumcheckInstanceResultPlan { symbol: "stage4.registers_read_write.instance", source: "stage4.sumcheck", claim: "stage4.registers_read_write.input", relation: "jolt.stage4.registers_read_write", index: 0, point_arity: 23, num_rounds: 23, round_offset: 0, point_order: "stage4_registers_rw", degree: 3 }, + Stage4SumcheckInstanceResultPlan { symbol: "stage4.ram_val_check.instance", source: "stage4.sumcheck", claim: "stage4.ram_val_check.input", relation: "jolt.stage4.ram_val_check", index: 1, point_arity: 16, num_rounds: 16, round_offset: 7, point_order: "reverse", degree: 3 }, +]; + +pub const STAGE4_SUMCHECK_EVALS: &[Stage4SumcheckEvalPlan] = &[ + Stage4SumcheckEvalPlan { symbol: "stage4.registers_read_write.eval.RegistersVal", source: "stage4.sumcheck", name: "stage4.registers_read_write.eval.RegistersVal", index: 0, oracle: "RegistersVal" }, + Stage4SumcheckEvalPlan { symbol: "stage4.registers_read_write.eval.Rs1Ra", source: "stage4.sumcheck", name: "stage4.registers_read_write.eval.Rs1Ra", index: 1, oracle: "Rs1Ra" }, + Stage4SumcheckEvalPlan { symbol: "stage4.registers_read_write.eval.Rs2Ra", source: "stage4.sumcheck", name: "stage4.registers_read_write.eval.Rs2Ra", index: 2, oracle: "Rs2Ra" }, + Stage4SumcheckEvalPlan { symbol: "stage4.registers_read_write.eval.RdWa", source: "stage4.sumcheck", name: "stage4.registers_read_write.eval.RdWa", index: 3, oracle: "RdWa" }, + Stage4SumcheckEvalPlan { symbol: "stage4.registers_read_write.eval.RdInc", source: "stage4.sumcheck", name: "stage4.registers_read_write.eval.RdInc", index: 4, oracle: "RdInc" }, + Stage4SumcheckEvalPlan { symbol: "stage4.ram_val_check.eval.RamRa", source: "stage4.sumcheck", name: "stage4.ram_val_check.eval.RamRa", index: 0, oracle: "RamRa" }, + Stage4SumcheckEvalPlan { symbol: "stage4.ram_val_check.eval.RamInc", source: "stage4.sumcheck", name: "stage4.ram_val_check.eval.RamInc", index: 1, oracle: "RamInc" }, +]; + +pub const STAGE4_POINT_SLICES: &[Stage4PointSlicePlan] = &[ + Stage4PointSlicePlan { symbol: "stage4.registers_read_write.point.RdInc", source: "stage4.registers_read_write.instance", offset: 7, length: 16, input: "stage4.registers_read_write.instance" }, + Stage4PointSlicePlan { symbol: "stage4.ram_val_check.point.RamAddress", source: "stage4.input.stage2.RamVal", offset: 0, length: 16, input: "stage4.input.stage2.RamVal" }, +]; + +pub const STAGE4_POINT_CONCATS: &[Stage4PointConcatPlan] = &[ + Stage4PointConcatPlan { symbol: "stage4.ram_val_check.point.RamRa", layout: "address_then_cycle", arity: 32, inputs: "stage4.ram_val_check.point.RamAddress|stage4.ram_val_check.instance" }, +]; +pub const STAGE4_OPENING_CLAIMS: &[Stage4OpeningClaimPlan] = &[ + Stage4OpeningClaimPlan { symbol: "stage4.registers_read_write.opening.RegistersVal", oracle: "RegistersVal", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual", point_source: "stage4.registers_read_write.instance", eval_source: "stage4.registers_read_write.eval.RegistersVal" }, + Stage4OpeningClaimPlan { symbol: "stage4.registers_read_write.opening.Rs1Ra", oracle: "Rs1Ra", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual", point_source: "stage4.registers_read_write.instance", eval_source: "stage4.registers_read_write.eval.Rs1Ra" }, + Stage4OpeningClaimPlan { symbol: "stage4.registers_read_write.opening.Rs2Ra", oracle: "Rs2Ra", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual", point_source: "stage4.registers_read_write.instance", eval_source: "stage4.registers_read_write.eval.Rs2Ra" }, + Stage4OpeningClaimPlan { symbol: "stage4.registers_read_write.opening.RdWa", oracle: "RdWa", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual", point_source: "stage4.registers_read_write.instance", eval_source: "stage4.registers_read_write.eval.RdWa" }, + Stage4OpeningClaimPlan { symbol: "stage4.registers_read_write.opening.RdInc", oracle: "RdInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed", point_source: "stage4.registers_read_write.point.RdInc", eval_source: "stage4.registers_read_write.eval.RdInc" }, + Stage4OpeningClaimPlan { symbol: "stage4.ram_val_check.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage4.ram_val_check.point.RamRa", eval_source: "stage4.ram_val_check.eval.RamRa" }, + Stage4OpeningClaimPlan { symbol: "stage4.ram_val_check.opening.RamInc", oracle: "RamInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed", point_source: "stage4.ram_val_check.instance", eval_source: "stage4.ram_val_check.eval.RamInc" }, +]; + +pub const STAGE4_OPENING_EQUALITIES: &[Stage4OpeningClaimEqualityPlan] = &[ + Stage4OpeningClaimEqualityPlan { symbol: "stage4.registers.rs1_claim_consistency", mode: "point_and_eval", lhs: "stage4.input.stage3.registers.Rs1Value", rhs: "stage4.input.stage3.instruction.Rs1Value" }, + Stage4OpeningClaimEqualityPlan { symbol: "stage4.registers.rs2_claim_consistency", mode: "point_and_eval", lhs: "stage4.input.stage3.registers.Rs2Value", rhs: "stage4.input.stage3.instruction.Rs2Value" }, +]; + +pub const STAGE4_OPENING_BATCHES: &[Stage4OpeningBatchPlan] = &[ + Stage4OpeningBatchPlan { symbol: "stage4.openings", stage: "stage4", proof_slot: "stage4.openings", policy: "jolt_stage4_output_order", count: 7, ordered_claims: "stage4.registers_read_write.opening.RegistersVal|stage4.registers_read_write.opening.Rs1Ra|stage4.registers_read_write.opening.Rs2Ra|stage4.registers_read_write.opening.RdWa|stage4.registers_read_write.opening.RdInc|stage4.ram_val_check.opening.RamRa|stage4.ram_val_check.opening.RamInc", claim_operands: "stage4.registers_read_write.opening.RegistersVal|stage4.registers_read_write.opening.Rs1Ra|stage4.registers_read_write.opening.Rs2Ra|stage4.registers_read_write.opening.RdWa|stage4.registers_read_write.opening.RdInc|stage4.ram_val_check.opening.RamRa|stage4.ram_val_check.opening.RamInc" }, +]; +pub const STAGE4_PROGRAM: Stage4VerifierProgramPlan = Stage4CpuProgramPlan { + role: "verifier", + params: STAGE4_PARAMS, + steps: STAGE4_PROGRAM_STEPS, + transcript_squeezes: STAGE4_TRANSCRIPT_SQUEEZES, + transcript_absorb_bytes: STAGE4_TRANSCRIPT_ABSORB_BYTES, + opening_inputs: STAGE4_OPENING_INPUTS, + field_constants: STAGE4_FIELD_CONSTANTS, + field_exprs: STAGE4_FIELD_EXPRS, + kernels: STAGE4_KERNELS, + claims: STAGE4_SUMCHECK_CLAIMS, + batches: STAGE4_SUMCHECK_BATCHES, + drivers: STAGE4_SUMCHECK_DRIVERS, + instance_results: STAGE4_SUMCHECK_INSTANCE_RESULTS, + evals: STAGE4_SUMCHECK_EVALS, + point_slices: STAGE4_POINT_SLICES, + point_concats: STAGE4_POINT_CONCATS, + opening_claims: STAGE4_OPENING_CLAIMS, + opening_equalities: STAGE4_OPENING_EQUALITIES, + opening_batches: STAGE4_OPENING_BATCHES, +}; + +pub fn verify_stage4( + proof: &Stage4Proof, + opening_inputs: &[Stage4OpeningInputValue], + transcript: &mut T, +) -> Result, VerifyStage4Error> +where + T: Transcript, +{ + verify_stage4_with_program(&STAGE4_PROGRAM, proof, opening_inputs, transcript) +} + +pub fn verify_stage4_with_program( + program: &'static Stage4VerifierProgramPlan, + proof: &Stage4Proof, + opening_inputs: &[Stage4OpeningInputValue], + transcript: &mut T, +) -> Result, VerifyStage4Error> +where + T: Transcript, +{ + if proof.sumchecks.len() != program.drivers.len() { + return Err(VerifyStage4Error::UnexpectedProofCount { + expected: program.drivers.len(), + got: proof.sumchecks.len(), + }); + } + let mut store = + super::common::ValueStore::with_opening_inputs(opening_inputs, program.opening_inputs)?; + store.seed_constants(program.field_constants); + let mut artifacts = Stage4ExecutionArtifacts::default(); + for step in program.steps { + match step.kind { + "transcript_squeeze" => { + let squeeze = + find_plan(program.transcript_squeezes, step.symbol).ok_or(VerifyStage4Error::MissingValue { + symbol: step.symbol, + })?; + verify_stage4_squeeze(program, squeeze, &mut store, transcript, &mut artifacts)?; + } + "transcript_absorb_bytes" => { + let absorb = find_plan(program.transcript_absorb_bytes, step.symbol).ok_or( + VerifyStage4Error::MissingValue { + symbol: step.symbol, + }, + )?; + absorb_stage4_bytes(absorb, transcript); + } + "sumcheck_driver" => { + let driver = + find_plan(program.drivers, step.symbol).ok_or(VerifyStage4Error::MissingProof { + driver: step.symbol, + })?; + verify_stage4_driver(program, driver, proof, &mut store, transcript, &mut artifacts)?; + } + _ => { + return Err(VerifyStage4Error::InvalidProof { + driver: step.symbol, + reason: "unsupported stage4 program step", + }); + } + } + } + artifacts + .opening_batches + .extend(program.opening_batches.iter()); + Ok(artifacts) +} + +pub fn stage4_verifier_program() -> &'static Stage4VerifierProgramPlan { + &STAGE4_PROGRAM +} + +fn verify_stage4_squeeze( + program: &'static Stage4VerifierProgramPlan, + squeeze: &'static Stage4TranscriptSqueezePlan, + store: &mut super::common::ValueStore, + transcript: &mut T, + artifacts: &mut Stage4ExecutionArtifacts, +) -> Result<(), VerifyStage4Error> +where + T: Transcript, +{ + let values = transcript.challenge_vector(squeeze.count); + store.observe_challenge_vector(squeeze, &values, |input, expected, actual| { + VerifyStage4Error::InvalidInputLength { + input, + expected, + actual, + } + })?; + store + .evaluate_available_field_exprs(program.field_exprs, super::common::evaluate_field_expr) + .map_err(VerifyStage4Error::from)?; + artifacts.challenge_vectors.push(Stage4ChallengeVector { + symbol: squeeze.symbol, + values, + }); + Ok(()) +} + +fn absorb_stage4_bytes(absorb: &'static Stage4TranscriptAbsorbBytesPlan, transcript: &mut T) +where + T: Transcript, +{ + transcript.append(&LabelWithCount( + absorb.label.as_bytes(), + absorb.payload.len() as u64, + )); + transcript.append_bytes(absorb.payload.as_bytes()); +} + +fn verify_stage4_driver( + program: &'static Stage4VerifierProgramPlan, + driver: &'static Stage4SumcheckDriverPlan, + proof: &Stage4Proof, + store: &mut super::common::ValueStore, + transcript: &mut T, + artifacts: &mut Stage4ExecutionArtifacts, +) -> Result<(), VerifyStage4Error> +where + T: Transcript, +{ + let proof = proof + .sumchecks + .get(artifacts.sumchecks.len()) + .ok_or(VerifyStage4Error::MissingProof { + driver: driver.symbol, + })?; + let relation = driver.relation.unwrap_or(""); + let output = match relation { + "jolt.stage4.batched" => { + verify_batched_stage4(program, driver, proof, store, transcript)? + } + _ => return Err(VerifyStage4Error::UnsupportedRelation { relation }), + }; + artifacts.sumchecks.push(output); + Ok(()) +} + +fn verify_batched_stage4( + program: &'static Stage4VerifierProgramPlan, + driver: &'static Stage4SumcheckDriverPlan, + proof: &Stage4SumcheckOutput, + store: &mut super::common::ValueStore, + transcript: &mut T, +) -> Result, VerifyStage4Error> +where + T: Transcript, +{ + super::common::verify_batched_sumcheck( + driver, + proof, + program.claims, + program.batches, + program.field_exprs, + program.opening_inputs, + program.opening_claims, + program.opening_batches, + store, + transcript, + |store, evals, point, batching_coeffs| { + expected_batched_output_claim(program, driver, store, evals, point, batching_coeffs) + }, + |store, verified| observe_stage4_sumcheck_output(program, store, verified), + |driver, error| VerifyStage4Error::Sumcheck { driver, error }, + ) +} + +fn observe_stage4_sumcheck_output( + program: &'static Stage4VerifierProgramPlan, + store: &mut super::common::ValueStore, + output: &Stage4SumcheckOutput, +) -> Result<(), VerifyStage4Error> { + store.observe_sumcheck_output( + program.instance_results, + program.evals, + output, + |instance, mut point| { + match instance.point_order { + "as_is" => {} + "reverse" => point.reverse(), + "stage4_registers_rw" => { + point = normalize_stage4_registers_rw_point(program, output.driver, &point)?; + } + _ => { + return Err(VerifyStage4Error::InvalidProof { + driver: output.driver, + reason: "unsupported point order", + }); + } + } + Ok(point) + }, + |input, expected, actual| VerifyStage4Error::InvalidInputLength { + input, + expected, + actual, + }, + |symbol| VerifyStage4Error::MissingValue { symbol }, + )?; + store.evaluate_available_points( + program.point_slices, + program.point_concats, + |input, expected, actual| VerifyStage4Error::InvalidInputLength { + input, + expected, + actual, + }, + )?; + store + .evaluate_available_field_exprs(program.field_exprs, super::common::evaluate_field_expr) + .map_err(VerifyStage4Error::from)?; + store.verify_opening_equalities( + program.opening_equalities, + |driver, reason| VerifyStage4Error::InvalidProof { driver, reason }, + |symbol| VerifyStage4Error::MissingValue { symbol }, + ) +} + +fn expected_batched_output_claim( + program: &'static Stage4VerifierProgramPlan, + driver: &'static Stage4SumcheckDriverPlan, + store: &super::common::ValueStore, + evals: &[Stage4NamedEval], + point: &[Fr], + batching_coeffs: &[Fr], +) -> Result { + let batch = find_batch(program.batches, driver.symbol, driver.batch)?; + let claims = batch_claims(program.claims, batch)?; + let mut expected = Fr::from_u64(0); + for (claim, coefficient) in claims.iter().zip(batching_coeffs) { + let instance = program + .instance_results + .iter() + .find(|instance| instance.claim == claim.symbol && instance.source == driver.symbol) + .ok_or(VerifyStage4Error::MissingClaim { + batch: batch.symbol, + claim: claim.symbol, + })?; + let local_point = point + .get(instance.round_offset..instance.round_offset + instance.num_rounds) + .ok_or(VerifyStage4Error::InvalidInputLength { + input: instance.symbol, + expected: instance.round_offset + instance.num_rounds, + actual: point.len(), + })?; + let relation = claim.relation.unwrap_or(""); + let value = match relation { + "jolt.stage4.registers_read_write" => { + expected_registers_read_write(store, evals, local_point)? + } + "jolt.stage4.ram_val_check" => { + expected_ram_val_check(store, evals, local_point)? + } + _ => return Err(VerifyStage4Error::UnsupportedRelation { relation }), + }; + expected += *coefficient * value; + } + Ok(expected) +} + +fn expected_registers_read_write( + store: &super::common::ValueStore, + evals: &[Stage4NamedEval], + local_point: &[Fr], +) -> Result { + let trace_point = super::common::store_point(store, "stage4.input.stage3.registers.RdWriteValue")?; + let r_cycle = normalize_stage4_registers_rw_cycle_point( + local_point, + trace_point.len(), + "stage4.registers_read_write.instance", + )?; + let eq_eval = EqPolynomial::::mle(&r_cycle, trace_point); + let registers_val = eval_by_name( + evals, + "stage4.registers_read_write.eval.RegistersVal", + )?; + let rs1_ra = eval_by_name(evals, "stage4.registers_read_write.eval.Rs1Ra")?; + let rs2_ra = eval_by_name(evals, "stage4.registers_read_write.eval.Rs2Ra")?; + let rd_wa = eval_by_name(evals, "stage4.registers_read_write.eval.RdWa")?; + let rd_inc = eval_by_name(evals, "stage4.registers_read_write.eval.RdInc")?; + let gamma = super::common::store_scalar(store, "stage4.registers_read_write.gamma")?; + Ok(eq_eval + * (rd_wa * (registers_val + rd_inc) + + gamma * (rs1_ra * registers_val + gamma * rs2_ra * registers_val))) +} + +fn expected_ram_val_check( + store: &super::common::ValueStore, + evals: &[Stage4NamedEval], + local_point: &[Fr], +) -> Result { + let ram_val_point = super::common::store_point(store, "stage4.input.stage2.RamVal")?; + let r_cycle_prime = reverse_slice(local_point); + let r_cycle = suffix_point( + ram_val_point, + r_cycle_prime.len(), + "stage4.input.stage2.RamVal", + )?; + let lt_eval = lt_polynomial_eval(&r_cycle_prime, r_cycle); + let gamma = super::common::store_scalar(store, "stage4.ram_val_check.gamma")?; + let ram_ra = eval_by_name(evals, "stage4.ram_val_check.eval.RamRa")?; + let ram_inc = eval_by_name(evals, "stage4.ram_val_check.eval.RamInc")?; + Ok(ram_inc * ram_ra * (lt_eval + gamma)) +} + +fn suffix_point<'a>( + point: &'a [Fr], + length: usize, + input: &'static str, +) -> Result<&'a [Fr], VerifyStage4Error> { + point + .get(point.len().saturating_sub(length)..) + .filter(|suffix| suffix.len() == length) + .ok_or(VerifyStage4Error::InvalidInputLength { + input, + expected: length, + actual: point.len(), + }) +} + +fn normalize_stage4_registers_rw_point( + program: &'static Stage4VerifierProgramPlan, + driver: &'static str, + point: &[F], +) -> Result, VerifyStage4Error> { + let driver_plan = find_plan(program.drivers, driver).ok_or(VerifyStage4Error::MissingProof { + driver, + })?; + if driver_plan.round_schedule.len() != 2 { + return Err(VerifyStage4Error::InvalidProof { + driver, + reason: "stage4 registers point normalization requires [cycle, address] schedule", + }); + } + let cycle_rounds = driver_plan.round_schedule[0]; + let address_rounds = driver_plan.round_schedule[1]; + if point.len() != cycle_rounds + address_rounds { + return Err(VerifyStage4Error::InvalidInputLength { + input: "stage4.registers_read_write.instance", + expected: cycle_rounds + address_rounds, + actual: point.len(), + }); + } + let (cycle, address) = point.split_at(cycle_rounds); + Ok(address + .iter() + .rev() + .copied() + .chain(cycle.iter().rev().copied()) + .collect()) +} + +fn normalize_stage4_registers_rw_cycle_point( + point: &[F], + cycle_rounds: usize, + input: &'static str, +) -> Result, VerifyStage4Error> { + let cycle = point + .get(..cycle_rounds) + .filter(|cycle| cycle.len() == cycle_rounds) + .ok_or(VerifyStage4Error::InvalidInputLength { + input, + expected: cycle_rounds, + actual: point.len(), + })?; + Ok(cycle.iter().rev().copied().collect()) +} diff --git a/crates/jolt-verifier/src/stages/stage5.rs b/crates/jolt-verifier/src/stages/stage5.rs new file mode 100644 index 0000000000..8ff3c55f10 --- /dev/null +++ b/crates/jolt-verifier/src/stages/stage5.rs @@ -0,0 +1,662 @@ +#![allow(dead_code)] + +use super::common::{batch_claims, eval_by_name, find_batch, find_plan, identity_polynomial_eval, indexed_evals_by_prefix, indexed_evals_by_prefix_any, lt_polynomial_eval, normalize_instruction_read_raf_point, operand_polynomial_eval, reverse_slice, suffix_point}; +use jolt_field::{Field, Fr}; +use jolt_lookup_tables::LookupTableKind; +use jolt_poly::EqPolynomial; +use jolt_sumcheck::SumcheckError; +use jolt_transcript::{Blake2bTranscript, LabelWithCount, Transcript}; + +pub type Stage5NamedEval = super::common::StageNamedEval; +pub type Stage5SumcheckOutput = super::common::StageSumcheckOutput; +pub type Stage5ChallengeVector = super::common::StageChallengeVector; +pub type Stage5ExecutionArtifacts = super::common::StageExecutionArtifacts; +pub type Stage5Proof = super::common::StageProof; +pub type Stage5OpeningInputValue = super::common::StageOpeningInputValue; + +pub use super::common::{ + FieldConstantPlan as Stage5FieldConstantPlan, FieldExprPlan as Stage5FieldExprPlan, + KernelPlan as Stage5KernelPlan, OpeningBatchPlan as Stage5OpeningBatchPlan, + OpeningClaimEqualityPlan as Stage5OpeningClaimEqualityPlan, + OpeningClaimPlan as Stage5OpeningClaimPlan, OpeningInputPlan as Stage5OpeningInputPlan, + PointConcatPlan as Stage5PointConcatPlan, PointSlicePlan as Stage5PointSlicePlan, + ProgramStepPlan as Stage5ProgramStepPlan, StageParams as Stage5Params, + StageProgramPlanNoPointZeros as Stage5CpuProgramPlan, + SumcheckBatchPlan as Stage5SumcheckBatchPlan, + SumcheckClaimPlan as Stage5SumcheckClaimPlan, SumcheckDriverPlan as Stage5SumcheckDriverPlan, + SumcheckEvalPlan as Stage5SumcheckEvalPlan, + SumcheckInstanceResultPlan as Stage5SumcheckInstanceResultPlan, + TranscriptAbsorbBytesPlan as Stage5TranscriptAbsorbBytesPlan, + TranscriptSqueezePlan as Stage5TranscriptSqueezePlan, +}; + +pub type DefaultStage5Transcript = Blake2bTranscript; +pub type Stage5VerifierProgramPlan = Stage5CpuProgramPlan; + +#[derive(Debug)] +pub enum VerifyStage5Error { + UnexpectedProofCount { expected: usize, got: usize }, + MissingProof { driver: &'static str }, + MissingBatch { driver: &'static str, batch: &'static str }, + MissingClaim { batch: &'static str, claim: &'static str }, + MissingValue { symbol: &'static str }, + InvalidInputLength { input: &'static str, expected: usize, actual: usize }, + InvalidProof { driver: &'static str, reason: &'static str }, + UnsupportedFieldExpr { symbol: &'static str, formula: &'static str }, + UnsupportedRelation { relation: &'static str }, + Sumcheck { driver: &'static str, error: SumcheckError }, +} + +super::common::impl_runtime_plan_error_conversion!(VerifyStage5Error); + +pub const STAGE5_PARAMS: Stage5Params = Stage5Params { + field: "bn254_fr", + pcs: "dory", + transcript: "blake2b_transcript", +}; +pub const STAGE5_PROGRAM_STEPS: &[Stage5ProgramStepPlan] = &[ + Stage5ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage5.instruction_read_raf.gamma" }, + Stage5ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage5.ram_ra_claim_reduction.gamma" }, + Stage5ProgramStepPlan { kind: "sumcheck_driver", symbol: "stage5.sumcheck" }, +]; + +pub const STAGE5_TRANSCRIPT_SQUEEZES: &[Stage5TranscriptSqueezePlan] = &[ + Stage5TranscriptSqueezePlan { symbol: "stage5.instruction_read_raf.gamma", label: "instruction_read_raf_gamma", kind: "challenge_scalar", count: 1 }, + Stage5TranscriptSqueezePlan { symbol: "stage5.ram_ra_claim_reduction.gamma", label: "ram_ra_claim_reduction_gamma", kind: "challenge_scalar", count: 1 }, +]; + +pub const STAGE5_TRANSCRIPT_ABSORB_BYTES: &[Stage5TranscriptAbsorbBytesPlan] = &[ + +]; + +pub const STAGE5_OPENING_INPUTS: &[Stage5OpeningInputPlan] = &[ + Stage5OpeningInputPlan { symbol: "stage5.input.stage2.instruction.LookupOutput", source_stage: "stage2", source_claim: "stage2.instruction_lookup.claim_reduction.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage5OpeningInputPlan { symbol: "stage5.input.stage2.product_virtual.LookupOutput", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage5OpeningInputPlan { symbol: "stage5.input.stage2.instruction.LeftLookupOperand", source_stage: "stage2", source_claim: "stage2.instruction_lookup.claim_reduction.opening.LeftLookupOperand", oracle: "LeftLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage5OpeningInputPlan { symbol: "stage5.input.stage2.instruction.RightLookupOperand", source_stage: "stage2", source_claim: "stage2.instruction_lookup.claim_reduction.opening.RightLookupOperand", oracle: "RightLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage5OpeningInputPlan { symbol: "stage5.input.stage2.ram_raf.RamRa", source_stage: "stage2", source_claim: "stage2.ram_raf.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual" }, + Stage5OpeningInputPlan { symbol: "stage5.input.stage2.ram_read_write.RamRa", source_stage: "stage2", source_claim: "stage2.ram_read_write.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual" }, + Stage5OpeningInputPlan { symbol: "stage5.input.stage4.ram_val_check.RamRa", source_stage: "stage4", source_claim: "stage4.ram_val_check.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual" }, + Stage5OpeningInputPlan { symbol: "stage5.input.stage4.registers.RegistersVal", source_stage: "stage4", source_claim: "stage4.registers_read_write.opening.RegistersVal", oracle: "RegistersVal", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual" }, +]; + +pub const STAGE5_FIELD_CONSTANTS: &[Stage5FieldConstantPlan] = &[ + +]; + +pub const STAGE5_FIELD_EXPRS: &[Stage5FieldExprPlan] = &[ + Stage5FieldExprPlan { symbol: "stage5.instruction_read_raf.gamma2", kind: "op", formula: "field.pow:2", operands: "stage5.instruction_read_raf.gamma" }, + Stage5FieldExprPlan { symbol: "stage5.instruction_read_raf.term.LeftLookupOperand", kind: "op", formula: "field.mul", operands: "stage5.instruction_read_raf.gamma|stage5.input.stage2.instruction.LeftLookupOperand" }, + Stage5FieldExprPlan { symbol: "stage5.instruction_read_raf.term.RightLookupOperand", kind: "op", formula: "field.mul", operands: "stage5.instruction_read_raf.gamma2|stage5.input.stage2.instruction.RightLookupOperand" }, + Stage5FieldExprPlan { symbol: "stage5.instruction_read_raf.partial.LookupOutputLeftOperand", kind: "op", formula: "field.add", operands: "stage5.input.stage2.instruction.LookupOutput|stage5.instruction_read_raf.term.LeftLookupOperand" }, + Stage5FieldExprPlan { symbol: "stage5.instruction_read_raf.claim_expr", kind: "op", formula: "field.add", operands: "stage5.instruction_read_raf.partial.LookupOutputLeftOperand|stage5.instruction_read_raf.term.RightLookupOperand" }, + Stage5FieldExprPlan { symbol: "stage5.ram_ra_claim_reduction.gamma2", kind: "op", formula: "field.pow:2", operands: "stage5.ram_ra_claim_reduction.gamma" }, + Stage5FieldExprPlan { symbol: "stage5.ram_ra_claim_reduction.term.RamRaReadWrite", kind: "op", formula: "field.mul", operands: "stage5.ram_ra_claim_reduction.gamma|stage5.input.stage2.ram_read_write.RamRa" }, + Stage5FieldExprPlan { symbol: "stage5.ram_ra_claim_reduction.term.RamRaValCheck", kind: "op", formula: "field.mul", operands: "stage5.ram_ra_claim_reduction.gamma2|stage5.input.stage4.ram_val_check.RamRa" }, + Stage5FieldExprPlan { symbol: "stage5.ram_ra_claim_reduction.partial.RafReadWrite", kind: "op", formula: "field.add", operands: "stage5.input.stage2.ram_raf.RamRa|stage5.ram_ra_claim_reduction.term.RamRaReadWrite" }, + Stage5FieldExprPlan { symbol: "stage5.ram_ra_claim_reduction.claim_expr", kind: "op", formula: "field.add", operands: "stage5.ram_ra_claim_reduction.partial.RafReadWrite|stage5.ram_ra_claim_reduction.term.RamRaValCheck" }, +]; +pub const STAGE5_KERNELS: &[Stage5KernelPlan] = &[ + +]; + +pub const STAGE5_SUMCHECK_CLAIMS: &[Stage5SumcheckClaimPlan] = &[ + Stage5SumcheckClaimPlan { symbol: "stage5.instruction_read_raf.input", stage: "stage5", domain: "jolt.stage5_instruction_read_raf_domain", num_rounds: 144, degree: 10, claim: "stage5.instruction_read_raf.weighted_lookup_values", kernel: None, relation: Some("jolt.stage5.instruction_read_raf"), claim_value: "stage5.instruction_read_raf.claim_expr", input_openings: "stage5.input.stage2.instruction.LookupOutput|stage5.input.stage2.instruction.LeftLookupOperand|stage5.input.stage2.instruction.RightLookupOperand" }, + Stage5SumcheckClaimPlan { symbol: "stage5.ram_ra_claim_reduction.input", stage: "stage5", domain: "jolt.trace_domain", num_rounds: 16, degree: 2, claim: "stage5.ram_ra_claim_reduction.weighted_ram_ra", kernel: None, relation: Some("jolt.stage5.ram_ra_claim_reduction"), claim_value: "stage5.ram_ra_claim_reduction.claim_expr", input_openings: "stage5.input.stage2.ram_raf.RamRa|stage5.input.stage2.ram_read_write.RamRa|stage5.input.stage4.ram_val_check.RamRa" }, + Stage5SumcheckClaimPlan { symbol: "stage5.registers_val_evaluation.input", stage: "stage5", domain: "jolt.trace_domain", num_rounds: 16, degree: 3, claim: "stage5.registers_val_evaluation.registers_val", kernel: None, relation: Some("jolt.stage5.registers_val_evaluation"), claim_value: "stage5.input.stage4.registers.RegistersVal", input_openings: "stage5.input.stage4.registers.RegistersVal" }, +]; +pub const STAGE5_SUMCHECK_BATCH_0_ROUND_SCHEDULE: &[usize] = &[ + 128, + 16, +]; + +pub const STAGE5_SUMCHECK_BATCHES: &[Stage5SumcheckBatchPlan] = &[ + Stage5SumcheckBatchPlan { symbol: "stage5.batch", stage: "stage5", proof_slot: "stage5.sumcheck", policy: "jolt_core_stage5_aligned", count: 3, ordered_claims: "stage5.instruction_read_raf.input|stage5.ram_ra_claim_reduction.input|stage5.registers_val_evaluation.input", claim_operands: "stage5.instruction_read_raf.input|stage5.ram_ra_claim_reduction.input|stage5.registers_val_evaluation.input", claim_label: "sumcheck_claim", round_label: "sumcheck_poly", round_schedule: STAGE5_SUMCHECK_BATCH_0_ROUND_SCHEDULE }, +]; +pub const STAGE5_SUMCHECK_DRIVER_0_ROUND_SCHEDULE: &[usize] = &[ + 128, + 16, +]; + +pub const STAGE5_SUMCHECK_DRIVERS: &[Stage5SumcheckDriverPlan] = &[ + Stage5SumcheckDriverPlan { symbol: "stage5.sumcheck", stage: "stage5", proof_slot: "stage5.sumcheck", kernel: None, relation: Some("jolt.stage5.batched"), batch: "stage5.batch", policy: "jolt_core_stage5_aligned", round_schedule: STAGE5_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 144, degree: 10 }, +]; +pub const STAGE5_SUMCHECK_INSTANCE_RESULTS: &[Stage5SumcheckInstanceResultPlan] = &[ + Stage5SumcheckInstanceResultPlan { symbol: "stage5.instruction_read_raf.instance", source: "stage5.sumcheck", claim: "stage5.instruction_read_raf.input", relation: "jolt.stage5.instruction_read_raf", index: 0, point_arity: 144, num_rounds: 144, round_offset: 0, point_order: "instruction_read_raf", degree: 10 }, + Stage5SumcheckInstanceResultPlan { symbol: "stage5.ram_ra_claim_reduction.instance", source: "stage5.sumcheck", claim: "stage5.ram_ra_claim_reduction.input", relation: "jolt.stage5.ram_ra_claim_reduction", index: 1, point_arity: 16, num_rounds: 16, round_offset: 128, point_order: "reverse", degree: 2 }, + Stage5SumcheckInstanceResultPlan { symbol: "stage5.registers_val_evaluation.instance", source: "stage5.sumcheck", claim: "stage5.registers_val_evaluation.input", relation: "jolt.stage5.registers_val_evaluation", index: 2, point_arity: 16, num_rounds: 16, round_offset: 128, point_order: "reverse", degree: 3 }, +]; + +pub const STAGE5_SUMCHECK_EVALS: &[Stage5SumcheckEvalPlan] = &[ + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_0", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_0", index: 0, oracle: "LookupTableFlag_0" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_1", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_1", index: 1, oracle: "LookupTableFlag_1" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_2", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_2", index: 2, oracle: "LookupTableFlag_2" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_3", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_3", index: 3, oracle: "LookupTableFlag_3" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_4", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_4", index: 4, oracle: "LookupTableFlag_4" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_5", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_5", index: 5, oracle: "LookupTableFlag_5" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_6", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_6", index: 6, oracle: "LookupTableFlag_6" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_7", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_7", index: 7, oracle: "LookupTableFlag_7" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_8", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_8", index: 8, oracle: "LookupTableFlag_8" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_9", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_9", index: 9, oracle: "LookupTableFlag_9" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_10", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_10", index: 10, oracle: "LookupTableFlag_10" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_11", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_11", index: 11, oracle: "LookupTableFlag_11" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_12", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_12", index: 12, oracle: "LookupTableFlag_12" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_13", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_13", index: 13, oracle: "LookupTableFlag_13" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_14", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_14", index: 14, oracle: "LookupTableFlag_14" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_15", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_15", index: 15, oracle: "LookupTableFlag_15" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_16", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_16", index: 16, oracle: "LookupTableFlag_16" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_17", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_17", index: 17, oracle: "LookupTableFlag_17" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_18", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_18", index: 18, oracle: "LookupTableFlag_18" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_19", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_19", index: 19, oracle: "LookupTableFlag_19" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_20", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_20", index: 20, oracle: "LookupTableFlag_20" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_21", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_21", index: 21, oracle: "LookupTableFlag_21" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_22", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_22", index: 22, oracle: "LookupTableFlag_22" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_23", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_23", index: 23, oracle: "LookupTableFlag_23" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_24", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_24", index: 24, oracle: "LookupTableFlag_24" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_25", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_25", index: 25, oracle: "LookupTableFlag_25" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_26", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_26", index: 26, oracle: "LookupTableFlag_26" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_27", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_27", index: 27, oracle: "LookupTableFlag_27" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_28", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_28", index: 28, oracle: "LookupTableFlag_28" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_29", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_29", index: 29, oracle: "LookupTableFlag_29" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_30", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_30", index: 30, oracle: "LookupTableFlag_30" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_31", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_31", index: 31, oracle: "LookupTableFlag_31" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_32", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_32", index: 32, oracle: "LookupTableFlag_32" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_33", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_33", index: 33, oracle: "LookupTableFlag_33" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_34", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_34", index: 34, oracle: "LookupTableFlag_34" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_35", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_35", index: 35, oracle: "LookupTableFlag_35" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_36", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_36", index: 36, oracle: "LookupTableFlag_36" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_37", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_37", index: 37, oracle: "LookupTableFlag_37" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_38", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_38", index: 38, oracle: "LookupTableFlag_38" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.LookupTableFlag_39", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.LookupTableFlag_39", index: 39, oracle: "LookupTableFlag_39" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.InstructionRa_0", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.InstructionRa_0", index: 40, oracle: "InstructionRa_0" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.InstructionRa_1", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.InstructionRa_1", index: 41, oracle: "InstructionRa_1" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.InstructionRa_2", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.InstructionRa_2", index: 42, oracle: "InstructionRa_2" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.InstructionRa_3", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.InstructionRa_3", index: 43, oracle: "InstructionRa_3" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.InstructionRa_4", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.InstructionRa_4", index: 44, oracle: "InstructionRa_4" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.InstructionRa_5", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.InstructionRa_5", index: 45, oracle: "InstructionRa_5" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.InstructionRa_6", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.InstructionRa_6", index: 46, oracle: "InstructionRa_6" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.InstructionRa_7", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.InstructionRa_7", index: 47, oracle: "InstructionRa_7" }, + Stage5SumcheckEvalPlan { symbol: "stage5.instruction_read_raf.eval.InstructionRafFlag", source: "stage5.sumcheck", name: "stage5.instruction_read_raf.eval.InstructionRafFlag", index: 48, oracle: "InstructionRafFlag" }, + Stage5SumcheckEvalPlan { symbol: "stage5.ram_ra_claim_reduction.eval.RamRa", source: "stage5.sumcheck", name: "stage5.ram_ra_claim_reduction.eval.RamRa", index: 0, oracle: "RamRa" }, + Stage5SumcheckEvalPlan { symbol: "stage5.registers_val_evaluation.eval.RdInc", source: "stage5.sumcheck", name: "stage5.registers_val_evaluation.eval.RdInc", index: 0, oracle: "RdInc" }, + Stage5SumcheckEvalPlan { symbol: "stage5.registers_val_evaluation.eval.RdWa", source: "stage5.sumcheck", name: "stage5.registers_val_evaluation.eval.RdWa", index: 1, oracle: "RdWa" }, +]; + +pub const STAGE5_POINT_SLICES: &[Stage5PointSlicePlan] = &[ + Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.Cycle", source: "stage5.instruction_read_raf.instance", offset: 128, length: 16, input: "stage5.instruction_read_raf.instance" }, + Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_0.address", source: "stage5.instruction_read_raf.instance", offset: 0, length: 16, input: "stage5.instruction_read_raf.instance" }, + Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_1.address", source: "stage5.instruction_read_raf.instance", offset: 16, length: 16, input: "stage5.instruction_read_raf.instance" }, + Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_2.address", source: "stage5.instruction_read_raf.instance", offset: 32, length: 16, input: "stage5.instruction_read_raf.instance" }, + Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_3.address", source: "stage5.instruction_read_raf.instance", offset: 48, length: 16, input: "stage5.instruction_read_raf.instance" }, + Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_4.address", source: "stage5.instruction_read_raf.instance", offset: 64, length: 16, input: "stage5.instruction_read_raf.instance" }, + Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_5.address", source: "stage5.instruction_read_raf.instance", offset: 80, length: 16, input: "stage5.instruction_read_raf.instance" }, + Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_6.address", source: "stage5.instruction_read_raf.instance", offset: 96, length: 16, input: "stage5.instruction_read_raf.instance" }, + Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_7.address", source: "stage5.instruction_read_raf.instance", offset: 112, length: 16, input: "stage5.instruction_read_raf.instance" }, + Stage5PointSlicePlan { symbol: "stage5.ram_ra_claim_reduction.point.RamAddress", source: "stage5.input.stage2.ram_raf.RamRa", offset: 0, length: 16, input: "stage5.input.stage2.ram_raf.RamRa" }, + Stage5PointSlicePlan { symbol: "stage5.registers_val_evaluation.point.RegisterAddress", source: "stage5.input.stage4.registers.RegistersVal", offset: 0, length: 7, input: "stage5.input.stage4.registers.RegistersVal" }, +]; + +pub const STAGE5_POINT_CONCATS: &[Stage5PointConcatPlan] = &[ + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_0", layout: "address_chunk_then_cycle", arity: 32, inputs: "stage5.instruction_read_raf.point.InstructionRa_0.address|stage5.instruction_read_raf.point.Cycle" }, + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_1", layout: "address_chunk_then_cycle", arity: 32, inputs: "stage5.instruction_read_raf.point.InstructionRa_1.address|stage5.instruction_read_raf.point.Cycle" }, + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_2", layout: "address_chunk_then_cycle", arity: 32, inputs: "stage5.instruction_read_raf.point.InstructionRa_2.address|stage5.instruction_read_raf.point.Cycle" }, + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_3", layout: "address_chunk_then_cycle", arity: 32, inputs: "stage5.instruction_read_raf.point.InstructionRa_3.address|stage5.instruction_read_raf.point.Cycle" }, + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_4", layout: "address_chunk_then_cycle", arity: 32, inputs: "stage5.instruction_read_raf.point.InstructionRa_4.address|stage5.instruction_read_raf.point.Cycle" }, + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_5", layout: "address_chunk_then_cycle", arity: 32, inputs: "stage5.instruction_read_raf.point.InstructionRa_5.address|stage5.instruction_read_raf.point.Cycle" }, + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_6", layout: "address_chunk_then_cycle", arity: 32, inputs: "stage5.instruction_read_raf.point.InstructionRa_6.address|stage5.instruction_read_raf.point.Cycle" }, + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_7", layout: "address_chunk_then_cycle", arity: 32, inputs: "stage5.instruction_read_raf.point.InstructionRa_7.address|stage5.instruction_read_raf.point.Cycle" }, + Stage5PointConcatPlan { symbol: "stage5.ram_ra_claim_reduction.point.RamRa", layout: "address_then_cycle", arity: 32, inputs: "stage5.ram_ra_claim_reduction.point.RamAddress|stage5.ram_ra_claim_reduction.instance" }, + Stage5PointConcatPlan { symbol: "stage5.registers_val_evaluation.point.RdWa", layout: "register_address_then_cycle", arity: 23, inputs: "stage5.registers_val_evaluation.point.RegisterAddress|stage5.registers_val_evaluation.instance" }, +]; +pub const STAGE5_OPENING_CLAIMS: &[Stage5OpeningClaimPlan] = &[ + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_0", oracle: "LookupTableFlag_0", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_0" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_1", oracle: "LookupTableFlag_1", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_1" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_2", oracle: "LookupTableFlag_2", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_2" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_3", oracle: "LookupTableFlag_3", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_3" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_4", oracle: "LookupTableFlag_4", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_4" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_5", oracle: "LookupTableFlag_5", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_5" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_6", oracle: "LookupTableFlag_6", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_6" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_7", oracle: "LookupTableFlag_7", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_7" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_8", oracle: "LookupTableFlag_8", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_8" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_9", oracle: "LookupTableFlag_9", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_9" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_10", oracle: "LookupTableFlag_10", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_10" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_11", oracle: "LookupTableFlag_11", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_11" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_12", oracle: "LookupTableFlag_12", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_12" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_13", oracle: "LookupTableFlag_13", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_13" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_14", oracle: "LookupTableFlag_14", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_14" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_15", oracle: "LookupTableFlag_15", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_15" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_16", oracle: "LookupTableFlag_16", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_16" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_17", oracle: "LookupTableFlag_17", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_17" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_18", oracle: "LookupTableFlag_18", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_18" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_19", oracle: "LookupTableFlag_19", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_19" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_20", oracle: "LookupTableFlag_20", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_20" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_21", oracle: "LookupTableFlag_21", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_21" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_22", oracle: "LookupTableFlag_22", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_22" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_23", oracle: "LookupTableFlag_23", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_23" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_24", oracle: "LookupTableFlag_24", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_24" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_25", oracle: "LookupTableFlag_25", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_25" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_26", oracle: "LookupTableFlag_26", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_26" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_27", oracle: "LookupTableFlag_27", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_27" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_28", oracle: "LookupTableFlag_28", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_28" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_29", oracle: "LookupTableFlag_29", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_29" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_30", oracle: "LookupTableFlag_30", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_30" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_31", oracle: "LookupTableFlag_31", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_31" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_32", oracle: "LookupTableFlag_32", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_32" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_33", oracle: "LookupTableFlag_33", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_33" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_34", oracle: "LookupTableFlag_34", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_34" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_35", oracle: "LookupTableFlag_35", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_35" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_36", oracle: "LookupTableFlag_36", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_36" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_37", oracle: "LookupTableFlag_37", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_37" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_38", oracle: "LookupTableFlag_38", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_38" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_39", oracle: "LookupTableFlag_39", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_39" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_0", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_0" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_1", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_1" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_2", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_2" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_3", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_3" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_4", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_4" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_5", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_5" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_6", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_6" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_7", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_7" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRafFlag", oracle: "InstructionRafFlag", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.InstructionRafFlag" }, + Stage5OpeningClaimPlan { symbol: "stage5.ram_ra_claim_reduction.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.ram_ra_claim_reduction.point.RamRa", eval_source: "stage5.ram_ra_claim_reduction.eval.RamRa" }, + Stage5OpeningClaimPlan { symbol: "stage5.registers_val_evaluation.opening.RdInc", oracle: "RdInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed", point_source: "stage5.registers_val_evaluation.instance", eval_source: "stage5.registers_val_evaluation.eval.RdInc" }, + Stage5OpeningClaimPlan { symbol: "stage5.registers_val_evaluation.opening.RdWa", oracle: "RdWa", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual", point_source: "stage5.registers_val_evaluation.point.RdWa", eval_source: "stage5.registers_val_evaluation.eval.RdWa" }, +]; + +pub const STAGE5_OPENING_EQUALITIES: &[Stage5OpeningClaimEqualityPlan] = &[ + Stage5OpeningClaimEqualityPlan { symbol: "stage5.instruction.lookup_output_claim_consistency", mode: "point_and_eval", lhs: "stage5.input.stage2.instruction.LookupOutput", rhs: "stage5.input.stage2.product_virtual.LookupOutput" }, +]; + +pub const STAGE5_OPENING_BATCHES: &[Stage5OpeningBatchPlan] = &[ + Stage5OpeningBatchPlan { symbol: "stage5.openings", stage: "stage5", proof_slot: "stage5.openings", policy: "jolt_stage5_output_order", count: 52, ordered_claims: "stage5.instruction_read_raf.opening.LookupTableFlag_0|stage5.instruction_read_raf.opening.LookupTableFlag_1|stage5.instruction_read_raf.opening.LookupTableFlag_2|stage5.instruction_read_raf.opening.LookupTableFlag_3|stage5.instruction_read_raf.opening.LookupTableFlag_4|stage5.instruction_read_raf.opening.LookupTableFlag_5|stage5.instruction_read_raf.opening.LookupTableFlag_6|stage5.instruction_read_raf.opening.LookupTableFlag_7|stage5.instruction_read_raf.opening.LookupTableFlag_8|stage5.instruction_read_raf.opening.LookupTableFlag_9|stage5.instruction_read_raf.opening.LookupTableFlag_10|stage5.instruction_read_raf.opening.LookupTableFlag_11|stage5.instruction_read_raf.opening.LookupTableFlag_12|stage5.instruction_read_raf.opening.LookupTableFlag_13|stage5.instruction_read_raf.opening.LookupTableFlag_14|stage5.instruction_read_raf.opening.LookupTableFlag_15|stage5.instruction_read_raf.opening.LookupTableFlag_16|stage5.instruction_read_raf.opening.LookupTableFlag_17|stage5.instruction_read_raf.opening.LookupTableFlag_18|stage5.instruction_read_raf.opening.LookupTableFlag_19|stage5.instruction_read_raf.opening.LookupTableFlag_20|stage5.instruction_read_raf.opening.LookupTableFlag_21|stage5.instruction_read_raf.opening.LookupTableFlag_22|stage5.instruction_read_raf.opening.LookupTableFlag_23|stage5.instruction_read_raf.opening.LookupTableFlag_24|stage5.instruction_read_raf.opening.LookupTableFlag_25|stage5.instruction_read_raf.opening.LookupTableFlag_26|stage5.instruction_read_raf.opening.LookupTableFlag_27|stage5.instruction_read_raf.opening.LookupTableFlag_28|stage5.instruction_read_raf.opening.LookupTableFlag_29|stage5.instruction_read_raf.opening.LookupTableFlag_30|stage5.instruction_read_raf.opening.LookupTableFlag_31|stage5.instruction_read_raf.opening.LookupTableFlag_32|stage5.instruction_read_raf.opening.LookupTableFlag_33|stage5.instruction_read_raf.opening.LookupTableFlag_34|stage5.instruction_read_raf.opening.LookupTableFlag_35|stage5.instruction_read_raf.opening.LookupTableFlag_36|stage5.instruction_read_raf.opening.LookupTableFlag_37|stage5.instruction_read_raf.opening.LookupTableFlag_38|stage5.instruction_read_raf.opening.LookupTableFlag_39|stage5.instruction_read_raf.opening.InstructionRa_0|stage5.instruction_read_raf.opening.InstructionRa_1|stage5.instruction_read_raf.opening.InstructionRa_2|stage5.instruction_read_raf.opening.InstructionRa_3|stage5.instruction_read_raf.opening.InstructionRa_4|stage5.instruction_read_raf.opening.InstructionRa_5|stage5.instruction_read_raf.opening.InstructionRa_6|stage5.instruction_read_raf.opening.InstructionRa_7|stage5.instruction_read_raf.opening.InstructionRafFlag|stage5.ram_ra_claim_reduction.opening.RamRa|stage5.registers_val_evaluation.opening.RdInc|stage5.registers_val_evaluation.opening.RdWa", claim_operands: "stage5.instruction_read_raf.opening.LookupTableFlag_0|stage5.instruction_read_raf.opening.LookupTableFlag_1|stage5.instruction_read_raf.opening.LookupTableFlag_2|stage5.instruction_read_raf.opening.LookupTableFlag_3|stage5.instruction_read_raf.opening.LookupTableFlag_4|stage5.instruction_read_raf.opening.LookupTableFlag_5|stage5.instruction_read_raf.opening.LookupTableFlag_6|stage5.instruction_read_raf.opening.LookupTableFlag_7|stage5.instruction_read_raf.opening.LookupTableFlag_8|stage5.instruction_read_raf.opening.LookupTableFlag_9|stage5.instruction_read_raf.opening.LookupTableFlag_10|stage5.instruction_read_raf.opening.LookupTableFlag_11|stage5.instruction_read_raf.opening.LookupTableFlag_12|stage5.instruction_read_raf.opening.LookupTableFlag_13|stage5.instruction_read_raf.opening.LookupTableFlag_14|stage5.instruction_read_raf.opening.LookupTableFlag_15|stage5.instruction_read_raf.opening.LookupTableFlag_16|stage5.instruction_read_raf.opening.LookupTableFlag_17|stage5.instruction_read_raf.opening.LookupTableFlag_18|stage5.instruction_read_raf.opening.LookupTableFlag_19|stage5.instruction_read_raf.opening.LookupTableFlag_20|stage5.instruction_read_raf.opening.LookupTableFlag_21|stage5.instruction_read_raf.opening.LookupTableFlag_22|stage5.instruction_read_raf.opening.LookupTableFlag_23|stage5.instruction_read_raf.opening.LookupTableFlag_24|stage5.instruction_read_raf.opening.LookupTableFlag_25|stage5.instruction_read_raf.opening.LookupTableFlag_26|stage5.instruction_read_raf.opening.LookupTableFlag_27|stage5.instruction_read_raf.opening.LookupTableFlag_28|stage5.instruction_read_raf.opening.LookupTableFlag_29|stage5.instruction_read_raf.opening.LookupTableFlag_30|stage5.instruction_read_raf.opening.LookupTableFlag_31|stage5.instruction_read_raf.opening.LookupTableFlag_32|stage5.instruction_read_raf.opening.LookupTableFlag_33|stage5.instruction_read_raf.opening.LookupTableFlag_34|stage5.instruction_read_raf.opening.LookupTableFlag_35|stage5.instruction_read_raf.opening.LookupTableFlag_36|stage5.instruction_read_raf.opening.LookupTableFlag_37|stage5.instruction_read_raf.opening.LookupTableFlag_38|stage5.instruction_read_raf.opening.LookupTableFlag_39|stage5.instruction_read_raf.opening.InstructionRa_0|stage5.instruction_read_raf.opening.InstructionRa_1|stage5.instruction_read_raf.opening.InstructionRa_2|stage5.instruction_read_raf.opening.InstructionRa_3|stage5.instruction_read_raf.opening.InstructionRa_4|stage5.instruction_read_raf.opening.InstructionRa_5|stage5.instruction_read_raf.opening.InstructionRa_6|stage5.instruction_read_raf.opening.InstructionRa_7|stage5.instruction_read_raf.opening.InstructionRafFlag|stage5.ram_ra_claim_reduction.opening.RamRa|stage5.registers_val_evaluation.opening.RdInc|stage5.registers_val_evaluation.opening.RdWa" }, +]; +pub const STAGE5_PROGRAM: Stage5VerifierProgramPlan = Stage5CpuProgramPlan { + role: "verifier", + params: STAGE5_PARAMS, + steps: STAGE5_PROGRAM_STEPS, + transcript_squeezes: STAGE5_TRANSCRIPT_SQUEEZES, + transcript_absorb_bytes: STAGE5_TRANSCRIPT_ABSORB_BYTES, + opening_inputs: STAGE5_OPENING_INPUTS, + field_constants: STAGE5_FIELD_CONSTANTS, + field_exprs: STAGE5_FIELD_EXPRS, + kernels: STAGE5_KERNELS, + claims: STAGE5_SUMCHECK_CLAIMS, + batches: STAGE5_SUMCHECK_BATCHES, + drivers: STAGE5_SUMCHECK_DRIVERS, + instance_results: STAGE5_SUMCHECK_INSTANCE_RESULTS, + evals: STAGE5_SUMCHECK_EVALS, + point_slices: STAGE5_POINT_SLICES, + point_concats: STAGE5_POINT_CONCATS, + opening_claims: STAGE5_OPENING_CLAIMS, + opening_equalities: STAGE5_OPENING_EQUALITIES, + opening_batches: STAGE5_OPENING_BATCHES, +}; + +pub fn verify_stage5( + proof: &Stage5Proof, + opening_inputs: &[Stage5OpeningInputValue], + transcript: &mut T, +) -> Result, VerifyStage5Error> +where + T: Transcript, +{ + verify_stage5_with_program(&STAGE5_PROGRAM, proof, opening_inputs, transcript) +} + +pub fn verify_stage5_with_program( + program: &'static Stage5VerifierProgramPlan, + proof: &Stage5Proof, + opening_inputs: &[Stage5OpeningInputValue], + transcript: &mut T, +) -> Result, VerifyStage5Error> +where + T: Transcript, +{ + if proof.sumchecks.len() != program.drivers.len() { + return Err(VerifyStage5Error::UnexpectedProofCount { + expected: program.drivers.len(), + got: proof.sumchecks.len(), + }); + } + let mut store = + super::common::ValueStore::with_opening_inputs(opening_inputs, program.opening_inputs)?; + store.seed_constants(program.field_constants); + let mut artifacts = Stage5ExecutionArtifacts::default(); + for step in program.steps { + match step.kind { + "transcript_squeeze" => { + let squeeze = + find_plan(program.transcript_squeezes, step.symbol).ok_or(VerifyStage5Error::MissingValue { + symbol: step.symbol, + })?; + verify_stage5_squeeze(program, squeeze, &mut store, transcript, &mut artifacts)?; + } + "transcript_absorb_bytes" => { + let absorb = find_plan(program.transcript_absorb_bytes, step.symbol).ok_or( + VerifyStage5Error::MissingValue { + symbol: step.symbol, + }, + )?; + absorb_stage5_bytes(absorb, transcript); + } + "sumcheck_driver" => { + let driver = + find_plan(program.drivers, step.symbol).ok_or(VerifyStage5Error::MissingProof { + driver: step.symbol, + })?; + verify_stage5_driver(program, driver, proof, &mut store, transcript, &mut artifacts)?; + } + _ => { + return Err(VerifyStage5Error::InvalidProof { + driver: step.symbol, + reason: "unsupported stage5 program step", + }); + } + } + } + artifacts + .opening_batches + .extend(program.opening_batches.iter()); + Ok(artifacts) +} + +pub fn stage5_verifier_program() -> &'static Stage5VerifierProgramPlan { + &STAGE5_PROGRAM +} + +fn verify_stage5_squeeze( + program: &'static Stage5VerifierProgramPlan, + squeeze: &'static Stage5TranscriptSqueezePlan, + store: &mut super::common::ValueStore, + transcript: &mut T, + artifacts: &mut Stage5ExecutionArtifacts, +) -> Result<(), VerifyStage5Error> +where + T: Transcript, +{ + let values = transcript.challenge_vector(squeeze.count); + store.observe_challenge_vector(squeeze, &values, |input, expected, actual| { + VerifyStage5Error::InvalidInputLength { + input, + expected, + actual, + } + })?; + store + .evaluate_available_field_exprs(program.field_exprs, super::common::evaluate_field_expr) + .map_err(VerifyStage5Error::from)?; + artifacts.challenge_vectors.push(Stage5ChallengeVector { + symbol: squeeze.symbol, + values, + }); + Ok(()) +} + +fn absorb_stage5_bytes(absorb: &'static Stage5TranscriptAbsorbBytesPlan, transcript: &mut T) +where + T: Transcript, +{ + transcript.append(&LabelWithCount( + absorb.label.as_bytes(), + absorb.payload.len() as u64, + )); + transcript.append_bytes(absorb.payload.as_bytes()); +} + +fn verify_stage5_driver( + program: &'static Stage5VerifierProgramPlan, + driver: &'static Stage5SumcheckDriverPlan, + proof: &Stage5Proof, + store: &mut super::common::ValueStore, + transcript: &mut T, + artifacts: &mut Stage5ExecutionArtifacts, +) -> Result<(), VerifyStage5Error> +where + T: Transcript, +{ + let proof = proof + .sumchecks + .get(artifacts.sumchecks.len()) + .ok_or(VerifyStage5Error::MissingProof { + driver: driver.symbol, + })?; + let relation = driver.relation.unwrap_or(""); + let output = match relation { + "jolt.stage5.batched" => { + verify_batched_stage5(program, driver, proof, store, transcript)? + } + _ => return Err(VerifyStage5Error::UnsupportedRelation { relation }), + }; + artifacts.sumchecks.push(output); + Ok(()) +} + +fn verify_batched_stage5( + program: &'static Stage5VerifierProgramPlan, + driver: &'static Stage5SumcheckDriverPlan, + proof: &Stage5SumcheckOutput, + store: &mut super::common::ValueStore, + transcript: &mut T, +) -> Result, VerifyStage5Error> +where + T: Transcript, +{ + super::common::verify_batched_sumcheck( + driver, + proof, + program.claims, + program.batches, + program.field_exprs, + program.opening_inputs, + program.opening_claims, + program.opening_batches, + store, + transcript, + |store, evals, point, batching_coeffs| { + expected_batched_output_claim(program, driver, store, evals, point, batching_coeffs) + }, + |store, verified| observe_stage5_sumcheck_output(program, store, verified), + |driver, error| VerifyStage5Error::Sumcheck { driver, error }, + ) +} + +fn observe_stage5_sumcheck_output( + program: &'static Stage5VerifierProgramPlan, + store: &mut super::common::ValueStore, + output: &Stage5SumcheckOutput, +) -> Result<(), VerifyStage5Error> { + store.observe_sumcheck_output( + program.instance_results, + program.evals, + output, + |instance, mut point| { + match instance.point_order { + "as_is" => {} + "reverse" => point.reverse(), + "instruction_read_raf" => { + point = normalize_instruction_read_raf_point(&point, "stage5.instruction_read_raf.point")?; + } + _ => { + return Err(VerifyStage5Error::InvalidProof { + driver: output.driver, + reason: "unsupported point order", + }); + } + } + Ok(point) + }, + |input, expected, actual| VerifyStage5Error::InvalidInputLength { + input, + expected, + actual, + }, + |symbol| VerifyStage5Error::MissingValue { symbol }, + )?; + store.evaluate_available_points( + program.point_slices, + program.point_concats, + |input, expected, actual| VerifyStage5Error::InvalidInputLength { + input, + expected, + actual, + }, + )?; + store + .evaluate_available_field_exprs(program.field_exprs, super::common::evaluate_field_expr) + .map_err(VerifyStage5Error::from)?; + store.verify_opening_equalities( + program.opening_equalities, + |driver, reason| VerifyStage5Error::InvalidProof { driver, reason }, + |symbol| VerifyStage5Error::MissingValue { symbol }, + ) +} + +fn expected_batched_output_claim( + program: &'static Stage5VerifierProgramPlan, + driver: &'static Stage5SumcheckDriverPlan, + store: &super::common::ValueStore, + evals: &[Stage5NamedEval], + point: &[Fr], + batching_coeffs: &[Fr], +) -> Result { + let batch = find_batch(program.batches, driver.symbol, driver.batch)?; + let claims = batch_claims(program.claims, batch)?; + let mut expected = Fr::from_u64(0); + for (claim, coefficient) in claims.iter().zip(batching_coeffs) { + let instance = program + .instance_results + .iter() + .find(|instance| instance.claim == claim.symbol && instance.source == driver.symbol) + .ok_or(VerifyStage5Error::MissingClaim { + batch: batch.symbol, + claim: claim.symbol, + })?; + let local_point = point + .get(instance.round_offset..instance.round_offset + instance.num_rounds) + .ok_or(VerifyStage5Error::InvalidInputLength { + input: instance.symbol, + expected: instance.round_offset + instance.num_rounds, + actual: point.len(), + })?; + let relation = claim.relation.unwrap_or(""); + let value = match relation { + "jolt.stage5.instruction_read_raf" => { + expected_instruction_read_raf(store, evals, local_point)? + } + "jolt.stage5.ram_ra_claim_reduction" => { + expected_ram_ra_claim_reduction(store, evals, local_point)? + } + "jolt.stage5.registers_val_evaluation" => { + expected_registers_val_evaluation(store, evals, local_point)? + } + _ => return Err(VerifyStage5Error::UnsupportedRelation { relation }), + }; + expected += *coefficient * value; + } + Ok(expected) +} + +fn expected_instruction_read_raf( + store: &super::common::ValueStore, + evals: &[Stage5NamedEval], + local_point: &[Fr], +) -> Result { + const LOG_K: usize = 128; + const XLEN: usize = 64; + + if local_point.len() < LOG_K { + return Err(VerifyStage5Error::InvalidInputLength { + input: "stage5.instruction_read_raf.point", + expected: LOG_K, + actual: local_point.len(), + }); + } + + let (r_address_prime, r_cycle) = local_point.split_at(LOG_K); + let r_cycle_prime = reverse_slice(r_cycle); + let r_reduction = super::common::store_point(store, "stage5.input.stage2.instruction.LookupOutput")?; + let eq_eval_r_reduction = EqPolynomial::::mle(r_reduction, &r_cycle_prime); + + let left_operand_eval = operand_polynomial_eval(r_address_prime, true); + let right_operand_eval = operand_polynomial_eval(r_address_prime, false); + let identity_poly_eval = identity_polynomial_eval(r_address_prime); + + let table_values = LookupTableKind::::all() + .iter() + .map(|table| table.evaluate_mle::(r_address_prime)) + .collect::>(); + let table_flag_claims = indexed_evals_by_prefix( + evals, + "stage5.instruction_read_raf.eval.LookupTableFlag_", + table_values.len(), + )?; + let val_claim = table_values + .into_iter() + .zip(table_flag_claims) + .map(|(table_value, flag_claim)| table_value * flag_claim) + .sum::(); + + let ra_claim = indexed_evals_by_prefix_any( + evals, + "stage5.instruction_read_raf.eval.InstructionRa_", + )? + .into_iter() + .product::(); + let raf_flag_claim = eval_by_name( + evals, + "stage5.instruction_read_raf.eval.InstructionRafFlag", + )?; + let gamma = super::common::store_scalar(store, "stage5.instruction_read_raf.gamma")?; + + let raf_claim = (Fr::from_u64(1) - raf_flag_claim) + * (left_operand_eval + gamma * right_operand_eval) + + raf_flag_claim * gamma * identity_poly_eval; + Ok(eq_eval_r_reduction * ra_claim * (val_claim + gamma * raf_claim)) +} + +fn expected_ram_ra_claim_reduction( + store: &super::common::ValueStore, + evals: &[Stage5NamedEval], + local_point: &[Fr], +) -> Result { + let r_cycle_reduced = reverse_slice(local_point); + let r_cycle_raf = suffix_point( + super::common::store_point(store, "stage5.input.stage2.ram_raf.RamRa")?, + r_cycle_reduced.len(), + "stage5.input.stage2.ram_raf.RamRa", + )?; + let r_cycle_rw = suffix_point( + super::common::store_point(store, "stage5.input.stage2.ram_read_write.RamRa")?, + r_cycle_reduced.len(), + "stage5.input.stage2.ram_read_write.RamRa", + )?; + let r_cycle_val = suffix_point( + super::common::store_point(store, "stage5.input.stage4.ram_val_check.RamRa")?, + r_cycle_reduced.len(), + "stage5.input.stage4.ram_val_check.RamRa", + )?; + let gamma = super::common::store_scalar(store, "stage5.ram_ra_claim_reduction.gamma")?; + let eq_combined = EqPolynomial::::mle(r_cycle_raf, &r_cycle_reduced) + + gamma * EqPolynomial::::mle(r_cycle_rw, &r_cycle_reduced) + + gamma.square() * EqPolynomial::::mle(r_cycle_val, &r_cycle_reduced); + let ram_ra = eval_by_name(evals, "stage5.ram_ra_claim_reduction.eval.RamRa")?; + Ok(eq_combined * ram_ra) +} + +fn expected_registers_val_evaluation( + store: &super::common::ValueStore, + evals: &[Stage5NamedEval], + local_point: &[Fr], +) -> Result { + let registers_val_point = super::common::store_point(store, "stage5.input.stage4.registers.RegistersVal")?; + let r_cycle = suffix_point( + registers_val_point, + local_point.len(), + "stage5.input.stage4.registers.RegistersVal", + )?; + let r_reduced = reverse_slice(local_point); + let lt_eval = lt_polynomial_eval(&r_reduced, r_cycle); + let rd_inc = eval_by_name(evals, "stage5.registers_val_evaluation.eval.RdInc")?; + let rd_wa = eval_by_name(evals, "stage5.registers_val_evaluation.eval.RdWa")?; + Ok(rd_inc * rd_wa * lt_eval) +} diff --git a/crates/jolt-verifier/src/stages/stage6.rs b/crates/jolt-verifier/src/stages/stage6.rs new file mode 100644 index 0000000000..c2a507525a --- /dev/null +++ b/crates/jolt-verifier/src/stages/stage6.rs @@ -0,0 +1,987 @@ +#![allow(dead_code)] + +use super::common::{batch_claims, expected_stage67_booleanity, expected_stage67_bytecode_read_raf, expected_stage67_hamming_booleanity, expected_stage67_inc_claim_reduction, expected_stage67_instruction_ra_virtual, expected_stage67_ram_ra_virtual, find_batch, find_plan, normalize_bytecode_read_raf_point, normalize_instruction_read_raf_point, stage67_trace_rounds, Stage67BytecodeEntry, Stage67BytecodeSymbols, Stage67RelationSymbols}; +use jolt_field::{Field, Fr}; +use jolt_sumcheck::SumcheckError; +use jolt_transcript::{Blake2bTranscript, LabelWithCount, Transcript}; + +pub type Stage6NamedEval = super::common::StageNamedEval; +pub type Stage6SumcheckOutput = super::common::StageSumcheckOutput; +pub type Stage6ChallengeVector = super::common::StageChallengeVector; +pub type Stage6ExecutionArtifacts = super::common::StageExecutionArtifacts; +pub type Stage6Proof = super::common::StageProof; +pub type Stage6OpeningInputValue = super::common::StageOpeningInputValue; + +pub use super::common::{ + FieldConstantPlan as Stage6FieldConstantPlan, FieldExprPlan as Stage6FieldExprPlan, + KernelPlan as Stage6KernelPlan, OpeningBatchPlan as Stage6OpeningBatchPlan, + OpeningClaimEqualityPlan as Stage6OpeningClaimEqualityPlan, + OpeningClaimPlan as Stage6OpeningClaimPlan, OpeningInputPlan as Stage6OpeningInputPlan, + PointConcatPlan as Stage6PointConcatPlan, PointSlicePlan as Stage6PointSlicePlan, + PointZeroPlan as Stage6PointZeroPlan, ProgramStepPlan as Stage6ProgramStepPlan, + StageParams as Stage6Params, StageProgramPlan as Stage6CpuProgramPlan, + SumcheckBatchPlan as Stage6SumcheckBatchPlan, + SumcheckClaimPlan as Stage6SumcheckClaimPlan, SumcheckDriverPlan as Stage6SumcheckDriverPlan, + SumcheckEvalPlan as Stage6SumcheckEvalPlan, + SumcheckInstanceResultPlan as Stage6SumcheckInstanceResultPlan, + TranscriptAbsorbBytesPlan as Stage6TranscriptAbsorbBytesPlan, + TranscriptSqueezePlan as Stage6TranscriptSqueezePlan, +}; + +pub type DefaultStage6Transcript = Blake2bTranscript; +pub type Stage6VerifierProgramPlan = Stage6CpuProgramPlan; + +#[derive(Clone, Debug)] +pub struct Stage6BytecodeEntry { + pub address: Fr, + pub imm: Fr, + pub circuit_flags: [bool; 14], + pub rd: Option, + pub rs1: Option, + pub rs2: Option, + pub lookup_table: Option, + pub is_interleaved: bool, + pub is_branch: bool, + pub left_is_rs1: bool, + pub left_is_pc: bool, + pub right_is_rs2: bool, + pub right_is_imm: bool, + pub is_noop: bool, +} + +impl Stage67BytecodeEntry for Stage6BytecodeEntry { + fn address(&self) -> Fr { self.address } + fn imm(&self) -> Fr { self.imm } + fn circuit_flags(&self) -> &[bool; 14] { &self.circuit_flags } + fn rd(&self) -> Option { self.rd } + fn rs1(&self) -> Option { self.rs1 } + fn rs2(&self) -> Option { self.rs2 } + fn lookup_table(&self) -> Option { self.lookup_table } + fn is_interleaved(&self) -> bool { self.is_interleaved } + fn is_branch(&self) -> bool { self.is_branch } + fn left_is_rs1(&self) -> bool { self.left_is_rs1 } + fn left_is_pc(&self) -> bool { self.left_is_pc } + fn right_is_rs2(&self) -> bool { self.right_is_rs2 } + fn right_is_imm(&self) -> bool { self.right_is_imm } + fn is_noop(&self) -> bool { self.is_noop } +} + + +#[derive(Clone, Debug)] +pub struct Stage6BytecodeReadRafData { + pub entries: Vec, + pub entry_bytecode_index: usize, + pub num_lookup_tables: usize, +} + +#[derive(Clone, Debug)] +pub struct Stage6VerifierData { + pub bytecode_read_raf: Option, +} + +const STAGE6_RELATION_SYMBOLS: Stage67RelationSymbols = Stage67RelationSymbols { + hamming_booleanity_relation: "jolt.stage6.hamming_booleanity", + hamming_booleanity_instance: "stage6.hamming_booleanity.instance", + booleanity_point: "stage6.booleanity.point", + stage5_instruction_ra0: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", + booleanity_combined_point: "stage6.booleanity.combined_point", + booleanity_gamma: "stage6.booleanity.gamma", + booleanity_instruction_ra_prefix: "stage6.booleanity.eval.InstructionRa_", + booleanity_bytecode_ra_prefix: "stage6.booleanity.eval.BytecodeRa_", + booleanity_ram_ra_prefix: "stage6.booleanity.eval.RamRa_", + hamming_weight_eval: "stage6.hamming_booleanity.eval.HammingWeight", + hamming_lookup_output: "stage6.input.stage1.LookupOutput", + ram_ra_virtual_cycle: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", + ram_ra_virtual_eval_prefix: "stage6.ram_ra_virtual.eval.RamRa_", + instruction_ra_virtual_cycle: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", + instruction_ra_virtual_eval_prefix: "stage6.instruction_ra_virtual.eval.InstructionRa_", + instruction_ra_virtual_input_prefix: "stage6.input.stage5.instruction_read_raf.InstructionRa_", + instruction_ra_virtual_gamma: "stage6.instruction_ra_virtual.gamma", + inc_ram_stage2: "stage6.input.stage2.ram_read_write.RamInc", + inc_ram_stage4: "stage6.input.stage4.ram_val_check.RamInc", + inc_rd_stage4: "stage6.input.stage4.registers_read_write.RdInc", + inc_rd_stage5: "stage6.input.stage5.registers_val_evaluation.RdInc", + inc_gamma: "stage6.inc_claim_reduction.gamma", + inc_ram_eval: "stage6.inc_claim_reduction.eval.RamInc", + inc_rd_eval: "stage6.inc_claim_reduction.eval.RdInc", +}; + +const STAGE6_BYTECODE_SYMBOLS: Stage67BytecodeSymbols = Stage67BytecodeSymbols { + point: "stage6.bytecode_read_raf.point", + gamma: "stage6.bytecode_read_raf.gamma", + bytecode_ra_eval_prefix: "stage6.bytecode_read_raf.eval.BytecodeRa_", + entries: "stage6.bytecode_read_raf.entries", + entry_bytecode_index: "stage6.bytecode_read_raf.entry_bytecode_index", + stage_gammas: [ + "stage6.bytecode_read_raf.stage1_gamma", + "stage6.bytecode_read_raf.stage2_gamma", + "stage6.bytecode_read_raf.stage3_gamma", + "stage6.bytecode_read_raf.stage4_gamma", + "stage6.bytecode_read_raf.stage5_gamma", + ], + stage_cycle_points: [ + "stage6.input.stage1.Imm", + "stage6.input.stage2.OpFlagJump", + "stage6.input.stage3.spartan_shift.UnexpandedPC", + "stage6.input.stage4.Rs1Ra", + "stage6.input.stage5.registers_val_evaluation.RdWa", + ], + stage4_register_point: "stage6.input.stage4.Rs1Ra", + stage5_register_point: "stage6.input.stage5.registers_val_evaluation.RdWa", + entry_rd: "stage6.bytecode.entry.rd", + entry_rs1: "stage6.bytecode.entry.rs1", + entry_rs2: "stage6.bytecode.entry.rs2", + entry_lookup_table: "stage6.bytecode.entry.lookup_table", +}; + +#[derive(Debug)] +pub enum VerifyStage6Error { + UnexpectedProofCount { expected: usize, got: usize }, + MissingProof { driver: &'static str }, + MissingBatch { driver: &'static str, batch: &'static str }, + MissingClaim { batch: &'static str, claim: &'static str }, + MissingValue { symbol: &'static str }, + InvalidInputLength { input: &'static str, expected: usize, actual: usize }, + InvalidProof { driver: &'static str, reason: &'static str }, + UnsupportedFieldExpr { symbol: &'static str, formula: &'static str }, + UnsupportedRelation { relation: &'static str }, + Sumcheck { driver: &'static str, error: SumcheckError }, +} + +super::common::impl_runtime_plan_error_conversion!(VerifyStage6Error); + +pub const STAGE6_PARAMS: Stage6Params = Stage6Params { + field: "bn254_fr", + pcs: "dory", + transcript: "blake2b_transcript", +}; +pub const STAGE6_PROGRAM_STEPS: &[Stage6ProgramStepPlan] = &[ + Stage6ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage6.bytecode_read_raf.gamma" }, + Stage6ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage6.bytecode_read_raf.stage1_gamma" }, + Stage6ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage6.bytecode_read_raf.stage2_gamma" }, + Stage6ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage6.bytecode_read_raf.stage3_gamma" }, + Stage6ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage6.bytecode_read_raf.stage4_gamma" }, + Stage6ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage6.bytecode_read_raf.stage5_gamma" }, + Stage6ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage6.booleanity.gamma" }, + Stage6ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage6.instruction_ra_virtual.gamma" }, + Stage6ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage6.inc_claim_reduction.gamma" }, + Stage6ProgramStepPlan { kind: "sumcheck_driver", symbol: "stage6.sumcheck" }, +]; + +pub const STAGE6_TRANSCRIPT_SQUEEZES: &[Stage6TranscriptSqueezePlan] = &[ + Stage6TranscriptSqueezePlan { symbol: "stage6.bytecode_read_raf.gamma", label: "bc_raf_gamma", kind: "challenge_scalar", count: 1 }, + Stage6TranscriptSqueezePlan { symbol: "stage6.bytecode_read_raf.stage1_gamma", label: "bc_raf_stage1_gamma", kind: "challenge_scalar", count: 1 }, + Stage6TranscriptSqueezePlan { symbol: "stage6.bytecode_read_raf.stage2_gamma", label: "bc_raf_stage2_gamma", kind: "challenge_scalar", count: 1 }, + Stage6TranscriptSqueezePlan { symbol: "stage6.bytecode_read_raf.stage3_gamma", label: "bc_raf_stage3_gamma", kind: "challenge_scalar", count: 1 }, + Stage6TranscriptSqueezePlan { symbol: "stage6.bytecode_read_raf.stage4_gamma", label: "bc_raf_stage4_gamma", kind: "challenge_scalar", count: 1 }, + Stage6TranscriptSqueezePlan { symbol: "stage6.bytecode_read_raf.stage5_gamma", label: "bc_raf_stage5_gamma", kind: "challenge_scalar", count: 1 }, + Stage6TranscriptSqueezePlan { symbol: "stage6.booleanity.gamma", label: "booleanity_gamma", kind: "challenge_scalar", count: 1 }, + Stage6TranscriptSqueezePlan { symbol: "stage6.instruction_ra_virtual.gamma", label: "inst_ra_virtual_gamma", kind: "challenge_scalar", count: 1 }, + Stage6TranscriptSqueezePlan { symbol: "stage6.inc_claim_reduction.gamma", label: "inc_reduction_gamma", kind: "challenge_scalar", count: 1 }, +]; + +pub const STAGE6_TRANSCRIPT_ABSORB_BYTES: &[Stage6TranscriptAbsorbBytesPlan] = &[ + +]; + +pub const STAGE6_OPENING_INPUTS: &[Stage6OpeningInputPlan] = &[ + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.UnexpandedPC", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.UnexpandedPC", oracle: "UnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.Imm", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.Imm", oracle: "Imm", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagAddOperands", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagAddOperands", oracle: "OpFlagAddOperands", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagSubtractOperands", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagSubtractOperands", oracle: "OpFlagSubtractOperands", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagMultiplyOperands", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagMultiplyOperands", oracle: "OpFlagMultiplyOperands", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagLoad", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagLoad", oracle: "OpFlagLoad", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagStore", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagStore", oracle: "OpFlagStore", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagJump", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagJump", oracle: "OpFlagJump", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagWriteLookupOutputToRD", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagWriteLookupOutputToRD", oracle: "OpFlagWriteLookupOutputToRD", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagVirtualInstruction", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagAssert", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagAssert", oracle: "OpFlagAssert", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagDoNotUpdateUnexpandedPC", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagDoNotUpdateUnexpandedPC", oracle: "OpFlagDoNotUpdateUnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagAdvice", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagAdvice", oracle: "OpFlagAdvice", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagIsCompressed", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagIsCompressed", oracle: "OpFlagIsCompressed", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagIsFirstInSequence", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagIsFirstInSequence", oracle: "OpFlagIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagIsLastInSequence", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagIsLastInSequence", oracle: "OpFlagIsLastInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage2.OpFlagJump", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.OpFlagJump", oracle: "OpFlagJump", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage2.InstructionFlagBranch", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.InstructionFlagBranch", oracle: "InstructionFlagBranch", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage2.OpFlagWriteLookupOutputToRD", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.OpFlagWriteLookupOutputToRD", oracle: "OpFlagWriteLookupOutputToRD", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage2.OpFlagVirtualInstruction", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.instruction_input.Imm", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.Imm", oracle: "Imm", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.spartan_shift.UnexpandedPC", source_stage: "stage3", source_claim: "stage3.spartan_shift.opening.UnexpandedPC", oracle: "UnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.instruction_input.InstructionFlagLeftOperandIsRs1Value", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.InstructionFlagLeftOperandIsRs1Value", oracle: "InstructionFlagLeftOperandIsRs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.instruction_input.InstructionFlagLeftOperandIsPC", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.InstructionFlagLeftOperandIsPC", oracle: "InstructionFlagLeftOperandIsPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.instruction_input.InstructionFlagRightOperandIsRs2Value", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.InstructionFlagRightOperandIsRs2Value", oracle: "InstructionFlagRightOperandIsRs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.instruction_input.InstructionFlagRightOperandIsImm", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.InstructionFlagRightOperandIsImm", oracle: "InstructionFlagRightOperandIsImm", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.spartan_shift.InstructionFlagIsNoop", source_stage: "stage3", source_claim: "stage3.spartan_shift.opening.InstructionFlagIsNoop", oracle: "InstructionFlagIsNoop", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.spartan_shift.OpFlagVirtualInstruction", source_stage: "stage3", source_claim: "stage3.spartan_shift.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.spartan_shift.OpFlagIsFirstInSequence", source_stage: "stage3", source_claim: "stage3.spartan_shift.opening.OpFlagIsFirstInSequence", oracle: "OpFlagIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage4.RdWa", source_stage: "stage4", source_claim: "stage4.registers_read_write.opening.RdWa", oracle: "RdWa", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage4.Rs1Ra", source_stage: "stage4", source_claim: "stage4.registers_read_write.opening.Rs1Ra", oracle: "Rs1Ra", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage4.Rs2Ra", source_stage: "stage4", source_claim: "stage4.registers_read_write.opening.Rs2Ra", oracle: "Rs2Ra", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.registers_val_evaluation.RdWa", source_stage: "stage5", source_claim: "stage5.registers_val_evaluation.opening.RdWa", oracle: "RdWa", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.InstructionRafFlag", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRafFlag", oracle: "InstructionRafFlag", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_0", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_0", oracle: "LookupTableFlag_0", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_1", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_1", oracle: "LookupTableFlag_1", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_2", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_2", oracle: "LookupTableFlag_2", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_3", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_3", oracle: "LookupTableFlag_3", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_4", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_4", oracle: "LookupTableFlag_4", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_5", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_5", oracle: "LookupTableFlag_5", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_6", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_6", oracle: "LookupTableFlag_6", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_7", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_7", oracle: "LookupTableFlag_7", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_8", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_8", oracle: "LookupTableFlag_8", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_9", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_9", oracle: "LookupTableFlag_9", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_10", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_10", oracle: "LookupTableFlag_10", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_11", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_11", oracle: "LookupTableFlag_11", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_12", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_12", oracle: "LookupTableFlag_12", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_13", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_13", oracle: "LookupTableFlag_13", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_14", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_14", oracle: "LookupTableFlag_14", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_15", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_15", oracle: "LookupTableFlag_15", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_16", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_16", oracle: "LookupTableFlag_16", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_17", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_17", oracle: "LookupTableFlag_17", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_18", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_18", oracle: "LookupTableFlag_18", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_19", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_19", oracle: "LookupTableFlag_19", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_20", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_20", oracle: "LookupTableFlag_20", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_21", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_21", oracle: "LookupTableFlag_21", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_22", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_22", oracle: "LookupTableFlag_22", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_23", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_23", oracle: "LookupTableFlag_23", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_24", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_24", oracle: "LookupTableFlag_24", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_25", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_25", oracle: "LookupTableFlag_25", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_26", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_26", oracle: "LookupTableFlag_26", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_27", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_27", oracle: "LookupTableFlag_27", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_28", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_28", oracle: "LookupTableFlag_28", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_29", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_29", oracle: "LookupTableFlag_29", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_30", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_30", oracle: "LookupTableFlag_30", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_31", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_31", oracle: "LookupTableFlag_31", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_32", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_32", oracle: "LookupTableFlag_32", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_33", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_33", oracle: "LookupTableFlag_33", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_34", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_34", oracle: "LookupTableFlag_34", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_35", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_35", oracle: "LookupTableFlag_35", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_36", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_36", oracle: "LookupTableFlag_36", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_37", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_37", oracle: "LookupTableFlag_37", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_38", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_38", oracle: "LookupTableFlag_38", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_39", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_39", oracle: "LookupTableFlag_39", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.PC", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.PC", oracle: "PC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.spartan_shift.PC", source_stage: "stage3", source_claim: "stage3.spartan_shift.opening.PC", oracle: "PC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", source_stage: "stage5", source_claim: "stage5.ram_ra_claim_reduction.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_1", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_2", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_3", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_4", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_5", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_6", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_7", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.LookupOutput", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage2.ram_read_write.RamInc", source_stage: "stage2", source_claim: "stage2.ram_read_write.opening.RamInc", oracle: "RamInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage4.ram_val_check.RamInc", source_stage: "stage4", source_claim: "stage4.ram_val_check.opening.RamInc", oracle: "RamInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage4.registers_read_write.RdInc", source_stage: "stage4", source_claim: "stage4.registers_read_write.opening.RdInc", oracle: "RdInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.registers_val_evaluation.RdInc", source_stage: "stage5", source_claim: "stage5.registers_val_evaluation.opening.RdInc", oracle: "RdInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed" }, +]; + +pub const STAGE6_FIELD_CONSTANTS: &[Stage6FieldConstantPlan] = &[ + Stage6FieldConstantPlan { symbol: "stage6.zero", field: "bn254_fr", value: 0 }, +]; + +macro_rules! stage6_field_expr { + ($symbol:literal, $formula:literal, $operands:literal) => { + Stage6FieldExprPlan { symbol: $symbol, kind: "op", formula: $formula, operands: $operands } + }; +} + +#[rustfmt::skip] +pub const STAGE6_FIELD_EXPRS: &[Stage6FieldExprPlan] = &[ + stage6_field_expr!("stage6.booleanity.gamma_sq_0", "field.pow:0", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_1", "field.pow:2", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_2", "field.pow:4", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_3", "field.pow:6", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_4", "field.pow:8", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_5", "field.pow:10", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_6", "field.pow:12", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_7", "field.pow:14", "stage6.booleanity.gamma"), + stage6_field_expr!("stage6.booleanity.gamma_sq_8", "field.pow:16", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_9", "field.pow:18", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_10", "field.pow:20", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_11", "field.pow:22", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_12", "field.pow:24", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_13", "field.pow:26", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_14", "field.pow:28", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_15", "field.pow:30", "stage6.booleanity.gamma"), + stage6_field_expr!("stage6.booleanity.gamma_sq_16", "field.pow:32", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_17", "field.pow:34", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_18", "field.pow:36", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_19", "field.pow:38", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_20", "field.pow:40", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_21", "field.pow:42", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_22", "field.pow:44", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_23", "field.pow:46", "stage6.booleanity.gamma"), + stage6_field_expr!("stage6.booleanity.gamma_sq_24", "field.pow:48", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_25", "field.pow:50", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_26", "field.pow:52", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_27", "field.pow:54", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_28", "field.pow:56", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_29", "field.pow:58", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_30", "field.pow:60", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_31", "field.pow:62", "stage6.booleanity.gamma"), + stage6_field_expr!("stage6.booleanity.gamma_sq_32", "field.pow:64", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_33", "field.pow:66", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_34", "field.pow:68", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_35", "field.pow:70", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_36", "field.pow:72", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_37", "field.pow:74", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_38", "field.pow:76", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_0", "field.pow:0", "stage6.booleanity.gamma"), + stage6_field_expr!("stage6.booleanity.gamma_pow_1", "field.pow:1", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_2", "field.pow:2", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_3", "field.pow:3", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_4", "field.pow:4", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_5", "field.pow:5", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_6", "field.pow:6", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_7", "field.pow:7", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_8", "field.pow:8", "stage6.booleanity.gamma"), + stage6_field_expr!("stage6.booleanity.gamma_pow_9", "field.pow:9", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_10", "field.pow:10", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_11", "field.pow:11", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_12", "field.pow:12", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_13", "field.pow:13", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_14", "field.pow:14", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_15", "field.pow:15", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_16", "field.pow:16", "stage6.booleanity.gamma"), + stage6_field_expr!("stage6.booleanity.gamma_pow_17", "field.pow:17", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_18", "field.pow:18", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_19", "field.pow:19", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_20", "field.pow:20", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_21", "field.pow:21", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_22", "field.pow:22", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_23", "field.pow:23", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_24", "field.pow:24", "stage6.booleanity.gamma"), + stage6_field_expr!("stage6.booleanity.gamma_pow_25", "field.pow:25", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_26", "field.pow:26", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_27", "field.pow:27", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_28", "field.pow:28", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_29", "field.pow:29", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_30", "field.pow:30", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_31", "field.pow:31", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_32", "field.pow:32", "stage6.booleanity.gamma"), + stage6_field_expr!("stage6.booleanity.gamma_pow_33", "field.pow:33", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_34", "field.pow:34", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_35", "field.pow:35", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_36", "field.pow:36", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_37", "field.pow:37", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_38", "field.pow:38", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term1.stage_gamma_pow", "field.pow:1", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term1.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term1.stage_gamma_pow|stage6.input.stage1.Imm"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term2.stage_gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term2.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term2.stage_gamma_pow|stage6.input.stage1.OpFlagAddOperands"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term3.stage_gamma_pow", "field.pow:3", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term3.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term3.stage_gamma_pow|stage6.input.stage1.OpFlagSubtractOperands"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term4.stage_gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term4.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term4.stage_gamma_pow|stage6.input.stage1.OpFlagMultiplyOperands"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term5.stage_gamma_pow", "field.pow:5", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term5.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term5.stage_gamma_pow|stage6.input.stage1.OpFlagLoad"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term6.stage_gamma_pow", "field.pow:6", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term6.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term6.stage_gamma_pow|stage6.input.stage1.OpFlagStore"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term7.stage_gamma_pow", "field.pow:7", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term7.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term7.stage_gamma_pow|stage6.input.stage1.OpFlagJump"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term8.stage_gamma_pow", "field.pow:8", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term8.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term8.stage_gamma_pow|stage6.input.stage1.OpFlagWriteLookupOutputToRD"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term9.stage_gamma_pow", "field.pow:9", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term9.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term9.stage_gamma_pow|stage6.input.stage1.OpFlagVirtualInstruction"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term10.stage_gamma_pow", "field.pow:10", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term10.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term10.stage_gamma_pow|stage6.input.stage1.OpFlagAssert"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term11.stage_gamma_pow", "field.pow:11", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term11.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term11.stage_gamma_pow|stage6.input.stage1.OpFlagDoNotUpdateUnexpandedPC"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term12.stage_gamma_pow", "field.pow:12", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term12.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term12.stage_gamma_pow|stage6.input.stage1.OpFlagAdvice"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term13.stage_gamma_pow", "field.pow:13", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term13.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term13.stage_gamma_pow|stage6.input.stage1.OpFlagIsCompressed"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term14.stage_gamma_pow", "field.pow:14", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term14.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term14.stage_gamma_pow|stage6.input.stage1.OpFlagIsFirstInSequence"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term15.stage_gamma_pow", "field.pow:15", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term15.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term15.stage_gamma_pow|stage6.input.stage1.OpFlagIsLastInSequence"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term16.gamma_pow", "field.pow:1", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term16.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term16.gamma_pow|stage6.input.stage2.OpFlagJump"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term17.stage_gamma_pow", "field.pow:1", "stage6.bytecode_read_raf.stage2_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term17.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term17.stage_gamma_pow|stage6.input.stage2.InstructionFlagBranch"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term17.gamma_pow", "field.pow:1", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term17.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term17.gamma_pow|stage6.bytecode_read_raf.claim.term17.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term18.stage_gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.stage2_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term18.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term18.stage_gamma_pow|stage6.input.stage2.OpFlagWriteLookupOutputToRD"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term18.gamma_pow", "field.pow:1", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term18.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term18.gamma_pow|stage6.bytecode_read_raf.claim.term18.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term19.stage_gamma_pow", "field.pow:3", "stage6.bytecode_read_raf.stage2_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term19.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term19.stage_gamma_pow|stage6.input.stage2.OpFlagVirtualInstruction"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term19.gamma_pow", "field.pow:1", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term19.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term19.gamma_pow|stage6.bytecode_read_raf.claim.term19.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term20.gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term20.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term20.gamma_pow|stage6.input.stage3.instruction_input.Imm"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term21.stage_gamma_pow", "field.pow:1", "stage6.bytecode_read_raf.stage3_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term21.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term21.stage_gamma_pow|stage6.input.stage3.spartan_shift.UnexpandedPC"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term21.gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term21.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term21.gamma_pow|stage6.bytecode_read_raf.claim.term21.stage_gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term22.stage_gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.stage3_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term22.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term22.stage_gamma_pow|stage6.input.stage3.instruction_input.InstructionFlagLeftOperandIsRs1Value"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term22.gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term22.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term22.gamma_pow|stage6.bytecode_read_raf.claim.term22.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term23.stage_gamma_pow", "field.pow:3", "stage6.bytecode_read_raf.stage3_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term23.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term23.stage_gamma_pow|stage6.input.stage3.instruction_input.InstructionFlagLeftOperandIsPC"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term23.gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term23.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term23.gamma_pow|stage6.bytecode_read_raf.claim.term23.stage_gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term24.stage_gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.stage3_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term24.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term24.stage_gamma_pow|stage6.input.stage3.instruction_input.InstructionFlagRightOperandIsRs2Value"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term24.gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term24.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term24.gamma_pow|stage6.bytecode_read_raf.claim.term24.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term25.stage_gamma_pow", "field.pow:5", "stage6.bytecode_read_raf.stage3_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term25.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term25.stage_gamma_pow|stage6.input.stage3.instruction_input.InstructionFlagRightOperandIsImm"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term25.gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term25.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term25.gamma_pow|stage6.bytecode_read_raf.claim.term25.stage_gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term26.stage_gamma_pow", "field.pow:6", "stage6.bytecode_read_raf.stage3_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term26.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term26.stage_gamma_pow|stage6.input.stage3.spartan_shift.InstructionFlagIsNoop"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term26.gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term26.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term26.gamma_pow|stage6.bytecode_read_raf.claim.term26.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term27.stage_gamma_pow", "field.pow:7", "stage6.bytecode_read_raf.stage3_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term27.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term27.stage_gamma_pow|stage6.input.stage3.spartan_shift.OpFlagVirtualInstruction"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term27.gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term27.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term27.gamma_pow|stage6.bytecode_read_raf.claim.term27.stage_gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term28.stage_gamma_pow", "field.pow:8", "stage6.bytecode_read_raf.stage3_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term28.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term28.stage_gamma_pow|stage6.input.stage3.spartan_shift.OpFlagIsFirstInSequence"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term28.gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term28.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term28.gamma_pow|stage6.bytecode_read_raf.claim.term28.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term29.gamma_pow", "field.pow:3", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term29.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term29.gamma_pow|stage6.input.stage4.RdWa"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term30.stage_gamma_pow", "field.pow:1", "stage6.bytecode_read_raf.stage4_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term30.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term30.stage_gamma_pow|stage6.input.stage4.Rs1Ra"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term30.gamma_pow", "field.pow:3", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term30.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term30.gamma_pow|stage6.bytecode_read_raf.claim.term30.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term31.stage_gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.stage4_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term31.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term31.stage_gamma_pow|stage6.input.stage4.Rs2Ra"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term31.gamma_pow", "field.pow:3", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term31.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term31.gamma_pow|stage6.bytecode_read_raf.claim.term31.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term32.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term32.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term32.gamma_pow|stage6.input.stage5.registers_val_evaluation.RdWa"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term33.stage_gamma_pow", "field.pow:1", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term33.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term33.stage_gamma_pow|stage6.input.stage5.InstructionRafFlag"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term33.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term33.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term33.gamma_pow|stage6.bytecode_read_raf.claim.term33.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term34.stage_gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term34.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term34.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_0"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term34.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term34.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term34.gamma_pow|stage6.bytecode_read_raf.claim.term34.stage_gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term35.stage_gamma_pow", "field.pow:3", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term35.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term35.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_1"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term35.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term35.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term35.gamma_pow|stage6.bytecode_read_raf.claim.term35.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term36.stage_gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term36.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term36.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_2"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term36.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term36.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term36.gamma_pow|stage6.bytecode_read_raf.claim.term36.stage_gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term37.stage_gamma_pow", "field.pow:5", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term37.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term37.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_3"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term37.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term37.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term37.gamma_pow|stage6.bytecode_read_raf.claim.term37.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term38.stage_gamma_pow", "field.pow:6", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term38.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term38.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_4"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term38.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term38.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term38.gamma_pow|stage6.bytecode_read_raf.claim.term38.stage_gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term39.stage_gamma_pow", "field.pow:7", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term39.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term39.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_5"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term39.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term39.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term39.gamma_pow|stage6.bytecode_read_raf.claim.term39.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term40.stage_gamma_pow", "field.pow:8", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term40.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term40.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_6"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term40.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term40.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term40.gamma_pow|stage6.bytecode_read_raf.claim.term40.stage_gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term41.stage_gamma_pow", "field.pow:9", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term41.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term41.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_7"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term41.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term41.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term41.gamma_pow|stage6.bytecode_read_raf.claim.term41.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term42.stage_gamma_pow", "field.pow:10", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term42.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term42.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_8"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term42.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term42.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term42.gamma_pow|stage6.bytecode_read_raf.claim.term42.stage_gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term43.stage_gamma_pow", "field.pow:11", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term43.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term43.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_9"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term43.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term43.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term43.gamma_pow|stage6.bytecode_read_raf.claim.term43.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term44.stage_gamma_pow", "field.pow:12", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term44.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term44.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_10"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term44.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term44.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term44.gamma_pow|stage6.bytecode_read_raf.claim.term44.stage_gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term45.stage_gamma_pow", "field.pow:13", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term45.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term45.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_11"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term45.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term45.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term45.gamma_pow|stage6.bytecode_read_raf.claim.term45.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term46.stage_gamma_pow", "field.pow:14", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term46.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term46.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_12"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term46.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term46.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term46.gamma_pow|stage6.bytecode_read_raf.claim.term46.stage_gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term47.stage_gamma_pow", "field.pow:15", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term47.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term47.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_13"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term47.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term47.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term47.gamma_pow|stage6.bytecode_read_raf.claim.term47.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term48.stage_gamma_pow", "field.pow:16", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term48.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term48.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_14"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term48.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term48.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term48.gamma_pow|stage6.bytecode_read_raf.claim.term48.stage_gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term49.stage_gamma_pow", "field.pow:17", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term49.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term49.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_15"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term49.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term49.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term49.gamma_pow|stage6.bytecode_read_raf.claim.term49.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term50.stage_gamma_pow", "field.pow:18", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term50.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term50.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_16"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term50.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term50.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term50.gamma_pow|stage6.bytecode_read_raf.claim.term50.stage_gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term51.stage_gamma_pow", "field.pow:19", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term51.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term51.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_17"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term51.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term51.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term51.gamma_pow|stage6.bytecode_read_raf.claim.term51.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term52.stage_gamma_pow", "field.pow:20", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term52.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term52.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_18"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term52.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term52.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term52.gamma_pow|stage6.bytecode_read_raf.claim.term52.stage_gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term53.stage_gamma_pow", "field.pow:21", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term53.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term53.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_19"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term53.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term53.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term53.gamma_pow|stage6.bytecode_read_raf.claim.term53.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term54.stage_gamma_pow", "field.pow:22", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term54.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term54.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_20"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term54.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term54.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term54.gamma_pow|stage6.bytecode_read_raf.claim.term54.stage_gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term55.stage_gamma_pow", "field.pow:23", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term55.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term55.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_21"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term55.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term55.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term55.gamma_pow|stage6.bytecode_read_raf.claim.term55.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term56.stage_gamma_pow", "field.pow:24", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term56.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term56.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_22"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term56.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term56.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term56.gamma_pow|stage6.bytecode_read_raf.claim.term56.stage_gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term57.stage_gamma_pow", "field.pow:25", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term57.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term57.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_23"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term57.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term57.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term57.gamma_pow|stage6.bytecode_read_raf.claim.term57.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term58.stage_gamma_pow", "field.pow:26", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term58.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term58.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_24"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term58.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term58.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term58.gamma_pow|stage6.bytecode_read_raf.claim.term58.stage_gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term59.stage_gamma_pow", "field.pow:27", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term59.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term59.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_25"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term59.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term59.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term59.gamma_pow|stage6.bytecode_read_raf.claim.term59.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term60.stage_gamma_pow", "field.pow:28", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term60.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term60.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_26"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term60.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term60.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term60.gamma_pow|stage6.bytecode_read_raf.claim.term60.stage_gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term61.stage_gamma_pow", "field.pow:29", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term61.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term61.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_27"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term61.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term61.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term61.gamma_pow|stage6.bytecode_read_raf.claim.term61.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term62.stage_gamma_pow", "field.pow:30", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term62.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term62.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_28"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term62.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term62.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term62.gamma_pow|stage6.bytecode_read_raf.claim.term62.stage_gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term63.stage_gamma_pow", "field.pow:31", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term63.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term63.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_29"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term63.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term63.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term63.gamma_pow|stage6.bytecode_read_raf.claim.term63.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term64.stage_gamma_pow", "field.pow:32", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term64.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term64.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_30"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term64.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term64.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term64.gamma_pow|stage6.bytecode_read_raf.claim.term64.stage_gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term65.stage_gamma_pow", "field.pow:33", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term65.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term65.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_31"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term65.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term65.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term65.gamma_pow|stage6.bytecode_read_raf.claim.term65.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term66.stage_gamma_pow", "field.pow:34", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term66.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term66.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_32"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term66.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term66.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term66.gamma_pow|stage6.bytecode_read_raf.claim.term66.stage_gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term67.stage_gamma_pow", "field.pow:35", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term67.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term67.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_33"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term67.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term67.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term67.gamma_pow|stage6.bytecode_read_raf.claim.term67.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term68.stage_gamma_pow", "field.pow:36", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term68.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term68.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_34"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term68.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term68.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term68.gamma_pow|stage6.bytecode_read_raf.claim.term68.stage_gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term69.stage_gamma_pow", "field.pow:37", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term69.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term69.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_35"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term69.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term69.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term69.gamma_pow|stage6.bytecode_read_raf.claim.term69.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term70.stage_gamma_pow", "field.pow:38", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term70.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term70.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_36"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term70.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term70.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term70.gamma_pow|stage6.bytecode_read_raf.claim.term70.stage_gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term71.stage_gamma_pow", "field.pow:39", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term71.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term71.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_37"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term71.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term71.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term71.gamma_pow|stage6.bytecode_read_raf.claim.term71.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term72.stage_gamma_pow", "field.pow:40", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term72.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term72.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_38"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term72.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term72.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term72.gamma_pow|stage6.bytecode_read_raf.claim.term72.stage_gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term73.stage_gamma_pow", "field.pow:41", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term73.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term73.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_39"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term73.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term73.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term73.gamma_pow|stage6.bytecode_read_raf.claim.term73.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term74.gamma_pow", "field.pow:5", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term74.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term74.gamma_pow|stage6.input.stage1.PC"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term75.gamma_pow", "field.pow:6", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term75.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term75.gamma_pow|stage6.input.stage3.spartan_shift.PC"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.entry_constant", "field.pow:7", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial0", "field.add", "stage6.input.stage1.UnexpandedPC|stage6.bytecode_read_raf.claim.term1.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial1", "field.add", "stage6.bytecode_read_raf.claim_expr.partial0|stage6.bytecode_read_raf.claim.term2.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial2", "field.add", "stage6.bytecode_read_raf.claim_expr.partial1|stage6.bytecode_read_raf.claim.term3.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial3", "field.add", "stage6.bytecode_read_raf.claim_expr.partial2|stage6.bytecode_read_raf.claim.term4.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial4", "field.add", "stage6.bytecode_read_raf.claim_expr.partial3|stage6.bytecode_read_raf.claim.term5.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial5", "field.add", "stage6.bytecode_read_raf.claim_expr.partial4|stage6.bytecode_read_raf.claim.term6.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial6", "field.add", "stage6.bytecode_read_raf.claim_expr.partial5|stage6.bytecode_read_raf.claim.term7.stage_gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial7", "field.add", "stage6.bytecode_read_raf.claim_expr.partial6|stage6.bytecode_read_raf.claim.term8.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial8", "field.add", "stage6.bytecode_read_raf.claim_expr.partial7|stage6.bytecode_read_raf.claim.term9.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial9", "field.add", "stage6.bytecode_read_raf.claim_expr.partial8|stage6.bytecode_read_raf.claim.term10.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial10", "field.add", "stage6.bytecode_read_raf.claim_expr.partial9|stage6.bytecode_read_raf.claim.term11.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial11", "field.add", "stage6.bytecode_read_raf.claim_expr.partial10|stage6.bytecode_read_raf.claim.term12.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial12", "field.add", "stage6.bytecode_read_raf.claim_expr.partial11|stage6.bytecode_read_raf.claim.term13.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial13", "field.add", "stage6.bytecode_read_raf.claim_expr.partial12|stage6.bytecode_read_raf.claim.term14.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial14", "field.add", "stage6.bytecode_read_raf.claim_expr.partial13|stage6.bytecode_read_raf.claim.term15.stage_gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial15", "field.add", "stage6.bytecode_read_raf.claim_expr.partial14|stage6.bytecode_read_raf.claim.term16.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial16", "field.add", "stage6.bytecode_read_raf.claim_expr.partial15|stage6.bytecode_read_raf.claim.term17.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial17", "field.add", "stage6.bytecode_read_raf.claim_expr.partial16|stage6.bytecode_read_raf.claim.term18.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial18", "field.add", "stage6.bytecode_read_raf.claim_expr.partial17|stage6.bytecode_read_raf.claim.term19.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial19", "field.add", "stage6.bytecode_read_raf.claim_expr.partial18|stage6.bytecode_read_raf.claim.term20.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial20", "field.add", "stage6.bytecode_read_raf.claim_expr.partial19|stage6.bytecode_read_raf.claim.term21.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial21", "field.add", "stage6.bytecode_read_raf.claim_expr.partial20|stage6.bytecode_read_raf.claim.term22.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial22", "field.add", "stage6.bytecode_read_raf.claim_expr.partial21|stage6.bytecode_read_raf.claim.term23.gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial23", "field.add", "stage6.bytecode_read_raf.claim_expr.partial22|stage6.bytecode_read_raf.claim.term24.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial24", "field.add", "stage6.bytecode_read_raf.claim_expr.partial23|stage6.bytecode_read_raf.claim.term25.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial25", "field.add", "stage6.bytecode_read_raf.claim_expr.partial24|stage6.bytecode_read_raf.claim.term26.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial26", "field.add", "stage6.bytecode_read_raf.claim_expr.partial25|stage6.bytecode_read_raf.claim.term27.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial27", "field.add", "stage6.bytecode_read_raf.claim_expr.partial26|stage6.bytecode_read_raf.claim.term28.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial28", "field.add", "stage6.bytecode_read_raf.claim_expr.partial27|stage6.bytecode_read_raf.claim.term29.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial29", "field.add", "stage6.bytecode_read_raf.claim_expr.partial28|stage6.bytecode_read_raf.claim.term30.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial30", "field.add", "stage6.bytecode_read_raf.claim_expr.partial29|stage6.bytecode_read_raf.claim.term31.gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial31", "field.add", "stage6.bytecode_read_raf.claim_expr.partial30|stage6.bytecode_read_raf.claim.term32.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial32", "field.add", "stage6.bytecode_read_raf.claim_expr.partial31|stage6.bytecode_read_raf.claim.term33.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial33", "field.add", "stage6.bytecode_read_raf.claim_expr.partial32|stage6.bytecode_read_raf.claim.term34.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial34", "field.add", "stage6.bytecode_read_raf.claim_expr.partial33|stage6.bytecode_read_raf.claim.term35.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial35", "field.add", "stage6.bytecode_read_raf.claim_expr.partial34|stage6.bytecode_read_raf.claim.term36.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial36", "field.add", "stage6.bytecode_read_raf.claim_expr.partial35|stage6.bytecode_read_raf.claim.term37.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial37", "field.add", "stage6.bytecode_read_raf.claim_expr.partial36|stage6.bytecode_read_raf.claim.term38.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial38", "field.add", "stage6.bytecode_read_raf.claim_expr.partial37|stage6.bytecode_read_raf.claim.term39.gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial39", "field.add", "stage6.bytecode_read_raf.claim_expr.partial38|stage6.bytecode_read_raf.claim.term40.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial40", "field.add", "stage6.bytecode_read_raf.claim_expr.partial39|stage6.bytecode_read_raf.claim.term41.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial41", "field.add", "stage6.bytecode_read_raf.claim_expr.partial40|stage6.bytecode_read_raf.claim.term42.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial42", "field.add", "stage6.bytecode_read_raf.claim_expr.partial41|stage6.bytecode_read_raf.claim.term43.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial43", "field.add", "stage6.bytecode_read_raf.claim_expr.partial42|stage6.bytecode_read_raf.claim.term44.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial44", "field.add", "stage6.bytecode_read_raf.claim_expr.partial43|stage6.bytecode_read_raf.claim.term45.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial45", "field.add", "stage6.bytecode_read_raf.claim_expr.partial44|stage6.bytecode_read_raf.claim.term46.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial46", "field.add", "stage6.bytecode_read_raf.claim_expr.partial45|stage6.bytecode_read_raf.claim.term47.gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial47", "field.add", "stage6.bytecode_read_raf.claim_expr.partial46|stage6.bytecode_read_raf.claim.term48.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial48", "field.add", "stage6.bytecode_read_raf.claim_expr.partial47|stage6.bytecode_read_raf.claim.term49.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial49", "field.add", "stage6.bytecode_read_raf.claim_expr.partial48|stage6.bytecode_read_raf.claim.term50.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial50", "field.add", "stage6.bytecode_read_raf.claim_expr.partial49|stage6.bytecode_read_raf.claim.term51.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial51", "field.add", "stage6.bytecode_read_raf.claim_expr.partial50|stage6.bytecode_read_raf.claim.term52.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial52", "field.add", "stage6.bytecode_read_raf.claim_expr.partial51|stage6.bytecode_read_raf.claim.term53.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial53", "field.add", "stage6.bytecode_read_raf.claim_expr.partial52|stage6.bytecode_read_raf.claim.term54.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial54", "field.add", "stage6.bytecode_read_raf.claim_expr.partial53|stage6.bytecode_read_raf.claim.term55.gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial55", "field.add", "stage6.bytecode_read_raf.claim_expr.partial54|stage6.bytecode_read_raf.claim.term56.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial56", "field.add", "stage6.bytecode_read_raf.claim_expr.partial55|stage6.bytecode_read_raf.claim.term57.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial57", "field.add", "stage6.bytecode_read_raf.claim_expr.partial56|stage6.bytecode_read_raf.claim.term58.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial58", "field.add", "stage6.bytecode_read_raf.claim_expr.partial57|stage6.bytecode_read_raf.claim.term59.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial59", "field.add", "stage6.bytecode_read_raf.claim_expr.partial58|stage6.bytecode_read_raf.claim.term60.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial60", "field.add", "stage6.bytecode_read_raf.claim_expr.partial59|stage6.bytecode_read_raf.claim.term61.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial61", "field.add", "stage6.bytecode_read_raf.claim_expr.partial60|stage6.bytecode_read_raf.claim.term62.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial62", "field.add", "stage6.bytecode_read_raf.claim_expr.partial61|stage6.bytecode_read_raf.claim.term63.gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial63", "field.add", "stage6.bytecode_read_raf.claim_expr.partial62|stage6.bytecode_read_raf.claim.term64.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial64", "field.add", "stage6.bytecode_read_raf.claim_expr.partial63|stage6.bytecode_read_raf.claim.term65.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial65", "field.add", "stage6.bytecode_read_raf.claim_expr.partial64|stage6.bytecode_read_raf.claim.term66.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial66", "field.add", "stage6.bytecode_read_raf.claim_expr.partial65|stage6.bytecode_read_raf.claim.term67.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial67", "field.add", "stage6.bytecode_read_raf.claim_expr.partial66|stage6.bytecode_read_raf.claim.term68.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial68", "field.add", "stage6.bytecode_read_raf.claim_expr.partial67|stage6.bytecode_read_raf.claim.term69.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial69", "field.add", "stage6.bytecode_read_raf.claim_expr.partial68|stage6.bytecode_read_raf.claim.term70.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial70", "field.add", "stage6.bytecode_read_raf.claim_expr.partial69|stage6.bytecode_read_raf.claim.term71.gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial71", "field.add", "stage6.bytecode_read_raf.claim_expr.partial70|stage6.bytecode_read_raf.claim.term72.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial72", "field.add", "stage6.bytecode_read_raf.claim_expr.partial71|stage6.bytecode_read_raf.claim.term73.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial73", "field.add", "stage6.bytecode_read_raf.claim_expr.partial72|stage6.bytecode_read_raf.claim.term74.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial74", "field.add", "stage6.bytecode_read_raf.claim_expr.partial73|stage6.bytecode_read_raf.claim.term75.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial75", "field.add", "stage6.bytecode_read_raf.claim_expr.partial74|stage6.bytecode_read_raf.claim.entry_constant"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term1.gamma_pow", "field.pow:1", "stage6.instruction_ra_virtual.gamma"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term1.gamma_term", "field.mul", "stage6.instruction_ra_virtual.claim.term1.gamma_pow|stage6.input.stage5.instruction_read_raf.InstructionRa_1"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term2.gamma_pow", "field.pow:2", "stage6.instruction_ra_virtual.gamma"), + stage6_field_expr!("stage6.instruction_ra_virtual.claim.term2.gamma_term", "field.mul", "stage6.instruction_ra_virtual.claim.term2.gamma_pow|stage6.input.stage5.instruction_read_raf.InstructionRa_2"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term3.gamma_pow", "field.pow:3", "stage6.instruction_ra_virtual.gamma"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term3.gamma_term", "field.mul", "stage6.instruction_ra_virtual.claim.term3.gamma_pow|stage6.input.stage5.instruction_read_raf.InstructionRa_3"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term4.gamma_pow", "field.pow:4", "stage6.instruction_ra_virtual.gamma"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term4.gamma_term", "field.mul", "stage6.instruction_ra_virtual.claim.term4.gamma_pow|stage6.input.stage5.instruction_read_raf.InstructionRa_4"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term5.gamma_pow", "field.pow:5", "stage6.instruction_ra_virtual.gamma"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term5.gamma_term", "field.mul", "stage6.instruction_ra_virtual.claim.term5.gamma_pow|stage6.input.stage5.instruction_read_raf.InstructionRa_5"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term6.gamma_pow", "field.pow:6", "stage6.instruction_ra_virtual.gamma"), + stage6_field_expr!("stage6.instruction_ra_virtual.claim.term6.gamma_term", "field.mul", "stage6.instruction_ra_virtual.claim.term6.gamma_pow|stage6.input.stage5.instruction_read_raf.InstructionRa_6"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term7.gamma_pow", "field.pow:7", "stage6.instruction_ra_virtual.gamma"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term7.gamma_term", "field.mul", "stage6.instruction_ra_virtual.claim.term7.gamma_pow|stage6.input.stage5.instruction_read_raf.InstructionRa_7"), stage6_field_expr!("stage6.instruction_ra_virtual.claim_expr.partial0", "field.add", "stage6.input.stage5.instruction_read_raf.InstructionRa_0|stage6.instruction_ra_virtual.claim.term1.gamma_term"), stage6_field_expr!("stage6.instruction_ra_virtual.claim_expr.partial1", "field.add", "stage6.instruction_ra_virtual.claim_expr.partial0|stage6.instruction_ra_virtual.claim.term2.gamma_term"), stage6_field_expr!("stage6.instruction_ra_virtual.claim_expr.partial2", "field.add", "stage6.instruction_ra_virtual.claim_expr.partial1|stage6.instruction_ra_virtual.claim.term3.gamma_term"), stage6_field_expr!("stage6.instruction_ra_virtual.claim_expr.partial3", "field.add", "stage6.instruction_ra_virtual.claim_expr.partial2|stage6.instruction_ra_virtual.claim.term4.gamma_term"), stage6_field_expr!("stage6.instruction_ra_virtual.claim_expr.partial4", "field.add", "stage6.instruction_ra_virtual.claim_expr.partial3|stage6.instruction_ra_virtual.claim.term5.gamma_term"), + stage6_field_expr!("stage6.instruction_ra_virtual.claim_expr.partial5", "field.add", "stage6.instruction_ra_virtual.claim_expr.partial4|stage6.instruction_ra_virtual.claim.term6.gamma_term"), stage6_field_expr!("stage6.instruction_ra_virtual.claim_expr.partial6", "field.add", "stage6.instruction_ra_virtual.claim_expr.partial5|stage6.instruction_ra_virtual.claim.term7.gamma_term"), stage6_field_expr!("stage6.inc_claim_reduction.claim.ram_inc_stage4.gamma_pow", "field.pow:1", "stage6.inc_claim_reduction.gamma"), stage6_field_expr!("stage6.inc_claim_reduction.claim.ram_inc_stage4.gamma_term", "field.mul", "stage6.inc_claim_reduction.claim.ram_inc_stage4.gamma_pow|stage6.input.stage4.ram_val_check.RamInc"), stage6_field_expr!("stage6.inc_claim_reduction.claim.rd_inc_stage4.gamma_pow", "field.pow:2", "stage6.inc_claim_reduction.gamma"), stage6_field_expr!("stage6.inc_claim_reduction.claim.rd_inc_stage4.gamma_term", "field.mul", "stage6.inc_claim_reduction.claim.rd_inc_stage4.gamma_pow|stage6.input.stage4.registers_read_write.RdInc"), stage6_field_expr!("stage6.inc_claim_reduction.claim.rd_inc_stage5.gamma_pow", "field.pow:3", "stage6.inc_claim_reduction.gamma"), stage6_field_expr!("stage6.inc_claim_reduction.claim.rd_inc_stage5.gamma_term", "field.mul", "stage6.inc_claim_reduction.claim.rd_inc_stage5.gamma_pow|stage6.input.stage5.registers_val_evaluation.RdInc"), + stage6_field_expr!("stage6.inc_claim_reduction.claim_expr.partial0", "field.add", "stage6.input.stage2.ram_read_write.RamInc|stage6.inc_claim_reduction.claim.ram_inc_stage4.gamma_term"), stage6_field_expr!("stage6.inc_claim_reduction.claim_expr.partial1", "field.add", "stage6.inc_claim_reduction.claim_expr.partial0|stage6.inc_claim_reduction.claim.rd_inc_stage4.gamma_term"), stage6_field_expr!("stage6.inc_claim_reduction.claim_expr.partial2", "field.add", "stage6.inc_claim_reduction.claim_expr.partial1|stage6.inc_claim_reduction.claim.rd_inc_stage5.gamma_term"), +]; +pub const STAGE6_KERNELS: &[Stage6KernelPlan] = &[ + +]; + +pub const STAGE6_SUMCHECK_CLAIMS: &[Stage6SumcheckClaimPlan] = &[ + Stage6SumcheckClaimPlan { symbol: "stage6.bytecode_read_raf.input", stage: "stage6", domain: "jolt.stage6_bytecode_read_raf_domain", num_rounds: 26, degree: 4, claim: "stage6.bytecode_read_raf.weighted_prior_stage_values", kernel: None, relation: Some("jolt.stage6.bytecode_read_raf"), claim_value: "stage6.bytecode_read_raf.claim_expr.partial75", input_openings: "stage6.input.stage1.UnexpandedPC|stage6.input.stage1.Imm|stage6.input.stage1.OpFlagAddOperands|stage6.input.stage1.OpFlagSubtractOperands|stage6.input.stage1.OpFlagMultiplyOperands|stage6.input.stage1.OpFlagLoad|stage6.input.stage1.OpFlagStore|stage6.input.stage1.OpFlagJump|stage6.input.stage1.OpFlagWriteLookupOutputToRD|stage6.input.stage1.OpFlagVirtualInstruction|stage6.input.stage1.OpFlagAssert|stage6.input.stage1.OpFlagDoNotUpdateUnexpandedPC|stage6.input.stage1.OpFlagAdvice|stage6.input.stage1.OpFlagIsCompressed|stage6.input.stage1.OpFlagIsFirstInSequence|stage6.input.stage1.OpFlagIsLastInSequence|stage6.input.stage2.OpFlagJump|stage6.input.stage2.InstructionFlagBranch|stage6.input.stage2.OpFlagWriteLookupOutputToRD|stage6.input.stage2.OpFlagVirtualInstruction|stage6.input.stage3.instruction_input.Imm|stage6.input.stage3.spartan_shift.UnexpandedPC|stage6.input.stage3.instruction_input.InstructionFlagLeftOperandIsRs1Value|stage6.input.stage3.instruction_input.InstructionFlagLeftOperandIsPC|stage6.input.stage3.instruction_input.InstructionFlagRightOperandIsRs2Value|stage6.input.stage3.instruction_input.InstructionFlagRightOperandIsImm|stage6.input.stage3.spartan_shift.InstructionFlagIsNoop|stage6.input.stage3.spartan_shift.OpFlagVirtualInstruction|stage6.input.stage3.spartan_shift.OpFlagIsFirstInSequence|stage6.input.stage4.RdWa|stage6.input.stage4.Rs1Ra|stage6.input.stage4.Rs2Ra|stage6.input.stage5.registers_val_evaluation.RdWa|stage6.input.stage5.InstructionRafFlag|stage6.input.stage5.LookupTableFlag_0|stage6.input.stage5.LookupTableFlag_1|stage6.input.stage5.LookupTableFlag_2|stage6.input.stage5.LookupTableFlag_3|stage6.input.stage5.LookupTableFlag_4|stage6.input.stage5.LookupTableFlag_5|stage6.input.stage5.LookupTableFlag_6|stage6.input.stage5.LookupTableFlag_7|stage6.input.stage5.LookupTableFlag_8|stage6.input.stage5.LookupTableFlag_9|stage6.input.stage5.LookupTableFlag_10|stage6.input.stage5.LookupTableFlag_11|stage6.input.stage5.LookupTableFlag_12|stage6.input.stage5.LookupTableFlag_13|stage6.input.stage5.LookupTableFlag_14|stage6.input.stage5.LookupTableFlag_15|stage6.input.stage5.LookupTableFlag_16|stage6.input.stage5.LookupTableFlag_17|stage6.input.stage5.LookupTableFlag_18|stage6.input.stage5.LookupTableFlag_19|stage6.input.stage5.LookupTableFlag_20|stage6.input.stage5.LookupTableFlag_21|stage6.input.stage5.LookupTableFlag_22|stage6.input.stage5.LookupTableFlag_23|stage6.input.stage5.LookupTableFlag_24|stage6.input.stage5.LookupTableFlag_25|stage6.input.stage5.LookupTableFlag_26|stage6.input.stage5.LookupTableFlag_27|stage6.input.stage5.LookupTableFlag_28|stage6.input.stage5.LookupTableFlag_29|stage6.input.stage5.LookupTableFlag_30|stage6.input.stage5.LookupTableFlag_31|stage6.input.stage5.LookupTableFlag_32|stage6.input.stage5.LookupTableFlag_33|stage6.input.stage5.LookupTableFlag_34|stage6.input.stage5.LookupTableFlag_35|stage6.input.stage5.LookupTableFlag_36|stage6.input.stage5.LookupTableFlag_37|stage6.input.stage5.LookupTableFlag_38|stage6.input.stage5.LookupTableFlag_39|stage6.input.stage1.PC|stage6.input.stage3.spartan_shift.PC" }, + Stage6SumcheckClaimPlan { symbol: "stage6.booleanity.input", stage: "stage6", domain: "jolt.stage6_booleanity_domain", num_rounds: 20, degree: 3, claim: "stage6.booleanity.zero", kernel: None, relation: Some("jolt.stage6.booleanity"), claim_value: "stage6.zero", input_openings: "" }, + Stage6SumcheckClaimPlan { symbol: "stage6.hamming_booleanity.input", stage: "stage6", domain: "jolt.trace_domain", num_rounds: 16, degree: 3, claim: "stage6.hamming_booleanity.zero", kernel: None, relation: Some("jolt.stage6.hamming_booleanity"), claim_value: "stage6.zero", input_openings: "stage6.input.stage1.LookupOutput" }, + Stage6SumcheckClaimPlan { symbol: "stage6.ram_ra_virtual.input", stage: "stage6", domain: "jolt.trace_domain", num_rounds: 16, degree: 5, claim: "stage6.ram_ra_virtual.weighted_ram_ra", kernel: None, relation: Some("jolt.stage6.ram_ra_virtual"), claim_value: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", input_openings: "stage6.input.stage5.ram_ra_claim_reduction.RamRa" }, + Stage6SumcheckClaimPlan { symbol: "stage6.instruction_ra_virtual.input", stage: "stage6", domain: "jolt.trace_domain", num_rounds: 16, degree: 5, claim: "stage6.instruction_ra_virtual.weighted_instruction_ra", kernel: None, relation: Some("jolt.stage6.instruction_ra_virtual"), claim_value: "stage6.instruction_ra_virtual.claim_expr.partial6", input_openings: "stage6.input.stage5.instruction_read_raf.InstructionRa_0|stage6.input.stage5.instruction_read_raf.InstructionRa_1|stage6.input.stage5.instruction_read_raf.InstructionRa_2|stage6.input.stage5.instruction_read_raf.InstructionRa_3|stage6.input.stage5.instruction_read_raf.InstructionRa_4|stage6.input.stage5.instruction_read_raf.InstructionRa_5|stage6.input.stage5.instruction_read_raf.InstructionRa_6|stage6.input.stage5.instruction_read_raf.InstructionRa_7" }, + Stage6SumcheckClaimPlan { symbol: "stage6.inc_claim_reduction.input", stage: "stage6", domain: "jolt.trace_domain", num_rounds: 16, degree: 2, claim: "stage6.inc_claim_reduction.weighted_increments", kernel: None, relation: Some("jolt.stage6.inc_claim_reduction"), claim_value: "stage6.inc_claim_reduction.claim_expr.partial2", input_openings: "stage6.input.stage2.ram_read_write.RamInc|stage6.input.stage4.ram_val_check.RamInc|stage6.input.stage4.registers_read_write.RdInc|stage6.input.stage5.registers_val_evaluation.RdInc" }, +]; +pub const STAGE6_SUMCHECK_BATCH_0_ROUND_SCHEDULE: &[usize] = &[ + 10, + 16, +]; + +pub const STAGE6_SUMCHECK_BATCHES: &[Stage6SumcheckBatchPlan] = &[ + Stage6SumcheckBatchPlan { symbol: "stage6.batch", stage: "stage6", proof_slot: "stage6.sumcheck", policy: "jolt_core_stage6_aligned", count: 6, ordered_claims: "stage6.bytecode_read_raf.input|stage6.booleanity.input|stage6.hamming_booleanity.input|stage6.ram_ra_virtual.input|stage6.instruction_ra_virtual.input|stage6.inc_claim_reduction.input", claim_operands: "stage6.bytecode_read_raf.input|stage6.booleanity.input|stage6.hamming_booleanity.input|stage6.ram_ra_virtual.input|stage6.instruction_ra_virtual.input|stage6.inc_claim_reduction.input", claim_label: "sumcheck_claim", round_label: "sumcheck_poly", round_schedule: STAGE6_SUMCHECK_BATCH_0_ROUND_SCHEDULE }, +]; +pub const STAGE6_SUMCHECK_DRIVER_0_ROUND_SCHEDULE: &[usize] = &[ + 10, + 16, +]; + +pub const STAGE6_SUMCHECK_DRIVERS: &[Stage6SumcheckDriverPlan] = &[ + Stage6SumcheckDriverPlan { symbol: "stage6.sumcheck", stage: "stage6", proof_slot: "stage6.sumcheck", kernel: None, relation: Some("jolt.stage6.batched"), batch: "stage6.batch", policy: "jolt_core_stage6_aligned", round_schedule: STAGE6_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 26, degree: 5 }, +]; +pub const STAGE6_SUMCHECK_INSTANCE_RESULTS: &[Stage6SumcheckInstanceResultPlan] = &[ + Stage6SumcheckInstanceResultPlan { symbol: "stage6.bytecode_read_raf.instance", source: "stage6.sumcheck", claim: "stage6.bytecode_read_raf.input", relation: "jolt.stage6.bytecode_read_raf", index: 0, point_arity: 26, num_rounds: 26, round_offset: 0, point_order: "bytecode_read_raf", degree: 4 }, + Stage6SumcheckInstanceResultPlan { symbol: "stage6.booleanity.instance", source: "stage6.sumcheck", claim: "stage6.booleanity.input", relation: "jolt.stage6.booleanity", index: 1, point_arity: 20, num_rounds: 20, round_offset: 6, point_order: "stage6_booleanity", degree: 3 }, + Stage6SumcheckInstanceResultPlan { symbol: "stage6.hamming_booleanity.instance", source: "stage6.sumcheck", claim: "stage6.hamming_booleanity.input", relation: "jolt.stage6.hamming_booleanity", index: 2, point_arity: 16, num_rounds: 16, round_offset: 10, point_order: "reverse", degree: 3 }, + Stage6SumcheckInstanceResultPlan { symbol: "stage6.ram_ra_virtual.instance", source: "stage6.sumcheck", claim: "stage6.ram_ra_virtual.input", relation: "jolt.stage6.ram_ra_virtual", index: 3, point_arity: 16, num_rounds: 16, round_offset: 10, point_order: "reverse", degree: 5 }, + Stage6SumcheckInstanceResultPlan { symbol: "stage6.instruction_ra_virtual.instance", source: "stage6.sumcheck", claim: "stage6.instruction_ra_virtual.input", relation: "jolt.stage6.instruction_ra_virtual", index: 4, point_arity: 16, num_rounds: 16, round_offset: 10, point_order: "reverse", degree: 5 }, + Stage6SumcheckInstanceResultPlan { symbol: "stage6.inc_claim_reduction.instance", source: "stage6.sumcheck", claim: "stage6.inc_claim_reduction.input", relation: "jolt.stage6.inc_claim_reduction", index: 5, point_arity: 16, num_rounds: 16, round_offset: 10, point_order: "reverse", degree: 2 }, +]; + +macro_rules! stage6_sumcheck_eval { + ($symbol:literal, $source:literal, $name:literal, $index:literal, $oracle:literal) => { + Stage6SumcheckEvalPlan { symbol: $symbol, source: $source, name: $name, index: $index, oracle: $oracle } + }; +} + +#[rustfmt::skip] +pub const STAGE6_SUMCHECK_EVALS: &[Stage6SumcheckEvalPlan] = &[ + stage6_sumcheck_eval!("stage6.bytecode_read_raf.eval.BytecodeRa_0", "stage6.sumcheck", "stage6.bytecode_read_raf.eval.BytecodeRa_0", 0, "BytecodeRa_0"), stage6_sumcheck_eval!("stage6.bytecode_read_raf.eval.BytecodeRa_1", "stage6.sumcheck", "stage6.bytecode_read_raf.eval.BytecodeRa_1", 1, "BytecodeRa_1"), stage6_sumcheck_eval!("stage6.bytecode_read_raf.eval.BytecodeRa_2", "stage6.sumcheck", "stage6.bytecode_read_raf.eval.BytecodeRa_2", 2, "BytecodeRa_2"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_0", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_0", 0, "InstructionRa_0"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_1", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_1", 1, "InstructionRa_1"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_2", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_2", 2, "InstructionRa_2"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_3", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_3", 3, "InstructionRa_3"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_4", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_4", 4, "InstructionRa_4"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_5", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_5", 5, "InstructionRa_5"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_6", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_6", 6, "InstructionRa_6"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_7", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_7", 7, "InstructionRa_7"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_8", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_8", 8, "InstructionRa_8"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_9", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_9", 9, "InstructionRa_9"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_10", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_10", 10, "InstructionRa_10"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_11", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_11", 11, "InstructionRa_11"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_12", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_12", 12, "InstructionRa_12"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_13", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_13", 13, "InstructionRa_13"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_14", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_14", 14, "InstructionRa_14"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_15", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_15", 15, "InstructionRa_15"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_16", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_16", 16, "InstructionRa_16"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_17", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_17", 17, "InstructionRa_17"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_18", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_18", 18, "InstructionRa_18"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_19", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_19", 19, "InstructionRa_19"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_20", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_20", 20, "InstructionRa_20"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_21", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_21", 21, "InstructionRa_21"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_22", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_22", 22, "InstructionRa_22"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_23", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_23", 23, "InstructionRa_23"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_24", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_24", 24, "InstructionRa_24"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_25", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_25", 25, "InstructionRa_25"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_26", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_26", 26, "InstructionRa_26"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_27", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_27", 27, "InstructionRa_27"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_28", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_28", 28, "InstructionRa_28"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_29", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_29", 29, "InstructionRa_29"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_30", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_30", 30, "InstructionRa_30"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_31", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_31", 31, "InstructionRa_31"), stage6_sumcheck_eval!("stage6.booleanity.eval.BytecodeRa_0", "stage6.sumcheck", "stage6.booleanity.eval.BytecodeRa_0", 32, "BytecodeRa_0"), + stage6_sumcheck_eval!("stage6.booleanity.eval.BytecodeRa_1", "stage6.sumcheck", "stage6.booleanity.eval.BytecodeRa_1", 33, "BytecodeRa_1"), stage6_sumcheck_eval!("stage6.booleanity.eval.BytecodeRa_2", "stage6.sumcheck", "stage6.booleanity.eval.BytecodeRa_2", 34, "BytecodeRa_2"), stage6_sumcheck_eval!("stage6.booleanity.eval.RamRa_0", "stage6.sumcheck", "stage6.booleanity.eval.RamRa_0", 35, "RamRa_0"), stage6_sumcheck_eval!("stage6.booleanity.eval.RamRa_1", "stage6.sumcheck", "stage6.booleanity.eval.RamRa_1", 36, "RamRa_1"), + stage6_sumcheck_eval!("stage6.booleanity.eval.RamRa_2", "stage6.sumcheck", "stage6.booleanity.eval.RamRa_2", 37, "RamRa_2"), stage6_sumcheck_eval!("stage6.booleanity.eval.RamRa_3", "stage6.sumcheck", "stage6.booleanity.eval.RamRa_3", 38, "RamRa_3"), stage6_sumcheck_eval!("stage6.hamming_booleanity.eval.HammingWeight", "stage6.sumcheck", "stage6.hamming_booleanity.eval.HammingWeight", 0, "HammingWeight"), stage6_sumcheck_eval!("stage6.ram_ra_virtual.eval.RamRa_0", "stage6.sumcheck", "stage6.ram_ra_virtual.eval.RamRa_0", 0, "RamRa_0"), + stage6_sumcheck_eval!("stage6.ram_ra_virtual.eval.RamRa_1", "stage6.sumcheck", "stage6.ram_ra_virtual.eval.RamRa_1", 1, "RamRa_1"), stage6_sumcheck_eval!("stage6.ram_ra_virtual.eval.RamRa_2", "stage6.sumcheck", "stage6.ram_ra_virtual.eval.RamRa_2", 2, "RamRa_2"), stage6_sumcheck_eval!("stage6.ram_ra_virtual.eval.RamRa_3", "stage6.sumcheck", "stage6.ram_ra_virtual.eval.RamRa_3", 3, "RamRa_3"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_0", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_0", 0, "InstructionRa_0"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_1", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_1", 1, "InstructionRa_1"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_2", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_2", 2, "InstructionRa_2"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_3", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_3", 3, "InstructionRa_3"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_4", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_4", 4, "InstructionRa_4"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_5", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_5", 5, "InstructionRa_5"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_6", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_6", 6, "InstructionRa_6"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_7", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_7", 7, "InstructionRa_7"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_8", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_8", 8, "InstructionRa_8"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_9", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_9", 9, "InstructionRa_9"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_10", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_10", 10, "InstructionRa_10"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_11", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_11", 11, "InstructionRa_11"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_12", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_12", 12, "InstructionRa_12"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_13", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_13", 13, "InstructionRa_13"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_14", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_14", 14, "InstructionRa_14"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_15", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_15", 15, "InstructionRa_15"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_16", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_16", 16, "InstructionRa_16"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_17", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_17", 17, "InstructionRa_17"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_18", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_18", 18, "InstructionRa_18"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_19", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_19", 19, "InstructionRa_19"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_20", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_20", 20, "InstructionRa_20"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_21", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_21", 21, "InstructionRa_21"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_22", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_22", 22, "InstructionRa_22"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_23", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_23", 23, "InstructionRa_23"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_24", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_24", 24, "InstructionRa_24"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_25", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_25", 25, "InstructionRa_25"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_26", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_26", 26, "InstructionRa_26"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_27", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_27", 27, "InstructionRa_27"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_28", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_28", 28, "InstructionRa_28"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_29", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_29", 29, "InstructionRa_29"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_30", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_30", 30, "InstructionRa_30"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_31", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_31", 31, "InstructionRa_31"), stage6_sumcheck_eval!("stage6.inc_claim_reduction.eval.RamInc", "stage6.sumcheck", "stage6.inc_claim_reduction.eval.RamInc", 0, "RamInc"), + stage6_sumcheck_eval!("stage6.inc_claim_reduction.eval.RdInc", "stage6.sumcheck", "stage6.inc_claim_reduction.eval.RdInc", 1, "RdInc"), +]; + +pub const STAGE6_POINT_ZEROS: &[Stage6PointZeroPlan] = &[ + Stage6PointZeroPlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_0.address.zero_pad", field: "bn254_fr", arity: 2 }, +]; + +pub const STAGE6_POINT_SLICES: &[Stage6PointSlicePlan] = &[ + Stage6PointSlicePlan { symbol: "stage6.bytecode_read_raf.point.Cycle", source: "stage6.bytecode_read_raf.instance", offset: 10, length: 16, input: "stage6.bytecode_read_raf.instance" }, + Stage6PointSlicePlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_0.address.source", source: "stage6.bytecode_read_raf.instance", offset: 0, length: 2, input: "stage6.bytecode_read_raf.instance" }, + Stage6PointSlicePlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_1.address", source: "stage6.bytecode_read_raf.instance", offset: 2, length: 4, input: "stage6.bytecode_read_raf.instance" }, + Stage6PointSlicePlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_2.address", source: "stage6.bytecode_read_raf.instance", offset: 6, length: 4, input: "stage6.bytecode_read_raf.instance" }, + Stage6PointSlicePlan { symbol: "stage6.ram_ra_virtual.point.RamRa_0.address", source: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", offset: 0, length: 4, input: "stage6.input.stage5.ram_ra_claim_reduction.RamRa" }, + Stage6PointSlicePlan { symbol: "stage6.ram_ra_virtual.point.RamRa_1.address", source: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", offset: 4, length: 4, input: "stage6.input.stage5.ram_ra_claim_reduction.RamRa" }, + Stage6PointSlicePlan { symbol: "stage6.ram_ra_virtual.point.RamRa_2.address", source: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", offset: 8, length: 4, input: "stage6.input.stage5.ram_ra_claim_reduction.RamRa" }, + Stage6PointSlicePlan { symbol: "stage6.ram_ra_virtual.point.RamRa_3.address", source: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", offset: 12, length: 4, input: "stage6.input.stage5.ram_ra_claim_reduction.RamRa" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_0.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", offset: 0, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_0" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_1.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", offset: 4, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_0" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_2.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", offset: 8, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_0" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_3.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", offset: 12, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_0" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_4.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_1", offset: 0, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_1" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_5.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_1", offset: 4, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_1" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_6.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_1", offset: 8, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_1" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_7.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_1", offset: 12, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_1" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_8.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_2", offset: 0, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_2" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_9.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_2", offset: 4, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_2" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_10.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_2", offset: 8, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_2" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_11.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_2", offset: 12, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_2" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_12.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_3", offset: 0, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_3" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_13.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_3", offset: 4, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_3" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_14.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_3", offset: 8, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_3" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_15.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_3", offset: 12, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_3" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_16.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_4", offset: 0, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_4" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_17.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_4", offset: 4, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_4" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_18.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_4", offset: 8, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_4" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_19.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_4", offset: 12, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_4" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_20.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_5", offset: 0, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_5" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_21.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_5", offset: 4, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_5" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_22.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_5", offset: 8, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_5" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_23.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_5", offset: 12, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_5" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_24.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_6", offset: 0, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_6" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_25.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_6", offset: 4, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_6" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_26.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_6", offset: 8, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_6" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_27.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_6", offset: 12, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_6" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_28.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_7", offset: 0, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_7" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_29.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_7", offset: 4, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_7" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_30.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_7", offset: 8, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_7" }, + Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_31.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_7", offset: 12, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_7" }, +]; + +pub const STAGE6_POINT_CONCATS: &[Stage6PointConcatPlan] = &[ + Stage6PointConcatPlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_0.address", layout: "left_zero_padded_address_chunk", arity: 4, inputs: "stage6.bytecode_read_raf.point.BytecodeRa_0.address.zero_pad|stage6.bytecode_read_raf.point.BytecodeRa_0.address.source" }, + Stage6PointConcatPlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_0", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.bytecode_read_raf.point.BytecodeRa_0.address|stage6.bytecode_read_raf.point.Cycle" }, + Stage6PointConcatPlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_1", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.bytecode_read_raf.point.BytecodeRa_1.address|stage6.bytecode_read_raf.point.Cycle" }, + Stage6PointConcatPlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_2", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.bytecode_read_raf.point.BytecodeRa_2.address|stage6.bytecode_read_raf.point.Cycle" }, + Stage6PointConcatPlan { symbol: "stage6.ram_ra_virtual.point.RamRa_0", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.ram_ra_virtual.point.RamRa_0.address|stage6.ram_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.ram_ra_virtual.point.RamRa_1", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.ram_ra_virtual.point.RamRa_1.address|stage6.ram_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.ram_ra_virtual.point.RamRa_2", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.ram_ra_virtual.point.RamRa_2.address|stage6.ram_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.ram_ra_virtual.point.RamRa_3", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.ram_ra_virtual.point.RamRa_3.address|stage6.ram_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_0", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_0.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_1", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_1.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_2", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_2.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_3", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_3.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_4", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_4.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_5", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_5.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_6", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_6.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_7", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_7.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_8", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_8.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_9", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_9.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_10", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_10.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_11", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_11.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_12", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_12.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_13", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_13.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_14", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_14.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_15", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_15.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_16", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_16.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_17", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_17.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_18", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_18.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_19", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_19.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_20", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_20.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_21", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_21.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_22", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_22.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_23", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_23.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_24", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_24.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_25", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_25.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_26", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_26.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_27", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_27.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_28", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_28.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_29", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_29.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_30", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_30.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_31", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_31.address|stage6.instruction_ra_virtual.instance" }, +]; +pub const STAGE6_OPENING_CLAIMS: &[Stage6OpeningClaimPlan] = &[ + Stage6OpeningClaimPlan { symbol: "stage6.bytecode_read_raf.opening.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.bytecode_read_raf.point.BytecodeRa_0", eval_source: "stage6.bytecode_read_raf.eval.BytecodeRa_0" }, + Stage6OpeningClaimPlan { symbol: "stage6.bytecode_read_raf.opening.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.bytecode_read_raf.point.BytecodeRa_1", eval_source: "stage6.bytecode_read_raf.eval.BytecodeRa_1" }, + Stage6OpeningClaimPlan { symbol: "stage6.bytecode_read_raf.opening.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.bytecode_read_raf.point.BytecodeRa_2", eval_source: "stage6.bytecode_read_raf.eval.BytecodeRa_2" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_0" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_1" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_2" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_3" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_4" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_5" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_6" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_7" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_8" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_9" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_10" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_11" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_12" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_13" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_14" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_15" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_16" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_17" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_18" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_19" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_20" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_21" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_22" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_23" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_24" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_25" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_26" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_27" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_28" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_29" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_30" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_31" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.BytecodeRa_0" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.BytecodeRa_1" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.BytecodeRa_2" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.RamRa_0" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.RamRa_1" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.RamRa_2" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.RamRa_3" }, + Stage6OpeningClaimPlan { symbol: "stage6.hamming_booleanity.opening.HammingWeight", oracle: "HammingWeight", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage6.hamming_booleanity.instance", eval_source: "stage6.hamming_booleanity.eval.HammingWeight" }, + Stage6OpeningClaimPlan { symbol: "stage6.ram_ra_virtual.opening.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.ram_ra_virtual.point.RamRa_0", eval_source: "stage6.ram_ra_virtual.eval.RamRa_0" }, + Stage6OpeningClaimPlan { symbol: "stage6.ram_ra_virtual.opening.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.ram_ra_virtual.point.RamRa_1", eval_source: "stage6.ram_ra_virtual.eval.RamRa_1" }, + Stage6OpeningClaimPlan { symbol: "stage6.ram_ra_virtual.opening.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.ram_ra_virtual.point.RamRa_2", eval_source: "stage6.ram_ra_virtual.eval.RamRa_2" }, + Stage6OpeningClaimPlan { symbol: "stage6.ram_ra_virtual.opening.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.ram_ra_virtual.point.RamRa_3", eval_source: "stage6.ram_ra_virtual.eval.RamRa_3" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_0", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_0" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_1", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_1" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_2", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_2" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_3", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_3" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_4", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_4" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_5", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_5" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_6", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_6" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_7", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_7" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_8", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_8" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_9", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_9" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_10", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_10" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_11", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_11" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_12", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_12" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_13", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_13" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_14", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_14" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_15", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_15" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_16", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_16" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_17", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_17" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_18", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_18" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_19", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_19" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_20", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_20" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_21", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_21" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_22", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_22" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_23", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_23" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_24", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_24" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_25", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_25" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_26", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_26" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_27", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_27" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_28", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_28" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_29", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_29" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_30", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_30" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_31", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_31" }, + Stage6OpeningClaimPlan { symbol: "stage6.inc_claim_reduction.opening.RamInc", oracle: "RamInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed", point_source: "stage6.inc_claim_reduction.instance", eval_source: "stage6.inc_claim_reduction.eval.RamInc" }, + Stage6OpeningClaimPlan { symbol: "stage6.inc_claim_reduction.opening.RdInc", oracle: "RdInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed", point_source: "stage6.inc_claim_reduction.instance", eval_source: "stage6.inc_claim_reduction.eval.RdInc" }, +]; + +pub const STAGE6_OPENING_EQUALITIES: &[Stage6OpeningClaimEqualityPlan] = &[ + +]; + +pub const STAGE6_OPENING_BATCHES: &[Stage6OpeningBatchPlan] = &[ + Stage6OpeningBatchPlan { symbol: "stage6.openings", stage: "stage6", proof_slot: "stage6.openings", policy: "jolt_stage6_output_order", count: 81, ordered_claims: "stage6.bytecode_read_raf.opening.BytecodeRa_0|stage6.bytecode_read_raf.opening.BytecodeRa_1|stage6.bytecode_read_raf.opening.BytecodeRa_2|stage6.booleanity.opening.InstructionRa_0|stage6.booleanity.opening.InstructionRa_1|stage6.booleanity.opening.InstructionRa_2|stage6.booleanity.opening.InstructionRa_3|stage6.booleanity.opening.InstructionRa_4|stage6.booleanity.opening.InstructionRa_5|stage6.booleanity.opening.InstructionRa_6|stage6.booleanity.opening.InstructionRa_7|stage6.booleanity.opening.InstructionRa_8|stage6.booleanity.opening.InstructionRa_9|stage6.booleanity.opening.InstructionRa_10|stage6.booleanity.opening.InstructionRa_11|stage6.booleanity.opening.InstructionRa_12|stage6.booleanity.opening.InstructionRa_13|stage6.booleanity.opening.InstructionRa_14|stage6.booleanity.opening.InstructionRa_15|stage6.booleanity.opening.InstructionRa_16|stage6.booleanity.opening.InstructionRa_17|stage6.booleanity.opening.InstructionRa_18|stage6.booleanity.opening.InstructionRa_19|stage6.booleanity.opening.InstructionRa_20|stage6.booleanity.opening.InstructionRa_21|stage6.booleanity.opening.InstructionRa_22|stage6.booleanity.opening.InstructionRa_23|stage6.booleanity.opening.InstructionRa_24|stage6.booleanity.opening.InstructionRa_25|stage6.booleanity.opening.InstructionRa_26|stage6.booleanity.opening.InstructionRa_27|stage6.booleanity.opening.InstructionRa_28|stage6.booleanity.opening.InstructionRa_29|stage6.booleanity.opening.InstructionRa_30|stage6.booleanity.opening.InstructionRa_31|stage6.booleanity.opening.BytecodeRa_0|stage6.booleanity.opening.BytecodeRa_1|stage6.booleanity.opening.BytecodeRa_2|stage6.booleanity.opening.RamRa_0|stage6.booleanity.opening.RamRa_1|stage6.booleanity.opening.RamRa_2|stage6.booleanity.opening.RamRa_3|stage6.hamming_booleanity.opening.HammingWeight|stage6.ram_ra_virtual.opening.RamRa_0|stage6.ram_ra_virtual.opening.RamRa_1|stage6.ram_ra_virtual.opening.RamRa_2|stage6.ram_ra_virtual.opening.RamRa_3|stage6.instruction_ra_virtual.opening.InstructionRa_0|stage6.instruction_ra_virtual.opening.InstructionRa_1|stage6.instruction_ra_virtual.opening.InstructionRa_2|stage6.instruction_ra_virtual.opening.InstructionRa_3|stage6.instruction_ra_virtual.opening.InstructionRa_4|stage6.instruction_ra_virtual.opening.InstructionRa_5|stage6.instruction_ra_virtual.opening.InstructionRa_6|stage6.instruction_ra_virtual.opening.InstructionRa_7|stage6.instruction_ra_virtual.opening.InstructionRa_8|stage6.instruction_ra_virtual.opening.InstructionRa_9|stage6.instruction_ra_virtual.opening.InstructionRa_10|stage6.instruction_ra_virtual.opening.InstructionRa_11|stage6.instruction_ra_virtual.opening.InstructionRa_12|stage6.instruction_ra_virtual.opening.InstructionRa_13|stage6.instruction_ra_virtual.opening.InstructionRa_14|stage6.instruction_ra_virtual.opening.InstructionRa_15|stage6.instruction_ra_virtual.opening.InstructionRa_16|stage6.instruction_ra_virtual.opening.InstructionRa_17|stage6.instruction_ra_virtual.opening.InstructionRa_18|stage6.instruction_ra_virtual.opening.InstructionRa_19|stage6.instruction_ra_virtual.opening.InstructionRa_20|stage6.instruction_ra_virtual.opening.InstructionRa_21|stage6.instruction_ra_virtual.opening.InstructionRa_22|stage6.instruction_ra_virtual.opening.InstructionRa_23|stage6.instruction_ra_virtual.opening.InstructionRa_24|stage6.instruction_ra_virtual.opening.InstructionRa_25|stage6.instruction_ra_virtual.opening.InstructionRa_26|stage6.instruction_ra_virtual.opening.InstructionRa_27|stage6.instruction_ra_virtual.opening.InstructionRa_28|stage6.instruction_ra_virtual.opening.InstructionRa_29|stage6.instruction_ra_virtual.opening.InstructionRa_30|stage6.instruction_ra_virtual.opening.InstructionRa_31|stage6.inc_claim_reduction.opening.RamInc|stage6.inc_claim_reduction.opening.RdInc", claim_operands: "stage6.bytecode_read_raf.opening.BytecodeRa_0|stage6.bytecode_read_raf.opening.BytecodeRa_1|stage6.bytecode_read_raf.opening.BytecodeRa_2|stage6.booleanity.opening.InstructionRa_0|stage6.booleanity.opening.InstructionRa_1|stage6.booleanity.opening.InstructionRa_2|stage6.booleanity.opening.InstructionRa_3|stage6.booleanity.opening.InstructionRa_4|stage6.booleanity.opening.InstructionRa_5|stage6.booleanity.opening.InstructionRa_6|stage6.booleanity.opening.InstructionRa_7|stage6.booleanity.opening.InstructionRa_8|stage6.booleanity.opening.InstructionRa_9|stage6.booleanity.opening.InstructionRa_10|stage6.booleanity.opening.InstructionRa_11|stage6.booleanity.opening.InstructionRa_12|stage6.booleanity.opening.InstructionRa_13|stage6.booleanity.opening.InstructionRa_14|stage6.booleanity.opening.InstructionRa_15|stage6.booleanity.opening.InstructionRa_16|stage6.booleanity.opening.InstructionRa_17|stage6.booleanity.opening.InstructionRa_18|stage6.booleanity.opening.InstructionRa_19|stage6.booleanity.opening.InstructionRa_20|stage6.booleanity.opening.InstructionRa_21|stage6.booleanity.opening.InstructionRa_22|stage6.booleanity.opening.InstructionRa_23|stage6.booleanity.opening.InstructionRa_24|stage6.booleanity.opening.InstructionRa_25|stage6.booleanity.opening.InstructionRa_26|stage6.booleanity.opening.InstructionRa_27|stage6.booleanity.opening.InstructionRa_28|stage6.booleanity.opening.InstructionRa_29|stage6.booleanity.opening.InstructionRa_30|stage6.booleanity.opening.InstructionRa_31|stage6.booleanity.opening.BytecodeRa_0|stage6.booleanity.opening.BytecodeRa_1|stage6.booleanity.opening.BytecodeRa_2|stage6.booleanity.opening.RamRa_0|stage6.booleanity.opening.RamRa_1|stage6.booleanity.opening.RamRa_2|stage6.booleanity.opening.RamRa_3|stage6.hamming_booleanity.opening.HammingWeight|stage6.ram_ra_virtual.opening.RamRa_0|stage6.ram_ra_virtual.opening.RamRa_1|stage6.ram_ra_virtual.opening.RamRa_2|stage6.ram_ra_virtual.opening.RamRa_3|stage6.instruction_ra_virtual.opening.InstructionRa_0|stage6.instruction_ra_virtual.opening.InstructionRa_1|stage6.instruction_ra_virtual.opening.InstructionRa_2|stage6.instruction_ra_virtual.opening.InstructionRa_3|stage6.instruction_ra_virtual.opening.InstructionRa_4|stage6.instruction_ra_virtual.opening.InstructionRa_5|stage6.instruction_ra_virtual.opening.InstructionRa_6|stage6.instruction_ra_virtual.opening.InstructionRa_7|stage6.instruction_ra_virtual.opening.InstructionRa_8|stage6.instruction_ra_virtual.opening.InstructionRa_9|stage6.instruction_ra_virtual.opening.InstructionRa_10|stage6.instruction_ra_virtual.opening.InstructionRa_11|stage6.instruction_ra_virtual.opening.InstructionRa_12|stage6.instruction_ra_virtual.opening.InstructionRa_13|stage6.instruction_ra_virtual.opening.InstructionRa_14|stage6.instruction_ra_virtual.opening.InstructionRa_15|stage6.instruction_ra_virtual.opening.InstructionRa_16|stage6.instruction_ra_virtual.opening.InstructionRa_17|stage6.instruction_ra_virtual.opening.InstructionRa_18|stage6.instruction_ra_virtual.opening.InstructionRa_19|stage6.instruction_ra_virtual.opening.InstructionRa_20|stage6.instruction_ra_virtual.opening.InstructionRa_21|stage6.instruction_ra_virtual.opening.InstructionRa_22|stage6.instruction_ra_virtual.opening.InstructionRa_23|stage6.instruction_ra_virtual.opening.InstructionRa_24|stage6.instruction_ra_virtual.opening.InstructionRa_25|stage6.instruction_ra_virtual.opening.InstructionRa_26|stage6.instruction_ra_virtual.opening.InstructionRa_27|stage6.instruction_ra_virtual.opening.InstructionRa_28|stage6.instruction_ra_virtual.opening.InstructionRa_29|stage6.instruction_ra_virtual.opening.InstructionRa_30|stage6.instruction_ra_virtual.opening.InstructionRa_31|stage6.inc_claim_reduction.opening.RamInc|stage6.inc_claim_reduction.opening.RdInc" }, +]; +pub const STAGE6_PROGRAM: Stage6VerifierProgramPlan = Stage6CpuProgramPlan { + role: "verifier", + params: STAGE6_PARAMS, + steps: STAGE6_PROGRAM_STEPS, + transcript_squeezes: STAGE6_TRANSCRIPT_SQUEEZES, + transcript_absorb_bytes: STAGE6_TRANSCRIPT_ABSORB_BYTES, + opening_inputs: STAGE6_OPENING_INPUTS, + field_constants: STAGE6_FIELD_CONSTANTS, + field_exprs: STAGE6_FIELD_EXPRS, + kernels: STAGE6_KERNELS, + claims: STAGE6_SUMCHECK_CLAIMS, + batches: STAGE6_SUMCHECK_BATCHES, + drivers: STAGE6_SUMCHECK_DRIVERS, + instance_results: STAGE6_SUMCHECK_INSTANCE_RESULTS, + evals: STAGE6_SUMCHECK_EVALS, + point_zeros: STAGE6_POINT_ZEROS, + point_slices: STAGE6_POINT_SLICES, + point_concats: STAGE6_POINT_CONCATS, + opening_claims: STAGE6_OPENING_CLAIMS, + opening_equalities: STAGE6_OPENING_EQUALITIES, + opening_batches: STAGE6_OPENING_BATCHES, +}; + +pub fn verify_stage6( + proof: &Stage6Proof, + opening_inputs: &[Stage6OpeningInputValue], + verifier_data: Option<&Stage6VerifierData>, + transcript: &mut T, +) -> Result, VerifyStage6Error> +where + T: Transcript, +{ + verify_stage6_with_program(&STAGE6_PROGRAM, proof, opening_inputs, verifier_data, transcript) +} + +pub fn verify_stage6_with_program( + program: &'static Stage6VerifierProgramPlan, + proof: &Stage6Proof, + opening_inputs: &[Stage6OpeningInputValue], + verifier_data: Option<&Stage6VerifierData>, + transcript: &mut T, +) -> Result, VerifyStage6Error> +where + T: Transcript, +{ + if proof.sumchecks.len() != program.drivers.len() { + return Err(VerifyStage6Error::UnexpectedProofCount { + expected: program.drivers.len(), + got: proof.sumchecks.len(), + }); + } + let mut store = + super::common::ValueStore::with_opening_inputs(opening_inputs, program.opening_inputs)?; + store.seed_constants(program.field_constants); + store.seed_point_zeros(program.point_zeros); + let mut artifacts = Stage6ExecutionArtifacts::default(); + for step in program.steps { + match step.kind { + "transcript_squeeze" => { + let squeeze = + find_plan(program.transcript_squeezes, step.symbol).ok_or(VerifyStage6Error::MissingValue { + symbol: step.symbol, + })?; + verify_stage6_squeeze(program, squeeze, &mut store, transcript, &mut artifacts)?; + } + "transcript_absorb_bytes" => { + let absorb = find_plan(program.transcript_absorb_bytes, step.symbol).ok_or( + VerifyStage6Error::MissingValue { + symbol: step.symbol, + }, + )?; + absorb_stage6_bytes(absorb, transcript); + } + "sumcheck_driver" => { + let driver = + find_plan(program.drivers, step.symbol).ok_or(VerifyStage6Error::MissingProof { + driver: step.symbol, + })?; + verify_stage6_driver( + program, + driver, + proof, + verifier_data, + &mut store, + transcript, + &mut artifacts, + )?; + } + _ => { + return Err(VerifyStage6Error::InvalidProof { + driver: step.symbol, + reason: "unsupported stage6 program step", + }); + } + } + } + artifacts + .opening_batches + .extend(program.opening_batches.iter()); + Ok(artifacts) +} + +pub fn stage6_verifier_program() -> &'static Stage6VerifierProgramPlan { + &STAGE6_PROGRAM +} + +fn verify_stage6_squeeze( + program: &'static Stage6VerifierProgramPlan, + squeeze: &'static Stage6TranscriptSqueezePlan, + store: &mut super::common::ValueStore, + transcript: &mut T, + artifacts: &mut Stage6ExecutionArtifacts, +) -> Result<(), VerifyStage6Error> +where + T: Transcript, +{ + let values = transcript.challenge_vector(squeeze.count); + store.observe_challenge_vector(squeeze, &values, |input, expected, actual| { + VerifyStage6Error::InvalidInputLength { + input, + expected, + actual, + } + })?; + store + .evaluate_available_field_exprs(program.field_exprs, super::common::evaluate_field_expr) + .map_err(VerifyStage6Error::from)?; + artifacts.challenge_vectors.push(Stage6ChallengeVector { + symbol: squeeze.symbol, + values, + }); + Ok(()) +} + +fn absorb_stage6_bytes(absorb: &'static Stage6TranscriptAbsorbBytesPlan, transcript: &mut T) +where + T: Transcript, +{ + transcript.append(&LabelWithCount( + absorb.label.as_bytes(), + absorb.payload.len() as u64, + )); + transcript.append_bytes(absorb.payload.as_bytes()); +} + +fn verify_stage6_driver( + program: &'static Stage6VerifierProgramPlan, + driver: &'static Stage6SumcheckDriverPlan, + proof: &Stage6Proof, + verifier_data: Option<&Stage6VerifierData>, + store: &mut super::common::ValueStore, + transcript: &mut T, + artifacts: &mut Stage6ExecutionArtifacts, +) -> Result<(), VerifyStage6Error> +where + T: Transcript, +{ + let proof = proof + .sumchecks + .get(artifacts.sumchecks.len()) + .ok_or(VerifyStage6Error::MissingProof { + driver: driver.symbol, + })?; + let relation = driver.relation.unwrap_or(""); + let output = match relation { + "jolt.stage6.batched" => { + verify_batched_stage6(program, driver, proof, verifier_data, store, transcript)? + } + _ => return Err(VerifyStage6Error::UnsupportedRelation { relation }), + }; + artifacts.sumchecks.push(output); + Ok(()) +} + +fn verify_batched_stage6( + program: &'static Stage6VerifierProgramPlan, + driver: &'static Stage6SumcheckDriverPlan, + proof: &Stage6SumcheckOutput, + verifier_data: Option<&Stage6VerifierData>, + store: &mut super::common::ValueStore, + transcript: &mut T, +) -> Result, VerifyStage6Error> +where + T: Transcript, +{ + super::common::verify_batched_sumcheck( + driver, + proof, + program.claims, + program.batches, + program.field_exprs, + program.opening_inputs, + program.opening_claims, + program.opening_batches, + store, + transcript, + |store, evals, point, batching_coeffs| { + expected_batched_output_claim( + program, + driver, + verifier_data, + store, + evals, + point, + batching_coeffs, + ) + }, + |store, verified| observe_stage6_sumcheck_output(program, store, verified), + |driver, error| VerifyStage6Error::Sumcheck { driver, error }, + ) +} + +fn observe_stage6_sumcheck_output( + program: &'static Stage6VerifierProgramPlan, + store: &mut super::common::ValueStore, + output: &Stage6SumcheckOutput, +) -> Result<(), VerifyStage6Error> { + store.observe_sumcheck_output( + program.instance_results, + program.evals, + output, + |instance, mut point| { + match instance.point_order { + "as_is" => {} + "reverse" => point.reverse(), + "bytecode_read_raf" => point = normalize_bytecode_read_raf_point(&point, stage6_trace_rounds(program)?, "stage6.bytecode_read_raf.point")?, + "stage6_booleanity" => {} + "instruction_read_raf" => point = normalize_instruction_read_raf_point(&point, "stage6.instruction_read_raf.point")?, + _ => { + return Err(VerifyStage6Error::InvalidProof { + driver: output.driver, + reason: "unsupported point order", + }); + } + } + Ok(point) + }, + |input, expected, actual| VerifyStage6Error::InvalidInputLength { + input, + expected, + actual, + }, + |symbol| VerifyStage6Error::MissingValue { symbol }, + )?; + store.evaluate_available_points( + program.point_slices, + program.point_concats, + |input, expected, actual| VerifyStage6Error::InvalidInputLength { + input, + expected, + actual, + }, + )?; + store + .evaluate_available_field_exprs(program.field_exprs, super::common::evaluate_field_expr) + .map_err(VerifyStage6Error::from)?; + store.verify_opening_equalities( + program.opening_equalities, + |driver, reason| VerifyStage6Error::InvalidProof { driver, reason }, + |symbol| VerifyStage6Error::MissingValue { symbol }, + ) +} + +fn expected_batched_output_claim( + program: &'static Stage6VerifierProgramPlan, + driver: &'static Stage6SumcheckDriverPlan, + verifier_data: Option<&Stage6VerifierData>, + store: &super::common::ValueStore, + evals: &[Stage6NamedEval], + point: &[Fr], + batching_coeffs: &[Fr], +) -> Result { + let batch = find_batch(program.batches, driver.symbol, driver.batch)?; + let claims = batch_claims(program.claims, batch)?; + let mut expected = Fr::from_u64(0); + for (claim, coefficient) in claims.iter().zip(batching_coeffs) { + let instance = program + .instance_results + .iter() + .find(|instance| instance.claim == claim.symbol && instance.source == driver.symbol) + .ok_or(VerifyStage6Error::MissingClaim { + batch: batch.symbol, + claim: claim.symbol, + })?; + let local_point = point + .get(instance.round_offset..instance.round_offset + instance.num_rounds) + .ok_or(VerifyStage6Error::InvalidInputLength { + input: instance.symbol, + expected: instance.round_offset + instance.num_rounds, + actual: point.len(), + })?; + let relation = claim.relation.unwrap_or(""); + let value = match relation { + "jolt.stage6.bytecode_read_raf" => { + let data = verifier_data + .and_then(|data| data.bytecode_read_raf.as_ref()) + .ok_or(VerifyStage6Error::MissingValue { + symbol: "stage6.bytecode_read_raf.data", + })?; + expected_bytecode_read_raf(program, data, store, evals, local_point)? + } + "jolt.stage6.booleanity" => { + expected_booleanity(program, store, evals, local_point)? + } + "jolt.stage6.hamming_booleanity" => { + expected_hamming_booleanity(store, evals, local_point)? + } + "jolt.stage6.ram_ra_virtual" => { + expected_ram_ra_virtual(store, evals, local_point)? + } + "jolt.stage6.instruction_ra_virtual" => { + expected_instruction_ra_virtual(program, store, evals, local_point)? + } + "jolt.stage6.inc_claim_reduction" => { + expected_inc_claim_reduction(store, evals, local_point)? + } + _ => return Err(VerifyStage6Error::UnsupportedRelation { relation }), + }; + expected += *coefficient * value; + } + Ok(expected) +} + +fn expected_bytecode_read_raf( + program: &'static Stage6VerifierProgramPlan, + data: &Stage6BytecodeReadRafData, + store: &super::common::ValueStore, + evals: &[Stage6NamedEval], + local_point: &[Fr], +) -> Result { + let log_t = stage6_trace_rounds(program)?; + Ok(expected_stage67_bytecode_read_raf( + &data.entries, + data.entry_bytecode_index, + data.num_lookup_tables, + store, + evals, + local_point, + log_t, + &STAGE6_BYTECODE_SYMBOLS, + )?) +} + +fn expected_booleanity( + program: &'static Stage6VerifierProgramPlan, + store: &super::common::ValueStore, + evals: &[Stage6NamedEval], + local_point: &[Fr], +) -> Result { + let log_t = stage6_trace_rounds(program)?; + Ok(expected_stage67_booleanity(store, evals, local_point, log_t, &STAGE6_RELATION_SYMBOLS)?) +} + +fn expected_hamming_booleanity( + store: &super::common::ValueStore, + evals: &[Stage6NamedEval], + local_point: &[Fr], +) -> Result { + Ok(expected_stage67_hamming_booleanity(store, evals, local_point, &STAGE6_RELATION_SYMBOLS)?) +} + +fn expected_ram_ra_virtual( + store: &super::common::ValueStore, + evals: &[Stage6NamedEval], + local_point: &[Fr], +) -> Result { + Ok(expected_stage67_ram_ra_virtual(store, evals, local_point, &STAGE6_RELATION_SYMBOLS)?) +} + +fn expected_instruction_ra_virtual( + program: &'static Stage6VerifierProgramPlan, + store: &super::common::ValueStore, + evals: &[Stage6NamedEval], + local_point: &[Fr], +) -> Result { + Ok(expected_stage67_instruction_ra_virtual(program.opening_inputs, store, evals, local_point, &STAGE6_RELATION_SYMBOLS)?) +} + +fn expected_inc_claim_reduction( + store: &super::common::ValueStore, + evals: &[Stage6NamedEval], + local_point: &[Fr], +) -> Result { + Ok(expected_stage67_inc_claim_reduction(store, evals, local_point, &STAGE6_RELATION_SYMBOLS)?) +} + +fn stage6_trace_rounds( + program: &'static Stage6VerifierProgramPlan, +) -> Result { + Ok(stage67_trace_rounds(program.instance_results, &STAGE6_RELATION_SYMBOLS)?) +} diff --git a/crates/jolt-verifier/src/stages/stage7.rs b/crates/jolt-verifier/src/stages/stage7.rs new file mode 100644 index 0000000000..b85a769034 --- /dev/null +++ b/crates/jolt-verifier/src/stages/stage7.rs @@ -0,0 +1,682 @@ +#![allow(dead_code)] + +use super::common::{batch_claims, eval_by_name, find_batch, find_plan, normalize_bytecode_read_raf_point, normalize_instruction_read_raf_point, reverse_slice}; +use jolt_field::{Field, Fr}; +use jolt_poly::EqPolynomial; +use jolt_sumcheck::SumcheckError; +use jolt_transcript::{Blake2bTranscript, LabelWithCount, Transcript}; + +pub type Stage7NamedEval = super::common::StageNamedEval; +pub type Stage7SumcheckOutput = super::common::StageSumcheckOutput; +pub type Stage7ChallengeVector = super::common::StageChallengeVector; +pub type Stage7ExecutionArtifacts = super::common::StageExecutionArtifacts; +pub type Stage7Proof = super::common::StageProof; +pub type Stage7OpeningInputValue = super::common::StageOpeningInputValue; + +pub use super::common::{ + FieldConstantPlan as Stage7FieldConstantPlan, FieldExprPlan as Stage7FieldExprPlan, + KernelPlan as Stage7KernelPlan, OpeningBatchPlan as Stage7OpeningBatchPlan, + OpeningClaimEqualityPlan as Stage7OpeningClaimEqualityPlan, + OpeningClaimPlan as Stage7OpeningClaimPlan, OpeningInputPlan as Stage7OpeningInputPlan, + PointConcatPlan as Stage7PointConcatPlan, PointSlicePlan as Stage7PointSlicePlan, + PointZeroPlan as Stage7PointZeroPlan, ProgramStepPlan as Stage7ProgramStepPlan, + StageParams as Stage7Params, StageProgramPlan as Stage7CpuProgramPlan, + SumcheckBatchPlan as Stage7SumcheckBatchPlan, + SumcheckClaimPlan as Stage7SumcheckClaimPlan, SumcheckDriverPlan as Stage7SumcheckDriverPlan, + SumcheckEvalPlan as Stage7SumcheckEvalPlan, + SumcheckInstanceResultPlan as Stage7SumcheckInstanceResultPlan, + TranscriptAbsorbBytesPlan as Stage7TranscriptAbsorbBytesPlan, + TranscriptSqueezePlan as Stage7TranscriptSqueezePlan, +}; + +pub type DefaultStage7Transcript = Blake2bTranscript; +pub type Stage7VerifierProgramPlan = Stage7CpuProgramPlan; + +#[derive(Debug)] +pub enum VerifyStage7Error { + UnexpectedProofCount { expected: usize, got: usize }, + MissingProof { driver: &'static str }, + MissingBatch { driver: &'static str, batch: &'static str }, + MissingClaim { batch: &'static str, claim: &'static str }, + MissingValue { symbol: &'static str }, + InvalidInputLength { input: &'static str, expected: usize, actual: usize }, + InvalidProof { driver: &'static str, reason: &'static str }, + UnsupportedFieldExpr { symbol: &'static str, formula: &'static str }, + UnsupportedRelation { relation: &'static str }, + Sumcheck { driver: &'static str, error: SumcheckError }, +} + +super::common::impl_runtime_plan_error_conversion!(VerifyStage7Error); + +pub const STAGE7_PARAMS: Stage7Params = Stage7Params { + field: "bn254_fr", + pcs: "dory", + transcript: "blake2b_transcript", +}; +pub const STAGE7_PROGRAM_STEPS: &[Stage7ProgramStepPlan] = &[ + Stage7ProgramStepPlan { kind: "transcript_squeeze", symbol: "stage7.hamming_weight_claim_reduction.gamma" }, + Stage7ProgramStepPlan { kind: "sumcheck_driver", symbol: "stage7.sumcheck" }, +]; + +pub const STAGE7_TRANSCRIPT_SQUEEZES: &[Stage7TranscriptSqueezePlan] = &[ + Stage7TranscriptSqueezePlan { symbol: "stage7.hamming_weight_claim_reduction.gamma", label: "hamming_weight_claim_reduction_gamma", kind: "challenge_scalar", count: 1 }, +]; + +pub const STAGE7_TRANSCRIPT_ABSORB_BYTES: &[Stage7TranscriptAbsorbBytesPlan] = &[ + +]; + +pub const STAGE7_OPENING_INPUTS: &[Stage7OpeningInputPlan] = &[ + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.hamming_booleanity.HammingWeight", source_stage: "stage6", source_claim: "stage6.hamming_booleanity.opening.HammingWeight", oracle: "HammingWeight", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_0", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_0", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_1", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_1", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_2", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_2", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_3", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_3", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_4", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_4", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_5", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_5", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_6", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_6", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_7", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_7", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_8", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_8", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_9", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_9", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_10", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_10", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_11", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_11", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_12", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_12", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_13", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_13", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_14", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_14", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_15", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_15", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_16", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_16", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_17", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_17", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_18", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_18", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_19", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_19", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_20", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_20", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_21", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_21", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_22", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_22", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_23", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_23", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_24", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_24", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_25", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_25", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_26", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_26", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_27", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_27", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_28", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_28", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_29", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_29", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_30", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_30", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_31", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_31", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.BytecodeRa_0", source_stage: "stage6", source_claim: "stage6.booleanity.opening.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.bytecode_read_raf.BytecodeRa_0", source_stage: "stage6", source_claim: "stage6.bytecode_read_raf.opening.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.BytecodeRa_1", source_stage: "stage6", source_claim: "stage6.booleanity.opening.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.bytecode_read_raf.BytecodeRa_1", source_stage: "stage6", source_claim: "stage6.bytecode_read_raf.opening.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.BytecodeRa_2", source_stage: "stage6", source_claim: "stage6.booleanity.opening.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.bytecode_read_raf.BytecodeRa_2", source_stage: "stage6", source_claim: "stage6.bytecode_read_raf.opening.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.RamRa_0", source_stage: "stage6", source_claim: "stage6.booleanity.opening.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.ram_ra_virtual.RamRa_0", source_stage: "stage6", source_claim: "stage6.ram_ra_virtual.opening.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.RamRa_1", source_stage: "stage6", source_claim: "stage6.booleanity.opening.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.ram_ra_virtual.RamRa_1", source_stage: "stage6", source_claim: "stage6.ram_ra_virtual.opening.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.RamRa_2", source_stage: "stage6", source_claim: "stage6.booleanity.opening.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.ram_ra_virtual.RamRa_2", source_stage: "stage6", source_claim: "stage6.ram_ra_virtual.opening.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.RamRa_3", source_stage: "stage6", source_claim: "stage6.booleanity.opening.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.ram_ra_virtual.RamRa_3", source_stage: "stage6", source_claim: "stage6.ram_ra_virtual.opening.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, +]; + +pub const STAGE7_FIELD_CONSTANTS: &[Stage7FieldConstantPlan] = &[ + Stage7FieldConstantPlan { symbol: "stage7.field.one", field: "bn254_fr", value: 1 }, +]; + +macro_rules! stage7_field_expr { + ($symbol:literal, $formula:literal, $operands:literal) => { + Stage7FieldExprPlan { symbol: $symbol, kind: "op", formula: $formula, operands: $operands } + }; +} + +#[rustfmt::skip] +pub const STAGE7_FIELD_EXPRS: &[Stage7FieldExprPlan] = &[ + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.0.booleanity.gamma_pow", "field.pow:1", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.0.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.0.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_0"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.0.virtualization.gamma_pow", "field.pow:2", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.0.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.0.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_0"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.1.hw.gamma_pow", "field.pow:3", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.1.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.1.hw.gamma_pow|stage7.field.one"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.1.booleanity.gamma_pow", "field.pow:4", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.1.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.1.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_1"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.1.virtualization.gamma_pow", "field.pow:5", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.1.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.1.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_1"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.2.hw.gamma_pow", "field.pow:6", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.2.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.2.hw.gamma_pow|stage7.field.one"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.2.booleanity.gamma_pow", "field.pow:7", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.2.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.2.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_2"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.2.virtualization.gamma_pow", "field.pow:8", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.2.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.2.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_2"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.3.hw.gamma_pow", "field.pow:9", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.3.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.3.hw.gamma_pow|stage7.field.one"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.3.booleanity.gamma_pow", "field.pow:10", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.3.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.3.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_3"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.3.virtualization.gamma_pow", "field.pow:11", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.3.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.3.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_3"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.4.hw.gamma_pow", "field.pow:12", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.4.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.4.hw.gamma_pow|stage7.field.one"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.4.booleanity.gamma_pow", "field.pow:13", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.4.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.4.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_4"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.4.virtualization.gamma_pow", "field.pow:14", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.4.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.4.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_4"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.5.hw.gamma_pow", "field.pow:15", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.5.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.5.hw.gamma_pow|stage7.field.one"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.5.booleanity.gamma_pow", "field.pow:16", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.5.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.5.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_5"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.5.virtualization.gamma_pow", "field.pow:17", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.5.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.5.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_5"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.6.hw.gamma_pow", "field.pow:18", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.6.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.6.hw.gamma_pow|stage7.field.one"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.6.booleanity.gamma_pow", "field.pow:19", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.6.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.6.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_6"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.6.virtualization.gamma_pow", "field.pow:20", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.6.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.6.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_6"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.7.hw.gamma_pow", "field.pow:21", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.7.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.7.hw.gamma_pow|stage7.field.one"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.7.booleanity.gamma_pow", "field.pow:22", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.7.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.7.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_7"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.7.virtualization.gamma_pow", "field.pow:23", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.7.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.7.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_7"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.8.hw.gamma_pow", "field.pow:24", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.8.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.8.hw.gamma_pow|stage7.field.one"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.8.booleanity.gamma_pow", "field.pow:25", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.8.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.8.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_8"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.8.virtualization.gamma_pow", "field.pow:26", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.8.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.8.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_8"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.9.hw.gamma_pow", "field.pow:27", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.9.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.9.hw.gamma_pow|stage7.field.one"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.9.booleanity.gamma_pow", "field.pow:28", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.9.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.9.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_9"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.9.virtualization.gamma_pow", "field.pow:29", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.9.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.9.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_9"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.10.hw.gamma_pow", "field.pow:30", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.10.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.10.hw.gamma_pow|stage7.field.one"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.10.booleanity.gamma_pow", "field.pow:31", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.10.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.10.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_10"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.10.virtualization.gamma_pow", "field.pow:32", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.10.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.10.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_10"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.11.hw.gamma_pow", "field.pow:33", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.11.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.11.hw.gamma_pow|stage7.field.one"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.11.booleanity.gamma_pow", "field.pow:34", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.11.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.11.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_11"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.11.virtualization.gamma_pow", "field.pow:35", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.11.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.11.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_11"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.12.hw.gamma_pow", "field.pow:36", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.12.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.12.hw.gamma_pow|stage7.field.one"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.12.booleanity.gamma_pow", "field.pow:37", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.12.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.12.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_12"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.12.virtualization.gamma_pow", "field.pow:38", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.12.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.12.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_12"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.13.hw.gamma_pow", "field.pow:39", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.13.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.13.hw.gamma_pow|stage7.field.one"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.13.booleanity.gamma_pow", "field.pow:40", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.13.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.13.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_13"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.13.virtualization.gamma_pow", "field.pow:41", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.13.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.13.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_13"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.14.hw.gamma_pow", "field.pow:42", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.14.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.14.hw.gamma_pow|stage7.field.one"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.14.booleanity.gamma_pow", "field.pow:43", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.14.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.14.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_14"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.14.virtualization.gamma_pow", "field.pow:44", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.14.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.14.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_14"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.15.hw.gamma_pow", "field.pow:45", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.15.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.15.hw.gamma_pow|stage7.field.one"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.15.booleanity.gamma_pow", "field.pow:46", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.15.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.15.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_15"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.15.virtualization.gamma_pow", "field.pow:47", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.15.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.15.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_15"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.16.hw.gamma_pow", "field.pow:48", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.16.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.16.hw.gamma_pow|stage7.field.one"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.16.booleanity.gamma_pow", "field.pow:49", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.16.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.16.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_16"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.16.virtualization.gamma_pow", "field.pow:50", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.16.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.16.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_16"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.17.hw.gamma_pow", "field.pow:51", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.17.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.17.hw.gamma_pow|stage7.field.one"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.17.booleanity.gamma_pow", "field.pow:52", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.17.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.17.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_17"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.17.virtualization.gamma_pow", "field.pow:53", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.17.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.17.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_17"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.18.hw.gamma_pow", "field.pow:54", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.18.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.18.hw.gamma_pow|stage7.field.one"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.18.booleanity.gamma_pow", "field.pow:55", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.18.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.18.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_18"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.18.virtualization.gamma_pow", "field.pow:56", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.18.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.18.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_18"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.19.hw.gamma_pow", "field.pow:57", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.19.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.19.hw.gamma_pow|stage7.field.one"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.19.booleanity.gamma_pow", "field.pow:58", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.19.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.19.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_19"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.19.virtualization.gamma_pow", "field.pow:59", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.19.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.19.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_19"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.20.hw.gamma_pow", "field.pow:60", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.20.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.20.hw.gamma_pow|stage7.field.one"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.20.booleanity.gamma_pow", "field.pow:61", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.20.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.20.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_20"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.20.virtualization.gamma_pow", "field.pow:62", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.20.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.20.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_20"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.21.hw.gamma_pow", "field.pow:63", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.21.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.21.hw.gamma_pow|stage7.field.one"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.21.booleanity.gamma_pow", "field.pow:64", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.21.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.21.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_21"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.21.virtualization.gamma_pow", "field.pow:65", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.21.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.21.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_21"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.22.hw.gamma_pow", "field.pow:66", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.22.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.22.hw.gamma_pow|stage7.field.one"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.22.booleanity.gamma_pow", "field.pow:67", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.22.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.22.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_22"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.22.virtualization.gamma_pow", "field.pow:68", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.22.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.22.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_22"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.23.hw.gamma_pow", "field.pow:69", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.23.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.23.hw.gamma_pow|stage7.field.one"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.23.booleanity.gamma_pow", "field.pow:70", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.23.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.23.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_23"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.23.virtualization.gamma_pow", "field.pow:71", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.23.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.23.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_23"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.24.hw.gamma_pow", "field.pow:72", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.24.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.24.hw.gamma_pow|stage7.field.one"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.24.booleanity.gamma_pow", "field.pow:73", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.24.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.24.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_24"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.24.virtualization.gamma_pow", "field.pow:74", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.24.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.24.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_24"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.25.hw.gamma_pow", "field.pow:75", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.25.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.25.hw.gamma_pow|stage7.field.one"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.25.booleanity.gamma_pow", "field.pow:76", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.25.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.25.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_25"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.25.virtualization.gamma_pow", "field.pow:77", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.25.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.25.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_25"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.26.hw.gamma_pow", "field.pow:78", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.26.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.26.hw.gamma_pow|stage7.field.one"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.26.booleanity.gamma_pow", "field.pow:79", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.26.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.26.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_26"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.26.virtualization.gamma_pow", "field.pow:80", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.26.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.26.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_26"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.27.hw.gamma_pow", "field.pow:81", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.27.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.27.hw.gamma_pow|stage7.field.one"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.27.booleanity.gamma_pow", "field.pow:82", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.27.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.27.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_27"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.27.virtualization.gamma_pow", "field.pow:83", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.27.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.27.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_27"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.28.hw.gamma_pow", "field.pow:84", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.28.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.28.hw.gamma_pow|stage7.field.one"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.28.booleanity.gamma_pow", "field.pow:85", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.28.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.28.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_28"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.28.virtualization.gamma_pow", "field.pow:86", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.28.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.28.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_28"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.29.hw.gamma_pow", "field.pow:87", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.29.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.29.hw.gamma_pow|stage7.field.one"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.29.booleanity.gamma_pow", "field.pow:88", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.29.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.29.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_29"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.29.virtualization.gamma_pow", "field.pow:89", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.29.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.29.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_29"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.30.hw.gamma_pow", "field.pow:90", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.30.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.30.hw.gamma_pow|stage7.field.one"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.30.booleanity.gamma_pow", "field.pow:91", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.30.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.30.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_30"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.30.virtualization.gamma_pow", "field.pow:92", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.30.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.30.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_30"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.31.hw.gamma_pow", "field.pow:93", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.31.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.31.hw.gamma_pow|stage7.field.one"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.31.booleanity.gamma_pow", "field.pow:94", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.31.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.31.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_31"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.31.virtualization.gamma_pow", "field.pow:95", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.31.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.31.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_31"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.32.hw.gamma_pow", "field.pow:96", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.32.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.32.hw.gamma_pow|stage7.field.one"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.32.booleanity.gamma_pow", "field.pow:97", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.32.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.32.booleanity.gamma_pow|stage7.input.stage6.booleanity.BytecodeRa_0"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.32.virtualization.gamma_pow", "field.pow:98", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.32.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.32.virtualization.gamma_pow|stage7.input.stage6.bytecode_read_raf.BytecodeRa_0"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.33.hw.gamma_pow", "field.pow:99", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.33.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.33.hw.gamma_pow|stage7.field.one"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.33.booleanity.gamma_pow", "field.pow:100", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.33.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.33.booleanity.gamma_pow|stage7.input.stage6.booleanity.BytecodeRa_1"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.33.virtualization.gamma_pow", "field.pow:101", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.33.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.33.virtualization.gamma_pow|stage7.input.stage6.bytecode_read_raf.BytecodeRa_1"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.34.hw.gamma_pow", "field.pow:102", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.34.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.34.hw.gamma_pow|stage7.field.one"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.34.booleanity.gamma_pow", "field.pow:103", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.34.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.34.booleanity.gamma_pow|stage7.input.stage6.booleanity.BytecodeRa_2"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.34.virtualization.gamma_pow", "field.pow:104", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.34.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.34.virtualization.gamma_pow|stage7.input.stage6.bytecode_read_raf.BytecodeRa_2"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.35.hw.gamma_pow", "field.pow:105", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.35.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.35.hw.gamma_pow|stage7.input.stage6.hamming_booleanity.HammingWeight"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.35.booleanity.gamma_pow", "field.pow:106", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.35.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.35.booleanity.gamma_pow|stage7.input.stage6.booleanity.RamRa_0"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.35.virtualization.gamma_pow", "field.pow:107", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.35.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.35.virtualization.gamma_pow|stage7.input.stage6.ram_ra_virtual.RamRa_0"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.36.hw.gamma_pow", "field.pow:108", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.36.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.36.hw.gamma_pow|stage7.input.stage6.hamming_booleanity.HammingWeight"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.36.booleanity.gamma_pow", "field.pow:109", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.36.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.36.booleanity.gamma_pow|stage7.input.stage6.booleanity.RamRa_1"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.36.virtualization.gamma_pow", "field.pow:110", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.36.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.36.virtualization.gamma_pow|stage7.input.stage6.ram_ra_virtual.RamRa_1"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.37.hw.gamma_pow", "field.pow:111", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.37.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.37.hw.gamma_pow|stage7.input.stage6.hamming_booleanity.HammingWeight"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.37.booleanity.gamma_pow", "field.pow:112", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.37.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.37.booleanity.gamma_pow|stage7.input.stage6.booleanity.RamRa_2"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.37.virtualization.gamma_pow", "field.pow:113", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.37.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.37.virtualization.gamma_pow|stage7.input.stage6.ram_ra_virtual.RamRa_2"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.38.hw.gamma_pow", "field.pow:114", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.38.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.38.hw.gamma_pow|stage7.input.stage6.hamming_booleanity.HammingWeight"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.38.booleanity.gamma_pow", "field.pow:115", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.38.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.38.booleanity.gamma_pow|stage7.input.stage6.booleanity.RamRa_3"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.38.virtualization.gamma_pow", "field.pow:116", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.38.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.38.virtualization.gamma_pow|stage7.input.stage6.ram_ra_virtual.RamRa_3"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial0", "field.add", "stage7.field.one|stage7.hamming_weight_claim_reduction.claim.0.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial1", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial0|stage7.hamming_weight_claim_reduction.claim.0.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial2", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial1|stage7.hamming_weight_claim_reduction.claim.1.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial3", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial2|stage7.hamming_weight_claim_reduction.claim.1.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial4", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial3|stage7.hamming_weight_claim_reduction.claim.1.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial5", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial4|stage7.hamming_weight_claim_reduction.claim.2.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial6", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial5|stage7.hamming_weight_claim_reduction.claim.2.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial7", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial6|stage7.hamming_weight_claim_reduction.claim.2.virtualization.gamma_term"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial8", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial7|stage7.hamming_weight_claim_reduction.claim.3.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial9", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial8|stage7.hamming_weight_claim_reduction.claim.3.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial10", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial9|stage7.hamming_weight_claim_reduction.claim.3.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial11", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial10|stage7.hamming_weight_claim_reduction.claim.4.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial12", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial11|stage7.hamming_weight_claim_reduction.claim.4.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial13", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial12|stage7.hamming_weight_claim_reduction.claim.4.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial14", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial13|stage7.hamming_weight_claim_reduction.claim.5.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial15", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial14|stage7.hamming_weight_claim_reduction.claim.5.booleanity.gamma_term"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial16", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial15|stage7.hamming_weight_claim_reduction.claim.5.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial17", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial16|stage7.hamming_weight_claim_reduction.claim.6.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial18", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial17|stage7.hamming_weight_claim_reduction.claim.6.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial19", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial18|stage7.hamming_weight_claim_reduction.claim.6.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial20", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial19|stage7.hamming_weight_claim_reduction.claim.7.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial21", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial20|stage7.hamming_weight_claim_reduction.claim.7.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial22", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial21|stage7.hamming_weight_claim_reduction.claim.7.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial23", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial22|stage7.hamming_weight_claim_reduction.claim.8.hw.gamma_term"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial24", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial23|stage7.hamming_weight_claim_reduction.claim.8.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial25", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial24|stage7.hamming_weight_claim_reduction.claim.8.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial26", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial25|stage7.hamming_weight_claim_reduction.claim.9.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial27", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial26|stage7.hamming_weight_claim_reduction.claim.9.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial28", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial27|stage7.hamming_weight_claim_reduction.claim.9.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial29", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial28|stage7.hamming_weight_claim_reduction.claim.10.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial30", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial29|stage7.hamming_weight_claim_reduction.claim.10.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial31", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial30|stage7.hamming_weight_claim_reduction.claim.10.virtualization.gamma_term"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial32", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial31|stage7.hamming_weight_claim_reduction.claim.11.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial33", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial32|stage7.hamming_weight_claim_reduction.claim.11.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial34", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial33|stage7.hamming_weight_claim_reduction.claim.11.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial35", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial34|stage7.hamming_weight_claim_reduction.claim.12.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial36", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial35|stage7.hamming_weight_claim_reduction.claim.12.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial37", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial36|stage7.hamming_weight_claim_reduction.claim.12.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial38", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial37|stage7.hamming_weight_claim_reduction.claim.13.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial39", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial38|stage7.hamming_weight_claim_reduction.claim.13.booleanity.gamma_term"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial40", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial39|stage7.hamming_weight_claim_reduction.claim.13.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial41", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial40|stage7.hamming_weight_claim_reduction.claim.14.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial42", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial41|stage7.hamming_weight_claim_reduction.claim.14.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial43", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial42|stage7.hamming_weight_claim_reduction.claim.14.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial44", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial43|stage7.hamming_weight_claim_reduction.claim.15.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial45", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial44|stage7.hamming_weight_claim_reduction.claim.15.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial46", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial45|stage7.hamming_weight_claim_reduction.claim.15.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial47", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial46|stage7.hamming_weight_claim_reduction.claim.16.hw.gamma_term"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial48", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial47|stage7.hamming_weight_claim_reduction.claim.16.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial49", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial48|stage7.hamming_weight_claim_reduction.claim.16.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial50", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial49|stage7.hamming_weight_claim_reduction.claim.17.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial51", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial50|stage7.hamming_weight_claim_reduction.claim.17.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial52", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial51|stage7.hamming_weight_claim_reduction.claim.17.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial53", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial52|stage7.hamming_weight_claim_reduction.claim.18.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial54", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial53|stage7.hamming_weight_claim_reduction.claim.18.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial55", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial54|stage7.hamming_weight_claim_reduction.claim.18.virtualization.gamma_term"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial56", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial55|stage7.hamming_weight_claim_reduction.claim.19.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial57", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial56|stage7.hamming_weight_claim_reduction.claim.19.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial58", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial57|stage7.hamming_weight_claim_reduction.claim.19.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial59", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial58|stage7.hamming_weight_claim_reduction.claim.20.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial60", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial59|stage7.hamming_weight_claim_reduction.claim.20.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial61", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial60|stage7.hamming_weight_claim_reduction.claim.20.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial62", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial61|stage7.hamming_weight_claim_reduction.claim.21.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial63", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial62|stage7.hamming_weight_claim_reduction.claim.21.booleanity.gamma_term"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial64", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial63|stage7.hamming_weight_claim_reduction.claim.21.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial65", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial64|stage7.hamming_weight_claim_reduction.claim.22.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial66", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial65|stage7.hamming_weight_claim_reduction.claim.22.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial67", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial66|stage7.hamming_weight_claim_reduction.claim.22.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial68", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial67|stage7.hamming_weight_claim_reduction.claim.23.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial69", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial68|stage7.hamming_weight_claim_reduction.claim.23.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial70", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial69|stage7.hamming_weight_claim_reduction.claim.23.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial71", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial70|stage7.hamming_weight_claim_reduction.claim.24.hw.gamma_term"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial72", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial71|stage7.hamming_weight_claim_reduction.claim.24.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial73", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial72|stage7.hamming_weight_claim_reduction.claim.24.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial74", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial73|stage7.hamming_weight_claim_reduction.claim.25.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial75", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial74|stage7.hamming_weight_claim_reduction.claim.25.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial76", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial75|stage7.hamming_weight_claim_reduction.claim.25.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial77", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial76|stage7.hamming_weight_claim_reduction.claim.26.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial78", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial77|stage7.hamming_weight_claim_reduction.claim.26.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial79", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial78|stage7.hamming_weight_claim_reduction.claim.26.virtualization.gamma_term"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial80", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial79|stage7.hamming_weight_claim_reduction.claim.27.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial81", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial80|stage7.hamming_weight_claim_reduction.claim.27.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial82", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial81|stage7.hamming_weight_claim_reduction.claim.27.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial83", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial82|stage7.hamming_weight_claim_reduction.claim.28.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial84", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial83|stage7.hamming_weight_claim_reduction.claim.28.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial85", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial84|stage7.hamming_weight_claim_reduction.claim.28.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial86", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial85|stage7.hamming_weight_claim_reduction.claim.29.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial87", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial86|stage7.hamming_weight_claim_reduction.claim.29.booleanity.gamma_term"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial88", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial87|stage7.hamming_weight_claim_reduction.claim.29.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial89", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial88|stage7.hamming_weight_claim_reduction.claim.30.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial90", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial89|stage7.hamming_weight_claim_reduction.claim.30.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial91", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial90|stage7.hamming_weight_claim_reduction.claim.30.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial92", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial91|stage7.hamming_weight_claim_reduction.claim.31.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial93", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial92|stage7.hamming_weight_claim_reduction.claim.31.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial94", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial93|stage7.hamming_weight_claim_reduction.claim.31.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial95", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial94|stage7.hamming_weight_claim_reduction.claim.32.hw.gamma_term"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial96", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial95|stage7.hamming_weight_claim_reduction.claim.32.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial97", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial96|stage7.hamming_weight_claim_reduction.claim.32.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial98", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial97|stage7.hamming_weight_claim_reduction.claim.33.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial99", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial98|stage7.hamming_weight_claim_reduction.claim.33.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial100", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial99|stage7.hamming_weight_claim_reduction.claim.33.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial101", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial100|stage7.hamming_weight_claim_reduction.claim.34.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial102", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial101|stage7.hamming_weight_claim_reduction.claim.34.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial103", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial102|stage7.hamming_weight_claim_reduction.claim.34.virtualization.gamma_term"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial104", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial103|stage7.hamming_weight_claim_reduction.claim.35.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial105", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial104|stage7.hamming_weight_claim_reduction.claim.35.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial106", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial105|stage7.hamming_weight_claim_reduction.claim.35.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial107", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial106|stage7.hamming_weight_claim_reduction.claim.36.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial108", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial107|stage7.hamming_weight_claim_reduction.claim.36.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial109", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial108|stage7.hamming_weight_claim_reduction.claim.36.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial110", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial109|stage7.hamming_weight_claim_reduction.claim.37.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial111", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial110|stage7.hamming_weight_claim_reduction.claim.37.booleanity.gamma_term"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial112", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial111|stage7.hamming_weight_claim_reduction.claim.37.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial113", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial112|stage7.hamming_weight_claim_reduction.claim.38.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial114", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial113|stage7.hamming_weight_claim_reduction.claim.38.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial115", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial114|stage7.hamming_weight_claim_reduction.claim.38.virtualization.gamma_term"), +]; +pub const STAGE7_KERNELS: &[Stage7KernelPlan] = &[ + +]; + +pub const STAGE7_SUMCHECK_CLAIMS: &[Stage7SumcheckClaimPlan] = &[ + Stage7SumcheckClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.input", stage: "stage7", domain: "jolt.stage7_hamming_weight_claim_reduction_domain", num_rounds: 4, degree: 2, claim: "stage7.hamming_weight_claim_reduction.weighted_stage6_claims", kernel: None, relation: Some("jolt.stage7.hamming_weight_claim_reduction"), claim_value: "stage7.hamming_weight_claim_reduction.claim_expr.partial115", input_openings: "stage7.input.stage6.hamming_booleanity.HammingWeight|stage7.input.stage6.booleanity.InstructionRa_0|stage7.input.stage6.instruction_ra_virtual.InstructionRa_0|stage7.input.stage6.booleanity.InstructionRa_1|stage7.input.stage6.instruction_ra_virtual.InstructionRa_1|stage7.input.stage6.booleanity.InstructionRa_2|stage7.input.stage6.instruction_ra_virtual.InstructionRa_2|stage7.input.stage6.booleanity.InstructionRa_3|stage7.input.stage6.instruction_ra_virtual.InstructionRa_3|stage7.input.stage6.booleanity.InstructionRa_4|stage7.input.stage6.instruction_ra_virtual.InstructionRa_4|stage7.input.stage6.booleanity.InstructionRa_5|stage7.input.stage6.instruction_ra_virtual.InstructionRa_5|stage7.input.stage6.booleanity.InstructionRa_6|stage7.input.stage6.instruction_ra_virtual.InstructionRa_6|stage7.input.stage6.booleanity.InstructionRa_7|stage7.input.stage6.instruction_ra_virtual.InstructionRa_7|stage7.input.stage6.booleanity.InstructionRa_8|stage7.input.stage6.instruction_ra_virtual.InstructionRa_8|stage7.input.stage6.booleanity.InstructionRa_9|stage7.input.stage6.instruction_ra_virtual.InstructionRa_9|stage7.input.stage6.booleanity.InstructionRa_10|stage7.input.stage6.instruction_ra_virtual.InstructionRa_10|stage7.input.stage6.booleanity.InstructionRa_11|stage7.input.stage6.instruction_ra_virtual.InstructionRa_11|stage7.input.stage6.booleanity.InstructionRa_12|stage7.input.stage6.instruction_ra_virtual.InstructionRa_12|stage7.input.stage6.booleanity.InstructionRa_13|stage7.input.stage6.instruction_ra_virtual.InstructionRa_13|stage7.input.stage6.booleanity.InstructionRa_14|stage7.input.stage6.instruction_ra_virtual.InstructionRa_14|stage7.input.stage6.booleanity.InstructionRa_15|stage7.input.stage6.instruction_ra_virtual.InstructionRa_15|stage7.input.stage6.booleanity.InstructionRa_16|stage7.input.stage6.instruction_ra_virtual.InstructionRa_16|stage7.input.stage6.booleanity.InstructionRa_17|stage7.input.stage6.instruction_ra_virtual.InstructionRa_17|stage7.input.stage6.booleanity.InstructionRa_18|stage7.input.stage6.instruction_ra_virtual.InstructionRa_18|stage7.input.stage6.booleanity.InstructionRa_19|stage7.input.stage6.instruction_ra_virtual.InstructionRa_19|stage7.input.stage6.booleanity.InstructionRa_20|stage7.input.stage6.instruction_ra_virtual.InstructionRa_20|stage7.input.stage6.booleanity.InstructionRa_21|stage7.input.stage6.instruction_ra_virtual.InstructionRa_21|stage7.input.stage6.booleanity.InstructionRa_22|stage7.input.stage6.instruction_ra_virtual.InstructionRa_22|stage7.input.stage6.booleanity.InstructionRa_23|stage7.input.stage6.instruction_ra_virtual.InstructionRa_23|stage7.input.stage6.booleanity.InstructionRa_24|stage7.input.stage6.instruction_ra_virtual.InstructionRa_24|stage7.input.stage6.booleanity.InstructionRa_25|stage7.input.stage6.instruction_ra_virtual.InstructionRa_25|stage7.input.stage6.booleanity.InstructionRa_26|stage7.input.stage6.instruction_ra_virtual.InstructionRa_26|stage7.input.stage6.booleanity.InstructionRa_27|stage7.input.stage6.instruction_ra_virtual.InstructionRa_27|stage7.input.stage6.booleanity.InstructionRa_28|stage7.input.stage6.instruction_ra_virtual.InstructionRa_28|stage7.input.stage6.booleanity.InstructionRa_29|stage7.input.stage6.instruction_ra_virtual.InstructionRa_29|stage7.input.stage6.booleanity.InstructionRa_30|stage7.input.stage6.instruction_ra_virtual.InstructionRa_30|stage7.input.stage6.booleanity.InstructionRa_31|stage7.input.stage6.instruction_ra_virtual.InstructionRa_31|stage7.input.stage6.booleanity.BytecodeRa_0|stage7.input.stage6.bytecode_read_raf.BytecodeRa_0|stage7.input.stage6.booleanity.BytecodeRa_1|stage7.input.stage6.bytecode_read_raf.BytecodeRa_1|stage7.input.stage6.booleanity.BytecodeRa_2|stage7.input.stage6.bytecode_read_raf.BytecodeRa_2|stage7.input.stage6.booleanity.RamRa_0|stage7.input.stage6.ram_ra_virtual.RamRa_0|stage7.input.stage6.booleanity.RamRa_1|stage7.input.stage6.ram_ra_virtual.RamRa_1|stage7.input.stage6.booleanity.RamRa_2|stage7.input.stage6.ram_ra_virtual.RamRa_2|stage7.input.stage6.booleanity.RamRa_3|stage7.input.stage6.ram_ra_virtual.RamRa_3" }, +]; +pub const STAGE7_SUMCHECK_BATCH_0_ROUND_SCHEDULE: &[usize] = &[ + 4, +]; + +pub const STAGE7_SUMCHECK_BATCHES: &[Stage7SumcheckBatchPlan] = &[ + Stage7SumcheckBatchPlan { symbol: "stage7.batch", stage: "stage7", proof_slot: "stage7.sumcheck", policy: "jolt_core_stage7_aligned", count: 1, ordered_claims: "stage7.hamming_weight_claim_reduction.input", claim_operands: "stage7.hamming_weight_claim_reduction.input", claim_label: "sumcheck_claim", round_label: "sumcheck_poly", round_schedule: STAGE7_SUMCHECK_BATCH_0_ROUND_SCHEDULE }, +]; +pub const STAGE7_SUMCHECK_DRIVER_0_ROUND_SCHEDULE: &[usize] = &[ + 4, +]; + +pub const STAGE7_SUMCHECK_DRIVERS: &[Stage7SumcheckDriverPlan] = &[ + Stage7SumcheckDriverPlan { symbol: "stage7.sumcheck", stage: "stage7", proof_slot: "stage7.sumcheck", kernel: None, relation: Some("jolt.stage7.batched"), batch: "stage7.batch", policy: "jolt_core_stage7_aligned", round_schedule: STAGE7_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 4, degree: 2 }, +]; +pub const STAGE7_SUMCHECK_INSTANCE_RESULTS: &[Stage7SumcheckInstanceResultPlan] = &[ + Stage7SumcheckInstanceResultPlan { symbol: "stage7.hamming_weight_claim_reduction.instance", source: "stage7.sumcheck", claim: "stage7.hamming_weight_claim_reduction.input", relation: "jolt.stage7.hamming_weight_claim_reduction", index: 0, point_arity: 4, num_rounds: 4, round_offset: 0, point_order: "reverse", degree: 2 }, +]; + +macro_rules! stage7_sumcheck_eval { + ($symbol:literal, $source:literal, $name:literal, $index:literal, $oracle:literal) => { + Stage7SumcheckEvalPlan { symbol: $symbol, source: $source, name: $name, index: $index, oracle: $oracle } + }; +} + +#[rustfmt::skip] +pub const STAGE7_SUMCHECK_EVALS: &[Stage7SumcheckEvalPlan] = &[ + stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_0", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_0", 0, "InstructionRa_0"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_1", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_1", 1, "InstructionRa_1"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_2", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_2", 2, "InstructionRa_2"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_3", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_3", 3, "InstructionRa_3"), + stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_4", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_4", 4, "InstructionRa_4"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_5", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_5", 5, "InstructionRa_5"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_6", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_6", 6, "InstructionRa_6"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_7", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_7", 7, "InstructionRa_7"), + stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_8", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_8", 8, "InstructionRa_8"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_9", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_9", 9, "InstructionRa_9"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_10", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_10", 10, "InstructionRa_10"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_11", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_11", 11, "InstructionRa_11"), + stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_12", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_12", 12, "InstructionRa_12"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_13", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_13", 13, "InstructionRa_13"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_14", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_14", 14, "InstructionRa_14"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_15", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_15", 15, "InstructionRa_15"), + stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_16", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_16", 16, "InstructionRa_16"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_17", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_17", 17, "InstructionRa_17"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_18", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_18", 18, "InstructionRa_18"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_19", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_19", 19, "InstructionRa_19"), + stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_20", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_20", 20, "InstructionRa_20"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_21", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_21", 21, "InstructionRa_21"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_22", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_22", 22, "InstructionRa_22"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_23", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_23", 23, "InstructionRa_23"), + stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_24", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_24", 24, "InstructionRa_24"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_25", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_25", 25, "InstructionRa_25"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_26", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_26", 26, "InstructionRa_26"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_27", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_27", 27, "InstructionRa_27"), + stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_28", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_28", 28, "InstructionRa_28"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_29", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_29", 29, "InstructionRa_29"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_30", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_30", 30, "InstructionRa_30"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_31", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_31", 31, "InstructionRa_31"), + stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.BytecodeRa_0", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_0", 32, "BytecodeRa_0"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.BytecodeRa_1", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_1", 33, "BytecodeRa_1"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.BytecodeRa_2", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_2", 34, "BytecodeRa_2"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.RamRa_0", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.RamRa_0", 35, "RamRa_0"), + stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.RamRa_1", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.RamRa_1", 36, "RamRa_1"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.RamRa_2", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.RamRa_2", 37, "RamRa_2"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.RamRa_3", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.RamRa_3", 38, "RamRa_3"), +]; + +pub const STAGE7_POINT_ZEROS: &[Stage7PointZeroPlan] = &[ + +]; + +pub const STAGE7_POINT_SLICES: &[Stage7PointSlicePlan] = &[ + Stage7PointSlicePlan { symbol: "stage7.hamming_weight_claim_reduction.point.cycle", source: "stage7.input.stage6.booleanity.InstructionRa_0", offset: 4, length: 16, input: "stage7.input.stage6.booleanity.InstructionRa_0" }, +]; + +pub const STAGE7_POINT_CONCATS: &[Stage7PointConcatPlan] = &[ + Stage7PointConcatPlan { symbol: "stage7.hamming_weight_claim_reduction.point", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage7.hamming_weight_claim_reduction.instance|stage7.hamming_weight_claim_reduction.point.cycle" }, +]; +pub const STAGE7_OPENING_CLAIMS: &[Stage7OpeningClaimPlan] = &[ + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_0" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_1" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_2" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_3" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_4" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_5" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_6" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_7" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_8" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_9" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_10" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_11" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_12" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_13" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_14" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_15" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_16" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_17" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_18" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_19" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_20" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_21" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_22" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_23" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_24" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_25" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_26" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_27" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_28" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_29" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_30" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_31" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_0" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_1" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_2" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.RamRa_0" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.RamRa_1" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.RamRa_2" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.RamRa_3" }, +]; + +pub const STAGE7_OPENING_EQUALITIES: &[Stage7OpeningClaimEqualityPlan] = &[ + +]; + +pub const STAGE7_OPENING_BATCHES: &[Stage7OpeningBatchPlan] = &[ + Stage7OpeningBatchPlan { symbol: "stage7.openings", stage: "stage7", proof_slot: "stage7.openings", policy: "jolt_stage7_output_order", count: 39, ordered_claims: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_0|stage7.hamming_weight_claim_reduction.opening.InstructionRa_1|stage7.hamming_weight_claim_reduction.opening.InstructionRa_2|stage7.hamming_weight_claim_reduction.opening.InstructionRa_3|stage7.hamming_weight_claim_reduction.opening.InstructionRa_4|stage7.hamming_weight_claim_reduction.opening.InstructionRa_5|stage7.hamming_weight_claim_reduction.opening.InstructionRa_6|stage7.hamming_weight_claim_reduction.opening.InstructionRa_7|stage7.hamming_weight_claim_reduction.opening.InstructionRa_8|stage7.hamming_weight_claim_reduction.opening.InstructionRa_9|stage7.hamming_weight_claim_reduction.opening.InstructionRa_10|stage7.hamming_weight_claim_reduction.opening.InstructionRa_11|stage7.hamming_weight_claim_reduction.opening.InstructionRa_12|stage7.hamming_weight_claim_reduction.opening.InstructionRa_13|stage7.hamming_weight_claim_reduction.opening.InstructionRa_14|stage7.hamming_weight_claim_reduction.opening.InstructionRa_15|stage7.hamming_weight_claim_reduction.opening.InstructionRa_16|stage7.hamming_weight_claim_reduction.opening.InstructionRa_17|stage7.hamming_weight_claim_reduction.opening.InstructionRa_18|stage7.hamming_weight_claim_reduction.opening.InstructionRa_19|stage7.hamming_weight_claim_reduction.opening.InstructionRa_20|stage7.hamming_weight_claim_reduction.opening.InstructionRa_21|stage7.hamming_weight_claim_reduction.opening.InstructionRa_22|stage7.hamming_weight_claim_reduction.opening.InstructionRa_23|stage7.hamming_weight_claim_reduction.opening.InstructionRa_24|stage7.hamming_weight_claim_reduction.opening.InstructionRa_25|stage7.hamming_weight_claim_reduction.opening.InstructionRa_26|stage7.hamming_weight_claim_reduction.opening.InstructionRa_27|stage7.hamming_weight_claim_reduction.opening.InstructionRa_28|stage7.hamming_weight_claim_reduction.opening.InstructionRa_29|stage7.hamming_weight_claim_reduction.opening.InstructionRa_30|stage7.hamming_weight_claim_reduction.opening.InstructionRa_31|stage7.hamming_weight_claim_reduction.opening.BytecodeRa_0|stage7.hamming_weight_claim_reduction.opening.BytecodeRa_1|stage7.hamming_weight_claim_reduction.opening.BytecodeRa_2|stage7.hamming_weight_claim_reduction.opening.RamRa_0|stage7.hamming_weight_claim_reduction.opening.RamRa_1|stage7.hamming_weight_claim_reduction.opening.RamRa_2|stage7.hamming_weight_claim_reduction.opening.RamRa_3", claim_operands: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_0|stage7.hamming_weight_claim_reduction.opening.InstructionRa_1|stage7.hamming_weight_claim_reduction.opening.InstructionRa_2|stage7.hamming_weight_claim_reduction.opening.InstructionRa_3|stage7.hamming_weight_claim_reduction.opening.InstructionRa_4|stage7.hamming_weight_claim_reduction.opening.InstructionRa_5|stage7.hamming_weight_claim_reduction.opening.InstructionRa_6|stage7.hamming_weight_claim_reduction.opening.InstructionRa_7|stage7.hamming_weight_claim_reduction.opening.InstructionRa_8|stage7.hamming_weight_claim_reduction.opening.InstructionRa_9|stage7.hamming_weight_claim_reduction.opening.InstructionRa_10|stage7.hamming_weight_claim_reduction.opening.InstructionRa_11|stage7.hamming_weight_claim_reduction.opening.InstructionRa_12|stage7.hamming_weight_claim_reduction.opening.InstructionRa_13|stage7.hamming_weight_claim_reduction.opening.InstructionRa_14|stage7.hamming_weight_claim_reduction.opening.InstructionRa_15|stage7.hamming_weight_claim_reduction.opening.InstructionRa_16|stage7.hamming_weight_claim_reduction.opening.InstructionRa_17|stage7.hamming_weight_claim_reduction.opening.InstructionRa_18|stage7.hamming_weight_claim_reduction.opening.InstructionRa_19|stage7.hamming_weight_claim_reduction.opening.InstructionRa_20|stage7.hamming_weight_claim_reduction.opening.InstructionRa_21|stage7.hamming_weight_claim_reduction.opening.InstructionRa_22|stage7.hamming_weight_claim_reduction.opening.InstructionRa_23|stage7.hamming_weight_claim_reduction.opening.InstructionRa_24|stage7.hamming_weight_claim_reduction.opening.InstructionRa_25|stage7.hamming_weight_claim_reduction.opening.InstructionRa_26|stage7.hamming_weight_claim_reduction.opening.InstructionRa_27|stage7.hamming_weight_claim_reduction.opening.InstructionRa_28|stage7.hamming_weight_claim_reduction.opening.InstructionRa_29|stage7.hamming_weight_claim_reduction.opening.InstructionRa_30|stage7.hamming_weight_claim_reduction.opening.InstructionRa_31|stage7.hamming_weight_claim_reduction.opening.BytecodeRa_0|stage7.hamming_weight_claim_reduction.opening.BytecodeRa_1|stage7.hamming_weight_claim_reduction.opening.BytecodeRa_2|stage7.hamming_weight_claim_reduction.opening.RamRa_0|stage7.hamming_weight_claim_reduction.opening.RamRa_1|stage7.hamming_weight_claim_reduction.opening.RamRa_2|stage7.hamming_weight_claim_reduction.opening.RamRa_3" }, +]; +pub const STAGE7_PROGRAM: Stage7VerifierProgramPlan = Stage7CpuProgramPlan { + role: "verifier", + params: STAGE7_PARAMS, + steps: STAGE7_PROGRAM_STEPS, + transcript_squeezes: STAGE7_TRANSCRIPT_SQUEEZES, + transcript_absorb_bytes: STAGE7_TRANSCRIPT_ABSORB_BYTES, + opening_inputs: STAGE7_OPENING_INPUTS, + field_constants: STAGE7_FIELD_CONSTANTS, + field_exprs: STAGE7_FIELD_EXPRS, + kernels: STAGE7_KERNELS, + claims: STAGE7_SUMCHECK_CLAIMS, + batches: STAGE7_SUMCHECK_BATCHES, + drivers: STAGE7_SUMCHECK_DRIVERS, + instance_results: STAGE7_SUMCHECK_INSTANCE_RESULTS, + evals: STAGE7_SUMCHECK_EVALS, + point_zeros: STAGE7_POINT_ZEROS, + point_slices: STAGE7_POINT_SLICES, + point_concats: STAGE7_POINT_CONCATS, + opening_claims: STAGE7_OPENING_CLAIMS, + opening_equalities: STAGE7_OPENING_EQUALITIES, + opening_batches: STAGE7_OPENING_BATCHES, +}; + +pub fn verify_stage7( + proof: &Stage7Proof, + opening_inputs: &[Stage7OpeningInputValue], + transcript: &mut T, +) -> Result, VerifyStage7Error> +where + T: Transcript, +{ + verify_stage7_with_program(&STAGE7_PROGRAM, proof, opening_inputs, transcript) +} + +pub fn verify_stage7_with_program( + program: &'static Stage7VerifierProgramPlan, + proof: &Stage7Proof, + opening_inputs: &[Stage7OpeningInputValue], + transcript: &mut T, +) -> Result, VerifyStage7Error> +where + T: Transcript, +{ + if proof.sumchecks.len() != program.drivers.len() { + return Err(VerifyStage7Error::UnexpectedProofCount { + expected: program.drivers.len(), + got: proof.sumchecks.len(), + }); + } + let mut store = + super::common::ValueStore::with_opening_inputs(opening_inputs, program.opening_inputs)?; + store.seed_constants(program.field_constants); + store.seed_point_zeros(program.point_zeros); + let mut artifacts = Stage7ExecutionArtifacts::default(); + for step in program.steps { + match step.kind { + "transcript_squeeze" => { + let squeeze = + find_plan(program.transcript_squeezes, step.symbol).ok_or(VerifyStage7Error::MissingValue { + symbol: step.symbol, + })?; + verify_stage7_squeeze(program, squeeze, &mut store, transcript, &mut artifacts)?; + } + "transcript_absorb_bytes" => { + let absorb = find_plan(program.transcript_absorb_bytes, step.symbol).ok_or( + VerifyStage7Error::MissingValue { + symbol: step.symbol, + }, + )?; + absorb_stage7_bytes(absorb, transcript); + } + "sumcheck_driver" => { + let driver = + find_plan(program.drivers, step.symbol).ok_or(VerifyStage7Error::MissingProof { + driver: step.symbol, + })?; + verify_stage7_driver( + program, + driver, + proof, + &mut store, + transcript, + &mut artifacts, + )?; + } + _ => { + return Err(VerifyStage7Error::InvalidProof { + driver: step.symbol, + reason: "unsupported stage7 program step", + }); + } + } + } + artifacts + .opening_batches + .extend(program.opening_batches.iter()); + Ok(artifacts) +} + +pub fn stage7_verifier_program() -> &'static Stage7VerifierProgramPlan { + &STAGE7_PROGRAM +} + +fn verify_stage7_squeeze( + program: &'static Stage7VerifierProgramPlan, + squeeze: &'static Stage7TranscriptSqueezePlan, + store: &mut super::common::ValueStore, + transcript: &mut T, + artifacts: &mut Stage7ExecutionArtifacts, +) -> Result<(), VerifyStage7Error> +where + T: Transcript, +{ + let values = transcript.challenge_vector(squeeze.count); + store.observe_challenge_vector(squeeze, &values, |input, expected, actual| { + VerifyStage7Error::InvalidInputLength { + input, + expected, + actual, + } + })?; + store + .evaluate_available_field_exprs(program.field_exprs, super::common::evaluate_field_expr) + .map_err(VerifyStage7Error::from)?; + artifacts.challenge_vectors.push(Stage7ChallengeVector { + symbol: squeeze.symbol, + values, + }); + Ok(()) +} + +fn absorb_stage7_bytes(absorb: &'static Stage7TranscriptAbsorbBytesPlan, transcript: &mut T) +where + T: Transcript, +{ + transcript.append(&LabelWithCount( + absorb.label.as_bytes(), + absorb.payload.len() as u64, + )); + transcript.append_bytes(absorb.payload.as_bytes()); +} + +fn verify_stage7_driver( + program: &'static Stage7VerifierProgramPlan, + driver: &'static Stage7SumcheckDriverPlan, + proof: &Stage7Proof, + store: &mut super::common::ValueStore, + transcript: &mut T, + artifacts: &mut Stage7ExecutionArtifacts, +) -> Result<(), VerifyStage7Error> +where + T: Transcript, +{ + let proof = proof + .sumchecks + .get(artifacts.sumchecks.len()) + .ok_or(VerifyStage7Error::MissingProof { + driver: driver.symbol, + })?; + let relation = driver.relation.unwrap_or(""); + let output = match relation { + "jolt.stage7.batched" => { + verify_batched_stage7(program, driver, proof, store, transcript)? + } + _ => return Err(VerifyStage7Error::UnsupportedRelation { relation }), + }; + artifacts.sumchecks.push(output); + Ok(()) +} + +fn verify_batched_stage7( + program: &'static Stage7VerifierProgramPlan, + driver: &'static Stage7SumcheckDriverPlan, + proof: &Stage7SumcheckOutput, + store: &mut super::common::ValueStore, + transcript: &mut T, +) -> Result, VerifyStage7Error> +where + T: Transcript, +{ + super::common::verify_batched_sumcheck( + driver, + proof, + program.claims, + program.batches, + program.field_exprs, + program.opening_inputs, + program.opening_claims, + program.opening_batches, + store, + transcript, + |store, evals, point, batching_coeffs| { + expected_batched_output_claim(program, driver, store, evals, point, batching_coeffs) + }, + |store, verified| observe_stage7_sumcheck_output(program, store, verified), + |driver, error| VerifyStage7Error::Sumcheck { driver, error }, + ) +} + +fn observe_stage7_sumcheck_output( + program: &'static Stage7VerifierProgramPlan, + store: &mut super::common::ValueStore, + output: &Stage7SumcheckOutput, +) -> Result<(), VerifyStage7Error> { + store.observe_sumcheck_output( + program.instance_results, + program.evals, + output, + |instance, mut point| { + match instance.point_order { + "as_is" => {} + "reverse" => point.reverse(), + "bytecode_read_raf" => point = normalize_bytecode_read_raf_point(&point, stage7_trace_rounds(program)?, "stage7.bytecode_read_raf.point")?, + "stage7_booleanity" => {} + "instruction_read_raf" => point = normalize_instruction_read_raf_point(&point, "stage7.instruction_read_raf.point")?, + _ => { + return Err(VerifyStage7Error::InvalidProof { + driver: output.driver, + reason: "unsupported point order", + }); + } + } + Ok(point) + }, + |input, expected, actual| VerifyStage7Error::InvalidInputLength { + input, + expected, + actual, + }, + |symbol| VerifyStage7Error::MissingValue { symbol }, + )?; + store.evaluate_available_points( + program.point_slices, + program.point_concats, + |input, expected, actual| VerifyStage7Error::InvalidInputLength { + input, + expected, + actual, + }, + )?; + store + .evaluate_available_field_exprs(program.field_exprs, super::common::evaluate_field_expr) + .map_err(VerifyStage7Error::from)?; + store.verify_opening_equalities( + program.opening_equalities, + |driver, reason| VerifyStage7Error::InvalidProof { driver, reason }, + |symbol| VerifyStage7Error::MissingValue { symbol }, + ) +} + +fn expected_batched_output_claim( + program: &'static Stage7VerifierProgramPlan, + driver: &'static Stage7SumcheckDriverPlan, + store: &super::common::ValueStore, + evals: &[Stage7NamedEval], + point: &[Fr], + batching_coeffs: &[Fr], +) -> Result { + let batch = find_batch(program.batches, driver.symbol, driver.batch)?; + let claims = batch_claims(program.claims, batch)?; + let mut expected = Fr::from_u64(0); + for (claim, coefficient) in claims.iter().zip(batching_coeffs) { + let instance = program + .instance_results + .iter() + .find(|instance| instance.claim == claim.symbol && instance.source == driver.symbol) + .ok_or(VerifyStage7Error::MissingClaim { + batch: batch.symbol, + claim: claim.symbol, + })?; + let local_point = point + .get(instance.round_offset..instance.round_offset + instance.num_rounds) + .ok_or(VerifyStage7Error::InvalidInputLength { + input: instance.symbol, + expected: instance.round_offset + instance.num_rounds, + actual: point.len(), + })?; + let relation = claim.relation.unwrap_or(""); + let value = match relation { + "jolt.stage7.hamming_weight_claim_reduction" => { + expected_hamming_weight_claim_reduction(program, driver, store, evals, local_point)? + } + _ => return Err(VerifyStage7Error::UnsupportedRelation { relation }), + }; + expected += *coefficient * value; + } + Ok(expected) +} + +fn expected_hamming_weight_claim_reduction( + program: &'static Stage7VerifierProgramPlan, + driver: &'static Stage7SumcheckDriverPlan, + store: &super::common::ValueStore, + evals: &[Stage7NamedEval], + local_point: &[Fr], +) -> Result { + let rho_rev = reverse_slice(local_point); + let booleanity_point = super::common::store_point(store, "stage7.input.stage6.booleanity.InstructionRa_0")?; + let r_addr_bool = + booleanity_point + .get(..local_point.len()) + .ok_or(VerifyStage7Error::InvalidInputLength { + input: "stage7.input.stage6.booleanity.InstructionRa_0", + expected: local_point.len(), + actual: booleanity_point.len(), + })?; + let eq_bool = EqPolynomial::::mle(&rho_rev, r_addr_bool); + let gamma = super::common::store_scalar(store, "stage7.hamming_weight_claim_reduction.gamma")?; + let mut gamma_power = Fr::from_u64(1); + let mut expected = Fr::from_u64(0); + let mut eval_plans = program + .evals + .iter() + .filter(|eval| eval.source == driver.symbol) + .collect::>(); + eval_plans.sort_by_key(|eval| eval.index); + for eval_plan in eval_plans { + let g_i = eval_by_name(evals, eval_plan.name)?; + let virt_point = + stage7_virtualization_point(store, eval_plan.oracle, local_point.len())?; + let eq_virt = EqPolynomial::::mle(&rho_rev, virt_point); + expected += g_i * (gamma_power + gamma_power * gamma * eq_bool + + gamma_power * gamma.square() * eq_virt); + gamma_power *= gamma; + gamma_power *= gamma; + gamma_power *= gamma; + } + Ok(expected) +} + +fn stage7_virtualization_point<'a>( + store: &'a super::common::ValueStore, + oracle: &str, + log_k_chunk: usize, +) -> Result<&'a [Fr], VerifyStage7Error> { + let symbol = if oracle.starts_with("InstructionRa_") { + format!("stage7.input.stage6.instruction_ra_virtual.{oracle}") + } else if oracle.starts_with("BytecodeRa_") { + format!("stage7.input.stage6.bytecode_read_raf.{oracle}") + } else if oracle.starts_with("RamRa_") { + format!("stage7.input.stage6.ram_ra_virtual.{oracle}") + } else { + return Err(VerifyStage7Error::MissingValue { + symbol: "stage7.hamming_weight_claim_reduction.oracle", + }); + }; + let point = store.try_point(&symbol).ok_or(VerifyStage7Error::MissingValue { + symbol: "stage7.hamming_weight_claim_reduction.virtualization_point", + })?; + point + .get(..log_k_chunk) + .ok_or(VerifyStage7Error::InvalidInputLength { + input: "stage7.hamming_weight_claim_reduction.virtualization_point", + expected: log_k_chunk, + actual: point.len(), + }) +} + +fn stage7_trace_rounds( + program: &'static Stage7VerifierProgramPlan, +) -> Result { + program + .instance_results + .iter() + .find(|instance| instance.relation == "jolt.stage7.hamming_booleanity") + .map(|instance| instance.num_rounds) + .ok_or(VerifyStage7Error::MissingValue { + symbol: "stage7.hamming_booleanity.instance", + }) +} diff --git a/crates/jolt-verifier/src/stages/stage8.rs b/crates/jolt-verifier/src/stages/stage8.rs new file mode 100644 index 0000000000..6d245c8ba9 --- /dev/null +++ b/crates/jolt-verifier/src/stages/stage8.rs @@ -0,0 +1,173 @@ +#![allow(clippy::too_many_lines)] + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage8Params { + pub field: &'static str, + pub pcs: &'static str, + pub transcript: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage8OpeningInputPlan { + pub symbol: &'static str, + pub source_stage: &'static str, + pub source_claim: &'static str, + pub oracle: &'static str, + pub domain: &'static str, + pub point_arity: usize, + pub claim_kind: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage8OpeningClaimPlan { + pub symbol: &'static str, + pub oracle: &'static str, + pub family: &'static str, + pub domain: &'static str, + pub point_arity: usize, + pub point_source: &'static str, + pub eval_source: &'static str, + pub source_stage: &'static str, + pub source_claim: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage8OpeningBatchPlan { + pub symbol: &'static str, + pub proof_slot: &'static str, + pub policy: &'static str, + pub count: usize, + pub ordered_claims: &'static [&'static str], +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage8PcsProofPlan { + pub symbol: &'static str, + pub mode: &'static str, + pub pcs: &'static str, + pub proof_slot: &'static str, + pub transcript_label: &'static str, + pub batch: &'static str, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Stage8EvaluationProgramPlan { + pub role: &'static str, + pub function: &'static str, + pub params: Stage8Params, + pub evaluation_point_source: Stage8OpeningInputPlan, + pub opening_inputs: &'static [Stage8OpeningInputPlan], + pub opening_claims: &'static [Stage8OpeningClaimPlan], + pub opening_batch: Stage8OpeningBatchPlan, + pub pcs_proof: Stage8PcsProofPlan, +} + +pub const STAGE8_PARAMS: Stage8Params = Stage8Params { field: "bn254_fr", pcs: "dory", transcript: "blake2b_transcript" }; + +pub const STAGE8_EVALUATION_POINT_SOURCE: Stage8OpeningInputPlan = Stage8OpeningInputPlan { symbol: "stage8.evaluation.point_source", source_stage: "stage7", source_claim: "stage7.input.stage6.booleanity.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }; + +pub const STAGE8_OPENING_INPUTS: &[Stage8OpeningInputPlan] = &[ + Stage8OpeningInputPlan { symbol: "stage8.evaluation.point_source", source_stage: "stage7", source_claim: "stage7.input.stage6.booleanity.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage6.RamInc", source_stage: "stage6", source_claim: "stage6.inc_claim_reduction.eval.RamInc", oracle: "RamInc", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage6.RdInc", source_stage: "stage6", source_claim: "stage6.inc_claim_reduction.eval.RdInc", oracle: "RdInc", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_3", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_4", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_5", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_6", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_7", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_8", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_9", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_10", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_11", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_12", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_13", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_14", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_15", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_16", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_17", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_18", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_19", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_20", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_21", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_22", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_23", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_24", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_25", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_26", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_27", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_28", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_29", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_30", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_31", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.BytecodeRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.BytecodeRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.BytecodeRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.RamRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.RamRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.RamRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.RamRa_3", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, +]; + +pub const STAGE8_OPENING_CLAIMS: &[Stage8OpeningClaimPlan] = &[ + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RamInc", oracle: "RamInc", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage6.RamInc", eval_source: "stage8.input.stage6.RamInc", source_stage: "stage6", source_claim: "stage6.inc_claim_reduction.eval.RamInc" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RdInc", oracle: "RdInc", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage6.RdInc", eval_source: "stage8.input.stage6.RdInc", source_stage: "stage6", source_claim: "stage6.inc_claim_reduction.eval.RdInc" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_0", oracle: "InstructionRa_0", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_0", eval_source: "stage8.input.stage7.InstructionRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_0" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_1", oracle: "InstructionRa_1", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_1", eval_source: "stage8.input.stage7.InstructionRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_1" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_2", oracle: "InstructionRa_2", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_2", eval_source: "stage8.input.stage7.InstructionRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_2" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_3", oracle: "InstructionRa_3", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_3", eval_source: "stage8.input.stage7.InstructionRa_3", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_3" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_4", oracle: "InstructionRa_4", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_4", eval_source: "stage8.input.stage7.InstructionRa_4", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_4" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_5", oracle: "InstructionRa_5", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_5", eval_source: "stage8.input.stage7.InstructionRa_5", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_5" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_6", oracle: "InstructionRa_6", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_6", eval_source: "stage8.input.stage7.InstructionRa_6", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_6" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_7", oracle: "InstructionRa_7", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_7", eval_source: "stage8.input.stage7.InstructionRa_7", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_7" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_8", oracle: "InstructionRa_8", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_8", eval_source: "stage8.input.stage7.InstructionRa_8", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_8" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_9", oracle: "InstructionRa_9", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_9", eval_source: "stage8.input.stage7.InstructionRa_9", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_9" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_10", oracle: "InstructionRa_10", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_10", eval_source: "stage8.input.stage7.InstructionRa_10", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_10" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_11", oracle: "InstructionRa_11", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_11", eval_source: "stage8.input.stage7.InstructionRa_11", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_11" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_12", oracle: "InstructionRa_12", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_12", eval_source: "stage8.input.stage7.InstructionRa_12", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_12" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_13", oracle: "InstructionRa_13", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_13", eval_source: "stage8.input.stage7.InstructionRa_13", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_13" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_14", oracle: "InstructionRa_14", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_14", eval_source: "stage8.input.stage7.InstructionRa_14", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_14" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_15", oracle: "InstructionRa_15", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_15", eval_source: "stage8.input.stage7.InstructionRa_15", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_15" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_16", oracle: "InstructionRa_16", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_16", eval_source: "stage8.input.stage7.InstructionRa_16", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_16" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_17", oracle: "InstructionRa_17", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_17", eval_source: "stage8.input.stage7.InstructionRa_17", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_17" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_18", oracle: "InstructionRa_18", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_18", eval_source: "stage8.input.stage7.InstructionRa_18", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_18" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_19", oracle: "InstructionRa_19", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_19", eval_source: "stage8.input.stage7.InstructionRa_19", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_19" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_20", oracle: "InstructionRa_20", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_20", eval_source: "stage8.input.stage7.InstructionRa_20", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_20" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_21", oracle: "InstructionRa_21", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_21", eval_source: "stage8.input.stage7.InstructionRa_21", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_21" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_22", oracle: "InstructionRa_22", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_22", eval_source: "stage8.input.stage7.InstructionRa_22", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_22" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_23", oracle: "InstructionRa_23", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_23", eval_source: "stage8.input.stage7.InstructionRa_23", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_23" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_24", oracle: "InstructionRa_24", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_24", eval_source: "stage8.input.stage7.InstructionRa_24", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_24" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_25", oracle: "InstructionRa_25", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_25", eval_source: "stage8.input.stage7.InstructionRa_25", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_25" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_26", oracle: "InstructionRa_26", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_26", eval_source: "stage8.input.stage7.InstructionRa_26", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_26" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_27", oracle: "InstructionRa_27", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_27", eval_source: "stage8.input.stage7.InstructionRa_27", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_27" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_28", oracle: "InstructionRa_28", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_28", eval_source: "stage8.input.stage7.InstructionRa_28", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_28" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_29", oracle: "InstructionRa_29", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_29", eval_source: "stage8.input.stage7.InstructionRa_29", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_29" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_30", oracle: "InstructionRa_30", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_30", eval_source: "stage8.input.stage7.InstructionRa_30", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_30" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_31", oracle: "InstructionRa_31", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_31", eval_source: "stage8.input.stage7.InstructionRa_31", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_31" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.BytecodeRa_0", oracle: "BytecodeRa_0", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.BytecodeRa_0", eval_source: "stage8.input.stage7.BytecodeRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_0" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.BytecodeRa_1", oracle: "BytecodeRa_1", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.BytecodeRa_1", eval_source: "stage8.input.stage7.BytecodeRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_1" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.BytecodeRa_2", oracle: "BytecodeRa_2", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.BytecodeRa_2", eval_source: "stage8.input.stage7.BytecodeRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_2" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RamRa_0", oracle: "RamRa_0", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.RamRa_0", eval_source: "stage8.input.stage7.RamRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_0" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RamRa_1", oracle: "RamRa_1", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.RamRa_1", eval_source: "stage8.input.stage7.RamRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_1" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RamRa_2", oracle: "RamRa_2", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.RamRa_2", eval_source: "stage8.input.stage7.RamRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_2" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RamRa_3", oracle: "RamRa_3", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.RamRa_3", eval_source: "stage8.input.stage7.RamRa_3", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_3" }, +]; + +pub const STAGE8_OPENING_BATCH_ORDERED_CLAIMS: &[&str] = &["stage8.evaluation.opening.RamInc", "stage8.evaluation.opening.RdInc", "stage8.evaluation.opening.InstructionRa_0", "stage8.evaluation.opening.InstructionRa_1", "stage8.evaluation.opening.InstructionRa_2", "stage8.evaluation.opening.InstructionRa_3", "stage8.evaluation.opening.InstructionRa_4", "stage8.evaluation.opening.InstructionRa_5", "stage8.evaluation.opening.InstructionRa_6", "stage8.evaluation.opening.InstructionRa_7", "stage8.evaluation.opening.InstructionRa_8", "stage8.evaluation.opening.InstructionRa_9", "stage8.evaluation.opening.InstructionRa_10", "stage8.evaluation.opening.InstructionRa_11", "stage8.evaluation.opening.InstructionRa_12", "stage8.evaluation.opening.InstructionRa_13", "stage8.evaluation.opening.InstructionRa_14", "stage8.evaluation.opening.InstructionRa_15", "stage8.evaluation.opening.InstructionRa_16", "stage8.evaluation.opening.InstructionRa_17", "stage8.evaluation.opening.InstructionRa_18", "stage8.evaluation.opening.InstructionRa_19", "stage8.evaluation.opening.InstructionRa_20", "stage8.evaluation.opening.InstructionRa_21", "stage8.evaluation.opening.InstructionRa_22", "stage8.evaluation.opening.InstructionRa_23", "stage8.evaluation.opening.InstructionRa_24", "stage8.evaluation.opening.InstructionRa_25", "stage8.evaluation.opening.InstructionRa_26", "stage8.evaluation.opening.InstructionRa_27", "stage8.evaluation.opening.InstructionRa_28", "stage8.evaluation.opening.InstructionRa_29", "stage8.evaluation.opening.InstructionRa_30", "stage8.evaluation.opening.InstructionRa_31", "stage8.evaluation.opening.BytecodeRa_0", "stage8.evaluation.opening.BytecodeRa_1", "stage8.evaluation.opening.BytecodeRa_2", "stage8.evaluation.opening.RamRa_0", "stage8.evaluation.opening.RamRa_1", "stage8.evaluation.opening.RamRa_2", "stage8.evaluation.opening.RamRa_3"]; + +pub const STAGE8_OPENING_BATCH: Stage8OpeningBatchPlan = Stage8OpeningBatchPlan { symbol: "stage8.evaluation.openings", proof_slot: "stage8.evaluation", policy: "jolt_stage8_joint_rlc", count: 41, ordered_claims: STAGE8_OPENING_BATCH_ORDERED_CLAIMS }; + +pub const STAGE8_PCS_PROOF: Stage8PcsProofPlan = Stage8PcsProofPlan { symbol: "stage8.evaluation.proof", mode: "verify", pcs: "dory", proof_slot: "stage8.evaluation", transcript_label: "rlc_claims", batch: "stage8.evaluation.openings" }; + +pub const STAGE8_PROGRAM: Stage8EvaluationProgramPlan = Stage8EvaluationProgramPlan { + role: "verifier", + function: "jolt.stage8", + params: STAGE8_PARAMS, + evaluation_point_source: STAGE8_EVALUATION_POINT_SOURCE, + opening_inputs: STAGE8_OPENING_INPUTS, + opening_claims: STAGE8_OPENING_CLAIMS, + opening_batch: STAGE8_OPENING_BATCH, + pcs_proof: STAGE8_PCS_PROOF, +}; diff --git a/crates/jolt-verifier/src/verifier.rs b/crates/jolt-verifier/src/verifier.rs new file mode 100644 index 0000000000..f6ad1ecc09 --- /dev/null +++ b/crates/jolt-verifier/src/verifier.rs @@ -0,0 +1,493 @@ +use std::collections::BTreeMap; + +use jolt_dory::{DoryCommitment, DoryProof, DoryScheme, DoryVerifierSetup}; +use jolt_field::{Field, Fr}; +use jolt_openings::{AdditivelyHomomorphic, CommitmentScheme, OpeningsError}; +use jolt_poly::EqPolynomial; +use jolt_transcript::{AppendToTranscript, LabelWithCount, Transcript}; + +use crate::stages::{commitment as commitment_stage, stage1_outer as stage1_outer_stage, stage2 as stage2_stage, stage3 as stage3_stage, stage4 as stage4_stage, stage5 as stage5_stage, stage6 as stage6_stage, stage7 as stage7_stage, stage8 as stage8_stage}; + +pub type JoltNamedEval = crate::stages::common::StageNamedEval; +pub type JoltSumcheckOutput = crate::stages::common::StageSumcheckOutput; +pub type JoltStageProof = crate::stages::common::StageProof; + +#[derive(Clone, Debug)] +pub struct JoltProof { + pub commitments: Vec>, + pub stage1_outer: JoltStageProof, + pub stage2: JoltStageProof, + pub stage3: JoltStageProof, + pub stage4: JoltStageProof, + pub stage5: JoltStageProof, + pub stage6: JoltStageProof, + pub stage7: JoltStageProof, + pub evaluation: Option, +} + +pub type JoltStage2RamAccess = crate::stages::stage2::Stage2RamAccess; +pub type JoltStage2RamOutputLayout = crate::stages::stage2::Stage2RamOutputLayout; +pub type JoltStage2RamData<'a> = crate::stages::stage2::Stage2RamData<'a>; +pub type JoltStageChallengeVector = crate::stages::common::StageChallengeVector; +pub type JoltStageExecutionArtifacts = crate::stages::common::StageExecutionArtifacts; +pub type JoltStageOpeningInputValue = crate::stages::common::StageOpeningInputValue; + +#[derive(Clone, Debug)] +pub struct JoltEvaluationProof { + pub joint_opening_proof: DoryProof, +} + +#[derive(Clone, Copy)] +pub struct JoltVerifierInputs<'a> { + pub stage2_openings: &'a [stage2_stage::Stage2OpeningInputValue], + pub stage2_ram: Option<&'a stage2_stage::Stage2RamData<'a>>, + pub stage3_openings: &'a [stage3_stage::Stage3OpeningInputValue], + pub stage4_openings: &'a [stage4_stage::Stage4OpeningInputValue], + pub stage5_openings: &'a [stage5_stage::Stage5OpeningInputValue], + pub stage6_openings: &'a [stage6_stage::Stage6OpeningInputValue], + pub stage6_data: Option<&'a stage6_stage::Stage6VerifierData>, + pub stage7_openings: &'a [stage7_stage::Stage7OpeningInputValue], + pub evaluation_setup: Option<&'a DoryVerifierSetup>, +} + +#[derive(Clone, Copy, Debug)] +pub struct JoltVerifierPrograms { + pub commitment: &'static commitment_stage::CommitmentVerifierProgramPlan, + pub stage1_outer: &'static stage1_outer_stage::Stage1VerifierProgramPlan, + pub stage2: &'static stage2_stage::Stage2VerifierProgramPlan, + pub stage3: &'static stage3_stage::Stage3VerifierProgramPlan, + pub stage4: &'static stage4_stage::Stage4VerifierProgramPlan, + pub stage5: &'static stage5_stage::Stage5VerifierProgramPlan, + pub stage6: &'static stage6_stage::Stage6VerifierProgramPlan, + pub stage7: &'static stage7_stage::Stage7VerifierProgramPlan, + pub stage8: &'static stage8_stage::Stage8EvaluationProgramPlan, +} + +pub fn default_verifier_programs() -> JoltVerifierPrograms { + JoltVerifierPrograms { + commitment: &commitment_stage::COMMITMENT_PROGRAM, + stage1_outer: &stage1_outer_stage::STAGE1_PROGRAM, + stage2: &stage2_stage::STAGE2_PROGRAM, + stage3: &stage3_stage::STAGE3_PROGRAM, + stage4: &stage4_stage::STAGE4_PROGRAM, + stage5: &stage5_stage::STAGE5_PROGRAM, + stage6: &stage6_stage::STAGE6_PROGRAM, + stage7: &stage7_stage::STAGE7_PROGRAM, + stage8: &stage8_stage::STAGE8_PROGRAM, + } +} + +#[derive(Clone, Debug)] +pub struct JoltVerificationArtifacts { + pub commitment: commitment_stage::CommitmentArtifacts, + pub stage1_outer: stage1_outer_stage::Stage1ExecutionArtifacts, + pub stage2: stage2_stage::Stage2ExecutionArtifacts, + pub stage3: stage3_stage::Stage3ExecutionArtifacts, + pub stage4: stage4_stage::Stage4ExecutionArtifacts, + pub stage5: stage5_stage::Stage5ExecutionArtifacts, + pub stage6: stage6_stage::Stage6ExecutionArtifacts, + pub stage7: stage7_stage::Stage7ExecutionArtifacts, +} + +#[derive(Debug)] +pub enum JoltVerifyError { + Commitment(commitment_stage::CommitmentPhaseError), + Stage1Outer(stage1_outer_stage::VerifyStage1Error), + Stage2(stage2_stage::VerifyStage2Error), + Stage3(stage3_stage::VerifyStage3Error), + Stage4(stage4_stage::VerifyStage4Error), + Stage5(stage5_stage::VerifyStage5Error), + Stage6(stage6_stage::VerifyStage6Error), + Stage7(stage7_stage::VerifyStage7Error), + Evaluation(JoltEvaluationProofError), +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum JoltVerifierTarget { + ThroughStage5, + ThroughStage6, + ThroughStage7, + Full, +} + +impl JoltVerifierTarget { + fn verifies_stage6(self) -> bool { matches!(self, Self::ThroughStage6 | Self::ThroughStage7 | Self::Full) } + fn verifies_stage7(self) -> bool { matches!(self, Self::ThroughStage7 | Self::Full) } + fn verifies_evaluation(self) -> bool { matches!(self, Self::Full) } + fn allows_optional_evaluation(self) -> bool { matches!(self, Self::ThroughStage7 | Self::Full) } +} + +#[derive(Debug)] +pub enum JoltEvaluationProofError { + MissingProof, + MissingVerifierSetup, + MissingStageEval { stage: &'static str, eval: &'static str }, + MissingStage7RaEval, + MissingStage7EvaluationPoint, + MissingCommitment { oracle: &'static str }, + InvalidPointLength { + artifact: &'static str, + expected: usize, + actual: usize, + }, + Opening(OpeningsError), +} + +macro_rules! define_jolt_verify_error_from { + ($module:ident, $error_ty:ident, $variant:ident) => { + impl From<$module::$error_ty> for JoltVerifyError { + fn from(error: $module::$error_ty) -> Self { + Self::$variant(error) + } + } + }; +} + +define_jolt_verify_error_from!(commitment_stage, CommitmentPhaseError, Commitment); +define_jolt_verify_error_from!(stage1_outer_stage, VerifyStage1Error, Stage1Outer); +define_jolt_verify_error_from!(stage2_stage, VerifyStage2Error, Stage2); +define_jolt_verify_error_from!(stage3_stage, VerifyStage3Error, Stage3); +define_jolt_verify_error_from!(stage4_stage, VerifyStage4Error, Stage4); +define_jolt_verify_error_from!(stage5_stage, VerifyStage5Error, Stage5); +define_jolt_verify_error_from!(stage6_stage, VerifyStage6Error, Stage6); +define_jolt_verify_error_from!(stage7_stage, VerifyStage7Error, Stage7); + +impl From for JoltVerifyError { + fn from(error: JoltEvaluationProofError) -> Self { + Self::Evaluation(error) + } +} + +impl From for JoltEvaluationProofError { + fn from(error: OpeningsError) -> Self { + Self::Opening(error) + } +} + +pub fn verify_jolt>(proof: &JoltProof, inputs: JoltVerifierInputs<'_>, transcript: &mut T) -> Result { + verify_jolt_with_programs(proof, inputs, default_verifier_programs(), transcript) +} + +pub fn verify_jolt_prefix>(proof: &JoltProof, inputs: JoltVerifierInputs<'_>, transcript: &mut T) -> Result { verify_jolt_prefix_with_programs(proof, inputs, default_verifier_programs(), transcript) } + +pub fn verify_jolt_through_stage5>(proof: &JoltProof, inputs: JoltVerifierInputs<'_>, transcript: &mut T) -> Result { verify_jolt_through_stage5_with_programs(proof, inputs, default_verifier_programs(), transcript) } + +pub fn verify_jolt_through_stage6>(proof: &JoltProof, inputs: JoltVerifierInputs<'_>, transcript: &mut T) -> Result { verify_jolt_through_stage6_with_programs(proof, inputs, default_verifier_programs(), transcript) } + +pub fn verify_jolt_through_stage7>(proof: &JoltProof, inputs: JoltVerifierInputs<'_>, transcript: &mut T) -> Result { verify_jolt_through_stage7_with_programs(proof, inputs, default_verifier_programs(), transcript) } + +pub fn verify_jolt_with_programs>(proof: &JoltProof, inputs: JoltVerifierInputs<'_>, programs: JoltVerifierPrograms, transcript: &mut T) -> Result { + verify_jolt_with_programs_inner(proof, inputs, programs, transcript, JoltVerifierTarget::Full) +} + +pub fn verify_jolt_through_stage5_with_programs>(proof: &JoltProof, inputs: JoltVerifierInputs<'_>, programs: JoltVerifierPrograms, transcript: &mut T) -> Result { verify_jolt_with_programs_inner(proof, inputs, programs, transcript, JoltVerifierTarget::ThroughStage5) } + +pub fn verify_jolt_through_stage6_with_programs>(proof: &JoltProof, inputs: JoltVerifierInputs<'_>, programs: JoltVerifierPrograms, transcript: &mut T) -> Result { verify_jolt_with_programs_inner(proof, inputs, programs, transcript, JoltVerifierTarget::ThroughStage6) } + +pub fn verify_jolt_through_stage7_with_programs>(proof: &JoltProof, inputs: JoltVerifierInputs<'_>, programs: JoltVerifierPrograms, transcript: &mut T) -> Result { verify_jolt_with_programs_inner(proof, inputs, programs, transcript, JoltVerifierTarget::ThroughStage7) } + +pub fn verify_jolt_prefix_with_programs>(proof: &JoltProof, inputs: JoltVerifierInputs<'_>, programs: JoltVerifierPrograms, transcript: &mut T) -> Result { verify_jolt_through_stage7_with_programs(proof, inputs, programs, transcript) } + +fn verify_jolt_with_programs_inner>(proof: &JoltProof, inputs: JoltVerifierInputs<'_>, programs: JoltVerifierPrograms, transcript: &mut T, target: JoltVerifierTarget) -> Result { + let _verify_span = tracing::info_span!("bolt.verify").entered(); + let commitment = commitment_stage::verify_commitment_phase_with_program(programs.commitment, &proof.commitments, transcript)?; + let stage1_outer = stage1_outer_stage::verify_stage1_outer_with_program(programs.stage1_outer, &proof.stage1_outer, transcript)?; + let stage2 = stage2_stage::verify_stage2_with_program(programs.stage2, &proof.stage2, inputs.stage2_openings, inputs.stage2_ram, transcript)?; + let stage3 = stage3_stage::verify_stage3_with_program(programs.stage3, &proof.stage3, inputs.stage3_openings, transcript)?; + let stage4 = stage4_stage::verify_stage4_with_program(programs.stage4, &proof.stage4, inputs.stage4_openings, transcript)?; + let stage5 = stage5_stage::verify_stage5_with_program(programs.stage5, &proof.stage5, inputs.stage5_openings, transcript)?; + let stage6 = if target.verifies_stage6() { + stage6_stage::verify_stage6_with_program(programs.stage6, &proof.stage6, inputs.stage6_openings, inputs.stage6_data, transcript)? + } else { + stage6_stage::Stage6ExecutionArtifacts::default() + }; + let stage7 = if target.verifies_stage7() { + stage7_stage::verify_stage7_with_program(programs.stage7, &proof.stage7, inputs.stage7_openings, transcript)? + } else { + stage7_stage::Stage7ExecutionArtifacts::default() + }; + if target.allows_optional_evaluation() { + match (&proof.evaluation, inputs.evaluation_setup) { + (Some(evaluation), Some(setup)) => { + verify_jolt_evaluation_proof( + programs.stage8, + evaluation, + &commitment, + &proof.stage6, + &proof.stage7, + inputs.stage7_openings, + setup, + transcript, + )?; + } + (Some(_), None) => return Err(JoltEvaluationProofError::MissingVerifierSetup.into()), + (None, Some(_)) => return Err(JoltEvaluationProofError::MissingProof.into()), + (None, None) if target.verifies_evaluation() => return Err(JoltEvaluationProofError::MissingProof.into()), + (None, None) => {} + } + } + + Ok(JoltVerificationArtifacts { + commitment, + stage1_outer, + stage2, + stage3, + stage4, + stage5, + stage6, + stage7, + }) +} + +impl<'a> JoltVerifierInputs<'a> { + pub fn through_stage5(mut self) -> Self { self.stage6_openings = &[]; self.stage7_openings = &[]; self.evaluation_setup = None; self } + pub fn through_stage6(mut self) -> Self { self.stage7_openings = &[]; self.evaluation_setup = None; self } + pub fn through_stage7(mut self) -> Self { self.evaluation_setup = None; self } + pub fn full(mut self, evaluation_setup: &'a DoryVerifierSetup) -> Self { self.evaluation_setup = Some(evaluation_setup); self } +} + +pub type JoltStage6BytecodeEntry = crate::stages::stage6::Stage6BytecodeEntry; +pub type JoltStage6BytecodeReadRafData = crate::stages::stage6::Stage6BytecodeReadRafData; +pub type JoltStage6VerifierData = crate::stages::stage6::Stage6VerifierData; + +#[expect( + clippy::too_many_arguments, + reason = "generated verifier entry point follows the Jolt proof artifact boundary" +)] +pub fn verify_jolt_evaluation_proof( + program: &'static stage8_stage::Stage8EvaluationProgramPlan, + proof: &JoltEvaluationProof, + commitments: &commitment_stage::CommitmentArtifacts, + stage6: &JoltStageProof, + stage7: &JoltStageProof, + stage7_openings: &[stage7_stage::Stage7OpeningInputValue], + verifier_setup: &DoryVerifierSetup, + transcript: &mut T, +) -> Result<(), JoltEvaluationProofError> +where + T: Transcript, +{ + let _state_span = tracing::info_span!("bolt.verify.evaluation_state").entered(); + let state = + evaluation_proof_state(program, commitments, stage6, stage7, stage7_openings, transcript)?; + drop(_state_span); + let _dory_verify_span = tracing::info_span!("bolt.verify.dory_verify").entered(); + ::verify( + &state.joint_commitment, + &state.opening_point, + state.joint_claim, + &proof.joint_opening_proof, + verifier_setup, + transcript, + )?; + drop(_dory_verify_span); + let _bind_span = tracing::info_span!("bolt.verify.bind_opening_inputs").entered(); + ::bind_opening_inputs( + transcript, + &state.opening_point, + &state.joint_claim, + ); + drop(_bind_span); + Ok(()) +} + +struct EvaluationProofState { + opening_point: Vec, + joint_claim: Fr, + joint_commitment: DoryCommitment, +} + +struct EvaluationClaim { + oracle: &'static str, + value: Fr, +} + +fn evaluation_proof_state( + program: &'static stage8_stage::Stage8EvaluationProgramPlan, + commitments: &commitment_stage::CommitmentArtifacts, + stage6: &JoltStageProof, + stage7: &JoltStageProof, + stage7_openings: &[stage7_stage::Stage7OpeningInputValue], + transcript: &mut T, +) -> Result +where + T: Transcript, +{ + let (sumcheck_address_point, stage7_values) = stage7_claim_values(program, stage7)?; + let address_point = reverse_point(&sumcheck_address_point); + let opening_point = stage7_evaluation_opening_point(program, &address_point, stage7_openings)?; + let lagrange_factor = EqPolynomial::::zero_selector(&address_point); + let claims = evaluation_claims(program, stage6, &stage7_values, lagrange_factor)?; + + append_rlc_claims(transcript, &claims); + let gamma_powers = gamma_powers(transcript, claims.len()); + let joint_claim = claims + .iter() + .zip(&gamma_powers) + .map(|(claim, gamma)| claim.value * *gamma) + .sum(); + let joint_commitment = joint_commitment(commitments, &claims, &gamma_powers)?; + + Ok(EvaluationProofState { + opening_point, + joint_claim, + joint_commitment, + }) +} + +fn stage_eval( + proof: &JoltStageProof, + stage: &'static str, + eval_name: &'static str, +) -> Result { + for output in &proof.sumchecks { + if let Some(eval) = output.evals.iter().find(|eval| eval.name == eval_name) { + return Ok(eval.value); + } + } + Err(JoltEvaluationProofError::MissingStageEval { + stage, + eval: eval_name, + }) +} + +fn evaluation_claims( + program: &'static stage8_stage::Stage8EvaluationProgramPlan, + stage6: &JoltStageProof, + stage7_values: &BTreeMap<&'static str, Fr>, + lagrange_factor: Fr, +) -> Result, JoltEvaluationProofError> { + let mut claims = Vec::with_capacity(program.opening_claims.len()); + for plan in program.opening_claims { + let value = match plan.source_stage { + "stage6" => stage_eval(stage6, plan.source_stage, plan.source_claim)? * lagrange_factor, + "stage7" => *stage7_values.get(plan.source_claim).ok_or( + JoltEvaluationProofError::MissingStageEval { + stage: plan.source_stage, + eval: plan.source_claim, + }, + )?, + _ => { + return Err(JoltEvaluationProofError::MissingStageEval { + stage: plan.source_stage, + eval: plan.source_claim, + }); + } + }; + claims.push(EvaluationClaim { + oracle: plan.oracle, + value, + }); + } + Ok(claims) +} + +fn stage7_claim_values( + program: &'static stage8_stage::Stage8EvaluationProgramPlan, + proof: &JoltStageProof, +) -> Result<(Vec, BTreeMap<&'static str, Fr>), JoltEvaluationProofError> { + let stage7_plans = program + .opening_claims + .iter() + .filter(|plan| plan.source_stage == "stage7") + .collect::>(); + for output in &proof.sumchecks { + let mut values = BTreeMap::new(); + for plan in &stage7_plans { + if let Some(eval) = output.evals.iter().find(|eval| eval.name == plan.source_claim) { + let _ = values.insert(plan.source_claim, eval.value); + } + } + if values.len() == stage7_plans.len() { + return Ok((output.point.clone(), values)); + } + } + Err(JoltEvaluationProofError::MissingStage7RaEval) +} + +fn reverse_point(point: &[Fr]) -> Vec { + point.iter().rev().copied().collect() +} + +fn stage7_evaluation_opening_point( + program: &'static stage8_stage::Stage8EvaluationProgramPlan, + address_point: &[Fr], + stage7_openings: &[stage7_stage::Stage7OpeningInputValue], +) -> Result, JoltEvaluationProofError> { + let cycle_source_symbol = program.evaluation_point_source.source_claim; + let cycle_source = stage7_openings + .iter() + .find(|input| input.symbol == cycle_source_symbol) + .ok_or(JoltEvaluationProofError::MissingStage7EvaluationPoint)?; + if cycle_source.point.len() < address_point.len() { + return Err(JoltEvaluationProofError::InvalidPointLength { + artifact: cycle_source_symbol, + expected: address_point.len(), + actual: cycle_source.point.len(), + }); + } + let mut point = Vec::with_capacity(cycle_source.point.len()); + point.extend_from_slice(address_point); + point.extend_from_slice(&cycle_source.point[address_point.len()..]); + Ok(point) +} + +fn append_rlc_claims(transcript: &mut T, claims: &[EvaluationClaim]) +where + T: Transcript, +{ + transcript.append(&LabelWithCount(b"rlc_claims", claims.len() as u64)); + for claim in claims { + claim.value.append_to_transcript(transcript); + } +} + +fn gamma_powers(transcript: &mut T, count: usize) -> Vec +where + T: Transcript, +{ + let gamma = transcript.challenge(); + let mut powers = Vec::with_capacity(count); + let mut power = Fr::from_u64(1); + for _ in 0..count { + powers.push(power); + power *= gamma; + } + powers +} + +fn joint_commitment( + commitments: &commitment_stage::CommitmentArtifacts, + claims: &[EvaluationClaim], + gamma_powers: &[Fr], +) -> Result { + let mut coefficients = BTreeMap::<&'static str, Fr>::new(); + for (claim, gamma) in claims.iter().zip(gamma_powers) { + let coefficient = coefficients.entry(claim.oracle).or_insert(Fr::from_u64(0)); + *coefficient += *gamma; + } + let mut commitment_values = Vec::with_capacity(coefficients.len()); + let mut scalars = Vec::with_capacity(coefficients.len()); + for (oracle, coefficient) in coefficients { + commitment_values.push(commitment_for_oracle(commitments, oracle)?); + scalars.push(coefficient); + } + Ok(::combine( + &commitment_values, + &scalars, + )) +} + +fn commitment_for_oracle( + commitments: &commitment_stage::CommitmentArtifacts, + oracle: &'static str, +) -> Result { + for (record, commitment) in commitments.records.iter().zip(&commitments.commitments) { + if record.oracle == oracle { + return commitment + .clone() + .ok_or(JoltEvaluationProofError::MissingCommitment { oracle }); + } + } + Err(JoltEvaluationProofError::MissingCommitment { oracle }) +} From 68adcb91bf60468d0102a22fd2c86e930a37a06d Mon Sep 17 00:00:00 2001 From: Markos Georghiades <53157953+Markos-The-G@users.noreply.github.com> Date: Fri, 8 May 2026 00:19:40 -0400 Subject: [PATCH 06/14] test(equivalence): add Bolt parity oracle Add the jolt-equivalence crate for comparing the Bolt-generated path against jolt-core, including generated-role parity, real-data/tamper gates, and perf oracle tests. Wire the crate into the workspace and add focused GitHub workflows plus a local Bolt LLVM/MLIR setup helper. Validation: cargo check -p jolt-equivalence -q attempted, blocked locally by missing llvm-config / MLIR_SYS_220_PREFIX. --- .github/workflows/bolt-equivalence.yml | 90 ++ .github/workflows/bolt-perf-oracle.yml | 91 ++ Cargo.lock | 36 + Cargo.toml | 2 + Makefile | 5 +- crates/jolt-equivalence/Cargo.toml | 45 + crates/jolt-equivalence/GOAL.md | 1418 +++++++++++++++++ crates/jolt-equivalence/README.md | 50 + crates/jolt-equivalence/src/adapters.rs | 59 + crates/jolt-equivalence/src/artifacts.rs | 144 ++ crates/jolt-equivalence/src/bolt_oracle.rs | 841 ++++++++++ crates/jolt-equivalence/src/bolt_programs.rs | 170 ++ crates/jolt-equivalence/src/checkpoint.rs | 273 ++++ crates/jolt-equivalence/src/checks.rs | 565 +++++++ .../jolt-equivalence/src/commitment_oracle.rs | 419 +++++ .../jolt-equivalence/src/core_conversion.rs | 372 +++++ crates/jolt-equivalence/src/core_oracle.rs | 518 ++++++ crates/jolt-equivalence/src/lib.rs | 28 + crates/jolt-equivalence/src/perf.rs | 128 ++ crates/jolt-equivalence/src/plan_adapters.rs | 755 +++++++++ .../src/plan_adapters/generated_commitment.rs | 87 + .../src/plan_adapters/generated_stage1.rs | 19 + .../src/plan_adapters/generated_stage2.rs | 25 + .../src/plan_adapters/generated_stage3.rs | 26 + .../src/plan_adapters/generated_stage4.rs | 28 + .../src/plan_adapters/generated_stage5.rs | 28 + .../src/plan_adapters/generated_stage6.rs | 29 + .../src/plan_adapters/generated_stage7.rs | 29 + .../src/plan_adapters/stage1.rs | 20 + .../src/plan_adapters/stage2.rs | 26 + .../src/plan_adapters/stage3.rs | 27 + .../src/plan_adapters/stage4.rs | 28 + .../src/plan_adapters/stage5.rs | 28 + .../src/plan_adapters/stage6.rs | 29 + .../src/plan_adapters/stage7.rs | 29 + crates/jolt-equivalence/src/tamper.rs | 894 +++++++++++ .../jolt-equivalence/tests/bolt_commitment.rs | 317 ++++ crates/jolt-equivalence/tests/bolt_perf.rs | 20 + .../tests/generated_role_crates.rs | 142 ++ scripts/setup-bolt-dev.sh | 99 ++ 40 files changed, 7938 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/bolt-equivalence.yml create mode 100644 .github/workflows/bolt-perf-oracle.yml create mode 100644 crates/jolt-equivalence/Cargo.toml create mode 100644 crates/jolt-equivalence/GOAL.md create mode 100644 crates/jolt-equivalence/README.md create mode 100644 crates/jolt-equivalence/src/adapters.rs create mode 100644 crates/jolt-equivalence/src/artifacts.rs create mode 100644 crates/jolt-equivalence/src/bolt_oracle.rs create mode 100644 crates/jolt-equivalence/src/bolt_programs.rs create mode 100644 crates/jolt-equivalence/src/checkpoint.rs create mode 100644 crates/jolt-equivalence/src/checks.rs create mode 100644 crates/jolt-equivalence/src/commitment_oracle.rs create mode 100644 crates/jolt-equivalence/src/core_conversion.rs create mode 100644 crates/jolt-equivalence/src/core_oracle.rs create mode 100644 crates/jolt-equivalence/src/lib.rs create mode 100644 crates/jolt-equivalence/src/perf.rs create mode 100644 crates/jolt-equivalence/src/plan_adapters.rs create mode 100644 crates/jolt-equivalence/src/plan_adapters/generated_commitment.rs create mode 100644 crates/jolt-equivalence/src/plan_adapters/generated_stage1.rs create mode 100644 crates/jolt-equivalence/src/plan_adapters/generated_stage2.rs create mode 100644 crates/jolt-equivalence/src/plan_adapters/generated_stage3.rs create mode 100644 crates/jolt-equivalence/src/plan_adapters/generated_stage4.rs create mode 100644 crates/jolt-equivalence/src/plan_adapters/generated_stage5.rs create mode 100644 crates/jolt-equivalence/src/plan_adapters/generated_stage6.rs create mode 100644 crates/jolt-equivalence/src/plan_adapters/generated_stage7.rs create mode 100644 crates/jolt-equivalence/src/plan_adapters/stage1.rs create mode 100644 crates/jolt-equivalence/src/plan_adapters/stage2.rs create mode 100644 crates/jolt-equivalence/src/plan_adapters/stage3.rs create mode 100644 crates/jolt-equivalence/src/plan_adapters/stage4.rs create mode 100644 crates/jolt-equivalence/src/plan_adapters/stage5.rs create mode 100644 crates/jolt-equivalence/src/plan_adapters/stage6.rs create mode 100644 crates/jolt-equivalence/src/plan_adapters/stage7.rs create mode 100644 crates/jolt-equivalence/src/tamper.rs create mode 100644 crates/jolt-equivalence/tests/bolt_commitment.rs create mode 100644 crates/jolt-equivalence/tests/bolt_perf.rs create mode 100644 crates/jolt-equivalence/tests/generated_role_crates.rs create mode 100755 scripts/setup-bolt-dev.sh diff --git a/.github/workflows/bolt-equivalence.yml b/.github/workflows/bolt-equivalence.yml new file mode 100644 index 0000000000..fbc2a5c3e6 --- /dev/null +++ b/.github/workflows/bolt-equivalence.yml @@ -0,0 +1,90 @@ +name: Bolt equivalence + +on: + pull_request: + branches: [main] + push: + branches: [main] + schedule: + - cron: "47 9 * * *" + workflow_dispatch: + inputs: + include_full_sweep: + description: "Run the optional full jolt-equivalence sweep" + required: false + default: "false" + +env: + CARGO_TERM_COLOR: always + RUSTFLAGS: -D warnings + +jobs: + generated-role-full-field: + name: generated role full-field challenge parity + runs-on: macos-latest + steps: + - uses: actions/checkout@v6 + - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + components: rust-src + - name: Install nextest + uses: taiki-e/install-action@nextest + - name: Install LLVM + run: brew install llvm + - name: Configure LLVM + run: | + llvm_prefix="$(brew --prefix llvm)" + sdkroot="$(xcrun --show-sdk-path)" + echo "MLIR_SYS_220_PREFIX=${llvm_prefix}" >> "$GITHUB_ENV" + echo "${llvm_prefix}/bin" >> "$GITHUB_PATH" + echo "SDKROOT=${sdkroot}" >> "$GITHUB_ENV" + echo "BINDGEN_EXTRA_CLANG_ARGS=-isysroot${sdkroot}" >> "$GITHUB_ENV" + - name: Run generated role parity + run: cargo nextest run -p jolt-equivalence --test generated_role_crates --cargo-quiet + + real-data-parity-tamper: + name: real-data parity and tamper gates + runs-on: macos-latest + steps: + - uses: actions/checkout@v6 + - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + components: rust-src + - name: Install nextest + uses: taiki-e/install-action@nextest + - name: Install LLVM + run: brew install llvm + - name: Configure LLVM + run: | + llvm_prefix="$(brew --prefix llvm)" + sdkroot="$(xcrun --show-sdk-path)" + echo "MLIR_SYS_220_PREFIX=${llvm_prefix}" >> "$GITHUB_ENV" + echo "${llvm_prefix}/bin" >> "$GITHUB_PATH" + echo "SDKROOT=${sdkroot}" >> "$GITHUB_ENV" + echo "BINDGEN_EXTRA_CLANG_ARGS=-isysroot${sdkroot}" >> "$GITHUB_ENV" + - name: Run real-data parity and tamper gates + run: cargo nextest run -p jolt-equivalence --test bolt_commitment --cargo-quiet + + full-equivalence-sweep: + name: optional full equivalence/tamper sweep + runs-on: macos-latest + if: github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && github.event.inputs.include_full_sweep == 'true') + steps: + - uses: actions/checkout@v6 + - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + components: rust-src + - name: Install nextest + uses: taiki-e/install-action@nextest + - name: Install LLVM + run: brew install llvm + - name: Configure LLVM + run: | + llvm_prefix="$(brew --prefix llvm)" + sdkroot="$(xcrun --show-sdk-path)" + echo "MLIR_SYS_220_PREFIX=${llvm_prefix}" >> "$GITHUB_ENV" + echo "${llvm_prefix}/bin" >> "$GITHUB_PATH" + echo "SDKROOT=${sdkroot}" >> "$GITHUB_ENV" + echo "BINDGEN_EXTRA_CLANG_ARGS=-isysroot${sdkroot}" >> "$GITHUB_ENV" + - name: Run full equivalence/tamper sweep + run: cargo nextest run -p jolt-equivalence --cargo-quiet diff --git a/.github/workflows/bolt-perf-oracle.yml b/.github/workflows/bolt-perf-oracle.yml new file mode 100644 index 0000000000..6def69112c --- /dev/null +++ b/.github/workflows/bolt-perf-oracle.yml @@ -0,0 +1,91 @@ +name: Bolt perf oracle + +on: + pull_request: + branches: [main] + push: + branches: [main] + schedule: + - cron: "23 8 * * *" + workflow_dispatch: + inputs: + include_large: + description: "Run the sha2-chain 2^20 gate" + required: false + default: "true" + +env: + CARGO_TERM_COLOR: always + RUSTFLAGS: -D warnings + +jobs: + sha2-chain-2-16: + name: sha2-chain 2^16 core-vs-Bolt + runs-on: macos-latest + steps: + - uses: actions/checkout@v6 + - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + components: rust-src + - name: Install nextest + uses: taiki-e/install-action@nextest + - name: Install LLVM + run: brew install llvm + - name: Configure LLVM + run: | + llvm_prefix="$(brew --prefix llvm)" + sdkroot="$(xcrun --show-sdk-path)" + echo "MLIR_SYS_220_PREFIX=${llvm_prefix}" >> "$GITHUB_ENV" + echo "${llvm_prefix}/bin" >> "$GITHUB_PATH" + echo "SDKROOT=${sdkroot}" >> "$GITHUB_ENV" + echo "BINDGEN_EXTRA_CLANG_ARGS=-isysroot${sdkroot}" >> "$GITHUB_ENV" + - name: Run perf oracle + env: + JOLT_BOLT_PERF_TRACE: "1" + run: > + cargo nextest run -p jolt-equivalence --test bolt_perf --release + --cargo-quiet --run-ignored only --no-capture + bolt_sha2_chain_2_16_core_vs_bolt_perf_oracle + - name: Upload Perfetto trace + if: always() + uses: actions/upload-artifact@v7 + with: + name: bolt-perf-oracle-sha2-chain-2-16 + path: benchmark-runs/perfetto_traces/*.json + if-no-files-found: warn + + sha2-chain-2-20: + name: sha2-chain 2^20 core-vs-Bolt + runs-on: macos-latest + if: github.event_name != 'workflow_dispatch' || inputs.include_large == 'true' + steps: + - uses: actions/checkout@v6 + - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + components: rust-src + - name: Install nextest + uses: taiki-e/install-action@nextest + - name: Install LLVM + run: brew install llvm + - name: Configure LLVM + run: | + llvm_prefix="$(brew --prefix llvm)" + sdkroot="$(xcrun --show-sdk-path)" + echo "MLIR_SYS_220_PREFIX=${llvm_prefix}" >> "$GITHUB_ENV" + echo "${llvm_prefix}/bin" >> "$GITHUB_PATH" + echo "SDKROOT=${sdkroot}" >> "$GITHUB_ENV" + echo "BINDGEN_EXTRA_CLANG_ARGS=-isysroot${sdkroot}" >> "$GITHUB_ENV" + - name: Run perf oracle + env: + JOLT_BOLT_PERF_TRACE: "1" + run: > + cargo nextest run -p jolt-equivalence --test bolt_perf --release + --cargo-quiet --run-ignored only --no-capture + bolt_sha2_chain_2_20_core_vs_bolt_perf_oracle + - name: Upload Perfetto trace + if: always() + uses: actions/upload-artifact@v7 + with: + name: bolt-perf-oracle-sha2-chain-2-20 + path: benchmark-runs/perfetto_traces/*.json + if-no-files-found: warn diff --git a/Cargo.lock b/Cargo.lock index 609fab23c2..c3792384a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2892,6 +2892,42 @@ dependencies = [ "tracing", ] +[[package]] +name = "jolt-equivalence" +version = "0.1.0" +dependencies = [ + "ark-bn254", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "blake2 0.11.0-rc.6", + "bolt", + "common", + "jolt-core", + "jolt-dory", + "jolt-field", + "jolt-inlines-sha2", + "jolt-kernels", + "jolt-lookup-tables", + "jolt-openings", + "jolt-poly", + "jolt-profiling", + "jolt-prover", + "jolt-r1cs", + "jolt-sumcheck", + "jolt-trace", + "jolt-transcript", + "jolt-verifier", + "jolt-witness", + "num-traits", + "postcard", + "rayon", + "serde", + "strum 0.28.0", + "tracer", + "tracing", +] + [[package]] name = "jolt-eval" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 8de50db4df..1358c6d455 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,6 +40,7 @@ members = [ "crates/jolt-kernels", "crates/jolt-prover", "crates/jolt-verifier", + "crates/jolt-equivalence", "crates/jolt-profiling", "crates/jolt-field", "jolt-core", @@ -395,6 +396,7 @@ bolt = { path = "./crates/bolt" } jolt-kernels = { path = "./crates/jolt-kernels" } jolt-prover = { path = "./crates/jolt-prover" } jolt-verifier = { path = "./crates/jolt-verifier" } +jolt-equivalence = { path = "./crates/jolt-equivalence" } jolt-riscv = { path = "./crates/jolt-riscv" } jolt-trace = { path = "./crates/jolt-trace" } jolt-lookup-tables = { path = "./crates/jolt-lookup-tables" } diff --git a/Makefile b/Makefile index e3147e9568..e15d10247d 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: help bootstrap build-emulator \ +.PHONY: help bootstrap bolt-dev-setup build-emulator \ arch-tests-64imac arch-tests-generate arch-tests-run arch-tests-smoke MAKEFILE_DIR := $(abspath $(dir $(firstword $(MAKEFILE_LIST)))) @@ -26,6 +26,9 @@ help: bootstrap: ## Install arch-test prerequisites (riscv64 toolchain, sail_riscv_sim) ./scripts/bootstrap +bolt-dev-setup: ## Install/configure the local Bolt LLVM/MLIR toolchain + ./scripts/setup-bolt-dev.sh + build-emulator: ## Build the jolt-emu binary in debug mode # Debug build is intentional — arch tests are correctness-sensitive and # don't benefit from release optimizations. diff --git a/crates/jolt-equivalence/Cargo.toml b/crates/jolt-equivalence/Cargo.toml new file mode 100644 index 0000000000..f34c8597fc --- /dev/null +++ b/crates/jolt-equivalence/Cargo.toml @@ -0,0 +1,45 @@ +[package] +name = "jolt-equivalence" +version = "0.1.0" +edition = "2021" +license = "MIT" +description = "Cross-system equivalence testing between jolt-core and Bolt-generated Jolt artifacts" + +[lints] +workspace = true + +[dependencies] +# jolt-core reference prover/verifier. Equivalence tests compare against the +# generated full-field Fiat-Shamir path. +jolt-core = { path = "../../jolt-core", features = ["host", "challenge-254-bit"] } +ark-bn254.workspace = true +ark-ff.workspace = true +ark-serialize.workspace = true +ark-std.workspace = true +postcard.workspace = true + +# Bolt-generated Jolt path and shared modular primitives. +common = { path = "../../common" } +jolt-field = { path = "../jolt-field", features = ["bn254"] } +jolt-transcript = { path = "../jolt-transcript" } +bolt = { path = "../bolt" } +jolt-prover = { path = "../jolt-prover" } +jolt-verifier = { path = "../jolt-verifier" } +jolt-trace = { path = "../jolt-trace" } +jolt-dory = { path = "../jolt-dory" } +jolt-inlines-sha2.workspace = true +jolt-kernels = { path = "../jolt-kernels" } +jolt-lookup-tables = { path = "../jolt-lookup-tables" } +jolt-openings = { path = "../jolt-openings", features = ["test-utils"] } +jolt-poly = { path = "../jolt-poly" } +jolt-profiling = { path = "../jolt-profiling" } +jolt-r1cs = { path = "../jolt-r1cs" } +jolt-sumcheck = { path = "../jolt-sumcheck" } +jolt-witness = { path = "../jolt-witness" } +tracer = { path = "../../tracer" } +num-traits.workspace = true +blake2.workspace = true +rayon.workspace = true +serde.workspace = true +strum.workspace = true +tracing.workspace = true diff --git a/crates/jolt-equivalence/GOAL.md b/crates/jolt-equivalence/GOAL.md new file mode 100644 index 0000000000..3ff20c9d6f --- /dev/null +++ b/crates/jolt-equivalence/GOAL.md @@ -0,0 +1,1418 @@ +# Jolt Equivalence Goal + +`jolt-equivalence` is the bootstrap oracle and gate suite for Jolt-on-Bolt. +It exists to prove that the Bolt-generated prover/verifier is equivalent to +`jolt-core` while Bolt is maturing. It must stay a thin logical comparison +crate: run both implementations, translate public artifacts into common shapes, +compare them, mutate proofs, and enforce perf gates. + +It must not become a shadow implementation of Jolt. + +## Objective + +Shrink `jolt-equivalence` into a strict oracle/gating crate while moving all +Jolt semantic construction required for equivalence into Jolt-on-Bolt itself. + +The target state is: + +```text +core temporary oracle -> canonical public artifacts +Bolt generated prover -> canonical public artifacts +Bolt generated verifier -> accepts valid Bolt proof and rejects mutated proofs +jolt-equivalence -> compares artifacts, drives fuzz/tamper/perf gates +``` + +The harness should answer: + +```text +Did Bolt produce the same public protocol artifacts as core? +Did Bolt verifier accept the honest Bolt proof? +Did Bolt verifier reject malformed or tampered proofs? +Did Bolt stay within configured perf bounds versus core? +``` + +The harness should not answer: + +```text +How are Stage 6/7 opening points normalized? +How is hamming-weight claim reduction constructed? +How are witness polynomials evaluated? +How do private core verifier stages compute intermediate state? +``` + +Those are Bolt/codegen/kernel responsibilities. + +## Non-Negotiables + +- `jolt-equivalence` must not encode major Jolt stage semantics. +- New semantic mismatches must be fixed in Bolt IR/codegen/kernels/generated + prover/verifier, not by adding reconstruction logic to the harness. +- Core access must use public APIs or explicit public oracle/export APIs added + for equivalence. Do not depend on private verifier stage methods. +- Generated Bolt artifacts must expose enough canonical data for the harness to + compare without rebuilding hidden state. +- Checked-in `jolt-prover` and `jolt-verifier` are generated artifacts, not + hand-maintained source. Any behavioral change visible there must be made in + Bolt IR/codegen/kernels or shared runtime/witness crates, then kept in sync + through the generated-artifact rail. +- The full-field non-zk path is the active equivalence target: + `Transcript` / `challenge-254-bit`. +- Later-stage prover-side witness data, claim inputs, and opening inputs must + come from generated Bolt prover artifacts or shared `jolt-witness` + primitives, not from harness reconstruction. +- The eventual replacement path is Bolt over core. Core is only the temporary + oracle until Bolt is mature enough to deprecate it. + +## Allowed Responsibilities + +`jolt-equivalence` may contain: + +- test fixtures that run core and Bolt on the same guest/input +- adapters from public core artifacts into canonical comparison structs +- adapters from generated Bolt artifacts into the same structs +- transcript checkpoint comparison +- commitment and opening-claim comparison +- proof acceptance checks +- proof mutation and fuzz/tamper helpers +- perf metric collection and threshold checks +- small, generic conversion helpers between core/Bolt field/proof types + +Adapters may normalize representation, but only when the normalization is a +thin public-format translation. If the code needs to know a stage-specific +formula, construct a witness polynomial, rebuild a claim reduction, or infer +hidden verifier state, it belongs outside `jolt-equivalence`. + +## Forbidden Responsibilities + +Do not add or preserve harness code that: + +- reconstructs Stage 6/7 opening points from sumcheck internals +- rebuilds hamming-weight claim reduction inputs +- evaluates committed witness polynomials to compensate for missing artifacts +- maintains a local value store mirroring generated verifier internals +- uses private `jolt-core` stage verifier methods as the main parity path +- hard-codes stage-specific point-order semantics in tests +- fixes equivalence failures by changing expected values only in the harness + +Existing code in this category is migration debt and should shrink each slice. + +## Current Baseline + +The important current baseline is approximately: + +```text +jolt-core full-field challenge patch: 4 files, 60 insertions, 19 deletions +jolt-equivalence Rust LOC: 6,064 total +tests/bolt_commitment.rs: 317 LOC +tests/bolt_perf.rs: 20 LOC +tests/generated_role_crates.rs: 142 LOC +adapters.rs: 62 LOC +artifacts.rs: 144 LOC +bolt_programs.rs: 170 LOC +checkpoint.rs: 273 LOC +plan_adapters.rs: 755 LOC +plan_adapters/generated_*.rs: 271 LOC +plan_adapters/stage{1..7}.rs: 187 LOC +bolt_oracle.rs: 842 LOC +commitment_oracle.rs: 419 LOC +core_conversion.rs: 374 LOC +tamper.rs: 897 LOC +checks.rs: 566 LOC +core_oracle.rs: 520 LOC +perf.rs: 77 LOC +jolt-kernels/src/trace.rs: 391 LOC +jolt-witness/src/lib.rs: 1,133 LOC +``` + +The core diff is acceptable in principle. The equivalence harness is too large +and currently contains semantic reconstruction that should move into Bolt. + +Known active blocker: + +```text +None for the focused muldiv equivalence oracle. Stage 6 Booleanity, Stage 7 +hamming-weight claim reduction, generated verification, Dory opening proof +bytes, and core acceptance all pass the focused real-trace parity gate. +``` + +Current progress on this branch: + +- Stage 6 execution artifacts now carry public opening-claim values, so Stage 7 + inputs can be adapted from Stage 6 artifacts instead of replaying a local + Stage 6 verifier store inside `jolt-equivalence`. +- Stage 6 core acceptance now includes a strict generated-eval to + `jolt_core::poly::opening_proof::OpeningId` comparison for public opening + claims. The check maps generated eval names to core opening IDs and compares + values only; it does not synthesize opening points or rebuild claims. +- Stage 1 kernel/generated plan adapters now use the shared adapter macro path + instead of bespoke per-role copies, reducing duplicated adapter code while + preserving the generated/kernel plan contract. +- Generated commitment prover/verifier plan adapters now share one local + lowering macro, preserving the same generated plan contract while cutting the + generated adapter subtree by another 60 LOC. +- Core/Bolt uni-skip proof conversion and Stage 1/2 uni-skip coefficient + checks now share generic helpers; Stage 4/5/6/7 artifact match wrappers now + share one macro. These are representation-only harness cleanups and do not + alter generated prover/verifier semantics. +- Stage 6 Booleanity now has an indexed kernel path that ports core's sparse + Booleanity semantics into `jolt-kernels`, with sparse RA index data supplied + by the caller. The dense fallback remains internally verifier-consistent, but + the core-equivalent path is sparse/indexed. +- Generated Stage 6 verifier output-claim reconstruction now uses core's + Booleanity segment-wise point convention via the Bolt verifier-common + template; `jolt-verifier` is regenerated from that source. +- Generic one-hot index/materialization helpers moved to `jolt-witness`: + sparse chunk indices, address-major one-hot materialization, point evals from + sparse indices, and MSB-first chunk/point splitting. +- Stage 6 witness materialization moved out of `jolt-equivalence` into + `jolt-witness`: sparse RA indices, Booleanity oracles, read-RAF chunks, + virtual RA evals, hamming-weight inputs, and `rd_inc`/`ram_inc` columns are + now produced by shared `Stage6WitnessInputs`/`Stage6WitnessParams` helpers. + The harness still invokes this shared primitive until generated prover + artifacts expose the same data directly. +- Stage 6/7 ordered witness-slice views moved into `jolt-witness` via + `Stage6WitnessSlices`; `bolt_oracle.rs` no longer assembles Booleanity, + read-RAF, virtual RA, or hamming-weight index chunk ordering by hand. +- Stage 6 witness construction no longer materializes dense RA Booleanity + one-hot polynomials for the normal sparse/indexed Booleanity path. The + generated prover now supplies sparse index chunks through `jolt-witness`, and + `jolt-kernels` derives the Booleanity domain from the sparse path when + indices are present. On SHA2-chain `2^20`, this moved + `bolt.prove.inputs.stage6_witness` from roughly `5.46s` to roughly `0.24s` + and reduced Bolt prove time from roughly `28.9s` to `22.6-22.8s`. +- Stage 6 bytecode read-RAF now consumes the sparse bytecode RA index chunks + already produced by `jolt-witness` when initializing its cycle phase, while + retaining the dense one-hot fallback for synthetic callers. On SHA2-chain + `2^20`, this reduced the bytecode read-RAF Stage 6 bucket from roughly + `4.3s` to roughly `1.6s` per Stage 6 execution and moved Bolt prove time to + roughly `19.4-19.9s` (`~1.97-2.00x` core). The SHA2-chain `2^16` prove ratio + is now `1.174x`, inside the 20% target. +- Stage 6 bytecode read-RAF witness construction no longer materializes dense + address-major bytecode RA chunks in the generated prover path. `jolt-witness` + now carries bytecode RA chunk lengths alongside sparse bytecode RA indices, + and `jolt-kernels` can run bytecode read-RAF from sparse indices plus chunk + lengths with no dense chunk input. The dense chunk fallback remains covered + by synthetic kernel tests. +- Stage 6/7 witness-slice-to-kernel input wiring moved onto `jolt-kernels` + public builder methods: `Stage6ProverInputs::with_stage6_witness` and + `Stage7ProverInputs::with_stage6_witness_indices`. The equivalence harness + now invokes kernel-owned routing instead of spelling out each witness field. +- Stage 6 witness construction from kernel opening inputs moved onto + `jolt-kernels::stage6_witness_from_opening_inputs`; `bolt_oracle.rs` no + longer builds `Stage6OpeningInputRef` lists or `Stage6WitnessInputs` locally. +- Generated `jolt-prover` now exposes `stage6_witness_from_opening_inputs` + from the Bolt artifact generator, so the full oracle calls the generated + prover API for Stage 6 witness materialization instead of invoking + `jolt-kernels` directly. +- Generated `jolt-prover` now also exposes `stage6_prover_inputs` and + `stage7_prover_inputs` from the Bolt artifact generator. The full oracle no + longer constructs Stage 6/7 prover input builders directly from + `jolt-kernels`; it asks the generated prover to route shared `jolt-witness` + data into the kernel executor shape. +- Generated `jolt-prover` now exposes Stage 1/2/3/4/5 prover-input helpers + from the Bolt artifact generator. The full oracle no longer spells out the + Stage 1 outer evaluator builder, Stage 2 product/instruction/RAM builder + chain, Stage 3 cycle builder, or Stage 4/5 sparse-trace builder chains in + either staged or monolithic prover setup. +- Generated `jolt-prover` now exposes Stage 5/6 opening-input derivation from + prior public artifacts. The full oracle no longer derives later-stage prover + opening inputs in `jolt-equivalence`; it only adapts the generated prover's + kernel-shaped opening inputs into generated-verifier-shaped inputs for + verifier calls. +- Generated `jolt-prover` now also exposes Stage 2/3/4 opening-input + derivation, including the Stage 4 initial-RAM precomputed opening through + `jolt-witness`. The generic source-claim opening-input derivation loop and + Stage 1/2/3/4 claim lookup helpers were deleted from + `jolt-equivalence::adapters`; remaining call sites delegate to the generated + prover API. +- Generated `jolt-prover` now exposes its stage artifact-to-proof conversion + helpers. `jolt-equivalence::adapters` no longer re-implements the generated + proof construction for Stage 2/3/4/5/6/7 or the monolithic Jolt proof stage + wrappers; it delegates to generated prover APIs and only keeps the narrow + Stage 1 tamper proof bridge and kernel replay bridges. +- Repetitive Bolt program lowering helpers in `bolt_programs.rs` were collapsed + into one local lowering macro. This is not a semantic move, but it removes + duplicated harness scaffolding around the Bolt compiler pipeline. +- Stage 2/3 full plan adapters now share the same static-plan conversion + macros as the later-stage adapter layer. +- The bespoke Stage 2 product-uniskip prefix adapter was deleted. The focused + product gate now uses the full Stage 2 generated/kernel plans while still + comparing and tampering the product sumcheck directly, so the harness no + longer owns a special partial-plan construction path. +- Stage 2/3 core opening-claim parity checks now share one comparison helper. +- Transcript state-history assertions now accept checkpoint logs directly, + removing repeated `transcript_states(...)` wrapping from the oracle and + tamper call sites without changing the gate semantics. +- Generated commitment prover/verifier artifact-to-trace conversion now shares + one adapter macro, keeping the commitment oracle focused on public + representation conversion. +- Commitment-oracle raw prover/verifier helpers are private and the one-use + prover-with-cycles wrapper is gone; tests use the focused pair runners. +- The harness-side Stage 1 core R1CS-row to RV64-row replay was deleted. + Stage 1 now gates typed RV64 and generic R1CS evaluators directly against + public core uni-skip proof coefficients, instead of maintaining a second + local core-row translation path. +- Monolithic Jolt tamper rejection assertions now share one local error-shape + assertion macro, preserving each negative case while removing repeated + `matches!(Err(...))` scaffolding. +- Removed a stale `core_conversion.rs` comment from the incremental staging + period that no longer described the proof-conversion adapter. +- Core proof-conversion helpers that are only used inside the crate are now + `fn`/`pub(crate)` instead of public API; the public surface keeps the + commitment transcript adapters used by tests. +- Commitment-oracle helpers that only wire generated artifacts internally are + now `fn`/`pub(crate)`, leaving the public surface focused on test-facing + commitment traces and transcript construction. +- Adapter canonicalizers, later-stage tamper inputs, and internal core/check + helpers are crate-private; an unused Stage 4 artifact match wrapper was + deleted after clippy exposed it as stale public surface. +- Core-oracle entry points now expose only the fixture builders and focused + Stage 1/2 acceptance checks used by integration tests; deeper full-oracle + acceptance helpers and generic guest fixture construction are crate-private. +- Unused `CheckpointTranscript` convenience methods and their stale usage + example were removed; live call sites use the borrowed checkpoint log. +- Obvious artifact/core-conversion comments that restated item names were + deleted while retaining representation and invariant notes. +- Redundant `bolt_oracle.rs` generated verifier-program rebundling, a + borrowed Stage 5 opening clone, and a duplicate transcript-prefix assertion + were deleted; the existing generated verifier bundle now drives all Stage + 5/6/7/full verifier gates. +- Plan-adapter re-exports now keep only the Stage 1/2 adapters used by the + focused integration tests public; commitment, later-stage, and Stage 8 plan + adapters are crate-private full-oracle plumbing. +- Bolt program builders now use the same public boundary: commitment and Stage + 1/2 builders remain public for focused tests, while Stage 3-8 builders are + crate-private full-oracle plumbing. +- `adapters` and `artifacts` are no longer public modules; canonical artifact + types remain re-exported from the crate root, while representation adapter + internals stay crate-private. +- Monolithic wrong-stage-slot tamper rejection now uses the shared local + verifier-error assertion macro instead of hand-rolled `matches!` scaffolding. +- `CoreMuldivCommitmentFixture` now exposes only the fields required by the + focused tests as public; later-stage witness/core-verifier data and Stage 6 + witness params are crate-private full-oracle inputs. +- Stage 2/3 core opening-claim parity now fails if Bolt omits any eval for a + mapped opening that `jolt-core` exposes publicly, and it fails if a stage's + mapping matches no public core claims. Candidate mappings that are not public + core opening claims remain ignored by this specific public-oracle gate. +- The full Bolt oracle now uses generated `jolt-prover` Stage 6/7 proof + conversion helpers instead of hand-building generated proof structs. +- The full Bolt oracle now calls generated prover stage execution wrappers for + Stage 1/2/3/4/5/6/7 prover paths and Stage 5/6/7 proof-carrying replay paths + instead of invoking `jolt-kernels` execution functions directly. Verifier-mode + kernel prefix checks still use direct kernel execution as public parity gates. +- Generated `jolt-prover` now also exposes Stage 5/6/7 proof-carrying replay + helpers. The full oracle no longer constructs later-stage proof-carrying + kernel executors directly; it asks the generated prover API to replay the + public proof artifacts with the generated prover plans. +- Generated `jolt-prover` also exposes Stage 1/2/3/4 verifier-mode replay + helpers for the public prefix parity gates. The full oracle no longer builds + early-stage verifier kernel executors or selects verifier execution mode + locally. +- Real-trace commitment proving now uses generated `jolt-prover` commitment + phase APIs with `jolt-witness::CommitmentTraceSources` / + `SparseCommitmentInputs`. The harness no longer interprets + `OracleGeneration` or materializes dense/one-hot witness oracles for the + muldiv commitment path. +- The synthetic commitment transcript-ordering gate also runs through the + generated commitment prover/verifier with a tiny synthetic input provider. + The old harness-local commitment commit/replay loop was deleted. +- Commitment transcript reconstruction now replays the generated commitment + phase's recorded append bytes after the Jolt preamble. Later-stage tests, + tamper gates, and the full Bolt oracle no longer pass Bolt commitment CPU + programs around only to recover transcript step ordering. +- Commitment oracle helpers now own generated commitment plan adaptation for + test-facing prover/verifier trace construction. The focused tests no longer + leak generated commitment plans at each call site. +- Core-vs-Bolt perf thresholds are now a named constant in + `jolt-equivalence::perf`, so the perf oracle configuration lives with the + perf helpers instead of inside the full Bolt oracle driver. +- Generated commitment trace-source storage now lives behind + `GeneratedCommitmentInputStorage` in `jolt-equivalence::commitment_oracle`. + The full Bolt oracle no longer imports generated commitment input types or + selects trace-source columns at the monolithic prover call site. +- The SHA2-chain `2^20` perf oracle job now runs on pull requests as a standard + CI gate. Manual workflow dispatch can still skip it with `include_large = + false`. +- Bolt equivalence and perf CI gates no longer use path filters, so required + PR gates cannot be skipped by changes in shared crates, guests, inlines, or + root `jolt-core`. +- The Bolt equivalence workflow now also has an optional full + `jolt-equivalence` sweep: it runs on the nightly schedule and can be triggered + manually with `include_full_sweep=true`, while the smaller generated-role and + real-data parity/tamper jobs remain the standard PR gates. +- `crates/bolt/TESTING.md` documents both SHA2-chain perf oracle PR gates, + the required nested commitment/evaluation/verification spans, and exact + local `cargo nextest` commands for the ignored perf tests. +- Perf span gating now uses span names observed by `jolt-profiling` rather + than a harness-populated allowlist, and `bolt.prove` is part of the required + top-level Bolt span contract. +- Stage 1 univariate-skip target ordering and proof-polynomial recovery now + live in `jolt-kernels`. `jolt-equivalence` still compares the resulting + values, but no longer owns that Stage 1 formula. +- The canonical artifact model now uses `jolt_profiling::PerfMetrics` + directly. The unused local `PerfSnapshot`/`PerfSpan` vocabulary was deleted + so perf gates have one metric shape. +- Non-generated `jolt-equivalence`/`jolt-kernels` code no longer uses local + `#[allow(...)]` lint suppressions. Intentional fail-fast oracle/test helper + panics are documented with `#[expect(...)]`, and + `cargo clippy -p jolt-equivalence --tests --offline -- -D warnings` + passes through the full local dependency stack. +- Bolt emitter/template sources now carry the lint expectations and mechanical + cleanups needed by generated `jolt-prover`/`jolt-verifier`, so the checked-in + generated artifacts stay aligned with their generator rail instead of being + hand-maintained. +- Generated commitment and evaluation proof code now emits nested perf spans + for Dory commitment work, Stage 8 joint-opening construction, and generated + verifier evaluation-proof checking. The core-vs-Bolt perf gate requires + those observed spans, giving CI visibility into commit/opening costs instead + of only coarse stage totals. +- Generated verifier common runtime now validates opening-input count, expected + symbols, and point arity before seeding verifier state. This is implemented + in the Bolt verifier-common template and reflected in checked-in + `jolt-verifier`, so extra/missing malformed opening inputs are rejected by + generated code rather than tolerated by the harness. +- Generated `jolt-prover` now owns construction of kernel prover executors from + generated stage-input structs, including a `JoltProverStageInputs` wrapper for + monolithic proving. The full oracle still supplies witness/input data, but no + longer instantiates prover executors or wires `JoltProverInputs` directly. +- Generated `jolt-prover` now exposes Stage 5 kernel-proof and Stage 6 bytecode + read-RAF data storage helpers. The full oracle no longer imports Stage 5/6 + kernel modules just to build those representation values. +- Generated `jolt-prover` now owns generated-to-kernel Stage 6/7 proof-shape + conversion for proof-carrying replay. The local + `define_kernel_proof_adapter!` macro was deleted from `adapters.rs`. +- Generated `jolt-verifier` now exposes public stage challenge/execution + artifact aliases, and generated `jolt-prover` now exposes Stage 6/7 generated + execution-artifact wrapping plus partial `JoltProof` assembly helpers. The + oracle and tamper gates call those generated APIs directly instead of + maintaining local Stage 6/7 artifact wrappers or partial proof constructors in + `jolt-equivalence`. +- Early-stage tamper gates now replay Stage 1/2/3 proof prefixes through + generated `jolt-prover` replay helpers instead of instantiating verifier + kernel executors in `jolt-equivalence`. +- Generated `jolt-prover` now exposes Stage 1 kernel-proof to generated-proof + conversion, and `jolt-equivalence::adapters` no longer maps Stage 1 + sumcheck/eval records by hand. +- The remaining pass-through generated proof adapters for Stages 2/3/4/5 were + deleted; oracle and tamper checks now call the generated `jolt-prover` + `stage*_proof` helpers directly. +- Generated `jolt-verifier` now exposes top-level Stage 2 RAM data aliases and + generated `jolt-prover` owns kernel-to-verifier Stage 2 RAM data storage. + The local `GeneratedStage2RamData` adapter was deleted from + `jolt-equivalence`. +- Generated `jolt-verifier` now exposes a top-level verifier opening-input + alias, and generated `jolt-prover` owns generic kernel-to-verifier + opening-input conversion. The six local generated opening-input adapter + functions were deleted from `jolt-equivalence`. +- Generated `jolt-verifier` now reexports standalone stage verifier entry + points and verifier program plan aliases at the crate root. The oracle and + tamper gates no longer invoke generated verifier stage functions through + `jolt_verifier::stages::*`; stage modules are only used where typed generated + proof/input aliases are still the public data shape. +- Generated `jolt-verifier` also reexports Stage 6 verifier-data aliases at + the crate root, and generated `jolt-prover` constructs them through that + boundary. The tamper module no longer imports generated verifier stage + modules for proof/opening/verifier-data type aliases. +- Common generated proof, opening-input, and execution-artifact shapes are now + named through `jolt_verifier` crate-root aliases in the oracle, conversion, + adapter, check, and tamper layers. Remaining `jolt_verifier::stages::*` + imports in `jolt-equivalence` are limited to real stage constants/plans such + as Stage 6 opening-claim plans and generated program adapters. +- Stale equivalence documentation was brought back in sync with the current + full standard non-zk prefix: `crates/jolt-equivalence/README.md` no longer + describes Stage 1/2 failures, and `crates/bolt/TESTING.md` now points at the + `jolt-equivalence` goal and nextest-based gates. +- Generated `jolt-prover` now owns Stage 6 witness-entry to generated verifier + bytecode data conversion, using public aliases emitted in generated + `jolt-verifier`. The local Stage 6 bytecode verifier-data adapter was deleted + from `jolt-equivalence`. +- The generated/kernel static-plan adapter macros are now mode-aware instead + of maintaining separate Stage 2/3 legacy and Stage 4/5/6/7 kernel/generated + mapping bodies. This keeps the remaining plan bridge as thin format + translation; the per-stage adapter submodules now carry much less repeated + field-mapping code. +- Stage 2/3 generated/kernel sumcheck plans now use the shared optional + `kernel`/`relation` shape. Generated Stage 2/3 verifier code aliases the + same shared plan structs as the later stages, and the equivalence adapter + uses one no-absorb generic lowering path instead of the stale Stage 2/3 + legacy adapter macro. +- Stage 1 generated/kernel sumcheck plans now also use the shared optional + `kernel`/`relation` shape. Generated Stage 1 verifier code aliases the same + shared plan structs, and the last `legacy_kernel`/`legacy_generated` + conversion arms were deleted from the equivalence plan adapter layer. +- The stale verifier-only sumcheck claim/driver plan structs were deleted from + the Bolt verifier-common template and checked-in `jolt-verifier` runtime. + All generated verifier stages now use the same shared sumcheck plan structs. +- Generated stage plus monolithic-prefix proof tamper rejection now shares one + local helper in `tamper.rs`, and stale one-use prefix replay wrappers were + deleted. The covered coefficient, eval, point, and opening-input mutations + are unchanged. +- The Stage 2 product-uniskip oracle now runs through the full Stage 2 + generated/kernel plans and passes Stage 2 RAM data through the existing + verifier input path. This deleted the focused product-only plan adapter and + reduced `plan_adapters.rs` to 767 LOC and the crate's Rust total to 6,572 + LOC without dropping the product proof parity or tamper gate. +- The full Bolt oracle now reuses the already-verified Stage 2 boundary + transcript and opening inputs when seeding the standalone generated Stage 3 + verifier path. This deletes a redundant Stage 1/2 prefix replay from + `bolt_oracle.rs`; the oracle still compares the same staged, generated, and + monolithic transcript histories. +- Stage 2/3 public core opening-claim expectation tables in `checks.rs` now + use a compact row macro with explicit one-row-per-claim mappings. This keeps + the public-oracle map visible while removing repeated wrapper boilerplate, + reducing `checks.rs` to 585 LOC and the crate's Rust total to 6,424 LOC. +- The shared Stage 1/2/3/4/5/6/7 plan adapter macros no longer carry stale + kernel/generated dispatch arms for already-unified claim and driver shapes. + The generated and kernel plan contracts are unchanged, but + `plan_adapters.rs` is down to 755 LOC and the crate's Rust total is 6,412 + LOC. +- Full core-proof conversion now reuses the staged Stage 1-7 core-proof patch + helper chain before patching commitments and the evaluation proof. This + removes a second hand-written list of Stage 1-7 sumcheck-field assignments + from `core_conversion.rs`. +- The one-use core opening-claims clone wrapper was deleted from + `core_conversion.rs`; the proof clone now spells the public `Claims` clone + directly at the field assignment site. +- Generated-role crate tests now share one small driver-presence assertion + macro, preserving the same Stage 1-7 prover/verifier surface checks while + trimming repeated test scaffolding. +- Stale commitment oracle wrappers were deleted: the unused direct + trace-source prover runner and the one-use transcript-trace method. The live + commitment path still goes through `GeneratedCommitmentInputStorage` and the + generated prover/verifier commitment APIs. +- Generated Stage 8 prover/verifier plan adapters now share the same typed + conversion macro, cutting another 67 LOC from `plan_adapters.rs` without + changing the public adapter functions. +- Stage 1/2/3/4 trace-row materialization moved into + `jolt-kernels::trace`, next to the kernel ABI structs that consume those + rows. The core oracle now calls shared kernel-owned helpers for RV64 rows, + product-virtual rows, instruction-lookup rows, RAM accesses, Stage 3 cycles, + Stage 4 register accesses, and Stage 5 lookup trace columns instead of + constructing them locally. +- Stage 6 bytecode-entry materialization also moved into + `jolt-kernels::trace`, using public `jolt-trace` instruction flag helpers. + The core oracle now supplies only the core lookup-table index callback, + keeping bytecode witness row construction out of the harness. +- Generated `jolt-prover` now exposes `JoltProverWitnessInputs` plus + `prove_jolt_with_witness_inputs`, emitted from the Bolt artifact generator. + The full Bolt oracle no longer constructs each monolithic kernel stage input + struct itself; it passes the public witness/opening views into the generated + prover API and lets that crate assemble the stage inputs. +- Generated `jolt-prover` now also exposes standalone Stage 1/2/3/4/5/6/7 + witness-input prove wrappers emitted from the Bolt artifact generator. The + staged full oracle now passes public witness/opening views to those generated + APIs instead of constructing each stage input struct locally. +- Generated `jolt-prover` crate-root exports now include those standalone + witness prove wrappers plus Stage 6 verifier-data conversion. The harness no + longer reaches into `jolt_prover::prover` for equivalence paths; it consumes + the generated crate's public API boundary directly. +- Focused Stage 1/2 tests and the full Bolt oracle no longer instantiate kernel + executors directly. They call generated prover/replay APIs and keep direct + kernel execution plumbing out of the harness path. +- The Stage 1 plan adapter no longer synthesizes missing verifier kernels in + the harness. Kernel replay uses the prover plan, while generated-verifier + checks use the generated verifier plan. +- Deleted the unused `CoreScaffold` bridge from `core_conversion.rs`; core-proof + conversion now keeps only live proof translation helpers. +- Stage 3/4/5 tamper checks now consume generated-verifier start transcripts + and opening inputs produced by the full oracle instead of replaying Stage 1/2 + prefixes and reconstructing Stage 3 openings internally for each mutation. +- Stage 2 batched tamper checks now consume the focused test's Stage 2 start + transcript and opening inputs instead of replaying Stage 1 inside every + mutation check. +- Stage 2 product-uniskip tamper checks reuse the verified Stage 2 start + transcript and generated opening inputs from their positive chain check, + avoiding repeated Stage 1 prefix replay per mutation. +- Stage 1 tamper checks now receive the already-created Stage 1 start + transcript from the focused test instead of rebuilding the commitment + transcript per mutation. +- Generated `jolt-prover` now owns Stage 6 witness construction inside + monolithic proving and exposes Stage 6/7 trace-witness prove wrappers. The + full oracle passes `Stage6WitnessParams` plus trace inputs instead of creating + `Stage6WitnessPolynomials` or witness slices locally. +- Generated `jolt-prover` also owns Stage 4/5 sparse trace witness + construction inside monolithic proving and exposes Stage 4/5 trace-witness + prove wrappers. The full oracle passes register/RAM accesses instead of + creating `Stage45SparseTraceWitness` locally, and the core fixture no longer + exposes that witness builder. +- Fixture-derived Stage 2 RAM data and Stage 6 witness parameters are now + exposed as named public views on `CoreMuldivCommitmentFixture`; `bolt_oracle.rs` + no longer spells out the fixture field mapping for those kernel inputs. +- Fixture-derived Stage 1 R1CS key/data views are now exposed on + `CoreMuldivCommitmentFixture`; the focused tests and Bolt oracle no longer + construct `Stage1OuterRv64Data`/`Stage1OuterR1csData` directly from fixture + fields. +- Stage 4/5 sparse trace witness routing moved onto `jolt-kernels` public + builder methods: `Stage4ProverInputs::with_sparse_trace_witness` and + `Stage5ProverInputs::with_sparse_trace_witness`. The equivalence harness no + longer constructs those kernel witness structs by hand in both standalone and + monolithic prover paths. +- Stage 4/5 sparse trace witness bundle routing moved further into + `jolt-kernels` via `with_stage45_sparse_trace_witness`; `bolt_oracle.rs` + now passes the shared `Stage45SparseTraceWitness` bundle instead of selecting + the per-stage sparse columns itself. +- Stage 4/5 sparse trace witness columns moved into + `jolt-witness::stage4_5_sparse_trace_witness`; `bolt_oracle.rs` no longer + computes `rd_inc`, `ram_inc`, RAM address, or RD write-address columns by + hand. +- Additional primitive prover-side helpers moved into `jolt-witness`: generated + dense/one-hot `CycleInput` source selection, one-hot padding policy mapping, + optional oracle fixture data, `u64` increment columns, optional address + columns, and generic `u64` MLE evaluation. The harness now calls shared + helpers instead of defining local `stage4_rd_inc`, `stage2_ram_inc`, + `dense_source`, `one_hot_source`, `padding_value`, `optional_oracle_data`, or + `mle_eval_u64` functions. +- Generated commitment trace-source grouping moved into + `jolt-witness::CommitmentTraceSources`, and the Bolt commitment emitter now + generates `CommitmentOracleInputs::from_trace_sources`. The equivalence + oracle no longer selects generated commitment columns by source-string at the + monolithic prover call site. +- The commitment oracle now exposes canonical `CommitmentTrace` and + `TranscriptTrace` snapshots. The commitment tests compare these + representation-only artifacts through `EquivalenceRun` for Bolt + prover/verifier parity and core commitment parity, starting to wire the + canonical model into live gates. +- Monolithic commitment parity now also compares canonical `CommitmentTrace` + snapshots, and the old raw optional-commitment checker was deleted from + `checks.rs`. +- Stage 4/5/6/7 artifact parity now compares canonical `StageArtifacts` + snapshots instead of comparing generated/kernel proof structs directly. +- The full Bolt oracle now compares staged-vs-monolithic generated prover + output as canonical `EquivalenceRun` commitments plus Stage 4/5/6/7 snapshots. +- Generated `jolt-verifier` now exposes explicit + `verify_jolt_through_stage{5,6,7}_with_programs` entrypoints emitted from + Bolt's artifact generator. The equivalence oracle no longer fabricates empty + Stage 6/7 verifier programs to scope prefix gates. +- Bolt perf metrics now include generated proof byte counts, and the perf + oracle enables the proof-size ratio gate instead of leaving proof size + unreported. +- Generated proof-size accounting now lives in `jolt-equivalence::perf` + instead of the full Bolt oracle, keeping measurement details with the perf + gate helpers. +- The full generated prover/verifier parity check now compares canonical + `EquivalenceRun` commitment and Stage 4/5/6/7 snapshots for both sides + instead of only checking late-stage sumcheck counts. +- Generated `jolt-prover` now exposes + `stage7_opening_inputs_from_stage6_artifacts{,_with_program}` from the Bolt + artifact generator. The full oracle no longer looks up Stage 6 opening + claims by Stage 7 source strings locally; `jolt-equivalence` only converts + the generated prover's kernel input shape into the generated verifier input + shape. +- The generated standalone verifier crate now has an explicit `serde` + dependency override, so the generated-artifact crate-layout gate compiles it + without relying on workspace path dependency resolution. +- Stage 6 bytecode read-RAF source data now uses a neutral + `jolt-witness::Stage6BytecodeEntry` fixture shape. Generated verifier data is + rendered from that shared witness shape, while kernel prover bytecode input is + rendered by `jolt-kernels::stage6::Stage6BytecodeReadRafDataStorage`. This + deletes the generated-verifier-to-kernel bytecode conversion from + `jolt-equivalence::adapters` and preserves the generated prover/verifier + import boundary enforced by the artifact gate. +- Stage 2 product-virtual witness construction moved into + `Stage2ProverInputs::with_product_virtual_witness`; the kernel now derives + the product uniskip extended evaluations from the Product opening point + instead of requiring `jolt-equivalence` to find `tau_low` and compute them. + The focused Stage 2 tests now use this builder too, so + `tests/bolt_commitment.rs` no longer imports or calls + `product_virtual_uniskip_extended_evals` directly. +- Stage 4/5 sparse trace witness construction over kernel access types moved + into `jolt-kernels::stage4::stage4_5_sparse_trace_witness_from_accesses`; + the equivalence oracle no longer maps `Stage4RegisterAccess` and + `Stage2RamAccess` into generic tuple streams itself. +- The core fixture now exposes the Stage 4/5 sparse trace witness as a named + public view; `bolt_oracle.rs` no longer pairs fixture register/RAM access + fields to build that witness at the call site. +- Stage 4 initial-RAM opening construction moved into + `jolt-witness::stage4_ram_val_init_opening`; `jolt-equivalence` no longer + performs the `RamValInit` MLE evaluation directly. +- Point-order helpers moved into `jolt-witness`: `reverse_point`, + `reversed_suffix`, `normalized_stage4_registers_rw_point`, + `stage5_instruction_cycle_point`, `stage5_instruction_ra_point`, + `stage5_ram_ra_point`, and `stage5_registers_val_point`. The harness still + wires opening inputs from generated/core artifacts, but no longer owns those + point-normalization primitives. +- Transcript state-history checker helpers moved from `tests/bolt_commitment.rs` + into `jolt-equivalence::checkpoint`, starting the Slice 4 split of checker + utilities out of the monolithic integration test. +- Commitment/proof checker helpers moved into `jolt-equivalence::checks`, and + the malformed unrelated Dory proof fixture moved into + `jolt-equivalence::tamper`. +- Stage 1 tamper rejection moved into `jolt-equivalence::tamper`; the + integration test invokes the tamper gate instead of owning the mutation and + verifier-rejection loop. +- Stage 2 product uni-skip chain verifier/tamper rejection moved into + `jolt-equivalence::tamper`; `tests/bolt_commitment.rs` no longer owns the + Stage 2 product mutation loop. +- Stage 2 batched verifier tamper rejection moved into + `jolt-equivalence::tamper`; the integration test now only supplies the + public Stage 1/2 artifacts, RAM data, and verifier plans. +- Repeated tamper mutation construction in `jolt-equivalence::tamper` now uses + small shared helpers for coefficient/eval/point edits, preserving the same + rejection coverage while shrinking stage-local boilerplate. +- Repeated tamper transcript replay, Stage 1/2 prefix replay, and generated + monolithic verifier rejection setup now use small shared helpers in + `jolt-equivalence::tamper`; the mutation set and verifier coverage are + unchanged. +- Bolt transcript construction with the Jolt preamble and commitment transcript + steps is now centralized in `jolt-equivalence::commitment_oracle`; the test + driver, `bolt_oracle.rs`, and `tamper.rs` no longer each own local + `CheckpointTranscript` bootstrap helpers. +- Repeated batched sumcheck tamper triplets now use one local macro in + `jolt-equivalence::tamper`; the same coefficient/eval/point mutations are + still applied to every covered stage. +- Stage 6/7 generated verifier and monolithic-prefix tamper rejection moved + into `jolt-equivalence::tamper`; `bolt_oracle.rs` now passes public + artifacts into those gates instead of owning the mutation loops. +- Stage 6/7 tamper gates now also mutate public opening-claim input + evaluations and require both the standalone generated verifier and generated + monolithic prefix verifier to reject them. The generated proof shape has no + separate opening-claim field, so this gates the public claim contract the + verifier actually consumes. +- Stage 6/7 tamper gates now also remove one opening-claim input and append a + duplicate extra opening-claim input, and shorten an opening point, requiring + both the standalone generated verifier and generated monolithic prefix + verifier to reject malformed public input lists and invalid point arity. +- Generated verifier opening-input validation now lives in the Bolt verifier + common template and checked-in generated verifier: malformed input count, + duplicate/missing symbols, and invalid point arity are rejected before a + stage accepts public opening inputs. +- The generated verifier cleanup gate is back under its strict targets after a + generator-level top-level API compaction and regeneration: + generated surface 5,966 LOC, shared runtime 1,789 LOC, total verifier 7,755 + LOC, and `verifier.rs` 487 LOC. +- Monolithic full-proof tamper gates now mutate the Stage 8 opening-point + suffix consumed from the declared Stage 7 opening input, and require the + generated verifier/Dory check to reject the proof. Prefix point coordinates + are intentionally not gated here because Stage 8 reconstructs them from the + Stage 7 sumcheck point rather than trusting the opening input. +- Stage 3/4/5 generated verifier and monolithic-prefix tamper rejection moved + into `jolt-equivalence::tamper`; the full-trace Bolt oracle no longer owns + per-stage proof mutation loops. +- Monolithic full-proof verifier rejection gates moved into + `jolt-equivalence::tamper`: missing verifier setup, missing evaluation proof, + tampered evaluation proof, missing required commitment, missing Stage 1-7 + proofs, and swapped Stage 6/7 proof slots. + `bolt_oracle.rs` now passes the honest monolithic proof plus public verifier + inputs into one tamper gate. +- Repeated generated monolithic `JoltVerifierInputs` literals in + `bolt_oracle.rs` now use one borrowed verifier-input view with explicit + stage-prefix constructors, reducing verifier wiring duplication without + changing any stage semantics. +- Generated `jolt-verifier` now emits target-scoping methods on + `JoltVerifierInputs` (`through_stage5`, `through_stage6`, `through_stage7`, + and `full`). The equivalence harness consumes that generated API directly, + so `adapters.rs` no longer owns monolithic Jolt verifier input construction. +- Stage 2/3 core opening-claim parity tables moved into + `jolt-equivalence::checks`; `tests/bolt_commitment.rs` no longer imports core + opening IDs or witness polynomial enums for those comparisons. +- Stage 1/2/3/6 core proof coefficient parity helpers moved into + `jolt-equivalence::checks`, further narrowing `tests/bolt_commitment.rs` to + orchestration plus core acceptance wiring. +- Stage 1 uniskip extended-eval parity moved into + `jolt-equivalence::checks`, removing another checker helper from the + monolithic integration driver. +- Stage 4/5/6/7 artifact equality assertions moved into + `jolt-equivalence::checks`, continuing the split of checker code out of the + monolithic `bolt_commitment.rs` test. +- Repeated Stage 4/5/6/7 artifact equality loops and Stage 2/3/6 compressed + sumcheck coefficient checks now use local checker macros; the assertions are + still thin public-artifact comparisons rather than semantic reconstruction. +- Repeated canonical Stage 4/5/6/7 artifact wrapper functions in + `jolt-equivalence::adapters` now share one typed adapter macro, preserving + public function names while cutting another 25 LOC of representation-only + boilerplate. +- The perf tracing setup helper moved into `jolt-equivalence::perf`; the perf + oracle tests now live in the dedicated `tests/bolt_perf.rs` target. +- Thin generated/kernel representation adapters for opening inputs, Stage 2 + RAM data, and Stage 6 bytecode entries moved into + `jolt-equivalence::adapters`. +- Repeated generated/kernel opening-input representation adapters now share one + typed adapter macro in `jolt-equivalence::adapters`. +- Stage 2/3/4/5/6 opening-input derivation now shares one generic + `source_stage`/`source_claim` adapter loop; the stage-specific source map is + explicit, but the harness no longer repeats the same map/assert/panic + scaffolding in every stage adapter. +- Generated Stage 2 RAM conversion now uses + `jolt-equivalence::adapters::GeneratedStage2RamData`; `bolt_oracle.rs` and + Stage 2 tamper checks no longer rebuild generated RAM access/layout structs + locally. +- Generated-to-kernel Stage 6 bytecode read-RAF conversion now uses + `jolt-equivalence::adapters::KernelStage6BytecodeData`; the Bolt oracle no + longer unwraps generated verifier data and rebuilds kernel bytecode data + locally. +- Bolt oracle transcript initialization now uses small preamble/commitment + helpers, keeping transcript setup explicit while reducing repeated harness + scaffolding. +- Generated Stage 6 verifier-data construction from bytecode preprocessing + moved into `jolt-equivalence::adapters`; `tests/bolt_commitment.rs` now + treats it as a public-format adapter instead of owning the conversion. +- Kernel/generated/Jolt proof-shape converters moved into + `jolt-equivalence::adapters`; `bolt_commitment.rs` now imports + `to_generated_*`, `to_kernel_*`, `to_jolt_*`, and generated execution + artifact adapters instead of defining them locally. +- Core proof-shape converters moved into `jolt-equivalence::core_conversion`; + `bolt_commitment.rs` now imports `clone_core_proof`, + `to_core_uniskip_proof`, and `to_core_stage2_uniskip_proof` instead of + defining local core proof constructors. +- Core proof patch builders for staged Bolt acceptance and full/evaluation + proofs moved into `jolt-equivalence::core_conversion`; the integration test + now only calls public core verifier acceptance on those converted proofs. +- Core oracle fixture construction, trace-to-kernel public oracle data, RV64 + row parity checks, and public core acceptance gates moved into + `jolt-equivalence::core_oracle`; the integration test no longer owns the + jolt-core runner or staged core verifier wrappers. +- Core commitment transcript replay moved into + `jolt-equivalence::core_conversion`; the monolithic test now supplies only + public commitment records and transcript steps to the oracle helper. +- Bolt commitment-phase replay moved into + `jolt-equivalence::commitment_oracle`; the test no longer owns commitment + materialization, optional-commit skip policy handling, Dory layout commits, + or commitment transcript-log construction. +- Bolt preamble transcript append logic moved into + `jolt-equivalence::commitment_oracle` behind a small source trait, removing + local label/u64/bytes transcript encoding helpers from the integration test. +- Commitment oracle data materialization for real traces moved into + `jolt-equivalence::commitment_oracle`; the integration test now asks the + Bolt adapter for oracle inputs instead of owning `OracleGeneration` handling. +- Bolt protocol-program construction moved into + `jolt-equivalence::bolt_programs`; `tests/bolt_commitment.rs` no longer owns + MLIR lowering/projecting/extraction glue for each stage. +- Generated/kernel static plan adapters moved into + `jolt-equivalence::plan_adapters`; the integration test now asks for + translated plans instead of owning the `leak_*` conversion block. +- Stage 1/2/3/4/5/6/7 kernel plan adapters were split into focused + `plan_adapters/stage*.rs` submodules, reducing the monolithic + `plan_adapters.rs` while preserving the same public adapter functions. +- Generated commitment and Stage 1/2/3/4/5/6/7 verifier plan adapters were + split into focused `plan_adapters/generated_*.rs` submodules. +- Stage 4/5/6/7 generated-verifier and kernel plan adapters now use typed + macro-generated field mapping instead of repeated stage-local boilerplate, + reducing the adapter subtree by about 1.3k LOC without changing the public + adapter functions. +- Kernel/generated/Jolt proof-shape converters now use typed adapter macros + instead of repeated stage-local conversion bodies, preserving the same public + conversion functions while cutting more boilerplate from `adapters.rs`. +- Full real-trace Bolt prover/verifier orchestration moved into + `jolt-equivalence::bolt_oracle`; `tests/bolt_commitment.rs` is now focused + on commitment/Stage 1/Stage 2 orchestration and public gate calls. +- Stage 7 opening-input adaptation from public Stage 6 opening claims moved + into `jolt-equivalence::adapters`. +- Stage 2/3/4/5/6/7 kernel execution artifacts now record public opening-claim + values produced by the stage plans, including logical aliases that are + transcript-deduped. Stage 3/4/5/6 opening inputs are now derived by thin + `source_claim` lookups over generated/kernel `opening_inputs` instead of + local stage point/eval formulas in `bolt_commitment.rs`. +- Stage 2 opening inputs are also derived by thin `source_claim` lookups over + the generated/kernel `opening_inputs` plan. The local + `stage2_product_opening_inputs` and `stage2_opening_inputs` builders were + deleted from `tests/bolt_commitment.rs`. +- Stage 2 RAM read-write instance point order is fixed in Bolt codegen and the + checked-in generated Stage 2 prover/verifier constants so committed `RamInc` + opening points match core-facing trace-domain semantics. This removed the + harness-only Stage 6 `RamInc` normalization workaround. +- Dead `#[cfg(any())]` private-core replay blocks were deleted from + `tests/bolt_commitment.rs`. +- The remaining live private-core preamble replay path was deleted: + `run_core_preamble`, `core_challenge_to_fr`, and + `assert_core_stage1_tau_matches_bolt` no longer exist. Stage 1 parity now + relies on public verifier acceptance plus direct proof-coefficient parity. +- Checked-in generated `jolt-prover` changes are regenerated from Bolt emitter + changes; `jolt-prover`/`jolt-verifier` remain generated artifacts. +- The focused `bolt_stage3_batched_real_muldiv_self_parity` oracle now hard-gates + Stage 5/6/7 core acceptance, generated verifier acceptance, full core + acceptance, and Dory joint-opening proof byte equality. +- Added a dedicated `Bolt equivalence` CI workflow with explicit macOS/LLVM + nextest jobs for generated role full-field parity and real-data + parity/tamper gates. +- Moved the ignored SHA2-chain perf oracle tests into dedicated + `tests/bolt_perf.rs` and pointed the perf-oracle workflow at that nextest + target. +- `scripts/setup-bolt-dev.sh` now installs `cargo-nextest` along with the + local LLVM/MLIR environment, matching the branch's documented gates. +- Deleted local generated-verifier replay debt: `Stage6LocalValueStore`, + `stage6_value_store`, `stage6_instance_point`, and + `stage6_opening_as_stage7_input`. +- Deleted stale `tests/hash_debug.rs`, a one-off Blake2b op-112 divergence + scanner with no assertions and no role in the equivalence or CI gates. +- Deleted the unused legacy `StageTrace`/`ProtocolTrace` API from `lib.rs`; + the crate now exposes the canonical `artifacts.rs` model instead of two + parallel comparison vocabularies. + +## Initial Helper Classification + +This classification is the Slice 1 migration ledger for +`tests/bolt_commitment.rs`. It is intentionally conservative: anything that +constructs stage-specific protocol meaning is semantic debt until it is moved +into Bolt, generated crates, or `jolt-witness`. + +Adapter/oracle helpers allowed to remain, but should move out of the monolithic +test file: + +- fixture runners: `core_muldiv_commitment_fixture`, + `core_sha2_chain_commitment_fixture`, `core_guest_commitment_fixture` +- Bolt protocol builders: `bolt_commitment_programs_with_params`, + `bolt_stage{1,2,3,4,5,6,7,8}_programs_with_params` +- generated-plan adapters: `leak_*`, `role_name`, `synthetic_stage1_*`, + `leak_stage*_program`, `leak_generated_*_program` +- proof/artifact representation adapters: `to_generated_*`, `to_jolt_*`, + `to_kernel_*`, `generated_stage*_execution_artifacts`, + `kernel_stage*_opening_inputs`, `generated_stage*_opening_inputs` +- commitment/transcript adapters: generated commitment phase runners, + `append_bolt_preamble`, `append_bolt_commitment_trace`, + `core_commitment_log`, `core_commitments_transcript_log` +- thin field/serialization conversions: `core_challenge_to_fr`, + `core_append_serializable_bytes`, `commit_with_layout`, + `into_padded_oracle` + +Checker helpers allowed to remain, but should move to focused check modules: + +- transcript/checkpoint checks: `transcript_states`, + `assert_state_history_match`, `assert_state_history_prefix_match` +- artifact equality checks: `assert_stage*_artifacts_match`, + `assert_commitments_match`, `assert_dory_proofs_match` +- core/Bolt acceptance gates that use public verifier APIs: + `assert_core_verifies_proof`, `assert_core_accepts_bolt_stage*`, + `assert_core_accepts_bolt_evaluation_proof`, + `assert_core_accepts_full_bolt_proof` +- early-stage parity checks that do not reconstruct hidden later-stage + semantics: `assert_core_stage*_sumcheck_proof_matches_bolt`, + `assert_stage1_uniskip_extended_evals_match_core` + +Tamper/fuzz helpers are allowed, but should move to `tamper.rs`: + +- `assert_bolt_stage1_tamper_rejected` +- stage-specific proof mutation helpers now live in `tamper.rs` +- malformed proof helpers such as `unrelated_dory_proof` + +Perf helpers are allowed, but should move to `perf.rs`: + +- `maybe_setup_perf_trace` +- dedicated ignored perf gates in `tests/bolt_perf.rs` +- core/Bolt timing, RSS, proof-size, and tracing metric collection + +Semantic debt that must leave `jolt-equivalence`: + +- private-core or accumulator-derived stage reconstruction: + `ProofOpeningClaims`, `core_stage{4,5,6,7}_artifacts`, + `core_stage8_transcript_states`, + `core_stage{4,5,6,7}_round_polynomials`, + `core_stage{4,5,6,7}_opening_inputs`, + `core_stage{4,5,6,7}_evals`, + `core_stage*_virtual_*`, `core_stage*_committed_*` +- core transcript state replay that depends on private verifier internals: + deleted from the live harness; keep it out. + +The expected trend is that adapter/checker/tamper/perf helpers move into small +modules, while semantic-debt helpers disappear because Bolt/generated artifacts +or `jolt-witness` expose the required public data directly. + +## Target Architecture + +Use a small canonical model inside `jolt-equivalence`: + +```rust +struct EquivalenceRun { + commitments: CommitmentTrace, + transcript: TranscriptTrace, + stages: Vec, + opening_claims: OpeningClaims, + verifier_result: VerifierResult, + perf: PerfMetrics, +} +``` + +Core and Bolt should each have narrow adapters: + +```text +core_oracle.rs + run_core(...) + public artifacts -> EquivalenceRun + +bolt_oracle.rs + run_generated_bolt(...) + generated artifacts -> EquivalenceRun + +checks.rs + compare_commitments + compare_transcripts + compare_opening_claims + compare_stage_outputs + compare_perf + +tamper.rs + mutate proof artifacts + assert generated verifier rejects +``` + +The heavy semantic logic must live in: + +```text +crates/bolt IR, typed plans, lowering, codegen +crates/jolt-witness prover-side witness/data materialization primitives +crates/jolt-kernels prover/runtime relation execution +crates/jolt-prover generated prover artifact production +crates/jolt-verifier generated verifier artifact checking +``` + +For later-stage prover inputs, Bolt should use or adapt `jolt-witness` rather +than rebuilding witness and claim materialization inside `jolt-equivalence`. +If Stage 6/7 needs reusable primitives for RA chunks, hamming-weight data, +opening-input materialization, claim inputs, or committed oracle layouts, add +those primitives to `jolt-witness` and have generated prover code consume them. +The equivalence crate may inspect the resulting public artifacts, but it must +not be the place where those prover-side semantics are constructed. + +`jolt-witness` is the canonical home for reusable prover-side construction +that is not inherently codegen-specific. That includes witness columns, +committed-oracle layouts, RA chunk/index materialization, hamming-weight inputs, +and claim/opening input data needed by later stages. The generated prover may +wrap or specialize those primitives, but `jolt-equivalence` must only compare +the public artifacts emitted by core and Bolt. + +## Focused Goal-Mode Slices + +### Slice 1: Define The Boundary + +Objective: + +```text +Introduce a canonical equivalence artifact model and classify existing +bolt_commitment.rs helpers as adapter, checker, tamper, perf, or semantic debt. +``` + +Acceptance gates: + +- No new semantic reconstruction is added. +- Documented list of debt helpers exists in code comments or this file. +- New canonical structs are representation-only. +- Existing tests are not weakened or deleted unless replaced by equivalent + stricter gates. + +### Slice 2: Move Stage 6 Opening Semantics Into Bolt + +Objective: + +```text +Make generated Bolt Stage 6 expose canonical opening claims and normalized +points/evals directly, matching core public semantics. +``` + +Required work: + +- Represent point order/normalization as typed protocol facts, not loose + stage-local string recovery in the harness. +- Use or extend `jolt-witness` for Stage 6 prover-side witness/data + materialization, including committed RA oracle layouts and claim inputs. +- Generated Stage 6 prover artifacts must carry the exact opening claims + Stage 7 consumes. +- Generated Stage 6 verifier must check those claims through the same public + artifact contract. +- Remove matching Stage 6 reconstruction from `bolt_commitment.rs`. + +Acceptance gates: + +- Stage 6 proof produced by Bolt self-verifies. +- Stage 6 canonical opening claims compare against core oracle. +- `jolt-equivalence` no longer synthesizes Stage 6 output opening points. +- Harness LOC decreases or any increase is limited to generic adapters/checks. + +### Slice 3: Move Stage 7 Hamming-Weight Semantics Into Bolt + +Objective: + +```text +Make generated Bolt Stage 7 consume Stage 6 canonical openings and construct +the hamming-weight claim reduction with core-equivalent semantics. +``` + +Required work: + +- Stage 7 input claim is derived from generated Stage 6 canonical openings. +- Use or extend `jolt-witness` for Stage 7 prover-side RA chunk/index and + hamming-weight input materialization. +- Hamming-weight reduction point construction matches core semantics in Bolt + kernels/codegen. +- Generated Stage 7 prover and verifier agree without harness-side witness MLE + evaluation. +- Stage 7 output opening claims are public generated artifacts. + +Acceptance gates: + +- Current failing Stage 7 relation output mismatch is resolved in Bolt code. +- `bolt_stage3_batched_real_muldiv_self_parity` passes without semantic + reconstruction in `jolt-equivalence`. +- Stage 7 tamper checks reject coefficient, eval, point, and opening-claim + mutations. +- Harness LOC decreases. + +### Slice 4: Thin The Harness + +Objective: + +```text +Refactor bolt_commitment.rs into focused oracle/check/tamper/perf modules and +delete semantic debt. +``` + +Target shape: + +```text +tests/bolt_commitment.rs small integration driver +src/core_oracle.rs core public oracle adapter +src/bolt_oracle.rs generated Bolt adapter +src/checks.rs parity assertions +src/tamper.rs proof mutations +src/perf.rs perf gates +``` + +Acceptance gates: + +- No local value-store replay in tests. +- No witness polynomial MLE evaluation in tests except generic checker helpers + operating on already-public artifacts. +- No private core verifier stage methods. +- `bolt_commitment.rs` is reduced to orchestration and assertions. + +### Slice 5: CI Gates + +Objective: + +```text +Make equivalence checks standard PR gates with small always-on tests and +explicit perf/fuzz lanes. +``` + +Required gates: + +- small real guest parity gate +- generated role crate full-field challenge parity gate +- Bolt proof tamper rejection gate +- SHA2-chain `2^16` core-vs-Bolt perf oracle +- SHA2-chain `2^20` core-vs-Bolt perf oracle +- optional longer fuzz/tamper lane + +Acceptance gates: + +- CI names are explicit and stable. +- Perf thresholds are configured in one place. +- Perf failures report stage-level timing, heavy computation spans, proof + bytes, and peak RSS. +- Ignored/local perf tests can be run manually with one documented command. + +### Slice 6: SHA2-Chain Perf Closure + +Objective: + +```text +Bring Jolt-on-Bolt SHA2-chain proving overhead within 20% of jolt-core while +keeping the equivalence crate a thin oracle/gate and keeping all semantic +changes in Bolt codegen, generated artifacts, jolt-kernels, or jolt-witness. +``` + +Current measured baseline: + +```text +sha2-chain 2^16: + prove_ms: core=1987.685, bolt=2523.469, ratio=1.270x + verify_ms: core=89.220, bolt=118.322, ratio=1.326x + proof_bytes: core=80209, bolt=111198, ratio=1.386x + peak_rss_mb: core=209, bolt=1248, ratio=5.971x + +sha2-chain 2^20: + prove_ms: core ~= 9.9s, bolt ~= 22.6-22.8s, ratio ~= 2.29-2.30x + verify_ms: core ~= 0.11s, bolt ~= 0.13s, ratio ~= 1.18-1.26x + proof_bytes: core=89041, bolt=121398, ratio=1.363x + peak_rss_mb: core ~= 1.84GB, bolt ~= 6.1-6.3GB, ratio ~= 3.3-3.4x +``` + +Perfetto/tracing overhead is not the cause of the 2^20 regression. Traced and +untraced runs landed in the same ratio band. + +Current post-witness-fix 2^20 hotspot shape: + +```text +bolt.stage6: ~10.6s + bytecode_read_raf: ~4.3s + instruction_ra_virtual: ~2.9s + booleanity: ~2.6s +bolt.commitment: ~5.3s +bolt.stage8: ~3.8s + joint_opening_hint: ~1.4s + dory_open: ~1.9s +``` + +Current post-bytecode-sparse 2^20 shape: + +```text +sha2-chain 2^16: + prove_ms: core=2020.866, bolt=2373.067, ratio=1.174x + verify_ms: core=90.403, bolt=118.888, ratio=1.315x + proof_bytes: core=80209, bolt=111198, ratio=1.386x + peak_rss_mb: core=207, bolt=1109, ratio=5.357x + +sha2-chain 2^20: + prove_ms: core=9825.685, bolt=19381.338, ratio=1.973x + verify_ms: core=104.379, bolt=132.872, ratio=1.273x + proof_bytes: core=89041, bolt=121398, ratio=1.363x + peak_rss_mb: core=1839, bolt=6094, ratio=3.314x + +Stage 6 per execution: + bytecode_read_raf: ~1.58s + instruction_ra_virtual: ~2.75-3.32s + booleanity: ~2.31-2.44s +``` + +The final dense bytecode read-RAF witness allocation removal was verified by +`jolt-witness`, focused Stage 6 kernel tests, kernel/witness clippy, and full +`jolt-equivalence`. Its 2^20 perf rerun was intentionally stopped during +laptop handoff, so the latest measured perf numbers above are from the sparse +kernel path before that allocation-only cleanup. Re-run the 2^20 perf gate +before judging any memory/setup movement from the allocation cleanup. + +#### Handoff Plan Of Attack + +Retained optimization: + +- Bytecode read-RAF now uses sparse bytecode RA index chunks plus explicit + chunk lengths. This is a core-equivalent direction and belongs in + `jolt-witness`/`jolt-kernels`, not `jolt-equivalence`. +- Dense bytecode RA read-RAF materialization is removed from normal + `stage6_witness_polynomials` output; callers that still provide dense chunks + continue through the dense fallback. + +Rejected experiment: + +- Parallelizing indexed Booleanity cycle-state construction and dense binds + made the 2^20 run slower (`prove_ms` about `25.5s`, ratio `2.13x`) and was + reverted. Do not reapply that shape without a more targeted profile. + +Next targets: + +1. Port `instruction_ra_virtual` from generic dense product terms toward the + core `RaPolynomial`/split-eq sum-of-products algorithm. This is now the + largest Stage 6 bucket, roughly `2.7-3.3s` per Stage 6 execution. +2. Improve indexed Booleanity with an algorithmic change rather than broad + parallel binding. Current bucket is roughly `2.3-2.4s` per Stage 6 + execution. +3. Re-run the post-allocation-cleanup 2^20 perf gate and record setup/prove/RSS + movement. The interrupted command was stopped deliberately before commit. +4. After Stage 6 is no longer dominant, attack `bolt.commitment` (`~5.3s`) and + Stage 8/Dory opening (`~3.8s`) with generated spans intact. +5. Tighten the perf thresholds from disabled diagnostic ratios to the actual + target gates once 2^20 prove is within `1.20x`. + +Primary target: + +```text +sha2-chain 2^16 prove_ms ratio <= 1.20x +sha2-chain 2^20 prove_ms ratio <= 1.20x +``` + +Secondary targets: + +```text +sha2-chain 2^16 verify_ms ratio <= 1.35x +sha2-chain 2^20 verify_ms ratio <= 1.35x +sha2-chain 2^16 proof_bytes ratio <= 1.40x +sha2-chain 2^20 proof_bytes ratio <= 1.40x +sha2-chain 2^16 peak_rss_mb <= 1.25GB +sha2-chain 2^20 peak_rss_mb <= 6.30GB, and should continue decreasing unless +a documented protocol change explains the tradeoff. +``` + +Required work: + +- Port the remaining Stage 6 RA-heavy prover paths toward core-equivalent + sparse/specialized algorithms instead of dense generic `DenseStage6State` + products. The first targets are bytecode read-RAF, instruction RA virtual, + and Booleanity. +- Keep semantic parity in `jolt-kernels`, `jolt-witness`, Bolt IR/codegen, or + checked-in generated artifacts. Do not add perf-specific reconstruction or + shortcuts to `jolt-equivalence`. +- Keep instrumentation code-generated when it concerns generated + `jolt-prover`/`jolt-verifier` code. Direct runtime/kernel spans belong in + the owning shared crate. +- Preserve the existing `bolt.prove`, `bolt.commitment`, `bolt.stage*`, + `bolt.evaluate.*`, and verifier perf span contract so regressions remain + attributable in CI. +- Treat `setup_ms`, commitment, and Stage 8/Dory opening work as follow-on + targets after Stage 6 is no longer the dominant gap. + +Acceptance gates: + +- Both ignored SHA2-chain perf oracle tests pass with `prove_ms <= 1.20x`. +- The 2^20 perf report identifies no single uninstrumented Bolt prover bucket + larger than `500ms`. +- `jolt-equivalence` contains no new stage-semantic reconstruction for the perf + fix. +- Focused Stage 6 kernel tests pass. +- The full `jolt-equivalence` suite passes. +- Generated artifacts are regenerated from Bolt when generated code changes. + +#### Active Goal Contract + +Goal: + +```text +Close the SHA2-chain Jolt-on-Bolt prover regression to <= 20% overhead versus +jolt-core at both 2^16 and 2^20, without moving Jolt semantics into the +equivalence harness. +``` + +Why this matters: + +```text +The equivalence crate is supposed to be an oracle/gate. If Bolt is slower or +semantically different, the fix must land in Bolt-generated code, +jolt-kernels, jolt-witness, or shared runtime code. The harness may measure and +compare; it must not compensate for missing prover semantics. +``` + +Non-negotiable scope: + +- Do not hand-edit generated `jolt-prover` or `jolt-verifier` behavior. Change + Bolt/codegen/templates/shared crates and regenerate. +- Do not add perf-specific witness reconstruction, opening reconstruction, or + stage-specific semantic shortcuts to `jolt-equivalence`. +- Do not weaken correctness, tamper, proof-size, verifier, or perf gates to + make the goal pass. +- Keep generated prover/verifier spans code-generated when the work being + measured is generated code. +- Keep runtime/kernel spans in the crate that owns the runtime/kernel work. +- Treat Perfetto overhead as negligible unless a repeat measurement proves + otherwise; the current traced and untraced runs agree on the 2^20 gap. + +Current blocking regression: + +```text +2^16 prove: core 2.02s, Bolt 2.37s, 1.174x +2^20 prove: core about 9.8s, Bolt about 19.4s, 1.97x +``` + +The current evidence points at Stage 6 first, then commitment and Stage 8: + +```text +bolt.stage6: still dominant, with instruction_ra_virtual and booleanity largest +bolt.commitment: about 5.3s +bolt.stage8: about 3.8s +``` + +Stage 6 subtargets, in priority order: + +```text +instruction_ra_virtual about 2.7-3.3s per Stage 6 execution +booleanity about 2.3-2.4s per Stage 6 execution +bytecode_read_raf about 1.6s per Stage 6 execution after sparse-index port +``` + +Implementation direction: + +- Prefer core-equivalent sparse/indexed paths over dense generic bind loops for + RA-heavy Stage 6 work. +- Use `jolt-witness` for reusable prover-side witness/index/chunk material + that is not inherently Bolt-codegen-specific. +- Use `jolt-kernels` for core-equivalent relation execution and specialized + prover algorithms. +- Use Bolt artifact generation for generated prover/verifier APIs and spans. +- Keep `jolt-equivalence` changes limited to metric collection, reporting, + thresholds, and thin public-artifact comparison. + +Completion evidence required: + +- Run the 2^16 and 2^20 SHA2-chain perf gates and report: + `setup_ms`, `prove_ms`, `verify_ms`, `proof_bytes`, peak RSS, and top spans. +- Re-run any surprising perf result at least once before treating it as real. +- Show no uninstrumented Bolt prover bucket larger than `500ms` at 2^20. +- Run focused Stage 6 kernel tests. +- Run the full `jolt-equivalence` suite. +- Run `cargo fmt --check` and `git diff --check`. +- If generated artifacts changed, show the generator command used to regenerate + them. + +## Strict Per-Slice Gates + +Every goal-mode slice must satisfy: + +```text +cargo fmt --check +git diff --check +cargo check -p jolt-core --no-default-features --features minimal --offline +cargo check -p jolt-core --no-default-features --features minimal,challenge-254-bit --offline +``` + +Use the local Bolt MLIR/LLVM environment for equivalence tests: + +```sh +env MLIR_SYS_220_PREFIX=/opt/homebrew/opt/llvm \ + PATH=/opt/homebrew/opt/llvm/bin:/Users/mgeorghiades/.cargo/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin \ + SDKROOT=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk \ + BINDGEN_EXTRA_CLANG_ARGS=-isysroot/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk \ + cargo nextest run -p jolt-equivalence --test generated_role_crates \ + --cargo-quiet --offline + +env MLIR_SYS_220_PREFIX=/opt/homebrew/opt/llvm \ + PATH=/opt/homebrew/opt/llvm/bin:/Users/mgeorghiades/.cargo/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin \ + SDKROOT=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk \ + BINDGEN_EXTRA_CLANG_ARGS=-isysroot/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk \ + cargo nextest run -p jolt-equivalence --test bolt_commitment \ + --cargo-quiet --offline +``` + +Before a slice is considered complete, also run the broadest feasible +equivalence gate: + +```sh +env MLIR_SYS_220_PREFIX=/opt/homebrew/opt/llvm \ + PATH=/opt/homebrew/opt/llvm/bin:/Users/mgeorghiades/.cargo/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin \ + SDKROOT=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk \ + BINDGEN_EXTRA_CLANG_ARGS=-isysroot/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk \ + cargo nextest run -p jolt-equivalence --cargo-quiet --offline +``` + +Perf oracle gates are required before landing perf-sensitive slices: + +```sh +env MLIR_SYS_220_PREFIX=/opt/homebrew/opt/llvm \ + PATH=/opt/homebrew/opt/llvm/bin:/Users/mgeorghiades/.cargo/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin \ + SDKROOT=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk \ + BINDGEN_EXTRA_CLANG_ARGS=-isysroot/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk \ + cargo nextest run -p jolt-equivalence --test bolt_perf --release \ + --cargo-quiet --offline --run-ignored only --no-capture \ + bolt_sha2_chain_2_16_core_vs_bolt_perf_oracle + +env MLIR_SYS_220_PREFIX=/opt/homebrew/opt/llvm \ + PATH=/opt/homebrew/opt/llvm/bin:/Users/mgeorghiades/.cargo/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin \ + SDKROOT=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk \ + BINDGEN_EXTRA_CLANG_ARGS=-isysroot/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk \ + cargo nextest run -p jolt-equivalence --test bolt_perf --release \ + --cargo-quiet --offline --run-ignored only --no-capture \ + bolt_sha2_chain_2_20_core_vs_bolt_perf_oracle +``` + +## Regression Rules + +A change fails review if it: + +- increases `jolt-equivalence` semantic reconstruction +- hides a Bolt/core mismatch behind harness normalization +- adds prover witness or claim materialization to `jolt-equivalence` instead of + `jolt-witness`/generated prover code +- weakens tamper rejection coverage +- removes a parity gate without replacing it with a stricter one +- adds new private-core dependencies +- makes generated verifier depend on prover-only crates or core internals +- makes perf gates less observable + +## Definition Of Done + +This goal is complete when: + +- Jolt-on-Bolt passes real-data completeness parity against core. +- Generated Bolt verifier rejects representative mutated proofs. +- Stage 6/7 semantics live in Bolt/codegen/kernels, not in the harness. +- `jolt-equivalence` is mostly adapters, checks, tamper/fuzz, and perf gates. +- Small correctness gates are practical for PR CI. +- Larger SHA2-chain perf gates are documented, stable, and actionable. +- The harness is small enough that future compiler work uses it as a gate + instead of treating it as a place to repair semantics. diff --git a/crates/jolt-equivalence/README.md b/crates/jolt-equivalence/README.md new file mode 100644 index 0000000000..de23e83b78 --- /dev/null +++ b/crates/jolt-equivalence/README.md @@ -0,0 +1,50 @@ +# jolt-equivalence + +`jolt-equivalence` is the real-data oracle for the Bolt implementation of +Jolt. Synthetic fixtures belong in unit tests, but a Bolt protocol stage is not +accepted until this crate proves the generated/Bolt artifacts agree with +`jolt-core` on real trace data. + +## Stage Gate Shape + +Each stage test should execute the complete implemented prefix and then check: + +1. **Bolt self-acceptance**: Bolt prover artifacts are accepted by the Bolt + verifier on the same trace. +2. **Bolt transcript parity**: Bolt prover and verifier transcript states match + step-for-step through the stage boundary. +3. **Core acceptance**: Bolt-produced artifacts are spliced into the matching + `jolt-core` proof fields, and `jolt-core` accepts through that stage. +4. **Core transcript/artifact parity**: Bolt transcript states and observable + proof components match `jolt-core` through the stage boundary. +5. **Tamper rejection**: the generated/Bolt verifier rejects representative + mutations for every new soundness obligation introduced by the stage. + +Stage tests should be named by stage, use real traced data, and avoid depending +on generated verifier internals that are not part of the canonical +`jolt-verifier` artifact contract. + +Equivalence tests should import the checked-in generated role crates under +`crates/jolt-prover` and `crates/jolt-verifier`, not temp compiler outputs. +Those crates are regenerated by Bolt's Rust artifact rail and expose the +implemented prefix through their generated stage registries plus top-level +prover/verifier APIs. + +## Current Prefix + +The active Bolt prefix covers the full standard non-zk path: commitment, +Stages 1-7, and Stage 8 evaluation/opening proof construction. The focused +real-trace oracle runs generated prover and verifier artifacts against +`jolt-core`, checks staged and monolithic verifier agreement, compares public +proof artifacts and transcript checkpoints, and requires representative +tampering to be rejected. + +The always-on equivalence gates are: + +```bash +cargo nextest run -p jolt-equivalence --test generated_role_crates --cargo-quiet +cargo nextest run -p jolt-equivalence --test bolt_commitment --cargo-quiet +``` + +The larger SHA2-chain perf oracles live in `tests/bolt_perf.rs` and are run by +the dedicated Bolt perf workflow. diff --git a/crates/jolt-equivalence/src/adapters.rs b/crates/jolt-equivalence/src/adapters.rs new file mode 100644 index 0000000000..8d53c6d00f --- /dev/null +++ b/crates/jolt-equivalence/src/adapters.rs @@ -0,0 +1,59 @@ +//! Thin representation adapters between kernel and generated stage types. + +use jolt_field::Fr; +use jolt_kernels::stage4::Stage4ExecutionArtifacts; +use jolt_verifier::{JoltStageExecutionArtifacts, JoltStageProof}; + +use crate::artifacts::{NamedScalar, StageArtifacts, SumcheckArtifacts}; + +macro_rules! canonical_stage_artifacts { + ($stage:literal, $artifacts:expr) => {{ + StageArtifacts { + stage: $stage.to_owned(), + sumchecks: $artifacts + .sumchecks + .iter() + .map(|output| SumcheckArtifacts { + driver: output.driver.to_owned(), + point: output.point.clone(), + round_polynomials: output + .proof + .round_polynomials + .iter() + .map(|poly| poly.clone().into_coefficients()) + .collect(), + evals: output + .evals + .iter() + .map(|eval| NamedScalar { + name: eval.name.to_owned(), + value: eval.value, + }) + .collect(), + }) + .collect(), + opening_batches: Vec::new(), + } + }}; +} + +macro_rules! define_canonical_stage_adapters { + ($($function:ident, $stage:literal, $input:ty;)*) => { + $( + pub(crate) fn $function(artifacts: &$input) -> StageArtifacts { + canonical_stage_artifacts!($stage, artifacts) + } + )* + }; +} + +define_canonical_stage_adapters! { + canonical_stage4_artifacts, "Stage 4", Stage4ExecutionArtifacts; + canonical_generated_stage4_execution_artifacts, "Stage 4", JoltStageExecutionArtifacts; + canonical_generated_stage5_proof, "Stage 5", JoltStageProof; + canonical_generated_stage5_execution_artifacts, "Stage 5", JoltStageExecutionArtifacts; + canonical_generated_stage6_proof, "Stage 6", JoltStageProof; + canonical_generated_stage6_execution_artifacts, "Stage 6", JoltStageExecutionArtifacts; + canonical_generated_stage7_proof, "Stage 7", JoltStageProof; + canonical_generated_stage7_execution_artifacts, "Stage 7", JoltStageExecutionArtifacts; +} diff --git a/crates/jolt-equivalence/src/artifacts.rs b/crates/jolt-equivalence/src/artifacts.rs new file mode 100644 index 0000000000..4c0da86fbd --- /dev/null +++ b/crates/jolt-equivalence/src/artifacts.rs @@ -0,0 +1,144 @@ +//! Canonical comparison artifacts for Jolt-on-Bolt equivalence gates. +//! +//! These types are intentionally representation-only. They give core and +//! generated Bolt adapters a common shape for public artifacts, but they do not +//! encode Jolt stage semantics, point normalization rules, witness +//! materialization, or claim-reduction formulas. + +use crate::TranscriptEvent; +use jolt_profiling::PerfMetrics; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum ArtifactSource { + Core, + Bolt, +} + +#[derive(Clone, Debug, PartialEq)] +pub struct EquivalenceRun { + pub source: ArtifactSource, + pub commitments: CommitmentTrace, + pub transcript: TranscriptTrace, + pub stages: Vec>, + pub opening_claims: OpeningClaims, + pub verifier_result: VerifierResult, + pub perf: Option, +} + +impl EquivalenceRun { + pub fn new(source: ArtifactSource) -> Self { + Self { + source, + commitments: CommitmentTrace::default(), + transcript: TranscriptTrace::default(), + stages: Vec::new(), + opening_claims: OpeningClaims::default(), + verifier_result: VerifierResult::not_run(), + perf: None, + } + } +} + +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub struct CommitmentTrace { + pub commitments: Vec, +} + +/// One public commitment slot. +/// +/// `bytes = None` represents an intentionally skipped optional commitment. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct CommitmentArtifact { + pub label: String, + pub artifact: String, + pub bytes: Option>, +} + +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub struct TranscriptTrace { + pub events: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct StageArtifacts { + pub stage: String, + pub sumchecks: Vec>, + pub opening_batches: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct SumcheckArtifacts { + pub driver: String, + pub point: Vec, + pub round_polynomials: Vec>, + pub evals: Vec>, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct NamedScalar { + pub name: String, + pub value: F, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct OpeningClaims { + pub claims: Vec>, +} + +impl Default for OpeningClaims { + fn default() -> Self { + Self { claims: Vec::new() } + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct OpeningClaim { + pub symbol: String, + pub oracle: String, + pub domain: String, + pub kind: OpeningClaimKind, + pub point: Vec, + pub eval: F, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum OpeningClaimKind { + Committed, + Virtual, + Advice, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct OpeningBatchArtifacts { + pub symbol: String, + pub ordered_claims: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct VerifierResult { + pub accepted: bool, + pub error: Option, +} + +impl VerifierResult { + pub fn accepted() -> Self { + Self { + accepted: true, + error: None, + } + } + + pub fn rejected(error: impl Into) -> Self { + Self { + accepted: false, + error: Some(error.into()), + } + } + + pub fn not_run() -> Self { + Self { + accepted: false, + error: Some("verifier not run".to_owned()), + } + } +} diff --git a/crates/jolt-equivalence/src/bolt_oracle.rs b/crates/jolt-equivalence/src/bolt_oracle.rs new file mode 100644 index 0000000000..3bca6cffef --- /dev/null +++ b/crates/jolt-equivalence/src/bolt_oracle.rs @@ -0,0 +1,841 @@ +//! Bolt-side oracle driver for full real-trace equivalence gates. +//! +//! This module orchestrates the generated/kernel Bolt prover and verifier path +//! and compares its public artifacts against the core oracle. Stage semantics +//! should continue to move into Bolt, kernels, generated crates, or +//! `jolt-witness`, not into this module. + +#![expect( + clippy::expect_used, + reason = "equivalence oracle should fail fast on invalid generated artifacts" +)] + +use std::time::Instant; + +use jolt_dory::{DoryProof, DoryScheme}; +use jolt_openings::CommitmentScheme as _; +use jolt_profiling::{check_core_vs_bolt_gate, time_it, PeakRssSampler}; + +use crate::adapters::{ + canonical_generated_stage4_execution_artifacts, canonical_generated_stage5_execution_artifacts, + canonical_generated_stage5_proof, canonical_generated_stage6_execution_artifacts, + canonical_generated_stage6_proof, canonical_generated_stage7_execution_artifacts, + canonical_generated_stage7_proof, canonical_stage4_artifacts, +}; +use crate::artifacts::{ArtifactSource, EquivalenceRun, TranscriptTrace, VerifierResult}; +use crate::bolt_programs::{ + bolt_commitment_programs_with_params, bolt_stage1_programs_with_params, + bolt_stage2_programs_with_params, bolt_stage3_programs_with_params, + bolt_stage4_programs_with_params, bolt_stage5_programs_with_params, + bolt_stage6_programs_with_params, bolt_stage7_programs_with_params, + bolt_stage8_programs_with_params, +}; +use crate::checkpoint::{assert_state_history_match, assert_state_history_prefix_match}; +use crate::checks::{ + assert_canonical_stage_artifacts_match, assert_dory_proofs_match, + assert_equivalence_run_artifacts_match, assert_stage5_artifacts_match, + assert_stage6_artifacts_match, assert_stage7_artifacts_match, +}; +use crate::commitment_oracle::{ + generated_commitment_trace, generated_verifier_commitment_trace, + run_generated_bolt_commitment_pair_with_cycles, transcript_with_bolt_commitment_trace, + transcript_with_bolt_preamble, GeneratedCommitmentInputStorage, +}; +use crate::core_oracle::{ + assert_core_accepts_bolt_evaluation_proof, assert_core_accepts_bolt_stage3, + assert_core_accepts_bolt_stage4, assert_core_accepts_bolt_stage5, + assert_core_accepts_bolt_stage6, assert_core_accepts_bolt_stage7, + assert_core_accepts_full_bolt_proof, CoreMuldivCommitmentFixture, +}; +use crate::perf::{ + generated_bolt_perf_metrics, print_core_vs_bolt_perf_summary, CORE_VS_BOLT_PERF_THRESHOLDS, +}; +use crate::plan_adapters::{ + leak_generated_commitment_prover_program, leak_generated_commitment_verifier_program, + leak_generated_stage1_verifier_program, leak_generated_stage2_verifier_program, + leak_generated_stage3_verifier_program, leak_generated_stage4_verifier_program, + leak_generated_stage5_verifier_program, leak_generated_stage6_verifier_program, + leak_generated_stage7_verifier_program, leak_generated_stage8_prover_program, + leak_generated_stage8_verifier_program, leak_stage1_program, leak_stage2_program, + leak_stage3_program, leak_stage4_program, leak_stage5_program, leak_stage6_program, + leak_stage7_program, +}; +use crate::tamper::{ + assert_bolt_stage3_4_5_tamper_rejected, assert_bolt_stage6_tamper_rejected, + assert_bolt_stage7_tamper_rejected, assert_monolithic_jolt_tamper_rejected, + MonolithicJoltTamperInput, Stage345TamperInput, Stage6TamperInput, Stage7TamperInput, +}; + +pub fn assert_bolt_full_real_trace_self_parity( + fixture: CoreMuldivCommitmentFixture, + enforce_perf_gate: bool, +) { + let bolt_setup_start = Instant::now(); + let _bolt_setup_span = tracing::info_span!("bolt.setup").entered(); + let (commitment_prover_program, commitment_verifier_program) = + bolt_commitment_programs_with_params(&fixture.params); + let (stage1_prover_program, stage1_verifier_program) = + bolt_stage1_programs_with_params(&fixture.params); + let (stage2_prover_program, stage2_verifier_program) = + bolt_stage2_programs_with_params(&fixture.params); + let (stage3_prover_program, stage3_verifier_program) = + bolt_stage3_programs_with_params(&fixture.params); + let (stage4_prover_program, stage4_verifier_program) = + bolt_stage4_programs_with_params(&fixture.params); + let (stage5_prover_program, stage5_verifier_program) = + bolt_stage5_programs_with_params(&fixture.params); + let (stage6_prover_program, stage6_verifier_program) = + bolt_stage6_programs_with_params(&fixture.params); + let (stage7_prover_program, stage7_verifier_program) = + bolt_stage7_programs_with_params(&fixture.params); + let (stage8_prover_program, stage8_verifier_program) = + bolt_stage8_programs_with_params(&fixture.params); + let generated_commitment_prover_plan = + leak_generated_commitment_prover_program(&commitment_prover_program); + let generated_commitment_verifier_plan = + leak_generated_commitment_verifier_program(&commitment_verifier_program); + + let (commitment_prover_trace, commitment_verifier_trace) = + run_generated_bolt_commitment_pair_with_cycles( + generated_commitment_prover_plan, + generated_commitment_verifier_plan, + &fixture.pcs_setup, + &fixture.cycle_inputs, + ); + + let stage1_prover_plan = leak_stage1_program(&stage1_prover_program); + let stage2_prover_plan = leak_stage2_program(&stage2_prover_program); + let stage3_prover_plan = leak_stage3_program(&stage3_prover_program); + let stage4_prover_plan = leak_stage4_program(&stage4_prover_program); + let stage5_prover_plan = leak_stage5_program(&stage5_prover_program); + let stage6_prover_plan = leak_stage6_program(&stage6_prover_program); + let stage7_prover_plan = leak_stage7_program(&stage7_prover_program); + let stage8_prover_plan = leak_generated_stage8_prover_program(&stage8_prover_program); + let generated_stage1_verifier_plan = + leak_generated_stage1_verifier_program(&stage1_verifier_program); + let generated_stage2_verifier_plan = + leak_generated_stage2_verifier_program(&stage2_verifier_program); + let generated_stage3_verifier_plan = + leak_generated_stage3_verifier_program(&stage3_verifier_program); + let generated_stage4_verifier_plan = + leak_generated_stage4_verifier_program(&stage4_verifier_program); + let generated_stage5_verifier_plan = + leak_generated_stage5_verifier_program(&stage5_verifier_program); + let generated_stage6_verifier_plan = + leak_generated_stage6_verifier_program(&stage6_verifier_program); + let generated_stage7_verifier_plan = + leak_generated_stage7_verifier_program(&stage7_verifier_program); + let generated_stage8_verifier_plan = + leak_generated_stage8_verifier_program(&stage8_verifier_program); + let generated_programs = jolt_verifier::JoltVerifierPrograms { + commitment: generated_commitment_verifier_plan, + stage1_outer: generated_stage1_verifier_plan, + stage2: generated_stage2_verifier_plan, + stage3: generated_stage3_verifier_plan, + stage4: generated_stage4_verifier_plan, + stage5: generated_stage5_verifier_plan, + stage6: generated_stage6_verifier_plan, + stage7: generated_stage7_verifier_plan, + stage8: generated_stage8_verifier_plan, + }; + let r1cs_key = fixture.r1cs_key(); + let data = fixture.stage1_outer_rv64_data(&r1cs_key); + let bolt_setup_ms = bolt_setup_start.elapsed().as_secs_f64() * 1_000.0; + drop(_bolt_setup_span); + + let mut prover_transcript = + transcript_with_bolt_commitment_trace(&fixture, &commitment_prover_trace); + let stage1_artifacts = jolt_prover::prove_stage1_outer_with_witness_inputs( + stage1_prover_plan, + r1cs_key.num_cycle_vars(), + &data, + &mut prover_transcript, + ) + .expect("Bolt Stage 1 prover succeeds"); + + let stage2_openings = + jolt_prover::stage2_opening_inputs_from_artifacts(stage2_prover_plan, &stage1_artifacts) + .expect("generated prover derives Stage 2 opening inputs from artifacts"); + let ram_data = fixture.stage2_ram_data(); + let stage2_artifacts = jolt_prover::prove_stage2_with_witness_inputs( + stage2_prover_plan, + &stage2_openings, + &fixture.product_virtual_cycles, + &fixture.instruction_lookup_cycles, + &ram_data, + &mut prover_transcript, + ) + .expect("Bolt Stage 2 prover succeeds"); + + let stage3_openings = jolt_prover::stage3_opening_inputs_from_artifacts( + stage3_prover_plan, + &stage1_artifacts, + &stage2_artifacts, + ) + .expect("generated prover derives Stage 3 opening inputs from artifacts"); + let stage3_artifacts = jolt_prover::prove_stage3_with_witness_inputs( + stage3_prover_plan, + &stage3_openings, + &fixture.stage3_cycles, + &mut prover_transcript, + ) + .expect("Bolt Stage 3 prover succeeds"); + + let stage4_openings = jolt_prover::stage4_opening_inputs_from_artifacts( + stage4_prover_plan, + &fixture.initial_ram_state, + &stage2_artifacts, + &stage3_artifacts, + ) + .expect("generated prover derives Stage 4 opening inputs from artifacts"); + let stage4_artifacts = jolt_prover::prove_stage4_with_trace_witness_inputs( + stage4_prover_plan, + &stage4_openings, + 1 << fixture.params.register_log_k, + fixture.proof.trace_length, + fixture.proof.ram_K, + &fixture.stage4_register_accesses, + &fixture.ram_accesses, + &mut prover_transcript, + ) + .expect("Bolt Stage 4 prover succeeds"); + + let mut verifier_transcript = + transcript_with_bolt_commitment_trace(&fixture, &commitment_verifier_trace); + let stage1_proof = stage1_artifacts.clone().into(); + let verified_stage1 = jolt_prover::replay_stage1_outer_proof_with_program( + stage1_prover_plan, + &stage1_proof, + &mut verifier_transcript, + ) + .expect("Bolt Stage 1 verifier accepts"); + let stage2_verifier_openings = + jolt_prover::stage2_opening_inputs_from_artifacts(stage2_prover_plan, &verified_stage1) + .expect("generated prover derives Stage 2 verifier opening inputs from artifacts"); + let stage2_proof = stage2_artifacts.clone().into(); + let verified_stage2 = jolt_prover::replay_stage2_proof_with_program( + stage2_prover_plan, + &stage2_proof, + &stage2_verifier_openings, + Some(&ram_data), + &mut verifier_transcript, + ) + .expect("Bolt Stage 2 verifier accepts"); + let generated_stage3_prefix_transcript = verifier_transcript.clone(); + let stage3_verifier_openings = jolt_prover::stage3_opening_inputs_from_artifacts( + stage3_prover_plan, + &verified_stage1, + &verified_stage2, + ) + .expect("generated prover derives Stage 3 verifier opening inputs from artifacts"); + let stage3_proof = stage3_artifacts.clone().into(); + let verified_stage3 = jolt_prover::replay_stage3_proof_with_program( + stage3_prover_plan, + &stage3_proof, + &stage3_verifier_openings, + &mut verifier_transcript, + ) + .expect("Bolt Stage 3 verifier accepts"); + let stage4_verifier_openings = jolt_prover::stage4_opening_inputs_from_artifacts( + stage4_prover_plan, + &fixture.initial_ram_state, + &verified_stage2, + &verified_stage3, + ) + .expect("generated prover derives Stage 4 verifier opening inputs from artifacts"); + let stage4_proof = stage4_artifacts.clone().into(); + let verified_stage4 = jolt_prover::replay_stage4_proof_with_program( + stage4_prover_plan, + &stage4_proof, + &stage4_verifier_openings, + &mut verifier_transcript, + ) + .expect("Bolt Stage 4 verifier accepts"); + + assert_eq!( + stage3_artifacts.sumchecks.len(), + verified_stage3.sumchecks.len() + ); + assert_eq!( + stage4_artifacts.sumchecks.len(), + verified_stage4.sumchecks.len() + ); + assert_state_history_match(prover_transcript.log(), verifier_transcript.log()); + assert_core_accepts_bolt_stage3( + &fixture, + &stage1_artifacts, + &stage2_artifacts, + &stage3_artifacts, + ); + assert_core_accepts_bolt_stage4( + &fixture, + &stage1_artifacts, + &stage2_artifacts, + &stage3_artifacts, + &stage4_artifacts, + ); + + let mut generated_verifier_transcript = generated_stage3_prefix_transcript; + let generated_stage3_openings = + jolt_prover::verifier_opening_inputs_from_kernel(&stage3_verifier_openings); + let generated_stage3_proof = jolt_prover::stage3_proof(&stage3_artifacts); + let generated_stage3_start_transcript = generated_verifier_transcript.clone(); + let generated_verified_stage3 = jolt_verifier::verify_stage3_with_program( + generated_stage3_verifier_plan, + &generated_stage3_proof, + &generated_stage3_openings, + &mut generated_verifier_transcript, + ) + .expect("generated Stage 3 verifier accepts real muldiv proof"); + assert_eq!( + stage3_artifacts.sumchecks.len(), + generated_verified_stage3.sumchecks.len() + ); + let generated_stage4_openings = + jolt_prover::verifier_opening_inputs_from_kernel(&stage4_verifier_openings); + let generated_stage4_proof = jolt_prover::stage4_proof(&stage4_artifacts); + let generated_stage4_start_transcript = generated_verifier_transcript.clone(); + let generated_verified_stage4 = jolt_verifier::verify_stage4_with_program( + generated_stage4_verifier_plan, + &generated_stage4_proof, + &generated_stage4_openings, + &mut generated_verifier_transcript, + ) + .expect("generated Stage 4 verifier accepts real muldiv proof"); + assert_eq!( + stage4_artifacts.sumchecks.len(), + generated_verified_stage4.sumchecks.len() + ); + assert_state_history_match( + verifier_transcript.log(), + generated_verifier_transcript.log(), + ); + let kernel_stage5_openings = jolt_prover::stage5_opening_inputs_from_artifacts( + stage5_prover_plan, + &stage2_artifacts, + &stage4_artifacts, + ) + .expect("generated prover derives Stage 5 opening inputs from artifacts"); + let generated_stage5_openings = + jolt_prover::verifier_opening_inputs_from_kernel(&kernel_stage5_openings); + let mut stage5_prover_transcript = prover_transcript.clone(); + let stage5_artifacts = jolt_prover::prove_stage5_with_trace_witness_inputs( + stage5_prover_plan, + &kernel_stage5_openings, + fixture.proof.trace_length, + fixture.proof.ram_K, + 1 << fixture.params.register_log_k, + &fixture.stage5_lookup_indices, + &fixture.stage5_lookup_table_indices, + &fixture.stage5_is_interleaved_operands, + fixture.params.lookups_ra_virtual_log_k_chunk, + &fixture.stage4_register_accesses, + &fixture.ram_accesses, + &mut stage5_prover_transcript, + ) + .expect("Bolt Stage 5 prover succeeds"); + assert_eq!(stage5_artifacts.sumchecks.len(), 1); + let stage5_proof = jolt_prover::stage5_kernel_proof(&stage5_artifacts); + let mut kernel_stage5_transcript = verifier_transcript.clone(); + let kernel_verified_stage5 = jolt_prover::replay_stage5_proof_with_program( + stage5_prover_plan, + &stage5_proof, + &kernel_stage5_openings, + &mut kernel_stage5_transcript, + ) + .expect("kernel Stage 5 replay accepts Bolt real muldiv proof"); + assert_eq!(kernel_verified_stage5.sumchecks.len(), 1); + assert_state_history_match( + stage5_prover_transcript.log(), + kernel_stage5_transcript.log(), + ); + let generated_stage5_proof = jolt_prover::stage5_proof(&stage5_artifacts); + let generated_stage5_start_transcript = generated_verifier_transcript.clone(); + let generated_verified_stage5 = jolt_verifier::verify_stage5_with_program( + generated_stage5_verifier_plan, + &generated_stage5_proof, + &generated_stage5_openings, + &mut generated_verifier_transcript, + ) + .expect("generated Stage 5 verifier accepts Bolt real muldiv proof"); + assert_eq!(generated_verified_stage5.sumchecks.len(), 1); + let generated_verified_stage5_proof = jolt_verifier::JoltStageProof { + sumchecks: generated_verified_stage5.sumchecks.clone(), + }; + assert_stage5_artifacts_match(&generated_stage5_proof, &generated_verified_stage5_proof); + assert_state_history_match( + stage5_prover_transcript.log(), + generated_verifier_transcript.log(), + ); + assert_core_accepts_bolt_stage5( + &fixture, + &stage1_artifacts, + &stage2_artifacts, + &stage3_artifacts, + &stage4_artifacts, + &generated_stage5_proof, + ); + let kernel_stage6_openings = jolt_prover::stage6_opening_inputs_from_artifacts( + stage6_prover_plan, + &stage1_artifacts, + &stage2_artifacts, + &stage3_artifacts, + &stage4_artifacts, + &stage5_artifacts, + ) + .expect("generated prover derives Stage 6 opening inputs from artifacts"); + let generated_stage6_openings = + jolt_prover::verifier_opening_inputs_from_kernel(&kernel_stage6_openings); + let generated_stage6_data = jolt_prover::stage6_verifier_data_from_witness_entries( + &fixture.stage6_bytecode_entries, + fixture.stage6_entry_bytecode_index, + fixture.stage6_num_lookup_tables, + ); + let kernel_stage6_bytecode_data = + jolt_prover::stage6_bytecode_read_raf_data_from_witness_entries( + &fixture.stage6_bytecode_entries, + fixture.stage6_entry_bytecode_index, + fixture.stage6_num_lookup_tables, + ); + let mut stage6_prover_transcript = generated_verifier_transcript.clone(); + let stage6_artifacts = jolt_prover::prove_stage6_with_trace_witness_inputs( + stage6_prover_plan, + &kernel_stage6_openings, + kernel_stage6_bytecode_data.as_input(), + fixture.stage6_witness_params(), + &fixture.cycle_inputs, + fixture.params.instruction_ra_virtual_d, + &mut stage6_prover_transcript, + ) + .expect("Bolt Stage 6 prover succeeds"); + assert_eq!(stage6_artifacts.sumchecks.len(), 1); + let generated_stage6_proof = jolt_prover::stage6_proof(&stage6_artifacts); + let generated_stage6_artifacts = jolt_prover::stage6_execution_artifacts(&stage6_artifacts); + assert_stage6_artifacts_match(&generated_stage6_proof, &generated_stage6_artifacts); + let mut kernel_stage6_transcript = generated_verifier_transcript.clone(); + let kernel_stage6_proof = jolt_prover::stage6_kernel_proof(&generated_stage6_proof); + let kernel_verified_stage6 = jolt_prover::replay_stage6_proof_with_program( + stage6_prover_plan, + &kernel_stage6_proof, + &kernel_stage6_openings, + Some(kernel_stage6_bytecode_data.as_input()), + &mut kernel_stage6_transcript, + ) + .expect("kernel Stage 6 replay accepts Bolt real muldiv proof"); + assert_eq!(kernel_verified_stage6.sumchecks.len(), 1); + assert_stage6_artifacts_match( + &generated_stage6_proof, + &jolt_prover::stage6_execution_artifacts(&kernel_verified_stage6), + ); + assert_state_history_match( + stage6_prover_transcript.log(), + kernel_stage6_transcript.log(), + ); + let mut generated_stage6_transcript = generated_verifier_transcript.clone(); + let generated_verified_stage6 = jolt_verifier::verify_stage6_with_program( + generated_stage6_verifier_plan, + &generated_stage6_proof, + &generated_stage6_openings, + Some(&generated_stage6_data), + &mut generated_stage6_transcript, + ) + .expect("generated Stage 6 verifier accepts Bolt real muldiv proof"); + assert_stage6_artifacts_match(&generated_stage6_proof, &generated_verified_stage6); + assert_state_history_match( + stage6_prover_transcript.log(), + generated_stage6_transcript.log(), + ); + assert_core_accepts_bolt_stage6( + &fixture, + &stage1_artifacts, + &stage2_artifacts, + &stage3_artifacts, + &stage4_artifacts, + &generated_stage5_proof, + &generated_stage6_proof, + ); + + let kernel_stage7_openings = + jolt_prover::stage7_opening_inputs_from_stage6_artifacts_with_program( + stage7_prover_plan, + &stage6_artifacts, + ) + .expect("generated prover derives Stage 7 opening inputs from Stage 6 artifacts"); + let generated_stage7_openings = + jolt_prover::verifier_opening_inputs_from_kernel(&kernel_stage7_openings); + let mut stage7_prover_transcript = stage6_prover_transcript.clone(); + let stage7_artifacts = jolt_prover::prove_stage7_with_trace_witness_inputs( + stage7_prover_plan, + &kernel_stage7_openings, + fixture.stage6_witness_params(), + &fixture.cycle_inputs, + &kernel_stage6_openings, + &mut stage7_prover_transcript, + ) + .expect("Bolt Stage 7 prover succeeds"); + assert_eq!(stage7_artifacts.sumchecks.len(), 1); + let generated_stage7_proof = jolt_prover::stage7_proof(&stage7_artifacts); + let generated_stage7_artifacts = jolt_prover::stage7_execution_artifacts(&stage7_artifacts); + assert_stage7_artifacts_match(&generated_stage7_proof, &generated_stage7_artifacts); + let mut kernel_stage7_transcript = generated_stage6_transcript.clone(); + let kernel_stage7_proof = jolt_prover::stage7_kernel_proof(&generated_stage7_proof); + let kernel_verified_stage7 = jolt_prover::replay_stage7_proof_with_program( + stage7_prover_plan, + &kernel_stage7_proof, + &kernel_stage7_openings, + &mut kernel_stage7_transcript, + ) + .expect("kernel Stage 7 replay accepts Bolt real muldiv proof"); + assert_eq!(kernel_verified_stage7.sumchecks.len(), 1); + assert_stage7_artifacts_match( + &generated_stage7_proof, + &jolt_prover::stage7_execution_artifacts(&kernel_verified_stage7), + ); + assert_state_history_match( + stage7_prover_transcript.log(), + kernel_stage7_transcript.log(), + ); + let mut generated_stage7_transcript = generated_stage6_transcript.clone(); + let generated_verified_stage7 = jolt_verifier::verify_stage7_with_program( + generated_stage7_verifier_plan, + &generated_stage7_proof, + &generated_stage7_openings, + &mut generated_stage7_transcript, + ) + .expect("generated Stage 7 verifier accepts Bolt real muldiv proof"); + assert_stage7_artifacts_match(&generated_stage7_proof, &generated_verified_stage7); + assert_state_history_match( + stage7_prover_transcript.log(), + generated_stage7_transcript.log(), + ); + assert_core_accepts_bolt_stage7( + &fixture, + &stage1_artifacts, + &stage2_artifacts, + &stage3_artifacts, + &stage4_artifacts, + &generated_stage5_proof, + &generated_stage6_proof, + &generated_stage7_proof, + ); + + let generated_jolt_stage2_openings = + jolt_prover::verifier_opening_inputs_from_kernel(&stage2_verifier_openings); + let generated_jolt_stage3_openings = + jolt_prover::verifier_opening_inputs_from_kernel(&stage3_verifier_openings); + let generated_jolt_stage4_openings = + jolt_prover::verifier_opening_inputs_from_kernel(&stage4_verifier_openings); + let generated_ram_data_storage = jolt_prover::stage2_verifier_ram_data(&ram_data); + let generated_ram_data = generated_ram_data_storage.as_input(); + let generated_jolt_inputs = jolt_verifier::JoltVerifierInputs { + stage2_openings: &generated_jolt_stage2_openings, + stage2_ram: Some(&generated_ram_data), + stage3_openings: &generated_jolt_stage3_openings, + stage4_openings: &generated_jolt_stage4_openings, + stage5_openings: &generated_stage5_openings, + stage6_openings: &generated_stage6_openings, + stage6_data: Some(&generated_stage6_data), + stage7_openings: &generated_stage7_openings, + evaluation_setup: None, + }; + let generated_jolt_proof = jolt_prover::jolt_proof_through_stage5( + &commitment_verifier_trace.commitments, + &stage1_artifacts, + &stage2_artifacts, + &stage3_artifacts, + &stage4_artifacts, + &generated_stage5_proof, + ); + let mut generated_jolt_transcript = transcript_with_bolt_preamble(&fixture); + let generated_jolt_artifacts = jolt_verifier::verify_jolt_through_stage5_with_programs( + &generated_jolt_proof, + generated_jolt_inputs.through_stage5(), + generated_programs, + &mut generated_jolt_transcript, + ) + .expect("generated monolithic verifier accepts real muldiv proof"); + assert_eq!( + stage3_artifacts.sumchecks.len(), + generated_jolt_artifacts.stage3.sumchecks.len() + ); + assert_canonical_stage_artifacts_match( + "generated monolithic through-stage5 Stage 4", + canonical_stage4_artifacts(&stage4_artifacts), + canonical_generated_stage4_execution_artifacts(&generated_jolt_artifacts.stage4), + ); + assert_canonical_stage_artifacts_match( + "generated monolithic through-stage5 Stage 5", + canonical_generated_stage5_proof(&generated_stage5_proof), + canonical_generated_stage5_execution_artifacts(&generated_jolt_artifacts.stage5), + ); + assert_state_history_match( + generated_verifier_transcript.log(), + generated_jolt_transcript.log(), + ); + let generated_jolt_proof_with_stage6 = jolt_prover::jolt_proof_through_stage6( + &commitment_verifier_trace.commitments, + &stage1_artifacts, + &stage2_artifacts, + &stage3_artifacts, + &stage4_artifacts, + &generated_stage5_proof, + &generated_stage6_proof, + ); + let mut generated_jolt_stage6_transcript = transcript_with_bolt_preamble(&fixture); + let generated_jolt_stage6_artifacts = jolt_verifier::verify_jolt_through_stage6_with_programs( + &generated_jolt_proof_with_stage6, + generated_jolt_inputs.through_stage6(), + generated_programs, + &mut generated_jolt_stage6_transcript, + ) + .expect("generated monolithic verifier accepts Bolt Stage 6 proof"); + assert_stage6_artifacts_match( + &generated_stage6_proof, + &generated_jolt_stage6_artifacts.stage6, + ); + assert_state_history_match( + generated_stage6_transcript.log(), + generated_jolt_stage6_transcript.log(), + ); + let generated_jolt_proof_with_stage7 = jolt_prover::jolt_proof_through_stage7( + &commitment_verifier_trace.commitments, + &stage1_artifacts, + &stage2_artifacts, + &stage3_artifacts, + &stage4_artifacts, + &generated_stage5_proof, + &generated_stage6_proof, + &generated_stage7_proof, + ); + let mut generated_jolt_stage7_transcript = transcript_with_bolt_preamble(&fixture); + let generated_jolt_stage7_artifacts = jolt_verifier::verify_jolt_through_stage7_with_programs( + &generated_jolt_proof_with_stage7, + generated_jolt_inputs.through_stage7(), + generated_programs, + &mut generated_jolt_stage7_transcript, + ) + .expect("generated monolithic verifier accepts Bolt Stage 7 proof"); + assert_stage7_artifacts_match( + &generated_stage7_proof, + &generated_jolt_stage7_artifacts.stage7, + ); + assert_state_history_match( + generated_stage7_transcript.log(), + generated_jolt_stage7_transcript.log(), + ); + + let monolithic_prover_programs = jolt_prover::JoltProverPrograms { + commitment: generated_commitment_prover_plan, + stage1_outer: stage1_prover_plan, + stage2: stage2_prover_plan, + stage3: stage3_prover_plan, + stage4: stage4_prover_plan, + stage5: stage5_prover_plan, + stage6: stage6_prover_plan, + stage7: stage7_prover_plan, + stage8: stage8_prover_plan, + }; + let monolithic_commitment_storage = + GeneratedCommitmentInputStorage::from_cycles(&fixture.cycle_inputs); + let mut monolithic_commitment_inputs = monolithic_commitment_storage.sparse_inputs(); + let mut monolithic_prover_transcript = transcript_with_bolt_preamble(&fixture); + let bolt_rss_sampler = PeakRssSampler::start().expect("start Bolt RSS sampler"); + let (bolt_prove_ms, monolithic_prove_result) = time_it(|| { + jolt_prover::prove_jolt_with_witness_inputs( + jolt_prover::JoltProverWitnessInputs { + commitment_inputs: &mut monolithic_commitment_inputs, + prover_setup: &fixture.pcs_setup, + stage1_trace_num_vars: r1cs_key.num_cycle_vars(), + stage1_outer_evaluator: &data, + stage2_openings: &stage2_openings, + product_virtual_cycles: &fixture.product_virtual_cycles, + instruction_lookup_cycles: &fixture.instruction_lookup_cycles, + ram: &ram_data, + stage3_openings: &stage3_openings, + stage3_cycles: &fixture.stage3_cycles, + stage4_openings: &stage4_openings, + register_count: 1 << fixture.params.register_log_k, + trace_len: fixture.proof.trace_length, + ram_k: fixture.proof.ram_K, + register_accesses: &fixture.stage4_register_accesses, + stage5_openings: &kernel_stage5_openings, + lookup_indices: &fixture.stage5_lookup_indices, + lookup_table_indices: &fixture.stage5_lookup_table_indices, + is_interleaved_operands: &fixture.stage5_is_interleaved_operands, + ra_virtual_log_k_chunk: fixture.params.lookups_ra_virtual_log_k_chunk, + stage6_openings: &kernel_stage6_openings, + stage6_bytecode_data: kernel_stage6_bytecode_data.as_input(), + stage6_witness_params: fixture.stage6_witness_params(), + cycle_inputs: &fixture.cycle_inputs, + instruction_ra_virtual_d: fixture.params.instruction_ra_virtual_d, + stage7_openings: &kernel_stage7_openings, + evaluation_openings: Some(&kernel_stage7_openings), + }, + monolithic_prover_programs, + &mut monolithic_prover_transcript, + ) + }); + let bolt_peak_rss_mb = bolt_rss_sampler.finish(); + let (monolithic_proof, monolithic_artifacts) = + monolithic_prove_result.expect("generated monolithic prover produces real trace proof"); + let monolithic_evaluation = monolithic_proof + .evaluation + .as_ref() + .expect("generated monolithic prover emits evaluation proof"); + assert_state_history_prefix_match( + generated_stage7_transcript.log(), + monolithic_prover_transcript.log(), + ); + assert_dory_proofs_match( + &DoryProof(fixture.proof.joint_opening_proof.clone()), + &monolithic_evaluation.joint_opening_proof, + ); + assert_core_accepts_full_bolt_proof(&fixture, &monolithic_proof, &monolithic_artifacts); + assert_core_accepts_bolt_evaluation_proof(&fixture, monolithic_evaluation); + + let mut staged_bolt_run = EquivalenceRun::new(ArtifactSource::Bolt); + staged_bolt_run.commitments = commitment_prover_trace.commitment_trace(); + staged_bolt_run.stages = vec![ + canonical_stage4_artifacts(&stage4_artifacts), + canonical_generated_stage5_proof(&generated_stage5_proof), + canonical_generated_stage6_proof(&generated_stage6_proof), + canonical_generated_stage7_proof(&generated_stage7_proof), + ]; + staged_bolt_run.verifier_result = VerifierResult::accepted(); + let monolithic_stage5_proof = jolt_prover::stage5_proof(&monolithic_artifacts.stage5); + let monolithic_stage6_artifacts = + jolt_prover::stage6_execution_artifacts(&monolithic_artifacts.stage6); + let monolithic_stage7_artifacts = + jolt_prover::stage7_execution_artifacts(&monolithic_artifacts.stage7); + let mut monolithic_bolt_run = EquivalenceRun::new(ArtifactSource::Bolt); + monolithic_bolt_run.commitments = generated_commitment_trace(&monolithic_artifacts.commitment); + monolithic_bolt_run.transcript = TranscriptTrace { + events: monolithic_prover_transcript.log().to_vec(), + }; + monolithic_bolt_run.stages = vec![ + canonical_stage4_artifacts(&monolithic_artifacts.stage4), + canonical_generated_stage5_proof(&monolithic_stage5_proof), + canonical_generated_stage6_execution_artifacts(&monolithic_stage6_artifacts), + canonical_generated_stage7_execution_artifacts(&monolithic_stage7_artifacts), + ]; + monolithic_bolt_run.verifier_result = VerifierResult::accepted(); + assert_equivalence_run_artifacts_match( + "staged-vs-monolithic generated prover", + &staged_bolt_run, + &monolithic_bolt_run, + ); + + let mut monolithic_verify_transcript = transcript_with_bolt_preamble(&fixture); + let evaluation_setup = DoryScheme::verifier_setup(&fixture.pcs_setup); + let (bolt_verify_ms, monolithic_verify_result) = time_it(|| { + jolt_verifier::verify_jolt_with_programs( + &monolithic_proof, + generated_jolt_inputs.full(&evaluation_setup), + generated_programs, + &mut monolithic_verify_transcript, + ) + }); + let monolithic_verified_artifacts = monolithic_verify_result + .expect("generated monolithic verifier accepts generated monolithic prover proof"); + let mut monolithic_verifier_run = EquivalenceRun::new(ArtifactSource::Bolt); + monolithic_verifier_run.commitments = + generated_verifier_commitment_trace(&monolithic_verified_artifacts.commitment); + monolithic_verifier_run.transcript = TranscriptTrace { + events: monolithic_verify_transcript.log().to_vec(), + }; + monolithic_verifier_run.stages = vec![ + canonical_generated_stage4_execution_artifacts(&monolithic_verified_artifacts.stage4), + canonical_generated_stage5_execution_artifacts(&monolithic_verified_artifacts.stage5), + canonical_generated_stage6_execution_artifacts(&monolithic_verified_artifacts.stage6), + canonical_generated_stage7_execution_artifacts(&monolithic_verified_artifacts.stage7), + ]; + monolithic_verifier_run.verifier_result = VerifierResult::accepted(); + assert_equivalence_run_artifacts_match( + "generated monolithic prover-vs-verifier", + &monolithic_bolt_run, + &monolithic_verifier_run, + ); + + let bolt_metrics = generated_bolt_perf_metrics( + bolt_setup_ms, + bolt_prove_ms, + bolt_verify_ms, + &monolithic_proof, + bolt_peak_rss_mb, + ); + if enforce_perf_gate { + let report = check_core_vs_bolt_gate( + &fixture.core_metrics, + &bolt_metrics, + CORE_VS_BOLT_PERF_THRESHOLDS, + ) + .expect("core-vs-Bolt perf oracle gate"); + print_core_vs_bolt_perf_summary(&fixture.core_metrics, &bolt_metrics, &report); + } + assert_state_history_match( + monolithic_prover_transcript.log(), + monolithic_verify_transcript.log(), + ); + + assert_monolithic_jolt_tamper_rejected(MonolithicJoltTamperInput { + preamble: &fixture, + proof: &monolithic_proof, + inputs: generated_jolt_inputs.full(&evaluation_setup), + programs: generated_programs, + }); + + assert_bolt_stage3_4_5_tamper_rejected(Stage345TamperInput { + preamble: &fixture, + commitment_verifier_trace: &commitment_verifier_trace, + stage1_artifacts: &stage1_artifacts, + stage2_artifacts: &stage2_artifacts, + stage3_artifacts: &stage3_artifacts, + stage4_artifacts: &stage4_artifacts, + generated_stage3_verifier_plan, + generated_stage3_openings: &generated_stage3_openings, + generated_stage3_start_transcript: &generated_stage3_start_transcript, + generated_stage4_verifier_plan, + generated_stage5_verifier_plan, + generated_stage4_start_transcript: &generated_stage4_start_transcript, + generated_stage4_openings: &generated_stage4_openings, + generated_stage5_openings: &generated_stage5_openings, + generated_stage5_proof: &generated_stage5_proof, + generated_stage5_start_transcript: &generated_stage5_start_transcript, + generated_jolt_inputs, + generated_programs, + }); + + assert_bolt_stage6_tamper_rejected(Stage6TamperInput { + preamble: &fixture, + commitment_verifier_trace: &commitment_verifier_trace, + verifier_transcript: &generated_verifier_transcript, + verifier_plan: generated_stage6_verifier_plan, + proof: &generated_stage6_proof, + openings: &generated_stage6_openings, + data: &generated_stage6_data, + stage1_artifacts: &stage1_artifacts, + stage2_artifacts: &stage2_artifacts, + stage3_artifacts: &stage3_artifacts, + stage4_artifacts: &stage4_artifacts, + stage5_proof: &generated_stage5_proof, + jolt_inputs: generated_jolt_inputs.through_stage6(), + programs: generated_programs, + }); + + assert_bolt_stage7_tamper_rejected(Stage7TamperInput { + preamble: &fixture, + commitment_verifier_trace: &commitment_verifier_trace, + verifier_transcript: &generated_stage6_transcript, + verifier_plan: generated_stage7_verifier_plan, + proof: &generated_stage7_proof, + openings: &generated_stage7_openings, + stage1_artifacts: &stage1_artifacts, + stage2_artifacts: &stage2_artifacts, + stage3_artifacts: &stage3_artifacts, + stage4_artifacts: &stage4_artifacts, + stage5_proof: &generated_stage5_proof, + stage6_proof: &generated_stage6_proof, + jolt_inputs: generated_jolt_inputs.through_stage7(), + programs: generated_programs, + }); +} diff --git a/crates/jolt-equivalence/src/bolt_programs.rs b/crates/jolt-equivalence/src/bolt_programs.rs new file mode 100644 index 0000000000..d678672c50 --- /dev/null +++ b/crates/jolt-equivalence/src/bolt_programs.rs @@ -0,0 +1,170 @@ +//! Bolt protocol-program construction helpers for equivalence tests. + +use bolt::protocols::jolt::{ + build_commitment_protocol, build_stage1_outer_protocol, build_stage2_protocol, + build_stage3_protocol, build_stage4_protocol, build_stage5_protocol, build_stage6_protocol, + build_stage7_protocol, build_stage8_protocol, commitment_cpu_program, + lower_commitment_to_compute, lower_compute_to_cpu, lower_stage1_to_compute, + lower_stage2_to_compute, lower_stage3_to_compute, lower_stage4_to_compute, + lower_stage5_to_compute, lower_stage6_to_compute, lower_stage7_to_compute, + lower_stage8_to_compute, resolve_compute_kernels, stage1_cpu_program, stage2_cpu_program, + stage3_cpu_program, stage4_cpu_program, stage5_cpu_program, stage6_cpu_program, + stage7_cpu_program, stage8_cpu_program, CommitmentCpuProgram, JoltProtocolParams, + Stage1CpuProgram as CompilerStage1CpuProgram, Stage2CpuProgram as CompilerStage2CpuProgram, + Stage3CpuProgram as CompilerStage3CpuProgram, Stage4CpuProgram as CompilerStage4CpuProgram, + Stage5CpuProgram as CompilerStage5CpuProgram, Stage6CpuProgram as CompilerStage6CpuProgram, + Stage7CpuProgram as CompilerStage7CpuProgram, Stage8CpuProgram as CompilerStage8CpuProgram, +}; +use bolt::{ + lower_piop_and_fiat_shamir, project_prover_party, project_verifier_party, MeliorContext, +}; + +pub fn bolt_commitment_programs() -> (CommitmentCpuProgram, CommitmentCpuProgram) { + let params = JoltProtocolParams::new(0, 0, 0); + bolt_commitment_programs_with_params(¶ms) +} + +macro_rules! define_bolt_programs_with_params { + ( + $function:ident, + $($rest:tt)* + ) => { + define_bolt_programs_with_params!(pub $function, $($rest)*); + }; + ( + $vis:vis $function:ident, + $program:ty, + $build:ident, + $lower:ident, + $extract:ident, + $label:literal, + resolve_kernels = $resolve_kernels:literal + ) => { + $vis fn $function(params: &JoltProtocolParams) -> ($program, $program) { + let context = MeliorContext::new(); + let protocol = $build(&context, params).expect(concat!("build ", $label, " protocol")); + let concrete = lower_piop_and_fiat_shamir(&context, &protocol).expect(concat!( + "lower ", + $label, + " protocol" + )); + let prover_party = project_prover_party(&context, &concrete).expect("project prover"); + let verifier_party = + project_verifier_party(&context, &concrete).expect("project verifier"); + let prover_compute = $lower(&context, &prover_party).expect(concat!( + "lower prover ", + $label, + " compute" + )); + let verifier_compute = $lower(&context, &verifier_party).expect(concat!( + "lower verifier ", + $label, + " compute" + )); + let (prover_compute, verifier_compute) = if $resolve_kernels { + ( + resolve_compute_kernels(&context, &prover_compute) + .expect("resolve prover kernels"), + resolve_compute_kernels(&context, &verifier_compute) + .expect("resolve verifier kernels"), + ) + } else { + (prover_compute, verifier_compute) + }; + let prover_cpu = + lower_compute_to_cpu(&context, &prover_compute).expect("lower prover CPU"); + let verifier_cpu = + lower_compute_to_cpu(&context, &verifier_compute).expect("lower verifier CPU"); + let prover_program = + $extract(&prover_cpu).expect(concat!("extract prover ", $label, " CPU program")); + let verifier_program = $extract(&verifier_cpu).expect(concat!( + "extract verifier ", + $label, + " CPU program" + )); + (prover_program, verifier_program) + } + }; +} + +define_bolt_programs_with_params!( + bolt_commitment_programs_with_params, + CommitmentCpuProgram, + build_commitment_protocol, + lower_commitment_to_compute, + commitment_cpu_program, + "commitment", + resolve_kernels = false +); +define_bolt_programs_with_params!( + bolt_stage1_programs_with_params, + CompilerStage1CpuProgram, + build_stage1_outer_protocol, + lower_stage1_to_compute, + stage1_cpu_program, + "Stage 1", + resolve_kernels = true +); +define_bolt_programs_with_params!( + bolt_stage2_programs_with_params, + CompilerStage2CpuProgram, + build_stage2_protocol, + lower_stage2_to_compute, + stage2_cpu_program, + "Stage 2", + resolve_kernels = true +); +define_bolt_programs_with_params!( + pub(crate) bolt_stage3_programs_with_params, + CompilerStage3CpuProgram, + build_stage3_protocol, + lower_stage3_to_compute, + stage3_cpu_program, + "Stage 3", + resolve_kernels = true +); +define_bolt_programs_with_params!( + pub(crate) bolt_stage4_programs_with_params, + CompilerStage4CpuProgram, + build_stage4_protocol, + lower_stage4_to_compute, + stage4_cpu_program, + "Stage 4", + resolve_kernels = true +); +define_bolt_programs_with_params!( + pub(crate) bolt_stage5_programs_with_params, + CompilerStage5CpuProgram, + build_stage5_protocol, + lower_stage5_to_compute, + stage5_cpu_program, + "Stage 5", + resolve_kernels = true +); +define_bolt_programs_with_params!( + pub(crate) bolt_stage6_programs_with_params, + CompilerStage6CpuProgram, + build_stage6_protocol, + lower_stage6_to_compute, + stage6_cpu_program, + "Stage 6", + resolve_kernels = true +); +define_bolt_programs_with_params!( + pub(crate) bolt_stage7_programs_with_params, + CompilerStage7CpuProgram, + build_stage7_protocol, + lower_stage7_to_compute, + stage7_cpu_program, + "Stage 7", + resolve_kernels = true +); +define_bolt_programs_with_params!( + pub(crate) bolt_stage8_programs_with_params, + CompilerStage8CpuProgram, + build_stage8_protocol, + lower_stage8_to_compute, + stage8_cpu_program, + "Stage 8", + resolve_kernels = false +); diff --git a/crates/jolt-equivalence/src/checkpoint.rs b/crates/jolt-equivalence/src/checkpoint.rs new file mode 100644 index 0000000000..4d602461c8 --- /dev/null +++ b/crates/jolt-equivalence/src/checkpoint.rs @@ -0,0 +1,273 @@ +//! Checkpoint transcript for fine-grained Fiat-Shamir comparison. +//! +//! Wraps any [`Transcript`] and records every append/squeeze operation as +//! a [`TranscriptEvent`]. Two event logs can then be compared element by +//! element to find the *exact* operation where two systems diverge. + +#![expect(clippy::panic, reason = "checkpoint assertions are test gates")] + +use std::fmt; + +use jolt_transcript::Transcript; + +/// A single transcript operation. +#[derive(Clone, PartialEq, Eq)] +pub enum TranscriptEvent { + /// Raw bytes were appended to the transcript. + Append { + /// The bytes that were absorbed. + bytes: Vec, + /// Transcript state *after* this append. + state_after: [u8; 32], + }, + /// A challenge was squeezed from the transcript. + Squeeze { + /// The 32-byte transcript state *after* the squeeze. + state_after: [u8; 32], + }, +} + +impl fmt::Debug for TranscriptEvent { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn hex(b: &[u8]) -> String { + use std::fmt::Write; + let mut s = String::with_capacity(b.len() * 2); + for byte in b { + let _ = write!(s, "{byte:02x}"); + } + s + } + match self { + TranscriptEvent::Append { bytes, state_after } => { + let preview = if bytes.len() <= 32 { + hex(bytes) + } else { + format!("{}... ({} bytes)", hex(&bytes[..16]), bytes.len()) + }; + write!(f, "Append({preview}) -> {}", &hex(state_after)[..16]) + } + TranscriptEvent::Squeeze { state_after } => { + write!(f, "Squeeze -> {}", &hex(state_after)[..16]) + } + } + } +} + +/// Wraps a concrete transcript, recording every operation. +/// +/// Implements [`Transcript`] so it can be used as a drop-in replacement. After +/// the protocol runs, call [`log`](Self::log) to inspect the event sequence. +pub struct CheckpointTranscript { + inner: T, + log: Vec, +} + +impl CheckpointTranscript { + /// Borrow the event log without consuming. + pub fn log(&self) -> &[TranscriptEvent] { + &self.log + } +} + +impl Clone for CheckpointTranscript { + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + log: self.log.clone(), + } + } +} + +impl Default for CheckpointTranscript { + fn default() -> Self { + Self { + inner: T::default(), + log: Vec::new(), + } + } +} + +impl Transcript for CheckpointTranscript { + type Challenge = ::Challenge; + + fn new(label: &'static [u8]) -> Self { + Self { + inner: T::new(label), + log: Vec::new(), + } + } + + fn append_bytes(&mut self, bytes: &[u8]) { + self.inner.append_bytes(bytes); + self.log.push(TranscriptEvent::Append { + bytes: bytes.to_vec(), + state_after: *self.inner.state(), + }); + } + + fn challenge(&mut self) -> Self::Challenge { + let c = self.inner.challenge(); + self.log.push(TranscriptEvent::Squeeze { + state_after: *self.inner.state(), + }); + c + } + + fn state(&self) -> &[u8; 32] { + self.inner.state() + } +} + +/// Describes where two transcript logs first diverge. +#[derive(Debug)] +pub struct TranscriptDivergence { + /// Zero-based index of the diverging operation. + pub op_index: usize, + /// What the reference system did. + pub expected: String, + /// What the candidate system did. + pub actual: String, +} + +impl fmt::Display for TranscriptDivergence { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "transcript divergence at op #{}: expected {}, got {}", + self.op_index, self.expected, self.actual + ) + } +} + +/// Compare two transcript event logs and return the first divergence. +/// +/// Returns `Ok(())` if the logs are identical (up to the length of the +/// shorter log — a length mismatch after identical prefixes is also reported). +pub fn find_divergence( + reference: &[TranscriptEvent], + candidate: &[TranscriptEvent], +) -> Result<(), TranscriptDivergence> { + let min_len = reference.len().min(candidate.len()); + + for i in 0..min_len { + let events_match = match (&reference[i], &candidate[i]) { + ( + TranscriptEvent::Append { + bytes: bytes_a, + state_after: sa, + .. + }, + TranscriptEvent::Append { + bytes: bytes_b, + state_after: sb, + .. + }, + ) => bytes_a == bytes_b && sa == sb, + ( + TranscriptEvent::Squeeze { state_after: sa }, + TranscriptEvent::Squeeze { state_after: sb }, + ) => sa == sb, + _ => false, // Different event kinds + }; + + if !events_match { + return Err(TranscriptDivergence { + op_index: i, + expected: format!("{:?}", reference[i]), + actual: format!("{:?}", candidate[i]), + }); + } + } + + if reference.len() != candidate.len() { + return Err(TranscriptDivergence { + op_index: min_len, + expected: if min_len < reference.len() { + format!("{:?}", reference[min_len]) + } else { + "".to_string() + }, + actual: if min_len < candidate.len() { + format!("{:?}", candidate[min_len]) + } else { + "".to_string() + }, + }); + } + + Ok(()) +} + +/// Compare two logs and panic with a detailed message on divergence. +#[expect(clippy::print_stderr)] +pub fn assert_transcripts_match(reference: &[TranscriptEvent], candidate: &[TranscriptEvent]) { + if let Err(div) = find_divergence(reference, candidate) { + // Print context: a few events before the divergence point. + let start = div.op_index.saturating_sub(3); + eprintln!("=== Transcript divergence at op #{} ===", div.op_index); + let end_ref = div.op_index.min(reference.len().saturating_sub(1)); + let end_cand = div.op_index.min(candidate.len().saturating_sub(1)); + eprintln!("Context (reference):"); + for (i, event) in reference.iter().enumerate().take(end_ref + 1).skip(start) { + let marker = if i == div.op_index { ">>>" } else { " " }; + eprintln!(" {marker} [{i}] {event:?}"); + } + eprintln!("Context (candidate):"); + for (i, event) in candidate.iter().enumerate().take(end_cand + 1).skip(start) { + let marker = if i == div.op_index { ">>>" } else { " " }; + eprintln!(" {marker} [{i}] {event:?}"); + } + panic!("{div}"); + } +} + +/// Extracts the transcript state after each recorded operation. +fn transcript_states(log: &[TranscriptEvent]) -> Vec<[u8; 32]> { + log.iter() + .map(|event| match event { + TranscriptEvent::Append { state_after, .. } + | TranscriptEvent::Squeeze { state_after } => *state_after, + }) + .collect() +} + +fn assert_state_prefix(expected: &[[u8; 32]], actual: &[[u8; 32]]) { + for index in 0..expected.len() { + assert_eq!( + expected[index], actual[index], + "transcript state mismatch at op #{index}" + ); + } +} + +/// Compare full transcript state histories. +pub fn assert_state_history_match( + expected_log: &[TranscriptEvent], + actual_log: &[TranscriptEvent], +) { + let expected = transcript_states(expected_log); + let actual = transcript_states(actual_log); + let min_len = expected.len().min(actual.len()); + assert_state_prefix(&expected[..min_len], &actual[..min_len]); + assert_eq!( + expected.len(), + actual.len(), + "transcript state count mismatch" + ); +} + +/// Compare an expected transcript state prefix against a full actual history. +pub(crate) fn assert_state_history_prefix_match( + expected_prefix_log: &[TranscriptEvent], + actual_log: &[TranscriptEvent], +) { + let expected_prefix = transcript_states(expected_prefix_log); + let actual = transcript_states(actual_log); + assert!( + actual.len() >= expected_prefix.len(), + "transcript state count mismatch: expected at least {}, got {}", + expected_prefix.len(), + actual.len() + ); + assert_state_prefix(&expected_prefix, &actual); +} diff --git a/crates/jolt-equivalence/src/checks.rs b/crates/jolt-equivalence/src/checks.rs new file mode 100644 index 0000000000..34e077080c --- /dev/null +++ b/crates/jolt-equivalence/src/checks.rs @@ -0,0 +1,565 @@ +//! Focused equivalence assertions shared by tests. + +#![expect( + clippy::expect_used, + clippy::panic, + reason = "equivalence assertions should fail fast with precise mismatch context" +)] + +use std::collections::BTreeMap; + +use jolt_core::curve::Bn254Curve; +use jolt_core::poly::commitment::dory::DoryCommitmentScheme; +use jolt_core::poly::opening_proof::SumcheckId as S; +use jolt_core::poly::opening_proof::{OpeningId, SumcheckId}; +use jolt_core::subprotocols::univariate_skip::UniSkipFirstRoundProofVariant; +use jolt_core::transcripts::Blake2bTranscript as CoreBlake2bTranscript; +use jolt_core::zkvm::instruction::{CircuitFlags, InstructionFlags}; +use jolt_core::zkvm::proof_serialization::JoltProof as CoreJoltProof; +use jolt_core::zkvm::witness::{CommittedPolynomial, VirtualPolynomial}; +use jolt_core::zkvm::witness::{CommittedPolynomial as C, VirtualPolynomial as V}; +use jolt_dory::DoryProof; +use jolt_field::{Field, Fr}; +use jolt_kernels::{ + stage1::{ + outer_uniskip_extended_evals_from_round_poly, outer_uniskip_targets, + Stage1ExecutionArtifacts, Stage1OuterR1csData, Stage1OuterRemainingEvaluator, + Stage1OuterRv64Data, Stage1SumcheckOutput, + }, + stage2::Stage2ExecutionArtifacts, + stage3::Stage3ExecutionArtifacts, +}; +use jolt_poly::UnivariatePoly; +use jolt_verifier::stages::stage6 as generated_stage6; +use jolt_verifier::{JoltStageExecutionArtifacts, JoltStageProof, JoltSumcheckOutput}; + +use crate::adapters::{ + canonical_generated_stage5_proof, canonical_generated_stage6_execution_artifacts, + canonical_generated_stage6_proof, canonical_generated_stage7_execution_artifacts, + canonical_generated_stage7_proof, +}; +use crate::artifacts::{EquivalenceRun, StageArtifacts}; +use crate::core_conversion::to_ark; + +pub type CoreProofForChecks = + CoreJoltProof; + +macro_rules! assert_core_compressed_sumcheck_match { + ($stage:literal, $core_proof:expr, $output:expr) => {{ + let core_polys = match $core_proof { + jolt_core::subprotocols::sumcheck::SumcheckInstanceProof::Clear(proof) => { + &proof.compressed_polys + } + jolt_core::subprotocols::sumcheck::SumcheckInstanceProof::Zk(_) => { + panic!("standard {} proof expected", $stage) + } + }; + assert_eq!( + core_polys.len(), + $output.proof.round_polynomials.len(), + "{} round count mismatch", + $stage + ); + for (round, (core, bolt)) in core_polys + .iter() + .zip(&$output.proof.round_polynomials) + .enumerate() + { + let bolt_coeffs = bolt.compress(); + let bolt_coeffs = bolt_coeffs + .coeffs_except_linear_term() + .iter() + .copied() + .map(to_ark) + .collect::>(); + assert_eq!( + core.coeffs_except_linear_term, bolt_coeffs, + "{} compressed coefficient mismatch at round {round}", + $stage + ); + } + }}; +} + +/// Assert byte-for-byte equality of Dory opening proofs. +pub(crate) fn assert_dory_proofs_match(expected: &DoryProof, actual: &DoryProof) { + assert_eq!( + dory_proof_bytes(expected), + dory_proof_bytes(actual), + "Dory joint opening proof mismatch" + ); +} + +fn dory_proof_bytes(proof: &DoryProof) -> Vec { + postcard::to_stdvec(proof).expect("serialize Dory proof") +} + +fn inverse_nonzero(value: Fr) -> Fr { + match value.inverse() { + Some(inverse) => inverse, + None => unreachable!("nonzero field element has an inverse"), + } +} + +fn assert_core_uniskip_coefficients_match( + stage: &str, + proof: &UniSkipFirstRoundProofVariant, + round_polynomials: &[UnivariatePoly], +) { + let core_coefficients = core_uniskip_coefficients(stage, proof); + assert_eq!(round_polynomials.len(), 1); + let bolt_coefficients = round_polynomials[0].coefficients(); + if let Some(index) = bolt_coefficients + .iter() + .zip(core_coefficients.iter()) + .position(|(bolt, core)| bolt != core) + { + let ratio = if core_coefficients[index] != Fr::from_u64(0) { + Some(bolt_coefficients[index] * inverse_nonzero(core_coefficients[index])) + } else { + None + }; + let next_ratio = bolt_coefficients + .iter() + .zip(core_coefficients.iter()) + .enumerate() + .skip(index + 1) + .find(|(_, (_, core))| **core != Fr::from_u64(0)) + .map(|(_, (bolt, core))| *bolt * inverse_nonzero(*core)); + panic!( + "{stage} uni-skip coefficient mismatch at {index}: bolt={:?} core={:?} ratio={:?} next_ratio={:?}", + bolt_coefficients[index], core_coefficients[index], ratio, next_ratio + ); + } + assert_eq!( + bolt_coefficients.len(), + core_coefficients.len(), + "{stage} uni-skip coefficient count mismatch" + ); +} + +fn core_uniskip_coefficients( + stage: &str, + proof: &UniSkipFirstRoundProofVariant, +) -> Vec { + match proof { + UniSkipFirstRoundProofVariant::Standard(proof) => proof + .uni_poly + .coeffs + .iter() + .copied() + .map(Fr::from) + .collect(), + UniSkipFirstRoundProofVariant::Zk(_) => panic!("standard {stage} proof expected"), + } +} + +pub fn assert_stage1_uniskip_extended_evals_match_core( + proof: &CoreProofForChecks, + typed_data: &Stage1OuterRv64Data<'_>, + generic_data: &Stage1OuterR1csData<'_, Fr>, + artifacts: &Stage1ExecutionArtifacts, +) { + let tau = artifacts + .challenge_vectors + .iter() + .find(|vector| vector.symbol == "stage1.tau") + .expect("Bolt stage1 tau") + .values + .as_slice(); + let typed_evals = typed_data + .uniskip_extended_evals(tau) + .expect("typed Stage 1 extended evals"); + let generic_evals = generic_data + .uniskip_extended_evals(tau) + .expect("generic Stage 1 extended evals"); + assert_stage1_extended_eval_vecs_match( + "typed RV64 vs generic R1CS", + &typed_evals, + &generic_evals, + ); + + let core_evals = core_stage1_uniskip_extended_evals(proof, tau[tau.len() - 1]); + assert_stage1_extended_eval_vecs_match( + "Bolt typed RV64 vs jolt-core", + &typed_evals, + &core_evals, + ); +} + +fn core_stage1_uniskip_extended_evals(proof: &CoreProofForChecks, tau_high: Fr) -> Vec { + let coefficients = + core_uniskip_coefficients("Stage 1", &proof.stage1_uni_skip_first_round_proof); + let s1 = UnivariatePoly::new(coefficients); + outer_uniskip_extended_evals_from_round_poly(&s1, tau_high) +} + +fn assert_stage1_extended_eval_vecs_match(label: &str, actual: &[Fr], expected: &[Fr]) { + assert_eq!( + actual.len(), + expected.len(), + "{label} extended eval count mismatch" + ); + let targets = outer_uniskip_targets(); + if let Some(index) = actual + .iter() + .zip(expected.iter()) + .position(|(actual, expected)| actual != expected) + { + panic!( + "{label} Stage 1 extended eval mismatch at target {} (index {index}): actual={:?} expected={:?}", + targets[index], actual[index], expected[index] + ); + } +} + +type CoreOpeningExpectation = (&'static str, OpeningId); + +fn expected_virtual_opening( + name: &'static str, + polynomial: VirtualPolynomial, + sumcheck: SumcheckId, +) -> CoreOpeningExpectation { + (name, OpeningId::virt(polynomial, sumcheck)) +} + +fn expected_committed_opening( + name: &'static str, + polynomial: CommittedPolynomial, + sumcheck: SumcheckId, +) -> CoreOpeningExpectation { + (name, OpeningId::committed(polynomial, sumcheck)) +} + +macro_rules! expected_opening { + (v, $name:literal, $polynomial:expr, $sumcheck:expr) => { + expected_virtual_opening($name, $polynomial, $sumcheck) + }; + (c, $name:literal, $polynomial:expr, $sumcheck:expr) => { + expected_committed_opening($name, $polynomial, $sumcheck) + }; +} + +macro_rules! expected_openings { + ($($kind:ident $name:literal $polynomial:expr => $sumcheck:expr;)+) => { + [$(expected_opening!($kind, $name, $polynomial, $sumcheck)),+] + }; +} + +fn assert_core_opening_claim_evals_match( + stage: &str, + proof: &CoreProofForChecks, + evals: impl IntoIterator, + expected: impl IntoIterator, +) { + let evals = evals.into_iter().collect::>(); + let mut matched_claims = 0usize; + + for (name, opening_id) in expected { + let Some((_, core_claim)) = proof.opening_claims.0.get(&opening_id) else { + continue; + }; + let Some(value) = evals.get(name) else { + panic!("{stage} proof missing expected opening eval {name}"); + }; + matched_claims += 1; + assert_eq!( + *value, + Fr::from(*core_claim), + "{stage} opening claim mismatch for {name}", + ); + } + assert!( + matched_claims > 0, + "{stage} opening claim check matched no core public claims" + ); +} + +/// Assert Stage 2 opening-claim evals against jolt-core public proof claims. +pub(crate) fn assert_core_stage2_opening_claims_match_bolt( + proof: &CoreProofForChecks, + artifacts: &Stage2ExecutionArtifacts, +) { + let expected = expected_openings! { + v "stage2.product_virtual.uniskip.eval.UnivariateSkip" V::UnivariateSkip => S::SpartanProductVirtualization; + v "stage2.ram_read_write.eval.RamVal" V::RamVal => S::RamReadWriteChecking; + v "stage2.ram_read_write.eval.RamRa" V::RamRa => S::RamReadWriteChecking; + c "stage2.ram_read_write.eval.RamInc" C::RamInc => S::RamReadWriteChecking; + v "stage2.product_virtual.remainder.eval.LeftInstructionInput" V::LeftInstructionInput => S::SpartanProductVirtualization; + v "stage2.product_virtual.remainder.eval.RightInstructionInput" V::RightInstructionInput => S::SpartanProductVirtualization; + v "stage2.product_virtual.remainder.eval.OpFlagJump" V::OpFlags(CircuitFlags::Jump) => S::SpartanProductVirtualization; + v "stage2.product_virtual.remainder.eval.OpFlagWriteLookupOutputToRD" V::OpFlags(CircuitFlags::WriteLookupOutputToRD) => S::SpartanProductVirtualization; + v "stage2.product_virtual.remainder.eval.LookupOutput" V::LookupOutput => S::SpartanProductVirtualization; + v "stage2.product_virtual.remainder.eval.InstructionFlagBranch" V::InstructionFlags(InstructionFlags::Branch) => S::SpartanProductVirtualization; + v "stage2.product_virtual.remainder.eval.NextIsNoop" V::NextIsNoop => S::SpartanProductVirtualization; + v "stage2.product_virtual.remainder.eval.OpFlagVirtualInstruction" V::OpFlags(CircuitFlags::VirtualInstruction) => S::SpartanProductVirtualization; + v "stage2.instruction_lookup.claim_reduction.eval.LookupOutput" V::LookupOutput => S::InstructionClaimReduction; + v "stage2.instruction_lookup.claim_reduction.eval.LeftLookupOperand" V::LeftLookupOperand => S::InstructionClaimReduction; + v "stage2.instruction_lookup.claim_reduction.eval.RightLookupOperand" V::RightLookupOperand => S::InstructionClaimReduction; + v "stage2.instruction_lookup.claim_reduction.eval.LeftInstructionInput" V::LeftInstructionInput => S::InstructionClaimReduction; + v "stage2.instruction_lookup.claim_reduction.eval.RightInstructionInput" V::RightInstructionInput => S::InstructionClaimReduction; + v "stage2.ram_raf.eval.RamRa" V::RamRa => S::RamRafEvaluation; + v "stage2.ram_output.eval.RamValFinal" V::RamValFinal => S::RamOutputCheck; + }; + assert_core_opening_claim_evals_match( + "Stage 2", + proof, + artifacts + .sumchecks + .iter() + .flat_map(|output| output.evals.iter().map(|eval| (eval.name, eval.value))), + expected, + ); +} + +/// Assert Stage 3 opening-claim evals against jolt-core public proof claims. +pub(crate) fn assert_core_stage3_opening_claims_match_bolt( + proof: &CoreProofForChecks, + artifacts: &Stage3ExecutionArtifacts, +) { + let expected = expected_openings! { + v "stage3.spartan_shift.eval.UnexpandedPC" V::UnexpandedPC => S::SpartanShift; + v "stage3.spartan_shift.eval.PC" V::PC => S::SpartanShift; + v "stage3.spartan_shift.eval.OpFlagVirtualInstruction" V::OpFlags(CircuitFlags::VirtualInstruction) => S::SpartanShift; + v "stage3.spartan_shift.eval.OpFlagIsFirstInSequence" V::OpFlags(CircuitFlags::IsFirstInSequence) => S::SpartanShift; + v "stage3.spartan_shift.eval.InstructionFlagIsNoop" V::InstructionFlags(InstructionFlags::IsNoop) => S::SpartanShift; + v "stage3.instruction_input.eval.InstructionFlagLeftOperandIsRs1Value" V::InstructionFlags(InstructionFlags::LeftOperandIsRs1Value) => S::InstructionInputVirtualization; + v "stage3.instruction_input.eval.Rs1Value" V::Rs1Value => S::InstructionInputVirtualization; + v "stage3.instruction_input.eval.InstructionFlagLeftOperandIsPC" V::InstructionFlags(InstructionFlags::LeftOperandIsPC) => S::InstructionInputVirtualization; + v "stage3.instruction_input.eval.UnexpandedPC" V::UnexpandedPC => S::InstructionInputVirtualization; + v "stage3.instruction_input.eval.InstructionFlagRightOperandIsRs2Value" V::InstructionFlags(InstructionFlags::RightOperandIsRs2Value) => S::InstructionInputVirtualization; + v "stage3.instruction_input.eval.Rs2Value" V::Rs2Value => S::InstructionInputVirtualization; + v "stage3.instruction_input.eval.InstructionFlagRightOperandIsImm" V::InstructionFlags(InstructionFlags::RightOperandIsImm) => S::InstructionInputVirtualization; + v "stage3.instruction_input.eval.Imm" V::Imm => S::InstructionInputVirtualization; + v "stage3.registers_claim_reduction.eval.RdWriteValue" V::RdWriteValue => S::RegistersClaimReduction; + v "stage3.registers_claim_reduction.eval.Rs1Value" V::Rs1Value => S::RegistersClaimReduction; + v "stage3.registers_claim_reduction.eval.Rs2Value" V::Rs2Value => S::RegistersClaimReduction; + }; + assert_core_opening_claim_evals_match( + "Stage 3", + proof, + artifacts + .sumchecks + .iter() + .flat_map(|output| output.evals.iter().map(|eval| (eval.name, eval.value))), + expected, + ); +} + +fn stage6_oracle_index(oracle: &'static str, prefix: &'static str) -> Option { + oracle.strip_prefix(prefix)?.parse().ok() +} + +fn stage6_committed_polynomial(oracle: &'static str) -> Option { + if let Some(index) = stage6_oracle_index(oracle, "InstructionRa_") { + return Some(CommittedPolynomial::InstructionRa(index)); + } + if let Some(index) = stage6_oracle_index(oracle, "BytecodeRa_") { + return Some(CommittedPolynomial::BytecodeRa(index)); + } + if let Some(index) = stage6_oracle_index(oracle, "RamRa_") { + return Some(CommittedPolynomial::RamRa(index)); + } + match oracle { + "RamInc" => Some(CommittedPolynomial::RamInc), + "RdInc" => Some(CommittedPolynomial::RdInc), + _ => None, + } +} + +fn stage6_opening_claim_id(claim: &generated_stage6::Stage6OpeningClaimPlan) -> Option { + if claim + .symbol + .starts_with("stage6.bytecode_read_raf.opening.") + { + return stage6_committed_polynomial(claim.oracle) + .map(|polynomial| OpeningId::committed(polynomial, SumcheckId::BytecodeReadRaf)); + } + if claim.symbol.starts_with("stage6.booleanity.opening.") { + return stage6_committed_polynomial(claim.oracle) + .map(|polynomial| OpeningId::committed(polynomial, SumcheckId::Booleanity)); + } + if claim.symbol == "stage6.hamming_booleanity.opening.HammingWeight" { + return Some(OpeningId::virt( + VirtualPolynomial::RamHammingWeight, + SumcheckId::RamHammingBooleanity, + )); + } + if claim.symbol.starts_with("stage6.ram_ra_virtual.opening.") { + return stage6_committed_polynomial(claim.oracle) + .map(|polynomial| OpeningId::committed(polynomial, SumcheckId::RamRaVirtualization)); + } + if claim + .symbol + .starts_with("stage6.instruction_ra_virtual.opening.") + { + return stage6_committed_polynomial(claim.oracle).map(|polynomial| { + OpeningId::committed(polynomial, SumcheckId::InstructionRaVirtualization) + }); + } + match claim.symbol { + "stage6.inc_claim_reduction.opening.RamInc" => Some(OpeningId::committed( + CommittedPolynomial::RamInc, + SumcheckId::IncClaimReduction, + )), + "stage6.inc_claim_reduction.opening.RdInc" => Some(OpeningId::committed( + CommittedPolynomial::RdInc, + SumcheckId::IncClaimReduction, + )), + _ => None, + } +} + +/// Assert Stage 6 opening-claim evals against jolt-core public proof claims. +pub(crate) fn assert_core_stage6_opening_claims_match_bolt( + proof: &CoreProofForChecks, + stage6_proof: &JoltStageProof, +) { + let evals = stage6_proof + .sumchecks + .iter() + .flat_map(|output| output.evals.iter()) + .map(|eval| (eval.name, eval.value)) + .collect::>(); + + for claim in generated_stage6::STAGE6_OPENING_CLAIMS { + let Some(opening_id) = stage6_opening_claim_id(claim) else { + panic!( + "Stage 6 opening claim has no core mapping: {}", + claim.symbol + ); + }; + let Some(value) = evals.get(claim.eval_source) else { + panic!( + "Stage 6 proof missing eval {} for opening claim {}", + claim.eval_source, claim.symbol + ); + }; + let Some((_, core_claim)) = proof.opening_claims.0.get(&opening_id) else { + panic!("Stage 6 core opening claim missing for {}", claim.symbol); + }; + assert_eq!( + *value, + Fr::from(*core_claim), + "Stage 6 opening claim mismatch for {}", + claim.symbol, + ); + } + assert!( + !generated_stage6::STAGE6_OPENING_CLAIMS.is_empty(), + "Stage 6 opening claim check was empty" + ); +} + +/// Assert Stage 1 uni-skip proof coefficients match jolt-core. +pub fn assert_core_stage1_uniskip_proof_matches_bolt( + proof: &CoreProofForChecks, + output: &Stage1SumcheckOutput, +) { + assert_core_uniskip_coefficients_match( + "Stage 1", + &proof.stage1_uni_skip_first_round_proof, + &output.proof.round_polynomials, + ); +} + +/// Assert Stage 2 uni-skip proof coefficients match jolt-core. +pub fn assert_core_stage2_uniskip_proof_matches_bolt( + proof: &CoreProofForChecks, + output: &jolt_kernels::stage2::Stage2SumcheckOutput, +) { + assert_core_uniskip_coefficients_match( + "Stage 2", + &proof.stage2_uni_skip_first_round_proof, + &output.proof.round_polynomials, + ); +} + +/// Assert Stage 2 compressed round polynomials match jolt-core. +pub(crate) fn assert_core_stage2_sumcheck_proof_matches_bolt( + proof: &CoreProofForChecks, + output: &jolt_kernels::stage2::Stage2SumcheckOutput, +) { + assert_core_compressed_sumcheck_match!("Stage 2", &proof.stage2_sumcheck_proof, output); +} + +/// Assert Stage 3 compressed round polynomials match jolt-core. +pub(crate) fn assert_core_stage3_sumcheck_proof_matches_bolt( + proof: &CoreProofForChecks, + output: &jolt_kernels::stage3::Stage3SumcheckOutput, +) { + assert_core_compressed_sumcheck_match!("Stage 3", &proof.stage3_sumcheck_proof, output); +} + +/// Assert Stage 6 compressed round polynomials match jolt-core. +pub(crate) fn assert_core_stage6_sumcheck_proof_matches_bolt( + proof: &CoreProofForChecks, + output: &JoltSumcheckOutput, +) { + assert_core_compressed_sumcheck_match!("Stage 6", &proof.stage6_sumcheck_proof, output); +} + +pub(crate) fn assert_canonical_stage_artifacts_match( + stage: &str, + expected: StageArtifacts, + actual: StageArtifacts, +) { + assert_eq!(expected, actual, "{stage} artifact mismatch"); +} + +pub(crate) fn assert_equivalence_run_artifacts_match( + label: &str, + expected: &EquivalenceRun, + actual: &EquivalenceRun, +) { + assert_eq!( + expected.commitments, actual.commitments, + "{label} commitment trace mismatch" + ); + assert_eq!(expected.stages, actual.stages, "{label} stage mismatch"); + assert_eq!( + expected.opening_claims, actual.opening_claims, + "{label} opening-claim mismatch" + ); + assert_eq!( + expected.verifier_result, actual.verifier_result, + "{label} verifier result mismatch" + ); +} + +macro_rules! define_stage_artifacts_match { + ($fn_name:ident, $stage:literal, $expected_ty:ty, $actual_ty:ty, $expected_adapter:path, $actual_adapter:path) => { + pub(crate) fn $fn_name(expected: &$expected_ty, actual: &$actual_ty) { + assert_canonical_stage_artifacts_match( + $stage, + $expected_adapter(expected), + $actual_adapter(actual), + ); + } + }; +} + +define_stage_artifacts_match!( + assert_stage5_artifacts_match, + "Stage 5", + JoltStageProof, + JoltStageProof, + canonical_generated_stage5_proof, + canonical_generated_stage5_proof +); +define_stage_artifacts_match!( + assert_stage6_artifacts_match, + "Stage 6", + JoltStageProof, + JoltStageExecutionArtifacts, + canonical_generated_stage6_proof, + canonical_generated_stage6_execution_artifacts +); +define_stage_artifacts_match!( + assert_stage7_artifacts_match, + "Stage 7", + JoltStageProof, + JoltStageExecutionArtifacts, + canonical_generated_stage7_proof, + canonical_generated_stage7_execution_artifacts +); diff --git a/crates/jolt-equivalence/src/commitment_oracle.rs b/crates/jolt-equivalence/src/commitment_oracle.rs new file mode 100644 index 0000000000..33f50f0554 --- /dev/null +++ b/crates/jolt-equivalence/src/commitment_oracle.rs @@ -0,0 +1,419 @@ +//! Commitment-phase oracle runner for Bolt/Jolt equivalence checks. +//! +//! This module owns the thin commitment bridge used by tests: run the +//! generated real-trace commitment phase, keep a small synthetic transcript +//! bridge for CPU-plan ordering tests, and expose transcript traces in the +//! canonical equivalence shape. + +#![expect( + clippy::expect_used, + clippy::panic, + reason = "commitment oracle gates should fail fast on malformed generated artifacts" +)] + +use std::borrow::Cow; + +use ark_serialize::CanonicalSerialize; +use bolt::protocols::jolt::CommitmentCpuProgram; +use common::jolt_device::JoltDevice; +use jolt_dory::{DoryCommitment, DoryProverSetup, DoryScheme}; +use jolt_field::Fr; +use jolt_prover::stages::commitment as generated_commitment; +use jolt_transcript::{Label, LabelWithCount, Transcript, U64Word}; +use jolt_verifier::stages::commitment as generated_verifier_commitment; +use jolt_witness::{ + commitment_trace_sources, optional_oracle_data, CommitmentTraceSources, CycleInput, +}; + +use crate::artifacts::{ + ArtifactSource, CommitmentArtifact, CommitmentTrace, EquivalenceRun, TranscriptTrace, +}; +use crate::checkpoint::{CheckpointTranscript, TranscriptEvent}; +use crate::core_conversion::{commitment_to_ark, CoreCommitment}; +use crate::plan_adapters::{ + leak_generated_commitment_prover_program, leak_generated_commitment_verifier_program, +}; + +const TRANSCRIPT_LABEL: &[u8] = b"Jolt"; + +pub type BoltTranscript = CheckpointTranscript>; + +#[derive(Clone, Debug)] +pub struct CommitmentRecord { + pub artifact: String, +} + +#[derive(Clone, Debug)] +pub struct BoltCommitmentTrace { + pub commitments: Vec>, + pub records: Vec, + pub log: Vec, +} + +impl BoltCommitmentTrace { + pub fn commitment_trace(&self) -> CommitmentTrace { + CommitmentTrace { + commitments: self + .records + .iter() + .zip(&self.commitments) + .map(|(record, commitment)| CommitmentArtifact { + label: record.artifact.clone(), + artifact: record.artifact.clone(), + bytes: commitment.as_ref().map(bolt_commitment_bytes), + }) + .collect(), + } + } + + pub fn committed_prefix(&self, len: usize) -> CommitmentTrace { + CommitmentTrace { + commitments: self + .records + .iter() + .zip(&self.commitments) + .filter_map(|(record, commitment)| { + commitment.as_ref().map(|commitment| CommitmentArtifact { + label: record.artifact.clone(), + artifact: record.artifact.clone(), + bytes: Some(bolt_commitment_bytes(commitment)), + }) + }) + .take(len) + .collect(), + } + } + + pub fn equivalence_run(&self, source: ArtifactSource) -> EquivalenceRun { + let mut run = EquivalenceRun::new(source); + run.commitments = self.commitment_trace(); + run.transcript = TranscriptTrace { + events: self.log.clone(), + }; + run + } +} + +pub fn core_commitment_trace(commitments: &[CoreCommitment], artifact: &str) -> CommitmentTrace { + CommitmentTrace { + commitments: commitments + .iter() + .map(|commitment| CommitmentArtifact { + label: artifact.to_owned(), + artifact: artifact.to_owned(), + bytes: Some(core_commitment_bytes(commitment)), + }) + .collect(), + } +} + +macro_rules! generated_commitment_trace_fns { + ($trace_fn:ident, $artifacts_to_trace_fn:ident, $artifacts:ty) => { + pub(crate) fn $trace_fn(artifacts: &$artifacts) -> CommitmentTrace { + CommitmentTrace { + commitments: artifacts + .records + .iter() + .zip(&artifacts.commitments) + .map(|(record, commitment)| CommitmentArtifact { + label: record.artifact.to_owned(), + artifact: record.artifact.to_owned(), + bytes: commitment.as_ref().map(bolt_commitment_bytes), + }) + .collect(), + } + } + + fn $artifacts_to_trace_fn( + artifacts: &$artifacts, + log: Vec, + ) -> BoltCommitmentTrace { + BoltCommitmentTrace { + commitments: artifacts.commitments.clone(), + records: artifacts + .records + .iter() + .map(|record| CommitmentRecord { + artifact: record.artifact.to_owned(), + }) + .collect(), + log, + } + } + }; +} + +generated_commitment_trace_fns!( + generated_commitment_trace, + generated_prover_commitment_artifacts_to_trace, + generated_commitment::CommitmentArtifacts +); +generated_commitment_trace_fns!( + generated_verifier_commitment_trace, + generated_verifier_commitment_artifacts_to_trace, + generated_verifier_commitment::CommitmentArtifacts +); + +fn bolt_commitment_bytes(commitment: &DoryCommitment) -> Vec { + core_commitment_bytes(&commitment_to_ark(commitment)) +} + +fn core_commitment_bytes(commitment: &CoreCommitment) -> Vec { + let mut bytes = Vec::new(); + commitment + .serialize_uncompressed(&mut bytes) + .expect("commitment serialization"); + bytes +} + +pub trait BoltPreambleSource { + fn program_io(&self) -> &JoltDevice; + fn preprocessing_digest(&self) -> [u8; 32]; + fn ram_k(&self) -> u64; + fn trace_length(&self) -> u64; + fn entry_address(&self) -> u64; + fn ram_rw_phase1_num_rounds(&self) -> u64; + fn ram_rw_phase2_num_rounds(&self) -> u64; + fn registers_rw_phase1_num_rounds(&self) -> u64; + fn registers_rw_phase2_num_rounds(&self) -> u64; + fn log_k_chunk(&self) -> u64; + fn lookups_ra_virtual_log_k_chunk(&self) -> u64; + fn dory_layout(&self) -> u64; +} + +fn append_bolt_preamble(transcript: &mut T, preamble: &P) +where + T: Transcript, + P: BoltPreambleSource, +{ + let program_io = preamble.program_io(); + let preprocessing_digest = preamble.preprocessing_digest(); + append_bytes(transcript, b"preprocessing_digest", &preprocessing_digest); + append_u64( + transcript, + b"max_input_size", + program_io.memory_layout.max_input_size, + ); + append_u64( + transcript, + b"max_output_size", + program_io.memory_layout.max_output_size, + ); + append_u64(transcript, b"heap_size", program_io.memory_layout.heap_size); + append_bytes(transcript, b"inputs", &program_io.inputs); + append_bytes(transcript, b"outputs", &program_io.outputs); + append_u64(transcript, b"panic", program_io.panic as u64); + append_u64(transcript, b"ram_K", preamble.ram_k()); + append_u64(transcript, b"trace_length", preamble.trace_length()); + append_u64(transcript, b"entry_address", preamble.entry_address()); + append_u64( + transcript, + b"ram_rw_phase1_num_rounds", + preamble.ram_rw_phase1_num_rounds(), + ); + append_u64( + transcript, + b"ram_rw_phase2_num_rounds", + preamble.ram_rw_phase2_num_rounds(), + ); + append_u64( + transcript, + b"registers_rw_phase1_num_rounds", + preamble.registers_rw_phase1_num_rounds(), + ); + append_u64( + transcript, + b"registers_rw_phase2_num_rounds", + preamble.registers_rw_phase2_num_rounds(), + ); + append_u64(transcript, b"log_k_chunk", preamble.log_k_chunk()); + append_u64( + transcript, + b"lookups_ra_virtual_log_k_chunk", + preamble.lookups_ra_virtual_log_k_chunk(), + ); + append_u64(transcript, b"dory_layout", preamble.dory_layout()); +} + +pub(crate) fn transcript_with_bolt_preamble

(preamble: &P) -> BoltTranscript +where + P: BoltPreambleSource, +{ + let mut transcript = BoltTranscript::new(TRANSCRIPT_LABEL); + append_bolt_preamble(&mut transcript, preamble); + transcript +} + +pub fn transcript_with_bolt_commitment_trace

( + preamble: &P, + trace: &BoltCommitmentTrace, +) -> BoltTranscript +where + P: BoltPreambleSource, +{ + let mut transcript = transcript_with_bolt_preamble(preamble); + append_bolt_commitment_trace(&mut transcript, trace); + transcript +} + +fn append_u64(transcript: &mut T, label: &'static [u8], value: u64) +where + T: Transcript, +{ + transcript.append(&Label(label)); + transcript.append(&U64Word(value)); +} + +fn append_bytes(transcript: &mut T, label: &'static [u8], bytes: &[u8]) +where + T: Transcript, +{ + transcript.append(&LabelWithCount(label, bytes.len() as u64)); + transcript.append_bytes(bytes); +} + +#[derive(Clone, Debug)] +pub(crate) struct GeneratedCommitmentInputStorage { + sources: CommitmentTraceSources, +} + +impl GeneratedCommitmentInputStorage { + pub(crate) fn from_cycles(cycle_inputs: &[CycleInput]) -> Self { + Self { + sources: commitment_trace_sources(cycle_inputs), + } + } + + pub(crate) fn sparse_inputs(&self) -> generated_commitment::SparseCommitmentInputs<'_> { + generated_commitment::SparseCommitmentInputs::new( + generated_commitment::CommitmentOracleInputs::from_trace_sources( + &self.sources, + None, + None, + ), + ) + } +} + +pub fn run_generated_bolt_commitment_pair_with_cpu_programs( + prover_program: &CommitmentCpuProgram, + verifier_program: &CommitmentCpuProgram, + setup: &DoryProverSetup, + cycle_inputs: &[CycleInput], +) -> (BoltCommitmentTrace, BoltCommitmentTrace) { + run_generated_bolt_commitment_pair_with_cycles( + leak_generated_commitment_prover_program(prover_program), + leak_generated_commitment_verifier_program(verifier_program), + setup, + cycle_inputs, + ) +} + +fn run_generated_synthetic_bolt_commitment_pair( + prover_program: &'static generated_commitment::CommitmentProverProgramPlan, + verifier_program: &'static generated_verifier_commitment::CommitmentVerifierProgramPlan, +) -> (BoltCommitmentTrace, BoltCommitmentTrace) { + let setup = DoryScheme::setup_prover(max_generated_num_vars(prover_program)); + let mut inputs = SyntheticCommitmentInputs; + let prover_trace = run_generated_bolt_commitment_prover(prover_program, &setup, &mut inputs); + let verifier_trace = + run_generated_bolt_commitment_verifier(verifier_program, &prover_trace.commitments); + (prover_trace, verifier_trace) +} + +pub fn run_generated_synthetic_bolt_commitment_pair_with_cpu_programs( + prover_program: &CommitmentCpuProgram, + verifier_program: &CommitmentCpuProgram, +) -> (BoltCommitmentTrace, BoltCommitmentTrace) { + run_generated_synthetic_bolt_commitment_pair( + leak_generated_commitment_prover_program(prover_program), + leak_generated_commitment_verifier_program(verifier_program), + ) +} + +pub(crate) fn run_generated_bolt_commitment_pair_with_cycles( + prover_program: &'static generated_commitment::CommitmentProverProgramPlan, + verifier_program: &'static generated_verifier_commitment::CommitmentVerifierProgramPlan, + setup: &DoryProverSetup, + cycle_inputs: &[CycleInput], +) -> (BoltCommitmentTrace, BoltCommitmentTrace) { + let storage = GeneratedCommitmentInputStorage::from_cycles(cycle_inputs); + let mut inputs = storage.sparse_inputs(); + let prover_trace = run_generated_bolt_commitment_prover(prover_program, setup, &mut inputs); + let verifier_trace = + run_generated_bolt_commitment_verifier(verifier_program, &prover_trace.commitments); + (prover_trace, verifier_trace) +} + +fn run_generated_bolt_commitment_prover( + program: &'static generated_commitment::CommitmentProverProgramPlan, + setup: &DoryProverSetup, + inputs: &mut I, +) -> BoltCommitmentTrace +where + I: generated_commitment::CommitmentInputProvider, +{ + let mut transcript = BoltTranscript::new(TRANSCRIPT_LABEL); + let artifacts = generated_commitment::prove_commitment_phase_with_program( + program, + inputs, + setup, + &mut transcript, + ) + .expect("generated Bolt commitment prover succeeds"); + generated_prover_commitment_artifacts_to_trace(&artifacts, transcript.log().to_vec()) +} + +fn run_generated_bolt_commitment_verifier( + program: &'static generated_verifier_commitment::CommitmentVerifierProgramPlan, + proof_commitments: &[Option], +) -> BoltCommitmentTrace { + let mut transcript = BoltTranscript::new(TRANSCRIPT_LABEL); + let artifacts = generated_verifier_commitment::verify_commitment_phase_with_program( + program, + proof_commitments, + &mut transcript, + ) + .expect("generated Bolt commitment verifier succeeds"); + generated_verifier_commitment_artifacts_to_trace(&artifacts, transcript.log().to_vec()) +} + +fn append_bolt_commitment_trace(transcript: &mut T, trace: &BoltCommitmentTrace) +where + T: Transcript, +{ + for event in &trace.log { + match event { + TranscriptEvent::Append { bytes, .. } => transcript.append_bytes(bytes), + TranscriptEvent::Squeeze { .. } => { + panic!("commitment transcript trace unexpectedly contains a squeeze") + } + } + } +} + +struct SyntheticCommitmentInputs; + +impl generated_commitment::CommitmentInputProvider for SyntheticCommitmentInputs { + fn materialize(&mut self, _oracle: &'static str) -> Option> { + None + } + + fn materialize_with_num_vars( + &mut self, + oracle: &'static str, + num_vars: usize, + ) -> Option> { + optional_oracle_data(oracle, num_vars).map(Cow::Owned) + } +} + +fn max_generated_num_vars(program: &generated_commitment::CommitmentProverProgramPlan) -> usize { + program + .batch_plans + .iter() + .map(|plan| plan.num_vars) + .chain(program.optional_plans.iter().map(|plan| plan.num_vars)) + .max() + .unwrap_or(0) +} diff --git a/crates/jolt-equivalence/src/core_conversion.rs b/crates/jolt-equivalence/src/core_conversion.rs new file mode 100644 index 0000000000..4daf754203 --- /dev/null +++ b/crates/jolt-equivalence/src/core_conversion.rs @@ -0,0 +1,372 @@ +//! Core proof conversion helpers for Bolt equivalence tests. +//! +//! The helpers here normalize field elements, commitments, and sumcheck +//! proofs into jolt-core shapes so Bolt equivalence tests can compare +//! generated artifacts against the reference implementation. +//! +#![expect( + clippy::expect_used, + clippy::panic, + clippy::too_many_arguments, + reason = "core proof adapters are test-oracle bridges and fail fast on malformed artifacts" +)] + +use ark_bn254::Fr as ArkFr; +use ark_serialize::CanonicalSerialize; +use bolt::protocols::jolt::TranscriptStep; +use jolt_core::curve::Bn254Curve; +use jolt_core::poly::commitment::commitment_scheme::CommitmentScheme; +use jolt_core::poly::commitment::dory::DoryCommitmentScheme; +use jolt_core::poly::unipoly::UniPoly; +use jolt_core::subprotocols::sumcheck::SumcheckInstanceProof; +use jolt_core::subprotocols::univariate_skip::{ + UniSkipFirstRoundProof, UniSkipFirstRoundProofVariant, +}; +use jolt_core::transcripts::{Blake2bTranscript, Transcript as _}; +use jolt_core::zkvm::proof_serialization::{Claims, JoltProof as CoreJoltProof}; +use jolt_field::Fr as NewFr; +use jolt_poly::UnivariatePoly; +use jolt_verifier::JoltStageProof; + +use crate::TranscriptEvent; + +pub type CoreCommitment = ::Commitment; +pub type CoreProofForConversion = + CoreJoltProof; + +/// Convert `NewFr` → `ArkFr`. Both are the BN254 scalar field; this is +/// a representation-only cast. +pub(crate) fn to_ark(f: NewFr) -> ArkFr { + f.into() +} + +/// Convert a modular `UnivariatePoly` into a jolt-core +/// `CompressedUniPoly`. `CompressedUniPoly` stores `[c0, c2, c3, +/// ...]` (linear term `c1` omitted; verifier reconstructs from `s(0) + s(1)`). +fn to_compressed_uni_poly( + poly: &UnivariatePoly, +) -> jolt_core::poly::unipoly::CompressedUniPoly { + let coeffs = poly.coefficients(); + assert!( + coeffs.len() >= 2, + "round poly must have at least 2 coefficients" + ); + let mut compressed = Vec::with_capacity(coeffs.len() - 1); + compressed.push(to_ark(coeffs[0])); + for c in &coeffs[2..] { + compressed.push(to_ark(*c)); + } + jolt_core::poly::unipoly::CompressedUniPoly { + coeffs_except_linear_term: compressed, + } +} + +fn to_core_sumcheck_proof( + round_polys: &[UnivariatePoly], +) -> SumcheckInstanceProof { + let compressed: Vec<_> = round_polys.iter().map(to_compressed_uni_poly).collect(); + SumcheckInstanceProof::Clear(jolt_core::subprotocols::sumcheck::ClearSumcheckProof::new( + compressed, + )) +} + +fn to_core_uniskip_proof_from_round_polys( + round_polys: &[UnivariatePoly], +) -> UniSkipFirstRoundProofVariant { + assert_eq!(round_polys.len(), 1); + let coefficients = round_polys[0] + .coefficients() + .iter() + .copied() + .map(to_ark) + .collect(); + UniSkipFirstRoundProofVariant::Standard(UniSkipFirstRoundProof::new(UniPoly::from_coeff( + coefficients, + ))) +} + +fn to_core_uniskip_proof( + output: &jolt_kernels::stage1::Stage1SumcheckOutput, +) -> UniSkipFirstRoundProofVariant { + to_core_uniskip_proof_from_round_polys(&output.proof.round_polynomials) +} + +fn to_core_stage2_uniskip_proof( + output: &jolt_kernels::stage2::Stage2SumcheckOutput, +) -> UniSkipFirstRoundProofVariant { + to_core_uniskip_proof_from_round_polys(&output.proof.round_polynomials) +} + +/// Clone a jolt-core proof without depending on private verifier state. +pub(crate) fn clone_core_proof(proof: &CoreProofForConversion) -> CoreProofForConversion { + CoreJoltProof { + commitments: proof.commitments.clone(), + stage1_uni_skip_first_round_proof: proof.stage1_uni_skip_first_round_proof.clone(), + stage1_sumcheck_proof: proof.stage1_sumcheck_proof.clone(), + stage2_uni_skip_first_round_proof: proof.stage2_uni_skip_first_round_proof.clone(), + stage2_sumcheck_proof: proof.stage2_sumcheck_proof.clone(), + stage3_sumcheck_proof: proof.stage3_sumcheck_proof.clone(), + stage4_sumcheck_proof: proof.stage4_sumcheck_proof.clone(), + stage5_sumcheck_proof: proof.stage5_sumcheck_proof.clone(), + stage6_sumcheck_proof: proof.stage6_sumcheck_proof.clone(), + stage7_sumcheck_proof: proof.stage7_sumcheck_proof.clone(), + joint_opening_proof: proof.joint_opening_proof.clone(), + untrusted_advice_commitment: proof.untrusted_advice_commitment, + opening_claims: Claims(proof.opening_claims.0.clone()), + trace_length: proof.trace_length, + ram_K: proof.ram_K, + rw_config: proof.rw_config.clone(), + one_hot_config: proof.one_hot_config.clone(), + dory_layout: proof.dory_layout, + } +} + +pub(crate) fn core_proof_with_bolt_stage1( + base: &CoreProofForConversion, + artifacts: &jolt_kernels::stage1::Stage1ExecutionArtifacts, +) -> CoreProofForConversion { + let mut proof = clone_core_proof(base); + proof.stage1_uni_skip_first_round_proof = to_core_uniskip_proof(&artifacts.sumchecks[0]); + proof.stage1_sumcheck_proof = + to_core_sumcheck_proof(&artifacts.sumchecks[1].proof.round_polynomials); + proof +} + +pub(crate) fn core_proof_with_bolt_stage2( + base: &CoreProofForConversion, + stage1_artifacts: &jolt_kernels::stage1::Stage1ExecutionArtifacts, + stage2_artifacts: &jolt_kernels::stage2::Stage2ExecutionArtifacts, +) -> CoreProofForConversion { + let mut proof = core_proof_with_bolt_stage1(base, stage1_artifacts); + proof.stage2_uni_skip_first_round_proof = + to_core_stage2_uniskip_proof(&stage2_artifacts.sumchecks[0]); + proof.stage2_sumcheck_proof = + to_core_sumcheck_proof(&stage2_artifacts.sumchecks[1].proof.round_polynomials); + proof +} + +pub(crate) fn core_proof_with_bolt_stage3( + base: &CoreProofForConversion, + stage1_artifacts: &jolt_kernels::stage1::Stage1ExecutionArtifacts, + stage2_artifacts: &jolt_kernels::stage2::Stage2ExecutionArtifacts, + stage3_artifacts: &jolt_kernels::stage3::Stage3ExecutionArtifacts, +) -> CoreProofForConversion { + let mut proof = core_proof_with_bolt_stage2(base, stage1_artifacts, stage2_artifacts); + proof.stage3_sumcheck_proof = + to_core_sumcheck_proof(&stage3_artifacts.sumchecks[0].proof.round_polynomials); + proof +} + +pub(crate) fn core_proof_with_bolt_stage4( + base: &CoreProofForConversion, + stage1_artifacts: &jolt_kernels::stage1::Stage1ExecutionArtifacts, + stage2_artifacts: &jolt_kernels::stage2::Stage2ExecutionArtifacts, + stage3_artifacts: &jolt_kernels::stage3::Stage3ExecutionArtifacts, + stage4_artifacts: &jolt_kernels::stage4::Stage4ExecutionArtifacts, +) -> CoreProofForConversion { + let mut proof = + core_proof_with_bolt_stage3(base, stage1_artifacts, stage2_artifacts, stage3_artifacts); + proof.stage4_sumcheck_proof = + to_core_sumcheck_proof(&stage4_artifacts.sumchecks[0].proof.round_polynomials); + proof +} + +pub(crate) fn core_proof_with_bolt_stage5( + base: &CoreProofForConversion, + stage1_artifacts: &jolt_kernels::stage1::Stage1ExecutionArtifacts, + stage2_artifacts: &jolt_kernels::stage2::Stage2ExecutionArtifacts, + stage3_artifacts: &jolt_kernels::stage3::Stage3ExecutionArtifacts, + stage4_artifacts: &jolt_kernels::stage4::Stage4ExecutionArtifacts, + stage5_proof: &JoltStageProof, +) -> CoreProofForConversion { + let mut proof = core_proof_with_bolt_stage4( + base, + stage1_artifacts, + stage2_artifacts, + stage3_artifacts, + stage4_artifacts, + ); + proof.stage5_sumcheck_proof = + to_core_sumcheck_proof(&stage5_proof.sumchecks[0].proof.round_polynomials); + proof +} + +pub(crate) fn core_proof_with_bolt_stage6( + base: &CoreProofForConversion, + stage1_artifacts: &jolt_kernels::stage1::Stage1ExecutionArtifacts, + stage2_artifacts: &jolt_kernels::stage2::Stage2ExecutionArtifacts, + stage3_artifacts: &jolt_kernels::stage3::Stage3ExecutionArtifacts, + stage4_artifacts: &jolt_kernels::stage4::Stage4ExecutionArtifacts, + stage5_proof: &JoltStageProof, + stage6_proof: &JoltStageProof, +) -> CoreProofForConversion { + let mut proof = core_proof_with_bolt_stage5( + base, + stage1_artifacts, + stage2_artifacts, + stage3_artifacts, + stage4_artifacts, + stage5_proof, + ); + proof.stage6_sumcheck_proof = + to_core_sumcheck_proof(&stage6_proof.sumchecks[0].proof.round_polynomials); + proof +} + +pub(crate) fn core_proof_with_bolt_stage7( + base: &CoreProofForConversion, + stage1_artifacts: &jolt_kernels::stage1::Stage1ExecutionArtifacts, + stage2_artifacts: &jolt_kernels::stage2::Stage2ExecutionArtifacts, + stage3_artifacts: &jolt_kernels::stage3::Stage3ExecutionArtifacts, + stage4_artifacts: &jolt_kernels::stage4::Stage4ExecutionArtifacts, + stage5_proof: &JoltStageProof, + stage6_proof: &JoltStageProof, + stage7_proof: &JoltStageProof, +) -> CoreProofForConversion { + let mut proof = core_proof_with_bolt_stage6( + base, + stage1_artifacts, + stage2_artifacts, + stage3_artifacts, + stage4_artifacts, + stage5_proof, + stage6_proof, + ); + proof.stage7_sumcheck_proof = + to_core_sumcheck_proof(&stage7_proof.sumchecks[0].proof.round_polynomials); + proof +} + +pub(crate) fn core_proof_with_bolt_evaluation( + base: &CoreProofForConversion, + evaluation: &jolt_verifier::JoltEvaluationProof, +) -> CoreProofForConversion { + let mut proof = clone_core_proof(base); + proof.joint_opening_proof = evaluation.joint_opening_proof.0.clone(); + proof +} + +pub(crate) fn core_proof_with_full_bolt( + base: &CoreProofForConversion, + proof: &jolt_verifier::JoltProof, + artifacts: &jolt_prover::JoltProverArtifacts, +) -> CoreProofForConversion { + let stage5_proof = jolt_prover::stage5_proof(&artifacts.stage5); + let stage6_proof = jolt_prover::stage6_proof(&artifacts.stage6); + let stage7_proof = jolt_prover::stage7_proof(&artifacts.stage7); + let mut core_proof = core_proof_with_bolt_stage7( + base, + &artifacts.stage1_outer, + &artifacts.stage2, + &artifacts.stage3, + &artifacts.stage4, + &stage5_proof, + &stage6_proof, + &stage7_proof, + ); + core_proof.commitments = proof + .commitments + .iter() + .filter_map(|commitment| commitment.as_ref().map(commitment_to_ark)) + .collect(); + core_proof.joint_opening_proof = proof + .evaluation + .as_ref() + .expect("Bolt proof includes evaluation proof") + .joint_opening_proof + .0 + .clone(); + core_proof +} + +pub fn core_commitment_log<'a>( + records: impl IntoIterator)>, + transcript_steps: &[TranscriptStep], +) -> Vec { + let records = records.into_iter().collect::>(); + let mut transcript = Blake2bTranscript::new(b"Jolt"); + let mut events = Vec::new(); + + for step in transcript_steps { + let mut appended = false; + for (artifact, commitment) in &records { + if *artifact != step.source { + continue; + } + if let Some(commitment) = commitment { + let core_commitment = commitment_to_ark(commitment); + let label = static_transcript_label(&step.label); + for bytes in core_append_serializable_bytes(label, &core_commitment) { + transcript.raw_append_bytes(&bytes); + events.push(TranscriptEvent::Append { + bytes, + state_after: transcript.state, + }); + } + appended = true; + } + } + assert!(step.optional || appended, "missing core transcript source"); + } + + events +} + +pub fn core_commitments_transcript_log( + commitments: &[CoreCommitment], + transcript_steps: &[TranscriptStep], +) -> Vec { + let mut transcript = Blake2bTranscript::new(b"Jolt"); + let mut events = Vec::new(); + + for step in transcript_steps { + if step.source != "jolt.main_witness_commitments" { + assert!(step.optional, "unexpected non-main commitment source"); + continue; + } + for commitment in commitments { + let label = static_transcript_label(&step.label); + for bytes in core_append_serializable_bytes(label, commitment) { + transcript.raw_append_bytes(&bytes); + events.push(TranscriptEvent::Append { + bytes, + state_after: transcript.state, + }); + } + } + } + + events +} + +fn core_append_serializable_bytes( + label: &'static [u8], + data: &T, +) -> Vec> { + let mut payload = Vec::new(); + data.serialize_uncompressed(&mut payload) + .expect("core commitment serialization"); + let mut header = [0u8; 32]; + header[..label.len()].copy_from_slice(label); + let len = (payload.len() as u64).to_be_bytes(); + header[24..].copy_from_slice(&len); + payload.reverse(); + vec![header.to_vec(), payload] +} + +fn static_transcript_label(label: &str) -> &'static [u8] { + match label { + "commitment" => b"commitment", + "untrusted_advice" => b"untrusted_advice", + "trusted_advice" => b"trusted_advice", + _ => panic!("unsupported transcript label `{label}`"), + } +} + +/// Convert a jolt-dory `DoryCommitment` to jolt-core's `ArkGT` shape. +/// +/// Both are repr(transparent) wrappers over the same `Fq12` type. +pub(crate) fn commitment_to_ark(c: &jolt_dory::types::DoryCommitment) -> CoreCommitment { + // SAFETY: Bn254GT and ArkGT are both repr(transparent) over Fq12. + unsafe { std::mem::transmute_copy(&c.0) } +} diff --git a/crates/jolt-equivalence/src/core_oracle.rs b/crates/jolt-equivalence/src/core_oracle.rs new file mode 100644 index 0000000000..d04a91392e --- /dev/null +++ b/crates/jolt-equivalence/src/core_oracle.rs @@ -0,0 +1,518 @@ +//! Core-side public oracle fixture and acceptance checks for equivalence gates. +//! +//! This module runs jolt-core as the temporary reference oracle and exposes the +//! public data needed by the Bolt equivalence tests. It does not patch expected +//! values to compensate for Bolt mismatches. + +#![expect( + clippy::expect_used, + clippy::too_many_arguments, + reason = "oracle fixtures should fail fast when reference setup is malformed" +)] + +use std::time::Instant; + +use ark_serialize::{CanonicalSerialize, Compress}; +use bolt::protocols::jolt::JoltProtocolParams; +use common::constants::{RAM_START_ADDRESS, XLEN}; +use common::jolt_device::JoltDevice; +use jolt_core::curve::Bn254Curve; +use jolt_core::host; +use jolt_core::poly::commitment::commitment_scheme::CommitmentScheme as CoreCommitmentScheme; +use jolt_core::poly::commitment::dory::DoryCommitmentScheme; +use jolt_core::transcripts::Blake2bTranscript as CoreBlake2bTranscript; +use jolt_core::zkvm::instruction::InstructionLookup; +use jolt_core::zkvm::lookup_table::LookupTables as CoreLookupTables; +use jolt_core::zkvm::proof_serialization::JoltProof as CoreJoltProof; +use jolt_core::zkvm::prover::{JoltCpuProver, JoltProverPreprocessing}; +use jolt_core::zkvm::ram::remap_address; +use jolt_core::zkvm::verifier::{JoltSharedPreprocessing, JoltVerifier, JoltVerifierPreprocessing}; +use jolt_dory::DoryProverSetup; +use jolt_field::Fr; +use jolt_kernels::stage1::{ + Stage1ExecutionArtifacts, Stage1OuterR1csData, Stage1OuterRv64Data, Stage1Rv64Cycle, +}; +use jolt_kernels::stage2::{ + Stage2ExecutionArtifacts, Stage2InstructionLookupCycle, Stage2ProductVirtualCycle, + Stage2RamAccess, Stage2RamData, Stage2RamOutputLayout, +}; +use jolt_kernels::stage3::{Stage3Cycle, Stage3ExecutionArtifacts}; +use jolt_kernels::stage4::{Stage4ExecutionArtifacts, Stage4RegisterAccess}; +use jolt_kernels::stage6::Stage6WitnessParams; +use jolt_kernels::trace::{ + stage1_rv64_cycles, stage2_instruction_lookup_cycles, stage2_product_virtual_cycles, + stage2_ram_accesses, stage3_cycles, stage4_register_accesses, stage5_lookup_trace, + stage6_bytecode_entries, +}; +use jolt_r1cs::{constraints::rv64, R1csKey}; +use jolt_trace::{extract_trace, BytecodePreprocessing}; +use jolt_verifier::JoltStageProof; +use jolt_witness::{CycleInput, Stage6BytecodeEntry}; +use strum::EnumCount; + +use crate::checks::{ + assert_core_stage1_uniskip_proof_matches_bolt, assert_core_stage2_opening_claims_match_bolt, + assert_core_stage2_sumcheck_proof_matches_bolt, assert_core_stage3_opening_claims_match_bolt, + assert_core_stage3_sumcheck_proof_matches_bolt, assert_core_stage6_opening_claims_match_bolt, + assert_core_stage6_sumcheck_proof_matches_bolt, +}; +use crate::commitment_oracle::BoltPreambleSource; +use crate::core_conversion::{ + clone_core_proof, core_proof_with_bolt_evaluation, core_proof_with_bolt_stage1, + core_proof_with_bolt_stage2, core_proof_with_bolt_stage3, core_proof_with_bolt_stage4, + core_proof_with_bolt_stage5, core_proof_with_bolt_stage6, core_proof_with_bolt_stage7, + core_proof_with_full_bolt, +}; +use jolt_profiling::{observed_span_names_with_prefix, time_it, PeakRssSampler, PerfMetrics}; + +pub type CoreFr = ark_bn254::Fr; +pub type CoreCommitment = ::Commitment; +type CoreProver<'a> = + JoltCpuProver<'a, CoreFr, Bn254Curve, DoryCommitmentScheme, CoreBlake2bTranscript>; +pub type CoreProof = CoreJoltProof; +type CoreVerifier<'a> = + JoltVerifier<'a, CoreFr, Bn254Curve, DoryCommitmentScheme, CoreBlake2bTranscript>; +pub type CoreVerifierPreprocessing = + JoltVerifierPreprocessing; + +fn assert_core_verifies_proof( + fixture: &CoreMuldivCommitmentFixture, + proof: CoreProof, + message: &str, +) { + CoreVerifier::new( + fixture.verifier_preprocessing, + proof, + fixture.io.clone(), + None, + None, + ) + .expect("construct core verifier") + .verify() + .expect(message); +} + +pub struct CoreMuldivCommitmentFixture { + pub params: JoltProtocolParams, + pub(crate) core_metrics: PerfMetrics, + pub pcs_setup: DoryProverSetup, + pub proof: CoreProof, + pub(crate) verifier_preprocessing: &'static CoreVerifierPreprocessing, + pub(crate) io: JoltDevice, + pub(crate) entry_address: u64, + pub cycle_inputs: Vec, + pub(crate) r1cs_witness: Vec, + pub(crate) rv64_cycles: Vec, + pub product_virtual_cycles: Vec, + pub instruction_lookup_cycles: Vec, + pub(crate) stage3_cycles: Vec, + pub(crate) stage4_register_accesses: Vec, + pub(crate) stage5_lookup_indices: Vec, + pub(crate) stage5_lookup_table_indices: Vec>, + pub(crate) stage5_is_interleaved_operands: Vec, + pub(crate) stage6_bytecode_entries: Vec>, + pub(crate) stage6_entry_bytecode_index: usize, + pub(crate) stage6_num_lookup_tables: usize, + pub(crate) ram_accesses: Vec, + pub(crate) initial_ram_state: Vec, + pub(crate) final_ram_state: Vec, + pub(crate) ram_start_address: u64, + pub(crate) ram_output_layout: Stage2RamOutputLayout, + pub commitments: Vec, +} + +impl CoreMuldivCommitmentFixture { + pub fn stage2_ram_data(&self) -> Stage2RamData<'_> { + Stage2RamData { + log_k: self.params.log_k_ram, + start_address: self.ram_start_address, + initial_ram: &self.initial_ram_state, + final_ram: &self.final_ram_state, + accesses: &self.ram_accesses, + output_layout: Some(self.ram_output_layout), + } + } + + pub fn r1cs_key(&self) -> R1csKey { + R1csKey::new(rv64::rv64_constraints::(), self.proof.trace_length) + } + + pub fn stage1_outer_rv64_data<'a>( + &'a self, + r1cs_key: &'a R1csKey, + ) -> Stage1OuterRv64Data<'a> { + Stage1OuterRv64Data::new(r1cs_key, &self.r1cs_witness, &self.rv64_cycles) + .expect("valid RV64-backed stage1 data") + } + + pub fn stage1_outer_r1cs_data<'a>( + &'a self, + r1cs_key: &'a R1csKey, + ) -> Stage1OuterR1csData<'a, Fr> { + Stage1OuterR1csData::new(r1cs_key, &self.r1cs_witness).expect("valid R1CS witness shape") + } + + pub(crate) fn stage6_witness_params(&self) -> Stage6WitnessParams { + Stage6WitnessParams { + trace_len: self.proof.trace_length, + log_k_chunk: self.params.log_k_chunk, + log_k_bytecode: self.params.log_k_bytecode, + log_k_ram: self.params.log_k_ram, + lookups_ra_virtual_log_k_chunk: self.params.lookups_ra_virtual_log_k_chunk, + instruction_d: self.params.instruction_d, + instruction_ra_virtual_d: self.params.instruction_ra_virtual_d, + bytecode_d: self.params.bytecode_d, + ram_d: self.params.ram_d, + } + } +} + +impl BoltPreambleSource for CoreMuldivCommitmentFixture { + fn program_io(&self) -> &JoltDevice { + &self.io + } + + fn preprocessing_digest(&self) -> [u8; 32] { + self.verifier_preprocessing.shared.digest() + } + + fn ram_k(&self) -> u64 { + self.proof.ram_K as u64 + } + + fn trace_length(&self) -> u64 { + self.proof.trace_length as u64 + } + + fn entry_address(&self) -> u64 { + self.entry_address + } + + fn ram_rw_phase1_num_rounds(&self) -> u64 { + self.proof.rw_config.ram_rw_phase1_num_rounds as u64 + } + + fn ram_rw_phase2_num_rounds(&self) -> u64 { + self.proof.rw_config.ram_rw_phase2_num_rounds as u64 + } + + fn registers_rw_phase1_num_rounds(&self) -> u64 { + self.proof.rw_config.registers_rw_phase1_num_rounds as u64 + } + + fn registers_rw_phase2_num_rounds(&self) -> u64 { + self.proof.rw_config.registers_rw_phase2_num_rounds as u64 + } + + fn log_k_chunk(&self) -> u64 { + self.proof.one_hot_config.log_k_chunk as u64 + } + + fn lookups_ra_virtual_log_k_chunk(&self) -> u64 { + self.proof.one_hot_config.lookups_ra_virtual_log_k_chunk as u64 + } + + fn dory_layout(&self) -> u64 { + self.proof.dory_layout as u64 + } +} + +pub fn core_muldiv_commitment_fixture() -> CoreMuldivCommitmentFixture { + let inputs = postcard::to_stdvec(&[9u32, 5u32, 3u32]).expect("muldiv inputs"); + core_guest_commitment_fixture("muldiv-guest", inputs, 1 << 16) +} + +pub fn core_sha2_chain_commitment_fixture(log_t: usize) -> CoreMuldivCommitmentFixture { + let target_cycles = ((1usize << log_t) as f64 * 0.9) as usize; + let num_iters = std::cmp::max(1, (target_cycles as f64 / 3396.0) as u32); + let mut inputs = Vec::new(); + inputs.extend(postcard::to_stdvec(&[5u8; 32]).expect("sha2-chain input")); + inputs.extend(postcard::to_stdvec(&num_iters).expect("sha2-chain iterations")); + core_guest_commitment_fixture("sha2-chain-guest", inputs, 1usize << log_t) +} + +fn core_guest_commitment_fixture( + guest_name: &str, + inputs: Vec, + max_trace_length: usize, +) -> CoreMuldivCommitmentFixture { + let setup_start = Instant::now(); + let _core_setup_span = tracing::info_span!("core.setup").entered(); + + let mut core_program = host::Program::new(guest_name); + let (core_bytecode, init_memory_state, _, entry_address) = core_program.decode(); + let core_bytecode_for_bolt = core_bytecode.clone(); + let (_, trace, _, host_io_device) = core_program.trace(&inputs, &[], &[]); + let shared_preprocessing = JoltSharedPreprocessing::new( + core_bytecode, + host_io_device.memory_layout.clone(), + init_memory_state, + max_trace_length, + entry_address, + ) + .expect("shared preprocessing"); + let prover_preprocessing = JoltProverPreprocessing::new(shared_preprocessing); + let elf_contents = core_program.get_elf_contents().expect("guest elf"); + let prover: CoreProver<'_> = CoreProver::gen_from_elf( + &prover_preprocessing, + &elf_contents, + &inputs, + &[], + &[], + None, + None, + None, + ); + let setup_ms = setup_start.elapsed().as_secs_f64() * 1_000.0; + drop(_core_setup_span); + let io = prover.program_io.clone(); + let initial_ram_state = prover.initial_ram_state.clone(); + let final_ram_state = prover.final_ram_state.clone(); + let core_rss_sampler = PeakRssSampler::start().expect("start core RSS sampler"); + let _core_prove_span = tracing::info_span!("core.prove").entered(); + let (prove_ms, (proof, _debug)) = time_it(|| prover.prove()); + drop(_core_prove_span); + let peak_rss_mb = core_rss_sampler.finish(); + let proof_bytes = proof.serialized_size(Compress::Yes) as u64; + let verifier_preprocessing: &'static _ = Box::leak(Box::new(JoltVerifierPreprocessing::from( + &prover_preprocessing, + ))); + let core_verifier = CoreVerifier::new( + verifier_preprocessing, + clone_core_proof(&proof), + io.clone(), + None, + None, + ) + .expect("construct core verifier"); + let _core_verify_span = tracing::info_span!("core.verify").entered(); + let (verify_ms, verify_result) = time_it(|| core_verifier.verify()); + drop(_core_verify_span); + verify_result.expect("core verifier accepts proof"); + let core_metrics = PerfMetrics { + setup_ms: Some(setup_ms), + prove_ms: Some(prove_ms), + verify_ms: Some(verify_ms), + proof_bytes: Some(proof_bytes), + peak_rss_mb: Some(peak_rss_mb), + span_names: observed_span_names_with_prefix("core."), + }; + + let mut padded_trace = trace.clone(); + padded_trace.resize(proof.trace_length, jolt_trace::Cycle::NoOp); + let product_virtual_cycles = stage2_product_virtual_cycles(&padded_trace, proof.trace_length); + let instruction_lookup_cycles = + stage2_instruction_lookup_cycles(&padded_trace, proof.trace_length); + let ram_accesses = stage2_ram_accesses(&padded_trace, proof.trace_length, |address| { + remap_address(address, &host_io_device.memory_layout).map(|address| address as usize) + }); + let ram_start_address = host_io_device.memory_layout.get_lowest_address(); + let ram_output_layout = Stage2RamOutputLayout { + io_start: remap_address( + host_io_device.memory_layout.input_start, + &host_io_device.memory_layout, + ) + .expect("input start remaps") as usize, + io_end: remap_address(RAM_START_ADDRESS, &host_io_device.memory_layout) + .expect("RAM start remaps") as usize, + }; + let bytecode = BytecodePreprocessing::preprocess(core_bytecode_for_bolt, entry_address); + let stage6_bytecode_entries = stage6_bytecode_entries(&bytecode, |instruction| { + InstructionLookup::::lookup_table(instruction) + .map(|table| CoreLookupTables::::enum_index(&table)) + }); + let stage6_entry_bytecode_index = bytecode.entry_bytecode_index(); + let stage6_num_lookup_tables = CoreLookupTables::::COUNT; + let r1cs_key = R1csKey::new(rv64::rv64_constraints::(), proof.trace_length); + let (cycle_inputs, r1cs_witness, _) = extract_trace::<_, Fr>( + &trace, + proof.trace_length, + &bytecode, + &host_io_device.memory_layout, + r1cs_key.num_vars_padded, + ); + let rv64_cycles = stage1_rv64_cycles(&trace, proof.trace_length, &bytecode); + let stage3_cycles = stage3_cycles(&trace, proof.trace_length, &bytecode); + let stage4_register_accesses = stage4_register_accesses(&trace, proof.trace_length); + let stage5_trace = stage5_lookup_trace(&padded_trace, proof.trace_length, |cycle| { + InstructionLookup::::lookup_table(cycle) + .map(|table| CoreLookupTables::::enum_index(&table)) + }); + let log_t = proof.trace_length.trailing_zeros() as usize; + let log_k_bytecode = prover_preprocessing + .shared + .bytecode + .code_size + .trailing_zeros() as usize; + let log_k_ram = proof.ram_K.trailing_zeros() as usize; + let params = JoltProtocolParams::new(log_t, log_k_bytecode, log_k_ram); + + let commitments = proof.commitments.clone(); + + CoreMuldivCommitmentFixture { + params, + core_metrics, + pcs_setup: DoryProverSetup(prover_preprocessing.generators.clone()), + proof, + verifier_preprocessing, + io, + entry_address, + cycle_inputs, + r1cs_witness, + rv64_cycles, + product_virtual_cycles, + instruction_lookup_cycles, + stage3_cycles, + stage4_register_accesses, + stage5_lookup_indices: stage5_trace.lookup_indices, + stage5_lookup_table_indices: stage5_trace.lookup_table_indices, + stage5_is_interleaved_operands: stage5_trace.is_interleaved_operands, + stage6_bytecode_entries, + stage6_entry_bytecode_index, + stage6_num_lookup_tables, + ram_accesses, + initial_ram_state, + final_ram_state, + ram_start_address, + ram_output_layout, + commitments, + } +} + +pub fn assert_core_accepts_bolt_stage1( + fixture: &CoreMuldivCommitmentFixture, + artifacts: &Stage1ExecutionArtifacts, +) { + assert_core_stage1_uniskip_proof_matches_bolt(&fixture.proof, &artifacts.sumchecks[0]); + let proof = core_proof_with_bolt_stage1(&fixture.proof, artifacts); + assert_core_verifies_proof(fixture, proof, "jolt-core accepts Bolt Stage 1 proof"); +} + +pub fn assert_core_accepts_bolt_stage2( + fixture: &CoreMuldivCommitmentFixture, + stage1_artifacts: &Stage1ExecutionArtifacts, + stage2_artifacts: &Stage2ExecutionArtifacts, +) { + let proof = core_proof_with_bolt_stage2(&fixture.proof, stage1_artifacts, stage2_artifacts); + assert_core_stage2_sumcheck_proof_matches_bolt(&fixture.proof, &stage2_artifacts.sumchecks[1]); + assert_core_stage2_opening_claims_match_bolt(&fixture.proof, stage2_artifacts); + + assert_core_verifies_proof(fixture, proof, "core accepts Bolt Stage 2"); +} + +pub(crate) fn assert_core_accepts_bolt_stage3( + fixture: &CoreMuldivCommitmentFixture, + stage1_artifacts: &Stage1ExecutionArtifacts, + stage2_artifacts: &Stage2ExecutionArtifacts, + stage3_artifacts: &Stage3ExecutionArtifacts, +) { + let proof = core_proof_with_bolt_stage3( + &fixture.proof, + stage1_artifacts, + stage2_artifacts, + stage3_artifacts, + ); + assert_core_stage3_sumcheck_proof_matches_bolt(&fixture.proof, &stage3_artifacts.sumchecks[0]); + assert_core_stage3_opening_claims_match_bolt(&fixture.proof, stage3_artifacts); + + assert_core_verifies_proof(fixture, proof, "core accepts Bolt Stage 3"); +} + +pub(crate) fn assert_core_accepts_bolt_stage4( + fixture: &CoreMuldivCommitmentFixture, + stage1_artifacts: &Stage1ExecutionArtifacts, + stage2_artifacts: &Stage2ExecutionArtifacts, + stage3_artifacts: &Stage3ExecutionArtifacts, + stage4_artifacts: &Stage4ExecutionArtifacts, +) { + let proof = core_proof_with_bolt_stage4( + &fixture.proof, + stage1_artifacts, + stage2_artifacts, + stage3_artifacts, + stage4_artifacts, + ); + assert_core_verifies_proof(fixture, proof, "core accepts Bolt Stage 4"); +} + +pub(crate) fn assert_core_accepts_bolt_stage5( + fixture: &CoreMuldivCommitmentFixture, + stage1_artifacts: &Stage1ExecutionArtifacts, + stage2_artifacts: &Stage2ExecutionArtifacts, + stage3_artifacts: &Stage3ExecutionArtifacts, + stage4_artifacts: &Stage4ExecutionArtifacts, + stage5_proof: &JoltStageProof, +) { + let proof = core_proof_with_bolt_stage5( + &fixture.proof, + stage1_artifacts, + stage2_artifacts, + stage3_artifacts, + stage4_artifacts, + stage5_proof, + ); + assert_core_verifies_proof(fixture, proof, "core accepts Bolt Stage 5"); +} + +pub(crate) fn assert_core_accepts_bolt_stage6( + fixture: &CoreMuldivCommitmentFixture, + stage1_artifacts: &Stage1ExecutionArtifacts, + stage2_artifacts: &Stage2ExecutionArtifacts, + stage3_artifacts: &Stage3ExecutionArtifacts, + stage4_artifacts: &Stage4ExecutionArtifacts, + stage5_proof: &JoltStageProof, + stage6_proof: &JoltStageProof, +) { + let proof = core_proof_with_bolt_stage6( + &fixture.proof, + stage1_artifacts, + stage2_artifacts, + stage3_artifacts, + stage4_artifacts, + stage5_proof, + stage6_proof, + ); + assert_core_stage6_sumcheck_proof_matches_bolt(&fixture.proof, &stage6_proof.sumchecks[0]); + assert_core_stage6_opening_claims_match_bolt(&fixture.proof, stage6_proof); + assert_core_verifies_proof(fixture, proof, "core accepts Bolt Stage 6"); +} + +pub(crate) fn assert_core_accepts_bolt_stage7( + fixture: &CoreMuldivCommitmentFixture, + stage1_artifacts: &Stage1ExecutionArtifacts, + stage2_artifacts: &Stage2ExecutionArtifacts, + stage3_artifacts: &Stage3ExecutionArtifacts, + stage4_artifacts: &Stage4ExecutionArtifacts, + stage5_proof: &JoltStageProof, + stage6_proof: &JoltStageProof, + stage7_proof: &JoltStageProof, +) { + let proof = core_proof_with_bolt_stage7( + &fixture.proof, + stage1_artifacts, + stage2_artifacts, + stage3_artifacts, + stage4_artifacts, + stage5_proof, + stage6_proof, + stage7_proof, + ); + assert_core_verifies_proof(fixture, proof, "core accepts Bolt Stage 7"); +} + +pub(crate) fn assert_core_accepts_bolt_evaluation_proof( + fixture: &CoreMuldivCommitmentFixture, + evaluation: &jolt_verifier::JoltEvaluationProof, +) { + let proof = core_proof_with_bolt_evaluation(&fixture.proof, evaluation); + assert_core_verifies_proof(fixture, proof, "core accepts Bolt evaluation proof"); +} + +pub(crate) fn assert_core_accepts_full_bolt_proof( + fixture: &CoreMuldivCommitmentFixture, + proof: &jolt_verifier::JoltProof, + artifacts: &jolt_prover::JoltProverArtifacts, +) { + let core_proof = core_proof_with_full_bolt(&fixture.proof, proof, artifacts); + assert_core_verifies_proof(fixture, core_proof, "core accepts full Bolt proof"); +} diff --git a/crates/jolt-equivalence/src/lib.rs b/crates/jolt-equivalence/src/lib.rs new file mode 100644 index 0000000000..0624fcf4ce --- /dev/null +++ b/crates/jolt-equivalence/src/lib.rs @@ -0,0 +1,28 @@ +//! Cross-system equivalence testing between jolt-core and Bolt-generated Jolt artifacts. +//! +//! The crate exposes representation-only artifact snapshots plus focused +//! oracle, checker, tamper, and perf helpers. Protocol semantics should live in +//! Bolt, generated artifacts, kernels, or `jolt-witness`, not in this crate. + +mod adapters; +mod artifacts; +pub mod bolt_oracle; +pub mod bolt_programs; +pub mod checkpoint; +pub mod checks; +pub mod commitment_oracle; +pub mod core_conversion; +pub mod core_oracle; +pub mod perf; +pub mod plan_adapters; +pub mod tamper; + +pub use artifacts::{ + ArtifactSource, CommitmentArtifact, CommitmentTrace, EquivalenceRun, NamedScalar, + OpeningBatchArtifacts, OpeningClaim, OpeningClaimKind, OpeningClaims, StageArtifacts, + SumcheckArtifacts, TranscriptTrace, VerifierResult, +}; +pub use checkpoint::{ + assert_transcripts_match, find_divergence, CheckpointTranscript, TranscriptDivergence, + TranscriptEvent, +}; diff --git a/crates/jolt-equivalence/src/perf.rs b/crates/jolt-equivalence/src/perf.rs new file mode 100644 index 0000000000..7a594ebe61 --- /dev/null +++ b/crates/jolt-equivalence/src/perf.rs @@ -0,0 +1,128 @@ +//! Perf-oracle helpers for equivalence tests. + +#![expect( + clippy::panic, + clippy::print_stdout, + reason = "perf oracle gates should fail fast and print successful ratio reports" +)] + +use std::sync::Once; + +use jolt_profiling::{ + observed_span_names_with_prefix, setup_tracing, CoreVsBoltGateReport, PerfGateThresholds, + PerfMetrics, TracingFormat, +}; +use serde::Serialize; + +static PERF_TRACING: Once = Once::new(); + +pub const CORE_VS_BOLT_PERF_THRESHOLDS: PerfGateThresholds = PerfGateThresholds { + max_setup_ratio: None, + max_prove_ratio: Some(100.0), + max_verify_ratio: Some(100.0), + max_proof_size_ratio: Some(100.0), + max_peak_rss_ratio: Some(100.0), +}; + +/// Installs perf span observation, and enables a Chrome/Perfetto trace when +/// `JOLT_BOLT_PERF_TRACE` is set. +pub fn maybe_setup_perf_trace(trace_name: &'static str) { + PERF_TRACING.call_once(|| { + let formats: &[TracingFormat] = if std::env::var_os("JOLT_BOLT_PERF_TRACE").is_some() { + &[TracingFormat::Chrome] + } else { + &[] + }; + let _ = Box::leak(Box::new(setup_tracing(formats, trace_name))); + }); +} + +pub fn generated_bolt_perf_metrics( + setup_ms: f64, + prove_ms: f64, + verify_ms: f64, + proof: &jolt_verifier::JoltProof, + peak_rss_mb: u64, +) -> PerfMetrics { + PerfMetrics { + setup_ms: Some(setup_ms), + prove_ms: Some(prove_ms), + verify_ms: Some(verify_ms), + proof_bytes: Some(generated_jolt_proof_bytes(proof)), + peak_rss_mb: Some(peak_rss_mb), + span_names: observed_span_names_with_prefix("bolt."), + } +} + +pub fn print_core_vs_bolt_perf_summary( + core: &PerfMetrics, + bolt: &PerfMetrics, + report: &CoreVsBoltGateReport, +) { + println!("core-vs-Bolt perf summary:"); + print_f64_metric("setup_ms", core.setup_ms, bolt.setup_ms); + print_f64_metric("prove_ms", core.prove_ms, bolt.prove_ms); + print_f64_metric("verify_ms", core.verify_ms, bolt.verify_ms); + print_u64_metric("proof_bytes", core.proof_bytes, bolt.proof_bytes); + print_u64_metric("peak_rss_mb", core.peak_rss_mb, bolt.peak_rss_mb); + for ratio in &report.ratios { + println!( + " gated {}: core={:.3}, bolt={:.3}, ratio={:.3}x, threshold={:.3}x", + ratio.metric, ratio.reference, ratio.candidate, ratio.ratio, ratio.threshold + ); + } +} + +fn print_f64_metric(label: &str, core: Option, bolt: Option) { + match (core, bolt) { + (Some(core), Some(bolt)) if core > 0.0 => { + println!( + " {label}: core={core:.3}, bolt={bolt:.3}, ratio={:.3}x", + bolt / core + ); + } + (Some(core), Some(bolt)) => { + println!(" {label}: core={core:.3}, bolt={bolt:.3}, ratio=n/a"); + } + _ => println!(" {label}: unavailable"), + } +} + +fn print_u64_metric(label: &str, core: Option, bolt: Option) { + match (core, bolt) { + (Some(core), Some(bolt)) if core > 0 => { + println!( + " {label}: core={core}, bolt={bolt}, ratio={:.3}x", + bolt as f64 / core as f64 + ); + } + (Some(core), Some(bolt)) => { + println!(" {label}: core={core}, bolt={bolt}, ratio=n/a"); + } + _ => println!(" {label}: unavailable"), + } +} + +fn generated_jolt_proof_bytes(proof: &jolt_verifier::JoltProof) -> u64 { + [ + serialized_component_size(&proof.commitments, "jolt proof commitments"), + serialized_component_size(&proof.stage1_outer, "jolt proof stage1"), + serialized_component_size(&proof.stage2, "jolt proof stage2"), + serialized_component_size(&proof.stage3, "jolt proof stage3"), + serialized_component_size(&proof.stage4, "jolt proof stage4"), + serialized_component_size(&proof.stage5, "jolt proof stage5"), + serialized_component_size(&proof.stage6, "jolt proof stage6"), + serialized_component_size(&proof.stage7, "jolt proof stage7"), + proof.evaluation.as_ref().map_or(0, |evaluation| { + serialized_component_size(&evaluation.joint_opening_proof, "jolt proof evaluation") + }), + ] + .into_iter() + .sum() +} + +fn serialized_component_size(component: &T, label: &str) -> u64 { + postcard::to_stdvec(component) + .unwrap_or_else(|error| panic!("serialize {label}: {error}")) + .len() as u64 +} diff --git a/crates/jolt-equivalence/src/plan_adapters.rs b/crates/jolt-equivalence/src/plan_adapters.rs new file mode 100644 index 0000000000..b577452cbf --- /dev/null +++ b/crates/jolt-equivalence/src/plan_adapters.rs @@ -0,0 +1,755 @@ +//! Static plan adapters from Bolt compiler plans to generated/kernel plans. +//! +//! These are compatibility shims for the equivalence oracle. They translate +//! Bolt's owned compiler plans into the currently generated static plan shape +//! expected by jolt-kernels, jolt-prover, and jolt-verifier. + +macro_rules! stage_list { + (kernel, $values:expr) => { + super::leak_str_slice($values) + }; + (generated, $values:expr) => { + super::leak_symbol_list($values) + }; +} + +macro_rules! stage_field_expr { + (kernel, $module:ident, $field_expr:ident, $plan:ident) => { + $module::$field_expr { + symbol: super::leak_str(&$plan.symbol), + kind: super::leak_str(&$plan.kind), + formula: super::leak_str(&$plan.formula), + operand_names: super::leak_str_slice(&$plan.operand_names), + operands: super::leak_str_slice(&$plan.operands), + } + }; + (generated, $module:ident, $field_expr:ident, $plan:ident) => { + $module::$field_expr { + symbol: super::leak_str(&$plan.symbol), + kind: super::leak_str(&$plan.kind), + formula: super::leak_str(&$plan.formula), + operands: super::leak_symbol_list(&$plan.operands), + } + }; +} + +macro_rules! stage_claim { + ($mode:ident, $module:ident, $claim:ident, $plan:ident) => { + $module::$claim { + symbol: super::leak_str(&$plan.symbol), + stage: super::leak_str(&$plan.stage), + domain: super::leak_str(&$plan.domain), + num_rounds: $plan.num_rounds, + degree: $plan.degree, + claim: super::leak_str(&$plan.claim), + kernel: $plan.kernel.as_deref().map(super::leak_str), + relation: $plan.relation.as_deref().map(super::leak_str), + claim_value: super::leak_str(&$plan.claim_value), + input_openings: stage_list!($mode, &$plan.input_openings), + } + }; +} + +macro_rules! stage_driver { + ($module:ident, $driver:ident, $plan:ident) => { + $module::$driver { + symbol: super::leak_str(&$plan.symbol), + stage: super::leak_str(&$plan.stage), + proof_slot: super::leak_str(&$plan.proof_slot), + kernel: $plan.kernel.as_deref().map(super::leak_str), + relation: $plan.relation.as_deref().map(super::leak_str), + batch: super::leak_str(&$plan.batch), + policy: super::leak_str(&$plan.policy), + round_schedule: super::leak_usize_slice(&$plan.round_schedule), + claim_label: super::leak_str(&$plan.claim_label), + round_label: super::leak_str(&$plan.round_label), + num_rounds: $plan.num_rounds, + degree: $plan.degree, + } + }; +} + +macro_rules! define_stage_adapter_impl { + ( + $mode:ident, + $function:ident, + $compiler:ty, + $module:ident, + $program:ident, + $params:ident, + $step:ident, + $squeeze:ident, + $opening_input:ident, + $field_constant:ident, + $field_expr:ident, + $claim:ident, + $batch:ident, + $driver:ident, + $instance_result:ident, + $eval:ident, + $point_slice:ident, + $point_concat:ident, + $opening_claim:ident, + $opening_batch:ident + $(, role = $role_field:ident)? + $(, transcript_absorb_bytes = $absorb:ident)? + $(, kernels = $kernel:ident)? + $(, point_zeros = $point_zero:ident)? + $(, opening_equalities = $opening_equality:ident)? + ) => { + pub fn $function(program: &$compiler) -> &'static $module::$program { + Box::leak(Box::new($module::$program { + $( + $role_field: super::role_name(&program.role), + )? + params: $module::$params { + field: super::leak_str(&program.params.field), + pcs: super::leak_str(&program.params.pcs), + transcript: super::leak_str(&program.params.transcript), + }, + steps: super::leak_slice( + program + .steps + .iter() + .map(|plan| $module::$step { + kind: super::leak_str(&plan.kind), + symbol: super::leak_str(&plan.symbol), + }) + .collect(), + ), + transcript_squeezes: super::leak_slice( + program + .transcript_squeezes + .iter() + .map(|plan| $module::$squeeze { + symbol: super::leak_str(&plan.symbol), + label: super::leak_str(&plan.label), + kind: super::leak_str(&plan.kind), + count: plan.count, + }) + .collect(), + ), + $( + transcript_absorb_bytes: super::leak_slice( + program + .transcript_absorb_bytes + .iter() + .map(|plan| $module::$absorb { + symbol: super::leak_str(&plan.symbol), + label: super::leak_str(&plan.label), + payload: super::leak_str(&plan.payload), + }) + .collect(), + ), + )? + opening_inputs: super::leak_slice( + program + .opening_inputs + .iter() + .map(|plan| $module::$opening_input { + symbol: super::leak_str(&plan.symbol), + source_stage: super::leak_str(&plan.source_stage), + source_claim: super::leak_str(&plan.source_claim), + oracle: super::leak_str(&plan.oracle), + domain: super::leak_str(&plan.domain), + point_arity: plan.point_arity, + claim_kind: super::leak_str(&plan.claim_kind), + }) + .collect(), + ), + field_constants: super::leak_slice( + program + .field_constants + .iter() + .map(|plan| $module::$field_constant { + symbol: super::leak_str(&plan.symbol), + field: super::leak_str(&plan.field), + value: plan.value, + }) + .collect(), + ), + field_exprs: super::leak_slice( + program + .field_exprs + .iter() + .map(|plan| stage_field_expr!($mode, $module, $field_expr, plan)) + .collect(), + ), + $( + kernels: super::leak_slice( + program + .kernels + .iter() + .map(|plan| $module::$kernel { + symbol: super::leak_str(&plan.symbol), + relation: super::leak_str(&plan.relation), + kind: super::leak_str(&plan.kind), + backend: super::leak_str(&plan.backend), + abi: super::leak_str(&plan.abi), + }) + .collect(), + ), + )? + claims: super::leak_slice( + program + .claims + .iter() + .map(|plan| stage_claim!($mode, $module, $claim, plan)) + .collect(), + ), + batches: super::leak_slice( + program + .batches + .iter() + .map(|plan| $module::$batch { + symbol: super::leak_str(&plan.symbol), + stage: super::leak_str(&plan.stage), + proof_slot: super::leak_str(&plan.proof_slot), + policy: super::leak_str(&plan.policy), + count: plan.count, + ordered_claims: stage_list!($mode, &plan.ordered_claims), + claim_operands: stage_list!($mode, &plan.claim_operands), + claim_label: super::leak_str(&plan.claim_label), + round_label: super::leak_str(&plan.round_label), + round_schedule: super::leak_usize_slice(&plan.round_schedule), + }) + .collect(), + ), + drivers: super::leak_slice( + program + .drivers + .iter() + .map(|plan| stage_driver!($module, $driver, plan)) + .collect(), + ), + instance_results: super::leak_slice( + program + .instance_results + .iter() + .map(|plan| $module::$instance_result { + symbol: super::leak_str(&plan.symbol), + source: super::leak_str(&plan.source), + claim: super::leak_str(&plan.claim), + relation: super::leak_str(&plan.relation), + index: plan.index, + point_arity: plan.point_arity, + num_rounds: plan.num_rounds, + round_offset: plan.round_offset, + point_order: super::leak_str(&plan.point_order), + degree: plan.degree, + }) + .collect(), + ), + evals: super::leak_slice( + program + .evals + .iter() + .map(|plan| $module::$eval { + symbol: super::leak_str(&plan.symbol), + source: super::leak_str(&plan.source), + name: super::leak_str(&plan.name), + index: plan.index, + oracle: super::leak_str(&plan.oracle), + }) + .collect(), + ), + $( + point_zeros: super::leak_slice( + program + .point_zeros + .iter() + .map(|plan| $module::$point_zero { + symbol: super::leak_str(&plan.symbol), + field: super::leak_str(&plan.field), + arity: plan.arity, + }) + .collect(), + ), + )? + point_slices: super::leak_slice( + program + .point_slices + .iter() + .map(|plan| $module::$point_slice { + symbol: super::leak_str(&plan.symbol), + source: super::leak_str(&plan.source), + offset: plan.offset, + length: plan.length, + input: super::leak_str(&plan.input), + }) + .collect(), + ), + point_concats: super::leak_slice( + program + .point_concats + .iter() + .map(|plan| $module::$point_concat { + symbol: super::leak_str(&plan.symbol), + layout: super::leak_str(&plan.layout), + arity: plan.arity, + inputs: stage_list!($mode, &plan.inputs), + }) + .collect(), + ), + opening_claims: super::leak_slice( + program + .opening_claims + .iter() + .map(|plan| $module::$opening_claim { + symbol: super::leak_str(&plan.symbol), + oracle: super::leak_str(&plan.oracle), + domain: super::leak_str(&plan.domain), + point_arity: plan.point_arity, + claim_kind: super::leak_str(&plan.claim_kind), + point_source: super::leak_str(&plan.point_source), + eval_source: super::leak_str(&plan.eval_source), + }) + .collect(), + ), + $( + opening_equalities: super::leak_slice( + program + .opening_equalities + .iter() + .map(|plan| $module::$opening_equality { + symbol: super::leak_str(&plan.symbol), + mode: super::leak_str(&plan.mode), + lhs: super::leak_str(&plan.lhs), + rhs: super::leak_str(&plan.rhs), + }) + .collect(), + ), + )? + opening_batches: super::leak_slice( + program + .opening_batches + .iter() + .map(|plan| $module::$opening_batch { + symbol: super::leak_str(&plan.symbol), + stage: super::leak_str(&plan.stage), + proof_slot: super::leak_str(&plan.proof_slot), + policy: super::leak_str(&plan.policy), + count: plan.count, + ordered_claims: stage_list!($mode, &plan.ordered_claims), + claim_operands: stage_list!($mode, &plan.claim_operands), + }) + .collect(), + ), + })) + } + }; +} + +macro_rules! define_stage_adapter { + ( + $mode:ident, + $function:ident, + $compiler:ty, + $module:ident, + $program:ident, + $params:ident, + $step:ident, + $squeeze:ident, + $absorb:ident, + $opening_input:ident, + $field_constant:ident, + $field_expr:ident, + $kernel:ident, + $claim:ident, + $batch:ident, + $driver:ident, + $instance_result:ident, + $eval:ident, + $point_slice:ident, + $point_concat:ident, + $opening_claim:ident, + $opening_equality:ident, + $opening_batch:ident + $(, point_zero = $point_zero:ident)? + ) => { + define_stage_adapter_impl!( + $mode, + $function, + $compiler, + $module, + $program, + $params, + $step, + $squeeze, + $opening_input, + $field_constant, + $field_expr, + $claim, + $batch, + $driver, + $instance_result, + $eval, + $point_slice, + $point_concat, + $opening_claim, + $opening_batch, + role = role, + transcript_absorb_bytes = $absorb, + kernels = $kernel + $(, point_zeros = $point_zero)?, + opening_equalities = $opening_equality + ); + }; +} + +macro_rules! define_stage_adapter_no_absorb { + ( + $mode:ident, + $function:ident, + $compiler:ty, + $module:ident, + $program:ident, + $params:ident, + $step:ident, + $squeeze:ident, + $opening_input:ident, + $field_constant:ident, + $field_expr:ident, + $claim:ident, + $batch:ident, + $driver:ident, + $instance_result:ident, + $eval:ident, + $point_slice:ident, + $point_concat:ident, + $opening_claim:ident, + $opening_batch:ident + $(, kernels = $kernel:ident)? + $(, opening_equalities = $opening_equality:ident)? + ) => { + define_stage_adapter_impl!( + $mode, + $function, + $compiler, + $module, + $program, + $params, + $step, + $squeeze, + $opening_input, + $field_constant, + $field_expr, + $claim, + $batch, + $driver, + $instance_result, + $eval, + $point_slice, + $point_concat, + $opening_claim, + $opening_batch + $(, kernels = $kernel)? + $(, opening_equalities = $opening_equality)? + ); + }; +} + +macro_rules! define_stage1_adapter { + ( + $mode:ident, + $function:ident, + $compiler:ty, + $module:ident, + $program:ident, + $params:ident, + $squeeze:ident, + $claim:ident, + $batch:ident, + $driver:ident, + $instance_result:ident, + $eval:ident, + $opening_claim:ident, + $opening_batch:ident + $(, kernels = $kernel:ident)? + ) => { + pub fn $function(program: &$compiler) -> &'static $module::$program { + Box::leak(Box::new($module::$program { + params: $module::$params { + field: super::leak_str(&program.params.field), + pcs: super::leak_str(&program.params.pcs), + transcript: super::leak_str(&program.params.transcript), + }, + transcript_squeezes: super::leak_slice( + program + .transcript_squeezes + .iter() + .map(|plan| $module::$squeeze { + symbol: super::leak_str(&plan.symbol), + label: super::leak_str(&plan.label), + kind: super::leak_str(&plan.kind), + count: plan.count, + }) + .collect(), + ), + $( + kernels: super::leak_slice( + program + .kernels + .iter() + .map(|plan| $module::$kernel { + symbol: super::leak_str(&plan.symbol), + relation: super::leak_str(&plan.relation), + kind: super::leak_str(&plan.kind), + backend: super::leak_str(&plan.backend), + abi: super::leak_str(&plan.abi), + }) + .collect(), + ), + )? + claims: super::leak_slice( + program + .claims + .iter() + .map(|plan| stage_claim!($mode, $module, $claim, plan)) + .collect(), + ), + batches: super::leak_slice( + program + .batches + .iter() + .map(|plan| $module::$batch { + symbol: super::leak_str(&plan.symbol), + stage: super::leak_str(&plan.stage), + proof_slot: super::leak_str(&plan.proof_slot), + policy: super::leak_str(&plan.policy), + count: plan.count, + ordered_claims: stage_list!($mode, &plan.ordered_claims), + claim_operands: stage_list!($mode, &plan.claim_operands), + claim_label: super::leak_str(&plan.claim_label), + round_label: super::leak_str(&plan.round_label), + round_schedule: super::leak_usize_slice(&plan.round_schedule), + }) + .collect(), + ), + drivers: super::leak_slice( + program + .drivers + .iter() + .map(|plan| stage_driver!($module, $driver, plan)) + .collect(), + ), + instance_results: super::leak_slice( + program + .instance_results + .iter() + .map(|plan| $module::$instance_result { + symbol: super::leak_str(&plan.symbol), + source: super::leak_str(&plan.source), + claim: super::leak_str(&plan.claim), + relation: super::leak_str(&plan.relation), + index: plan.index, + point_arity: plan.point_arity, + num_rounds: plan.num_rounds, + round_offset: plan.round_offset, + point_order: super::leak_str(&plan.point_order), + degree: plan.degree, + }) + .collect(), + ), + evals: super::leak_slice( + program + .evals + .iter() + .map(|plan| $module::$eval { + symbol: super::leak_str(&plan.symbol), + source: super::leak_str(&plan.source), + name: super::leak_str(&plan.name), + index: plan.index, + oracle: super::leak_str(&plan.oracle), + }) + .collect(), + ), + opening_claims: super::leak_slice( + program + .opening_claims + .iter() + .map(|plan| $module::$opening_claim { + symbol: super::leak_str(&plan.symbol), + oracle: super::leak_str(&plan.oracle), + domain: super::leak_str(&plan.domain), + point_arity: plan.point_arity, + claim_kind: super::leak_str(&plan.claim_kind), + point_source: super::leak_str(&plan.point_source), + eval_source: super::leak_str(&plan.eval_source), + }) + .collect(), + ), + opening_batches: super::leak_slice( + program + .opening_batches + .iter() + .map(|plan| $module::$opening_batch { + symbol: super::leak_str(&plan.symbol), + stage: super::leak_str(&plan.stage), + proof_slot: super::leak_str(&plan.proof_slot), + policy: super::leak_str(&plan.policy), + count: plan.count, + ordered_claims: stage_list!($mode, &plan.ordered_claims), + claim_operands: stage_list!($mode, &plan.claim_operands), + }) + .collect(), + ), + })) + } + }; +} + +mod generated_commitment; +mod generated_stage1; +mod generated_stage2; +mod generated_stage3; +mod generated_stage4; +mod generated_stage5; +mod generated_stage6; +mod generated_stage7; +mod stage1; +mod stage2; +mod stage3; +mod stage4; +mod stage5; +mod stage6; +mod stage7; + +pub(crate) use generated_commitment::{ + leak_generated_commitment_prover_program, leak_generated_commitment_verifier_program, +}; +pub use generated_stage1::leak_generated_stage1_verifier_program; +pub use generated_stage2::leak_generated_stage2_verifier_program; +pub(crate) use generated_stage3::leak_generated_stage3_verifier_program; +pub(crate) use generated_stage4::leak_generated_stage4_verifier_program; +pub(crate) use generated_stage5::leak_generated_stage5_verifier_program; +pub(crate) use generated_stage6::leak_generated_stage6_verifier_program; +pub(crate) use generated_stage7::leak_generated_stage7_verifier_program; +pub use stage1::leak_stage1_program; +pub use stage2::leak_stage2_program; +pub(crate) use stage3::leak_stage3_program; +pub(crate) use stage4::leak_stage4_program; +pub(crate) use stage5::leak_stage5_program; +pub(crate) use stage6::leak_stage6_program; +pub(crate) use stage7::leak_stage7_program; + +use bolt::protocols::jolt::Stage8CpuProgram as CompilerStage8CpuProgram; +use bolt::Role; +use jolt_prover::stages::stage8 as generated_prover_stage8; +use jolt_verifier::stages::stage8 as generated_stage8; + +macro_rules! define_stage8_adapter { + ($function:ident, $module:ident) => { + pub(crate) fn $function( + program: &CompilerStage8CpuProgram, + ) -> &'static $module::Stage8EvaluationProgramPlan { + let evaluation_point_source = program + .opening_inputs + .iter() + .find(|input| input.symbol == "stage8.evaluation.point_source") + .expect("stage8 evaluation point source exists"); + Box::leak(Box::new($module::Stage8EvaluationProgramPlan { + role: role_name(&program.role), + function: leak_str(&program.function), + params: $module::Stage8Params { + field: leak_str(&program.params.field), + pcs: leak_str(&program.params.pcs), + transcript: leak_str(&program.params.transcript), + }, + evaluation_point_source: $module::Stage8OpeningInputPlan { + symbol: leak_str(&evaluation_point_source.symbol), + source_stage: leak_str(&evaluation_point_source.source_stage), + source_claim: leak_str(&evaluation_point_source.source_claim), + oracle: leak_str(&evaluation_point_source.oracle), + domain: leak_str(&evaluation_point_source.domain), + point_arity: evaluation_point_source.point_arity, + claim_kind: leak_str(&evaluation_point_source.claim_kind), + }, + opening_inputs: leak_slice( + program + .opening_inputs + .iter() + .map(|plan| $module::Stage8OpeningInputPlan { + symbol: leak_str(&plan.symbol), + source_stage: leak_str(&plan.source_stage), + source_claim: leak_str(&plan.source_claim), + oracle: leak_str(&plan.oracle), + domain: leak_str(&plan.domain), + point_arity: plan.point_arity, + claim_kind: leak_str(&plan.claim_kind), + }) + .collect(), + ), + opening_claims: leak_slice( + program + .opening_claims + .iter() + .map(|plan| $module::Stage8OpeningClaimPlan { + symbol: leak_str(&plan.symbol), + oracle: leak_str(&plan.oracle), + family: leak_str(&plan.family), + domain: leak_str(&plan.domain), + point_arity: plan.point_arity, + point_source: leak_str(&plan.point_source), + eval_source: leak_str(&plan.eval_source), + source_stage: leak_str(&plan.source_stage), + source_claim: leak_str(&plan.source_claim), + }) + .collect(), + ), + opening_batch: $module::Stage8OpeningBatchPlan { + symbol: leak_str(&program.opening_batches[0].symbol), + proof_slot: leak_str(&program.opening_batches[0].proof_slot), + policy: leak_str(&program.opening_batches[0].policy), + count: program.opening_batches[0].count, + ordered_claims: leak_str_slice(&program.opening_batches[0].ordered_claims), + }, + pcs_proof: $module::Stage8PcsProofPlan { + symbol: leak_str(&program.pcs_proofs[0].symbol), + mode: leak_str(&program.pcs_proofs[0].mode), + pcs: leak_str(&program.pcs_proofs[0].pcs), + proof_slot: leak_str(&program.pcs_proofs[0].proof_slot), + transcript_label: leak_str(&program.pcs_proofs[0].transcript_label), + batch: leak_str(&program.pcs_proofs[0].batch), + }, + })) + } + }; +} + +define_stage8_adapter!( + leak_generated_stage8_prover_program, + generated_prover_stage8 +); +define_stage8_adapter!(leak_generated_stage8_verifier_program, generated_stage8); + +fn role_name(role: &Role) -> &'static str { + match role { + Role::Prover => "prover", + Role::Verifier => "verifier", + } +} + +fn leak_str(value: &str) -> &'static str { + Box::leak(value.to_owned().into_boxed_str()) +} + +fn leak_str_slice(values: &[String]) -> &'static [&'static str] { + let leaked = values + .iter() + .map(|value| leak_str(value)) + .collect::>(); + Box::leak(leaked.into_boxed_slice()) +} + +fn leak_symbol_list(values: &[String]) -> &'static str { + leak_str(&values.join("|")) +} + +fn leak_usize_slice(values: &[usize]) -> &'static [usize] { + Box::leak(values.to_vec().into_boxed_slice()) +} + +fn leak_slice(values: Vec) -> &'static [T] { + Box::leak(values.into_boxed_slice()) +} diff --git a/crates/jolt-equivalence/src/plan_adapters/generated_commitment.rs b/crates/jolt-equivalence/src/plan_adapters/generated_commitment.rs new file mode 100644 index 0000000000..9893eba1f1 --- /dev/null +++ b/crates/jolt-equivalence/src/plan_adapters/generated_commitment.rs @@ -0,0 +1,87 @@ +use bolt::protocols::jolt::{CommitmentCpuProgram, OptionalSkipPolicy}; +use jolt_prover::stages::commitment as generated_prover_commitment; +use jolt_verifier::stages::commitment as generated_commitment; + +use super::{leak_slice, leak_str, leak_str_slice}; + +macro_rules! define_generated_commitment_adapter { + ($function:ident, $module:ident, $program_plan:ident) => { + pub fn $function(program: &CommitmentCpuProgram) -> &'static $module::$program_plan { + Box::leak(Box::new($module::$program_plan { + params: $module::CommitmentParams { + field: leak_str(&program.params.field), + pcs: leak_str(&program.params.pcs), + transcript: leak_str(&program.params.transcript), + }, + oracle_plans: leak_slice( + program + .oracle_plans + .iter() + .map(|plan| $module::OraclePlan { + oracle: leak_str(&plan.oracle), + domain: leak_str(&plan.domain), + num_vars: plan.num_vars, + }) + .collect(), + ), + batch_plans: leak_slice( + program + .batch_plans + .iter() + .map(|plan| $module::CommitmentBatchPlan { + artifact: leak_str(&plan.artifact), + pcs: leak_str(&plan.pcs), + oracle_family: leak_str(&plan.oracle_family), + label: leak_str(&plan.label), + oracles: leak_str_slice(&plan.oracles), + count: plan.count, + domain: leak_str(&plan.domain), + num_vars: plan.num_vars, + }) + .collect(), + ), + optional_plans: leak_slice( + program + .optional_plans + .iter() + .map(|plan| $module::OptionalCommitmentPlan { + artifact: leak_str(&plan.artifact), + pcs: leak_str(&plan.pcs), + oracle: leak_str(&plan.oracle), + label: leak_str(&plan.label), + domain: leak_str(&plan.domain), + num_vars: plan.num_vars, + skip_policy: match plan.skip_policy { + OptionalSkipPolicy::MissingOrZero => { + $module::OptionalSkipPolicy::MissingOrZero + } + }, + }) + .collect(), + ), + transcript_steps: leak_slice( + program + .transcript_steps + .iter() + .map(|step| $module::TranscriptStep { + label: leak_str(&step.label), + source: leak_str(&step.source), + optional: step.optional, + }) + .collect(), + ), + })) + } + }; +} + +define_generated_commitment_adapter!( + leak_generated_commitment_prover_program, + generated_prover_commitment, + CommitmentProverProgramPlan +); +define_generated_commitment_adapter!( + leak_generated_commitment_verifier_program, + generated_commitment, + CommitmentVerifierProgramPlan +); diff --git a/crates/jolt-equivalence/src/plan_adapters/generated_stage1.rs b/crates/jolt-equivalence/src/plan_adapters/generated_stage1.rs new file mode 100644 index 0000000000..865e762ee4 --- /dev/null +++ b/crates/jolt-equivalence/src/plan_adapters/generated_stage1.rs @@ -0,0 +1,19 @@ +use bolt::protocols::jolt::Stage1CpuProgram as CompilerStage1CpuProgram; +use jolt_verifier::stages::stage1_outer as generated_stage1; + +define_stage1_adapter!( + generated, + leak_generated_stage1_verifier_program, + CompilerStage1CpuProgram, + generated_stage1, + Stage1VerifierProgramPlan, + Stage1Params, + Stage1TranscriptSqueezePlan, + Stage1SumcheckClaimPlan, + Stage1SumcheckBatchPlan, + Stage1SumcheckDriverPlan, + Stage1SumcheckInstanceResultPlan, + Stage1SumcheckEvalPlan, + Stage1OpeningClaimPlan, + Stage1OpeningBatchPlan +); diff --git a/crates/jolt-equivalence/src/plan_adapters/generated_stage2.rs b/crates/jolt-equivalence/src/plan_adapters/generated_stage2.rs new file mode 100644 index 0000000000..517e934a68 --- /dev/null +++ b/crates/jolt-equivalence/src/plan_adapters/generated_stage2.rs @@ -0,0 +1,25 @@ +use bolt::protocols::jolt::Stage2CpuProgram as CompilerStage2CpuProgram; +use jolt_verifier::stages::stage2 as generated_stage2; + +define_stage_adapter_no_absorb!( + generated, + leak_generated_stage2_verifier_program, + CompilerStage2CpuProgram, + generated_stage2, + Stage2VerifierProgramPlan, + Stage2Params, + Stage2ProgramStepPlan, + Stage2TranscriptSqueezePlan, + Stage2OpeningInputPlan, + Stage2FieldConstantPlan, + Stage2FieldExprPlan, + Stage2SumcheckClaimPlan, + Stage2SumcheckBatchPlan, + Stage2SumcheckDriverPlan, + Stage2SumcheckInstanceResultPlan, + Stage2SumcheckEvalPlan, + Stage2PointSlicePlan, + Stage2PointConcatPlan, + Stage2OpeningClaimPlan, + Stage2OpeningBatchPlan +); diff --git a/crates/jolt-equivalence/src/plan_adapters/generated_stage3.rs b/crates/jolt-equivalence/src/plan_adapters/generated_stage3.rs new file mode 100644 index 0000000000..5dcb77bf10 --- /dev/null +++ b/crates/jolt-equivalence/src/plan_adapters/generated_stage3.rs @@ -0,0 +1,26 @@ +use bolt::protocols::jolt::Stage3CpuProgram as CompilerStage3CpuProgram; +use jolt_verifier::stages::stage3 as generated_stage3; + +define_stage_adapter_no_absorb!( + generated, + leak_generated_stage3_verifier_program, + CompilerStage3CpuProgram, + generated_stage3, + Stage3VerifierProgramPlan, + Stage3Params, + Stage3ProgramStepPlan, + Stage3TranscriptSqueezePlan, + Stage3OpeningInputPlan, + Stage3FieldConstantPlan, + Stage3FieldExprPlan, + Stage3SumcheckClaimPlan, + Stage3SumcheckBatchPlan, + Stage3SumcheckDriverPlan, + Stage3SumcheckInstanceResultPlan, + Stage3SumcheckEvalPlan, + Stage3PointSlicePlan, + Stage3PointConcatPlan, + Stage3OpeningClaimPlan, + Stage3OpeningBatchPlan, + opening_equalities = Stage3OpeningClaimEqualityPlan +); diff --git a/crates/jolt-equivalence/src/plan_adapters/generated_stage4.rs b/crates/jolt-equivalence/src/plan_adapters/generated_stage4.rs new file mode 100644 index 0000000000..a9340f0907 --- /dev/null +++ b/crates/jolt-equivalence/src/plan_adapters/generated_stage4.rs @@ -0,0 +1,28 @@ +use bolt::protocols::jolt::Stage4CpuProgram as CompilerStage4CpuProgram; +use jolt_verifier::stages::stage4 as generated_stage4; + +define_stage_adapter!( + generated, + leak_generated_stage4_verifier_program, + CompilerStage4CpuProgram, + generated_stage4, + Stage4VerifierProgramPlan, + Stage4Params, + Stage4ProgramStepPlan, + Stage4TranscriptSqueezePlan, + Stage4TranscriptAbsorbBytesPlan, + Stage4OpeningInputPlan, + Stage4FieldConstantPlan, + Stage4FieldExprPlan, + Stage4KernelPlan, + Stage4SumcheckClaimPlan, + Stage4SumcheckBatchPlan, + Stage4SumcheckDriverPlan, + Stage4SumcheckInstanceResultPlan, + Stage4SumcheckEvalPlan, + Stage4PointSlicePlan, + Stage4PointConcatPlan, + Stage4OpeningClaimPlan, + Stage4OpeningClaimEqualityPlan, + Stage4OpeningBatchPlan +); diff --git a/crates/jolt-equivalence/src/plan_adapters/generated_stage5.rs b/crates/jolt-equivalence/src/plan_adapters/generated_stage5.rs new file mode 100644 index 0000000000..0033acb89a --- /dev/null +++ b/crates/jolt-equivalence/src/plan_adapters/generated_stage5.rs @@ -0,0 +1,28 @@ +use bolt::protocols::jolt::Stage5CpuProgram as CompilerStage5CpuProgram; +use jolt_verifier::stages::stage5 as generated_stage5; + +define_stage_adapter!( + generated, + leak_generated_stage5_verifier_program, + CompilerStage5CpuProgram, + generated_stage5, + Stage5VerifierProgramPlan, + Stage5Params, + Stage5ProgramStepPlan, + Stage5TranscriptSqueezePlan, + Stage5TranscriptAbsorbBytesPlan, + Stage5OpeningInputPlan, + Stage5FieldConstantPlan, + Stage5FieldExprPlan, + Stage5KernelPlan, + Stage5SumcheckClaimPlan, + Stage5SumcheckBatchPlan, + Stage5SumcheckDriverPlan, + Stage5SumcheckInstanceResultPlan, + Stage5SumcheckEvalPlan, + Stage5PointSlicePlan, + Stage5PointConcatPlan, + Stage5OpeningClaimPlan, + Stage5OpeningClaimEqualityPlan, + Stage5OpeningBatchPlan +); diff --git a/crates/jolt-equivalence/src/plan_adapters/generated_stage6.rs b/crates/jolt-equivalence/src/plan_adapters/generated_stage6.rs new file mode 100644 index 0000000000..76072dd614 --- /dev/null +++ b/crates/jolt-equivalence/src/plan_adapters/generated_stage6.rs @@ -0,0 +1,29 @@ +use bolt::protocols::jolt::Stage6CpuProgram as CompilerStage6CpuProgram; +use jolt_verifier::stages::stage6 as generated_stage6; + +define_stage_adapter!( + generated, + leak_generated_stage6_verifier_program, + CompilerStage6CpuProgram, + generated_stage6, + Stage6VerifierProgramPlan, + Stage6Params, + Stage6ProgramStepPlan, + Stage6TranscriptSqueezePlan, + Stage6TranscriptAbsorbBytesPlan, + Stage6OpeningInputPlan, + Stage6FieldConstantPlan, + Stage6FieldExprPlan, + Stage6KernelPlan, + Stage6SumcheckClaimPlan, + Stage6SumcheckBatchPlan, + Stage6SumcheckDriverPlan, + Stage6SumcheckInstanceResultPlan, + Stage6SumcheckEvalPlan, + Stage6PointSlicePlan, + Stage6PointConcatPlan, + Stage6OpeningClaimPlan, + Stage6OpeningClaimEqualityPlan, + Stage6OpeningBatchPlan, + point_zero = Stage6PointZeroPlan +); diff --git a/crates/jolt-equivalence/src/plan_adapters/generated_stage7.rs b/crates/jolt-equivalence/src/plan_adapters/generated_stage7.rs new file mode 100644 index 0000000000..457ac30812 --- /dev/null +++ b/crates/jolt-equivalence/src/plan_adapters/generated_stage7.rs @@ -0,0 +1,29 @@ +use bolt::protocols::jolt::Stage7CpuProgram as CompilerStage7CpuProgram; +use jolt_verifier::stages::stage7 as generated_stage7; + +define_stage_adapter!( + generated, + leak_generated_stage7_verifier_program, + CompilerStage7CpuProgram, + generated_stage7, + Stage7VerifierProgramPlan, + Stage7Params, + Stage7ProgramStepPlan, + Stage7TranscriptSqueezePlan, + Stage7TranscriptAbsorbBytesPlan, + Stage7OpeningInputPlan, + Stage7FieldConstantPlan, + Stage7FieldExprPlan, + Stage7KernelPlan, + Stage7SumcheckClaimPlan, + Stage7SumcheckBatchPlan, + Stage7SumcheckDriverPlan, + Stage7SumcheckInstanceResultPlan, + Stage7SumcheckEvalPlan, + Stage7PointSlicePlan, + Stage7PointConcatPlan, + Stage7OpeningClaimPlan, + Stage7OpeningClaimEqualityPlan, + Stage7OpeningBatchPlan, + point_zero = Stage7PointZeroPlan +); diff --git a/crates/jolt-equivalence/src/plan_adapters/stage1.rs b/crates/jolt-equivalence/src/plan_adapters/stage1.rs new file mode 100644 index 0000000000..f6263d2e9d --- /dev/null +++ b/crates/jolt-equivalence/src/plan_adapters/stage1.rs @@ -0,0 +1,20 @@ +use bolt::protocols::jolt::Stage1CpuProgram as CompilerStage1CpuProgram; +use jolt_kernels::stage1 as kernel_stage1; + +define_stage1_adapter!( + kernel, + leak_stage1_program, + CompilerStage1CpuProgram, + kernel_stage1, + Stage1CpuProgramPlan, + Stage1Params, + Stage1TranscriptSqueezePlan, + Stage1SumcheckClaimPlan, + Stage1SumcheckBatchPlan, + Stage1SumcheckDriverPlan, + Stage1SumcheckInstanceResultPlan, + Stage1SumcheckEvalPlan, + Stage1OpeningClaimPlan, + Stage1OpeningBatchPlan, + kernels = Stage1KernelPlan +); diff --git a/crates/jolt-equivalence/src/plan_adapters/stage2.rs b/crates/jolt-equivalence/src/plan_adapters/stage2.rs new file mode 100644 index 0000000000..e67ecd6c86 --- /dev/null +++ b/crates/jolt-equivalence/src/plan_adapters/stage2.rs @@ -0,0 +1,26 @@ +use bolt::protocols::jolt::Stage2CpuProgram as CompilerStage2CpuProgram; +use jolt_kernels::stage2 as kernel_stage2; + +define_stage_adapter_no_absorb!( + kernel, + leak_stage2_program, + CompilerStage2CpuProgram, + kernel_stage2, + Stage2CpuProgramPlan, + Stage2Params, + Stage2ProgramStepPlan, + Stage2TranscriptSqueezePlan, + Stage2OpeningInputPlan, + Stage2FieldConstantPlan, + Stage2FieldExprPlan, + Stage2SumcheckClaimPlan, + Stage2SumcheckBatchPlan, + Stage2SumcheckDriverPlan, + Stage2SumcheckInstanceResultPlan, + Stage2SumcheckEvalPlan, + Stage2PointSlicePlan, + Stage2PointConcatPlan, + Stage2OpeningClaimPlan, + Stage2OpeningBatchPlan, + kernels = Stage2KernelPlan +); diff --git a/crates/jolt-equivalence/src/plan_adapters/stage3.rs b/crates/jolt-equivalence/src/plan_adapters/stage3.rs new file mode 100644 index 0000000000..6824047c1f --- /dev/null +++ b/crates/jolt-equivalence/src/plan_adapters/stage3.rs @@ -0,0 +1,27 @@ +use bolt::protocols::jolt::Stage3CpuProgram as CompilerStage3CpuProgram; +use jolt_kernels::stage3 as kernel_stage3; + +define_stage_adapter_no_absorb!( + kernel, + leak_stage3_program, + CompilerStage3CpuProgram, + kernel_stage3, + Stage3CpuProgramPlan, + Stage3Params, + Stage3ProgramStepPlan, + Stage3TranscriptSqueezePlan, + Stage3OpeningInputPlan, + Stage3FieldConstantPlan, + Stage3FieldExprPlan, + Stage3SumcheckClaimPlan, + Stage3SumcheckBatchPlan, + Stage3SumcheckDriverPlan, + Stage3SumcheckInstanceResultPlan, + Stage3SumcheckEvalPlan, + Stage3PointSlicePlan, + Stage3PointConcatPlan, + Stage3OpeningClaimPlan, + Stage3OpeningBatchPlan, + kernels = Stage3KernelPlan, + opening_equalities = Stage3OpeningClaimEqualityPlan +); diff --git a/crates/jolt-equivalence/src/plan_adapters/stage4.rs b/crates/jolt-equivalence/src/plan_adapters/stage4.rs new file mode 100644 index 0000000000..5a973a7c98 --- /dev/null +++ b/crates/jolt-equivalence/src/plan_adapters/stage4.rs @@ -0,0 +1,28 @@ +use bolt::protocols::jolt::Stage4CpuProgram as CompilerStage4CpuProgram; +use jolt_kernels::stage4 as kernel_stage4; + +define_stage_adapter!( + kernel, + leak_stage4_program, + CompilerStage4CpuProgram, + kernel_stage4, + Stage4CpuProgramPlan, + Stage4Params, + Stage4ProgramStepPlan, + Stage4TranscriptSqueezePlan, + Stage4TranscriptAbsorbBytesPlan, + Stage4OpeningInputPlan, + Stage4FieldConstantPlan, + Stage4FieldExprPlan, + Stage4KernelPlan, + Stage4SumcheckClaimPlan, + Stage4SumcheckBatchPlan, + Stage4SumcheckDriverPlan, + Stage4SumcheckInstanceResultPlan, + Stage4SumcheckEvalPlan, + Stage4PointSlicePlan, + Stage4PointConcatPlan, + Stage4OpeningClaimPlan, + Stage4OpeningClaimEqualityPlan, + Stage4OpeningBatchPlan +); diff --git a/crates/jolt-equivalence/src/plan_adapters/stage5.rs b/crates/jolt-equivalence/src/plan_adapters/stage5.rs new file mode 100644 index 0000000000..58bfe583c8 --- /dev/null +++ b/crates/jolt-equivalence/src/plan_adapters/stage5.rs @@ -0,0 +1,28 @@ +use bolt::protocols::jolt::Stage5CpuProgram as CompilerStage5CpuProgram; +use jolt_kernels::stage5 as kernel_stage5; + +define_stage_adapter!( + kernel, + leak_stage5_program, + CompilerStage5CpuProgram, + kernel_stage5, + Stage5CpuProgramPlan, + Stage5Params, + Stage5ProgramStepPlan, + Stage5TranscriptSqueezePlan, + Stage5TranscriptAbsorbBytesPlan, + Stage5OpeningInputPlan, + Stage5FieldConstantPlan, + Stage5FieldExprPlan, + Stage5KernelPlan, + Stage5SumcheckClaimPlan, + Stage5SumcheckBatchPlan, + Stage5SumcheckDriverPlan, + Stage5SumcheckInstanceResultPlan, + Stage5SumcheckEvalPlan, + Stage5PointSlicePlan, + Stage5PointConcatPlan, + Stage5OpeningClaimPlan, + Stage5OpeningClaimEqualityPlan, + Stage5OpeningBatchPlan +); diff --git a/crates/jolt-equivalence/src/plan_adapters/stage6.rs b/crates/jolt-equivalence/src/plan_adapters/stage6.rs new file mode 100644 index 0000000000..8423eec48c --- /dev/null +++ b/crates/jolt-equivalence/src/plan_adapters/stage6.rs @@ -0,0 +1,29 @@ +use bolt::protocols::jolt::Stage6CpuProgram as CompilerStage6CpuProgram; +use jolt_kernels::stage6 as kernel_stage6; + +define_stage_adapter!( + kernel, + leak_stage6_program, + CompilerStage6CpuProgram, + kernel_stage6, + Stage6CpuProgramPlan, + Stage6Params, + Stage6ProgramStepPlan, + Stage6TranscriptSqueezePlan, + Stage6TranscriptAbsorbBytesPlan, + Stage6OpeningInputPlan, + Stage6FieldConstantPlan, + Stage6FieldExprPlan, + Stage6KernelPlan, + Stage6SumcheckClaimPlan, + Stage6SumcheckBatchPlan, + Stage6SumcheckDriverPlan, + Stage6SumcheckInstanceResultPlan, + Stage6SumcheckEvalPlan, + Stage6PointSlicePlan, + Stage6PointConcatPlan, + Stage6OpeningClaimPlan, + Stage6OpeningClaimEqualityPlan, + Stage6OpeningBatchPlan, + point_zero = Stage6PointZeroPlan +); diff --git a/crates/jolt-equivalence/src/plan_adapters/stage7.rs b/crates/jolt-equivalence/src/plan_adapters/stage7.rs new file mode 100644 index 0000000000..e83b4ff5ec --- /dev/null +++ b/crates/jolt-equivalence/src/plan_adapters/stage7.rs @@ -0,0 +1,29 @@ +use bolt::protocols::jolt::Stage7CpuProgram as CompilerStage7CpuProgram; +use jolt_kernels::stage7 as kernel_stage7; + +define_stage_adapter!( + kernel, + leak_stage7_program, + CompilerStage7CpuProgram, + kernel_stage7, + Stage7CpuProgramPlan, + Stage7Params, + Stage7ProgramStepPlan, + Stage7TranscriptSqueezePlan, + Stage7TranscriptAbsorbBytesPlan, + Stage7OpeningInputPlan, + Stage7FieldConstantPlan, + Stage7FieldExprPlan, + Stage7KernelPlan, + Stage7SumcheckClaimPlan, + Stage7SumcheckBatchPlan, + Stage7SumcheckDriverPlan, + Stage7SumcheckInstanceResultPlan, + Stage7SumcheckEvalPlan, + Stage7PointSlicePlan, + Stage7PointConcatPlan, + Stage7OpeningClaimPlan, + Stage7OpeningClaimEqualityPlan, + Stage7OpeningBatchPlan, + point_zero = Stage7PointZeroPlan +); diff --git a/crates/jolt-equivalence/src/tamper.rs b/crates/jolt-equivalence/src/tamper.rs new file mode 100644 index 0000000000..27a808ae75 --- /dev/null +++ b/crates/jolt-equivalence/src/tamper.rs @@ -0,0 +1,894 @@ +//! Malformed proof fixtures for verifier rejection tests. + +#![expect( + clippy::expect_used, + reason = "tamper gates should fail fast when honest prefix setup fails" +)] + +use jolt_dory::{DoryProof, DoryScheme}; +use jolt_field::{Field, Fr}; +use jolt_kernels::stage1::{ + Stage1CpuProgramPlan as KernelStage1CpuProgramPlan, Stage1ExecutionArtifacts, Stage1Proof, +}; +use jolt_kernels::stage2::{ + Stage2CpuProgramPlan as KernelStage2CpuProgramPlan, Stage2ExecutionArtifacts, + Stage2OpeningInputValue, Stage2Proof, Stage2RamData, +}; +use jolt_kernels::stage3::Stage3ExecutionArtifacts; +use jolt_kernels::stage4::Stage4ExecutionArtifacts; +use jolt_openings::CommitmentScheme; +use jolt_poly::Polynomial; +use jolt_poly::UnivariatePoly; +use jolt_transcript::Transcript; +use jolt_verifier::{ + JoltStage6VerifierData, JoltStageOpeningInputValue, JoltStageProof, Stage1VerifierProgramPlan, + Stage2VerifierProgramPlan, Stage3VerifierProgramPlan, Stage4VerifierProgramPlan, + Stage5VerifierProgramPlan, Stage6VerifierProgramPlan, Stage7VerifierProgramPlan, +}; + +use crate::checkpoint::assert_state_history_match; +use crate::commitment_oracle::{ + transcript_with_bolt_commitment_trace, transcript_with_bolt_preamble, BoltCommitmentTrace, + BoltPreambleSource, BoltTranscript, +}; +use crate::core_oracle::CoreMuldivCommitmentFixture; + +fn stage2_opening_inputs_from_artifacts( + program: &'static KernelStage2CpuProgramPlan, + stage1_artifacts: &Stage1ExecutionArtifacts, +) -> Vec> { + jolt_prover::stage2_opening_inputs_from_artifacts(program, stage1_artifacts) + .expect("generated prover derives Stage 2 opening inputs from artifacts") +} + +macro_rules! tampered_sumcheck_coefficient { + ($proof:expr, $sumcheck_index:expr) => {{ + let mut tampered = $proof.clone(); + let round_poly = &mut tampered.sumchecks[$sumcheck_index].proof.round_polynomials[0]; + let mut coefficients = round_poly.clone().into_coefficients(); + coefficients[0] += Fr::from_u64(1); + *round_poly = UnivariatePoly::new(coefficients); + tampered + }}; +} + +macro_rules! tampered_sumcheck_eval { + ($proof:expr, $sumcheck_index:expr) => {{ + let mut tampered = $proof.clone(); + tampered.sumchecks[$sumcheck_index].evals[0].value += Fr::from_u64(1); + tampered + }}; +} + +macro_rules! tampered_sumcheck_point { + ($proof:expr, $sumcheck_index:expr) => {{ + let mut tampered = $proof.clone(); + tampered.sumchecks[$sumcheck_index].point[0] += Fr::from_u64(1); + tampered + }}; +} + +macro_rules! assert_batched_sumcheck_tampers { + ($assert_fn:ident, $proof:expr, $sumcheck_index:expr, $prefix:literal) => {{ + $assert_fn( + tampered_sumcheck_coefficient!($proof, $sumcheck_index), + concat!($prefix, " accepted a tampered batched sumcheck coefficient"), + ); + $assert_fn( + tampered_sumcheck_eval!($proof, $sumcheck_index), + concat!($prefix, " accepted a tampered batched opening evaluation"), + ); + $assert_fn( + tampered_sumcheck_point!($proof, $sumcheck_index), + concat!($prefix, " accepted a tampered batched sumcheck point"), + ); + }}; +} + +fn assert_opening_input_tampers( + openings: &[jolt_verifier::JoltStageOpeningInputValue], + stage: &str, + mut assert_tamper_rejected: F, +) where + F: FnMut(&[jolt_verifier::JoltStageOpeningInputValue], &str), +{ + let tampered_openings = tampered_opening_input_eval(openings); + assert_tamper_rejected( + &tampered_openings, + &format!("{stage} verifier accepted a tampered opening-claim input evaluation"), + ); + let missing_openings = opening_inputs_without_first(openings); + assert_tamper_rejected( + &missing_openings, + &format!("{stage} verifier accepted a missing opening-claim input"), + ); + let extra_openings = opening_inputs_with_extra_first(openings); + assert_tamper_rejected( + &extra_openings, + &format!("{stage} verifier accepted an extra opening-claim input"), + ); + let short_point_openings = opening_inputs_with_short_first_point(openings); + assert_tamper_rejected( + &short_point_openings, + &format!("{stage} verifier accepted an opening-claim input with invalid point arity"), + ); +} + +fn tampered_opening_input_eval( + openings: &[jolt_verifier::JoltStageOpeningInputValue], +) -> Vec { + let mut tampered = openings.to_vec(); + tampered + .get_mut(0) + .expect("stage has at least one opening input") + .eval += Fr::from_u64(1); + tampered +} + +fn opening_inputs_without_first(openings: &[T]) -> Vec { + assert!(!openings.is_empty(), "stage has at least one opening input"); + openings[1..].to_vec() +} + +fn opening_inputs_with_extra_first(openings: &[T]) -> Vec { + let mut tampered = openings.to_vec(); + tampered.push( + openings + .first() + .expect("stage has at least one opening input") + .clone(), + ); + tampered +} + +fn opening_inputs_with_short_first_point( + openings: &[jolt_verifier::JoltStageOpeningInputValue], +) -> Vec { + let mut tampered = openings.to_vec(); + let _removed_coordinate = tampered + .first_mut() + .expect("stage has at least one opening input") + .point + .pop() + .expect("opening input has at least one point coordinate"); + tampered +} + +fn tampered_opening_input_suffix_point( + openings: &[jolt_verifier::JoltStageOpeningInputValue], + symbol: &'static str, + prefix_len: usize, +) -> Vec { + let mut tampered = openings.to_vec(); + let point = tampered + .iter_mut() + .find(|opening| opening.symbol == symbol) + .expect("stage has opening input symbol") + .point + .get_mut(prefix_len) + .expect("opening input has a suffix point coordinate"); + *point += Fr::from_u64(1); + tampered +} + +fn assert_generated_jolt_prefix_tamper_rejected

( + preamble: &P, + proof: &jolt_verifier::JoltProof, + inputs: jolt_verifier::JoltVerifierInputs<'_>, + programs: jolt_verifier::JoltVerifierPrograms, + message: &str, +) where + P: BoltPreambleSource, +{ + let mut transcript = transcript_with_bolt_preamble(preamble); + let result = if !inputs.stage7_openings.is_empty() { + jolt_verifier::verify_jolt_through_stage7_with_programs( + proof, + inputs, + programs, + &mut transcript, + ) + } else if !inputs.stage6_openings.is_empty() { + jolt_verifier::verify_jolt_through_stage6_with_programs( + proof, + inputs, + programs, + &mut transcript, + ) + } else { + jolt_verifier::verify_jolt_through_stage5_with_programs( + proof, + inputs, + programs, + &mut transcript, + ) + }; + assert!(result.is_err(), "generated monolithic {message}"); +} + +macro_rules! assert_generated_stage_and_prefix_tamper_rejected { + ($preamble:expr, $message:expr, $inputs:expr, $programs:expr, $stage_result:expr, $prefix_proof:expr $(,)?) => {{ + assert!($stage_result.is_err(), "generated {}", $message); + assert_generated_jolt_prefix_tamper_rejected( + $preamble, + &$prefix_proof, + $inputs, + $programs, + $message, + ); + }}; +} + +/// Produces a valid Dory proof for an unrelated polynomial/opening claim. +fn unrelated_dory_proof() -> DoryProof { + let prover_setup = DoryScheme::setup_prover(1); + let poly = Polynomial::new(vec![Fr::from_u64(0), Fr::from_u64(1)]); + let point = vec![Fr::from_u64(7)]; + let mut transcript = jolt_transcript::Blake2bTranscript::new(b"unrelated-dory-proof"); + DoryScheme::open( + &poly, + &point, + point[0], + &prover_setup, + None, + &mut transcript, + ) +} + +pub(crate) struct MonolithicJoltTamperInput<'a> { + pub(crate) preamble: &'a CoreMuldivCommitmentFixture, + pub(crate) proof: &'a jolt_verifier::JoltProof, + pub(crate) inputs: jolt_verifier::JoltVerifierInputs<'a>, + pub(crate) programs: jolt_verifier::JoltVerifierPrograms, +} + +pub(crate) fn assert_monolithic_jolt_tamper_rejected(input: MonolithicJoltTamperInput<'_>) { + let mut inputs_without_setup = input.inputs; + inputs_without_setup.evaluation_setup = None; + + let verify = |proof: &jolt_verifier::JoltProof, + inputs: jolt_verifier::JoltVerifierInputs<'_>| { + let mut transcript = transcript_with_bolt_preamble(input.preamble); + jolt_verifier::verify_jolt_with_programs(proof, inputs, input.programs, &mut transcript) + }; + + macro_rules! assert_verify_error { + ($result:expr, $error:pat, $message:expr $(,)?) => { + assert!(matches!($result, $error), $message); + }; + } + + assert_verify_error!( + verify(input.proof, inputs_without_setup), + Err(jolt_verifier::JoltVerifyError::Evaluation( + jolt_verifier::JoltEvaluationProofError::MissingVerifierSetup + )), + "generated monolithic verifier accepted evaluation proof without verifier setup", + ); + + let mut missing_evaluation_proof = input.proof.clone(); + missing_evaluation_proof.evaluation = None; + assert_verify_error!( + verify(&missing_evaluation_proof, input.inputs), + Err(jolt_verifier::JoltVerifyError::Evaluation( + jolt_verifier::JoltEvaluationProofError::MissingProof + )), + "generated monolithic verifier accepted missing evaluation proof with verifier setup", + ); + + assert_verify_error!( + verify(&missing_evaluation_proof, inputs_without_setup), + Err(jolt_verifier::JoltVerifyError::Evaluation( + jolt_verifier::JoltEvaluationProofError::MissingProof + )), + "generated monolithic verifier accepted missing evaluation proof without verifier setup", + ); + + let mut tampered_evaluation_proof = input.proof.clone(); + tampered_evaluation_proof + .evaluation + .as_mut() + .expect("evaluation proof") + .joint_opening_proof = unrelated_dory_proof(); + assert_verify_error!( + verify(&tampered_evaluation_proof, input.inputs), + Err(jolt_verifier::JoltVerifyError::Evaluation(_)), + "generated monolithic verifier accepted a tampered evaluation proof", + ); + + let stage8_source_symbol = input.programs.stage8.evaluation_point_source.source_claim; + let stage7_address_prefix_len = input + .proof + .stage7 + .sumchecks + .first() + .expect("monolithic proof has a Stage 7 sumcheck") + .point + .len(); + let tampered_stage7_openings = tampered_opening_input_suffix_point( + input.inputs.stage7_openings, + stage8_source_symbol, + stage7_address_prefix_len, + ); + let mut tampered_stage7_opening_inputs = input.inputs; + tampered_stage7_opening_inputs.stage7_openings = &tampered_stage7_openings; + assert_verify_error!( + verify(input.proof, tampered_stage7_opening_inputs), + Err(jolt_verifier::JoltVerifyError::Evaluation(_)), + "generated monolithic verifier accepted a tampered Stage 8 opening-point suffix", + ); + + let mut missing_commitment_proof = input.proof.clone(); + *missing_commitment_proof + .commitments + .get_mut(0) + .expect("monolithic proof has a main commitment") = None; + assert_verify_error!( + verify(&missing_commitment_proof, input.inputs), + Err(jolt_verifier::JoltVerifyError::Commitment(_)), + "generated monolithic verifier accepted a missing required commitment", + ); + + macro_rules! assert_missing_stage_rejected { + ($field:ident, $variant:ident, $stage:literal) => {{ + let mut missing_stage_proof = input.proof.clone(); + missing_stage_proof.$field.sumchecks.clear(); + assert_verify_error!( + verify(&missing_stage_proof, input.inputs), + Err(jolt_verifier::JoltVerifyError::$variant(_)), + concat!( + "generated monolithic verifier accepted a missing ", + $stage, + " proof" + ), + ); + }}; + } + + assert_missing_stage_rejected!(stage1_outer, Stage1Outer, "Stage 1 outer"); + assert_missing_stage_rejected!(stage2, Stage2, "Stage 2"); + assert_missing_stage_rejected!(stage3, Stage3, "Stage 3"); + assert_missing_stage_rejected!(stage4, Stage4, "Stage 4"); + assert_missing_stage_rejected!(stage5, Stage5, "Stage 5"); + assert_missing_stage_rejected!(stage6, Stage6, "Stage 6"); + assert_missing_stage_rejected!(stage7, Stage7, "Stage 7"); + + let mut wrong_stage_slot_proof = input.proof.clone(); + std::mem::swap( + &mut wrong_stage_slot_proof.stage6, + &mut wrong_stage_slot_proof.stage7, + ); + assert_verify_error!( + verify(&wrong_stage_slot_proof, input.inputs), + Err(jolt_verifier::JoltVerifyError::Stage6(_)), + "generated monolithic verifier accepted a stage proof in the wrong slot" + ); +} + +pub fn assert_bolt_stage1_tamper_rejected( + stage1_verifier_plan: &'static KernelStage1CpuProgramPlan, + generated_stage1_verifier_plan: &'static Stage1VerifierProgramPlan, + proof: &Stage1Proof, + stage1_start_transcript: &BoltTranscript, +) { + let assert_stage1_tamper_rejected = |tampered: Stage1Proof, message: &str| { + let mut transcript = stage1_start_transcript.clone(); + + let result = jolt_prover::replay_stage1_outer_proof_with_program( + stage1_verifier_plan, + &tampered, + &mut transcript, + ); + assert!(result.is_err(), "{message}"); + + let mut generated_transcript = stage1_start_transcript.clone(); + let generated_tampered = jolt_prover::stage1_outer_proof_from_kernel_proof(&tampered); + let generated_result = jolt_verifier::verify_stage1_outer_with_program( + generated_stage1_verifier_plan, + &generated_tampered, + &mut generated_transcript, + ); + assert!(generated_result.is_err(), "generated {message}"); + }; + + assert_stage1_tamper_rejected( + tampered_sumcheck_coefficient!(proof, 1), + "Bolt Stage 1 verifier accepted a tampered remaining sumcheck coefficient", + ); + + assert_stage1_tamper_rejected( + tampered_sumcheck_coefficient!(proof, 0), + "Bolt Stage 1 verifier accepted a tampered uniskip sumcheck coefficient", + ); + + assert_stage1_tamper_rejected( + tampered_sumcheck_point!(proof, 0), + "Bolt Stage 1 verifier accepted a tampered uniskip point", + ); + + assert_stage1_tamper_rejected( + tampered_sumcheck_eval!(proof, 0), + "Bolt Stage 1 verifier accepted a tampered uniskip eval", + ); + + assert_stage1_tamper_rejected( + tampered_sumcheck_point!(proof, 1), + "Bolt Stage 1 verifier accepted a tampered remaining sumcheck point", + ); +} + +pub struct BoltStage2ChainVerifierInput<'a> { + pub fixture: &'a CoreMuldivCommitmentFixture, + pub commitment_verifier_trace: &'a BoltCommitmentTrace, + pub stage1_prover_plan: &'static KernelStage1CpuProgramPlan, + pub stage2_prover_plan: &'static KernelStage2CpuProgramPlan, + pub generated_stage2_verifier_plan: &'static Stage2VerifierProgramPlan, + pub stage1_artifacts: &'a Stage1ExecutionArtifacts, + pub stage2_artifacts: &'a Stage2ExecutionArtifacts, + pub ram_data: &'a Stage2RamData<'a>, + pub prover_transcript: &'a BoltTranscript, +} + +pub fn assert_bolt_chain_verifier_accepts_stage2_product_uniskip( + input: BoltStage2ChainVerifierInput<'_>, +) { + let mut verifier_transcript = + transcript_with_bolt_commitment_trace(input.fixture, input.commitment_verifier_trace); + + let stage1_proof = Stage1Proof::from(input.stage1_artifacts.clone()); + let verified_stage1 = jolt_prover::replay_stage1_outer_proof_with_program( + input.stage1_prover_plan, + &stage1_proof, + &mut verifier_transcript, + ) + .expect("Bolt Stage 1 verifier accepts Bolt prover proof"); + assert_eq!( + input.stage1_artifacts.sumchecks.len(), + verified_stage1.sumchecks.len() + ); + assert_eq!( + input.stage1_artifacts.opening_values.len(), + verified_stage1.opening_values.len() + ); + + let stage2_openings = + stage2_opening_inputs_from_artifacts(input.stage2_prover_plan, &verified_stage1); + let generated_stage2_openings = + jolt_prover::verifier_opening_inputs_from_kernel(&stage2_openings); + let generated_ram_data_storage = jolt_prover::stage2_verifier_ram_data(input.ram_data); + let generated_ram_data = generated_ram_data_storage.as_input(); + let stage2_proof = Stage2Proof::from(input.stage2_artifacts.clone()); + let stage2_start_transcript = verifier_transcript.clone(); + let verified_stage2 = jolt_prover::replay_stage2_proof_with_program( + input.stage2_prover_plan, + &stage2_proof, + &stage2_openings, + Some(input.ram_data), + &mut verifier_transcript, + ) + .expect("Bolt Stage 2 verifier accepts Bolt prover proof"); + + assert_eq!( + input.stage2_artifacts.sumchecks.len(), + verified_stage2.sumchecks.len() + ); + assert_eq!( + input.stage2_artifacts.sumchecks[0].point, + verified_stage2.sumchecks[0].point + ); + assert_eq!( + input.stage2_artifacts.sumchecks[0].evals[0].value, + verified_stage2.sumchecks[0].evals[0].value + ); + assert_state_history_match(input.prover_transcript.log(), verifier_transcript.log()); + + let assert_stage2_product_tamper_rejected = + |tampered_stage2_artifacts: Stage2ExecutionArtifacts, message: &str| { + let mut tamper_transcript = stage2_start_transcript.clone(); + let tampered_stage2_proof = Stage2Proof::from(tampered_stage2_artifacts.clone()); + let tamper_result = jolt_prover::replay_stage2_proof_with_program( + input.stage2_prover_plan, + &tampered_stage2_proof, + &stage2_openings, + Some(input.ram_data), + &mut tamper_transcript, + ); + assert!(tamper_result.is_err(), "{message}"); + + let mut generated_tamper_transcript = stage2_start_transcript.clone(); + let generated_tampered_stage2_proof = + jolt_prover::stage2_proof(&tampered_stage2_artifacts); + let generated_tamper_result = jolt_verifier::verify_stage2_with_program( + input.generated_stage2_verifier_plan, + &generated_tampered_stage2_proof, + &generated_stage2_openings, + Some(&generated_ram_data), + &mut generated_tamper_transcript, + ); + assert!(generated_tamper_result.is_err(), "generated {message}"); + }; + + assert_stage2_product_tamper_rejected( + tampered_sumcheck_coefficient!(input.stage2_artifacts, 0), + "Bolt Stage 2 verifier accepted a tampered product uni-skip coefficient", + ); + + assert_stage2_product_tamper_rejected( + tampered_sumcheck_eval!(input.stage2_artifacts, 0), + "Bolt Stage 2 verifier accepted a tampered product uni-skip opening evaluation", + ); + + assert_stage2_product_tamper_rejected( + tampered_sumcheck_point!(input.stage2_artifacts, 0), + "Bolt Stage 2 verifier accepted a tampered product uni-skip point", + ); +} + +pub struct Stage2BatchedTamperInput<'a> { + pub stage2_prover_plan: &'static KernelStage2CpuProgramPlan, + pub generated_stage2_verifier_plan: &'static Stage2VerifierProgramPlan, + pub stage2_start_transcript: &'a BoltTranscript, + pub stage2_openings: &'a [Stage2OpeningInputValue], + pub stage2_artifacts: &'a Stage2ExecutionArtifacts, + pub ram_data: &'a Stage2RamData<'a>, +} + +pub fn assert_bolt_stage2_batched_tamper_rejected(input: Stage2BatchedTamperInput<'_>) { + let generated_stage2_openings = + jolt_prover::verifier_opening_inputs_from_kernel(input.stage2_openings); + let generated_ram_data_storage = jolt_prover::stage2_verifier_ram_data(input.ram_data); + let generated_ram_data = generated_ram_data_storage.as_input(); + + let assert_stage2_tamper_rejected = + |tampered_stage2_artifacts: Stage2ExecutionArtifacts, message: &str| { + let mut tamper_transcript = input.stage2_start_transcript.clone(); + let tampered_stage2_proof = Stage2Proof::from(tampered_stage2_artifacts.clone()); + let tamper_result = jolt_prover::replay_stage2_proof_with_program( + input.stage2_prover_plan, + &tampered_stage2_proof, + input.stage2_openings, + Some(input.ram_data), + &mut tamper_transcript, + ); + assert!(tamper_result.is_err(), "{message}"); + + let mut generated_tamper_transcript = input.stage2_start_transcript.clone(); + let generated_tampered_stage2_proof = + jolt_prover::stage2_proof(&tampered_stage2_artifacts); + let generated_tamper_result = jolt_verifier::verify_stage2_with_program( + input.generated_stage2_verifier_plan, + &generated_tampered_stage2_proof, + &generated_stage2_openings, + Some(&generated_ram_data), + &mut generated_tamper_transcript, + ); + assert!(generated_tamper_result.is_err(), "generated {message}"); + }; + + assert_batched_sumcheck_tampers!( + assert_stage2_tamper_rejected, + input.stage2_artifacts, + 1, + "Bolt Stage 2 verifier" + ); +} + +pub(crate) struct Stage6TamperInput<'a> { + pub(crate) preamble: &'a CoreMuldivCommitmentFixture, + pub(crate) commitment_verifier_trace: &'a BoltCommitmentTrace, + pub(crate) verifier_transcript: &'a BoltTranscript, + pub(crate) verifier_plan: &'static Stage6VerifierProgramPlan, + pub(crate) proof: &'a JoltStageProof, + pub(crate) openings: &'a [JoltStageOpeningInputValue], + pub(crate) data: &'a JoltStage6VerifierData, + pub(crate) stage1_artifacts: &'a Stage1ExecutionArtifacts, + pub(crate) stage2_artifacts: &'a Stage2ExecutionArtifacts, + pub(crate) stage3_artifacts: &'a Stage3ExecutionArtifacts, + pub(crate) stage4_artifacts: &'a Stage4ExecutionArtifacts, + pub(crate) stage5_proof: &'a JoltStageProof, + pub(crate) jolt_inputs: jolt_verifier::JoltVerifierInputs<'a>, + pub(crate) programs: jolt_verifier::JoltVerifierPrograms, +} + +pub(crate) fn assert_bolt_stage6_tamper_rejected(input: Stage6TamperInput<'_>) { + let assert_tamper_rejected = |tampered_stage6_proof: JoltStageProof, message: &str| { + assert_generated_stage_and_prefix_tamper_rejected!( + input.preamble, + message, + input.jolt_inputs, + input.programs, + { + let mut transcript = input.verifier_transcript.clone(); + jolt_verifier::verify_stage6_with_program( + input.verifier_plan, + &tampered_stage6_proof, + input.openings, + Some(input.data), + &mut transcript, + ) + }, + jolt_prover::jolt_proof_through_stage6( + &input.commitment_verifier_trace.commitments, + input.stage1_artifacts, + input.stage2_artifacts, + input.stage3_artifacts, + input.stage4_artifacts, + input.stage5_proof, + &tampered_stage6_proof, + ), + ); + }; + + assert_batched_sumcheck_tampers!(assert_tamper_rejected, input.proof, 0, "Stage 6 verifier"); + + let assert_opening_input_tamper_rejected = + |tampered_openings: &[JoltStageOpeningInputValue], message: &str| { + let mut generated_tamper_transcript = input.verifier_transcript.clone(); + let generated_tamper_result = jolt_verifier::verify_stage6_with_program( + input.verifier_plan, + input.proof, + tampered_openings, + Some(input.data), + &mut generated_tamper_transcript, + ); + assert!(generated_tamper_result.is_err(), "generated {message}"); + + let generated_jolt_proof = jolt_prover::jolt_proof_through_stage6( + &input.commitment_verifier_trace.commitments, + input.stage1_artifacts, + input.stage2_artifacts, + input.stage3_artifacts, + input.stage4_artifacts, + input.stage5_proof, + input.proof, + ); + let mut tampered_inputs = input.jolt_inputs; + tampered_inputs.stage6_openings = tampered_openings; + assert_generated_jolt_prefix_tamper_rejected( + input.preamble, + &generated_jolt_proof, + tampered_inputs, + input.programs, + message, + ); + }; + + assert_opening_input_tampers( + input.openings, + "Stage 6", + assert_opening_input_tamper_rejected, + ); +} + +pub(crate) struct Stage7TamperInput<'a> { + pub(crate) preamble: &'a CoreMuldivCommitmentFixture, + pub(crate) commitment_verifier_trace: &'a BoltCommitmentTrace, + pub(crate) verifier_transcript: &'a BoltTranscript, + pub(crate) verifier_plan: &'static Stage7VerifierProgramPlan, + pub(crate) proof: &'a JoltStageProof, + pub(crate) openings: &'a [JoltStageOpeningInputValue], + pub(crate) stage1_artifacts: &'a Stage1ExecutionArtifacts, + pub(crate) stage2_artifacts: &'a Stage2ExecutionArtifacts, + pub(crate) stage3_artifacts: &'a Stage3ExecutionArtifacts, + pub(crate) stage4_artifacts: &'a Stage4ExecutionArtifacts, + pub(crate) stage5_proof: &'a JoltStageProof, + pub(crate) stage6_proof: &'a JoltStageProof, + pub(crate) jolt_inputs: jolt_verifier::JoltVerifierInputs<'a>, + pub(crate) programs: jolt_verifier::JoltVerifierPrograms, +} + +pub(crate) fn assert_bolt_stage7_tamper_rejected(input: Stage7TamperInput<'_>) { + let assert_tamper_rejected = |tampered_stage7_proof: JoltStageProof, message: &str| { + assert_generated_stage_and_prefix_tamper_rejected!( + input.preamble, + message, + input.jolt_inputs, + input.programs, + { + let mut transcript = input.verifier_transcript.clone(); + jolt_verifier::verify_stage7_with_program( + input.verifier_plan, + &tampered_stage7_proof, + input.openings, + &mut transcript, + ) + }, + jolt_prover::jolt_proof_through_stage7( + &input.commitment_verifier_trace.commitments, + input.stage1_artifacts, + input.stage2_artifacts, + input.stage3_artifacts, + input.stage4_artifacts, + input.stage5_proof, + input.stage6_proof, + &tampered_stage7_proof, + ), + ); + }; + + assert_batched_sumcheck_tampers!(assert_tamper_rejected, input.proof, 0, "Stage 7 verifier"); + + let assert_opening_input_tamper_rejected = + |tampered_openings: &[JoltStageOpeningInputValue], message: &str| { + let mut generated_tamper_transcript = input.verifier_transcript.clone(); + let generated_tamper_result = jolt_verifier::verify_stage7_with_program( + input.verifier_plan, + input.proof, + tampered_openings, + &mut generated_tamper_transcript, + ); + assert!(generated_tamper_result.is_err(), "generated {message}"); + + let generated_jolt_proof = jolt_prover::jolt_proof_through_stage7( + &input.commitment_verifier_trace.commitments, + input.stage1_artifacts, + input.stage2_artifacts, + input.stage3_artifacts, + input.stage4_artifacts, + input.stage5_proof, + input.stage6_proof, + input.proof, + ); + let mut tampered_inputs = input.jolt_inputs; + tampered_inputs.stage7_openings = tampered_openings; + assert_generated_jolt_prefix_tamper_rejected( + input.preamble, + &generated_jolt_proof, + tampered_inputs, + input.programs, + message, + ); + }; + + assert_opening_input_tampers( + input.openings, + "Stage 7", + assert_opening_input_tamper_rejected, + ); +} + +pub(crate) struct Stage345TamperInput<'a> { + pub(crate) preamble: &'a CoreMuldivCommitmentFixture, + pub(crate) commitment_verifier_trace: &'a BoltCommitmentTrace, + pub(crate) stage1_artifacts: &'a Stage1ExecutionArtifacts, + pub(crate) stage2_artifacts: &'a Stage2ExecutionArtifacts, + pub(crate) stage3_artifacts: &'a Stage3ExecutionArtifacts, + pub(crate) stage4_artifacts: &'a Stage4ExecutionArtifacts, + pub(crate) generated_stage3_verifier_plan: &'static Stage3VerifierProgramPlan, + pub(crate) generated_stage3_openings: &'a [JoltStageOpeningInputValue], + pub(crate) generated_stage3_start_transcript: &'a BoltTranscript, + pub(crate) generated_stage4_verifier_plan: &'static Stage4VerifierProgramPlan, + pub(crate) generated_stage4_start_transcript: &'a BoltTranscript, + pub(crate) generated_stage5_verifier_plan: &'static Stage5VerifierProgramPlan, + pub(crate) generated_stage4_openings: &'a [JoltStageOpeningInputValue], + pub(crate) generated_stage5_openings: &'a [JoltStageOpeningInputValue], + pub(crate) generated_stage5_proof: &'a JoltStageProof, + pub(crate) generated_stage5_start_transcript: &'a BoltTranscript, + pub(crate) generated_jolt_inputs: jolt_verifier::JoltVerifierInputs<'a>, + pub(crate) generated_programs: jolt_verifier::JoltVerifierPrograms, +} + +pub(crate) fn assert_bolt_stage3_4_5_tamper_rejected(input: Stage345TamperInput<'_>) { + let Stage345TamperInput { + preamble: fixture, + commitment_verifier_trace, + stage1_artifacts, + stage2_artifacts, + stage3_artifacts, + stage4_artifacts, + generated_stage3_verifier_plan, + generated_stage3_openings, + generated_stage3_start_transcript, + generated_stage4_verifier_plan, + generated_stage4_start_transcript, + generated_stage5_verifier_plan, + generated_stage4_openings, + generated_stage5_openings, + generated_stage5_proof, + generated_stage5_start_transcript, + generated_jolt_inputs, + generated_programs, + } = input; + let assert_stage3_tamper_rejected = + |tampered_stage3_artifacts: Stage3ExecutionArtifacts, message: &str| { + assert_generated_stage_and_prefix_tamper_rejected!( + fixture, + message, + generated_jolt_inputs.through_stage5(), + generated_programs, + { + let mut transcript = generated_stage3_start_transcript.clone(); + let proof = jolt_prover::stage3_proof(&tampered_stage3_artifacts); + jolt_verifier::verify_stage3_with_program( + generated_stage3_verifier_plan, + &proof, + generated_stage3_openings, + &mut transcript, + ) + }, + jolt_prover::jolt_proof_through_stage5( + &commitment_verifier_trace.commitments, + stage1_artifacts, + stage2_artifacts, + &tampered_stage3_artifacts, + stage4_artifacts, + generated_stage5_proof, + ), + ); + }; + + assert_batched_sumcheck_tampers!( + assert_stage3_tamper_rejected, + stage3_artifacts, + 0, + "Bolt Stage 3 verifier" + ); + + let assert_stage4_tamper_rejected = + |tampered_stage4_artifacts: Stage4ExecutionArtifacts, message: &str| { + assert_generated_stage_and_prefix_tamper_rejected!( + fixture, + message, + generated_jolt_inputs.through_stage5(), + generated_programs, + { + let mut transcript = generated_stage4_start_transcript.clone(); + let proof = jolt_prover::stage4_proof(&tampered_stage4_artifacts); + jolt_verifier::verify_stage4_with_program( + generated_stage4_verifier_plan, + &proof, + generated_stage4_openings, + &mut transcript, + ) + }, + jolt_prover::jolt_proof_through_stage5( + &commitment_verifier_trace.commitments, + stage1_artifacts, + stage2_artifacts, + stage3_artifacts, + &tampered_stage4_artifacts, + generated_stage5_proof, + ), + ); + }; + + assert_batched_sumcheck_tampers!( + assert_stage4_tamper_rejected, + stage4_artifacts, + 0, + "Stage 4 verifier" + ); + + let assert_stage5_tamper_rejected = |tampered_stage5_proof: JoltStageProof, message: &str| { + assert_generated_stage_and_prefix_tamper_rejected!( + fixture, + message, + generated_jolt_inputs.through_stage5(), + generated_programs, + { + let mut transcript = generated_stage5_start_transcript.clone(); + jolt_verifier::verify_stage5_with_program( + generated_stage5_verifier_plan, + &tampered_stage5_proof, + generated_stage5_openings, + &mut transcript, + ) + }, + jolt_prover::jolt_proof_through_stage5( + &commitment_verifier_trace.commitments, + stage1_artifacts, + stage2_artifacts, + stage3_artifacts, + stage4_artifacts, + &tampered_stage5_proof, + ), + ); + }; + + assert_batched_sumcheck_tampers!( + assert_stage5_tamper_rejected, + generated_stage5_proof, + 0, + "Stage 5 verifier" + ); +} diff --git a/crates/jolt-equivalence/tests/bolt_commitment.rs b/crates/jolt-equivalence/tests/bolt_commitment.rs new file mode 100644 index 0000000000..544d7a3f01 --- /dev/null +++ b/crates/jolt-equivalence/tests/bolt_commitment.rs @@ -0,0 +1,317 @@ +//! Commitment-phase transcript bridge between Bolt IR and jolt-core. +//! +//! This keeps the first oracle intentionally narrow: Bolt owns the commitment +//! ordering through its CPU IR, while jolt-core owns the reference +//! `append_serializable` transcript semantics for the same Dory commitments. + +#![expect( + clippy::expect_used, + reason = "integration gates should fail fast when positive prover/verifier setup fails" +)] + +use jolt_equivalence::bolt_oracle::assert_bolt_full_real_trace_self_parity; +use jolt_equivalence::bolt_programs::{ + bolt_commitment_programs, bolt_commitment_programs_with_params, + bolt_stage1_programs_with_params, bolt_stage2_programs_with_params, +}; +use jolt_equivalence::checkpoint::{assert_state_history_match, assert_transcripts_match}; +use jolt_equivalence::checks::{ + assert_core_stage2_uniskip_proof_matches_bolt, assert_stage1_uniskip_extended_evals_match_core, +}; +use jolt_equivalence::commitment_oracle::{ + core_commitment_trace, run_generated_bolt_commitment_pair_with_cpu_programs, + run_generated_synthetic_bolt_commitment_pair_with_cpu_programs, + transcript_with_bolt_commitment_trace, +}; +use jolt_equivalence::core_conversion::{core_commitment_log, core_commitments_transcript_log}; +use jolt_equivalence::core_oracle::{ + assert_core_accepts_bolt_stage1, assert_core_accepts_bolt_stage2, + core_muldiv_commitment_fixture, +}; +use jolt_equivalence::plan_adapters::{ + leak_generated_stage1_verifier_program, leak_generated_stage2_verifier_program, + leak_stage1_program, leak_stage2_program, +}; +use jolt_equivalence::tamper::{ + assert_bolt_chain_verifier_accepts_stage2_product_uniskip, assert_bolt_stage1_tamper_rejected, + assert_bolt_stage2_batched_tamper_rejected, BoltStage2ChainVerifierInput, + Stage2BatchedTamperInput, +}; +use jolt_equivalence::ArtifactSource; + +#[test] +fn bolt_commitment_transcript_matches_jolt_core_append_serializable() { + let (prover_program, verifier_program) = bolt_commitment_programs(); + let (prover_trace, verifier_trace) = + run_generated_synthetic_bolt_commitment_pair_with_cpu_programs( + &prover_program, + &verifier_program, + ); + let core_log = core_commitment_log( + prover_trace + .records + .iter() + .zip(&prover_trace.commitments) + .map(|(record, commitment)| (record.artifact.as_str(), commitment.as_ref())), + &prover_program.transcript_steps, + ); + + let prover_run = prover_trace.equivalence_run(ArtifactSource::Bolt); + let verifier_run = verifier_trace.equivalence_run(ArtifactSource::Bolt); + assert_eq!(prover_run.commitments, verifier_run.commitments); + assert_transcripts_match(&prover_trace.log, &verifier_trace.log); + assert_eq!(prover_run.transcript, verifier_run.transcript); + assert_transcripts_match(&core_log, &prover_trace.log); +} + +#[test] +fn bolt_commitment_real_muldiv_trace_matches_jolt_core() { + let fixture = core_muldiv_commitment_fixture(); + let (prover_program, verifier_program) = bolt_commitment_programs_with_params(&fixture.params); + + let (prover_trace, verifier_trace) = run_generated_bolt_commitment_pair_with_cpu_programs( + &prover_program, + &verifier_program, + &fixture.pcs_setup, + &fixture.cycle_inputs, + ); + + assert_eq!( + prover_trace.committed_prefix(fixture.commitments.len()), + core_commitment_trace(&fixture.commitments, "jolt.main_witness_commitments"), + ); + + let core_log = + core_commitments_transcript_log(&fixture.commitments, &prover_program.transcript_steps); + let prover_run = prover_trace.equivalence_run(ArtifactSource::Bolt); + let verifier_run = verifier_trace.equivalence_run(ArtifactSource::Bolt); + assert_eq!(prover_run.commitments, verifier_run.commitments); + assert_transcripts_match(&prover_trace.log, &verifier_trace.log); + assert_eq!(prover_run.transcript, verifier_run.transcript); + assert_transcripts_match(&core_log, &prover_trace.log); +} + +#[test] +fn bolt_commitment_stage1_real_muldiv_parity_checks() { + let fixture = core_muldiv_commitment_fixture(); + let (commitment_prover_program, commitment_verifier_program) = + bolt_commitment_programs_with_params(&fixture.params); + let (stage1_prover_program, stage1_verifier_program) = + bolt_stage1_programs_with_params(&fixture.params); + + let (commitment_prover_trace, commitment_verifier_trace) = + run_generated_bolt_commitment_pair_with_cpu_programs( + &commitment_prover_program, + &commitment_verifier_program, + &fixture.pcs_setup, + &fixture.cycle_inputs, + ); + + let stage1_prover_plan = leak_stage1_program(&stage1_prover_program); + let generated_stage1_verifier_plan = + leak_generated_stage1_verifier_program(&stage1_verifier_program); + let r1cs_key = fixture.r1cs_key(); + let data = fixture.stage1_outer_rv64_data(&r1cs_key); + let generic_data = fixture.stage1_outer_r1cs_data(&r1cs_key); + + let mut prover_transcript = + transcript_with_bolt_commitment_trace(&fixture, &commitment_prover_trace); + let stage1_artifacts = jolt_prover::prove_stage1_outer_with_witness_inputs( + stage1_prover_plan, + r1cs_key.num_cycle_vars(), + &data, + &mut prover_transcript, + ) + .expect("Bolt Stage 1 prover succeeds"); + assert_stage1_uniskip_extended_evals_match_core( + &fixture.proof, + &data, + &generic_data, + &stage1_artifacts, + ); + + let stage1_proof = stage1_artifacts.clone().into(); + let mut verifier_transcript = + transcript_with_bolt_commitment_trace(&fixture, &commitment_verifier_trace); + let stage1_start_transcript = verifier_transcript.clone(); + let verified_stage1 = jolt_prover::replay_stage1_outer_proof_with_program( + stage1_prover_plan, + &stage1_proof, + &mut verifier_transcript, + ) + .expect("Bolt Stage 1 verifier accepts prover proof"); + + assert_eq!( + stage1_artifacts.sumchecks.len(), + verified_stage1.sumchecks.len() + ); + assert_transcripts_match(prover_transcript.log(), verifier_transcript.log()); + + assert_core_accepts_bolt_stage1(&fixture, &stage1_artifacts); + assert_bolt_stage1_tamper_rejected( + stage1_prover_plan, + generated_stage1_verifier_plan, + &stage1_proof, + &stage1_start_transcript, + ); +} + +#[test] +fn bolt_stage2_product_uniskip_real_muldiv_matches_jolt_core() { + let fixture = core_muldiv_commitment_fixture(); + let (commitment_prover_program, commitment_verifier_program) = + bolt_commitment_programs_with_params(&fixture.params); + let (stage1_prover_program, _) = bolt_stage1_programs_with_params(&fixture.params); + let (stage2_prover_program, stage2_verifier_program) = + bolt_stage2_programs_with_params(&fixture.params); + + let (commitment_prover_trace, commitment_verifier_trace) = + run_generated_bolt_commitment_pair_with_cpu_programs( + &commitment_prover_program, + &commitment_verifier_program, + &fixture.pcs_setup, + &fixture.cycle_inputs, + ); + + let stage1_prover_plan = leak_stage1_program(&stage1_prover_program); + let r1cs_key = fixture.r1cs_key(); + let data = fixture.stage1_outer_rv64_data(&r1cs_key); + + let mut bolt_transcript = + transcript_with_bolt_commitment_trace(&fixture, &commitment_prover_trace); + let stage1_artifacts = jolt_prover::prove_stage1_outer_with_witness_inputs( + stage1_prover_plan, + r1cs_key.num_cycle_vars(), + &data, + &mut bolt_transcript, + ) + .expect("Bolt Stage 1 prover succeeds"); + + let stage2_prover_plan = leak_stage2_program(&stage2_prover_program); + let stage2_openings = + jolt_prover::stage2_opening_inputs_from_artifacts(stage2_prover_plan, &stage1_artifacts) + .expect("generated prover derives Stage 2 opening inputs from artifacts"); + let ram_data = fixture.stage2_ram_data(); + let generated_stage2_verifier_plan = + leak_generated_stage2_verifier_program(&stage2_verifier_program); + let stage2_artifacts = jolt_prover::prove_stage2_with_witness_inputs( + stage2_prover_plan, + &stage2_openings, + &fixture.product_virtual_cycles, + &fixture.instruction_lookup_cycles, + &ram_data, + &mut bolt_transcript, + ) + .expect("Bolt Stage 2 prover succeeds"); + + assert_core_stage2_uniskip_proof_matches_bolt(&fixture.proof, &stage2_artifacts.sumchecks[0]); + assert_bolt_chain_verifier_accepts_stage2_product_uniskip(BoltStage2ChainVerifierInput { + fixture: &fixture, + commitment_verifier_trace: &commitment_verifier_trace, + stage1_prover_plan, + stage2_prover_plan, + generated_stage2_verifier_plan, + stage1_artifacts: &stage1_artifacts, + stage2_artifacts: &stage2_artifacts, + ram_data: &ram_data, + prover_transcript: &bolt_transcript, + }); + + assert_eq!( + commitment_prover_trace.commitments, + commitment_verifier_trace.commitments + ); +} + +#[test] +fn bolt_stage2_batched_real_muldiv_self_parity() { + let fixture = core_muldiv_commitment_fixture(); + let (commitment_prover_program, commitment_verifier_program) = + bolt_commitment_programs_with_params(&fixture.params); + let (stage1_prover_program, _) = bolt_stage1_programs_with_params(&fixture.params); + let (stage2_prover_program, stage2_verifier_program) = + bolt_stage2_programs_with_params(&fixture.params); + + let (commitment_prover_trace, commitment_verifier_trace) = + run_generated_bolt_commitment_pair_with_cpu_programs( + &commitment_prover_program, + &commitment_verifier_program, + &fixture.pcs_setup, + &fixture.cycle_inputs, + ); + + let stage1_prover_plan = leak_stage1_program(&stage1_prover_program); + let r1cs_key = fixture.r1cs_key(); + let data = fixture.stage1_outer_rv64_data(&r1cs_key); + + let mut prover_transcript = + transcript_with_bolt_commitment_trace(&fixture, &commitment_prover_trace); + let stage1_artifacts = jolt_prover::prove_stage1_outer_with_witness_inputs( + stage1_prover_plan, + r1cs_key.num_cycle_vars(), + &data, + &mut prover_transcript, + ) + .expect("Bolt Stage 1 prover succeeds"); + + let stage2_prover_plan = leak_stage2_program(&stage2_prover_program); + let stage2_openings = + jolt_prover::stage2_opening_inputs_from_artifacts(stage2_prover_plan, &stage1_artifacts) + .expect("generated prover derives Stage 2 opening inputs from artifacts"); + let ram_data = fixture.stage2_ram_data(); + let generated_stage2_verifier_plan = + leak_generated_stage2_verifier_program(&stage2_verifier_program); + let stage2_artifacts = jolt_prover::prove_stage2_with_witness_inputs( + stage2_prover_plan, + &stage2_openings, + &fixture.product_virtual_cycles, + &fixture.instruction_lookup_cycles, + &ram_data, + &mut prover_transcript, + ) + .expect("Bolt Stage 2 prover succeeds"); + + let mut verifier_transcript = + transcript_with_bolt_commitment_trace(&fixture, &commitment_verifier_trace); + let stage1_proof = stage1_artifacts.clone().into(); + let verified_stage1 = jolt_prover::replay_stage1_outer_proof_with_program( + stage1_prover_plan, + &stage1_proof, + &mut verifier_transcript, + ) + .expect("Bolt Stage 1 verifier accepts"); + let stage2_verifier_openings = + jolt_prover::stage2_opening_inputs_from_artifacts(stage2_prover_plan, &verified_stage1) + .expect("generated prover derives Stage 2 verifier opening inputs from artifacts"); + let stage2_proof = stage2_artifacts.clone().into(); + let stage2_start_transcript = verifier_transcript.clone(); + let verified_stage2 = jolt_prover::replay_stage2_proof_with_program( + stage2_prover_plan, + &stage2_proof, + &stage2_verifier_openings, + Some(&ram_data), + &mut verifier_transcript, + ) + .expect("Bolt Stage 2 verifier accepts"); + + assert_eq!( + stage2_artifacts.sumchecks.len(), + verified_stage2.sumchecks.len() + ); + assert_state_history_match(prover_transcript.log(), verifier_transcript.log()); + assert_core_accepts_bolt_stage2(&fixture, &stage1_artifacts, &stage2_artifacts); + + assert_bolt_stage2_batched_tamper_rejected(Stage2BatchedTamperInput { + stage2_prover_plan, + generated_stage2_verifier_plan, + stage2_start_transcript: &stage2_start_transcript, + stage2_openings: &stage2_verifier_openings, + stage2_artifacts: &stage2_artifacts, + ram_data: &ram_data, + }); +} + +#[test] +fn bolt_stage3_batched_real_muldiv_self_parity() { + assert_bolt_full_real_trace_self_parity(core_muldiv_commitment_fixture(), false); +} diff --git a/crates/jolt-equivalence/tests/bolt_perf.rs b/crates/jolt-equivalence/tests/bolt_perf.rs new file mode 100644 index 0000000000..9aff818425 --- /dev/null +++ b/crates/jolt-equivalence/tests/bolt_perf.rs @@ -0,0 +1,20 @@ +//! Dedicated perf-oracle gates for real-data core-vs-Bolt runs. + +use jolt_equivalence::bolt_oracle::assert_bolt_full_real_trace_self_parity; +use jolt_equivalence::core_oracle::core_sha2_chain_commitment_fixture; +use jolt_equivalence::perf::maybe_setup_perf_trace; +use jolt_inlines_sha2 as _; + +#[test] +#[ignore = "run by the Bolt perf-oracle CI workflow"] +fn bolt_sha2_chain_2_16_core_vs_bolt_perf_oracle() { + maybe_setup_perf_trace("bolt_sha2_chain_2_16_core_vs_bolt"); + assert_bolt_full_real_trace_self_parity(core_sha2_chain_commitment_fixture(16), true); +} + +#[test] +#[ignore = "run by the Bolt perf-oracle CI workflow"] +fn bolt_sha2_chain_2_20_core_vs_bolt_perf_oracle() { + maybe_setup_perf_trace("bolt_sha2_chain_2_20_core_vs_bolt"); + assert_bolt_full_real_trace_self_parity(core_sha2_chain_commitment_fixture(20), true); +} diff --git a/crates/jolt-equivalence/tests/generated_role_crates.rs b/crates/jolt-equivalence/tests/generated_role_crates.rs new file mode 100644 index 0000000000..bb166e401e --- /dev/null +++ b/crates/jolt-equivalence/tests/generated_role_crates.rs @@ -0,0 +1,142 @@ +use jolt_core::transcripts::{ + Blake2bTranscript as CoreBlake2bTranscript, Transcript as CoreTranscript, +}; +use jolt_core::zkvm::lookup_table::LookupTables as CoreLookupTables; +use jolt_field::Fr; +use jolt_lookup_tables::LookupTableKind; +use jolt_transcript::{Blake2bTranscript, Transcript as GeneratedTranscript}; +use strum::{EnumCount, IntoEnumIterator}; + +#[test] +fn generated_role_crates_expose_matching_stage_prefix() { + let prover_stages = jolt_prover::generated_stage_names().collect::>(); + let verifier_stages = jolt_verifier::generated_stage_names().collect::>(); + + assert_eq!(prover_stages, verifier_stages); + assert_eq!( + prover_stages, + vec![ + "commitment", + "stage1_outer", + "stage2", + "stage3", + "stage4", + "stage5", + "stage6", + "stage7", + "stage8" + ] + ); + + assert!(!jolt_prover::stages::commitment::TRANSCRIPT_PLAN.is_empty()); + assert!(!jolt_verifier::stages::commitment::TRANSCRIPT_PLAN.is_empty()); + macro_rules! assert_stage_drivers { + ($(($prover:expr, $verifier:expr)),+ $(,)?) => { + $( + assert!(!$prover.drivers.is_empty()); + assert!(!$verifier.drivers.is_empty()); + )+ + }; + } + assert_stage_drivers!( + ( + jolt_prover::stages::stage1_outer::STAGE1_PROGRAM, + jolt_verifier::stages::stage1_outer::STAGE1_PROGRAM + ), + ( + jolt_prover::stages::stage2::STAGE2_PROGRAM, + jolt_verifier::stages::stage2::STAGE2_PROGRAM + ), + ( + jolt_prover::stages::stage3::STAGE3_PROGRAM, + jolt_verifier::stages::stage3::STAGE3_PROGRAM + ), + ( + jolt_prover::stages::stage4::STAGE4_PROGRAM, + jolt_verifier::stages::stage4::STAGE4_PROGRAM + ), + ( + jolt_prover::stages::stage5::STAGE5_PROGRAM, + jolt_verifier::stages::stage5::STAGE5_PROGRAM + ), + ( + jolt_prover::stages::stage6::STAGE6_PROGRAM, + jolt_verifier::stages::stage6::STAGE6_PROGRAM + ), + ( + jolt_prover::stages::stage7::STAGE7_PROGRAM, + jolt_verifier::stages::stage7::STAGE7_PROGRAM + ), + ); + assert!(!jolt_prover::stages::stage8::STAGE8_PROGRAM + .opening_claims + .is_empty()); + assert!(!jolt_verifier::stages::stage8::STAGE8_PROGRAM + .opening_claims + .is_empty()); + assert_eq!( + jolt_prover::stages::stage8::STAGE8_PROGRAM.pcs_proof.mode, + "open" + ); + assert_eq!( + jolt_verifier::stages::stage8::STAGE8_PROGRAM.pcs_proof.mode, + "verify" + ); + let _proof = jolt_verifier::JoltProof { + commitments: Vec::new(), + stage1_outer: jolt_verifier::JoltStageProof::default(), + stage2: jolt_verifier::JoltStageProof::default(), + stage3: jolt_verifier::JoltStageProof::default(), + stage4: jolt_verifier::JoltStageProof::default(), + stage5: jolt_verifier::JoltStageProof::default(), + stage6: jolt_verifier::JoltStageProof::default(), + stage7: jolt_verifier::JoltStageProof::default(), + evaluation: None, + }; +} + +#[test] +fn monolithic_transcript_challenges_match_core_full_field_path() { + let mut core = ::new(b"Jolt"); + let mut generated = as GeneratedTranscript>::new(b"Jolt"); + + let core_challenge: ark_bn254::Fr = core.challenge_scalar_optimized::().into(); + let generated_challenge: ark_bn254::Fr = generated.challenge().into(); + + assert_eq!(core_challenge, generated_challenge); + assert_eq!(core.state, *generated.state()); +} + +#[test] +fn modular_lookup_table_list_matches_core_order() { + const XLEN: usize = 64; + + let modular_tables = LookupTableKind::::all(); + assert_eq!(modular_tables.len(), CoreLookupTables::::COUNT); + assert_eq!( + modular_tables.len(), + as EnumCount>::COUNT + ); + + for (index, (core_table, modular_table)) in CoreLookupTables::::iter() + .zip(modular_tables) + .enumerate() + { + let core_name: &'static str = core_table.into(); + assert_eq!( + modular_table.name(), + core_name, + "table name at index {index}" + ); + assert_eq!( + LookupTableKind::index(&modular_table), + index, + "modular table index for {core_name}" + ); + assert_eq!( + CoreLookupTables::enum_index(&core_table), + index, + "core table index for {core_name}" + ); + } +} diff --git a/scripts/setup-bolt-dev.sh b/scripts/setup-bolt-dev.sh new file mode 100755 index 0000000000..7f23a687f3 --- /dev/null +++ b/scripts/setup-bolt-dev.sh @@ -0,0 +1,99 @@ +#!/usr/bin/env bash +set -euo pipefail + +repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +env_file="${repo_root}/.bolt-dev-env" + +usage() { + cat <<'USAGE' +Usage: scripts/setup-bolt-dev.sh + +Installs/configures the local dependencies needed by Bolt MLIR/codegen and +Jolt-on-Bolt perf oracle checks on macOS: + + - Homebrew llvm + - rustup components: rust-src, rustfmt, clippy + - cargo-nextest + - .bolt-dev-env with MLIR_SYS_220_PREFIX, PATH, SDKROOT, and bindgen flags + +After it finishes, run: + + source .bolt-dev-env +USAGE +} + +if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then + usage + exit 0 +fi + +if [[ "$(uname -s)" != "Darwin" ]]; then + cat >&2 <<'EOF' +scripts/setup-bolt-dev.sh currently supports macOS/Homebrew. + +Bolt's MLIR path needs LLVM/MLIR 22 visible through llvm-config. On non-macOS +hosts, install an LLVM 22 toolchain and export: + + MLIR_SYS_220_PREFIX= + PATH=/bin:$PATH + +EOF + exit 1 +fi + +if ! command -v brew >/dev/null 2>&1; then + cat >&2 <<'EOF' +Homebrew is required to install the LLVM toolchain for this helper. +Install Homebrew first: https://brew.sh +EOF + exit 1 +fi + +if ! command -v xcrun >/dev/null 2>&1; then + cat >&2 <<'EOF' +xcrun is missing. Install the Xcode command line tools first: + + xcode-select --install +EOF + exit 1 +fi + +if ! brew list llvm >/dev/null 2>&1; then + brew install llvm +fi + +if command -v rustup >/dev/null 2>&1; then + rustup component add rust-src rustfmt clippy +else + cat >&2 <<'EOF' +rustup is not installed. Install Rust from https://rustup.rs, then rerun this +script so it can add rust-src, rustfmt, and clippy. +EOF + exit 1 +fi + +if ! cargo nextest --version >/dev/null 2>&1; then + cargo install cargo-nextest --locked +fi + +llvm_prefix="$(brew --prefix llvm)" +sdkroot="$(xcrun --show-sdk-path)" + +cat >"${env_file}" </dev/null + +cat < Date: Thu, 14 May 2026 13:02:15 -0500 Subject: [PATCH 07/14] feat(sdk): modular prove/verify entry points + #[jolt::provable(backend = "modular")] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds the modular SDK API surface as a clean overlay on `refactor/crates`, no protocol changes: - New crate `jolt-host` providing `prove_program` + `verify_proof` + `ProofBundle`. Drives a guest ELF through the full Bolt stage chain (commitment → Stage1..7 → evaluation proof) and rebuilds verifier inputs from prover artifacts without re-tracing. Lifted from the FR-coprocessor branch (currently `sagar/fr-coprocessor`) with all FR-specific plumbing stripped — the architecture is FR-agnostic by design; FR is "always on but zero contribution for non-FR guests" when it lands. - `#[jolt::provable(backend = "modular")]` macro arg. When set, the macro emits `compile_` / `prove_` / `verify_` wired to `jolt_host::{prove_program, verify_proof}` instead of jolt-core's `RV64IMACProver`. `prove_` returns `(T, ProofBundle)` with the guest's typed return value postcard-decoded from `io_device.outputs`. Legacy default unchanged. - Guardrails in the macro: compile_error when `max_trace_length > 2^FIXTURE_LOG_T` (currently 2^16 = 65536, matching `JoltProtocolParams::fixture() = (16, 10, 16)`), trusted advice, or `wasm`. ZK is rejected indirectly — `jolt-sdk` only re-exports `jolt_host` / `jolt_trace` when `feature = "zk"` is OFF, so enabling zk with the modular backend produces a clean "cannot find `jolt_host` in crate `jolt`" build error. Two enablement changes in `crates/jolt-trace` (same shape as on the FR branch — these are infrastructure jolt-host needs to exist, not modular-specific): - `BytecodePreprocessing::preprocess_padded(bytecode, entry, min_size)`: pads bytecode up to `min_size.next_power_of_two()` so small guests reuse a larger goldens-baked fixture without manual regen. - `#[macro_export]` on `with_isa_struct!` so jolt-host can use it for instruction → lookup-table-index dispatch. The FR coprocessor work (on `sagar/fr-coprocessor`) is layered on top of this SDK and will rebase forward after this lands. --- Cargo.lock | 24 + Cargo.toml | 2 + common/src/attributes.rs | 25 + crates/jolt-host/Cargo.toml | 30 + crates/jolt-host/src/lib.rs | 891 ++++++++++++++++++ crates/jolt-host/tests/prove_program_smoke.rs | 51 + crates/jolt-trace/src/bytecode.rs | 23 + crates/jolt-trace/src/tracer_cycle.rs | 1 + jolt-sdk/Cargo.toml | 4 + jolt-sdk/macros/src/lib.rs | 241 ++++- jolt-sdk/src/host_utils.rs | 9 + 11 files changed, 1276 insertions(+), 25 deletions(-) create mode 100644 crates/jolt-host/Cargo.toml create mode 100644 crates/jolt-host/src/lib.rs create mode 100644 crates/jolt-host/tests/prove_program_smoke.rs diff --git a/Cargo.lock b/Cargo.lock index c3792384a0..1f3bc1d6f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2982,6 +2982,28 @@ dependencies = [ "serde", ] +[[package]] +name = "jolt-host" +version = "0.1.0" +dependencies = [ + "common", + "jolt-dory", + "jolt-field", + "jolt-kernels", + "jolt-lookup-tables", + "jolt-openings", + "jolt-prover", + "jolt-r1cs", + "jolt-riscv", + "jolt-trace", + "jolt-transcript", + "jolt-verifier", + "jolt-witness", + "postcard", + "tracer", + "tracing", +] + [[package]] name = "jolt-hyperkzg" version = "0.1.0" @@ -3253,8 +3275,10 @@ dependencies = [ "cfg-if", "common", "jolt-core", + "jolt-host", "jolt-platform", "jolt-sdk-macros", + "jolt-trace", "postcard", "riscv 0.16.0", "serde", diff --git a/Cargo.toml b/Cargo.toml index 1358c6d455..08874dc33b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,6 +40,7 @@ members = [ "crates/jolt-kernels", "crates/jolt-prover", "crates/jolt-verifier", + "crates/jolt-host", "crates/jolt-equivalence", "crates/jolt-profiling", "crates/jolt-field", @@ -396,6 +397,7 @@ bolt = { path = "./crates/bolt" } jolt-kernels = { path = "./crates/jolt-kernels" } jolt-prover = { path = "./crates/jolt-prover" } jolt-verifier = { path = "./crates/jolt-verifier" } +jolt-host = { path = "./crates/jolt-host" } jolt-equivalence = { path = "./crates/jolt-equivalence" } jolt-riscv = { path = "./crates/jolt-riscv" } jolt-trace = { path = "./crates/jolt-trace" } diff --git a/common/src/attributes.rs b/common/src/attributes.rs index 949e6dde88..3863ac21d8 100644 --- a/common/src/attributes.rs +++ b/common/src/attributes.rs @@ -6,6 +6,12 @@ use crate::constants::{ DEFAULT_MAX_TRUSTED_ADVICE_SIZE, DEFAULT_MAX_UNTRUSTED_ADVICE_SIZE, DEFAULT_STACK_SIZE, }; +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Backend { + Legacy, + Modular, +} + pub struct Attributes { pub wasm: bool, pub nightly: bool, @@ -20,6 +26,10 @@ pub struct Attributes { pub max_untrusted_advice_size: u64, pub max_trace_length: u64, pub backtrace: Option, + /// Prover backend selector. `Legacy` (default) drives jolt-core's + /// monolithic `RV64IMACProver`. `Modular` drives the Bolt-based modular + /// stack via `jolt_host::prove_program` + `verify_proof`. + pub backend: Backend, } pub fn parse_attributes(attr: &Punctuated) -> Attributes { @@ -29,6 +39,7 @@ pub fn parse_attributes(attr: &Punctuated) -> Attributes { let mut nightly = false; let mut profile: Option = None; let mut backtrace: Option = None; + let mut backend = Backend::Legacy; for meta in attr { match meta { @@ -53,6 +64,19 @@ pub fn parse_attributes(attr: &Punctuated) -> Attributes { }; profile = Some(value); } + "backend" => { + let value = match lit { + Lit::Str(lit) => lit.value(), + _ => panic!("backend attribute expects a string literal"), + }; + backend = match value.as_str() { + "legacy" => Backend::Legacy, + "modular" => Backend::Modular, + other => panic!( + "invalid backend = \"{other}\"; expected \"legacy\" or \"modular\"" + ), + }; + } _ => { let value: u64 = match lit { Lit::Int(lit) => lit.base10_parse().unwrap(), @@ -122,5 +146,6 @@ pub fn parse_attributes(attr: &Punctuated) -> Attributes { max_untrusted_advice_size, max_trace_length, backtrace, + backend, } } diff --git a/crates/jolt-host/Cargo.toml b/crates/jolt-host/Cargo.toml new file mode 100644 index 0000000000..44d198d55d --- /dev/null +++ b/crates/jolt-host/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "jolt-host" +version = "0.1.0" +edition = "2021" +license = "MIT OR Apache-2.0" +description = "Host-side modular prove entry point — bridges Program + tracer + jolt-prover stages" +repository = "https://github.com/a16z/jolt" + +[lints] +workspace = true + +[dev-dependencies] +postcard = { workspace = true, features = ["alloc"] } + +[dependencies] +common.workspace = true +jolt-dory.workspace = true +jolt-field.workspace = true +jolt-kernels.workspace = true +jolt-lookup-tables.workspace = true +jolt-openings.workspace = true +jolt-prover.workspace = true +jolt-r1cs.workspace = true +jolt-riscv.workspace = true +jolt-trace.workspace = true +jolt-transcript.workspace = true +jolt-verifier.workspace = true +jolt-witness.workspace = true +tracer = { workspace = true, features = ["std"] } +tracing.workspace = true diff --git a/crates/jolt-host/src/lib.rs b/crates/jolt-host/src/lib.rs new file mode 100644 index 0000000000..71a663adfc --- /dev/null +++ b/crates/jolt-host/src/lib.rs @@ -0,0 +1,891 @@ +//! Host-side entry point for the modular Bolt-based prover. +//! +//! `prove_program` takes a guest `Program` + inputs and returns a verifiable +//! `JoltProof` by driving the modular stack (jolt-prover + jolt-verifier + +//! Bolt goldens) end-to-end. The companion `verify_proof` rebuilds verifier +//! inputs from the prover artifacts and closes the soundness loop without +//! re-tracing the guest. Together they form the host-side surface that +//! `#[jolt::provable(backend = "modular")]` lowers to. +//! +//! The implementation mirrors `crates/jolt-equivalence/src/bolt_oracle.rs` +//! (the canonical staged-prove chain) with three substitutions: +//! 1. Bolt program plans come from +//! `jolt_prover::default_prover_programs()` (committed `pub const` +//! goldens) instead of being regenerated by Bolt at runtime. +//! 2. Trace-derived data (cycle_inputs, r1cs_witness, rv64_cycles, etc.) +//! is built from a real tracer run on the supplied ELF rather than +//! borrowed from a fixture. +//! 3. The redundant `prove_jolt_with_witness_inputs` call at +//! `bolt_oracle.rs:644` is omitted — the staged chain produces the +//! proof directly. + +use common::constants::{BYTES_PER_INSTRUCTION, RAM_START_ADDRESS}; +use common::jolt_device::{JoltDevice, MemoryLayout}; +use jolt_dory::{DoryProverSetup, DoryScheme}; +use jolt_field::Fr; +use jolt_kernels::stage1::{Stage1OuterRv64Data, Stage1Rv64Cycle}; +use jolt_kernels::stage2::{Stage2RamAccess, Stage2RamData, Stage2RamOutputLayout}; +use jolt_kernels::stage3::Stage3Cycle; +use jolt_kernels::stage4::Stage4RegisterAccess; +use jolt_kernels::trace::{ + stage1_rv64_cycles, stage2_instruction_lookup_cycles, stage2_product_virtual_cycles, + stage2_ram_accesses, stage3_cycles, stage4_register_accesses, stage5_lookup_trace, + stage6_bytecode_entries, Stage5LookupTrace, +}; +use jolt_lookup_tables::traits::InstructionLookupTable; +use jolt_lookup_tables::XLEN; +use jolt_openings::CommitmentScheme as _; +use jolt_r1cs::{constraints::rv64, R1csKey}; +use jolt_trace::ram::build_ram_states; +use jolt_trace::{extract_trace, with_isa_struct, BytecodePreprocessing, CycleRow, Program}; +use jolt_transcript::{Blake2bTranscript, Label, LabelWithCount, Transcript, U64Word}; +use jolt_verifier::{ + default_verifier_programs, verify_jolt_with_programs, JoltProof, JoltVerifierInputs, + JoltVerifyError, +}; +use jolt_witness::{ + Stage6BytecodeEntry as WitnessStage6BytecodeEntry, Stage6WitnessParams, +}; +use tracer::instruction::Instruction; + +use jolt_prover::{default_prover_programs, JoltProveError, JoltProverArtifacts}; + +/// Dispatch `&tracer::Instruction` to its `InstructionLookupTable` impl +/// in jolt-lookup-tables and return the table discriminant index. +/// Matches jolt-core's +/// `InstructionLookup::lookup_table().map(LookupTables::enum_index)` +/// across all 77 instruction variants (including the virtual ones that +/// shifts and DIVs expand into). Used as the closure for +/// `stage5_lookup_trace` and `stage6_bytecode_entries`. +fn instruction_lookup_table_index(instr: &Instruction) -> Option { + with_isa_struct!( + instr, + |i| <_ as InstructionLookupTable>::lookup_table(&i).map(|t| t.index()), + noop => None + ) +} + +/// Transcript label used by the modular prover (matches jolt-equivalence's +/// `TRANSCRIPT_LABEL`). +pub const TRANSCRIPT_LABEL: &[u8] = b"Jolt"; + +/// The single goldens-baked shape supported by `prove_program` today. +/// Matches `bolt::protocols::jolt::JoltProtocolParams::fixture()`. +/// Guests with naturally larger traces fail with +/// [`ProveProgramError::UnsupportedShape`]. Kept in sync with the +/// `MAX_MODULAR_TRACE_LENGTH` cap in the +/// `#[jolt::provable(backend = "modular")]` macro guard. +pub const FIXTURE_LOG_T: usize = 16; +pub const FIXTURE_LOG_K_BYTECODE: usize = 10; +pub const FIXTURE_LOG_K_RAM: usize = 16; + +/// Errors produced by `prove_program`. +#[derive(Debug)] +pub enum ProveProgramError { + /// Inner prover failure (commitment / Stage 1-7 / evaluation). + Prove(JoltProveError), + /// Opening-input derivation failure between stages. + Openings(jolt_prover::prover::JoltOpeningInputError), + /// The supplied guest program produced a trace shape (log_t, + /// log_k_bytecode, log_k_ram) that doesn't match the goldens-baked + /// fixture. v1 of `prove_program` only supports the fixture shape + /// (log_t=16, log_k_bytecode=10, log_k_ram=16). Larger guests require + /// regenerated goldens. + UnsupportedShape { + log_t: usize, + log_k_bytecode: usize, + log_k_ram: usize, + }, +} + +impl From for ProveProgramError { + fn from(value: JoltProveError) -> Self { + Self::Prove(value) + } +} + +impl From for ProveProgramError { + fn from(value: jolt_prover::prover::JoltOpeningInputError) -> Self { + Self::Openings(value) + } +} + +/// Errors produced by `verify_proof`. +#[derive(Debug)] +pub enum VerifyProgramError { + /// Inner verifier failure (commitment / Stage 1-7 / evaluation). + Verify(JoltVerifyError), + /// Opening-input re-derivation failed when reconstructing verifier inputs. + Openings(jolt_prover::prover::JoltOpeningInputError), + /// `prove_program` did not produce an evaluation proof, so the verifier + /// cannot complete the round-trip. + MissingEvaluation, + /// Re-decoded bytecode shape doesn't match the proven program's shape + /// (would indicate a stale `ProofBundle` paired with a mutated `Program`). + UnsupportedShape { + log_t: usize, + log_k_bytecode: usize, + log_k_ram: usize, + }, +} + +impl From for VerifyProgramError { + fn from(value: JoltVerifyError) -> Self { + Self::Verify(value) + } +} + +impl From for VerifyProgramError { + fn from(value: jolt_prover::prover::JoltOpeningInputError) -> Self { + Self::Openings(value) + } +} + +/// Bundle returned by `prove_program` carrying everything needed to verify +/// the proof end-to-end via `verify_proof`. Owning the auxiliary state +/// (bytecode entries, RAM bufs, PCS setup, etc.) lets `verify_proof` rebuild +/// verifier inputs without re-tracing the guest. +pub struct ProofBundle { + pub proof: JoltProof, + pub io_device: JoltDevice, + pub artifacts: JoltProverArtifacts, + pub bytecode_entries: Vec>, + pub entry_bytecode_index: usize, + pub lookup_table_count: usize, + pub initial_ram_state: Vec, + pub final_ram_state: Vec, + pub lowest_addr: u64, + pub entry_address: u64, + params: ModularJoltParams, + pcs_setup: DoryProverSetup, +} + +/// JoltProtocolParams equivalent without the MLIR/LLVM dependency. +/// +/// Hand-port of `JoltProtocolParams::new` from `crates/bolt/src/protocols/ +/// jolt/params.rs`, keeping only the numeric fields needed at runtime. +/// Stays in sync with that file by construction (same formulas, same +/// constants). +#[derive(Clone, Copy, Debug)] +struct ModularJoltParams { + log_t: usize, + trace_length: usize, + log_k_bytecode: usize, + #[expect(dead_code, reason = "kept for symmetry with JoltProtocolParams::new")] + bytecode_k: usize, + log_k_ram: usize, + ram_k: usize, + log_k_chunk: usize, + lookups_ra_virtual_log_k_chunk: usize, + register_log_k: usize, + instruction_d: usize, + instruction_ra_virtual_d: usize, + bytecode_d: usize, + ram_d: usize, +} + +impl ModularJoltParams { + fn new(log_t: usize, log_k_bytecode: usize, log_k_ram: usize) -> Self { + let log_k_chunk = if log_t < 25 { 4 } else { 8 }; + let instruction_log_k = 128; + let lookups_ra_virtual_log_k_chunk = if log_t < 25 { + instruction_log_k / 8 + } else { + instruction_log_k / 4 + }; + let instruction_d = instruction_log_k / log_k_chunk; + let instruction_ra_virtual_d = instruction_log_k / lookups_ra_virtual_log_k_chunk; + let bytecode_d = log_k_bytecode.div_ceil(log_k_chunk); + let ram_d = log_k_ram.div_ceil(log_k_chunk); + Self { + log_t, + trace_length: 1usize << log_t, + log_k_bytecode, + bytecode_k: 1usize << log_k_bytecode, + log_k_ram, + ram_k: 1usize << log_k_ram, + log_k_chunk, + lookups_ra_virtual_log_k_chunk, + register_log_k: 7, + instruction_d, + instruction_ra_virtual_d, + bytecode_d, + ram_d, + } + } + + fn stage6_witness_params(&self) -> Stage6WitnessParams { + Stage6WitnessParams { + trace_len: self.trace_length, + log_k_chunk: self.log_k_chunk, + log_k_bytecode: self.log_k_bytecode, + log_k_ram: self.log_k_ram, + lookups_ra_virtual_log_k_chunk: self.lookups_ra_virtual_log_k_chunk, + instruction_d: self.instruction_d, + instruction_ra_virtual_d: self.instruction_ra_virtual_d, + bytecode_d: self.bytecode_d, + ram_d: self.ram_d, + } + } +} + +/// Top-level entry: build a Jolt proof from a guest program + inputs by +/// driving the modular Bolt-based prover end-to-end. +/// +/// # Constraints (v1) +/// - Requires the guest's padded trace, bytecode size, and RAM size to +/// match the goldens-baked fixture shape (`log_t=16`, +/// `log_k_bytecode=10`, `log_k_ram=16`). Larger guests need a fresh +/// `JOLT_UPDATE_GOLDENS=1` regen at the right params. +/// - Currently bypasses trusted advice commitments (no +/// `trusted_advice_commitment` argument); only untrusted advice is +/// threaded. +/// +/// # Returns +/// A [`ProofBundle`] bundle containing the proof and everything +/// [`verify_proof`] needs to run the modular verifier round-trip without +/// re-tracing the guest. +pub fn prove_program( + program: &mut Program, + inputs: &[u8], + untrusted_advice: &[u8], + trusted_advice: &[u8], +) -> Result { + let (_lazy_trace, trace, final_memory, io_device) = + program.trace(inputs, untrusted_advice, trusted_advice); + let (bytecode_raw, init_mem, _program_size, entry_address) = program.decode(); + + let shape = check_shape(&trace, &io_device, &init_mem, bytecode_raw, entry_address)?; + let params = ModularJoltParams::new(shape.log_t, shape.log_k_bytecode, shape.log_k_ram); + + let stages = assemble_and_prove( + &trace, + &shape.bytecode, + &io_device, + &init_mem, + &final_memory, + entry_address, + ¶ms, + shape.trace_length, + shape.ram_k, + )?; + + Ok(ProofBundle { + proof: stages.proof, + io_device, + artifacts: stages.artifacts, + bytecode_entries: stages.bytecode_entries, + entry_bytecode_index: stages.entry_bytecode_index, + lookup_table_count: stages.lookup_table_count, + initial_ram_state: stages.initial_ram_state, + final_ram_state: stages.final_ram_state, + lowest_addr: stages.lowest_addr, + entry_address, + params, + pcs_setup: stages.pcs_setup, + }) +} + +/// Resolved shape parameters after padding small guests up to the goldens +/// fixture. `prove_program` rejects anything whose natural padded shape +/// doesn't equal the fixture in `(log_t, log_k_bytecode, log_k_ram)`. +struct ResolvedShape { + bytecode: BytecodePreprocessing, + trace_length: usize, + ram_k: usize, + log_t: usize, + log_k_bytecode: usize, + log_k_ram: usize, +} + +/// Phase 1.5 + 2: pad trace/bytecode/RAM up to the goldens-baked fixture +/// and reject anything that doesn't match exactly. The goldens depend on +/// the d-regime AND the absolute fixture log_t (dory tier-1 streaming +/// buffers are sized at the fixture trace length). +fn check_shape( + trace: &[tracer::instruction::Cycle], + io_device: &JoltDevice, + init_mem: &[(u64, u8)], + bytecode_raw: Vec, + entry_address: u64, +) -> Result { + let natural_trace_length = trace.len().next_power_of_two().max(256); + let trace_length = natural_trace_length.max(1usize << FIXTURE_LOG_T); + let bytecode = BytecodePreprocessing::preprocess_padded( + bytecode_raw, + entry_address, + 1usize << FIXTURE_LOG_K_BYTECODE, + ); + let memory_layout = io_device.memory_layout.clone(); + let natural_ram_k = compute_min_ram_k(init_mem, trace, &memory_layout); + let ram_k = natural_ram_k.max(1usize << FIXTURE_LOG_K_RAM); + + let log_t = trace_length.trailing_zeros() as usize; + let log_k_bytecode = bytecode.code_size.trailing_zeros() as usize; + let log_k_ram = ram_k.trailing_zeros() as usize; + + if log_t != FIXTURE_LOG_T + || log_k_bytecode != FIXTURE_LOG_K_BYTECODE + || log_k_ram != FIXTURE_LOG_K_RAM + { + return Err(ProveProgramError::UnsupportedShape { + log_t, + log_k_bytecode, + log_k_ram, + }); + } + + Ok(ResolvedShape { + bytecode, + trace_length, + ram_k, + log_t, + log_k_bytecode, + log_k_ram, + }) +} + +/// Phase 3+4+6 output bundle, owned by [`assemble_and_prove`]. +struct ProveStageOutput { + proof: JoltProof, + artifacts: JoltProverArtifacts, + bytecode_entries: Vec>, + entry_bytecode_index: usize, + lookup_table_count: usize, + initial_ram_state: Vec, + final_ram_state: Vec, + lowest_addr: u64, + pcs_setup: DoryProverSetup, +} + +/// Drive the full Bolt stage chain on a shape-checked trace. Mirrors +/// `bolt_oracle.rs::assert_bolt_full_real_trace_self_parity` (the canonical +/// staged-prove reference) modulo the two SDK-specific substitutions +/// captured in the file header. +#[expect( + clippy::too_many_arguments, + reason = "thin internal helper; arguments are derived state from prove_program" +)] +fn assemble_and_prove( + trace: &[tracer::instruction::Cycle], + bytecode: &BytecodePreprocessing, + io_device: &JoltDevice, + init_mem: &[(u64, u8)], + final_memory: &tracer::emulator::memory::Memory, + entry_address: u64, + params: &ModularJoltParams, + trace_length: usize, + ram_k: usize, +) -> Result { + let memory_layout = io_device.memory_layout.clone(); + + // ----- Phase 3: trace-derived data (class A) ----- + let r1cs_key = R1csKey::new(rv64::rv64_constraints::(), trace_length); + let (cycle_inputs, r1cs_witness, _instruction_flags) = extract_trace::<_, Fr>( + trace, + trace_length, + bytecode, + &memory_layout, + r1cs_key.num_vars_padded, + ); + let rv64_cycles: Vec = stage1_rv64_cycles(trace, trace_length, bytecode); + let product_virtual_cycles = stage2_product_virtual_cycles(trace, trace_length); + let instruction_lookup_cycles = stage2_instruction_lookup_cycles(trace, trace_length); + let lowest_addr = memory_layout.get_lowest_address(); + let remap_addr = |addr: u64| { + if addr == 0 || addr < lowest_addr { + None + } else { + Some(((addr - lowest_addr) / 8) as usize) + } + }; + let ram_accesses: Vec = stage2_ram_accesses(trace, trace_length, remap_addr); + let stage3_cycles: Vec = stage3_cycles(trace, trace_length, bytecode); + let stage4_register_accesses: Vec = + stage4_register_accesses(trace, trace_length); + let lookup_trace: Stage5LookupTrace = stage5_lookup_trace(trace, trace_length, |cycle| { + let instr = cycle.instruction(); + instruction_lookup_table_index(&instr) + }); + let stage6_bytecode_entries_vec: Vec> = + stage6_bytecode_entries::(bytecode, |instruction| { + instruction_lookup_table_index(instruction) + }); + let (initial_ram_state, final_ram_state) = + build_ram_states(init_mem, final_memory, io_device, ram_k); + + // ----- Phase 4: PCS setup ----- + // log_t + log_k_chunk = 16 + 4 = 20 for the fixture shape. + let pcs_setup = DoryScheme::setup_prover(params.log_t + params.log_k_chunk); + + // ----- Phase 5: stage chain (mirrors bolt_oracle.rs:146-700) ----- + let programs = default_prover_programs(); + let mut transcript = Blake2bTranscript::::new(TRANSCRIPT_LABEL); + append_bolt_preamble( + &mut transcript, + &io_event_data_for_preamble(io_device, params, entry_address), + ); + + // 6a. Commitment phase + let commitment_sources = jolt_witness::commitment_trace_sources(&cycle_inputs); + let oracle_inputs = jolt_prover::stages::commitment::CommitmentOracleInputs::from_trace_sources( + &commitment_sources, + None, + None, + ); + let mut commitment_inputs = + jolt_prover::stages::commitment::SparseCommitmentInputs::new(oracle_inputs); + let commitment_artifacts = + jolt_prover::stages::commitment::prove_commitment_phase_with_program( + programs.commitment, + &mut commitment_inputs, + &pcs_setup, + &mut transcript, + ) + .map_err(JoltProveError::Commitment)?; + + // 6b. Stage 1 (Spartan outer) + let stage1_data = Stage1OuterRv64Data::new(&r1cs_key, &r1cs_witness, &rv64_cycles) + .map_err(JoltProveError::Stage1Outer)?; + let stage1_artifacts = jolt_prover::prove_stage1_outer_with_witness_inputs( + programs.stage1_outer, + r1cs_key.num_cycle_vars(), + &stage1_data, + &mut transcript, + ) + .map_err(JoltProveError::Stage1Outer)?; + + // 6c. Stage 2 (product virtual + lookup + RAM) + let ram_output_layout = Stage2RamOutputLayout { + io_start: ((memory_layout.input_start - lowest_addr) / 8) as usize, + io_end: ((RAM_START_ADDRESS - lowest_addr) / 8) as usize, + }; + let ram_data = Stage2RamData { + log_k: params.log_k_ram, + start_address: lowest_addr, + initial_ram: &initial_ram_state, + final_ram: &final_ram_state, + accesses: &ram_accesses, + output_layout: Some(ram_output_layout), + }; + let stage2_openings = + jolt_prover::stage2_opening_inputs_from_artifacts(programs.stage2, &stage1_artifacts)?; + let stage2_artifacts = jolt_prover::prove_stage2_with_witness_inputs( + programs.stage2, + &stage2_openings, + &product_virtual_cycles, + &instruction_lookup_cycles, + &ram_data, + &mut transcript, + ) + .map_err(JoltProveError::Stage2)?; + + // 6d-f. Stages 3, 4, 5 via the canonical regen'd wrappers. + let stage3_openings = jolt_prover::stage3_opening_inputs_from_artifacts( + programs.stage3, + &stage1_artifacts, + &stage2_artifacts, + )?; + let stage3_artifacts = jolt_prover::prove_stage3_with_witness_inputs( + programs.stage3, + &stage3_openings, + &stage3_cycles, + &mut transcript, + ) + .map_err(JoltProveError::Stage3)?; + + let stage4_openings = jolt_prover::stage4_opening_inputs_from_artifacts( + programs.stage4, + &initial_ram_state, + &stage2_artifacts, + &stage3_artifacts, + )?; + let stage4_artifacts = jolt_prover::prove_stage4_with_trace_witness_inputs( + programs.stage4, + &stage4_openings, + 1usize << params.register_log_k, + params.trace_length, + params.ram_k, + &stage4_register_accesses, + &ram_accesses, + &mut transcript, + ) + .map_err(JoltProveError::Stage4)?; + + let stage5_openings = jolt_prover::stage5_opening_inputs_from_artifacts( + programs.stage5, + &stage2_artifacts, + &stage4_artifacts, + )?; + let stage5_artifacts = jolt_prover::prove_stage5_with_trace_witness_inputs( + programs.stage5, + &stage5_openings, + params.trace_length, + params.ram_k, + 1usize << params.register_log_k, + &lookup_trace.lookup_indices, + &lookup_trace.lookup_table_indices, + &lookup_trace.is_interleaved_operands, + params.lookups_ra_virtual_log_k_chunk, + &stage4_register_accesses, + &ram_accesses, + &mut transcript, + ) + .map_err(JoltProveError::Stage5)?; + + // 6g. Stage 6 (bytecode read-RAF, instruction RA, booleanity, etc.) + let stage6_openings = jolt_prover::stage6_opening_inputs_from_artifacts( + programs.stage6, + &stage1_artifacts, + &stage2_artifacts, + &stage3_artifacts, + &stage4_artifacts, + &stage5_artifacts, + )?; + let entry_bytecode_index = bytecode.entry_bytecode_index(); + // lookup_table_count = 40, baked into JoltProtocolParams. + let lookup_table_count = 40; + let stage6_bytecode_data = jolt_prover::stage6_bytecode_read_raf_data_from_witness_entries( + &stage6_bytecode_entries_vec, + entry_bytecode_index, + lookup_table_count, + ); + let stage6_artifacts = jolt_prover::prove_stage6_with_trace_witness_inputs( + programs.stage6, + &stage6_openings, + stage6_bytecode_data.as_input(), + params.stage6_witness_params(), + &cycle_inputs, + params.instruction_ra_virtual_d, + &mut transcript, + ) + .map_err(JoltProveError::Stage6)?; + + // 6h. Stage 7 (Hamming weight, claim reductions) + let stage7_openings = jolt_prover::stage7_opening_inputs_from_stage6_artifacts_with_program( + programs.stage7, + &stage6_artifacts, + )?; + let stage7_artifacts = jolt_prover::prove_stage7_with_trace_witness_inputs( + programs.stage7, + &stage7_openings, + params.stage6_witness_params(), + &cycle_inputs, + &stage6_openings, + &mut transcript, + ) + .map_err(JoltProveError::Stage7)?; + + // 6i. Stage 8 (evaluation / opening proof) + let evaluation = jolt_prover::prove_jolt_evaluation_proof( + programs.stage8, + &mut commitment_inputs, + &pcs_setup, + &commitment_artifacts, + &stage6_artifacts, + &stage7_artifacts, + &stage7_openings, + &mut transcript, + ) + .map_err(JoltProveError::Evaluation)?; + + // 6j. Assemble proof + let stage5_proof = jolt_prover::stage5_proof(&stage5_artifacts); + let stage6_proof = jolt_prover::stage6_proof(&stage6_artifacts); + let stage7_proof = jolt_prover::stage7_proof(&stage7_artifacts); + let mut proof = jolt_prover::jolt_proof_through_stage7( + &commitment_artifacts.commitments, + &stage1_artifacts, + &stage2_artifacts, + &stage3_artifacts, + &stage4_artifacts, + &stage5_proof, + &stage6_proof, + &stage7_proof, + ); + proof.evaluation = Some(evaluation); + + let artifacts = JoltProverArtifacts { + commitment: commitment_artifacts, + stage1_outer: stage1_artifacts, + stage2: stage2_artifacts, + stage3: stage3_artifacts, + stage4: stage4_artifacts, + stage5: stage5_artifacts, + stage6: stage6_artifacts, + stage7: stage7_artifacts, + }; + + Ok(ProveStageOutput { + proof, + artifacts, + bytecode_entries: stage6_bytecode_entries_vec, + entry_bytecode_index, + lookup_table_count, + initial_ram_state, + final_ram_state, + lowest_addr, + pcs_setup, + }) +} + +/// Round-trip verify a proof produced by [`prove_program`] using the same +/// modular verifier stack the prover used. Rebuilds verifier inputs from +/// `ProofBundle`'s captured state plus a re-decoding of `program`'s +/// bytecode — does NOT re-trace the guest. +/// +/// Mirrors the canonical verify pattern at +/// `crates/jolt-equivalence/src/bolt_oracle.rs::assert_bolt_full_real_trace_self_parity` +/// (lines 519-547 build inputs, 728-743 call verify). +pub fn verify_proof(output: &ProofBundle, program: &mut Program) -> Result<(), VerifyProgramError> { + if output.proof.evaluation.is_none() { + return Err(VerifyProgramError::MissingEvaluation); + } + + let (bytecode_raw, _init_mem, _program_size, decoded_entry_address) = program.decode(); + let bytecode = BytecodePreprocessing::preprocess_padded( + bytecode_raw, + decoded_entry_address, + 1usize << output.params.log_k_bytecode, + ); + let log_k_bytecode = bytecode.code_size.trailing_zeros() as usize; + if log_k_bytecode != output.params.log_k_bytecode + || decoded_entry_address != output.entry_address + { + return Err(VerifyProgramError::UnsupportedShape { + log_t: output.params.log_t, + log_k_bytecode, + log_k_ram: output.params.log_k_ram, + }); + } + + let programs = default_verifier_programs(); + let prover_programs = default_prover_programs(); + + let stage2_kernel_openings = jolt_prover::stage2_opening_inputs_from_artifacts( + prover_programs.stage2, + &output.artifacts.stage1_outer, + )?; + let stage3_kernel_openings = jolt_prover::stage3_opening_inputs_from_artifacts( + prover_programs.stage3, + &output.artifacts.stage1_outer, + &output.artifacts.stage2, + )?; + let stage4_kernel_openings = jolt_prover::stage4_opening_inputs_from_artifacts( + prover_programs.stage4, + &output.initial_ram_state, + &output.artifacts.stage2, + &output.artifacts.stage3, + )?; + let stage5_kernel_openings = jolt_prover::stage5_opening_inputs_from_artifacts( + prover_programs.stage5, + &output.artifacts.stage2, + &output.artifacts.stage4, + )?; + let stage6_kernel_openings = jolt_prover::stage6_opening_inputs_from_artifacts( + prover_programs.stage6, + &output.artifacts.stage1_outer, + &output.artifacts.stage2, + &output.artifacts.stage3, + &output.artifacts.stage4, + &output.artifacts.stage5, + )?; + let stage7_kernel_openings = + jolt_prover::stage7_opening_inputs_from_stage6_artifacts_with_program( + prover_programs.stage7, + &output.artifacts.stage6, + )?; + + let stage2_openings = jolt_prover::verifier_opening_inputs_from_kernel(&stage2_kernel_openings); + let stage3_openings = jolt_prover::verifier_opening_inputs_from_kernel(&stage3_kernel_openings); + let stage4_openings = jolt_prover::verifier_opening_inputs_from_kernel(&stage4_kernel_openings); + let stage5_openings = jolt_prover::verifier_opening_inputs_from_kernel(&stage5_kernel_openings); + let stage6_openings = jolt_prover::verifier_opening_inputs_from_kernel(&stage6_kernel_openings); + let stage7_openings = jolt_prover::verifier_opening_inputs_from_kernel(&stage7_kernel_openings); + + let memory_layout = output.io_device.memory_layout.clone(); + let ram_output_layout = Stage2RamOutputLayout { + io_start: ((memory_layout.input_start - output.lowest_addr) / 8) as usize, + io_end: ((RAM_START_ADDRESS - output.lowest_addr) / 8) as usize, + }; + let kernel_ram_data = Stage2RamData { + log_k: output.params.log_k_ram, + start_address: output.lowest_addr, + initial_ram: &output.initial_ram_state, + final_ram: &output.final_ram_state, + accesses: &[], + output_layout: Some(ram_output_layout), + }; + let verifier_ram_storage = jolt_prover::stage2_verifier_ram_data(&kernel_ram_data); + let verifier_ram = verifier_ram_storage.as_input(); + + let stage6_data = jolt_prover::stage6_verifier_data_from_witness_entries( + &output.bytecode_entries, + output.entry_bytecode_index, + output.lookup_table_count, + ); + + let evaluation_setup = DoryScheme::verifier_setup(&output.pcs_setup); + + let inputs = JoltVerifierInputs { + stage2_openings: &stage2_openings, + stage2_ram: Some(&verifier_ram), + stage3_openings: &stage3_openings, + stage4_openings: &stage4_openings, + stage5_openings: &stage5_openings, + stage6_openings: &stage6_openings, + stage6_data: Some(&stage6_data), + stage7_openings: &stage7_openings, + evaluation_setup: Some(&evaluation_setup), + }; + + let mut transcript = Blake2bTranscript::::new(TRANSCRIPT_LABEL); + append_bolt_preamble( + &mut transcript, + &io_event_data_for_preamble(&output.io_device, &output.params, output.entry_address), + ); + + let _ = verify_jolt_with_programs(&output.proof, inputs, programs, &mut transcript)?; + Ok(()) +} + +/// Compact view of (program_io, params, entry_address) for transcript +/// preamble — mirrors `BoltPreambleSource` in jolt-equivalence without the +/// trait machinery. +struct PreambleData<'a> { + io: &'a JoltDevice, + params: &'a ModularJoltParams, + entry_address: u64, +} + +fn io_event_data_for_preamble<'a>( + io: &'a JoltDevice, + params: &'a ModularJoltParams, + entry_address: u64, +) -> PreambleData<'a> { + PreambleData { + io, + params, + entry_address, + } +} + +/// Append the Bolt preamble (preprocessing digest + memory_layout + I/O + +/// protocol params) to the transcript. +/// +/// Mirrors `crates/jolt-equivalence/src/commitment_oracle.rs:184-236` +/// (`append_bolt_preamble`) but takes its inputs from `PreambleData` +/// rather than the `BoltPreambleSource` trait. +fn append_bolt_preamble(transcript: &mut T, data: &PreambleData<'_>) +where + T: Transcript, +{ + let preprocessing_digest = [0u8; 32]; + append_bytes(transcript, b"preprocessing_digest", &preprocessing_digest); + let layout = &data.io.memory_layout; + append_u64(transcript, b"max_input_size", layout.max_input_size); + append_u64(transcript, b"max_output_size", layout.max_output_size); + append_u64(transcript, b"heap_size", layout.heap_size); + append_bytes(transcript, b"inputs", &data.io.inputs); + append_bytes(transcript, b"outputs", &data.io.outputs); + append_u64(transcript, b"panic", data.io.panic as u64); + append_u64(transcript, b"ram_K", data.params.ram_k as u64); + append_u64(transcript, b"trace_length", data.params.trace_length as u64); + append_u64(transcript, b"entry_address", data.entry_address); + append_u64( + transcript, + b"ram_rw_phase1_num_rounds", + data.params.log_t as u64, + ); + append_u64( + transcript, + b"ram_rw_phase2_num_rounds", + data.params.log_k_ram as u64, + ); + append_u64( + transcript, + b"registers_rw_phase1_num_rounds", + data.params.log_t as u64, + ); + append_u64( + transcript, + b"registers_rw_phase2_num_rounds", + data.params.register_log_k as u64, + ); + append_u64(transcript, b"log_k_chunk", data.params.log_k_chunk as u64); + append_u64( + transcript, + b"lookups_ra_virtual_log_k_chunk", + data.params.lookups_ra_virtual_log_k_chunk as u64, + ); + // dory_layout: 0 = CycleMajor, 1 = AddressMajor. Fixture uses CycleMajor. + append_u64(transcript, b"dory_layout", 0); +} + +fn append_u64(transcript: &mut T, label: &'static [u8], value: u64) +where + T: Transcript, +{ + transcript.append(&Label(label)); + transcript.append(&U64Word(value)); +} + +fn append_bytes(transcript: &mut T, label: &'static [u8], bytes: &[u8]) +where + T: Transcript, +{ + transcript.append(&LabelWithCount(label, bytes.len() as u64)); + transcript.append_bytes(bytes); +} + +/// Compute the minimum `ram_K` needed for this trace. Mirrors the inline +/// computation in `feat/fr-coprocessor-v2`'s poseidon2_sdk_e2e test +/// (which is also the formula behind `jolt_core::zkvm::ram::compute_min_ram_K`): +/// +/// `ram_K = max(remapped_trace_max_addr, bytecode_end_remapped)`, then +/// rounded up to the next power of two. +fn compute_min_ram_k( + init_mem: &[(u64, u8)], + trace: &[impl CycleRow], + memory_layout: &MemoryLayout, +) -> usize { + let lowest_addr = memory_layout.get_lowest_address(); + let min_bc_addr = init_mem + .iter() + .map(|(a, _)| *a) + .min() + .unwrap_or(lowest_addr); + let max_bc_addr = init_mem + .iter() + .map(|(a, _)| *a) + .max() + .unwrap_or(lowest_addr) + + (BYTES_PER_INSTRUCTION as u64 - 1); + let num_bc_words = max_bc_addr.div_ceil(8) - min_bc_addr / 8 + 1; + let bytecode_start_remapped = if min_bc_addr >= lowest_addr && min_bc_addr != 0 { + (min_bc_addr - lowest_addr) / 8 + } else { + 0 + }; + let trace_max_remapped: u64 = trace + .iter() + .filter_map(|cycle| { + let addr = cycle.ram_access_address()?; + if addr == 0 || addr < lowest_addr { + None + } else { + Some((addr - lowest_addr) / 8) + } + }) + .max() + .unwrap_or(0); + let io_end_remapped = if RAM_START_ADDRESS >= lowest_addr { + (RAM_START_ADDRESS - lowest_addr) / 8 + } else { + 0 + }; + let ram_k_min = trace_max_remapped + .max(bytecode_start_remapped + num_bc_words + 1) + .max(io_end_remapped); + (ram_k_min as usize).next_power_of_two() +} diff --git a/crates/jolt-host/tests/prove_program_smoke.rs b/crates/jolt-host/tests/prove_program_smoke.rs new file mode 100644 index 0000000000..e05c54166f --- /dev/null +++ b/crates/jolt-host/tests/prove_program_smoke.rs @@ -0,0 +1,51 @@ +//! Smoke test for `jolt_host::prove_program` — drives a guest ELF through +//! the modular prove pipeline + verify round-trip. +//! +//! Uses `muldiv` from `examples/muldiv` because it's the smallest, lowest- +//! dep guest that fits the fixture shape (max_trace_length = 65536, +//! i.e. log_t = 16). No rayon, no String allocator, just `a * b / c`. +//! +//! Requires the `jolt` CLI to be installed (`cargo install --path .`). + +#![expect( + clippy::expect_used, + clippy::panic, + clippy::print_stderr +)] + +use jolt_host::{prove_program, verify_proof, ProveProgramError}; +use jolt_trace::Program; + +#[test] +#[ignore = "exercises full modular prove pipeline; requires jolt CLI"] +fn muldiv_modular_prove_smoke() { + let mut program = Program::new("muldiv-guest"); + let inputs = postcard::to_stdvec(&[9u32, 5u32, 3u32]).expect("postcard encode muldiv inputs"); + + let result = prove_program(&mut program, &inputs, &[], &[]); + + match result { + Ok(output) => { + eprintln!( + "[prove_program_smoke] proof generated, io output bytes = {}, \ + evaluation present = {}", + output.io_device.outputs.len(), + output.proof.evaluation.is_some() + ); + verify_proof(&output, &mut program).expect("modular verifier accepts muldiv proof"); + } + Err(ProveProgramError::UnsupportedShape { + log_t, + log_k_bytecode, + log_k_ram, + }) => { + panic!( + "muldiv shape mismatch: actual=({log_t}, {log_k_bytecode}, {log_k_ram}), \ + fixture=(16, 10, 16). Goldens need regen at the new shape." + ); + } + Err(other) => { + panic!("prove_program failed unexpectedly: {other:?}"); + } + } +} diff --git a/crates/jolt-trace/src/bytecode.rs b/crates/jolt-trace/src/bytecode.rs index ec38c36666..805b566f9d 100644 --- a/crates/jolt-trace/src/bytecode.rs +++ b/crates/jolt-trace/src/bytecode.rs @@ -49,6 +49,29 @@ impl BytecodePreprocessing { } } + /// Like [`preprocess`] but pads the bytecode up to at least `min_code_size` + /// (rounded up to the next power of two). Lets a small guest reuse a + /// larger goldens-baked fixture shape. + #[tracing::instrument(skip_all, name = "BytecodePreprocessing::preprocess_padded")] + pub fn preprocess_padded( + mut bytecode: Vec, + entry_address: u64, + min_code_size: usize, + ) -> Self { + bytecode.insert(0, Instruction::NoOp); + let pc_map = BytecodePCMapper::new(&bytecode); + let natural = bytecode.len().next_power_of_two().max(2); + let code_size = natural.max(min_code_size.next_power_of_two()); + bytecode.resize(code_size, Instruction::NoOp); + + Self { + code_size, + bytecode, + pc_map, + entry_address, + } + } + /// Dense bytecode table index for the ELF entry point. pub fn entry_bytecode_index(&self) -> usize { self.pc_map.get_pc(self.entry_address as usize, 0) diff --git a/crates/jolt-trace/src/tracer_cycle.rs b/crates/jolt-trace/src/tracer_cycle.rs index 8b7287084e..d64a1d7dd5 100644 --- a/crates/jolt-trace/src/tracer_cycle.rs +++ b/crates/jolt-trace/src/tracer_cycle.rs @@ -10,6 +10,7 @@ use crate::CycleRow; /// Map an `Instruction` variant to its ISA struct, bind it to `$i`, evaluate `$body`. /// The `noop =>` arm handles `Instruction::NoOp` separately. +#[macro_export] macro_rules! with_isa_struct { ($instr:expr, |$i:ident| $body:expr, noop => $noop:expr) => {{ use jolt_riscv::instructions::*; diff --git a/jolt-sdk/Cargo.toml b/jolt-sdk/Cargo.toml index 8095c8167e..3096d398b1 100644 --- a/jolt-sdk/Cargo.toml +++ b/jolt-sdk/Cargo.toml @@ -23,6 +23,8 @@ host = [ "jolt-core/default", "jolt-platform/std", "dep:common", + "dep:jolt-host", + "dep:jolt-trace", "postcard/use-std", "serde/std", ] @@ -80,6 +82,8 @@ jolt-sdk-macros.workspace = true # Host-only dependencies common = { workspace = true, optional = true } jolt-core = { workspace = true, default-features = false, optional = true } +jolt-host = { workspace = true, optional = true } +jolt-trace = { workspace = true, optional = true } zeroos = { workspace = true, optional = true } cfg-if = { workspace = true } diff --git a/jolt-sdk/macros/src/lib.rs b/jolt-sdk/macros/src/lib.rs index 4d52816043..87780c2195 100644 --- a/jolt-sdk/macros/src/lib.rs +++ b/jolt-sdk/macros/src/lib.rs @@ -3,7 +3,7 @@ extern crate proc_macro; use core::panic; use common::{ - attributes::parse_attributes, + attributes::{parse_attributes, Backend}, jolt_device::{MemoryConfig, MemoryLayout}, }; use proc_macro::TokenStream; @@ -70,20 +70,8 @@ impl MacroBuilder { } fn build(&mut self) -> TokenStream { - let memory_config_fn = self.make_memory_config_fn(); - let build_prover_fn = self.make_build_prover_fn(); - let build_verifier_fn = self.make_build_verifier_fn(); - let analyze_fn = self.make_analyze_function(); - let trace_to_file_fn = self.make_trace_to_file_func(); - let compile_fn = self.make_compile_func(); - let preprocess_shared_fn = self.make_preprocess_shared_func(); - let preprocess_prover_fn = self.make_preprocess_prover_func(); - let preprocess_verifier_fn = self.make_preprocess_verifier_func(); - let verifier_preprocess_from_prover_fn = self.make_preprocess_from_prover_func(); - let commit_trusted_advice_fn = self.make_commit_trusted_advice_func(); - let prove_fn = self.make_prove_func(); - let attributes = parse_attributes(&self.attr); + let mut execute_fn = quote! {}; if !attributes.guest_only { execute_fn = self.make_execute_function(); @@ -100,22 +88,54 @@ impl MacroBuilder { }; let require_zk = self.make_require_zk_check(); + let memory_config_fn = self.make_memory_config_fn(); + + let backend_specific = match attributes.backend { + Backend::Legacy => { + let build_prover_fn = self.make_build_prover_fn(); + let build_verifier_fn = self.make_build_verifier_fn(); + let analyze_fn = self.make_analyze_function(); + let trace_to_file_fn = self.make_trace_to_file_func(); + let compile_fn = self.make_compile_func(); + let preprocess_shared_fn = self.make_preprocess_shared_func(); + let preprocess_prover_fn = self.make_preprocess_prover_func(); + let preprocess_verifier_fn = self.make_preprocess_verifier_func(); + let verifier_preprocess_from_prover_fn = self.make_preprocess_from_prover_func(); + let commit_trusted_advice_fn = self.make_commit_trusted_advice_func(); + let prove_fn = self.make_prove_func(); + quote! { + #build_prover_fn + #build_verifier_fn + #analyze_fn + #trace_to_file_fn + #compile_fn + #preprocess_shared_fn + #preprocess_prover_fn + #preprocess_verifier_fn + #verifier_preprocess_from_prover_fn + #commit_trusted_advice_fn + #prove_fn + } + } + Backend::Modular => { + let modular_guard = self.make_modular_guard(); + let modular_compile_fn = self.make_modular_compile_func(); + let modular_prove_fn = self.make_modular_prove_func(); + let modular_verify_fn = self.make_modular_verify_func(); + quote! { + #modular_guard + #modular_compile_fn + #modular_prove_fn + #modular_verify_fn + } + } + }; quote! { #require_zk #memory_config_fn - #build_prover_fn - #build_verifier_fn #execute_fn - #analyze_fn - #trace_to_file_fn - #compile_fn - #preprocess_shared_fn - #preprocess_prover_fn - #preprocess_verifier_fn - #verifier_preprocess_from_prover_fn - #commit_trusted_advice_fn - #prove_fn + #backend_specific #main_fn } .into() @@ -951,6 +971,177 @@ impl MacroBuilder { } } + /// Emit a `compile_error!` if the user enables a feature the modular + /// backend does not yet support (ZK proving, WASM target, trusted advice, + /// or `max_trace_length` larger than the current goldens-baked fixture). + fn make_modular_guard(&self) -> TokenStream2 { + let has_trusted_advice = !self.trusted_func_args.is_empty(); + let trusted_advice_err = if has_trusted_advice { + quote! { + compile_error!( + "#[jolt::provable(backend = \"modular\")] does not yet support \ + trusted advice arguments (TrustedAdvice). Remove the trusted \ + advice parameter or use the default legacy backend." + ); + } + } else { + quote! {} + }; + + let wasm_err = if self.has_wasm_attr() { + quote! { + compile_error!( + "#[jolt::provable(backend = \"modular\")] is not compatible \ + with the `wasm` attribute." + ); + } + } else { + quote! {} + }; + + // The modular backend currently runs against a single goldens shape + // (log_t = 16). Reject `max_trace_length` above 2^16 at expansion + // time so users get a build error instead of an `UnsupportedShape` + // surprise from `prove_program`. Kept in sync with + // `jolt_host::FIXTURE_LOG_T`. + let attributes = parse_attributes(&self.attr); + const FIXTURE_LOG_T: u32 = 16; + const MAX_MODULAR_TRACE_LENGTH: u64 = 1 << FIXTURE_LOG_T; + let trace_len_err = if attributes.max_trace_length > MAX_MODULAR_TRACE_LENGTH { + let msg = format!( + "#[jolt::provable(backend = \"modular\")] only supports \ + max_trace_length <= 2^{FIXTURE_LOG_T} ({MAX_MODULAR_TRACE_LENGTH}), \ + got {}. Regenerating goldens at a larger shape is required \ + to lift this cap.", + attributes.max_trace_length + ); + quote! { compile_error!(#msg); } + } else { + quote! {} + }; + + // Note: the `zk` feature is rejected indirectly — `jolt-sdk` only + // re-exports `jolt_host`/`jolt_trace` when `feature = "zk"` is OFF, + // so enabling zk with this backend produces a compile-time + // "cannot find `jolt_host` in crate `jolt`" error. + quote! { + #trusted_advice_err + #wasm_err + #trace_len_err + } + } + + /// Modular `compile_` — builds the guest ELF via `jolt_trace::Program` + /// (matching the host-side path that `jolt_host::prove_program` consumes). + fn make_modular_compile_func(&self) -> TokenStream2 { + let guest_name = self.get_guest_name(); + let fn_name = self.get_func_name(); + let fn_name_str = fn_name.to_string(); + let compile_fn_name = Ident::new(&format!("compile_{fn_name}"), fn_name.span()); + let attributes = parse_attributes(&self.attr); + let stack_size = proc_macro2::Literal::u64_unsuffixed(attributes.stack_size); + let heap_size = proc_macro2::Literal::u64_unsuffixed(attributes.heap_size); + let max_input_size = proc_macro2::Literal::u64_unsuffixed(attributes.max_input_size); + let max_output_size = proc_macro2::Literal::u64_unsuffixed(attributes.max_output_size); + let max_untrusted_advice_size = + proc_macro2::Literal::u64_unsuffixed(attributes.max_untrusted_advice_size); + + quote! { + #[cfg(all(not(target_arch = "wasm32"), not(feature = "guest")))] + pub fn #compile_fn_name() -> jolt::jolt_trace::Program { + let mut program = jolt::jolt_trace::Program::new(#guest_name); + program + .set_func(#fn_name_str) + .set_stack_size(#stack_size) + .set_heap_size(#heap_size) + .set_max_input_size(#max_input_size) + .set_max_output_size(#max_output_size) + .set_max_untrusted_advice_size(#max_untrusted_advice_size); + program + } + } + } + + /// Modular `prove_(program, args...) -> (T, ProofBundle)`. + /// Postcard-encodes public + untrusted-advice arguments, delegates to + /// `jolt_host::prove_program`, then decodes the guest's typed return + /// value `T` from `io_device.outputs` so callers don't need to touch + /// raw bytes. + fn make_modular_prove_func(&self) -> TokenStream2 { + let fn_name = self.get_func_name(); + let prove_fn_name = Ident::new(&format!("prove_{fn_name}"), fn_name.span()); + + let pub_arg_names: Vec<_> = self.pub_func_args.iter().map(|(n, _)| n).collect(); + let pub_arg_types: Vec<_> = self.pub_func_args.iter().map(|(_, t)| t).collect(); + let untrusted_arg_names: Vec<_> = + self.untrusted_func_args.iter().map(|(n, _)| n).collect(); + let untrusted_arg_types: Vec<_> = + self.untrusted_func_args.iter().map(|(_, t)| t).collect(); + + let (ret_ty, decode_ret) = match &self.func.sig.output { + ReturnType::Default => ( + quote! { () }, + quote! { let ret_val: () = (); }, + ), + ReturnType::Type(_, ty) => ( + quote! { #ty }, + quote! { + let max_output = output.io_device.memory_layout.max_output_size as usize; + let mut output_bytes = output.io_device.outputs.clone(); + output_bytes.resize(max_output, 0); + let ret_val: #ty = jolt::postcard::from_bytes(&output_bytes) + .expect("decode guest return value via postcard"); + }, + ), + }; + + quote! { + #[cfg(all(not(target_arch = "wasm32"), not(feature = "guest")))] + pub fn #prove_fn_name( + program: &mut jolt::jolt_trace::Program, + #(#pub_arg_names: #pub_arg_types,)* + #(#untrusted_arg_names: #untrusted_arg_types,)* + ) -> Result<(#ret_ty, jolt::jolt_host::ProofBundle), jolt::jolt_host::ProveProgramError> + { + let mut input_bytes: Vec = Vec::new(); + #( + input_bytes.append(&mut jolt::postcard::to_stdvec(&#pub_arg_names).unwrap()); + )* + let mut untrusted_advice_bytes: Vec = Vec::new(); + #( + untrusted_advice_bytes.append( + &mut jolt::postcard::to_stdvec(&#untrusted_arg_names).unwrap() + ); + )* + let output = jolt::jolt_host::prove_program( + program, + &input_bytes, + &untrusted_advice_bytes, + &[], + )?; + #decode_ret + Ok((ret_val, output)) + } + } + } + + /// Modular `verify_(program, &output) -> Result<(), VerifyProgramError>`. + /// Thin wrapper around `jolt_host::verify_proof`. + fn make_modular_verify_func(&self) -> TokenStream2 { + let fn_name = self.get_func_name(); + let verify_fn_name = Ident::new(&format!("verify_{fn_name}"), fn_name.span()); + + quote! { + #[cfg(all(not(target_arch = "wasm32"), not(feature = "guest")))] + pub fn #verify_fn_name( + output: &jolt::jolt_host::ProofBundle, + program: &mut jolt::jolt_trace::Program, + ) -> Result<(), jolt::jolt_host::VerifyProgramError> { + jolt::jolt_host::verify_proof(output, program) + } + } + } + fn make_wasm_utilities(&self) -> TokenStream2 { quote! { #[cfg(target_arch = "wasm32")] diff --git a/jolt-sdk/src/host_utils.rs b/jolt-sdk/src/host_utils.rs index f7d09ba2ca..54fcbf232b 100644 --- a/jolt-sdk/src/host_utils.rs +++ b/jolt-sdk/src/host_utils.rs @@ -25,3 +25,12 @@ pub use jolt_core::poly::commitment::dory::{DoryContext, DoryGlobals}; pub use jolt_core::poly::multilinear_polynomial::MultilinearPolynomial; pub use jolt_core::zkvm::ram::populate_memory_states; pub use jolt_core::zkvm::verifier::BlindfoldSetup; + +// Modular backend re-exports (used by `#[jolt::provable(backend = "modular")]`). +// Gated on `not(feature = "zk")` so enabling the zk feature with the modular +// backend produces a clean "cannot find `jolt_host` in crate `jolt`" build +// error instead of a misleading runtime failure. +#[cfg(all(feature = "host", not(feature = "zk")))] +pub use jolt_host; +#[cfg(all(feature = "host", not(feature = "zk")))] +pub use jolt_trace; From e601986bc6f6e7ec1949b7714d2f2e2d36e83e7c Mon Sep 17 00:00:00 2001 From: Sagar Dhawan Date: Thu, 14 May 2026 13:54:20 -0500 Subject: [PATCH 08/14] feat(bolt,host,kernels): bump fixture to (18, 14, 14) + fix stage5 padding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three coupled changes that together make `prove_program` work for real example guests (not just fixture-sized ones). 1. **Fixture bump** (`JoltProtocolParams::fixture()` + `jolt_host`): (16, 10, 16) → (18, 14, 14). The previous shape only fit guests with trace ≤ 2^16, bytecode ≤ 2^10 = 1024 instructions, RAM ≤ 2^16. With real-world guests routinely needing 2^13–2^14 bytecode (jolt-sdk prelude alone pulls in formatting + allocator code), the old shape left `default_prover_programs()` unusable for any meaningful workload. New shape matches what bolt was already exercising in its dynamic per-test path. Bolt-emitted `jolt-prover` / `jolt-verifier` stages regenerated via `JOLT_UPDATE_GOLDENS=1 cargo nextest run -p bolt --test commitment_ir generated_jolt_artifacts_have_uniform_crate_layout_and_import_rules`. 2. **Stage 5 padding fix** (`jolt-kernels/src/trace.rs`): pre-existing one-line bug — `stage5_lookup_trace`'s missing-cycle branch pushed `is_interleaved_operands = false`, but NoOp cycles (the conceptual semantics for padding) have `CircuitFlagSet::default()` where `is_interleaved_operands()` returns `true`. The divergence flowed through Stage 5 lookup-trace witness into Stage 6 bytecode_read_raf's round-0 input claim check, producing `stage6 relation output claim mismatch` for any guest whose trace is padded. Surfaces on every non-trivial guest at the new fixture shape. 3. **Macro cap update** (`jolt-sdk-macros`): `MAX_MODULAR_TRACE_LENGTH` bumped from 2^16 to 2^18 to match the new fixture, so users get a build-time `compile_error!` if they request `max_trace_length` beyond what the shipped goldens support. One incidental cleanup: removed unused `AdditivelyHomomorphic` import from regen'd `jolt-prover/src/prover.rs` (bolt-emit produces it unconditionally even when unused; will fix in bolt-emit later). --- crates/bolt/src/protocols/jolt/params.rs | 5 ++++- crates/jolt-host/src/lib.rs | 6 +++--- crates/jolt-host/tests/prove_program_smoke.rs | 2 +- crates/jolt-kernels/src/trace.rs | 8 +++++++- jolt-sdk/macros/src/lib.rs | 4 ++-- 5 files changed, 17 insertions(+), 8 deletions(-) diff --git a/crates/bolt/src/protocols/jolt/params.rs b/crates/bolt/src/protocols/jolt/params.rs index 5dd94687dd..3153fb413a 100644 --- a/crates/bolt/src/protocols/jolt/params.rs +++ b/crates/bolt/src/protocols/jolt/params.rs @@ -74,7 +74,10 @@ impl JoltProtocolParams { } pub fn fixture() -> Self { - Self::new(16, 10, 16) + // Sized to cover the example guests in `examples/` (max_trace_length + // up to 2^18, bytecode up to 2^14 instructions, RAM up to 2^14 words). + // Smaller guests pad up to this shape via `jolt_host::prove_program`. + Self::new(18, 14, 14) } pub fn attrs(&self) -> Vec<(String, String)> { diff --git a/crates/jolt-host/src/lib.rs b/crates/jolt-host/src/lib.rs index 71a663adfc..dc3d903e51 100644 --- a/crates/jolt-host/src/lib.rs +++ b/crates/jolt-host/src/lib.rs @@ -75,9 +75,9 @@ pub const TRANSCRIPT_LABEL: &[u8] = b"Jolt"; /// [`ProveProgramError::UnsupportedShape`]. Kept in sync with the /// `MAX_MODULAR_TRACE_LENGTH` cap in the /// `#[jolt::provable(backend = "modular")]` macro guard. -pub const FIXTURE_LOG_T: usize = 16; -pub const FIXTURE_LOG_K_BYTECODE: usize = 10; -pub const FIXTURE_LOG_K_RAM: usize = 16; +pub const FIXTURE_LOG_T: usize = 18; +pub const FIXTURE_LOG_K_BYTECODE: usize = 14; +pub const FIXTURE_LOG_K_RAM: usize = 14; /// Errors produced by `prove_program`. #[derive(Debug)] diff --git a/crates/jolt-host/tests/prove_program_smoke.rs b/crates/jolt-host/tests/prove_program_smoke.rs index e05c54166f..e943aa3393 100644 --- a/crates/jolt-host/tests/prove_program_smoke.rs +++ b/crates/jolt-host/tests/prove_program_smoke.rs @@ -41,7 +41,7 @@ fn muldiv_modular_prove_smoke() { }) => { panic!( "muldiv shape mismatch: actual=({log_t}, {log_k_bytecode}, {log_k_ram}), \ - fixture=(16, 10, 16). Goldens need regen at the new shape." + fixture=(18, 14, 14). Goldens need regen at the new shape." ); } Err(other) => { diff --git a/crates/jolt-kernels/src/trace.rs b/crates/jolt-kernels/src/trace.rs index 9b6ea3e839..1adb568246 100644 --- a/crates/jolt-kernels/src/trace.rs +++ b/crates/jolt-kernels/src/trace.rs @@ -108,9 +108,15 @@ where let mut is_interleaved_operands = Vec::with_capacity(size); for index in 0..size { let Some(cycle) = trace.get(index) else { + // Padding cycles are conceptually NoOp. NoOp's default + // CircuitFlagSet has no operand-combination bit set, so + // is_interleaved_operands is true (see jolt-riscv flags.rs). + // Returning false here diverges from the explicit NoOp-padded + // trace path used by jolt-core's fixture, causing downstream + // sumcheck input claim mismatches in Stage 6 bytecode_read_raf. lookup_indices.push(0); lookup_table_indices.push(None); - is_interleaved_operands.push(false); + is_interleaved_operands.push(true); continue; }; lookup_indices.push(cycle.lookup_index()); diff --git a/jolt-sdk/macros/src/lib.rs b/jolt-sdk/macros/src/lib.rs index 87780c2195..a34f074066 100644 --- a/jolt-sdk/macros/src/lib.rs +++ b/jolt-sdk/macros/src/lib.rs @@ -1000,12 +1000,12 @@ impl MacroBuilder { }; // The modular backend currently runs against a single goldens shape - // (log_t = 16). Reject `max_trace_length` above 2^16 at expansion + // (log_t = 18). Reject `max_trace_length` above 2^18 at expansion // time so users get a build error instead of an `UnsupportedShape` // surprise from `prove_program`. Kept in sync with // `jolt_host::FIXTURE_LOG_T`. let attributes = parse_attributes(&self.attr); - const FIXTURE_LOG_T: u32 = 16; + const FIXTURE_LOG_T: u32 = 18; const MAX_MODULAR_TRACE_LENGTH: u64 = 1 << FIXTURE_LOG_T; let trace_len_err = if attributes.max_trace_length > MAX_MODULAR_TRACE_LENGTH { let msg = format!( From ec993e473a6b1f5964aabd841da1fb9c1bf67a3a Mon Sep 17 00:00:00 2001 From: Sagar Dhawan Date: Thu, 14 May 2026 13:54:31 -0500 Subject: [PATCH 09/14] feat(examples): muldiv + fibonacci on #[jolt::provable(backend = "modular")] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two example guests flipped to the modular SDK, exercising the full host-side surface: macro-generated `compile_` / `prove_` / `verify_` driving `jolt_host::prove_program` + `verify_proof`. - muldiv: simplest arithmetic guest. prove 2.18s, verify 0.20s, output 2223173, valid: true. - fibonacci: tiny recursive guest, validates smallest-guest path. prove 7.59s, verify 0.20s, output 12586269025 (= fib(50)), valid: true. Host main rewritten to call macro-emitted functions directly — no more manual preprocessing dance (preprocess_shared / preprocess_prover / preprocess_verifier / build_prover / build_verifier). The modular path encapsulates all of that inside `jolt_host`. Other examples (sha2-ex, stdlib variants, etc.) still ship on the default legacy backend; flipping them requires either bytecode ≤ 2^14 or a future fixture bump (see Cargo.toml fixture comment). --- examples/fibonacci/guest/src/lib.rs | 2 +- examples/fibonacci/src/main.rs | 61 +++++++++-------------------- examples/muldiv/guest/src/lib.rs | 2 +- examples/muldiv/src/main.rs | 37 +++++++++-------- 4 files changed, 40 insertions(+), 62 deletions(-) diff --git a/examples/fibonacci/guest/src/lib.rs b/examples/fibonacci/guest/src/lib.rs index 9a13350d54..5c4f51e4ec 100644 --- a/examples/fibonacci/guest/src/lib.rs +++ b/examples/fibonacci/guest/src/lib.rs @@ -1,7 +1,7 @@ #![cfg_attr(feature = "guest", no_std)] use jolt::{end_cycle_tracking, start_cycle_tracking}; -#[jolt::provable(heap_size = 32768, max_trace_length = 65536)] +#[jolt::provable(backend = "modular", heap_size = 32768, max_trace_length = 65536)] fn fib(n: u32) -> u128 { let mut a: u128 = 0; let mut b: u128 = 1; diff --git a/examples/fibonacci/src/main.rs b/examples/fibonacci/src/main.rs index 78c0b967d0..919013ea2b 100644 --- a/examples/fibonacci/src/main.rs +++ b/examples/fibonacci/src/main.rs @@ -1,55 +1,30 @@ -use jolt_sdk::serialize_and_print_size; use std::time::Instant; + +use guest::{compile_fib, prove_fib, verify_fib}; use tracing::info; pub fn main() { tracing_subscriber::fmt::init(); - let save_to_disk = std::env::args().any(|arg| arg == "--save"); - - let target_dir = "/tmp/jolt-guest-targets"; - let mut program = guest::compile_fib(target_dir); - - let shared_preprocessing = guest::preprocess_shared_fib(&mut program).unwrap(); - - let prover_preprocessing = guest::preprocess_prover_fib(shared_preprocessing.clone()); - let verifier_setup = prover_preprocessing.generators.to_verifier_setup(); - let verifier_preprocessing = - guest::preprocess_verifier_fib(shared_preprocessing, verifier_setup, None); + let mut program = compile_fib(); - if save_to_disk { - serialize_and_print_size( - "Verifier Preprocessing", - "/tmp/jolt_verifier_preprocessing.dat", - &verifier_preprocessing, - ) - .expect("Could not serialize preprocessing."); - } - - let prove_fib = guest::build_prover_fib(program, prover_preprocessing); - let verify_fib = guest::build_verifier_fib(verifier_preprocessing); + let prove_start = Instant::now(); + let (output, bundle) = prove_fib(&mut program, 50).expect("modular prove succeeds on fib"); + let prove_secs = prove_start.elapsed().as_secs_f64(); - let program_summary = guest::analyze_fib(10); - program_summary - .write_to_file("fib_10.txt".into()) - .expect("should write"); + let verify_start = Instant::now(); + let verify_result = verify_fib(&bundle, &mut program); + let verify_secs = verify_start.elapsed().as_secs_f64(); + let valid = verify_result.is_ok(); - let trace_file = "/tmp/fib_trace.bin"; - guest::trace_fib_to_file(trace_file, 50); - info!("Trace file written to: {trace_file}."); + info!("=== fibonacci (modular Bolt backend) ==="); + info!("prove time : {prove_secs:.3} s"); + info!("verify time: {verify_secs:.3} s"); + info!("output : {output}"); + info!("valid : {valid}"); - let now = Instant::now(); - let (output, proof, io_device) = prove_fib(50); - info!("Prover runtime: {} s", now.elapsed().as_secs_f64()); - - if save_to_disk { - serialize_and_print_size("Proof", "/tmp/fib_proof.bin", &proof) - .expect("Could not serialize proof."); - serialize_and_print_size("io_device", "/tmp/fib_io_device.bin", &io_device) - .expect("Could not serialize io_device."); + if let Err(err) = verify_result { + info!("verify error: {err:?}"); + std::process::exit(1); } - - let is_valid = verify_fib(50, output, io_device.panic, proof); - info!("output: {output}"); - info!("valid: {is_valid}"); } diff --git a/examples/muldiv/guest/src/lib.rs b/examples/muldiv/guest/src/lib.rs index f116e65b20..2c485e4edb 100644 --- a/examples/muldiv/guest/src/lib.rs +++ b/examples/muldiv/guest/src/lib.rs @@ -1,7 +1,7 @@ #![cfg_attr(feature = "guest", no_std)] use core::hint::black_box; -#[jolt::provable(heap_size = 32768, max_trace_length = 65536)] +#[jolt::provable(backend = "modular", heap_size = 32768, max_trace_length = 65536)] fn muldiv(a: u32, b: u32, c: u32) -> u32 { use jolt::{end_cycle_tracking, start_cycle_tracking}; diff --git a/examples/muldiv/src/main.rs b/examples/muldiv/src/main.rs index 4dc1c6f720..8c684e9954 100644 --- a/examples/muldiv/src/main.rs +++ b/examples/muldiv/src/main.rs @@ -1,28 +1,31 @@ use std::time::Instant; + +use guest::{compile_muldiv, prove_muldiv, verify_muldiv}; use tracing::info; pub fn main() { tracing_subscriber::fmt::init(); - let target_dir = "/tmp/jolt-guest-targets"; - let mut program = guest::compile_muldiv(target_dir); + let mut program = compile_muldiv(); - let shared_preprocessing = guest::preprocess_shared_muldiv(&mut program).unwrap(); - let prover_preprocessing = guest::preprocess_prover_muldiv(shared_preprocessing.clone()); - let verifier_preprocessing = guest::preprocess_verifier_muldiv( - shared_preprocessing, - prover_preprocessing.generators.to_verifier_setup(), - None, - ); + let prove_start = Instant::now(); + let (output, bundle) = prove_muldiv(&mut program, 12031293, 17, 92) + .expect("modular prove succeeds on muldiv"); + let prove_secs = prove_start.elapsed().as_secs_f64(); - let prove = guest::build_prover_muldiv(program, prover_preprocessing); - let verify = guest::build_verifier_muldiv(verifier_preprocessing); + let verify_start = Instant::now(); + let verify_result = verify_muldiv(&bundle, &mut program); + let verify_secs = verify_start.elapsed().as_secs_f64(); + let valid = verify_result.is_ok(); - let now = Instant::now(); - let (output, proof, program_io) = prove(12031293, 17, 92); - info!("Prover runtime: {} s", now.elapsed().as_secs_f64()); - let is_valid = verify(12031293, 17, 92, output, program_io.panic, proof); + info!("=== muldiv (modular Bolt backend) ==="); + info!("prove time : {prove_secs:.3} s"); + info!("verify time: {verify_secs:.3} s"); + info!("output : {output}"); + info!("valid : {valid}"); - info!("output: {output}"); - info!("valid: {is_valid}"); + if let Err(err) = verify_result { + info!("verify error: {err:?}"); + std::process::exit(1); + } } From ef8f6c0730863719156711e53926037645a0be64 Mon Sep 17 00:00:00 2001 From: Sagar Dhawan Date: Thu, 14 May 2026 14:23:56 -0500 Subject: [PATCH 10/14] fix(bolt,macros): 6 stale assertions post-regen + set_std emission MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two fixes uncovered while investigating libstd guest support on the modular backend: 1. **6 stale numeric assertions in `bolt::commitment_ir`** — fallout from the fixture bump (18, 14, 14). Numeric assertion updates: - `trace_length = 65536` → `262144` (log_t 16 → 18) - `num_committed = 41` → `42` (bytecode_d 3 → 4 lifts the count) - `round_offset = 16` → `14` (stage2 RAM) - `round_schedule = [128, 16]` → `[128, 18]` (stage5) - `round_schedule = [10, 16]` → `[14, 18]` (stage6 bytecode read raf) - `point_zeros.len() = 1` → `2` (stage6) - `point_concats` formula extended `+ 1` (stage6) Schema rejection message also updated for num_committed = 42. Also restored an `AdditivelyHomomorphic` import in `crates/jolt-prover/src/prover.rs` that I had pruned manually after the regen — but the regen test compares verbatim source against what bolt-emit produces, so manual edits break the check. Leaving the import (with the cargo unused-import warning) is the right choice until bolt-emit gains conditional emission. 2. **Macro `set_std` emission on the modular backend** — bug found trying to flip stdlib's `int_to_string` to `backend = "modular"`. The legacy `compile_` emits `program.set_std(true)` when the guest crate enables `guest-std`; this routes the build through `riscv64imac-zero-linux-musl` instead of `*-unknown-none-elf`. My `make_modular_compile_func` was missing those `set_std` / `set_backtrace` / `set_profile` calls, so libstd-using guests built for the wrong target (downstream crossbeam-utils, serde_core etc. failing because std types aren't available on `none-elf`). With this fix, libstd guests build correctly. Stdlib still can't actually prove on the current `(18, 14, 14)` fixture because `int_to_string` produces a 2^18-instruction bytecode + 2^18 RAM footprint after compilation (std runtime is heavy) — that needs a `(18, 18, 18)` fixture, tracked as separate goldens-bump work. --- crates/bolt/tests/commitment_ir.rs | 16 ++++++++-------- jolt-sdk/macros/src/lib.rs | 10 ++++++++++ 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/crates/bolt/tests/commitment_ir.rs b/crates/bolt/tests/commitment_ir.rs index 64c31d4016..f4073cb052 100644 --- a/crates/bolt/tests/commitment_ir.rs +++ b/crates/bolt/tests/commitment_ir.rs @@ -66,8 +66,8 @@ fn commitment_protocol_uses_bolt_semantic_dialects() { assert!(text.contains("\"protocol.params\"()")); assert!(text.contains("sym_name = \"jolt.params\"")); - assert!(text.contains("trace_length = 65536")); - assert!(text.contains("num_committed = 41")); + assert!(text.contains("trace_length = 262144")); + assert!(text.contains("num_committed = 42")); assert!(text.contains("\"field.define\"()")); assert!(text.contains("sym_name = \"bn254_fr\"")); assert!(text.contains("\"poly.domain\"()")); @@ -283,7 +283,7 @@ fn protocol_schema_rejects_bad_derived_params() { .expect("append family"); let error = verify_jolt_protocol_schema(&bad).expect_err("bad derived param rejected"); - assert!(error.to_string().contains("num_committed must be 41")); + assert!(error.to_string().contains("num_committed must be 42")); } #[test] @@ -474,7 +474,7 @@ fn jolt_stage2_protocol_defines_product_ram_claim_flow() { assert!(text.contains("\"poly.lagrange_basis_eval\"(%")); assert!(text.contains("sym_name = \"stage2.ram_read_write.claim_expr\"")); assert!(text.contains("\"piop.sumcheck_instance_result\"(%")); - assert!(text.contains("round_offset = 16 : i64")); + assert!(text.contains("round_offset = 14 : i64")); assert!(text.contains("\"poly.point_slice\"(%")); assert!(text.contains("\"poly.point_concat\"(%")); assert!(text.contains( @@ -808,7 +808,7 @@ fn jolt_stage5_protocol_defines_value_lookup_reduction_flow() { assert!(text.contains("sym_name = \"stage5.instruction_read_raf.gamma\"")); assert!(text.contains("sym_name = \"stage5.ram_ra_claim_reduction.gamma\"")); assert!(text.contains("sym_name = \"stage5.instruction.lookup_output_claim_consistency\"")); - assert!(text.contains("round_schedule = [128, 16]")); + assert!(text.contains("round_schedule = [128, 18]")); assert!(text.contains("ordered_claims = [@stage5.instruction_read_raf.input, @stage5.ram_ra_claim_reduction.input, @stage5.registers_val_evaluation.input]")); assert!(text.contains("@stage5.instruction_read_raf.opening.LookupTableFlag_0")); assert!(text.contains("@stage5.instruction_read_raf.opening.InstructionRa_0")); @@ -899,7 +899,7 @@ fn jolt_stage6_protocol_defines_bytecode_booleanity_and_virtualization_flow() { assert!(text.contains("source_claim = @stage2.ram_read_write.opening.RamInc")); assert!(text.contains("source_claim = @stage4.registers_read_write.opening.RdInc")); assert!(text.contains("source_claim = @stage5.registers_val_evaluation.opening.RdInc")); - assert!(text.contains("round_schedule = [10, 16]")); + assert!(text.contains("round_schedule = [14, 18]")); assert!(text.contains("ordered_claims = [@stage6.bytecode_read_raf.input, @stage6.booleanity.input, @stage6.hamming_booleanity.input, @stage6.ram_ra_virtual.input, @stage6.instruction_ra_virtual.input, @stage6.inc_claim_reduction.input]")); assert!(text.contains("@stage6.bytecode_read_raf.opening.BytecodeRa_0")); assert!(text.contains("@stage6.booleanity.opening.InstructionRa_0")); @@ -1471,14 +1471,14 @@ fn stage6_rust_targets_extract_and_compile() { + params.instruction_d + 2 ); - assert_eq!(prover_program.point_zeros.len(), 1); + assert_eq!(prover_program.point_zeros.len(), 2); assert_eq!( prover_program.point_slices.len(), params.bytecode_d + 1 + params.ram_d + params.instruction_d ); assert_eq!( prover_program.point_concats.len(), - params.bytecode_d + 1 + params.ram_d + params.instruction_d + params.bytecode_d + 1 + params.ram_d + params.instruction_d + 1 ); assert_eq!( prover_program.opening_claims.len(), diff --git a/jolt-sdk/macros/src/lib.rs b/jolt-sdk/macros/src/lib.rs index a34f074066..a1376203c3 100644 --- a/jolt-sdk/macros/src/lib.rs +++ b/jolt-sdk/macros/src/lib.rs @@ -1045,6 +1045,13 @@ impl MacroBuilder { let max_output_size = proc_macro2::Literal::u64_unsuffixed(attributes.max_output_size); let max_untrusted_advice_size = proc_macro2::Literal::u64_unsuffixed(attributes.max_untrusted_advice_size); + // Guests that depend on std (via the `guest-std` feature on jolt-sdk) + // must build for `riscv64imac-zero-linux-musl` rather than the default + // `*-unknown-none-elf` target. `self.std` reflects the macro's + // `guest-std` cfg detection (see MacroBuilder::new). + let set_std = self.make_set_std(); + let set_backtrace = self.make_set_backtrace(); + let set_profile = self.make_set_profile(); quote! { #[cfg(all(not(target_arch = "wasm32"), not(feature = "guest")))] @@ -1057,6 +1064,9 @@ impl MacroBuilder { .set_max_input_size(#max_input_size) .set_max_output_size(#max_output_size) .set_max_untrusted_advice_size(#max_untrusted_advice_size); + #set_std + #set_profile + #set_backtrace program } } From 8f3fd98d932cb6bdda4ae719c836f337bdc61f92 Mon Sep 17 00:00:00 2001 From: Sagar Dhawan Date: Thu, 14 May 2026 15:06:09 -0500 Subject: [PATCH 11/14] docs: trim verbose / stale comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `JoltProtocolParams::fixture()` — single-line comment naming the kernel ceiling (degree_bound > 5 unsupported), drops the longer example-coverage prose. - `jolt-host` fixture constants — drop the multi-line "Matches bolt's fixture() / Kept in sync with macro guard" preamble; the in-source call-site assertion in the macro guard is the actual source of truth. - `prove_program` doc — drops stale (16, 10, 16) reference; use `FIXTURE_LOG_T` etc. as the constant names rather than spelling out values that drift. - `ProveProgramError::UnsupportedShape` doc — same. - `assemble_and_prove` — remove `Phase 3:` / `Phase 5:` section separators and the 6a..6j step labels; the per-stage helper call names already describe what each block does. - Phase 4 PCS-setup math comment — drops stale `log_t + log_k_chunk = 16 + 4 = 20` (it's 22 at the current fixture, but the value isn't what matters; the formula `params.log_t + params.log_k_chunk` is self-explanatory). No behavior change. --- crates/bolt/src/protocols/jolt/params.rs | 6 +-- crates/jolt-host/src/lib.rs | 47 +++++++----------------- 2 files changed, 16 insertions(+), 37 deletions(-) diff --git a/crates/bolt/src/protocols/jolt/params.rs b/crates/bolt/src/protocols/jolt/params.rs index 3153fb413a..595f42d8c7 100644 --- a/crates/bolt/src/protocols/jolt/params.rs +++ b/crates/bolt/src/protocols/jolt/params.rs @@ -74,9 +74,9 @@ impl JoltProtocolParams { } pub fn fixture() -> Self { - // Sized to cover the example guests in `examples/` (max_trace_length - // up to 2^18, bytecode up to 2^14 instructions, RAM up to 2^14 words). - // Smaller guests pad up to this shape via `jolt_host::prove_program`. + // Max shape supported by current jolt-kernels Stage 6 RA-virtual + // sumcheck (`degree_bound > 5` is hardcoded unsupported, so ram_d + // and bytecode_d are capped at 4 under log_k_chunk = 4). Self::new(18, 14, 14) } diff --git a/crates/jolt-host/src/lib.rs b/crates/jolt-host/src/lib.rs index dc3d903e51..10497ce305 100644 --- a/crates/jolt-host/src/lib.rs +++ b/crates/jolt-host/src/lib.rs @@ -69,12 +69,7 @@ fn instruction_lookup_table_index(instr: &Instruction) -> Option { /// `TRANSCRIPT_LABEL`). pub const TRANSCRIPT_LABEL: &[u8] = b"Jolt"; -/// The single goldens-baked shape supported by `prove_program` today. -/// Matches `bolt::protocols::jolt::JoltProtocolParams::fixture()`. -/// Guests with naturally larger traces fail with -/// [`ProveProgramError::UnsupportedShape`]. Kept in sync with the -/// `MAX_MODULAR_TRACE_LENGTH` cap in the -/// `#[jolt::provable(backend = "modular")]` macro guard. +/// Goldens-baked shape. Must equal `JoltProtocolParams::fixture()` in bolt. pub const FIXTURE_LOG_T: usize = 18; pub const FIXTURE_LOG_K_BYTECODE: usize = 14; pub const FIXTURE_LOG_K_RAM: usize = 14; @@ -88,9 +83,7 @@ pub enum ProveProgramError { Openings(jolt_prover::prover::JoltOpeningInputError), /// The supplied guest program produced a trace shape (log_t, /// log_k_bytecode, log_k_ram) that doesn't match the goldens-baked - /// fixture. v1 of `prove_program` only supports the fixture shape - /// (log_t=16, log_k_bytecode=10, log_k_ram=16). Larger guests require - /// regenerated goldens. + /// fixture. Larger guests require regenerated goldens. UnsupportedShape { log_t: usize, log_k_bytecode: usize, @@ -232,17 +225,15 @@ impl ModularJoltParams { /// Top-level entry: build a Jolt proof from a guest program + inputs by /// driving the modular Bolt-based prover end-to-end. /// -/// # Constraints (v1) -/// - Requires the guest's padded trace, bytecode size, and RAM size to -/// match the goldens-baked fixture shape (`log_t=16`, -/// `log_k_bytecode=10`, `log_k_ram=16`). Larger guests need a fresh -/// `JOLT_UPDATE_GOLDENS=1` regen at the right params. -/// - Currently bypasses trusted advice commitments (no -/// `trusted_advice_commitment` argument); only untrusted advice is -/// threaded. +/// # Constraints +/// - Guest's padded trace, bytecode size, and RAM size must match the +/// goldens-baked fixture shape (`FIXTURE_LOG_T` etc). Larger guests +/// need a fresh `JOLT_UPDATE_GOLDENS=1` regen. +/// - Trusted advice commitments are not threaded; only untrusted advice +/// is wired through. /// /// # Returns -/// A [`ProofBundle`] bundle containing the proof and everything +/// A [`ProofBundle`] containing the proof and everything /// [`verify_proof`] needs to run the modular verifier round-trip without /// re-tracing the guest. pub fn prove_program( @@ -298,10 +289,10 @@ struct ResolvedShape { log_k_ram: usize, } -/// Phase 1.5 + 2: pad trace/bytecode/RAM up to the goldens-baked fixture -/// and reject anything that doesn't match exactly. The goldens depend on -/// the d-regime AND the absolute fixture log_t (dory tier-1 streaming -/// buffers are sized at the fixture trace length). +/// Pad trace/bytecode/RAM up to the goldens-baked fixture and reject +/// anything that doesn't match. Both the d-regime and the absolute +/// fixture log_t are baked in (dory tier-1 streaming sizes its buffers +/// at the fixture trace length). fn check_shape( trace: &[tracer::instruction::Cycle], io_device: &JoltDevice, @@ -379,7 +370,6 @@ fn assemble_and_prove( ) -> Result { let memory_layout = io_device.memory_layout.clone(); - // ----- Phase 3: trace-derived data (class A) ----- let r1cs_key = R1csKey::new(rv64::rv64_constraints::(), trace_length); let (cycle_inputs, r1cs_witness, _instruction_flags) = extract_trace::<_, Fr>( trace, @@ -414,11 +404,8 @@ fn assemble_and_prove( let (initial_ram_state, final_ram_state) = build_ram_states(init_mem, final_memory, io_device, ram_k); - // ----- Phase 4: PCS setup ----- - // log_t + log_k_chunk = 16 + 4 = 20 for the fixture shape. let pcs_setup = DoryScheme::setup_prover(params.log_t + params.log_k_chunk); - // ----- Phase 5: stage chain (mirrors bolt_oracle.rs:146-700) ----- let programs = default_prover_programs(); let mut transcript = Blake2bTranscript::::new(TRANSCRIPT_LABEL); append_bolt_preamble( @@ -426,7 +413,6 @@ fn assemble_and_prove( &io_event_data_for_preamble(io_device, params, entry_address), ); - // 6a. Commitment phase let commitment_sources = jolt_witness::commitment_trace_sources(&cycle_inputs); let oracle_inputs = jolt_prover::stages::commitment::CommitmentOracleInputs::from_trace_sources( &commitment_sources, @@ -444,7 +430,6 @@ fn assemble_and_prove( ) .map_err(JoltProveError::Commitment)?; - // 6b. Stage 1 (Spartan outer) let stage1_data = Stage1OuterRv64Data::new(&r1cs_key, &r1cs_witness, &rv64_cycles) .map_err(JoltProveError::Stage1Outer)?; let stage1_artifacts = jolt_prover::prove_stage1_outer_with_witness_inputs( @@ -455,7 +440,6 @@ fn assemble_and_prove( ) .map_err(JoltProveError::Stage1Outer)?; - // 6c. Stage 2 (product virtual + lookup + RAM) let ram_output_layout = Stage2RamOutputLayout { io_start: ((memory_layout.input_start - lowest_addr) / 8) as usize, io_end: ((RAM_START_ADDRESS - lowest_addr) / 8) as usize, @@ -480,7 +464,6 @@ fn assemble_and_prove( ) .map_err(JoltProveError::Stage2)?; - // 6d-f. Stages 3, 4, 5 via the canonical regen'd wrappers. let stage3_openings = jolt_prover::stage3_opening_inputs_from_artifacts( programs.stage3, &stage1_artifacts, @@ -533,7 +516,6 @@ fn assemble_and_prove( ) .map_err(JoltProveError::Stage5)?; - // 6g. Stage 6 (bytecode read-RAF, instruction RA, booleanity, etc.) let stage6_openings = jolt_prover::stage6_opening_inputs_from_artifacts( programs.stage6, &stage1_artifacts, @@ -561,7 +543,6 @@ fn assemble_and_prove( ) .map_err(JoltProveError::Stage6)?; - // 6h. Stage 7 (Hamming weight, claim reductions) let stage7_openings = jolt_prover::stage7_opening_inputs_from_stage6_artifacts_with_program( programs.stage7, &stage6_artifacts, @@ -576,7 +557,6 @@ fn assemble_and_prove( ) .map_err(JoltProveError::Stage7)?; - // 6i. Stage 8 (evaluation / opening proof) let evaluation = jolt_prover::prove_jolt_evaluation_proof( programs.stage8, &mut commitment_inputs, @@ -589,7 +569,6 @@ fn assemble_and_prove( ) .map_err(JoltProveError::Evaluation)?; - // 6j. Assemble proof let stage5_proof = jolt_prover::stage5_proof(&stage5_artifacts); let stage6_proof = jolt_prover::stage6_proof(&stage6_artifacts); let stage7_proof = jolt_prover::stage7_proof(&stage7_artifacts); From 37adc54621e9d416ecd7bc2e3d442ffb957dad98 Mon Sep 17 00:00:00 2001 From: Sagar Dhawan Date: Fri, 15 May 2026 11:35:38 -0500 Subject: [PATCH 12/14] regen(prover,verifier): regenerate goldens at fixture (18, 14, 14) Output of `JOLT_UPDATE_GOLDENS=1 cargo nextest run -p bolt --test commitment_ir generated_jolt_artifacts_have_uniform_crate_layout_and_import_rules` against jolt-v2/equivalence base (bolt at 68adcb91b) with the bumped fixture from the previous commit. --- crates/jolt-prover/src/prover.rs | 1 + crates/jolt-prover/src/stages/commitment.rs | 183 +++-- crates/jolt-prover/src/stages/stage1_outer.rs | 82 +- crates/jolt-prover/src/stages/stage2.rs | 80 +- crates/jolt-prover/src/stages/stage3.rs | 74 +- crates/jolt-prover/src/stages/stage4.rs | 44 +- crates/jolt-prover/src/stages/stage5.rs | 152 ++-- crates/jolt-prover/src/stages/stage6.rs | 598 +++++++------- crates/jolt-prover/src/stages/stage7.rs | 774 ++++++++++-------- crates/jolt-prover/src/stages/stage8.rs | 174 ++-- crates/jolt-verifier/src/lib.rs | 4 +- crates/jolt-verifier/src/stages/commitment.rs | 94 +-- .../jolt-verifier/src/stages/stage1_outer.rs | 82 +- crates/jolt-verifier/src/stages/stage2.rs | 80 +- crates/jolt-verifier/src/stages/stage3.rs | 75 +- crates/jolt-verifier/src/stages/stage4.rs | 45 +- crates/jolt-verifier/src/stages/stage5.rs | 153 ++-- crates/jolt-verifier/src/stages/stage6.rs | 616 +++++++------- crates/jolt-verifier/src/stages/stage7.rs | 288 +++---- crates/jolt-verifier/src/stages/stage8.rs | 174 ++-- crates/jolt-verifier/src/verifier.rs | 1 + 21 files changed, 1934 insertions(+), 1840 deletions(-) diff --git a/crates/jolt-prover/src/prover.rs b/crates/jolt-prover/src/prover.rs index acd8c0475d..6a5b0bcec6 100644 --- a/crates/jolt-prover/src/prover.rs +++ b/crates/jolt-prover/src/prover.rs @@ -2088,3 +2088,4 @@ fn stage7_eval(eval: &stage7::Stage7NamedEval) -> JoltNamedEval { value: eval.value, } } + diff --git a/crates/jolt-prover/src/stages/commitment.rs b/crates/jolt-prover/src/stages/commitment.rs index 7378d2bd39..fb8961cc33 100644 --- a/crates/jolt-prover/src/stages/commitment.rs +++ b/crates/jolt-prover/src/stages/commitment.rs @@ -642,6 +642,7 @@ pub struct CommitmentOracles { pub bytecode_ra_0: Vec, pub bytecode_ra_1: Vec, pub bytecode_ra_2: Vec, + pub bytecode_ra_3: Vec, pub untrusted_advice: Option>, pub trusted_advice: Option>, } @@ -690,6 +691,7 @@ impl CommitmentInputProvider for CommitmentOracles { "BytecodeRa_0" => Some(Cow::Borrowed(&self.bytecode_ra_0)), "BytecodeRa_1" => Some(Cow::Borrowed(&self.bytecode_ra_1)), "BytecodeRa_2" => Some(Cow::Borrowed(&self.bytecode_ra_2)), + "BytecodeRa_3" => Some(Cow::Borrowed(&self.bytecode_ra_3)), "UntrustedAdvice" => self.untrusted_advice.as_deref().map(Cow::Borrowed), "TrustedAdvice" => self.trusted_advice.as_deref().map(Cow::Borrowed), _ => None, @@ -701,49 +703,50 @@ pub fn build_commitment_oracles( inputs: &CommitmentOracleInputs<'_>, ) -> Result { Ok(CommitmentOracles { - rd_inc: dense_i128_column_to_field(inputs.rd_inc, target_len(16)?), - ram_inc: dense_i128_column_to_field(inputs.ram_inc, target_len(16)?), - instruction_ra_0: one_hot_chunk_address_major(inputs.instruction_keys, 0, 32, 4, target_len(16)?, Some(0)), - instruction_ra_1: one_hot_chunk_address_major(inputs.instruction_keys, 1, 32, 4, target_len(16)?, Some(0)), - instruction_ra_2: one_hot_chunk_address_major(inputs.instruction_keys, 2, 32, 4, target_len(16)?, Some(0)), - instruction_ra_3: one_hot_chunk_address_major(inputs.instruction_keys, 3, 32, 4, target_len(16)?, Some(0)), - instruction_ra_4: one_hot_chunk_address_major(inputs.instruction_keys, 4, 32, 4, target_len(16)?, Some(0)), - instruction_ra_5: one_hot_chunk_address_major(inputs.instruction_keys, 5, 32, 4, target_len(16)?, Some(0)), - instruction_ra_6: one_hot_chunk_address_major(inputs.instruction_keys, 6, 32, 4, target_len(16)?, Some(0)), - instruction_ra_7: one_hot_chunk_address_major(inputs.instruction_keys, 7, 32, 4, target_len(16)?, Some(0)), - instruction_ra_8: one_hot_chunk_address_major(inputs.instruction_keys, 8, 32, 4, target_len(16)?, Some(0)), - instruction_ra_9: one_hot_chunk_address_major(inputs.instruction_keys, 9, 32, 4, target_len(16)?, Some(0)), - instruction_ra_10: one_hot_chunk_address_major(inputs.instruction_keys, 10, 32, 4, target_len(16)?, Some(0)), - instruction_ra_11: one_hot_chunk_address_major(inputs.instruction_keys, 11, 32, 4, target_len(16)?, Some(0)), - instruction_ra_12: one_hot_chunk_address_major(inputs.instruction_keys, 12, 32, 4, target_len(16)?, Some(0)), - instruction_ra_13: one_hot_chunk_address_major(inputs.instruction_keys, 13, 32, 4, target_len(16)?, Some(0)), - instruction_ra_14: one_hot_chunk_address_major(inputs.instruction_keys, 14, 32, 4, target_len(16)?, Some(0)), - instruction_ra_15: one_hot_chunk_address_major(inputs.instruction_keys, 15, 32, 4, target_len(16)?, Some(0)), - instruction_ra_16: one_hot_chunk_address_major(inputs.instruction_keys, 16, 32, 4, target_len(16)?, Some(0)), - instruction_ra_17: one_hot_chunk_address_major(inputs.instruction_keys, 17, 32, 4, target_len(16)?, Some(0)), - instruction_ra_18: one_hot_chunk_address_major(inputs.instruction_keys, 18, 32, 4, target_len(16)?, Some(0)), - instruction_ra_19: one_hot_chunk_address_major(inputs.instruction_keys, 19, 32, 4, target_len(16)?, Some(0)), - instruction_ra_20: one_hot_chunk_address_major(inputs.instruction_keys, 20, 32, 4, target_len(16)?, Some(0)), - instruction_ra_21: one_hot_chunk_address_major(inputs.instruction_keys, 21, 32, 4, target_len(16)?, Some(0)), - instruction_ra_22: one_hot_chunk_address_major(inputs.instruction_keys, 22, 32, 4, target_len(16)?, Some(0)), - instruction_ra_23: one_hot_chunk_address_major(inputs.instruction_keys, 23, 32, 4, target_len(16)?, Some(0)), - instruction_ra_24: one_hot_chunk_address_major(inputs.instruction_keys, 24, 32, 4, target_len(16)?, Some(0)), - instruction_ra_25: one_hot_chunk_address_major(inputs.instruction_keys, 25, 32, 4, target_len(16)?, Some(0)), - instruction_ra_26: one_hot_chunk_address_major(inputs.instruction_keys, 26, 32, 4, target_len(16)?, Some(0)), - instruction_ra_27: one_hot_chunk_address_major(inputs.instruction_keys, 27, 32, 4, target_len(16)?, Some(0)), - instruction_ra_28: one_hot_chunk_address_major(inputs.instruction_keys, 28, 32, 4, target_len(16)?, Some(0)), - instruction_ra_29: one_hot_chunk_address_major(inputs.instruction_keys, 29, 32, 4, target_len(16)?, Some(0)), - instruction_ra_30: one_hot_chunk_address_major(inputs.instruction_keys, 30, 32, 4, target_len(16)?, Some(0)), - instruction_ra_31: one_hot_chunk_address_major(inputs.instruction_keys, 31, 32, 4, target_len(16)?, Some(0)), - ram_ra_0: one_hot_chunk_address_major(inputs.ram_addresses, 0, 4, 4, target_len(16)?, None), - ram_ra_1: one_hot_chunk_address_major(inputs.ram_addresses, 1, 4, 4, target_len(16)?, None), - ram_ra_2: one_hot_chunk_address_major(inputs.ram_addresses, 2, 4, 4, target_len(16)?, None), - ram_ra_3: one_hot_chunk_address_major(inputs.ram_addresses, 3, 4, 4, target_len(16)?, None), - bytecode_ra_0: one_hot_chunk_address_major(inputs.bytecode_indices, 0, 3, 4, target_len(16)?, Some(0)), - bytecode_ra_1: one_hot_chunk_address_major(inputs.bytecode_indices, 1, 3, 4, target_len(16)?, Some(0)), - bytecode_ra_2: one_hot_chunk_address_major(inputs.bytecode_indices, 2, 3, 4, target_len(16)?, Some(0)), - untrusted_advice: optional_field_oracle(inputs.untrusted_advice, target_len(16)?), - trusted_advice: optional_field_oracle(inputs.trusted_advice, target_len(16)?), + rd_inc: dense_i128_column_to_field(inputs.rd_inc, target_len(18)?), + ram_inc: dense_i128_column_to_field(inputs.ram_inc, target_len(18)?), + instruction_ra_0: one_hot_chunk_address_major(inputs.instruction_keys, 0, 32, 4, target_len(18)?, Some(0)), + instruction_ra_1: one_hot_chunk_address_major(inputs.instruction_keys, 1, 32, 4, target_len(18)?, Some(0)), + instruction_ra_2: one_hot_chunk_address_major(inputs.instruction_keys, 2, 32, 4, target_len(18)?, Some(0)), + instruction_ra_3: one_hot_chunk_address_major(inputs.instruction_keys, 3, 32, 4, target_len(18)?, Some(0)), + instruction_ra_4: one_hot_chunk_address_major(inputs.instruction_keys, 4, 32, 4, target_len(18)?, Some(0)), + instruction_ra_5: one_hot_chunk_address_major(inputs.instruction_keys, 5, 32, 4, target_len(18)?, Some(0)), + instruction_ra_6: one_hot_chunk_address_major(inputs.instruction_keys, 6, 32, 4, target_len(18)?, Some(0)), + instruction_ra_7: one_hot_chunk_address_major(inputs.instruction_keys, 7, 32, 4, target_len(18)?, Some(0)), + instruction_ra_8: one_hot_chunk_address_major(inputs.instruction_keys, 8, 32, 4, target_len(18)?, Some(0)), + instruction_ra_9: one_hot_chunk_address_major(inputs.instruction_keys, 9, 32, 4, target_len(18)?, Some(0)), + instruction_ra_10: one_hot_chunk_address_major(inputs.instruction_keys, 10, 32, 4, target_len(18)?, Some(0)), + instruction_ra_11: one_hot_chunk_address_major(inputs.instruction_keys, 11, 32, 4, target_len(18)?, Some(0)), + instruction_ra_12: one_hot_chunk_address_major(inputs.instruction_keys, 12, 32, 4, target_len(18)?, Some(0)), + instruction_ra_13: one_hot_chunk_address_major(inputs.instruction_keys, 13, 32, 4, target_len(18)?, Some(0)), + instruction_ra_14: one_hot_chunk_address_major(inputs.instruction_keys, 14, 32, 4, target_len(18)?, Some(0)), + instruction_ra_15: one_hot_chunk_address_major(inputs.instruction_keys, 15, 32, 4, target_len(18)?, Some(0)), + instruction_ra_16: one_hot_chunk_address_major(inputs.instruction_keys, 16, 32, 4, target_len(18)?, Some(0)), + instruction_ra_17: one_hot_chunk_address_major(inputs.instruction_keys, 17, 32, 4, target_len(18)?, Some(0)), + instruction_ra_18: one_hot_chunk_address_major(inputs.instruction_keys, 18, 32, 4, target_len(18)?, Some(0)), + instruction_ra_19: one_hot_chunk_address_major(inputs.instruction_keys, 19, 32, 4, target_len(18)?, Some(0)), + instruction_ra_20: one_hot_chunk_address_major(inputs.instruction_keys, 20, 32, 4, target_len(18)?, Some(0)), + instruction_ra_21: one_hot_chunk_address_major(inputs.instruction_keys, 21, 32, 4, target_len(18)?, Some(0)), + instruction_ra_22: one_hot_chunk_address_major(inputs.instruction_keys, 22, 32, 4, target_len(18)?, Some(0)), + instruction_ra_23: one_hot_chunk_address_major(inputs.instruction_keys, 23, 32, 4, target_len(18)?, Some(0)), + instruction_ra_24: one_hot_chunk_address_major(inputs.instruction_keys, 24, 32, 4, target_len(18)?, Some(0)), + instruction_ra_25: one_hot_chunk_address_major(inputs.instruction_keys, 25, 32, 4, target_len(18)?, Some(0)), + instruction_ra_26: one_hot_chunk_address_major(inputs.instruction_keys, 26, 32, 4, target_len(18)?, Some(0)), + instruction_ra_27: one_hot_chunk_address_major(inputs.instruction_keys, 27, 32, 4, target_len(18)?, Some(0)), + instruction_ra_28: one_hot_chunk_address_major(inputs.instruction_keys, 28, 32, 4, target_len(18)?, Some(0)), + instruction_ra_29: one_hot_chunk_address_major(inputs.instruction_keys, 29, 32, 4, target_len(18)?, Some(0)), + instruction_ra_30: one_hot_chunk_address_major(inputs.instruction_keys, 30, 32, 4, target_len(18)?, Some(0)), + instruction_ra_31: one_hot_chunk_address_major(inputs.instruction_keys, 31, 32, 4, target_len(18)?, Some(0)), + ram_ra_0: one_hot_chunk_address_major(inputs.ram_addresses, 0, 4, 4, target_len(18)?, None), + ram_ra_1: one_hot_chunk_address_major(inputs.ram_addresses, 1, 4, 4, target_len(18)?, None), + ram_ra_2: one_hot_chunk_address_major(inputs.ram_addresses, 2, 4, 4, target_len(18)?, None), + ram_ra_3: one_hot_chunk_address_major(inputs.ram_addresses, 3, 4, 4, target_len(18)?, None), + bytecode_ra_0: one_hot_chunk_address_major(inputs.bytecode_indices, 0, 4, 4, target_len(18)?, Some(0)), + bytecode_ra_1: one_hot_chunk_address_major(inputs.bytecode_indices, 1, 4, 4, target_len(18)?, Some(0)), + bytecode_ra_2: one_hot_chunk_address_major(inputs.bytecode_indices, 2, 4, 4, target_len(18)?, Some(0)), + bytecode_ra_3: one_hot_chunk_address_major(inputs.bytecode_indices, 3, 4, 4, target_len(18)?, Some(0)), + untrusted_advice: optional_field_oracle(inputs.untrusted_advice, target_len(18)?), + trusted_advice: optional_field_oracle(inputs.trusted_advice, target_len(18)?), }) } @@ -753,49 +756,50 @@ pub const COMMITMENT_PARAMS: CommitmentParams = CommitmentParams { transcript: "blake2b_transcript", }; pub const ORACLE_PLANS: &[OraclePlan] = &[ - OraclePlan { oracle: "RdInc", domain: "jolt.trace_domain", num_vars: 16 }, - OraclePlan { oracle: "RamInc", domain: "jolt.trace_domain", num_vars: 16 }, - OraclePlan { oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "UntrustedAdvice", domain: "jolt.trace_domain", num_vars: 16 }, - OraclePlan { oracle: "TrustedAdvice", domain: "jolt.trace_domain", num_vars: 16 }, + OraclePlan { oracle: "RdInc", domain: "jolt.trace_domain", num_vars: 18 }, + OraclePlan { oracle: "RamInc", domain: "jolt.trace_domain", num_vars: 18 }, + OraclePlan { oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "BytecodeRa_3", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "UntrustedAdvice", domain: "jolt.trace_domain", num_vars: 18 }, + OraclePlan { oracle: "TrustedAdvice", domain: "jolt.trace_domain", num_vars: 18 }, ]; pub const COMMITMENT_BATCH_0_ORACLES: &[&str] = &[ "RdInc", @@ -839,13 +843,14 @@ pub const COMMITMENT_BATCH_0_ORACLES: &[&str] = &[ "BytecodeRa_0", "BytecodeRa_1", "BytecodeRa_2", + "BytecodeRa_3", ]; pub const COMMITMENT_BATCH_PLANS: &[CommitmentBatchPlan] = &[ - CommitmentBatchPlan { artifact: "jolt.main_witness_commitments", pcs: "dory", oracle_family: "jolt.main_witness_polys", label: "commitment", oracles: COMMITMENT_BATCH_0_ORACLES, count: 41, domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + CommitmentBatchPlan { artifact: "jolt.main_witness_commitments", pcs: "dory", oracle_family: "jolt.main_witness_polys", label: "commitment", oracles: COMMITMENT_BATCH_0_ORACLES, count: 42, domain: "jolt.main_witness_commit_domain", num_vars: 22 }, ]; pub const OPTIONAL_COMMITMENT_PLANS: &[OptionalCommitmentPlan] = &[ - OptionalCommitmentPlan { artifact: "jolt.untrusted_advice_commitment", pcs: "dory", oracle: "UntrustedAdvice", label: "untrusted_advice", domain: "jolt.trace_domain", num_vars: 16, skip_policy: OptionalSkipPolicy::MissingOrZero }, - OptionalCommitmentPlan { artifact: "jolt.trusted_advice_commitment", pcs: "dory", oracle: "TrustedAdvice", label: "trusted_advice", domain: "jolt.trace_domain", num_vars: 16, skip_policy: OptionalSkipPolicy::MissingOrZero }, + OptionalCommitmentPlan { artifact: "jolt.untrusted_advice_commitment", pcs: "dory", oracle: "UntrustedAdvice", label: "untrusted_advice", domain: "jolt.trace_domain", num_vars: 18, skip_policy: OptionalSkipPolicy::MissingOrZero }, + OptionalCommitmentPlan { artifact: "jolt.trusted_advice_commitment", pcs: "dory", oracle: "TrustedAdvice", label: "trusted_advice", domain: "jolt.trace_domain", num_vars: 18, skip_policy: OptionalSkipPolicy::MissingOrZero }, ]; pub const TRANSCRIPT_PLAN: &[TranscriptStep] = &[ TranscriptStep { label: "commitment", source: "jolt.main_witness_commitments", optional: false }, diff --git a/crates/jolt-prover/src/stages/stage1_outer.rs b/crates/jolt-prover/src/stages/stage1_outer.rs index e31d49a81e..6117af09dd 100644 --- a/crates/jolt-prover/src/stages/stage1_outer.rs +++ b/crates/jolt-prover/src/stages/stage1_outer.rs @@ -12,7 +12,7 @@ pub const STAGE1_PARAMS: Stage1Params = Stage1Params { transcript: "blake2b_transcript", }; pub const STAGE1_TRANSCRIPT_SQUEEZES: &[Stage1TranscriptSqueezePlan] = &[ - Stage1TranscriptSqueezePlan { symbol: "stage1.tau", label: "outer_tau", kind: "challenge_vector", count: 18 }, + Stage1TranscriptSqueezePlan { symbol: "stage1.tau", label: "outer_tau", kind: "challenge_vector", count: 20 }, ]; pub const STAGE1_KERNELS: &[Stage1KernelPlan] = &[ @@ -26,7 +26,7 @@ pub const STAGE1_SUMCHECK_CLAIM_1_INPUT_OPENINGS: &[&str] = &["stage1.uniskip.op pub const STAGE1_SUMCHECK_CLAIMS: &[Stage1SumcheckClaimPlan] = &[ Stage1SumcheckClaimPlan { symbol: "stage1.uniskip.input", stage: "stage1", domain: "jolt.stage1_uniskip_domain", num_rounds: 1, degree: 27, claim: "stage1.zero", kernel: Some("jolt.cpu.stage1.outer.uniskip"), relation: None, claim_value: "stage1.zero", input_openings: STAGE1_SUMCHECK_CLAIM_0_INPUT_OPENINGS }, - Stage1SumcheckClaimPlan { symbol: "stage1.outer_remaining.input", stage: "stage1", domain: "jolt.trace_domain", num_rounds: 17, degree: 3, claim: "stage1.uniskip.eval", kernel: Some("jolt.cpu.stage1.outer.remaining"), relation: None, claim_value: "stage1.uniskip.eval", input_openings: STAGE1_SUMCHECK_CLAIM_1_INPUT_OPENINGS }, + Stage1SumcheckClaimPlan { symbol: "stage1.outer_remaining.input", stage: "stage1", domain: "jolt.trace_domain", num_rounds: 19, degree: 3, claim: "stage1.uniskip.eval", kernel: Some("jolt.cpu.stage1.outer.remaining"), relation: None, claim_value: "stage1.uniskip.eval", input_openings: STAGE1_SUMCHECK_CLAIM_1_INPUT_OPENINGS }, ]; pub const STAGE1_SUMCHECK_BATCH_0_ORDERED_CLAIMS: &[&str] = &["stage1.uniskip.input"]; @@ -41,7 +41,7 @@ pub const STAGE1_SUMCHECK_BATCH_1_ORDERED_CLAIMS: &[&str] = &["stage1.outer_rema pub const STAGE1_SUMCHECK_BATCH_1_CLAIM_OPERANDS: &[&str] = &["stage1.outer_remaining.input"]; pub const STAGE1_SUMCHECK_BATCH_1_ROUND_SCHEDULE: &[usize] = &[ - 17, + 19, ]; pub const STAGE1_SUMCHECK_BATCHES: &[Stage1SumcheckBatchPlan] = &[ @@ -53,16 +53,16 @@ pub const STAGE1_SUMCHECK_DRIVER_0_ROUND_SCHEDULE: &[usize] = &[ ]; pub const STAGE1_SUMCHECK_DRIVER_1_ROUND_SCHEDULE: &[usize] = &[ - 17, + 19, ]; pub const STAGE1_SUMCHECK_DRIVERS: &[Stage1SumcheckDriverPlan] = &[ Stage1SumcheckDriverPlan { symbol: "stage1.uniskip.sumcheck", stage: "stage1", proof_slot: "stage1.uni_skip_first_round", kernel: Some("jolt.cpu.stage1.outer.uniskip"), relation: None, batch: "stage1.uniskip.batch", policy: "univariate_skip", round_schedule: STAGE1_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "uniskip_claim", round_label: "uniskip_poly", num_rounds: 1, degree: 27 }, - Stage1SumcheckDriverPlan { symbol: "stage1.outer_remaining.sumcheck", stage: "stage1", proof_slot: "stage1.sumcheck", kernel: Some("jolt.cpu.stage1.outer.remaining"), relation: None, batch: "stage1.outer_remaining.batch", policy: "jolt_core_front_loaded", round_schedule: STAGE1_SUMCHECK_DRIVER_1_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 17, degree: 3 }, + Stage1SumcheckDriverPlan { symbol: "stage1.outer_remaining.sumcheck", stage: "stage1", proof_slot: "stage1.sumcheck", kernel: Some("jolt.cpu.stage1.outer.remaining"), relation: None, batch: "stage1.outer_remaining.batch", policy: "jolt_core_front_loaded", round_schedule: STAGE1_SUMCHECK_DRIVER_1_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 19, degree: 3 }, ]; pub const STAGE1_SUMCHECK_INSTANCE_RESULTS: &[Stage1SumcheckInstanceResultPlan] = &[ Stage1SumcheckInstanceResultPlan { symbol: "stage1.uniskip.instance", source: "stage1.uniskip.sumcheck", claim: "stage1.uniskip.input", relation: "jolt.stage1.outer.uniskip", index: 0, point_arity: 1, num_rounds: 1, round_offset: 0, point_order: "as_is", degree: 27 }, - Stage1SumcheckInstanceResultPlan { symbol: "stage1.outer_remaining.instance", source: "stage1.outer_remaining.sumcheck", claim: "stage1.outer_remaining.input", relation: "jolt.stage1.outer.remaining", index: 0, point_arity: 16, num_rounds: 17, round_offset: 1, point_order: "reverse", degree: 3 }, + Stage1SumcheckInstanceResultPlan { symbol: "stage1.outer_remaining.instance", source: "stage1.outer_remaining.sumcheck", claim: "stage1.outer_remaining.input", relation: "jolt.stage1.outer.remaining", index: 0, point_arity: 18, num_rounds: 19, round_offset: 1, point_order: "reverse", degree: 3 }, ]; pub const STAGE1_SUMCHECK_EVALS: &[Stage1SumcheckEvalPlan] = &[ @@ -106,41 +106,41 @@ pub const STAGE1_SUMCHECK_EVALS: &[Stage1SumcheckEvalPlan] = &[ pub const STAGE1_OPENING_CLAIMS: &[Stage1OpeningClaimPlan] = &[ Stage1OpeningClaimPlan { symbol: "stage1.uniskip.opening", oracle: "UnivariateSkip", domain: "jolt.stage1_uniskip_domain", point_arity: 1, claim_kind: "virtual", point_source: "stage1.uniskip.instance", eval_source: "stage1.uniskip.eval" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.LeftInstructionInput" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RightInstructionInput" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.Product", oracle: "Product", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.Product" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.ShouldBranch", oracle: "ShouldBranch", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.ShouldBranch" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.PC", oracle: "PC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.PC" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.UnexpandedPC", oracle: "UnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.UnexpandedPC" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.Imm", oracle: "Imm", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.Imm" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RamAddress", oracle: "RamAddress", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RamAddress" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.Rs1Value" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.Rs2Value" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RdWriteValue", oracle: "RdWriteValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RdWriteValue" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RamReadValue", oracle: "RamReadValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RamReadValue" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RamWriteValue", oracle: "RamWriteValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RamWriteValue" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.LeftLookupOperand", oracle: "LeftLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.LeftLookupOperand" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RightLookupOperand", oracle: "RightLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RightLookupOperand" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.NextUnexpandedPC", oracle: "NextUnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.NextUnexpandedPC" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.NextPC", oracle: "NextPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.NextPC" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.NextIsVirtual", oracle: "NextIsVirtual", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.NextIsVirtual" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.NextIsFirstInSequence", oracle: "NextIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.NextIsFirstInSequence" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.LookupOutput" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.ShouldJump", oracle: "ShouldJump", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.ShouldJump" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagAddOperands", oracle: "OpFlagAddOperands", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagAddOperands" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagSubtractOperands", oracle: "OpFlagSubtractOperands", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagSubtractOperands" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagMultiplyOperands", oracle: "OpFlagMultiplyOperands", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagMultiplyOperands" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagLoad", oracle: "OpFlagLoad", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagLoad" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagStore", oracle: "OpFlagStore", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagStore" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagJump", oracle: "OpFlagJump", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagJump" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagWriteLookupOutputToRD", oracle: "OpFlagWriteLookupOutputToRD", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagWriteLookupOutputToRD" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagVirtualInstruction" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagAssert", oracle: "OpFlagAssert", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagAssert" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagDoNotUpdateUnexpandedPC", oracle: "OpFlagDoNotUpdateUnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagDoNotUpdateUnexpandedPC" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagAdvice", oracle: "OpFlagAdvice", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagAdvice" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagIsCompressed", oracle: "OpFlagIsCompressed", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagIsCompressed" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagIsFirstInSequence", oracle: "OpFlagIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagIsFirstInSequence" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagIsLastInSequence", oracle: "OpFlagIsLastInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagIsLastInSequence" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.LeftInstructionInput" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RightInstructionInput" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.Product", oracle: "Product", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.Product" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.ShouldBranch", oracle: "ShouldBranch", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.ShouldBranch" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.PC", oracle: "PC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.PC" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.UnexpandedPC", oracle: "UnexpandedPC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.UnexpandedPC" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.Imm", oracle: "Imm", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.Imm" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RamAddress", oracle: "RamAddress", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RamAddress" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.Rs1Value" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.Rs2Value" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RdWriteValue", oracle: "RdWriteValue", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RdWriteValue" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RamReadValue", oracle: "RamReadValue", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RamReadValue" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RamWriteValue", oracle: "RamWriteValue", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RamWriteValue" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.LeftLookupOperand", oracle: "LeftLookupOperand", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.LeftLookupOperand" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RightLookupOperand", oracle: "RightLookupOperand", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RightLookupOperand" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.NextUnexpandedPC", oracle: "NextUnexpandedPC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.NextUnexpandedPC" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.NextPC", oracle: "NextPC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.NextPC" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.NextIsVirtual", oracle: "NextIsVirtual", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.NextIsVirtual" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.NextIsFirstInSequence", oracle: "NextIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.NextIsFirstInSequence" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.LookupOutput" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.ShouldJump", oracle: "ShouldJump", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.ShouldJump" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagAddOperands", oracle: "OpFlagAddOperands", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagAddOperands" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagSubtractOperands", oracle: "OpFlagSubtractOperands", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagSubtractOperands" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagMultiplyOperands", oracle: "OpFlagMultiplyOperands", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagMultiplyOperands" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagLoad", oracle: "OpFlagLoad", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagLoad" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagStore", oracle: "OpFlagStore", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagStore" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagJump", oracle: "OpFlagJump", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagJump" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagWriteLookupOutputToRD", oracle: "OpFlagWriteLookupOutputToRD", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagWriteLookupOutputToRD" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagVirtualInstruction" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagAssert", oracle: "OpFlagAssert", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagAssert" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagDoNotUpdateUnexpandedPC", oracle: "OpFlagDoNotUpdateUnexpandedPC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagDoNotUpdateUnexpandedPC" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagAdvice", oracle: "OpFlagAdvice", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagAdvice" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagIsCompressed", oracle: "OpFlagIsCompressed", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagIsCompressed" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagIsFirstInSequence", oracle: "OpFlagIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagIsFirstInSequence" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagIsLastInSequence", oracle: "OpFlagIsLastInSequence", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagIsLastInSequence" }, ]; pub const STAGE1_OPENING_BATCH_0_ORDERED_CLAIMS: &[&str] = &[ diff --git a/crates/jolt-prover/src/stages/stage2.rs b/crates/jolt-prover/src/stages/stage2.rs index ece68d1c0b..c71c070f18 100644 --- a/crates/jolt-prover/src/stages/stage2.rs +++ b/crates/jolt-prover/src/stages/stage2.rs @@ -24,21 +24,21 @@ pub const STAGE2_TRANSCRIPT_SQUEEZES: &[Stage2TranscriptSqueezePlan] = &[ Stage2TranscriptSqueezePlan { symbol: "stage2.product_virtual.tau_high", label: "product_virtual_tau_high", kind: "challenge_scalar", count: 1 }, Stage2TranscriptSqueezePlan { symbol: "stage2.ram_read_write.gamma", label: "ram_read_write_gamma", kind: "challenge_scalar", count: 1 }, Stage2TranscriptSqueezePlan { symbol: "stage2.instruction_lookup.gamma", label: "instruction_lookup_gamma", kind: "challenge_scalar", count: 1 }, - Stage2TranscriptSqueezePlan { symbol: "stage2.ram_output.r_address", label: "ram_output_r_address", kind: "challenge_vector", count: 16 }, + Stage2TranscriptSqueezePlan { symbol: "stage2.ram_output.r_address", label: "ram_output_r_address", kind: "challenge_vector", count: 14 }, ]; pub const STAGE2_OPENING_INPUTS: &[Stage2OpeningInputPlan] = &[ - Stage2OpeningInputPlan { symbol: "stage2.input.stage1.Product", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.Product", oracle: "Product", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage2OpeningInputPlan { symbol: "stage2.input.stage1.ShouldBranch", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.ShouldBranch", oracle: "ShouldBranch", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage2OpeningInputPlan { symbol: "stage2.input.stage1.ShouldJump", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.ShouldJump", oracle: "ShouldJump", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage2OpeningInputPlan { symbol: "stage2.input.stage1.RamReadValue", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RamReadValue", oracle: "RamReadValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage2OpeningInputPlan { symbol: "stage2.input.stage1.RamWriteValue", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RamWriteValue", oracle: "RamWriteValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage2OpeningInputPlan { symbol: "stage2.input.stage1.LookupOutput", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage2OpeningInputPlan { symbol: "stage2.input.stage1.LeftLookupOperand", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.LeftLookupOperand", oracle: "LeftLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage2OpeningInputPlan { symbol: "stage2.input.stage1.RightLookupOperand", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RightLookupOperand", oracle: "RightLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage2OpeningInputPlan { symbol: "stage2.input.stage1.LeftInstructionInput", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage2OpeningInputPlan { symbol: "stage2.input.stage1.RightInstructionInput", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage2OpeningInputPlan { symbol: "stage2.input.stage1.RamAddress", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RamAddress", oracle: "RamAddress", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.Product", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.Product", oracle: "Product", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.ShouldBranch", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.ShouldBranch", oracle: "ShouldBranch", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.ShouldJump", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.ShouldJump", oracle: "ShouldJump", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.RamReadValue", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RamReadValue", oracle: "RamReadValue", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.RamWriteValue", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RamWriteValue", oracle: "RamWriteValue", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.LookupOutput", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.LeftLookupOperand", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.LeftLookupOperand", oracle: "LeftLookupOperand", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.RightLookupOperand", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RightLookupOperand", oracle: "RightLookupOperand", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.LeftInstructionInput", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.RightInstructionInput", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.RamAddress", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RamAddress", oracle: "RamAddress", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, ]; pub const STAGE2_FIELD_CONSTANTS: &[Stage2FieldConstantPlan] = &[ @@ -198,10 +198,10 @@ pub const STAGE2_SUMCHECK_CLAIM_5_INPUT_OPENINGS: &[&str] = &[]; pub const STAGE2_SUMCHECK_CLAIMS: &[Stage2SumcheckClaimPlan] = &[ Stage2SumcheckClaimPlan { symbol: "stage2.product_virtual.uniskip.input", stage: "stage2", domain: "jolt.stage2_uniskip_domain", num_rounds: 1, degree: 6, claim: "stage2.product_virtual.weighted_stage1_outputs", kernel: Some("jolt.cpu.stage2.product_virtual.uniskip"), relation: None, claim_value: "stage2.product_virtual.uniskip.claim_expr", input_openings: STAGE2_SUMCHECK_CLAIM_0_INPUT_OPENINGS }, Stage2SumcheckClaimPlan { symbol: "stage2.ram_read_write.input", stage: "stage2", domain: "jolt.stage2_ram_rw_domain", num_rounds: 32, degree: 3, claim: "stage2.ram_read_write.weighted_values", kernel: Some("jolt.cpu.stage2.ram.read_write"), relation: None, claim_value: "stage2.ram_read_write.claim_expr", input_openings: STAGE2_SUMCHECK_CLAIM_1_INPUT_OPENINGS }, - Stage2SumcheckClaimPlan { symbol: "stage2.product_virtual.remainder.input", stage: "stage2", domain: "jolt.trace_domain", num_rounds: 16, degree: 3, claim: "stage2.product_virtual.uniskip.opening", kernel: Some("jolt.cpu.stage2.product_virtual.remainder"), relation: None, claim_value: "stage2.product_virtual.uniskip.eval.UnivariateSkip", input_openings: STAGE2_SUMCHECK_CLAIM_2_INPUT_OPENINGS }, - Stage2SumcheckClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.input", stage: "stage2", domain: "jolt.trace_domain", num_rounds: 16, degree: 2, claim: "stage2.instruction_lookup.weighted_operands", kernel: Some("jolt.cpu.stage2.instruction_lookup.claim_reduction"), relation: None, claim_value: "stage2.instruction_lookup.claim_reduction.claim_expr", input_openings: STAGE2_SUMCHECK_CLAIM_3_INPUT_OPENINGS }, - Stage2SumcheckClaimPlan { symbol: "stage2.ram_raf.input", stage: "stage2", domain: "jolt.ram_address_domain", num_rounds: 16, degree: 2, claim: "stage2.ram_raf.ram_address", kernel: Some("jolt.cpu.stage2.ram.raf_evaluation"), relation: None, claim_value: "stage2.input.stage1.RamAddress", input_openings: STAGE2_SUMCHECK_CLAIM_4_INPUT_OPENINGS }, - Stage2SumcheckClaimPlan { symbol: "stage2.ram_output.input", stage: "stage2", domain: "jolt.ram_address_domain", num_rounds: 16, degree: 3, claim: "zero", kernel: Some("jolt.cpu.stage2.ram.output_check"), relation: None, claim_value: "stage2.ram_output.zero", input_openings: STAGE2_SUMCHECK_CLAIM_5_INPUT_OPENINGS }, + Stage2SumcheckClaimPlan { symbol: "stage2.product_virtual.remainder.input", stage: "stage2", domain: "jolt.trace_domain", num_rounds: 18, degree: 3, claim: "stage2.product_virtual.uniskip.opening", kernel: Some("jolt.cpu.stage2.product_virtual.remainder"), relation: None, claim_value: "stage2.product_virtual.uniskip.eval.UnivariateSkip", input_openings: STAGE2_SUMCHECK_CLAIM_2_INPUT_OPENINGS }, + Stage2SumcheckClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.input", stage: "stage2", domain: "jolt.trace_domain", num_rounds: 18, degree: 2, claim: "stage2.instruction_lookup.weighted_operands", kernel: Some("jolt.cpu.stage2.instruction_lookup.claim_reduction"), relation: None, claim_value: "stage2.instruction_lookup.claim_reduction.claim_expr", input_openings: STAGE2_SUMCHECK_CLAIM_3_INPUT_OPENINGS }, + Stage2SumcheckClaimPlan { symbol: "stage2.ram_raf.input", stage: "stage2", domain: "jolt.ram_address_domain", num_rounds: 14, degree: 2, claim: "stage2.ram_raf.ram_address", kernel: Some("jolt.cpu.stage2.ram.raf_evaluation"), relation: None, claim_value: "stage2.input.stage1.RamAddress", input_openings: STAGE2_SUMCHECK_CLAIM_4_INPUT_OPENINGS }, + Stage2SumcheckClaimPlan { symbol: "stage2.ram_output.input", stage: "stage2", domain: "jolt.ram_address_domain", num_rounds: 14, degree: 3, claim: "zero", kernel: Some("jolt.cpu.stage2.ram.output_check"), relation: None, claim_value: "stage2.ram_output.zero", input_openings: STAGE2_SUMCHECK_CLAIM_5_INPUT_OPENINGS }, ]; pub const STAGE2_SUMCHECK_BATCH_0_ORDERED_CLAIMS: &[&str] = &["stage2.product_virtual.uniskip.input"]; @@ -228,8 +228,8 @@ pub const STAGE2_SUMCHECK_BATCH_1_CLAIM_OPERANDS: &[&str] = &[ ]; pub const STAGE2_SUMCHECK_BATCH_1_ROUND_SCHEDULE: &[usize] = &[ - 16, - 16, + 18, + 14, ]; pub const STAGE2_SUMCHECK_BATCHES: &[Stage2SumcheckBatchPlan] = &[ @@ -241,8 +241,8 @@ pub const STAGE2_SUMCHECK_DRIVER_0_ROUND_SCHEDULE: &[usize] = &[ ]; pub const STAGE2_SUMCHECK_DRIVER_1_ROUND_SCHEDULE: &[usize] = &[ - 16, - 16, + 18, + 14, ]; pub const STAGE2_SUMCHECK_DRIVERS: &[Stage2SumcheckDriverPlan] = &[ @@ -252,10 +252,10 @@ pub const STAGE2_SUMCHECK_DRIVERS: &[Stage2SumcheckDriverPlan] = &[ pub const STAGE2_SUMCHECK_INSTANCE_RESULTS: &[Stage2SumcheckInstanceResultPlan] = &[ Stage2SumcheckInstanceResultPlan { symbol: "stage2.product_virtual.uniskip.instance", source: "stage2.product_virtual.uniskip.sumcheck", claim: "stage2.product_virtual.uniskip.input", relation: "jolt.stage2.product_virtual.uniskip", index: 0, point_arity: 1, num_rounds: 1, round_offset: 0, point_order: "as_is", degree: 6 }, Stage2SumcheckInstanceResultPlan { symbol: "stage2.ram_read_write.instance", source: "stage2.sumcheck", claim: "stage2.ram_read_write.input", relation: "jolt.stage2.ram.read_write", index: 0, point_arity: 32, num_rounds: 32, round_offset: 0, point_order: "reverse", degree: 3 }, - Stage2SumcheckInstanceResultPlan { symbol: "stage2.product_virtual.remainder.instance", source: "stage2.sumcheck", claim: "stage2.product_virtual.remainder.input", relation: "jolt.stage2.product_virtual.remainder", index: 1, point_arity: 16, num_rounds: 16, round_offset: 16, point_order: "reverse", degree: 3 }, - Stage2SumcheckInstanceResultPlan { symbol: "stage2.instruction_lookup.claim_reduction.instance", source: "stage2.sumcheck", claim: "stage2.instruction_lookup.claim_reduction.input", relation: "jolt.stage2.instruction_lookup.claim_reduction", index: 2, point_arity: 16, num_rounds: 16, round_offset: 16, point_order: "reverse", degree: 2 }, - Stage2SumcheckInstanceResultPlan { symbol: "stage2.ram_raf.instance", source: "stage2.sumcheck", claim: "stage2.ram_raf.input", relation: "jolt.stage2.ram.raf_evaluation", index: 3, point_arity: 16, num_rounds: 16, round_offset: 16, point_order: "reverse", degree: 2 }, - Stage2SumcheckInstanceResultPlan { symbol: "stage2.ram_output.instance", source: "stage2.sumcheck", claim: "stage2.ram_output.input", relation: "jolt.stage2.ram.output_check", index: 4, point_arity: 16, num_rounds: 16, round_offset: 16, point_order: "reverse", degree: 3 }, + Stage2SumcheckInstanceResultPlan { symbol: "stage2.product_virtual.remainder.instance", source: "stage2.sumcheck", claim: "stage2.product_virtual.remainder.input", relation: "jolt.stage2.product_virtual.remainder", index: 1, point_arity: 18, num_rounds: 18, round_offset: 14, point_order: "reverse", degree: 3 }, + Stage2SumcheckInstanceResultPlan { symbol: "stage2.instruction_lookup.claim_reduction.instance", source: "stage2.sumcheck", claim: "stage2.instruction_lookup.claim_reduction.input", relation: "jolt.stage2.instruction_lookup.claim_reduction", index: 2, point_arity: 18, num_rounds: 18, round_offset: 14, point_order: "reverse", degree: 2 }, + Stage2SumcheckInstanceResultPlan { symbol: "stage2.ram_raf.instance", source: "stage2.sumcheck", claim: "stage2.ram_raf.input", relation: "jolt.stage2.ram.raf_evaluation", index: 3, point_arity: 14, num_rounds: 14, round_offset: 18, point_order: "reverse", degree: 2 }, + Stage2SumcheckInstanceResultPlan { symbol: "stage2.ram_output.instance", source: "stage2.sumcheck", claim: "stage2.ram_output.input", relation: "jolt.stage2.ram.output_check", index: 4, point_arity: 14, num_rounds: 14, round_offset: 18, point_order: "reverse", degree: 3 }, ]; pub const STAGE2_SUMCHECK_EVALS: &[Stage2SumcheckEvalPlan] = &[ @@ -281,7 +281,7 @@ pub const STAGE2_SUMCHECK_EVALS: &[Stage2SumcheckEvalPlan] = &[ ]; pub const STAGE2_POINT_SLICES: &[Stage2PointSlicePlan] = &[ - Stage2PointSlicePlan { symbol: "stage2.ram_read_write.point.RamInc", source: "stage2.ram_read_write.instance", offset: 16, length: 16, input: "stage2.ram_read_write.instance" }, + Stage2PointSlicePlan { symbol: "stage2.ram_read_write.point.RamInc", source: "stage2.ram_read_write.instance", offset: 14, length: 18, input: "stage2.ram_read_write.instance" }, ]; pub const STAGE2_POINT_CONCAT_0_INPUTS: &[&str] = &[ @@ -296,22 +296,22 @@ pub const STAGE2_OPENING_CLAIMS: &[Stage2OpeningClaimPlan] = &[ Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.uniskip.opening.UnivariateSkip", oracle: "UnivariateSkip", domain: "jolt.stage2_uniskip_domain", point_arity: 1, claim_kind: "virtual", point_source: "stage2.product_virtual.uniskip.instance", eval_source: "stage2.product_virtual.uniskip.eval.UnivariateSkip" }, Stage2OpeningClaimPlan { symbol: "stage2.ram_read_write.opening.RamVal", oracle: "RamVal", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage2.ram_read_write.instance", eval_source: "stage2.ram_read_write.eval.RamVal" }, Stage2OpeningClaimPlan { symbol: "stage2.ram_read_write.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage2.ram_read_write.instance", eval_source: "stage2.ram_read_write.eval.RamRa" }, - Stage2OpeningClaimPlan { symbol: "stage2.ram_read_write.opening.RamInc", oracle: "RamInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed", point_source: "stage2.ram_read_write.point.RamInc", eval_source: "stage2.ram_read_write.eval.RamInc" }, - Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.LeftInstructionInput" }, - Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.RightInstructionInput" }, - Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.OpFlagJump", oracle: "OpFlagJump", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.OpFlagJump" }, - Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.OpFlagWriteLookupOutputToRD", oracle: "OpFlagWriteLookupOutputToRD", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.OpFlagWriteLookupOutputToRD" }, - Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.LookupOutput" }, - Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.InstructionFlagBranch", oracle: "InstructionFlagBranch", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.InstructionFlagBranch" }, - Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.NextIsNoop", oracle: "NextIsNoop", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.NextIsNoop" }, - Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.OpFlagVirtualInstruction" }, - Stage2OpeningClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.instruction_lookup.claim_reduction.instance", eval_source: "stage2.instruction_lookup.claim_reduction.eval.LookupOutput" }, - Stage2OpeningClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.opening.LeftLookupOperand", oracle: "LeftLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.instruction_lookup.claim_reduction.instance", eval_source: "stage2.instruction_lookup.claim_reduction.eval.LeftLookupOperand" }, - Stage2OpeningClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.opening.RightLookupOperand", oracle: "RightLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.instruction_lookup.claim_reduction.instance", eval_source: "stage2.instruction_lookup.claim_reduction.eval.RightLookupOperand" }, - Stage2OpeningClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.instruction_lookup.claim_reduction.instance", eval_source: "stage2.instruction_lookup.claim_reduction.eval.LeftInstructionInput" }, - Stage2OpeningClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.instruction_lookup.claim_reduction.instance", eval_source: "stage2.instruction_lookup.claim_reduction.eval.RightInstructionInput" }, + Stage2OpeningClaimPlan { symbol: "stage2.ram_read_write.opening.RamInc", oracle: "RamInc", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "committed", point_source: "stage2.ram_read_write.point.RamInc", eval_source: "stage2.ram_read_write.eval.RamInc" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.LeftInstructionInput" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.RightInstructionInput" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.OpFlagJump", oracle: "OpFlagJump", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.OpFlagJump" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.OpFlagWriteLookupOutputToRD", oracle: "OpFlagWriteLookupOutputToRD", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.OpFlagWriteLookupOutputToRD" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.LookupOutput" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.InstructionFlagBranch", oracle: "InstructionFlagBranch", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.InstructionFlagBranch" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.NextIsNoop", oracle: "NextIsNoop", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.NextIsNoop" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.OpFlagVirtualInstruction" }, + Stage2OpeningClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage2.instruction_lookup.claim_reduction.instance", eval_source: "stage2.instruction_lookup.claim_reduction.eval.LookupOutput" }, + Stage2OpeningClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.opening.LeftLookupOperand", oracle: "LeftLookupOperand", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage2.instruction_lookup.claim_reduction.instance", eval_source: "stage2.instruction_lookup.claim_reduction.eval.LeftLookupOperand" }, + Stage2OpeningClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.opening.RightLookupOperand", oracle: "RightLookupOperand", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage2.instruction_lookup.claim_reduction.instance", eval_source: "stage2.instruction_lookup.claim_reduction.eval.RightLookupOperand" }, + Stage2OpeningClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage2.instruction_lookup.claim_reduction.instance", eval_source: "stage2.instruction_lookup.claim_reduction.eval.LeftInstructionInput" }, + Stage2OpeningClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage2.instruction_lookup.claim_reduction.instance", eval_source: "stage2.instruction_lookup.claim_reduction.eval.RightInstructionInput" }, Stage2OpeningClaimPlan { symbol: "stage2.ram_raf.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage2.ram_raf.point.RamRa", eval_source: "stage2.ram_raf.eval.RamRa" }, - Stage2OpeningClaimPlan { symbol: "stage2.ram_output.opening.RamValFinal", oracle: "RamValFinal", domain: "jolt.ram_address_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.ram_output.instance", eval_source: "stage2.ram_output.eval.RamValFinal" }, + Stage2OpeningClaimPlan { symbol: "stage2.ram_output.opening.RamValFinal", oracle: "RamValFinal", domain: "jolt.ram_address_domain", point_arity: 14, claim_kind: "virtual", point_source: "stage2.ram_output.instance", eval_source: "stage2.ram_output.eval.RamValFinal" }, ]; pub const STAGE2_OPENING_BATCH_0_ORDERED_CLAIMS: &[&str] = &[ diff --git a/crates/jolt-prover/src/stages/stage3.rs b/crates/jolt-prover/src/stages/stage3.rs index f1ca47494b..a9d50ccbdd 100644 --- a/crates/jolt-prover/src/stages/stage3.rs +++ b/crates/jolt-prover/src/stages/stage3.rs @@ -25,18 +25,18 @@ pub const STAGE3_TRANSCRIPT_SQUEEZES: &[Stage3TranscriptSqueezePlan] = &[ ]; pub const STAGE3_OPENING_INPUTS: &[Stage3OpeningInputPlan] = &[ - Stage3OpeningInputPlan { symbol: "stage3.input.stage1.NextUnexpandedPC", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.NextUnexpandedPC", oracle: "NextUnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage3OpeningInputPlan { symbol: "stage3.input.stage1.NextPC", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.NextPC", oracle: "NextPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage3OpeningInputPlan { symbol: "stage3.input.stage1.NextIsVirtual", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.NextIsVirtual", oracle: "NextIsVirtual", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage3OpeningInputPlan { symbol: "stage3.input.stage1.NextIsFirstInSequence", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.NextIsFirstInSequence", oracle: "NextIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage3OpeningInputPlan { symbol: "stage3.input.stage2.product_virtual.NextIsNoop", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.NextIsNoop", oracle: "NextIsNoop", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage3OpeningInputPlan { symbol: "stage3.input.stage2.product_virtual.LeftInstructionInput", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage3OpeningInputPlan { symbol: "stage3.input.stage2.product_virtual.RightInstructionInput", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage3OpeningInputPlan { symbol: "stage3.input.stage2.instruction_lookup.LeftInstructionInput", source_stage: "stage2", source_claim: "stage2.instruction_lookup.claim_reduction.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage3OpeningInputPlan { symbol: "stage3.input.stage2.instruction_lookup.RightInstructionInput", source_stage: "stage2", source_claim: "stage2.instruction_lookup.claim_reduction.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage3OpeningInputPlan { symbol: "stage3.input.stage1.RdWriteValue", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RdWriteValue", oracle: "RdWriteValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage3OpeningInputPlan { symbol: "stage3.input.stage1.Rs1Value", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage3OpeningInputPlan { symbol: "stage3.input.stage1.Rs2Value", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage1.NextUnexpandedPC", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.NextUnexpandedPC", oracle: "NextUnexpandedPC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage1.NextPC", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.NextPC", oracle: "NextPC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage1.NextIsVirtual", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.NextIsVirtual", oracle: "NextIsVirtual", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage1.NextIsFirstInSequence", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.NextIsFirstInSequence", oracle: "NextIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage2.product_virtual.NextIsNoop", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.NextIsNoop", oracle: "NextIsNoop", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage2.product_virtual.LeftInstructionInput", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage2.product_virtual.RightInstructionInput", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage2.instruction_lookup.LeftInstructionInput", source_stage: "stage2", source_claim: "stage2.instruction_lookup.claim_reduction.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage2.instruction_lookup.RightInstructionInput", source_stage: "stage2", source_claim: "stage2.instruction_lookup.claim_reduction.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage1.RdWriteValue", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RdWriteValue", oracle: "RdWriteValue", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage1.Rs1Value", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage1.Rs2Value", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, ]; pub const STAGE3_FIELD_CONSTANTS: &[Stage3FieldConstantPlan] = &[ @@ -180,9 +180,9 @@ pub const STAGE3_SUMCHECK_CLAIM_2_INPUT_OPENINGS: &[&str] = &[ ]; pub const STAGE3_SUMCHECK_CLAIMS: &[Stage3SumcheckClaimPlan] = &[ - Stage3SumcheckClaimPlan { symbol: "stage3.spartan_shift.input", stage: "stage3", domain: "jolt.trace_domain", num_rounds: 16, degree: 2, claim: "stage3.spartan_shift.weighted_next_values", kernel: Some("jolt.cpu.stage3.spartan_shift"), relation: None, claim_value: "stage3.spartan_shift.claim_expr", input_openings: STAGE3_SUMCHECK_CLAIM_0_INPUT_OPENINGS }, - Stage3SumcheckClaimPlan { symbol: "stage3.instruction_input.input", stage: "stage3", domain: "jolt.trace_domain", num_rounds: 16, degree: 3, claim: "stage3.instruction_input.weighted_inputs", kernel: Some("jolt.cpu.stage3.instruction_input"), relation: None, claim_value: "stage3.instruction_input.claim_expr", input_openings: STAGE3_SUMCHECK_CLAIM_1_INPUT_OPENINGS }, - Stage3SumcheckClaimPlan { symbol: "stage3.registers_claim_reduction.input", stage: "stage3", domain: "jolt.trace_domain", num_rounds: 16, degree: 2, claim: "stage3.registers.weighted_register_values", kernel: Some("jolt.cpu.stage3.registers_claim_reduction"), relation: None, claim_value: "stage3.registers.claim_expr", input_openings: STAGE3_SUMCHECK_CLAIM_2_INPUT_OPENINGS }, + Stage3SumcheckClaimPlan { symbol: "stage3.spartan_shift.input", stage: "stage3", domain: "jolt.trace_domain", num_rounds: 18, degree: 2, claim: "stage3.spartan_shift.weighted_next_values", kernel: Some("jolt.cpu.stage3.spartan_shift"), relation: None, claim_value: "stage3.spartan_shift.claim_expr", input_openings: STAGE3_SUMCHECK_CLAIM_0_INPUT_OPENINGS }, + Stage3SumcheckClaimPlan { symbol: "stage3.instruction_input.input", stage: "stage3", domain: "jolt.trace_domain", num_rounds: 18, degree: 3, claim: "stage3.instruction_input.weighted_inputs", kernel: Some("jolt.cpu.stage3.instruction_input"), relation: None, claim_value: "stage3.instruction_input.claim_expr", input_openings: STAGE3_SUMCHECK_CLAIM_1_INPUT_OPENINGS }, + Stage3SumcheckClaimPlan { symbol: "stage3.registers_claim_reduction.input", stage: "stage3", domain: "jolt.trace_domain", num_rounds: 18, degree: 2, claim: "stage3.registers.weighted_register_values", kernel: Some("jolt.cpu.stage3.registers_claim_reduction"), relation: None, claim_value: "stage3.registers.claim_expr", input_openings: STAGE3_SUMCHECK_CLAIM_2_INPUT_OPENINGS }, ]; pub const STAGE3_SUMCHECK_BATCH_0_ORDERED_CLAIMS: &[&str] = &[ "stage3.spartan_shift.input", @@ -197,23 +197,23 @@ pub const STAGE3_SUMCHECK_BATCH_0_CLAIM_OPERANDS: &[&str] = &[ ]; pub const STAGE3_SUMCHECK_BATCH_0_ROUND_SCHEDULE: &[usize] = &[ - 16, + 18, ]; pub const STAGE3_SUMCHECK_BATCHES: &[Stage3SumcheckBatchPlan] = &[ Stage3SumcheckBatchPlan { symbol: "stage3.batch", stage: "stage3", proof_slot: "stage3.sumcheck", policy: "jolt_core_stage3_aligned", count: 3, ordered_claims: STAGE3_SUMCHECK_BATCH_0_ORDERED_CLAIMS, claim_operands: STAGE3_SUMCHECK_BATCH_0_CLAIM_OPERANDS, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", round_schedule: STAGE3_SUMCHECK_BATCH_0_ROUND_SCHEDULE }, ]; pub const STAGE3_SUMCHECK_DRIVER_0_ROUND_SCHEDULE: &[usize] = &[ - 16, + 18, ]; pub const STAGE3_SUMCHECK_DRIVERS: &[Stage3SumcheckDriverPlan] = &[ - Stage3SumcheckDriverPlan { symbol: "stage3.sumcheck", stage: "stage3", proof_slot: "stage3.sumcheck", kernel: Some("jolt.cpu.stage3.batched"), relation: None, batch: "stage3.batch", policy: "jolt_core_stage3_aligned", round_schedule: STAGE3_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 16, degree: 3 }, + Stage3SumcheckDriverPlan { symbol: "stage3.sumcheck", stage: "stage3", proof_slot: "stage3.sumcheck", kernel: Some("jolt.cpu.stage3.batched"), relation: None, batch: "stage3.batch", policy: "jolt_core_stage3_aligned", round_schedule: STAGE3_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 18, degree: 3 }, ]; pub const STAGE3_SUMCHECK_INSTANCE_RESULTS: &[Stage3SumcheckInstanceResultPlan] = &[ - Stage3SumcheckInstanceResultPlan { symbol: "stage3.spartan_shift.instance", source: "stage3.sumcheck", claim: "stage3.spartan_shift.input", relation: "jolt.stage3.spartan_shift", index: 0, point_arity: 16, num_rounds: 16, round_offset: 0, point_order: "reverse", degree: 2 }, - Stage3SumcheckInstanceResultPlan { symbol: "stage3.instruction_input.instance", source: "stage3.sumcheck", claim: "stage3.instruction_input.input", relation: "jolt.stage3.instruction_input", index: 1, point_arity: 16, num_rounds: 16, round_offset: 0, point_order: "reverse", degree: 3 }, - Stage3SumcheckInstanceResultPlan { symbol: "stage3.registers_claim_reduction.instance", source: "stage3.sumcheck", claim: "stage3.registers_claim_reduction.input", relation: "jolt.stage3.registers_claim_reduction", index: 2, point_arity: 16, num_rounds: 16, round_offset: 0, point_order: "reverse", degree: 2 }, + Stage3SumcheckInstanceResultPlan { symbol: "stage3.spartan_shift.instance", source: "stage3.sumcheck", claim: "stage3.spartan_shift.input", relation: "jolt.stage3.spartan_shift", index: 0, point_arity: 18, num_rounds: 18, round_offset: 0, point_order: "reverse", degree: 2 }, + Stage3SumcheckInstanceResultPlan { symbol: "stage3.instruction_input.instance", source: "stage3.sumcheck", claim: "stage3.instruction_input.input", relation: "jolt.stage3.instruction_input", index: 1, point_arity: 18, num_rounds: 18, round_offset: 0, point_order: "reverse", degree: 3 }, + Stage3SumcheckInstanceResultPlan { symbol: "stage3.registers_claim_reduction.instance", source: "stage3.sumcheck", claim: "stage3.registers_claim_reduction.input", relation: "jolt.stage3.registers_claim_reduction", index: 2, point_arity: 18, num_rounds: 18, round_offset: 0, point_order: "reverse", degree: 2 }, ]; pub const STAGE3_SUMCHECK_EVALS: &[Stage3SumcheckEvalPlan] = &[ @@ -243,22 +243,22 @@ pub const STAGE3_POINT_CONCATS: &[Stage3PointConcatPlan] = &[ ]; pub const STAGE3_OPENING_CLAIMS: &[Stage3OpeningClaimPlan] = &[ - Stage3OpeningClaimPlan { symbol: "stage3.spartan_shift.opening.UnexpandedPC", oracle: "UnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.spartan_shift.instance", eval_source: "stage3.spartan_shift.eval.UnexpandedPC" }, - Stage3OpeningClaimPlan { symbol: "stage3.spartan_shift.opening.PC", oracle: "PC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.spartan_shift.instance", eval_source: "stage3.spartan_shift.eval.PC" }, - Stage3OpeningClaimPlan { symbol: "stage3.spartan_shift.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.spartan_shift.instance", eval_source: "stage3.spartan_shift.eval.OpFlagVirtualInstruction" }, - Stage3OpeningClaimPlan { symbol: "stage3.spartan_shift.opening.OpFlagIsFirstInSequence", oracle: "OpFlagIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.spartan_shift.instance", eval_source: "stage3.spartan_shift.eval.OpFlagIsFirstInSequence" }, - Stage3OpeningClaimPlan { symbol: "stage3.spartan_shift.opening.InstructionFlagIsNoop", oracle: "InstructionFlagIsNoop", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.spartan_shift.instance", eval_source: "stage3.spartan_shift.eval.InstructionFlagIsNoop" }, - Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.InstructionFlagLeftOperandIsRs1Value", oracle: "InstructionFlagLeftOperandIsRs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.InstructionFlagLeftOperandIsRs1Value" }, - Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.Rs1Value" }, - Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.InstructionFlagLeftOperandIsPC", oracle: "InstructionFlagLeftOperandIsPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.InstructionFlagLeftOperandIsPC" }, - Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.UnexpandedPC", oracle: "UnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.UnexpandedPC" }, - Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.InstructionFlagRightOperandIsRs2Value", oracle: "InstructionFlagRightOperandIsRs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.InstructionFlagRightOperandIsRs2Value" }, - Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.Rs2Value" }, - Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.InstructionFlagRightOperandIsImm", oracle: "InstructionFlagRightOperandIsImm", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.InstructionFlagRightOperandIsImm" }, - Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.Imm", oracle: "Imm", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.Imm" }, - Stage3OpeningClaimPlan { symbol: "stage3.registers_claim_reduction.opening.RdWriteValue", oracle: "RdWriteValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.registers_claim_reduction.instance", eval_source: "stage3.registers_claim_reduction.eval.RdWriteValue" }, - Stage3OpeningClaimPlan { symbol: "stage3.registers_claim_reduction.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.registers_claim_reduction.instance", eval_source: "stage3.registers_claim_reduction.eval.Rs1Value" }, - Stage3OpeningClaimPlan { symbol: "stage3.registers_claim_reduction.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.registers_claim_reduction.instance", eval_source: "stage3.registers_claim_reduction.eval.Rs2Value" }, + Stage3OpeningClaimPlan { symbol: "stage3.spartan_shift.opening.UnexpandedPC", oracle: "UnexpandedPC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.spartan_shift.instance", eval_source: "stage3.spartan_shift.eval.UnexpandedPC" }, + Stage3OpeningClaimPlan { symbol: "stage3.spartan_shift.opening.PC", oracle: "PC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.spartan_shift.instance", eval_source: "stage3.spartan_shift.eval.PC" }, + Stage3OpeningClaimPlan { symbol: "stage3.spartan_shift.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.spartan_shift.instance", eval_source: "stage3.spartan_shift.eval.OpFlagVirtualInstruction" }, + Stage3OpeningClaimPlan { symbol: "stage3.spartan_shift.opening.OpFlagIsFirstInSequence", oracle: "OpFlagIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.spartan_shift.instance", eval_source: "stage3.spartan_shift.eval.OpFlagIsFirstInSequence" }, + Stage3OpeningClaimPlan { symbol: "stage3.spartan_shift.opening.InstructionFlagIsNoop", oracle: "InstructionFlagIsNoop", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.spartan_shift.instance", eval_source: "stage3.spartan_shift.eval.InstructionFlagIsNoop" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.InstructionFlagLeftOperandIsRs1Value", oracle: "InstructionFlagLeftOperandIsRs1Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.InstructionFlagLeftOperandIsRs1Value" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.Rs1Value" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.InstructionFlagLeftOperandIsPC", oracle: "InstructionFlagLeftOperandIsPC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.InstructionFlagLeftOperandIsPC" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.UnexpandedPC", oracle: "UnexpandedPC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.UnexpandedPC" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.InstructionFlagRightOperandIsRs2Value", oracle: "InstructionFlagRightOperandIsRs2Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.InstructionFlagRightOperandIsRs2Value" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.Rs2Value" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.InstructionFlagRightOperandIsImm", oracle: "InstructionFlagRightOperandIsImm", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.InstructionFlagRightOperandIsImm" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.Imm", oracle: "Imm", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.Imm" }, + Stage3OpeningClaimPlan { symbol: "stage3.registers_claim_reduction.opening.RdWriteValue", oracle: "RdWriteValue", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.registers_claim_reduction.instance", eval_source: "stage3.registers_claim_reduction.eval.RdWriteValue" }, + Stage3OpeningClaimPlan { symbol: "stage3.registers_claim_reduction.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.registers_claim_reduction.instance", eval_source: "stage3.registers_claim_reduction.eval.Rs1Value" }, + Stage3OpeningClaimPlan { symbol: "stage3.registers_claim_reduction.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.registers_claim_reduction.instance", eval_source: "stage3.registers_claim_reduction.eval.Rs2Value" }, ]; pub const STAGE3_OPENING_EQUALITIES: &[Stage3OpeningClaimEqualityPlan] = &[ diff --git a/crates/jolt-prover/src/stages/stage4.rs b/crates/jolt-prover/src/stages/stage4.rs index 03a8258a94..cc58a42256 100644 --- a/crates/jolt-prover/src/stages/stage4.rs +++ b/crates/jolt-prover/src/stages/stage4.rs @@ -28,14 +28,14 @@ pub const STAGE4_TRANSCRIPT_ABSORB_BYTES: &[Stage4TranscriptAbsorbBytesPlan] = & ]; pub const STAGE4_OPENING_INPUTS: &[Stage4OpeningInputPlan] = &[ - Stage4OpeningInputPlan { symbol: "stage4.input.stage3.registers.RdWriteValue", source_stage: "stage3", source_claim: "stage3.registers_claim_reduction.opening.RdWriteValue", oracle: "RdWriteValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage4OpeningInputPlan { symbol: "stage4.input.stage3.registers.Rs1Value", source_stage: "stage3", source_claim: "stage3.registers_claim_reduction.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage4OpeningInputPlan { symbol: "stage4.input.stage3.registers.Rs2Value", source_stage: "stage3", source_claim: "stage3.registers_claim_reduction.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage4OpeningInputPlan { symbol: "stage4.input.stage3.instruction.Rs1Value", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage4OpeningInputPlan { symbol: "stage4.input.stage3.instruction.Rs2Value", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage4OpeningInputPlan { symbol: "stage4.input.stage3.registers.RdWriteValue", source_stage: "stage3", source_claim: "stage3.registers_claim_reduction.opening.RdWriteValue", oracle: "RdWriteValue", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage4OpeningInputPlan { symbol: "stage4.input.stage3.registers.Rs1Value", source_stage: "stage3", source_claim: "stage3.registers_claim_reduction.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage4OpeningInputPlan { symbol: "stage4.input.stage3.registers.Rs2Value", source_stage: "stage3", source_claim: "stage3.registers_claim_reduction.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage4OpeningInputPlan { symbol: "stage4.input.stage3.instruction.Rs1Value", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage4OpeningInputPlan { symbol: "stage4.input.stage3.instruction.Rs2Value", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, Stage4OpeningInputPlan { symbol: "stage4.input.stage2.RamVal", source_stage: "stage2", source_claim: "stage2.ram_read_write.opening.RamVal", oracle: "RamVal", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual" }, - Stage4OpeningInputPlan { symbol: "stage4.input.stage2.RamValFinal", source_stage: "stage2", source_claim: "stage2.ram_output.opening.RamValFinal", oracle: "RamValFinal", domain: "jolt.ram_address_domain", point_arity: 16, claim_kind: "virtual" }, - Stage4OpeningInputPlan { symbol: "stage4.input.initial_ram.RamValInit", source_stage: "stage4_precomputed", source_claim: "stage4.ram_val_check.initial_ram_eval", oracle: "RamValInit", domain: "jolt.ram_address_domain", point_arity: 16, claim_kind: "virtual" }, + Stage4OpeningInputPlan { symbol: "stage4.input.stage2.RamValFinal", source_stage: "stage2", source_claim: "stage2.ram_output.opening.RamValFinal", oracle: "RamValFinal", domain: "jolt.ram_address_domain", point_arity: 14, claim_kind: "virtual" }, + Stage4OpeningInputPlan { symbol: "stage4.input.initial_ram.RamValInit", source_stage: "stage4_precomputed", source_claim: "stage4.ram_val_check.initial_ram_eval", oracle: "RamValInit", domain: "jolt.ram_address_domain", point_arity: 14, claim_kind: "virtual" }, ]; pub const STAGE4_FIELD_CONSTANTS: &[Stage4FieldConstantPlan] = &[ @@ -114,8 +114,8 @@ pub const STAGE4_SUMCHECK_CLAIM_1_INPUT_OPENINGS: &[&str] = &[ ]; pub const STAGE4_SUMCHECK_CLAIMS: &[Stage4SumcheckClaimPlan] = &[ - Stage4SumcheckClaimPlan { symbol: "stage4.registers_read_write.input", stage: "stage4", domain: "jolt.stage4_registers_rw_domain", num_rounds: 23, degree: 3, claim: "stage4.registers_read_write.weighted_values", kernel: Some("jolt.cpu.stage4.registers_read_write"), relation: None, claim_value: "stage4.registers_read_write.claim_expr", input_openings: STAGE4_SUMCHECK_CLAIM_0_INPUT_OPENINGS }, - Stage4SumcheckClaimPlan { symbol: "stage4.ram_val_check.input", stage: "stage4", domain: "jolt.trace_domain", num_rounds: 16, degree: 3, claim: "stage4.ram_val_check.weighted_values", kernel: Some("jolt.cpu.stage4.ram_val_check"), relation: None, claim_value: "stage4.ram_val_check.claim_expr", input_openings: STAGE4_SUMCHECK_CLAIM_1_INPUT_OPENINGS }, + Stage4SumcheckClaimPlan { symbol: "stage4.registers_read_write.input", stage: "stage4", domain: "jolt.stage4_registers_rw_domain", num_rounds: 25, degree: 3, claim: "stage4.registers_read_write.weighted_values", kernel: Some("jolt.cpu.stage4.registers_read_write"), relation: None, claim_value: "stage4.registers_read_write.claim_expr", input_openings: STAGE4_SUMCHECK_CLAIM_0_INPUT_OPENINGS }, + Stage4SumcheckClaimPlan { symbol: "stage4.ram_val_check.input", stage: "stage4", domain: "jolt.trace_domain", num_rounds: 18, degree: 3, claim: "stage4.ram_val_check.weighted_values", kernel: Some("jolt.cpu.stage4.ram_val_check"), relation: None, claim_value: "stage4.ram_val_check.claim_expr", input_openings: STAGE4_SUMCHECK_CLAIM_1_INPUT_OPENINGS }, ]; pub const STAGE4_SUMCHECK_BATCH_0_ORDERED_CLAIMS: &[&str] = &[ "stage4.registers_read_write.input", @@ -128,7 +128,7 @@ pub const STAGE4_SUMCHECK_BATCH_0_CLAIM_OPERANDS: &[&str] = &[ ]; pub const STAGE4_SUMCHECK_BATCH_0_ROUND_SCHEDULE: &[usize] = &[ - 16, + 18, 7, ]; @@ -136,16 +136,16 @@ pub const STAGE4_SUMCHECK_BATCHES: &[Stage4SumcheckBatchPlan] = &[ Stage4SumcheckBatchPlan { symbol: "stage4.batch", stage: "stage4", proof_slot: "stage4.sumcheck", policy: "jolt_core_stage4_aligned", count: 2, ordered_claims: STAGE4_SUMCHECK_BATCH_0_ORDERED_CLAIMS, claim_operands: STAGE4_SUMCHECK_BATCH_0_CLAIM_OPERANDS, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", round_schedule: STAGE4_SUMCHECK_BATCH_0_ROUND_SCHEDULE }, ]; pub const STAGE4_SUMCHECK_DRIVER_0_ROUND_SCHEDULE: &[usize] = &[ - 16, + 18, 7, ]; pub const STAGE4_SUMCHECK_DRIVERS: &[Stage4SumcheckDriverPlan] = &[ - Stage4SumcheckDriverPlan { symbol: "stage4.sumcheck", stage: "stage4", proof_slot: "stage4.sumcheck", kernel: Some("jolt.cpu.stage4.batched"), relation: None, batch: "stage4.batch", policy: "jolt_core_stage4_aligned", round_schedule: STAGE4_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 23, degree: 3 }, + Stage4SumcheckDriverPlan { symbol: "stage4.sumcheck", stage: "stage4", proof_slot: "stage4.sumcheck", kernel: Some("jolt.cpu.stage4.batched"), relation: None, batch: "stage4.batch", policy: "jolt_core_stage4_aligned", round_schedule: STAGE4_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 25, degree: 3 }, ]; pub const STAGE4_SUMCHECK_INSTANCE_RESULTS: &[Stage4SumcheckInstanceResultPlan] = &[ - Stage4SumcheckInstanceResultPlan { symbol: "stage4.registers_read_write.instance", source: "stage4.sumcheck", claim: "stage4.registers_read_write.input", relation: "jolt.stage4.registers_read_write", index: 0, point_arity: 23, num_rounds: 23, round_offset: 0, point_order: "stage4_registers_rw", degree: 3 }, - Stage4SumcheckInstanceResultPlan { symbol: "stage4.ram_val_check.instance", source: "stage4.sumcheck", claim: "stage4.ram_val_check.input", relation: "jolt.stage4.ram_val_check", index: 1, point_arity: 16, num_rounds: 16, round_offset: 7, point_order: "reverse", degree: 3 }, + Stage4SumcheckInstanceResultPlan { symbol: "stage4.registers_read_write.instance", source: "stage4.sumcheck", claim: "stage4.registers_read_write.input", relation: "jolt.stage4.registers_read_write", index: 0, point_arity: 25, num_rounds: 25, round_offset: 0, point_order: "stage4_registers_rw", degree: 3 }, + Stage4SumcheckInstanceResultPlan { symbol: "stage4.ram_val_check.instance", source: "stage4.sumcheck", claim: "stage4.ram_val_check.input", relation: "jolt.stage4.ram_val_check", index: 1, point_arity: 18, num_rounds: 18, round_offset: 7, point_order: "reverse", degree: 3 }, ]; pub const STAGE4_SUMCHECK_EVALS: &[Stage4SumcheckEvalPlan] = &[ @@ -159,8 +159,8 @@ pub const STAGE4_SUMCHECK_EVALS: &[Stage4SumcheckEvalPlan] = &[ ]; pub const STAGE4_POINT_SLICES: &[Stage4PointSlicePlan] = &[ - Stage4PointSlicePlan { symbol: "stage4.registers_read_write.point.RdInc", source: "stage4.registers_read_write.instance", offset: 7, length: 16, input: "stage4.registers_read_write.instance" }, - Stage4PointSlicePlan { symbol: "stage4.ram_val_check.point.RamAddress", source: "stage4.input.stage2.RamVal", offset: 0, length: 16, input: "stage4.input.stage2.RamVal" }, + Stage4PointSlicePlan { symbol: "stage4.registers_read_write.point.RdInc", source: "stage4.registers_read_write.instance", offset: 7, length: 18, input: "stage4.registers_read_write.instance" }, + Stage4PointSlicePlan { symbol: "stage4.ram_val_check.point.RamAddress", source: "stage4.input.stage2.RamVal", offset: 0, length: 14, input: "stage4.input.stage2.RamVal" }, ]; pub const STAGE4_POINT_CONCAT_0_INPUTS: &[&str] = &[ @@ -172,13 +172,13 @@ pub const STAGE4_POINT_CONCATS: &[Stage4PointConcatPlan] = &[ Stage4PointConcatPlan { symbol: "stage4.ram_val_check.point.RamRa", layout: "address_then_cycle", arity: 32, inputs: STAGE4_POINT_CONCAT_0_INPUTS }, ]; pub const STAGE4_OPENING_CLAIMS: &[Stage4OpeningClaimPlan] = &[ - Stage4OpeningClaimPlan { symbol: "stage4.registers_read_write.opening.RegistersVal", oracle: "RegistersVal", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual", point_source: "stage4.registers_read_write.instance", eval_source: "stage4.registers_read_write.eval.RegistersVal" }, - Stage4OpeningClaimPlan { symbol: "stage4.registers_read_write.opening.Rs1Ra", oracle: "Rs1Ra", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual", point_source: "stage4.registers_read_write.instance", eval_source: "stage4.registers_read_write.eval.Rs1Ra" }, - Stage4OpeningClaimPlan { symbol: "stage4.registers_read_write.opening.Rs2Ra", oracle: "Rs2Ra", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual", point_source: "stage4.registers_read_write.instance", eval_source: "stage4.registers_read_write.eval.Rs2Ra" }, - Stage4OpeningClaimPlan { symbol: "stage4.registers_read_write.opening.RdWa", oracle: "RdWa", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual", point_source: "stage4.registers_read_write.instance", eval_source: "stage4.registers_read_write.eval.RdWa" }, - Stage4OpeningClaimPlan { symbol: "stage4.registers_read_write.opening.RdInc", oracle: "RdInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed", point_source: "stage4.registers_read_write.point.RdInc", eval_source: "stage4.registers_read_write.eval.RdInc" }, + Stage4OpeningClaimPlan { symbol: "stage4.registers_read_write.opening.RegistersVal", oracle: "RegistersVal", domain: "jolt.stage4_registers_rw_domain", point_arity: 25, claim_kind: "virtual", point_source: "stage4.registers_read_write.instance", eval_source: "stage4.registers_read_write.eval.RegistersVal" }, + Stage4OpeningClaimPlan { symbol: "stage4.registers_read_write.opening.Rs1Ra", oracle: "Rs1Ra", domain: "jolt.stage4_registers_rw_domain", point_arity: 25, claim_kind: "virtual", point_source: "stage4.registers_read_write.instance", eval_source: "stage4.registers_read_write.eval.Rs1Ra" }, + Stage4OpeningClaimPlan { symbol: "stage4.registers_read_write.opening.Rs2Ra", oracle: "Rs2Ra", domain: "jolt.stage4_registers_rw_domain", point_arity: 25, claim_kind: "virtual", point_source: "stage4.registers_read_write.instance", eval_source: "stage4.registers_read_write.eval.Rs2Ra" }, + Stage4OpeningClaimPlan { symbol: "stage4.registers_read_write.opening.RdWa", oracle: "RdWa", domain: "jolt.stage4_registers_rw_domain", point_arity: 25, claim_kind: "virtual", point_source: "stage4.registers_read_write.instance", eval_source: "stage4.registers_read_write.eval.RdWa" }, + Stage4OpeningClaimPlan { symbol: "stage4.registers_read_write.opening.RdInc", oracle: "RdInc", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "committed", point_source: "stage4.registers_read_write.point.RdInc", eval_source: "stage4.registers_read_write.eval.RdInc" }, Stage4OpeningClaimPlan { symbol: "stage4.ram_val_check.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage4.ram_val_check.point.RamRa", eval_source: "stage4.ram_val_check.eval.RamRa" }, - Stage4OpeningClaimPlan { symbol: "stage4.ram_val_check.opening.RamInc", oracle: "RamInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed", point_source: "stage4.ram_val_check.instance", eval_source: "stage4.ram_val_check.eval.RamInc" }, + Stage4OpeningClaimPlan { symbol: "stage4.ram_val_check.opening.RamInc", oracle: "RamInc", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "committed", point_source: "stage4.ram_val_check.instance", eval_source: "stage4.ram_val_check.eval.RamInc" }, ]; pub const STAGE4_OPENING_EQUALITIES: &[Stage4OpeningClaimEqualityPlan] = &[ diff --git a/crates/jolt-prover/src/stages/stage5.rs b/crates/jolt-prover/src/stages/stage5.rs index 9febfac702..9d6fe2b7c7 100644 --- a/crates/jolt-prover/src/stages/stage5.rs +++ b/crates/jolt-prover/src/stages/stage5.rs @@ -27,14 +27,14 @@ pub const STAGE5_TRANSCRIPT_ABSORB_BYTES: &[Stage5TranscriptAbsorbBytesPlan] = & ]; pub const STAGE5_OPENING_INPUTS: &[Stage5OpeningInputPlan] = &[ - Stage5OpeningInputPlan { symbol: "stage5.input.stage2.instruction.LookupOutput", source_stage: "stage2", source_claim: "stage2.instruction_lookup.claim_reduction.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage5OpeningInputPlan { symbol: "stage5.input.stage2.product_virtual.LookupOutput", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage5OpeningInputPlan { symbol: "stage5.input.stage2.instruction.LeftLookupOperand", source_stage: "stage2", source_claim: "stage2.instruction_lookup.claim_reduction.opening.LeftLookupOperand", oracle: "LeftLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage5OpeningInputPlan { symbol: "stage5.input.stage2.instruction.RightLookupOperand", source_stage: "stage2", source_claim: "stage2.instruction_lookup.claim_reduction.opening.RightLookupOperand", oracle: "RightLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage5OpeningInputPlan { symbol: "stage5.input.stage2.instruction.LookupOutput", source_stage: "stage2", source_claim: "stage2.instruction_lookup.claim_reduction.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage5OpeningInputPlan { symbol: "stage5.input.stage2.product_virtual.LookupOutput", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage5OpeningInputPlan { symbol: "stage5.input.stage2.instruction.LeftLookupOperand", source_stage: "stage2", source_claim: "stage2.instruction_lookup.claim_reduction.opening.LeftLookupOperand", oracle: "LeftLookupOperand", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage5OpeningInputPlan { symbol: "stage5.input.stage2.instruction.RightLookupOperand", source_stage: "stage2", source_claim: "stage2.instruction_lookup.claim_reduction.opening.RightLookupOperand", oracle: "RightLookupOperand", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, Stage5OpeningInputPlan { symbol: "stage5.input.stage2.ram_raf.RamRa", source_stage: "stage2", source_claim: "stage2.ram_raf.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual" }, Stage5OpeningInputPlan { symbol: "stage5.input.stage2.ram_read_write.RamRa", source_stage: "stage2", source_claim: "stage2.ram_read_write.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual" }, Stage5OpeningInputPlan { symbol: "stage5.input.stage4.ram_val_check.RamRa", source_stage: "stage4", source_claim: "stage4.ram_val_check.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual" }, - Stage5OpeningInputPlan { symbol: "stage5.input.stage4.registers.RegistersVal", source_stage: "stage4", source_claim: "stage4.registers_read_write.opening.RegistersVal", oracle: "RegistersVal", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual" }, + Stage5OpeningInputPlan { symbol: "stage5.input.stage4.registers.RegistersVal", source_stage: "stage4", source_claim: "stage4.registers_read_write.opening.RegistersVal", oracle: "RegistersVal", domain: "jolt.stage4_registers_rw_domain", point_arity: 25, claim_kind: "virtual" }, ]; pub const STAGE5_FIELD_CONSTANTS: &[Stage5FieldConstantPlan] = &[ @@ -119,9 +119,9 @@ pub const STAGE5_SUMCHECK_CLAIM_1_INPUT_OPENINGS: &[&str] = &[ pub const STAGE5_SUMCHECK_CLAIM_2_INPUT_OPENINGS: &[&str] = &["stage5.input.stage4.registers.RegistersVal"]; pub const STAGE5_SUMCHECK_CLAIMS: &[Stage5SumcheckClaimPlan] = &[ - Stage5SumcheckClaimPlan { symbol: "stage5.instruction_read_raf.input", stage: "stage5", domain: "jolt.stage5_instruction_read_raf_domain", num_rounds: 144, degree: 10, claim: "stage5.instruction_read_raf.weighted_lookup_values", kernel: Some("jolt.cpu.stage5.instruction_read_raf"), relation: None, claim_value: "stage5.instruction_read_raf.claim_expr", input_openings: STAGE5_SUMCHECK_CLAIM_0_INPUT_OPENINGS }, - Stage5SumcheckClaimPlan { symbol: "stage5.ram_ra_claim_reduction.input", stage: "stage5", domain: "jolt.trace_domain", num_rounds: 16, degree: 2, claim: "stage5.ram_ra_claim_reduction.weighted_ram_ra", kernel: Some("jolt.cpu.stage5.ram_ra_claim_reduction"), relation: None, claim_value: "stage5.ram_ra_claim_reduction.claim_expr", input_openings: STAGE5_SUMCHECK_CLAIM_1_INPUT_OPENINGS }, - Stage5SumcheckClaimPlan { symbol: "stage5.registers_val_evaluation.input", stage: "stage5", domain: "jolt.trace_domain", num_rounds: 16, degree: 3, claim: "stage5.registers_val_evaluation.registers_val", kernel: Some("jolt.cpu.stage5.registers_val_evaluation"), relation: None, claim_value: "stage5.input.stage4.registers.RegistersVal", input_openings: STAGE5_SUMCHECK_CLAIM_2_INPUT_OPENINGS }, + Stage5SumcheckClaimPlan { symbol: "stage5.instruction_read_raf.input", stage: "stage5", domain: "jolt.stage5_instruction_read_raf_domain", num_rounds: 146, degree: 10, claim: "stage5.instruction_read_raf.weighted_lookup_values", kernel: Some("jolt.cpu.stage5.instruction_read_raf"), relation: None, claim_value: "stage5.instruction_read_raf.claim_expr", input_openings: STAGE5_SUMCHECK_CLAIM_0_INPUT_OPENINGS }, + Stage5SumcheckClaimPlan { symbol: "stage5.ram_ra_claim_reduction.input", stage: "stage5", domain: "jolt.trace_domain", num_rounds: 18, degree: 2, claim: "stage5.ram_ra_claim_reduction.weighted_ram_ra", kernel: Some("jolt.cpu.stage5.ram_ra_claim_reduction"), relation: None, claim_value: "stage5.ram_ra_claim_reduction.claim_expr", input_openings: STAGE5_SUMCHECK_CLAIM_1_INPUT_OPENINGS }, + Stage5SumcheckClaimPlan { symbol: "stage5.registers_val_evaluation.input", stage: "stage5", domain: "jolt.trace_domain", num_rounds: 18, degree: 3, claim: "stage5.registers_val_evaluation.registers_val", kernel: Some("jolt.cpu.stage5.registers_val_evaluation"), relation: None, claim_value: "stage5.input.stage4.registers.RegistersVal", input_openings: STAGE5_SUMCHECK_CLAIM_2_INPUT_OPENINGS }, ]; pub const STAGE5_SUMCHECK_BATCH_0_ORDERED_CLAIMS: &[&str] = &[ "stage5.instruction_read_raf.input", @@ -137,7 +137,7 @@ pub const STAGE5_SUMCHECK_BATCH_0_CLAIM_OPERANDS: &[&str] = &[ pub const STAGE5_SUMCHECK_BATCH_0_ROUND_SCHEDULE: &[usize] = &[ 128, - 16, + 18, ]; pub const STAGE5_SUMCHECK_BATCHES: &[Stage5SumcheckBatchPlan] = &[ @@ -145,16 +145,16 @@ pub const STAGE5_SUMCHECK_BATCHES: &[Stage5SumcheckBatchPlan] = &[ ]; pub const STAGE5_SUMCHECK_DRIVER_0_ROUND_SCHEDULE: &[usize] = &[ 128, - 16, + 18, ]; pub const STAGE5_SUMCHECK_DRIVERS: &[Stage5SumcheckDriverPlan] = &[ - Stage5SumcheckDriverPlan { symbol: "stage5.sumcheck", stage: "stage5", proof_slot: "stage5.sumcheck", kernel: Some("jolt.cpu.stage5.batched"), relation: None, batch: "stage5.batch", policy: "jolt_core_stage5_aligned", round_schedule: STAGE5_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 144, degree: 10 }, + Stage5SumcheckDriverPlan { symbol: "stage5.sumcheck", stage: "stage5", proof_slot: "stage5.sumcheck", kernel: Some("jolt.cpu.stage5.batched"), relation: None, batch: "stage5.batch", policy: "jolt_core_stage5_aligned", round_schedule: STAGE5_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 146, degree: 10 }, ]; pub const STAGE5_SUMCHECK_INSTANCE_RESULTS: &[Stage5SumcheckInstanceResultPlan] = &[ - Stage5SumcheckInstanceResultPlan { symbol: "stage5.instruction_read_raf.instance", source: "stage5.sumcheck", claim: "stage5.instruction_read_raf.input", relation: "jolt.stage5.instruction_read_raf", index: 0, point_arity: 144, num_rounds: 144, round_offset: 0, point_order: "instruction_read_raf", degree: 10 }, - Stage5SumcheckInstanceResultPlan { symbol: "stage5.ram_ra_claim_reduction.instance", source: "stage5.sumcheck", claim: "stage5.ram_ra_claim_reduction.input", relation: "jolt.stage5.ram_ra_claim_reduction", index: 1, point_arity: 16, num_rounds: 16, round_offset: 128, point_order: "reverse", degree: 2 }, - Stage5SumcheckInstanceResultPlan { symbol: "stage5.registers_val_evaluation.instance", source: "stage5.sumcheck", claim: "stage5.registers_val_evaluation.input", relation: "jolt.stage5.registers_val_evaluation", index: 2, point_arity: 16, num_rounds: 16, round_offset: 128, point_order: "reverse", degree: 3 }, + Stage5SumcheckInstanceResultPlan { symbol: "stage5.instruction_read_raf.instance", source: "stage5.sumcheck", claim: "stage5.instruction_read_raf.input", relation: "jolt.stage5.instruction_read_raf", index: 0, point_arity: 146, num_rounds: 146, round_offset: 0, point_order: "instruction_read_raf", degree: 10 }, + Stage5SumcheckInstanceResultPlan { symbol: "stage5.ram_ra_claim_reduction.instance", source: "stage5.sumcheck", claim: "stage5.ram_ra_claim_reduction.input", relation: "jolt.stage5.ram_ra_claim_reduction", index: 1, point_arity: 18, num_rounds: 18, round_offset: 128, point_order: "reverse", degree: 2 }, + Stage5SumcheckInstanceResultPlan { symbol: "stage5.registers_val_evaluation.instance", source: "stage5.sumcheck", claim: "stage5.registers_val_evaluation.input", relation: "jolt.stage5.registers_val_evaluation", index: 2, point_arity: 18, num_rounds: 18, round_offset: 128, point_order: "reverse", degree: 3 }, ]; pub const STAGE5_SUMCHECK_EVALS: &[Stage5SumcheckEvalPlan] = &[ @@ -213,7 +213,7 @@ pub const STAGE5_SUMCHECK_EVALS: &[Stage5SumcheckEvalPlan] = &[ ]; pub const STAGE5_POINT_SLICES: &[Stage5PointSlicePlan] = &[ - Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.Cycle", source: "stage5.instruction_read_raf.instance", offset: 128, length: 16, input: "stage5.instruction_read_raf.instance" }, + Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.Cycle", source: "stage5.instruction_read_raf.instance", offset: 128, length: 18, input: "stage5.instruction_read_raf.instance" }, Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_0.address", source: "stage5.instruction_read_raf.instance", offset: 0, length: 16, input: "stage5.instruction_read_raf.instance" }, Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_1.address", source: "stage5.instruction_read_raf.instance", offset: 16, length: 16, input: "stage5.instruction_read_raf.instance" }, Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_2.address", source: "stage5.instruction_read_raf.instance", offset: 32, length: 16, input: "stage5.instruction_read_raf.instance" }, @@ -222,7 +222,7 @@ pub const STAGE5_POINT_SLICES: &[Stage5PointSlicePlan] = &[ Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_5.address", source: "stage5.instruction_read_raf.instance", offset: 80, length: 16, input: "stage5.instruction_read_raf.instance" }, Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_6.address", source: "stage5.instruction_read_raf.instance", offset: 96, length: 16, input: "stage5.instruction_read_raf.instance" }, Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_7.address", source: "stage5.instruction_read_raf.instance", offset: 112, length: 16, input: "stage5.instruction_read_raf.instance" }, - Stage5PointSlicePlan { symbol: "stage5.ram_ra_claim_reduction.point.RamAddress", source: "stage5.input.stage2.ram_raf.RamRa", offset: 0, length: 16, input: "stage5.input.stage2.ram_raf.RamRa" }, + Stage5PointSlicePlan { symbol: "stage5.ram_ra_claim_reduction.point.RamAddress", source: "stage5.input.stage2.ram_raf.RamRa", offset: 0, length: 14, input: "stage5.input.stage2.ram_raf.RamRa" }, Stage5PointSlicePlan { symbol: "stage5.registers_val_evaluation.point.RegisterAddress", source: "stage5.input.stage4.registers.RegistersVal", offset: 0, length: 7, input: "stage5.input.stage4.registers.RegistersVal" }, ]; @@ -277,70 +277,70 @@ pub const STAGE5_POINT_CONCAT_9_INPUTS: &[&str] = &[ ]; pub const STAGE5_POINT_CONCATS: &[Stage5PointConcatPlan] = &[ - Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_0", layout: "address_chunk_then_cycle", arity: 32, inputs: STAGE5_POINT_CONCAT_0_INPUTS }, - Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_1", layout: "address_chunk_then_cycle", arity: 32, inputs: STAGE5_POINT_CONCAT_1_INPUTS }, - Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_2", layout: "address_chunk_then_cycle", arity: 32, inputs: STAGE5_POINT_CONCAT_2_INPUTS }, - Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_3", layout: "address_chunk_then_cycle", arity: 32, inputs: STAGE5_POINT_CONCAT_3_INPUTS }, - Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_4", layout: "address_chunk_then_cycle", arity: 32, inputs: STAGE5_POINT_CONCAT_4_INPUTS }, - Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_5", layout: "address_chunk_then_cycle", arity: 32, inputs: STAGE5_POINT_CONCAT_5_INPUTS }, - Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_6", layout: "address_chunk_then_cycle", arity: 32, inputs: STAGE5_POINT_CONCAT_6_INPUTS }, - Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_7", layout: "address_chunk_then_cycle", arity: 32, inputs: STAGE5_POINT_CONCAT_7_INPUTS }, + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_0", layout: "address_chunk_then_cycle", arity: 34, inputs: STAGE5_POINT_CONCAT_0_INPUTS }, + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_1", layout: "address_chunk_then_cycle", arity: 34, inputs: STAGE5_POINT_CONCAT_1_INPUTS }, + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_2", layout: "address_chunk_then_cycle", arity: 34, inputs: STAGE5_POINT_CONCAT_2_INPUTS }, + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_3", layout: "address_chunk_then_cycle", arity: 34, inputs: STAGE5_POINT_CONCAT_3_INPUTS }, + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_4", layout: "address_chunk_then_cycle", arity: 34, inputs: STAGE5_POINT_CONCAT_4_INPUTS }, + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_5", layout: "address_chunk_then_cycle", arity: 34, inputs: STAGE5_POINT_CONCAT_5_INPUTS }, + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_6", layout: "address_chunk_then_cycle", arity: 34, inputs: STAGE5_POINT_CONCAT_6_INPUTS }, + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_7", layout: "address_chunk_then_cycle", arity: 34, inputs: STAGE5_POINT_CONCAT_7_INPUTS }, Stage5PointConcatPlan { symbol: "stage5.ram_ra_claim_reduction.point.RamRa", layout: "address_then_cycle", arity: 32, inputs: STAGE5_POINT_CONCAT_8_INPUTS }, - Stage5PointConcatPlan { symbol: "stage5.registers_val_evaluation.point.RdWa", layout: "register_address_then_cycle", arity: 23, inputs: STAGE5_POINT_CONCAT_9_INPUTS }, + Stage5PointConcatPlan { symbol: "stage5.registers_val_evaluation.point.RdWa", layout: "register_address_then_cycle", arity: 25, inputs: STAGE5_POINT_CONCAT_9_INPUTS }, ]; pub const STAGE5_OPENING_CLAIMS: &[Stage5OpeningClaimPlan] = &[ - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_0", oracle: "LookupTableFlag_0", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_0" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_1", oracle: "LookupTableFlag_1", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_1" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_2", oracle: "LookupTableFlag_2", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_2" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_3", oracle: "LookupTableFlag_3", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_3" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_4", oracle: "LookupTableFlag_4", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_4" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_5", oracle: "LookupTableFlag_5", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_5" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_6", oracle: "LookupTableFlag_6", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_6" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_7", oracle: "LookupTableFlag_7", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_7" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_8", oracle: "LookupTableFlag_8", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_8" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_9", oracle: "LookupTableFlag_9", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_9" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_10", oracle: "LookupTableFlag_10", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_10" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_11", oracle: "LookupTableFlag_11", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_11" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_12", oracle: "LookupTableFlag_12", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_12" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_13", oracle: "LookupTableFlag_13", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_13" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_14", oracle: "LookupTableFlag_14", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_14" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_15", oracle: "LookupTableFlag_15", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_15" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_16", oracle: "LookupTableFlag_16", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_16" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_17", oracle: "LookupTableFlag_17", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_17" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_18", oracle: "LookupTableFlag_18", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_18" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_19", oracle: "LookupTableFlag_19", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_19" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_20", oracle: "LookupTableFlag_20", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_20" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_21", oracle: "LookupTableFlag_21", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_21" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_22", oracle: "LookupTableFlag_22", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_22" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_23", oracle: "LookupTableFlag_23", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_23" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_24", oracle: "LookupTableFlag_24", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_24" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_25", oracle: "LookupTableFlag_25", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_25" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_26", oracle: "LookupTableFlag_26", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_26" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_27", oracle: "LookupTableFlag_27", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_27" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_28", oracle: "LookupTableFlag_28", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_28" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_29", oracle: "LookupTableFlag_29", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_29" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_30", oracle: "LookupTableFlag_30", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_30" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_31", oracle: "LookupTableFlag_31", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_31" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_32", oracle: "LookupTableFlag_32", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_32" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_33", oracle: "LookupTableFlag_33", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_33" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_34", oracle: "LookupTableFlag_34", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_34" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_35", oracle: "LookupTableFlag_35", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_35" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_36", oracle: "LookupTableFlag_36", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_36" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_37", oracle: "LookupTableFlag_37", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_37" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_38", oracle: "LookupTableFlag_38", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_38" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_39", oracle: "LookupTableFlag_39", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_39" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_0", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_0" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_1", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_1" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_2", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_2" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_3", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_3" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_4", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_4" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_5", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_5" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_6", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_6" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_7", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_7" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRafFlag", oracle: "InstructionRafFlag", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.InstructionRafFlag" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_0", oracle: "LookupTableFlag_0", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_0" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_1", oracle: "LookupTableFlag_1", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_1" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_2", oracle: "LookupTableFlag_2", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_2" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_3", oracle: "LookupTableFlag_3", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_3" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_4", oracle: "LookupTableFlag_4", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_4" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_5", oracle: "LookupTableFlag_5", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_5" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_6", oracle: "LookupTableFlag_6", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_6" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_7", oracle: "LookupTableFlag_7", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_7" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_8", oracle: "LookupTableFlag_8", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_8" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_9", oracle: "LookupTableFlag_9", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_9" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_10", oracle: "LookupTableFlag_10", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_10" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_11", oracle: "LookupTableFlag_11", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_11" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_12", oracle: "LookupTableFlag_12", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_12" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_13", oracle: "LookupTableFlag_13", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_13" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_14", oracle: "LookupTableFlag_14", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_14" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_15", oracle: "LookupTableFlag_15", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_15" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_16", oracle: "LookupTableFlag_16", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_16" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_17", oracle: "LookupTableFlag_17", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_17" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_18", oracle: "LookupTableFlag_18", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_18" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_19", oracle: "LookupTableFlag_19", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_19" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_20", oracle: "LookupTableFlag_20", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_20" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_21", oracle: "LookupTableFlag_21", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_21" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_22", oracle: "LookupTableFlag_22", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_22" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_23", oracle: "LookupTableFlag_23", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_23" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_24", oracle: "LookupTableFlag_24", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_24" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_25", oracle: "LookupTableFlag_25", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_25" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_26", oracle: "LookupTableFlag_26", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_26" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_27", oracle: "LookupTableFlag_27", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_27" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_28", oracle: "LookupTableFlag_28", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_28" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_29", oracle: "LookupTableFlag_29", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_29" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_30", oracle: "LookupTableFlag_30", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_30" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_31", oracle: "LookupTableFlag_31", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_31" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_32", oracle: "LookupTableFlag_32", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_32" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_33", oracle: "LookupTableFlag_33", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_33" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_34", oracle: "LookupTableFlag_34", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_34" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_35", oracle: "LookupTableFlag_35", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_35" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_36", oracle: "LookupTableFlag_36", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_36" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_37", oracle: "LookupTableFlag_37", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_37" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_38", oracle: "LookupTableFlag_38", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_38" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_39", oracle: "LookupTableFlag_39", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_39" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_0", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_0" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_1", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_1" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_2", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_2" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_3", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_3" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_4", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_4" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_5", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_5" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_6", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_6" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_7", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_7" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRafFlag", oracle: "InstructionRafFlag", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.InstructionRafFlag" }, Stage5OpeningClaimPlan { symbol: "stage5.ram_ra_claim_reduction.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.ram_ra_claim_reduction.point.RamRa", eval_source: "stage5.ram_ra_claim_reduction.eval.RamRa" }, - Stage5OpeningClaimPlan { symbol: "stage5.registers_val_evaluation.opening.RdInc", oracle: "RdInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed", point_source: "stage5.registers_val_evaluation.instance", eval_source: "stage5.registers_val_evaluation.eval.RdInc" }, - Stage5OpeningClaimPlan { symbol: "stage5.registers_val_evaluation.opening.RdWa", oracle: "RdWa", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual", point_source: "stage5.registers_val_evaluation.point.RdWa", eval_source: "stage5.registers_val_evaluation.eval.RdWa" }, + Stage5OpeningClaimPlan { symbol: "stage5.registers_val_evaluation.opening.RdInc", oracle: "RdInc", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "committed", point_source: "stage5.registers_val_evaluation.instance", eval_source: "stage5.registers_val_evaluation.eval.RdInc" }, + Stage5OpeningClaimPlan { symbol: "stage5.registers_val_evaluation.opening.RdWa", oracle: "RdWa", domain: "jolt.stage4_registers_rw_domain", point_arity: 25, claim_kind: "virtual", point_source: "stage5.registers_val_evaluation.point.RdWa", eval_source: "stage5.registers_val_evaluation.eval.RdWa" }, ]; pub const STAGE5_OPENING_EQUALITIES: &[Stage5OpeningClaimEqualityPlan] = &[ diff --git a/crates/jolt-prover/src/stages/stage6.rs b/crates/jolt-prover/src/stages/stage6.rs index bf0d368c7b..2a5c837b2c 100644 --- a/crates/jolt-prover/src/stages/stage6.rs +++ b/crates/jolt-prover/src/stages/stage6.rs @@ -41,96 +41,96 @@ pub const STAGE6_TRANSCRIPT_ABSORB_BYTES: &[Stage6TranscriptAbsorbBytesPlan] = & ]; pub const STAGE6_OPENING_INPUTS: &[Stage6OpeningInputPlan] = &[ - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.UnexpandedPC", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.UnexpandedPC", oracle: "UnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.Imm", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.Imm", oracle: "Imm", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagAddOperands", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagAddOperands", oracle: "OpFlagAddOperands", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagSubtractOperands", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagSubtractOperands", oracle: "OpFlagSubtractOperands", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagMultiplyOperands", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagMultiplyOperands", oracle: "OpFlagMultiplyOperands", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagLoad", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagLoad", oracle: "OpFlagLoad", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagStore", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagStore", oracle: "OpFlagStore", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagJump", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagJump", oracle: "OpFlagJump", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagWriteLookupOutputToRD", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagWriteLookupOutputToRD", oracle: "OpFlagWriteLookupOutputToRD", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagVirtualInstruction", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagAssert", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagAssert", oracle: "OpFlagAssert", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagDoNotUpdateUnexpandedPC", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagDoNotUpdateUnexpandedPC", oracle: "OpFlagDoNotUpdateUnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagAdvice", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagAdvice", oracle: "OpFlagAdvice", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagIsCompressed", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagIsCompressed", oracle: "OpFlagIsCompressed", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagIsFirstInSequence", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagIsFirstInSequence", oracle: "OpFlagIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagIsLastInSequence", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagIsLastInSequence", oracle: "OpFlagIsLastInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage2.OpFlagJump", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.OpFlagJump", oracle: "OpFlagJump", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage2.InstructionFlagBranch", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.InstructionFlagBranch", oracle: "InstructionFlagBranch", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage2.OpFlagWriteLookupOutputToRD", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.OpFlagWriteLookupOutputToRD", oracle: "OpFlagWriteLookupOutputToRD", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage2.OpFlagVirtualInstruction", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage3.instruction_input.Imm", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.Imm", oracle: "Imm", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage3.spartan_shift.UnexpandedPC", source_stage: "stage3", source_claim: "stage3.spartan_shift.opening.UnexpandedPC", oracle: "UnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage3.instruction_input.InstructionFlagLeftOperandIsRs1Value", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.InstructionFlagLeftOperandIsRs1Value", oracle: "InstructionFlagLeftOperandIsRs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage3.instruction_input.InstructionFlagLeftOperandIsPC", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.InstructionFlagLeftOperandIsPC", oracle: "InstructionFlagLeftOperandIsPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage3.instruction_input.InstructionFlagRightOperandIsRs2Value", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.InstructionFlagRightOperandIsRs2Value", oracle: "InstructionFlagRightOperandIsRs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage3.instruction_input.InstructionFlagRightOperandIsImm", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.InstructionFlagRightOperandIsImm", oracle: "InstructionFlagRightOperandIsImm", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage3.spartan_shift.InstructionFlagIsNoop", source_stage: "stage3", source_claim: "stage3.spartan_shift.opening.InstructionFlagIsNoop", oracle: "InstructionFlagIsNoop", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage3.spartan_shift.OpFlagVirtualInstruction", source_stage: "stage3", source_claim: "stage3.spartan_shift.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage3.spartan_shift.OpFlagIsFirstInSequence", source_stage: "stage3", source_claim: "stage3.spartan_shift.opening.OpFlagIsFirstInSequence", oracle: "OpFlagIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage4.RdWa", source_stage: "stage4", source_claim: "stage4.registers_read_write.opening.RdWa", oracle: "RdWa", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage4.Rs1Ra", source_stage: "stage4", source_claim: "stage4.registers_read_write.opening.Rs1Ra", oracle: "Rs1Ra", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage4.Rs2Ra", source_stage: "stage4", source_claim: "stage4.registers_read_write.opening.Rs2Ra", oracle: "Rs2Ra", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.registers_val_evaluation.RdWa", source_stage: "stage5", source_claim: "stage5.registers_val_evaluation.opening.RdWa", oracle: "RdWa", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.InstructionRafFlag", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRafFlag", oracle: "InstructionRafFlag", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_0", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_0", oracle: "LookupTableFlag_0", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_1", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_1", oracle: "LookupTableFlag_1", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_2", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_2", oracle: "LookupTableFlag_2", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_3", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_3", oracle: "LookupTableFlag_3", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_4", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_4", oracle: "LookupTableFlag_4", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_5", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_5", oracle: "LookupTableFlag_5", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_6", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_6", oracle: "LookupTableFlag_6", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_7", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_7", oracle: "LookupTableFlag_7", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_8", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_8", oracle: "LookupTableFlag_8", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_9", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_9", oracle: "LookupTableFlag_9", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_10", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_10", oracle: "LookupTableFlag_10", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_11", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_11", oracle: "LookupTableFlag_11", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_12", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_12", oracle: "LookupTableFlag_12", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_13", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_13", oracle: "LookupTableFlag_13", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_14", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_14", oracle: "LookupTableFlag_14", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_15", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_15", oracle: "LookupTableFlag_15", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_16", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_16", oracle: "LookupTableFlag_16", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_17", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_17", oracle: "LookupTableFlag_17", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_18", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_18", oracle: "LookupTableFlag_18", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_19", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_19", oracle: "LookupTableFlag_19", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_20", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_20", oracle: "LookupTableFlag_20", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_21", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_21", oracle: "LookupTableFlag_21", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_22", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_22", oracle: "LookupTableFlag_22", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_23", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_23", oracle: "LookupTableFlag_23", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_24", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_24", oracle: "LookupTableFlag_24", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_25", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_25", oracle: "LookupTableFlag_25", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_26", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_26", oracle: "LookupTableFlag_26", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_27", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_27", oracle: "LookupTableFlag_27", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_28", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_28", oracle: "LookupTableFlag_28", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_29", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_29", oracle: "LookupTableFlag_29", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_30", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_30", oracle: "LookupTableFlag_30", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_31", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_31", oracle: "LookupTableFlag_31", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_32", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_32", oracle: "LookupTableFlag_32", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_33", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_33", oracle: "LookupTableFlag_33", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_34", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_34", oracle: "LookupTableFlag_34", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_35", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_35", oracle: "LookupTableFlag_35", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_36", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_36", oracle: "LookupTableFlag_36", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_37", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_37", oracle: "LookupTableFlag_37", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_38", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_38", oracle: "LookupTableFlag_38", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_39", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_39", oracle: "LookupTableFlag_39", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.PC", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.PC", oracle: "PC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage3.spartan_shift.PC", source_stage: "stage3", source_claim: "stage3.spartan_shift.opening.PC", oracle: "PC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.UnexpandedPC", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.UnexpandedPC", oracle: "UnexpandedPC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.Imm", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.Imm", oracle: "Imm", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagAddOperands", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagAddOperands", oracle: "OpFlagAddOperands", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagSubtractOperands", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagSubtractOperands", oracle: "OpFlagSubtractOperands", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagMultiplyOperands", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagMultiplyOperands", oracle: "OpFlagMultiplyOperands", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagLoad", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagLoad", oracle: "OpFlagLoad", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagStore", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagStore", oracle: "OpFlagStore", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagJump", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagJump", oracle: "OpFlagJump", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagWriteLookupOutputToRD", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagWriteLookupOutputToRD", oracle: "OpFlagWriteLookupOutputToRD", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagVirtualInstruction", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagAssert", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagAssert", oracle: "OpFlagAssert", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagDoNotUpdateUnexpandedPC", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagDoNotUpdateUnexpandedPC", oracle: "OpFlagDoNotUpdateUnexpandedPC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagAdvice", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagAdvice", oracle: "OpFlagAdvice", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagIsCompressed", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagIsCompressed", oracle: "OpFlagIsCompressed", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagIsFirstInSequence", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagIsFirstInSequence", oracle: "OpFlagIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagIsLastInSequence", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagIsLastInSequence", oracle: "OpFlagIsLastInSequence", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage2.OpFlagJump", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.OpFlagJump", oracle: "OpFlagJump", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage2.InstructionFlagBranch", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.InstructionFlagBranch", oracle: "InstructionFlagBranch", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage2.OpFlagWriteLookupOutputToRD", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.OpFlagWriteLookupOutputToRD", oracle: "OpFlagWriteLookupOutputToRD", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage2.OpFlagVirtualInstruction", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.instruction_input.Imm", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.Imm", oracle: "Imm", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.spartan_shift.UnexpandedPC", source_stage: "stage3", source_claim: "stage3.spartan_shift.opening.UnexpandedPC", oracle: "UnexpandedPC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.instruction_input.InstructionFlagLeftOperandIsRs1Value", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.InstructionFlagLeftOperandIsRs1Value", oracle: "InstructionFlagLeftOperandIsRs1Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.instruction_input.InstructionFlagLeftOperandIsPC", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.InstructionFlagLeftOperandIsPC", oracle: "InstructionFlagLeftOperandIsPC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.instruction_input.InstructionFlagRightOperandIsRs2Value", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.InstructionFlagRightOperandIsRs2Value", oracle: "InstructionFlagRightOperandIsRs2Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.instruction_input.InstructionFlagRightOperandIsImm", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.InstructionFlagRightOperandIsImm", oracle: "InstructionFlagRightOperandIsImm", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.spartan_shift.InstructionFlagIsNoop", source_stage: "stage3", source_claim: "stage3.spartan_shift.opening.InstructionFlagIsNoop", oracle: "InstructionFlagIsNoop", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.spartan_shift.OpFlagVirtualInstruction", source_stage: "stage3", source_claim: "stage3.spartan_shift.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.spartan_shift.OpFlagIsFirstInSequence", source_stage: "stage3", source_claim: "stage3.spartan_shift.opening.OpFlagIsFirstInSequence", oracle: "OpFlagIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage4.RdWa", source_stage: "stage4", source_claim: "stage4.registers_read_write.opening.RdWa", oracle: "RdWa", domain: "jolt.stage4_registers_rw_domain", point_arity: 25, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage4.Rs1Ra", source_stage: "stage4", source_claim: "stage4.registers_read_write.opening.Rs1Ra", oracle: "Rs1Ra", domain: "jolt.stage4_registers_rw_domain", point_arity: 25, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage4.Rs2Ra", source_stage: "stage4", source_claim: "stage4.registers_read_write.opening.Rs2Ra", oracle: "Rs2Ra", domain: "jolt.stage4_registers_rw_domain", point_arity: 25, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.registers_val_evaluation.RdWa", source_stage: "stage5", source_claim: "stage5.registers_val_evaluation.opening.RdWa", oracle: "RdWa", domain: "jolt.stage4_registers_rw_domain", point_arity: 25, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.InstructionRafFlag", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRafFlag", oracle: "InstructionRafFlag", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_0", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_0", oracle: "LookupTableFlag_0", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_1", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_1", oracle: "LookupTableFlag_1", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_2", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_2", oracle: "LookupTableFlag_2", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_3", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_3", oracle: "LookupTableFlag_3", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_4", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_4", oracle: "LookupTableFlag_4", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_5", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_5", oracle: "LookupTableFlag_5", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_6", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_6", oracle: "LookupTableFlag_6", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_7", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_7", oracle: "LookupTableFlag_7", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_8", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_8", oracle: "LookupTableFlag_8", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_9", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_9", oracle: "LookupTableFlag_9", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_10", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_10", oracle: "LookupTableFlag_10", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_11", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_11", oracle: "LookupTableFlag_11", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_12", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_12", oracle: "LookupTableFlag_12", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_13", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_13", oracle: "LookupTableFlag_13", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_14", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_14", oracle: "LookupTableFlag_14", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_15", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_15", oracle: "LookupTableFlag_15", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_16", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_16", oracle: "LookupTableFlag_16", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_17", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_17", oracle: "LookupTableFlag_17", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_18", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_18", oracle: "LookupTableFlag_18", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_19", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_19", oracle: "LookupTableFlag_19", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_20", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_20", oracle: "LookupTableFlag_20", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_21", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_21", oracle: "LookupTableFlag_21", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_22", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_22", oracle: "LookupTableFlag_22", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_23", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_23", oracle: "LookupTableFlag_23", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_24", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_24", oracle: "LookupTableFlag_24", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_25", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_25", oracle: "LookupTableFlag_25", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_26", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_26", oracle: "LookupTableFlag_26", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_27", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_27", oracle: "LookupTableFlag_27", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_28", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_28", oracle: "LookupTableFlag_28", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_29", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_29", oracle: "LookupTableFlag_29", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_30", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_30", oracle: "LookupTableFlag_30", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_31", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_31", oracle: "LookupTableFlag_31", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_32", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_32", oracle: "LookupTableFlag_32", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_33", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_33", oracle: "LookupTableFlag_33", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_34", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_34", oracle: "LookupTableFlag_34", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_35", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_35", oracle: "LookupTableFlag_35", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_36", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_36", oracle: "LookupTableFlag_36", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_37", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_37", oracle: "LookupTableFlag_37", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_38", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_38", oracle: "LookupTableFlag_38", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_39", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_39", oracle: "LookupTableFlag_39", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.PC", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.PC", oracle: "PC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.spartan_shift.PC", source_stage: "stage3", source_claim: "stage3.spartan_shift.opening.PC", oracle: "PC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, Stage6OpeningInputPlan { symbol: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", source_stage: "stage5", source_claim: "stage5.ram_ra_claim_reduction.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_1", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_2", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_3", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_4", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_5", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_6", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_7", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.LookupOutput", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage2.ram_read_write.RamInc", source_stage: "stage2", source_claim: "stage2.ram_read_write.opening.RamInc", oracle: "RamInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage4.ram_val_check.RamInc", source_stage: "stage4", source_claim: "stage4.ram_val_check.opening.RamInc", oracle: "RamInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage4.registers_read_write.RdInc", source_stage: "stage4", source_claim: "stage4.registers_read_write.opening.RdInc", oracle: "RdInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.registers_val_evaluation.RdInc", source_stage: "stage5", source_claim: "stage5.registers_val_evaluation.opening.RdInc", oracle: "RdInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_1", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_2", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_3", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_4", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_5", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_6", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_7", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.LookupOutput", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage2.ram_read_write.RamInc", source_stage: "stage2", source_claim: "stage2.ram_read_write.opening.RamInc", oracle: "RamInc", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "committed" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage4.ram_val_check.RamInc", source_stage: "stage4", source_claim: "stage4.ram_val_check.opening.RamInc", oracle: "RamInc", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "committed" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage4.registers_read_write.RdInc", source_stage: "stage4", source_claim: "stage4.registers_read_write.opening.RdInc", oracle: "RdInc", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "committed" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.registers_val_evaluation.RdInc", source_stage: "stage5", source_claim: "stage5.registers_val_evaluation.opening.RdInc", oracle: "RdInc", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "committed" }, ]; pub const STAGE6_FIELD_CONSTANTS: &[Stage6FieldConstantPlan] = &[ @@ -1320,6 +1320,7 @@ pub const STAGE6_FIELD_EXPRS: &[Stage6FieldExprPlan] = &[ Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_36", kind: "op", formula: "field.pow:72", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_37", kind: "op", formula: "field.pow:74", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_38", kind: "op", formula: "field.pow:76", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_sq_39", kind: "op", formula: "field.pow:78", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_0", kind: "op", formula: "field.pow:0", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_1", kind: "op", formula: "field.pow:1", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_2", kind: "op", formula: "field.pow:2", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, @@ -1359,6 +1360,7 @@ pub const STAGE6_FIELD_EXPRS: &[Stage6FieldExprPlan] = &[ Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_36", kind: "op", formula: "field.pow:36", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_37", kind: "op", formula: "field.pow:37", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_38", kind: "op", formula: "field.pow:38", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, + Stage6FieldExprPlan { symbol: "stage6.booleanity.gamma_pow_39", kind: "op", formula: "field.pow:39", operand_names: STAGE6_FIELD_EXPR_OPERANDS_0, operands: STAGE6_FIELD_EXPR_OPERANDS_0 }, Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term1.stage_gamma_pow", kind: "op", formula: "field.pow:1", operand_names: STAGE6_FIELD_EXPR_OPERANDS_1, operands: STAGE6_FIELD_EXPR_OPERANDS_1 }, Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term1.stage_gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE6_FIELD_EXPR_OPERANDS_2, operands: STAGE6_FIELD_EXPR_OPERANDS_2 }, Stage6FieldExprPlan { symbol: "stage6.bytecode_read_raf.claim.term2.stage_gamma_pow", kind: "op", formula: "field.pow:2", operand_names: STAGE6_FIELD_EXPR_OPERANDS_1, operands: STAGE6_FIELD_EXPR_OPERANDS_1 }, @@ -1839,12 +1841,12 @@ pub const STAGE6_SUMCHECK_CLAIM_5_INPUT_OPENINGS: &[&str] = &[ ]; pub const STAGE6_SUMCHECK_CLAIMS: &[Stage6SumcheckClaimPlan] = &[ - Stage6SumcheckClaimPlan { symbol: "stage6.bytecode_read_raf.input", stage: "stage6", domain: "jolt.stage6_bytecode_read_raf_domain", num_rounds: 26, degree: 4, claim: "stage6.bytecode_read_raf.weighted_prior_stage_values", kernel: Some("jolt.cpu.stage6.bytecode_read_raf"), relation: None, claim_value: "stage6.bytecode_read_raf.claim_expr.partial75", input_openings: STAGE6_SUMCHECK_CLAIM_0_INPUT_OPENINGS }, - Stage6SumcheckClaimPlan { symbol: "stage6.booleanity.input", stage: "stage6", domain: "jolt.stage6_booleanity_domain", num_rounds: 20, degree: 3, claim: "stage6.booleanity.zero", kernel: Some("jolt.cpu.stage6.booleanity"), relation: None, claim_value: "stage6.zero", input_openings: STAGE6_SUMCHECK_CLAIM_1_INPUT_OPENINGS }, - Stage6SumcheckClaimPlan { symbol: "stage6.hamming_booleanity.input", stage: "stage6", domain: "jolt.trace_domain", num_rounds: 16, degree: 3, claim: "stage6.hamming_booleanity.zero", kernel: Some("jolt.cpu.stage6.hamming_booleanity"), relation: None, claim_value: "stage6.zero", input_openings: STAGE6_SUMCHECK_CLAIM_2_INPUT_OPENINGS }, - Stage6SumcheckClaimPlan { symbol: "stage6.ram_ra_virtual.input", stage: "stage6", domain: "jolt.trace_domain", num_rounds: 16, degree: 5, claim: "stage6.ram_ra_virtual.weighted_ram_ra", kernel: Some("jolt.cpu.stage6.ram_ra_virtual"), relation: None, claim_value: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", input_openings: STAGE6_SUMCHECK_CLAIM_3_INPUT_OPENINGS }, - Stage6SumcheckClaimPlan { symbol: "stage6.instruction_ra_virtual.input", stage: "stage6", domain: "jolt.trace_domain", num_rounds: 16, degree: 5, claim: "stage6.instruction_ra_virtual.weighted_instruction_ra", kernel: Some("jolt.cpu.stage6.instruction_ra_virtual"), relation: None, claim_value: "stage6.instruction_ra_virtual.claim_expr.partial6", input_openings: STAGE6_SUMCHECK_CLAIM_4_INPUT_OPENINGS }, - Stage6SumcheckClaimPlan { symbol: "stage6.inc_claim_reduction.input", stage: "stage6", domain: "jolt.trace_domain", num_rounds: 16, degree: 2, claim: "stage6.inc_claim_reduction.weighted_increments", kernel: Some("jolt.cpu.stage6.inc_claim_reduction"), relation: None, claim_value: "stage6.inc_claim_reduction.claim_expr.partial2", input_openings: STAGE6_SUMCHECK_CLAIM_5_INPUT_OPENINGS }, + Stage6SumcheckClaimPlan { symbol: "stage6.bytecode_read_raf.input", stage: "stage6", domain: "jolt.stage6_bytecode_read_raf_domain", num_rounds: 32, degree: 5, claim: "stage6.bytecode_read_raf.weighted_prior_stage_values", kernel: Some("jolt.cpu.stage6.bytecode_read_raf"), relation: None, claim_value: "stage6.bytecode_read_raf.claim_expr.partial75", input_openings: STAGE6_SUMCHECK_CLAIM_0_INPUT_OPENINGS }, + Stage6SumcheckClaimPlan { symbol: "stage6.booleanity.input", stage: "stage6", domain: "jolt.stage6_booleanity_domain", num_rounds: 22, degree: 3, claim: "stage6.booleanity.zero", kernel: Some("jolt.cpu.stage6.booleanity"), relation: None, claim_value: "stage6.zero", input_openings: STAGE6_SUMCHECK_CLAIM_1_INPUT_OPENINGS }, + Stage6SumcheckClaimPlan { symbol: "stage6.hamming_booleanity.input", stage: "stage6", domain: "jolt.trace_domain", num_rounds: 18, degree: 3, claim: "stage6.hamming_booleanity.zero", kernel: Some("jolt.cpu.stage6.hamming_booleanity"), relation: None, claim_value: "stage6.zero", input_openings: STAGE6_SUMCHECK_CLAIM_2_INPUT_OPENINGS }, + Stage6SumcheckClaimPlan { symbol: "stage6.ram_ra_virtual.input", stage: "stage6", domain: "jolt.trace_domain", num_rounds: 18, degree: 5, claim: "stage6.ram_ra_virtual.weighted_ram_ra", kernel: Some("jolt.cpu.stage6.ram_ra_virtual"), relation: None, claim_value: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", input_openings: STAGE6_SUMCHECK_CLAIM_3_INPUT_OPENINGS }, + Stage6SumcheckClaimPlan { symbol: "stage6.instruction_ra_virtual.input", stage: "stage6", domain: "jolt.trace_domain", num_rounds: 18, degree: 5, claim: "stage6.instruction_ra_virtual.weighted_instruction_ra", kernel: Some("jolt.cpu.stage6.instruction_ra_virtual"), relation: None, claim_value: "stage6.instruction_ra_virtual.claim_expr.partial6", input_openings: STAGE6_SUMCHECK_CLAIM_4_INPUT_OPENINGS }, + Stage6SumcheckClaimPlan { symbol: "stage6.inc_claim_reduction.input", stage: "stage6", domain: "jolt.trace_domain", num_rounds: 18, degree: 2, claim: "stage6.inc_claim_reduction.weighted_increments", kernel: Some("jolt.cpu.stage6.inc_claim_reduction"), relation: None, claim_value: "stage6.inc_claim_reduction.claim_expr.partial2", input_openings: STAGE6_SUMCHECK_CLAIM_5_INPUT_OPENINGS }, ]; pub const STAGE6_SUMCHECK_BATCH_0_ORDERED_CLAIMS: &[&str] = &[ "stage6.bytecode_read_raf.input", @@ -1865,28 +1867,28 @@ pub const STAGE6_SUMCHECK_BATCH_0_CLAIM_OPERANDS: &[&str] = &[ ]; pub const STAGE6_SUMCHECK_BATCH_0_ROUND_SCHEDULE: &[usize] = &[ - 10, - 16, + 14, + 18, ]; pub const STAGE6_SUMCHECK_BATCHES: &[Stage6SumcheckBatchPlan] = &[ Stage6SumcheckBatchPlan { symbol: "stage6.batch", stage: "stage6", proof_slot: "stage6.sumcheck", policy: "jolt_core_stage6_aligned", count: 6, ordered_claims: STAGE6_SUMCHECK_BATCH_0_ORDERED_CLAIMS, claim_operands: STAGE6_SUMCHECK_BATCH_0_CLAIM_OPERANDS, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", round_schedule: STAGE6_SUMCHECK_BATCH_0_ROUND_SCHEDULE }, ]; pub const STAGE6_SUMCHECK_DRIVER_0_ROUND_SCHEDULE: &[usize] = &[ - 10, - 16, + 14, + 18, ]; pub const STAGE6_SUMCHECK_DRIVERS: &[Stage6SumcheckDriverPlan] = &[ - Stage6SumcheckDriverPlan { symbol: "stage6.sumcheck", stage: "stage6", proof_slot: "stage6.sumcheck", kernel: Some("jolt.cpu.stage6.batched"), relation: None, batch: "stage6.batch", policy: "jolt_core_stage6_aligned", round_schedule: STAGE6_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 26, degree: 5 }, + Stage6SumcheckDriverPlan { symbol: "stage6.sumcheck", stage: "stage6", proof_slot: "stage6.sumcheck", kernel: Some("jolt.cpu.stage6.batched"), relation: None, batch: "stage6.batch", policy: "jolt_core_stage6_aligned", round_schedule: STAGE6_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 32, degree: 5 }, ]; pub const STAGE6_SUMCHECK_INSTANCE_RESULTS: &[Stage6SumcheckInstanceResultPlan] = &[ - Stage6SumcheckInstanceResultPlan { symbol: "stage6.bytecode_read_raf.instance", source: "stage6.sumcheck", claim: "stage6.bytecode_read_raf.input", relation: "jolt.stage6.bytecode_read_raf", index: 0, point_arity: 26, num_rounds: 26, round_offset: 0, point_order: "bytecode_read_raf", degree: 4 }, - Stage6SumcheckInstanceResultPlan { symbol: "stage6.booleanity.instance", source: "stage6.sumcheck", claim: "stage6.booleanity.input", relation: "jolt.stage6.booleanity", index: 1, point_arity: 20, num_rounds: 20, round_offset: 6, point_order: "stage6_booleanity", degree: 3 }, - Stage6SumcheckInstanceResultPlan { symbol: "stage6.hamming_booleanity.instance", source: "stage6.sumcheck", claim: "stage6.hamming_booleanity.input", relation: "jolt.stage6.hamming_booleanity", index: 2, point_arity: 16, num_rounds: 16, round_offset: 10, point_order: "reverse", degree: 3 }, - Stage6SumcheckInstanceResultPlan { symbol: "stage6.ram_ra_virtual.instance", source: "stage6.sumcheck", claim: "stage6.ram_ra_virtual.input", relation: "jolt.stage6.ram_ra_virtual", index: 3, point_arity: 16, num_rounds: 16, round_offset: 10, point_order: "reverse", degree: 5 }, - Stage6SumcheckInstanceResultPlan { symbol: "stage6.instruction_ra_virtual.instance", source: "stage6.sumcheck", claim: "stage6.instruction_ra_virtual.input", relation: "jolt.stage6.instruction_ra_virtual", index: 4, point_arity: 16, num_rounds: 16, round_offset: 10, point_order: "reverse", degree: 5 }, - Stage6SumcheckInstanceResultPlan { symbol: "stage6.inc_claim_reduction.instance", source: "stage6.sumcheck", claim: "stage6.inc_claim_reduction.input", relation: "jolt.stage6.inc_claim_reduction", index: 5, point_arity: 16, num_rounds: 16, round_offset: 10, point_order: "reverse", degree: 2 }, + Stage6SumcheckInstanceResultPlan { symbol: "stage6.bytecode_read_raf.instance", source: "stage6.sumcheck", claim: "stage6.bytecode_read_raf.input", relation: "jolt.stage6.bytecode_read_raf", index: 0, point_arity: 32, num_rounds: 32, round_offset: 0, point_order: "bytecode_read_raf", degree: 5 }, + Stage6SumcheckInstanceResultPlan { symbol: "stage6.booleanity.instance", source: "stage6.sumcheck", claim: "stage6.booleanity.input", relation: "jolt.stage6.booleanity", index: 1, point_arity: 22, num_rounds: 22, round_offset: 10, point_order: "stage6_booleanity", degree: 3 }, + Stage6SumcheckInstanceResultPlan { symbol: "stage6.hamming_booleanity.instance", source: "stage6.sumcheck", claim: "stage6.hamming_booleanity.input", relation: "jolt.stage6.hamming_booleanity", index: 2, point_arity: 18, num_rounds: 18, round_offset: 14, point_order: "reverse", degree: 3 }, + Stage6SumcheckInstanceResultPlan { symbol: "stage6.ram_ra_virtual.instance", source: "stage6.sumcheck", claim: "stage6.ram_ra_virtual.input", relation: "jolt.stage6.ram_ra_virtual", index: 3, point_arity: 18, num_rounds: 18, round_offset: 14, point_order: "reverse", degree: 5 }, + Stage6SumcheckInstanceResultPlan { symbol: "stage6.instruction_ra_virtual.instance", source: "stage6.sumcheck", claim: "stage6.instruction_ra_virtual.input", relation: "jolt.stage6.instruction_ra_virtual", index: 4, point_arity: 18, num_rounds: 18, round_offset: 14, point_order: "reverse", degree: 5 }, + Stage6SumcheckInstanceResultPlan { symbol: "stage6.inc_claim_reduction.instance", source: "stage6.sumcheck", claim: "stage6.inc_claim_reduction.input", relation: "jolt.stage6.inc_claim_reduction", index: 5, point_arity: 18, num_rounds: 18, round_offset: 14, point_order: "reverse", degree: 2 }, ]; macro_rules! stage6_sumcheck_eval { @@ -1897,42 +1899,44 @@ macro_rules! stage6_sumcheck_eval { #[rustfmt::skip] pub const STAGE6_SUMCHECK_EVALS: &[Stage6SumcheckEvalPlan] = &[ - stage6_sumcheck_eval!("stage6.bytecode_read_raf.eval.BytecodeRa_0", "stage6.sumcheck", "stage6.bytecode_read_raf.eval.BytecodeRa_0", 0, "BytecodeRa_0"), stage6_sumcheck_eval!("stage6.bytecode_read_raf.eval.BytecodeRa_1", "stage6.sumcheck", "stage6.bytecode_read_raf.eval.BytecodeRa_1", 1, "BytecodeRa_1"), stage6_sumcheck_eval!("stage6.bytecode_read_raf.eval.BytecodeRa_2", "stage6.sumcheck", "stage6.bytecode_read_raf.eval.BytecodeRa_2", 2, "BytecodeRa_2"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_0", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_0", 0, "InstructionRa_0"), - stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_1", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_1", 1, "InstructionRa_1"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_2", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_2", 2, "InstructionRa_2"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_3", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_3", 3, "InstructionRa_3"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_4", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_4", 4, "InstructionRa_4"), - stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_5", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_5", 5, "InstructionRa_5"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_6", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_6", 6, "InstructionRa_6"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_7", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_7", 7, "InstructionRa_7"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_8", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_8", 8, "InstructionRa_8"), - stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_9", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_9", 9, "InstructionRa_9"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_10", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_10", 10, "InstructionRa_10"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_11", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_11", 11, "InstructionRa_11"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_12", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_12", 12, "InstructionRa_12"), - stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_13", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_13", 13, "InstructionRa_13"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_14", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_14", 14, "InstructionRa_14"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_15", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_15", 15, "InstructionRa_15"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_16", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_16", 16, "InstructionRa_16"), - stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_17", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_17", 17, "InstructionRa_17"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_18", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_18", 18, "InstructionRa_18"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_19", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_19", 19, "InstructionRa_19"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_20", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_20", 20, "InstructionRa_20"), - stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_21", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_21", 21, "InstructionRa_21"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_22", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_22", 22, "InstructionRa_22"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_23", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_23", 23, "InstructionRa_23"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_24", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_24", 24, "InstructionRa_24"), - stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_25", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_25", 25, "InstructionRa_25"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_26", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_26", 26, "InstructionRa_26"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_27", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_27", 27, "InstructionRa_27"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_28", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_28", 28, "InstructionRa_28"), - stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_29", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_29", 29, "InstructionRa_29"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_30", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_30", 30, "InstructionRa_30"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_31", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_31", 31, "InstructionRa_31"), stage6_sumcheck_eval!("stage6.booleanity.eval.BytecodeRa_0", "stage6.sumcheck", "stage6.booleanity.eval.BytecodeRa_0", 32, "BytecodeRa_0"), - stage6_sumcheck_eval!("stage6.booleanity.eval.BytecodeRa_1", "stage6.sumcheck", "stage6.booleanity.eval.BytecodeRa_1", 33, "BytecodeRa_1"), stage6_sumcheck_eval!("stage6.booleanity.eval.BytecodeRa_2", "stage6.sumcheck", "stage6.booleanity.eval.BytecodeRa_2", 34, "BytecodeRa_2"), stage6_sumcheck_eval!("stage6.booleanity.eval.RamRa_0", "stage6.sumcheck", "stage6.booleanity.eval.RamRa_0", 35, "RamRa_0"), stage6_sumcheck_eval!("stage6.booleanity.eval.RamRa_1", "stage6.sumcheck", "stage6.booleanity.eval.RamRa_1", 36, "RamRa_1"), - stage6_sumcheck_eval!("stage6.booleanity.eval.RamRa_2", "stage6.sumcheck", "stage6.booleanity.eval.RamRa_2", 37, "RamRa_2"), stage6_sumcheck_eval!("stage6.booleanity.eval.RamRa_3", "stage6.sumcheck", "stage6.booleanity.eval.RamRa_3", 38, "RamRa_3"), stage6_sumcheck_eval!("stage6.hamming_booleanity.eval.HammingWeight", "stage6.sumcheck", "stage6.hamming_booleanity.eval.HammingWeight", 0, "HammingWeight"), stage6_sumcheck_eval!("stage6.ram_ra_virtual.eval.RamRa_0", "stage6.sumcheck", "stage6.ram_ra_virtual.eval.RamRa_0", 0, "RamRa_0"), - stage6_sumcheck_eval!("stage6.ram_ra_virtual.eval.RamRa_1", "stage6.sumcheck", "stage6.ram_ra_virtual.eval.RamRa_1", 1, "RamRa_1"), stage6_sumcheck_eval!("stage6.ram_ra_virtual.eval.RamRa_2", "stage6.sumcheck", "stage6.ram_ra_virtual.eval.RamRa_2", 2, "RamRa_2"), stage6_sumcheck_eval!("stage6.ram_ra_virtual.eval.RamRa_3", "stage6.sumcheck", "stage6.ram_ra_virtual.eval.RamRa_3", 3, "RamRa_3"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_0", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_0", 0, "InstructionRa_0"), - stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_1", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_1", 1, "InstructionRa_1"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_2", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_2", 2, "InstructionRa_2"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_3", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_3", 3, "InstructionRa_3"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_4", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_4", 4, "InstructionRa_4"), - stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_5", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_5", 5, "InstructionRa_5"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_6", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_6", 6, "InstructionRa_6"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_7", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_7", 7, "InstructionRa_7"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_8", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_8", 8, "InstructionRa_8"), - stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_9", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_9", 9, "InstructionRa_9"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_10", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_10", 10, "InstructionRa_10"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_11", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_11", 11, "InstructionRa_11"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_12", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_12", 12, "InstructionRa_12"), - stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_13", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_13", 13, "InstructionRa_13"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_14", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_14", 14, "InstructionRa_14"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_15", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_15", 15, "InstructionRa_15"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_16", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_16", 16, "InstructionRa_16"), - stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_17", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_17", 17, "InstructionRa_17"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_18", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_18", 18, "InstructionRa_18"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_19", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_19", 19, "InstructionRa_19"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_20", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_20", 20, "InstructionRa_20"), - stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_21", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_21", 21, "InstructionRa_21"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_22", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_22", 22, "InstructionRa_22"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_23", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_23", 23, "InstructionRa_23"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_24", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_24", 24, "InstructionRa_24"), - stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_25", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_25", 25, "InstructionRa_25"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_26", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_26", 26, "InstructionRa_26"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_27", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_27", 27, "InstructionRa_27"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_28", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_28", 28, "InstructionRa_28"), - stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_29", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_29", 29, "InstructionRa_29"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_30", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_30", 30, "InstructionRa_30"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_31", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_31", 31, "InstructionRa_31"), stage6_sumcheck_eval!("stage6.inc_claim_reduction.eval.RamInc", "stage6.sumcheck", "stage6.inc_claim_reduction.eval.RamInc", 0, "RamInc"), - stage6_sumcheck_eval!("stage6.inc_claim_reduction.eval.RdInc", "stage6.sumcheck", "stage6.inc_claim_reduction.eval.RdInc", 1, "RdInc"), + stage6_sumcheck_eval!("stage6.bytecode_read_raf.eval.BytecodeRa_0", "stage6.sumcheck", "stage6.bytecode_read_raf.eval.BytecodeRa_0", 0, "BytecodeRa_0"), stage6_sumcheck_eval!("stage6.bytecode_read_raf.eval.BytecodeRa_1", "stage6.sumcheck", "stage6.bytecode_read_raf.eval.BytecodeRa_1", 1, "BytecodeRa_1"), stage6_sumcheck_eval!("stage6.bytecode_read_raf.eval.BytecodeRa_2", "stage6.sumcheck", "stage6.bytecode_read_raf.eval.BytecodeRa_2", 2, "BytecodeRa_2"), stage6_sumcheck_eval!("stage6.bytecode_read_raf.eval.BytecodeRa_3", "stage6.sumcheck", "stage6.bytecode_read_raf.eval.BytecodeRa_3", 3, "BytecodeRa_3"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_0", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_0", 0, "InstructionRa_0"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_1", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_1", 1, "InstructionRa_1"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_2", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_2", 2, "InstructionRa_2"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_3", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_3", 3, "InstructionRa_3"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_4", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_4", 4, "InstructionRa_4"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_5", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_5", 5, "InstructionRa_5"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_6", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_6", 6, "InstructionRa_6"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_7", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_7", 7, "InstructionRa_7"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_8", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_8", 8, "InstructionRa_8"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_9", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_9", 9, "InstructionRa_9"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_10", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_10", 10, "InstructionRa_10"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_11", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_11", 11, "InstructionRa_11"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_12", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_12", 12, "InstructionRa_12"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_13", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_13", 13, "InstructionRa_13"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_14", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_14", 14, "InstructionRa_14"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_15", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_15", 15, "InstructionRa_15"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_16", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_16", 16, "InstructionRa_16"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_17", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_17", 17, "InstructionRa_17"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_18", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_18", 18, "InstructionRa_18"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_19", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_19", 19, "InstructionRa_19"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_20", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_20", 20, "InstructionRa_20"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_21", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_21", 21, "InstructionRa_21"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_22", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_22", 22, "InstructionRa_22"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_23", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_23", 23, "InstructionRa_23"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_24", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_24", 24, "InstructionRa_24"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_25", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_25", 25, "InstructionRa_25"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_26", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_26", 26, "InstructionRa_26"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_27", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_27", 27, "InstructionRa_27"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_28", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_28", 28, "InstructionRa_28"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_29", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_29", 29, "InstructionRa_29"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_30", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_30", 30, "InstructionRa_30"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_31", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_31", 31, "InstructionRa_31"), + stage6_sumcheck_eval!("stage6.booleanity.eval.BytecodeRa_0", "stage6.sumcheck", "stage6.booleanity.eval.BytecodeRa_0", 32, "BytecodeRa_0"), stage6_sumcheck_eval!("stage6.booleanity.eval.BytecodeRa_1", "stage6.sumcheck", "stage6.booleanity.eval.BytecodeRa_1", 33, "BytecodeRa_1"), stage6_sumcheck_eval!("stage6.booleanity.eval.BytecodeRa_2", "stage6.sumcheck", "stage6.booleanity.eval.BytecodeRa_2", 34, "BytecodeRa_2"), stage6_sumcheck_eval!("stage6.booleanity.eval.BytecodeRa_3", "stage6.sumcheck", "stage6.booleanity.eval.BytecodeRa_3", 35, "BytecodeRa_3"), + stage6_sumcheck_eval!("stage6.booleanity.eval.RamRa_0", "stage6.sumcheck", "stage6.booleanity.eval.RamRa_0", 36, "RamRa_0"), stage6_sumcheck_eval!("stage6.booleanity.eval.RamRa_1", "stage6.sumcheck", "stage6.booleanity.eval.RamRa_1", 37, "RamRa_1"), stage6_sumcheck_eval!("stage6.booleanity.eval.RamRa_2", "stage6.sumcheck", "stage6.booleanity.eval.RamRa_2", 38, "RamRa_2"), stage6_sumcheck_eval!("stage6.booleanity.eval.RamRa_3", "stage6.sumcheck", "stage6.booleanity.eval.RamRa_3", 39, "RamRa_3"), + stage6_sumcheck_eval!("stage6.hamming_booleanity.eval.HammingWeight", "stage6.sumcheck", "stage6.hamming_booleanity.eval.HammingWeight", 0, "HammingWeight"), stage6_sumcheck_eval!("stage6.ram_ra_virtual.eval.RamRa_0", "stage6.sumcheck", "stage6.ram_ra_virtual.eval.RamRa_0", 0, "RamRa_0"), stage6_sumcheck_eval!("stage6.ram_ra_virtual.eval.RamRa_1", "stage6.sumcheck", "stage6.ram_ra_virtual.eval.RamRa_1", 1, "RamRa_1"), stage6_sumcheck_eval!("stage6.ram_ra_virtual.eval.RamRa_2", "stage6.sumcheck", "stage6.ram_ra_virtual.eval.RamRa_2", 2, "RamRa_2"), + stage6_sumcheck_eval!("stage6.ram_ra_virtual.eval.RamRa_3", "stage6.sumcheck", "stage6.ram_ra_virtual.eval.RamRa_3", 3, "RamRa_3"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_0", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_0", 0, "InstructionRa_0"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_1", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_1", 1, "InstructionRa_1"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_2", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_2", 2, "InstructionRa_2"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_3", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_3", 3, "InstructionRa_3"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_4", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_4", 4, "InstructionRa_4"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_5", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_5", 5, "InstructionRa_5"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_6", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_6", 6, "InstructionRa_6"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_7", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_7", 7, "InstructionRa_7"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_8", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_8", 8, "InstructionRa_8"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_9", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_9", 9, "InstructionRa_9"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_10", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_10", 10, "InstructionRa_10"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_11", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_11", 11, "InstructionRa_11"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_12", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_12", 12, "InstructionRa_12"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_13", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_13", 13, "InstructionRa_13"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_14", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_14", 14, "InstructionRa_14"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_15", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_15", 15, "InstructionRa_15"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_16", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_16", 16, "InstructionRa_16"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_17", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_17", 17, "InstructionRa_17"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_18", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_18", 18, "InstructionRa_18"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_19", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_19", 19, "InstructionRa_19"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_20", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_20", 20, "InstructionRa_20"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_21", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_21", 21, "InstructionRa_21"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_22", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_22", 22, "InstructionRa_22"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_23", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_23", 23, "InstructionRa_23"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_24", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_24", 24, "InstructionRa_24"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_25", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_25", 25, "InstructionRa_25"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_26", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_26", 26, "InstructionRa_26"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_27", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_27", 27, "InstructionRa_27"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_28", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_28", 28, "InstructionRa_28"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_29", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_29", 29, "InstructionRa_29"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_30", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_30", 30, "InstructionRa_30"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_31", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_31", 31, "InstructionRa_31"), stage6_sumcheck_eval!("stage6.inc_claim_reduction.eval.RamInc", "stage6.sumcheck", "stage6.inc_claim_reduction.eval.RamInc", 0, "RamInc"), stage6_sumcheck_eval!("stage6.inc_claim_reduction.eval.RdInc", "stage6.sumcheck", "stage6.inc_claim_reduction.eval.RdInc", 1, "RdInc"), ]; pub const STAGE6_POINT_ZEROS: &[Stage6PointZeroPlan] = &[ Stage6PointZeroPlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_0.address.zero_pad", field: "bn254_fr", arity: 2 }, + Stage6PointZeroPlan { symbol: "stage6.ram_ra_virtual.point.RamRa_0.address.zero_pad", field: "bn254_fr", arity: 2 }, ]; pub const STAGE6_POINT_SLICES: &[Stage6PointSlicePlan] = &[ - Stage6PointSlicePlan { symbol: "stage6.bytecode_read_raf.point.Cycle", source: "stage6.bytecode_read_raf.instance", offset: 10, length: 16, input: "stage6.bytecode_read_raf.instance" }, + Stage6PointSlicePlan { symbol: "stage6.bytecode_read_raf.point.Cycle", source: "stage6.bytecode_read_raf.instance", offset: 14, length: 18, input: "stage6.bytecode_read_raf.instance" }, Stage6PointSlicePlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_0.address.source", source: "stage6.bytecode_read_raf.instance", offset: 0, length: 2, input: "stage6.bytecode_read_raf.instance" }, Stage6PointSlicePlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_1.address", source: "stage6.bytecode_read_raf.instance", offset: 2, length: 4, input: "stage6.bytecode_read_raf.instance" }, Stage6PointSlicePlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_2.address", source: "stage6.bytecode_read_raf.instance", offset: 6, length: 4, input: "stage6.bytecode_read_raf.instance" }, - Stage6PointSlicePlan { symbol: "stage6.ram_ra_virtual.point.RamRa_0.address", source: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", offset: 0, length: 4, input: "stage6.input.stage5.ram_ra_claim_reduction.RamRa" }, - Stage6PointSlicePlan { symbol: "stage6.ram_ra_virtual.point.RamRa_1.address", source: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", offset: 4, length: 4, input: "stage6.input.stage5.ram_ra_claim_reduction.RamRa" }, - Stage6PointSlicePlan { symbol: "stage6.ram_ra_virtual.point.RamRa_2.address", source: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", offset: 8, length: 4, input: "stage6.input.stage5.ram_ra_claim_reduction.RamRa" }, - Stage6PointSlicePlan { symbol: "stage6.ram_ra_virtual.point.RamRa_3.address", source: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", offset: 12, length: 4, input: "stage6.input.stage5.ram_ra_claim_reduction.RamRa" }, + Stage6PointSlicePlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_3.address", source: "stage6.bytecode_read_raf.instance", offset: 10, length: 4, input: "stage6.bytecode_read_raf.instance" }, + Stage6PointSlicePlan { symbol: "stage6.ram_ra_virtual.point.RamRa_0.address.source", source: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", offset: 0, length: 2, input: "stage6.input.stage5.ram_ra_claim_reduction.RamRa" }, + Stage6PointSlicePlan { symbol: "stage6.ram_ra_virtual.point.RamRa_1.address", source: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", offset: 2, length: 4, input: "stage6.input.stage5.ram_ra_claim_reduction.RamRa" }, + Stage6PointSlicePlan { symbol: "stage6.ram_ra_virtual.point.RamRa_2.address", source: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", offset: 6, length: 4, input: "stage6.input.stage5.ram_ra_claim_reduction.RamRa" }, + Stage6PointSlicePlan { symbol: "stage6.ram_ra_virtual.point.RamRa_3.address", source: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", offset: 10, length: 4, input: "stage6.input.stage5.ram_ra_claim_reduction.RamRa" }, Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_0.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", offset: 0, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_0" }, Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_1.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", offset: 4, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_0" }, Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_2.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", offset: 8, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_0" }, @@ -1988,309 +1992,323 @@ pub const STAGE6_POINT_CONCAT_3_INPUTS: &[&str] = &[ ]; pub const STAGE6_POINT_CONCAT_4_INPUTS: &[&str] = &[ + "stage6.bytecode_read_raf.point.BytecodeRa_3.address", + "stage6.bytecode_read_raf.point.Cycle", +]; + +pub const STAGE6_POINT_CONCAT_5_INPUTS: &[&str] = &[ + "stage6.ram_ra_virtual.point.RamRa_0.address.zero_pad", + "stage6.ram_ra_virtual.point.RamRa_0.address.source", +]; + +pub const STAGE6_POINT_CONCAT_6_INPUTS: &[&str] = &[ "stage6.ram_ra_virtual.point.RamRa_0.address", "stage6.ram_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_5_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_7_INPUTS: &[&str] = &[ "stage6.ram_ra_virtual.point.RamRa_1.address", "stage6.ram_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_6_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_8_INPUTS: &[&str] = &[ "stage6.ram_ra_virtual.point.RamRa_2.address", "stage6.ram_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_7_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_9_INPUTS: &[&str] = &[ "stage6.ram_ra_virtual.point.RamRa_3.address", "stage6.ram_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_8_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_10_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_0.address", "stage6.instruction_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_9_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_11_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_1.address", "stage6.instruction_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_10_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_12_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_2.address", "stage6.instruction_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_11_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_13_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_3.address", "stage6.instruction_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_12_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_14_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_4.address", "stage6.instruction_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_13_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_15_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_5.address", "stage6.instruction_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_14_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_16_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_6.address", "stage6.instruction_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_15_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_17_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_7.address", "stage6.instruction_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_16_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_18_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_8.address", "stage6.instruction_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_17_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_19_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_9.address", "stage6.instruction_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_18_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_20_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_10.address", "stage6.instruction_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_19_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_21_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_11.address", "stage6.instruction_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_20_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_22_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_12.address", "stage6.instruction_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_21_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_23_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_13.address", "stage6.instruction_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_22_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_24_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_14.address", "stage6.instruction_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_23_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_25_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_15.address", "stage6.instruction_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_24_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_26_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_16.address", "stage6.instruction_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_25_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_27_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_17.address", "stage6.instruction_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_26_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_28_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_18.address", "stage6.instruction_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_27_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_29_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_19.address", "stage6.instruction_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_28_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_30_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_20.address", "stage6.instruction_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_29_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_31_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_21.address", "stage6.instruction_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_30_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_32_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_22.address", "stage6.instruction_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_31_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_33_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_23.address", "stage6.instruction_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_32_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_34_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_24.address", "stage6.instruction_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_33_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_35_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_25.address", "stage6.instruction_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_34_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_36_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_26.address", "stage6.instruction_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_35_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_37_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_27.address", "stage6.instruction_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_36_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_38_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_28.address", "stage6.instruction_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_37_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_39_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_29.address", "stage6.instruction_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_38_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_40_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_30.address", "stage6.instruction_ra_virtual.instance", ]; -pub const STAGE6_POINT_CONCAT_39_INPUTS: &[&str] = &[ +pub const STAGE6_POINT_CONCAT_41_INPUTS: &[&str] = &[ "stage6.instruction_ra_virtual.point.InstructionRa_31.address", "stage6.instruction_ra_virtual.instance", ]; pub const STAGE6_POINT_CONCATS: &[Stage6PointConcatPlan] = &[ Stage6PointConcatPlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_0.address", layout: "left_zero_padded_address_chunk", arity: 4, inputs: STAGE6_POINT_CONCAT_0_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_0", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_1_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_1", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_2_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_2", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_3_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.ram_ra_virtual.point.RamRa_0", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_4_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.ram_ra_virtual.point.RamRa_1", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_5_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.ram_ra_virtual.point.RamRa_2", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_6_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.ram_ra_virtual.point.RamRa_3", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_7_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_0", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_8_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_1", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_9_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_2", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_10_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_3", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_11_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_4", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_12_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_5", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_13_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_6", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_14_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_7", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_15_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_8", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_16_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_9", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_17_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_10", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_18_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_11", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_19_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_12", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_20_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_13", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_21_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_14", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_22_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_15", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_23_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_16", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_24_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_17", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_25_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_18", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_26_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_19", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_27_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_20", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_28_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_21", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_29_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_22", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_30_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_23", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_31_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_24", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_32_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_25", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_33_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_26", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_34_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_27", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_35_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_28", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_36_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_29", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_37_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_30", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_38_INPUTS }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_31", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE6_POINT_CONCAT_39_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_0", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_1_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_1", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_2_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_2", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_3_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_3", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_4_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.ram_ra_virtual.point.RamRa_0.address", layout: "left_zero_padded_address_chunk", arity: 4, inputs: STAGE6_POINT_CONCAT_5_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.ram_ra_virtual.point.RamRa_0", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_6_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.ram_ra_virtual.point.RamRa_1", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_7_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.ram_ra_virtual.point.RamRa_2", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_8_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.ram_ra_virtual.point.RamRa_3", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_9_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_0", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_10_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_1", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_11_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_2", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_12_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_3", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_13_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_4", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_14_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_5", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_15_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_6", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_16_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_7", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_17_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_8", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_18_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_9", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_19_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_10", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_20_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_11", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_21_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_12", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_22_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_13", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_23_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_14", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_24_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_15", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_25_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_16", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_26_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_17", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_27_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_18", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_28_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_19", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_29_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_20", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_30_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_21", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_31_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_22", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_32_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_23", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_33_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_24", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_34_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_25", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_35_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_26", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_36_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_27", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_37_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_28", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_38_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_29", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_39_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_30", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_40_INPUTS }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_31", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE6_POINT_CONCAT_41_INPUTS }, ]; pub const STAGE6_OPENING_CLAIMS: &[Stage6OpeningClaimPlan] = &[ - Stage6OpeningClaimPlan { symbol: "stage6.bytecode_read_raf.opening.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.bytecode_read_raf.point.BytecodeRa_0", eval_source: "stage6.bytecode_read_raf.eval.BytecodeRa_0" }, - Stage6OpeningClaimPlan { symbol: "stage6.bytecode_read_raf.opening.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.bytecode_read_raf.point.BytecodeRa_1", eval_source: "stage6.bytecode_read_raf.eval.BytecodeRa_1" }, - Stage6OpeningClaimPlan { symbol: "stage6.bytecode_read_raf.opening.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.bytecode_read_raf.point.BytecodeRa_2", eval_source: "stage6.bytecode_read_raf.eval.BytecodeRa_2" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_0" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_1" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_2" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_3" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_4" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_5" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_6" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_7" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_8" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_9" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_10" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_11" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_12" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_13" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_14" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_15" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_16" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_17" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_18" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_19" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_20" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_21" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_22" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_23" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_24" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_25" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_26" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_27" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_28" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_29" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_30" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_31" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.BytecodeRa_0" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.BytecodeRa_1" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.BytecodeRa_2" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.RamRa_0" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.RamRa_1" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.RamRa_2" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.RamRa_3" }, - Stage6OpeningClaimPlan { symbol: "stage6.hamming_booleanity.opening.HammingWeight", oracle: "HammingWeight", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage6.hamming_booleanity.instance", eval_source: "stage6.hamming_booleanity.eval.HammingWeight" }, - Stage6OpeningClaimPlan { symbol: "stage6.ram_ra_virtual.opening.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.ram_ra_virtual.point.RamRa_0", eval_source: "stage6.ram_ra_virtual.eval.RamRa_0" }, - Stage6OpeningClaimPlan { symbol: "stage6.ram_ra_virtual.opening.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.ram_ra_virtual.point.RamRa_1", eval_source: "stage6.ram_ra_virtual.eval.RamRa_1" }, - Stage6OpeningClaimPlan { symbol: "stage6.ram_ra_virtual.opening.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.ram_ra_virtual.point.RamRa_2", eval_source: "stage6.ram_ra_virtual.eval.RamRa_2" }, - Stage6OpeningClaimPlan { symbol: "stage6.ram_ra_virtual.opening.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.ram_ra_virtual.point.RamRa_3", eval_source: "stage6.ram_ra_virtual.eval.RamRa_3" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_0", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_0" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_1", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_1" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_2", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_2" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_3", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_3" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_4", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_4" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_5", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_5" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_6", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_6" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_7", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_7" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_8", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_8" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_9", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_9" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_10", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_10" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_11", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_11" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_12", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_12" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_13", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_13" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_14", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_14" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_15", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_15" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_16", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_16" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_17", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_17" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_18", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_18" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_19", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_19" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_20", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_20" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_21", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_21" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_22", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_22" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_23", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_23" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_24", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_24" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_25", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_25" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_26", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_26" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_27", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_27" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_28", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_28" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_29", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_29" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_30", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_30" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_31", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_31" }, - Stage6OpeningClaimPlan { symbol: "stage6.inc_claim_reduction.opening.RamInc", oracle: "RamInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed", point_source: "stage6.inc_claim_reduction.instance", eval_source: "stage6.inc_claim_reduction.eval.RamInc" }, - Stage6OpeningClaimPlan { symbol: "stage6.inc_claim_reduction.opening.RdInc", oracle: "RdInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed", point_source: "stage6.inc_claim_reduction.instance", eval_source: "stage6.inc_claim_reduction.eval.RdInc" }, + Stage6OpeningClaimPlan { symbol: "stage6.bytecode_read_raf.opening.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.bytecode_read_raf.point.BytecodeRa_0", eval_source: "stage6.bytecode_read_raf.eval.BytecodeRa_0" }, + Stage6OpeningClaimPlan { symbol: "stage6.bytecode_read_raf.opening.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.bytecode_read_raf.point.BytecodeRa_1", eval_source: "stage6.bytecode_read_raf.eval.BytecodeRa_1" }, + Stage6OpeningClaimPlan { symbol: "stage6.bytecode_read_raf.opening.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.bytecode_read_raf.point.BytecodeRa_2", eval_source: "stage6.bytecode_read_raf.eval.BytecodeRa_2" }, + Stage6OpeningClaimPlan { symbol: "stage6.bytecode_read_raf.opening.BytecodeRa_3", oracle: "BytecodeRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.bytecode_read_raf.point.BytecodeRa_3", eval_source: "stage6.bytecode_read_raf.eval.BytecodeRa_3" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_0" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_1" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_2" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_3" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_4" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_5" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_6" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_7" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_8" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_9" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_10" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_11" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_12" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_13" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_14" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_15" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_16" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_17" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_18" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_19" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_20" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_21" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_22" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_23" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_24" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_25" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_26" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_27" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_28" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_29" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_30" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_31" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.BytecodeRa_0" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.BytecodeRa_1" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.BytecodeRa_2" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.BytecodeRa_3", oracle: "BytecodeRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.BytecodeRa_3" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.RamRa_0" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.RamRa_1" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.RamRa_2" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.RamRa_3" }, + Stage6OpeningClaimPlan { symbol: "stage6.hamming_booleanity.opening.HammingWeight", oracle: "HammingWeight", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage6.hamming_booleanity.instance", eval_source: "stage6.hamming_booleanity.eval.HammingWeight" }, + Stage6OpeningClaimPlan { symbol: "stage6.ram_ra_virtual.opening.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.ram_ra_virtual.point.RamRa_0", eval_source: "stage6.ram_ra_virtual.eval.RamRa_0" }, + Stage6OpeningClaimPlan { symbol: "stage6.ram_ra_virtual.opening.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.ram_ra_virtual.point.RamRa_1", eval_source: "stage6.ram_ra_virtual.eval.RamRa_1" }, + Stage6OpeningClaimPlan { symbol: "stage6.ram_ra_virtual.opening.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.ram_ra_virtual.point.RamRa_2", eval_source: "stage6.ram_ra_virtual.eval.RamRa_2" }, + Stage6OpeningClaimPlan { symbol: "stage6.ram_ra_virtual.opening.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.ram_ra_virtual.point.RamRa_3", eval_source: "stage6.ram_ra_virtual.eval.RamRa_3" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_0", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_0" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_1", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_1" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_2", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_2" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_3", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_3" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_4", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_4" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_5", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_5" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_6", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_6" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_7", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_7" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_8", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_8" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_9", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_9" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_10", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_10" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_11", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_11" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_12", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_12" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_13", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_13" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_14", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_14" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_15", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_15" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_16", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_16" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_17", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_17" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_18", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_18" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_19", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_19" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_20", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_20" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_21", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_21" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_22", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_22" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_23", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_23" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_24", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_24" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_25", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_25" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_26", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_26" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_27", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_27" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_28", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_28" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_29", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_29" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_30", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_30" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_31", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_31" }, + Stage6OpeningClaimPlan { symbol: "stage6.inc_claim_reduction.opening.RamInc", oracle: "RamInc", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "committed", point_source: "stage6.inc_claim_reduction.instance", eval_source: "stage6.inc_claim_reduction.eval.RamInc" }, + Stage6OpeningClaimPlan { symbol: "stage6.inc_claim_reduction.opening.RdInc", oracle: "RdInc", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "committed", point_source: "stage6.inc_claim_reduction.instance", eval_source: "stage6.inc_claim_reduction.eval.RdInc" }, ]; pub const STAGE6_OPENING_EQUALITIES: &[Stage6OpeningClaimEqualityPlan] = &[ @@ -2301,6 +2319,7 @@ pub const STAGE6_OPENING_BATCH_0_ORDERED_CLAIMS: &[&str] = &[ "stage6.bytecode_read_raf.opening.BytecodeRa_0", "stage6.bytecode_read_raf.opening.BytecodeRa_1", "stage6.bytecode_read_raf.opening.BytecodeRa_2", + "stage6.bytecode_read_raf.opening.BytecodeRa_3", "stage6.booleanity.opening.InstructionRa_0", "stage6.booleanity.opening.InstructionRa_1", "stage6.booleanity.opening.InstructionRa_2", @@ -2336,6 +2355,7 @@ pub const STAGE6_OPENING_BATCH_0_ORDERED_CLAIMS: &[&str] = &[ "stage6.booleanity.opening.BytecodeRa_0", "stage6.booleanity.opening.BytecodeRa_1", "stage6.booleanity.opening.BytecodeRa_2", + "stage6.booleanity.opening.BytecodeRa_3", "stage6.booleanity.opening.RamRa_0", "stage6.booleanity.opening.RamRa_1", "stage6.booleanity.opening.RamRa_2", @@ -2385,6 +2405,7 @@ pub const STAGE6_OPENING_BATCH_0_CLAIM_OPERANDS: &[&str] = &[ "stage6.bytecode_read_raf.opening.BytecodeRa_0", "stage6.bytecode_read_raf.opening.BytecodeRa_1", "stage6.bytecode_read_raf.opening.BytecodeRa_2", + "stage6.bytecode_read_raf.opening.BytecodeRa_3", "stage6.booleanity.opening.InstructionRa_0", "stage6.booleanity.opening.InstructionRa_1", "stage6.booleanity.opening.InstructionRa_2", @@ -2420,6 +2441,7 @@ pub const STAGE6_OPENING_BATCH_0_CLAIM_OPERANDS: &[&str] = &[ "stage6.booleanity.opening.BytecodeRa_0", "stage6.booleanity.opening.BytecodeRa_1", "stage6.booleanity.opening.BytecodeRa_2", + "stage6.booleanity.opening.BytecodeRa_3", "stage6.booleanity.opening.RamRa_0", "stage6.booleanity.opening.RamRa_1", "stage6.booleanity.opening.RamRa_2", @@ -2466,7 +2488,7 @@ pub const STAGE6_OPENING_BATCH_0_CLAIM_OPERANDS: &[&str] = &[ ]; pub const STAGE6_OPENING_BATCHES: &[Stage6OpeningBatchPlan] = &[ - Stage6OpeningBatchPlan { symbol: "stage6.openings", stage: "stage6", proof_slot: "stage6.openings", policy: "jolt_stage6_output_order", count: 81, ordered_claims: STAGE6_OPENING_BATCH_0_ORDERED_CLAIMS, claim_operands: STAGE6_OPENING_BATCH_0_CLAIM_OPERANDS }, + Stage6OpeningBatchPlan { symbol: "stage6.openings", stage: "stage6", proof_slot: "stage6.openings", policy: "jolt_stage6_output_order", count: 83, ordered_claims: STAGE6_OPENING_BATCH_0_ORDERED_CLAIMS, claim_operands: STAGE6_OPENING_BATCH_0_CLAIM_OPERANDS }, ]; pub const STAGE6_PROGRAM: Stage6CpuProgramPlan = Stage6CpuProgramPlan { role: "prover", diff --git a/crates/jolt-prover/src/stages/stage7.rs b/crates/jolt-prover/src/stages/stage7.rs index 831534a4b9..4dfa6eec1a 100644 --- a/crates/jolt-prover/src/stages/stage7.rs +++ b/crates/jolt-prover/src/stages/stage7.rs @@ -25,85 +25,87 @@ pub const STAGE7_TRANSCRIPT_ABSORB_BYTES: &[Stage7TranscriptAbsorbBytesPlan] = & ]; pub const STAGE7_OPENING_INPUTS: &[Stage7OpeningInputPlan] = &[ - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.hamming_booleanity.HammingWeight", source_stage: "stage6", source_claim: "stage6.hamming_booleanity.opening.HammingWeight", oracle: "HammingWeight", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_0", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_0", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_1", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_1", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_2", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_2", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_3", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_3", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_4", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_4", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_5", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_5", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_6", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_6", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_7", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_7", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_8", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_8", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_9", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_9", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_10", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_10", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_11", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_11", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_12", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_12", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_13", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_13", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_14", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_14", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_15", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_15", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_16", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_16", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_17", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_17", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_18", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_18", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_19", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_19", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_20", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_20", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_21", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_21", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_22", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_22", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_23", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_23", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_24", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_24", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_25", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_25", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_26", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_26", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_27", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_27", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_28", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_28", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_29", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_29", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_30", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_30", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_31", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_31", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.BytecodeRa_0", source_stage: "stage6", source_claim: "stage6.booleanity.opening.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.bytecode_read_raf.BytecodeRa_0", source_stage: "stage6", source_claim: "stage6.bytecode_read_raf.opening.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.BytecodeRa_1", source_stage: "stage6", source_claim: "stage6.booleanity.opening.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.bytecode_read_raf.BytecodeRa_1", source_stage: "stage6", source_claim: "stage6.bytecode_read_raf.opening.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.BytecodeRa_2", source_stage: "stage6", source_claim: "stage6.booleanity.opening.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.bytecode_read_raf.BytecodeRa_2", source_stage: "stage6", source_claim: "stage6.bytecode_read_raf.opening.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.RamRa_0", source_stage: "stage6", source_claim: "stage6.booleanity.opening.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.ram_ra_virtual.RamRa_0", source_stage: "stage6", source_claim: "stage6.ram_ra_virtual.opening.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.RamRa_1", source_stage: "stage6", source_claim: "stage6.booleanity.opening.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.ram_ra_virtual.RamRa_1", source_stage: "stage6", source_claim: "stage6.ram_ra_virtual.opening.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.RamRa_2", source_stage: "stage6", source_claim: "stage6.booleanity.opening.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.ram_ra_virtual.RamRa_2", source_stage: "stage6", source_claim: "stage6.ram_ra_virtual.opening.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.RamRa_3", source_stage: "stage6", source_claim: "stage6.booleanity.opening.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.ram_ra_virtual.RamRa_3", source_stage: "stage6", source_claim: "stage6.ram_ra_virtual.opening.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.hamming_booleanity.HammingWeight", source_stage: "stage6", source_claim: "stage6.hamming_booleanity.opening.HammingWeight", oracle: "HammingWeight", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_0", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_0", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_1", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_1", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_2", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_2", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_3", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_3", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_4", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_4", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_5", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_5", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_6", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_6", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_7", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_7", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_8", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_8", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_9", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_9", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_10", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_10", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_11", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_11", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_12", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_12", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_13", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_13", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_14", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_14", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_15", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_15", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_16", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_16", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_17", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_17", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_18", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_18", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_19", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_19", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_20", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_20", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_21", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_21", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_22", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_22", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_23", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_23", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_24", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_24", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_25", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_25", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_26", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_26", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_27", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_27", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_28", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_28", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_29", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_29", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_30", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_30", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_31", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_31", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.BytecodeRa_0", source_stage: "stage6", source_claim: "stage6.booleanity.opening.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.bytecode_read_raf.BytecodeRa_0", source_stage: "stage6", source_claim: "stage6.bytecode_read_raf.opening.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.BytecodeRa_1", source_stage: "stage6", source_claim: "stage6.booleanity.opening.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.bytecode_read_raf.BytecodeRa_1", source_stage: "stage6", source_claim: "stage6.bytecode_read_raf.opening.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.BytecodeRa_2", source_stage: "stage6", source_claim: "stage6.booleanity.opening.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.bytecode_read_raf.BytecodeRa_2", source_stage: "stage6", source_claim: "stage6.bytecode_read_raf.opening.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.BytecodeRa_3", source_stage: "stage6", source_claim: "stage6.booleanity.opening.BytecodeRa_3", oracle: "BytecodeRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.bytecode_read_raf.BytecodeRa_3", source_stage: "stage6", source_claim: "stage6.bytecode_read_raf.opening.BytecodeRa_3", oracle: "BytecodeRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.RamRa_0", source_stage: "stage6", source_claim: "stage6.booleanity.opening.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.ram_ra_virtual.RamRa_0", source_stage: "stage6", source_claim: "stage6.ram_ra_virtual.opening.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.RamRa_1", source_stage: "stage6", source_claim: "stage6.booleanity.opening.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.ram_ra_virtual.RamRa_1", source_stage: "stage6", source_claim: "stage6.ram_ra_virtual.opening.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.RamRa_2", source_stage: "stage6", source_claim: "stage6.booleanity.opening.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.ram_ra_virtual.RamRa_2", source_stage: "stage6", source_claim: "stage6.ram_ra_virtual.opening.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.RamRa_3", source_stage: "stage6", source_claim: "stage6.booleanity.opening.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.ram_ra_virtual.RamRa_3", source_stage: "stage6", source_claim: "stage6.ram_ra_virtual.opening.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, ]; pub const STAGE7_FIELD_CONSTANTS: &[Stage7FieldConstantPlan] = &[ @@ -634,17 +636,17 @@ pub const STAGE7_FIELD_EXPR_OPERANDS_104: &[&str] = &[ pub const STAGE7_FIELD_EXPR_OPERANDS_105: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim.35.hw.gamma_pow", - "stage7.input.stage6.hamming_booleanity.HammingWeight", + "stage7.field.one", ]; pub const STAGE7_FIELD_EXPR_OPERANDS_106: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim.35.booleanity.gamma_pow", - "stage7.input.stage6.booleanity.RamRa_0", + "stage7.input.stage6.booleanity.BytecodeRa_3", ]; pub const STAGE7_FIELD_EXPR_OPERANDS_107: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim.35.virtualization.gamma_pow", - "stage7.input.stage6.ram_ra_virtual.RamRa_0", + "stage7.input.stage6.bytecode_read_raf.BytecodeRa_3", ]; pub const STAGE7_FIELD_EXPR_OPERANDS_108: &[&str] = &[ @@ -654,12 +656,12 @@ pub const STAGE7_FIELD_EXPR_OPERANDS_108: &[&str] = &[ pub const STAGE7_FIELD_EXPR_OPERANDS_109: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim.36.booleanity.gamma_pow", - "stage7.input.stage6.booleanity.RamRa_1", + "stage7.input.stage6.booleanity.RamRa_0", ]; pub const STAGE7_FIELD_EXPR_OPERANDS_110: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim.36.virtualization.gamma_pow", - "stage7.input.stage6.ram_ra_virtual.RamRa_1", + "stage7.input.stage6.ram_ra_virtual.RamRa_0", ]; pub const STAGE7_FIELD_EXPR_OPERANDS_111: &[&str] = &[ @@ -669,12 +671,12 @@ pub const STAGE7_FIELD_EXPR_OPERANDS_111: &[&str] = &[ pub const STAGE7_FIELD_EXPR_OPERANDS_112: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim.37.booleanity.gamma_pow", - "stage7.input.stage6.booleanity.RamRa_2", + "stage7.input.stage6.booleanity.RamRa_1", ]; pub const STAGE7_FIELD_EXPR_OPERANDS_113: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim.37.virtualization.gamma_pow", - "stage7.input.stage6.ram_ra_virtual.RamRa_2", + "stage7.input.stage6.ram_ra_virtual.RamRa_1", ]; pub const STAGE7_FIELD_EXPR_OPERANDS_114: &[&str] = &[ @@ -684,594 +686,624 @@ pub const STAGE7_FIELD_EXPR_OPERANDS_114: &[&str] = &[ pub const STAGE7_FIELD_EXPR_OPERANDS_115: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim.38.booleanity.gamma_pow", - "stage7.input.stage6.booleanity.RamRa_3", + "stage7.input.stage6.booleanity.RamRa_2", ]; pub const STAGE7_FIELD_EXPR_OPERANDS_116: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim.38.virtualization.gamma_pow", - "stage7.input.stage6.ram_ra_virtual.RamRa_3", + "stage7.input.stage6.ram_ra_virtual.RamRa_2", ]; pub const STAGE7_FIELD_EXPR_OPERANDS_117: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.39.hw.gamma_pow", + "stage7.input.stage6.hamming_booleanity.HammingWeight", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_118: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.39.booleanity.gamma_pow", + "stage7.input.stage6.booleanity.RamRa_3", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_119: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim.39.virtualization.gamma_pow", + "stage7.input.stage6.ram_ra_virtual.RamRa_3", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_120: &[&str] = &[ "stage7.field.one", "stage7.hamming_weight_claim_reduction.claim.0.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_118: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_121: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial0", "stage7.hamming_weight_claim_reduction.claim.0.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_119: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_122: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial1", "stage7.hamming_weight_claim_reduction.claim.1.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_120: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_123: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial2", "stage7.hamming_weight_claim_reduction.claim.1.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_121: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_124: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial3", "stage7.hamming_weight_claim_reduction.claim.1.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_122: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_125: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial4", "stage7.hamming_weight_claim_reduction.claim.2.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_123: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_126: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial5", "stage7.hamming_weight_claim_reduction.claim.2.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_124: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_127: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial6", "stage7.hamming_weight_claim_reduction.claim.2.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_125: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_128: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial7", "stage7.hamming_weight_claim_reduction.claim.3.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_126: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_129: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial8", "stage7.hamming_weight_claim_reduction.claim.3.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_127: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_130: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial9", "stage7.hamming_weight_claim_reduction.claim.3.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_128: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_131: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial10", "stage7.hamming_weight_claim_reduction.claim.4.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_129: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_132: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial11", "stage7.hamming_weight_claim_reduction.claim.4.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_130: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_133: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial12", "stage7.hamming_weight_claim_reduction.claim.4.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_131: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_134: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial13", "stage7.hamming_weight_claim_reduction.claim.5.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_132: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_135: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial14", "stage7.hamming_weight_claim_reduction.claim.5.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_133: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_136: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial15", "stage7.hamming_weight_claim_reduction.claim.5.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_134: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_137: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial16", "stage7.hamming_weight_claim_reduction.claim.6.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_135: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_138: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial17", "stage7.hamming_weight_claim_reduction.claim.6.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_136: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_139: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial18", "stage7.hamming_weight_claim_reduction.claim.6.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_137: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_140: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial19", "stage7.hamming_weight_claim_reduction.claim.7.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_138: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_141: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial20", "stage7.hamming_weight_claim_reduction.claim.7.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_139: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_142: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial21", "stage7.hamming_weight_claim_reduction.claim.7.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_140: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_143: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial22", "stage7.hamming_weight_claim_reduction.claim.8.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_141: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_144: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial23", "stage7.hamming_weight_claim_reduction.claim.8.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_142: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_145: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial24", "stage7.hamming_weight_claim_reduction.claim.8.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_143: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_146: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial25", "stage7.hamming_weight_claim_reduction.claim.9.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_144: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_147: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial26", "stage7.hamming_weight_claim_reduction.claim.9.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_145: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_148: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial27", "stage7.hamming_weight_claim_reduction.claim.9.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_146: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_149: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial28", "stage7.hamming_weight_claim_reduction.claim.10.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_147: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_150: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial29", "stage7.hamming_weight_claim_reduction.claim.10.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_148: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_151: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial30", "stage7.hamming_weight_claim_reduction.claim.10.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_149: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_152: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial31", "stage7.hamming_weight_claim_reduction.claim.11.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_150: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_153: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial32", "stage7.hamming_weight_claim_reduction.claim.11.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_151: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_154: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial33", "stage7.hamming_weight_claim_reduction.claim.11.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_152: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_155: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial34", "stage7.hamming_weight_claim_reduction.claim.12.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_153: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_156: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial35", "stage7.hamming_weight_claim_reduction.claim.12.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_154: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_157: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial36", "stage7.hamming_weight_claim_reduction.claim.12.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_155: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_158: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial37", "stage7.hamming_weight_claim_reduction.claim.13.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_156: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_159: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial38", "stage7.hamming_weight_claim_reduction.claim.13.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_157: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_160: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial39", "stage7.hamming_weight_claim_reduction.claim.13.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_158: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_161: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial40", "stage7.hamming_weight_claim_reduction.claim.14.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_159: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_162: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial41", "stage7.hamming_weight_claim_reduction.claim.14.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_160: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_163: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial42", "stage7.hamming_weight_claim_reduction.claim.14.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_161: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_164: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial43", "stage7.hamming_weight_claim_reduction.claim.15.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_162: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_165: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial44", "stage7.hamming_weight_claim_reduction.claim.15.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_163: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_166: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial45", "stage7.hamming_weight_claim_reduction.claim.15.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_164: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_167: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial46", "stage7.hamming_weight_claim_reduction.claim.16.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_165: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_168: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial47", "stage7.hamming_weight_claim_reduction.claim.16.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_166: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_169: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial48", "stage7.hamming_weight_claim_reduction.claim.16.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_167: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_170: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial49", "stage7.hamming_weight_claim_reduction.claim.17.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_168: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_171: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial50", "stage7.hamming_weight_claim_reduction.claim.17.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_169: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_172: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial51", "stage7.hamming_weight_claim_reduction.claim.17.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_170: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_173: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial52", "stage7.hamming_weight_claim_reduction.claim.18.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_171: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_174: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial53", "stage7.hamming_weight_claim_reduction.claim.18.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_172: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_175: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial54", "stage7.hamming_weight_claim_reduction.claim.18.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_173: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_176: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial55", "stage7.hamming_weight_claim_reduction.claim.19.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_174: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_177: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial56", "stage7.hamming_weight_claim_reduction.claim.19.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_175: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_178: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial57", "stage7.hamming_weight_claim_reduction.claim.19.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_176: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_179: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial58", "stage7.hamming_weight_claim_reduction.claim.20.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_177: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_180: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial59", "stage7.hamming_weight_claim_reduction.claim.20.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_178: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_181: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial60", "stage7.hamming_weight_claim_reduction.claim.20.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_179: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_182: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial61", "stage7.hamming_weight_claim_reduction.claim.21.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_180: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_183: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial62", "stage7.hamming_weight_claim_reduction.claim.21.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_181: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_184: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial63", "stage7.hamming_weight_claim_reduction.claim.21.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_182: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_185: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial64", "stage7.hamming_weight_claim_reduction.claim.22.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_183: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_186: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial65", "stage7.hamming_weight_claim_reduction.claim.22.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_184: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_187: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial66", "stage7.hamming_weight_claim_reduction.claim.22.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_185: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_188: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial67", "stage7.hamming_weight_claim_reduction.claim.23.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_186: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_189: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial68", "stage7.hamming_weight_claim_reduction.claim.23.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_187: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_190: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial69", "stage7.hamming_weight_claim_reduction.claim.23.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_188: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_191: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial70", "stage7.hamming_weight_claim_reduction.claim.24.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_189: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_192: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial71", "stage7.hamming_weight_claim_reduction.claim.24.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_190: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_193: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial72", "stage7.hamming_weight_claim_reduction.claim.24.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_191: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_194: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial73", "stage7.hamming_weight_claim_reduction.claim.25.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_192: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_195: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial74", "stage7.hamming_weight_claim_reduction.claim.25.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_193: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_196: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial75", "stage7.hamming_weight_claim_reduction.claim.25.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_194: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_197: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial76", "stage7.hamming_weight_claim_reduction.claim.26.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_195: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_198: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial77", "stage7.hamming_weight_claim_reduction.claim.26.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_196: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_199: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial78", "stage7.hamming_weight_claim_reduction.claim.26.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_197: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_200: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial79", "stage7.hamming_weight_claim_reduction.claim.27.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_198: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_201: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial80", "stage7.hamming_weight_claim_reduction.claim.27.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_199: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_202: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial81", "stage7.hamming_weight_claim_reduction.claim.27.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_200: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_203: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial82", "stage7.hamming_weight_claim_reduction.claim.28.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_201: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_204: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial83", "stage7.hamming_weight_claim_reduction.claim.28.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_202: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_205: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial84", "stage7.hamming_weight_claim_reduction.claim.28.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_203: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_206: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial85", "stage7.hamming_weight_claim_reduction.claim.29.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_204: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_207: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial86", "stage7.hamming_weight_claim_reduction.claim.29.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_205: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_208: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial87", "stage7.hamming_weight_claim_reduction.claim.29.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_206: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_209: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial88", "stage7.hamming_weight_claim_reduction.claim.30.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_207: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_210: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial89", "stage7.hamming_weight_claim_reduction.claim.30.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_208: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_211: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial90", "stage7.hamming_weight_claim_reduction.claim.30.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_209: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_212: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial91", "stage7.hamming_weight_claim_reduction.claim.31.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_210: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_213: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial92", "stage7.hamming_weight_claim_reduction.claim.31.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_211: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_214: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial93", "stage7.hamming_weight_claim_reduction.claim.31.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_212: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_215: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial94", "stage7.hamming_weight_claim_reduction.claim.32.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_213: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_216: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial95", "stage7.hamming_weight_claim_reduction.claim.32.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_214: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_217: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial96", "stage7.hamming_weight_claim_reduction.claim.32.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_215: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_218: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial97", "stage7.hamming_weight_claim_reduction.claim.33.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_216: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_219: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial98", "stage7.hamming_weight_claim_reduction.claim.33.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_217: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_220: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial99", "stage7.hamming_weight_claim_reduction.claim.33.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_218: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_221: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial100", "stage7.hamming_weight_claim_reduction.claim.34.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_219: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_222: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial101", "stage7.hamming_weight_claim_reduction.claim.34.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_220: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_223: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial102", "stage7.hamming_weight_claim_reduction.claim.34.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_221: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_224: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial103", "stage7.hamming_weight_claim_reduction.claim.35.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_222: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_225: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial104", "stage7.hamming_weight_claim_reduction.claim.35.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_223: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_226: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial105", "stage7.hamming_weight_claim_reduction.claim.35.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_224: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_227: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial106", "stage7.hamming_weight_claim_reduction.claim.36.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_225: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_228: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial107", "stage7.hamming_weight_claim_reduction.claim.36.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_226: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_229: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial108", "stage7.hamming_weight_claim_reduction.claim.36.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_227: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_230: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial109", "stage7.hamming_weight_claim_reduction.claim.37.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_228: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_231: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial110", "stage7.hamming_weight_claim_reduction.claim.37.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_229: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_232: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial111", "stage7.hamming_weight_claim_reduction.claim.37.virtualization.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_230: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_233: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial112", "stage7.hamming_weight_claim_reduction.claim.38.hw.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_231: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_234: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial113", "stage7.hamming_weight_claim_reduction.claim.38.booleanity.gamma_term", ]; -pub const STAGE7_FIELD_EXPR_OPERANDS_232: &[&str] = &[ +pub const STAGE7_FIELD_EXPR_OPERANDS_235: &[&str] = &[ "stage7.hamming_weight_claim_reduction.claim_expr.partial114", "stage7.hamming_weight_claim_reduction.claim.38.virtualization.gamma_term", ]; +pub const STAGE7_FIELD_EXPR_OPERANDS_236: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial115", + "stage7.hamming_weight_claim_reduction.claim.39.hw.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_237: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial116", + "stage7.hamming_weight_claim_reduction.claim.39.booleanity.gamma_term", +]; + +pub const STAGE7_FIELD_EXPR_OPERANDS_238: &[&str] = &[ + "stage7.hamming_weight_claim_reduction.claim_expr.partial117", + "stage7.hamming_weight_claim_reduction.claim.39.virtualization.gamma_term", +]; + pub const STAGE7_FIELD_EXPRS: &[Stage7FieldExprPlan] = &[ Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.0.booleanity.gamma_pow", kind: "op", formula: "field.pow:1", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.0.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_1, operands: STAGE7_FIELD_EXPR_OPERANDS_1 }, @@ -1505,122 +1537,131 @@ pub const STAGE7_FIELD_EXPRS: &[Stage7FieldExprPlan] = &[ Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.38.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_115, operands: STAGE7_FIELD_EXPR_OPERANDS_115 }, Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.38.virtualization.gamma_pow", kind: "op", formula: "field.pow:116", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.38.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_116, operands: STAGE7_FIELD_EXPR_OPERANDS_116 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial0", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_117, operands: STAGE7_FIELD_EXPR_OPERANDS_117 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial1", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_118, operands: STAGE7_FIELD_EXPR_OPERANDS_118 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial2", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_119, operands: STAGE7_FIELD_EXPR_OPERANDS_119 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial3", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_120, operands: STAGE7_FIELD_EXPR_OPERANDS_120 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial4", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_121, operands: STAGE7_FIELD_EXPR_OPERANDS_121 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial5", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_122, operands: STAGE7_FIELD_EXPR_OPERANDS_122 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial6", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_123, operands: STAGE7_FIELD_EXPR_OPERANDS_123 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial7", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_124, operands: STAGE7_FIELD_EXPR_OPERANDS_124 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial8", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_125, operands: STAGE7_FIELD_EXPR_OPERANDS_125 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial9", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_126, operands: STAGE7_FIELD_EXPR_OPERANDS_126 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial10", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_127, operands: STAGE7_FIELD_EXPR_OPERANDS_127 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial11", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_128, operands: STAGE7_FIELD_EXPR_OPERANDS_128 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial12", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_129, operands: STAGE7_FIELD_EXPR_OPERANDS_129 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial13", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_130, operands: STAGE7_FIELD_EXPR_OPERANDS_130 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial14", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_131, operands: STAGE7_FIELD_EXPR_OPERANDS_131 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial15", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_132, operands: STAGE7_FIELD_EXPR_OPERANDS_132 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial16", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_133, operands: STAGE7_FIELD_EXPR_OPERANDS_133 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial17", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_134, operands: STAGE7_FIELD_EXPR_OPERANDS_134 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial18", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_135, operands: STAGE7_FIELD_EXPR_OPERANDS_135 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial19", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_136, operands: STAGE7_FIELD_EXPR_OPERANDS_136 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial20", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_137, operands: STAGE7_FIELD_EXPR_OPERANDS_137 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial21", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_138, operands: STAGE7_FIELD_EXPR_OPERANDS_138 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial22", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_139, operands: STAGE7_FIELD_EXPR_OPERANDS_139 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial23", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_140, operands: STAGE7_FIELD_EXPR_OPERANDS_140 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial24", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_141, operands: STAGE7_FIELD_EXPR_OPERANDS_141 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial25", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_142, operands: STAGE7_FIELD_EXPR_OPERANDS_142 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial26", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_143, operands: STAGE7_FIELD_EXPR_OPERANDS_143 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial27", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_144, operands: STAGE7_FIELD_EXPR_OPERANDS_144 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial28", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_145, operands: STAGE7_FIELD_EXPR_OPERANDS_145 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial29", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_146, operands: STAGE7_FIELD_EXPR_OPERANDS_146 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial30", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_147, operands: STAGE7_FIELD_EXPR_OPERANDS_147 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial31", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_148, operands: STAGE7_FIELD_EXPR_OPERANDS_148 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial32", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_149, operands: STAGE7_FIELD_EXPR_OPERANDS_149 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial33", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_150, operands: STAGE7_FIELD_EXPR_OPERANDS_150 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial34", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_151, operands: STAGE7_FIELD_EXPR_OPERANDS_151 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial35", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_152, operands: STAGE7_FIELD_EXPR_OPERANDS_152 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial36", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_153, operands: STAGE7_FIELD_EXPR_OPERANDS_153 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial37", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_154, operands: STAGE7_FIELD_EXPR_OPERANDS_154 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial38", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_155, operands: STAGE7_FIELD_EXPR_OPERANDS_155 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial39", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_156, operands: STAGE7_FIELD_EXPR_OPERANDS_156 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial40", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_157, operands: STAGE7_FIELD_EXPR_OPERANDS_157 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial41", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_158, operands: STAGE7_FIELD_EXPR_OPERANDS_158 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial42", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_159, operands: STAGE7_FIELD_EXPR_OPERANDS_159 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial43", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_160, operands: STAGE7_FIELD_EXPR_OPERANDS_160 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial44", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_161, operands: STAGE7_FIELD_EXPR_OPERANDS_161 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial45", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_162, operands: STAGE7_FIELD_EXPR_OPERANDS_162 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial46", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_163, operands: STAGE7_FIELD_EXPR_OPERANDS_163 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial47", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_164, operands: STAGE7_FIELD_EXPR_OPERANDS_164 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial48", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_165, operands: STAGE7_FIELD_EXPR_OPERANDS_165 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial49", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_166, operands: STAGE7_FIELD_EXPR_OPERANDS_166 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial50", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_167, operands: STAGE7_FIELD_EXPR_OPERANDS_167 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial51", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_168, operands: STAGE7_FIELD_EXPR_OPERANDS_168 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial52", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_169, operands: STAGE7_FIELD_EXPR_OPERANDS_169 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial53", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_170, operands: STAGE7_FIELD_EXPR_OPERANDS_170 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial54", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_171, operands: STAGE7_FIELD_EXPR_OPERANDS_171 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial55", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_172, operands: STAGE7_FIELD_EXPR_OPERANDS_172 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial56", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_173, operands: STAGE7_FIELD_EXPR_OPERANDS_173 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial57", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_174, operands: STAGE7_FIELD_EXPR_OPERANDS_174 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial58", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_175, operands: STAGE7_FIELD_EXPR_OPERANDS_175 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial59", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_176, operands: STAGE7_FIELD_EXPR_OPERANDS_176 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial60", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_177, operands: STAGE7_FIELD_EXPR_OPERANDS_177 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial61", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_178, operands: STAGE7_FIELD_EXPR_OPERANDS_178 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial62", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_179, operands: STAGE7_FIELD_EXPR_OPERANDS_179 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial63", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_180, operands: STAGE7_FIELD_EXPR_OPERANDS_180 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial64", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_181, operands: STAGE7_FIELD_EXPR_OPERANDS_181 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial65", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_182, operands: STAGE7_FIELD_EXPR_OPERANDS_182 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial66", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_183, operands: STAGE7_FIELD_EXPR_OPERANDS_183 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial67", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_184, operands: STAGE7_FIELD_EXPR_OPERANDS_184 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial68", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_185, operands: STAGE7_FIELD_EXPR_OPERANDS_185 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial69", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_186, operands: STAGE7_FIELD_EXPR_OPERANDS_186 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial70", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_187, operands: STAGE7_FIELD_EXPR_OPERANDS_187 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial71", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_188, operands: STAGE7_FIELD_EXPR_OPERANDS_188 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial72", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_189, operands: STAGE7_FIELD_EXPR_OPERANDS_189 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial73", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_190, operands: STAGE7_FIELD_EXPR_OPERANDS_190 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial74", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_191, operands: STAGE7_FIELD_EXPR_OPERANDS_191 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial75", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_192, operands: STAGE7_FIELD_EXPR_OPERANDS_192 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial76", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_193, operands: STAGE7_FIELD_EXPR_OPERANDS_193 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial77", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_194, operands: STAGE7_FIELD_EXPR_OPERANDS_194 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial78", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_195, operands: STAGE7_FIELD_EXPR_OPERANDS_195 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial79", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_196, operands: STAGE7_FIELD_EXPR_OPERANDS_196 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial80", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_197, operands: STAGE7_FIELD_EXPR_OPERANDS_197 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial81", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_198, operands: STAGE7_FIELD_EXPR_OPERANDS_198 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial82", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_199, operands: STAGE7_FIELD_EXPR_OPERANDS_199 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial83", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_200, operands: STAGE7_FIELD_EXPR_OPERANDS_200 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial84", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_201, operands: STAGE7_FIELD_EXPR_OPERANDS_201 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial85", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_202, operands: STAGE7_FIELD_EXPR_OPERANDS_202 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial86", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_203, operands: STAGE7_FIELD_EXPR_OPERANDS_203 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial87", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_204, operands: STAGE7_FIELD_EXPR_OPERANDS_204 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial88", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_205, operands: STAGE7_FIELD_EXPR_OPERANDS_205 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial89", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_206, operands: STAGE7_FIELD_EXPR_OPERANDS_206 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial90", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_207, operands: STAGE7_FIELD_EXPR_OPERANDS_207 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial91", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_208, operands: STAGE7_FIELD_EXPR_OPERANDS_208 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial92", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_209, operands: STAGE7_FIELD_EXPR_OPERANDS_209 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial93", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_210, operands: STAGE7_FIELD_EXPR_OPERANDS_210 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial94", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_211, operands: STAGE7_FIELD_EXPR_OPERANDS_211 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial95", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_212, operands: STAGE7_FIELD_EXPR_OPERANDS_212 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial96", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_213, operands: STAGE7_FIELD_EXPR_OPERANDS_213 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial97", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_214, operands: STAGE7_FIELD_EXPR_OPERANDS_214 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial98", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_215, operands: STAGE7_FIELD_EXPR_OPERANDS_215 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial99", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_216, operands: STAGE7_FIELD_EXPR_OPERANDS_216 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial100", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_217, operands: STAGE7_FIELD_EXPR_OPERANDS_217 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial101", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_218, operands: STAGE7_FIELD_EXPR_OPERANDS_218 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial102", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_219, operands: STAGE7_FIELD_EXPR_OPERANDS_219 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial103", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_220, operands: STAGE7_FIELD_EXPR_OPERANDS_220 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial104", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_221, operands: STAGE7_FIELD_EXPR_OPERANDS_221 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial105", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_222, operands: STAGE7_FIELD_EXPR_OPERANDS_222 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial106", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_223, operands: STAGE7_FIELD_EXPR_OPERANDS_223 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial107", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_224, operands: STAGE7_FIELD_EXPR_OPERANDS_224 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial108", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_225, operands: STAGE7_FIELD_EXPR_OPERANDS_225 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial109", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_226, operands: STAGE7_FIELD_EXPR_OPERANDS_226 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial110", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_227, operands: STAGE7_FIELD_EXPR_OPERANDS_227 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial111", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_228, operands: STAGE7_FIELD_EXPR_OPERANDS_228 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial112", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_229, operands: STAGE7_FIELD_EXPR_OPERANDS_229 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial113", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_230, operands: STAGE7_FIELD_EXPR_OPERANDS_230 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial114", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_231, operands: STAGE7_FIELD_EXPR_OPERANDS_231 }, - Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial115", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_232, operands: STAGE7_FIELD_EXPR_OPERANDS_232 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.39.hw.gamma_pow", kind: "op", formula: "field.pow:117", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.39.hw.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_117, operands: STAGE7_FIELD_EXPR_OPERANDS_117 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.39.booleanity.gamma_pow", kind: "op", formula: "field.pow:118", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.39.booleanity.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_118, operands: STAGE7_FIELD_EXPR_OPERANDS_118 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.39.virtualization.gamma_pow", kind: "op", formula: "field.pow:119", operand_names: STAGE7_FIELD_EXPR_OPERANDS_0, operands: STAGE7_FIELD_EXPR_OPERANDS_0 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim.39.virtualization.gamma_term", kind: "op", formula: "field.mul", operand_names: STAGE7_FIELD_EXPR_OPERANDS_119, operands: STAGE7_FIELD_EXPR_OPERANDS_119 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial0", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_120, operands: STAGE7_FIELD_EXPR_OPERANDS_120 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial1", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_121, operands: STAGE7_FIELD_EXPR_OPERANDS_121 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial2", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_122, operands: STAGE7_FIELD_EXPR_OPERANDS_122 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial3", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_123, operands: STAGE7_FIELD_EXPR_OPERANDS_123 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial4", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_124, operands: STAGE7_FIELD_EXPR_OPERANDS_124 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial5", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_125, operands: STAGE7_FIELD_EXPR_OPERANDS_125 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial6", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_126, operands: STAGE7_FIELD_EXPR_OPERANDS_126 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial7", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_127, operands: STAGE7_FIELD_EXPR_OPERANDS_127 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial8", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_128, operands: STAGE7_FIELD_EXPR_OPERANDS_128 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial9", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_129, operands: STAGE7_FIELD_EXPR_OPERANDS_129 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial10", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_130, operands: STAGE7_FIELD_EXPR_OPERANDS_130 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial11", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_131, operands: STAGE7_FIELD_EXPR_OPERANDS_131 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial12", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_132, operands: STAGE7_FIELD_EXPR_OPERANDS_132 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial13", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_133, operands: STAGE7_FIELD_EXPR_OPERANDS_133 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial14", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_134, operands: STAGE7_FIELD_EXPR_OPERANDS_134 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial15", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_135, operands: STAGE7_FIELD_EXPR_OPERANDS_135 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial16", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_136, operands: STAGE7_FIELD_EXPR_OPERANDS_136 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial17", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_137, operands: STAGE7_FIELD_EXPR_OPERANDS_137 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial18", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_138, operands: STAGE7_FIELD_EXPR_OPERANDS_138 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial19", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_139, operands: STAGE7_FIELD_EXPR_OPERANDS_139 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial20", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_140, operands: STAGE7_FIELD_EXPR_OPERANDS_140 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial21", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_141, operands: STAGE7_FIELD_EXPR_OPERANDS_141 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial22", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_142, operands: STAGE7_FIELD_EXPR_OPERANDS_142 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial23", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_143, operands: STAGE7_FIELD_EXPR_OPERANDS_143 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial24", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_144, operands: STAGE7_FIELD_EXPR_OPERANDS_144 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial25", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_145, operands: STAGE7_FIELD_EXPR_OPERANDS_145 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial26", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_146, operands: STAGE7_FIELD_EXPR_OPERANDS_146 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial27", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_147, operands: STAGE7_FIELD_EXPR_OPERANDS_147 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial28", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_148, operands: STAGE7_FIELD_EXPR_OPERANDS_148 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial29", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_149, operands: STAGE7_FIELD_EXPR_OPERANDS_149 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial30", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_150, operands: STAGE7_FIELD_EXPR_OPERANDS_150 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial31", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_151, operands: STAGE7_FIELD_EXPR_OPERANDS_151 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial32", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_152, operands: STAGE7_FIELD_EXPR_OPERANDS_152 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial33", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_153, operands: STAGE7_FIELD_EXPR_OPERANDS_153 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial34", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_154, operands: STAGE7_FIELD_EXPR_OPERANDS_154 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial35", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_155, operands: STAGE7_FIELD_EXPR_OPERANDS_155 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial36", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_156, operands: STAGE7_FIELD_EXPR_OPERANDS_156 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial37", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_157, operands: STAGE7_FIELD_EXPR_OPERANDS_157 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial38", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_158, operands: STAGE7_FIELD_EXPR_OPERANDS_158 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial39", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_159, operands: STAGE7_FIELD_EXPR_OPERANDS_159 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial40", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_160, operands: STAGE7_FIELD_EXPR_OPERANDS_160 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial41", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_161, operands: STAGE7_FIELD_EXPR_OPERANDS_161 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial42", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_162, operands: STAGE7_FIELD_EXPR_OPERANDS_162 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial43", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_163, operands: STAGE7_FIELD_EXPR_OPERANDS_163 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial44", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_164, operands: STAGE7_FIELD_EXPR_OPERANDS_164 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial45", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_165, operands: STAGE7_FIELD_EXPR_OPERANDS_165 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial46", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_166, operands: STAGE7_FIELD_EXPR_OPERANDS_166 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial47", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_167, operands: STAGE7_FIELD_EXPR_OPERANDS_167 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial48", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_168, operands: STAGE7_FIELD_EXPR_OPERANDS_168 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial49", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_169, operands: STAGE7_FIELD_EXPR_OPERANDS_169 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial50", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_170, operands: STAGE7_FIELD_EXPR_OPERANDS_170 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial51", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_171, operands: STAGE7_FIELD_EXPR_OPERANDS_171 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial52", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_172, operands: STAGE7_FIELD_EXPR_OPERANDS_172 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial53", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_173, operands: STAGE7_FIELD_EXPR_OPERANDS_173 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial54", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_174, operands: STAGE7_FIELD_EXPR_OPERANDS_174 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial55", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_175, operands: STAGE7_FIELD_EXPR_OPERANDS_175 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial56", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_176, operands: STAGE7_FIELD_EXPR_OPERANDS_176 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial57", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_177, operands: STAGE7_FIELD_EXPR_OPERANDS_177 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial58", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_178, operands: STAGE7_FIELD_EXPR_OPERANDS_178 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial59", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_179, operands: STAGE7_FIELD_EXPR_OPERANDS_179 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial60", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_180, operands: STAGE7_FIELD_EXPR_OPERANDS_180 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial61", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_181, operands: STAGE7_FIELD_EXPR_OPERANDS_181 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial62", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_182, operands: STAGE7_FIELD_EXPR_OPERANDS_182 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial63", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_183, operands: STAGE7_FIELD_EXPR_OPERANDS_183 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial64", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_184, operands: STAGE7_FIELD_EXPR_OPERANDS_184 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial65", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_185, operands: STAGE7_FIELD_EXPR_OPERANDS_185 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial66", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_186, operands: STAGE7_FIELD_EXPR_OPERANDS_186 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial67", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_187, operands: STAGE7_FIELD_EXPR_OPERANDS_187 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial68", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_188, operands: STAGE7_FIELD_EXPR_OPERANDS_188 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial69", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_189, operands: STAGE7_FIELD_EXPR_OPERANDS_189 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial70", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_190, operands: STAGE7_FIELD_EXPR_OPERANDS_190 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial71", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_191, operands: STAGE7_FIELD_EXPR_OPERANDS_191 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial72", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_192, operands: STAGE7_FIELD_EXPR_OPERANDS_192 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial73", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_193, operands: STAGE7_FIELD_EXPR_OPERANDS_193 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial74", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_194, operands: STAGE7_FIELD_EXPR_OPERANDS_194 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial75", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_195, operands: STAGE7_FIELD_EXPR_OPERANDS_195 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial76", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_196, operands: STAGE7_FIELD_EXPR_OPERANDS_196 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial77", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_197, operands: STAGE7_FIELD_EXPR_OPERANDS_197 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial78", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_198, operands: STAGE7_FIELD_EXPR_OPERANDS_198 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial79", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_199, operands: STAGE7_FIELD_EXPR_OPERANDS_199 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial80", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_200, operands: STAGE7_FIELD_EXPR_OPERANDS_200 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial81", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_201, operands: STAGE7_FIELD_EXPR_OPERANDS_201 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial82", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_202, operands: STAGE7_FIELD_EXPR_OPERANDS_202 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial83", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_203, operands: STAGE7_FIELD_EXPR_OPERANDS_203 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial84", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_204, operands: STAGE7_FIELD_EXPR_OPERANDS_204 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial85", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_205, operands: STAGE7_FIELD_EXPR_OPERANDS_205 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial86", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_206, operands: STAGE7_FIELD_EXPR_OPERANDS_206 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial87", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_207, operands: STAGE7_FIELD_EXPR_OPERANDS_207 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial88", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_208, operands: STAGE7_FIELD_EXPR_OPERANDS_208 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial89", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_209, operands: STAGE7_FIELD_EXPR_OPERANDS_209 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial90", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_210, operands: STAGE7_FIELD_EXPR_OPERANDS_210 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial91", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_211, operands: STAGE7_FIELD_EXPR_OPERANDS_211 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial92", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_212, operands: STAGE7_FIELD_EXPR_OPERANDS_212 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial93", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_213, operands: STAGE7_FIELD_EXPR_OPERANDS_213 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial94", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_214, operands: STAGE7_FIELD_EXPR_OPERANDS_214 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial95", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_215, operands: STAGE7_FIELD_EXPR_OPERANDS_215 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial96", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_216, operands: STAGE7_FIELD_EXPR_OPERANDS_216 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial97", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_217, operands: STAGE7_FIELD_EXPR_OPERANDS_217 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial98", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_218, operands: STAGE7_FIELD_EXPR_OPERANDS_218 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial99", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_219, operands: STAGE7_FIELD_EXPR_OPERANDS_219 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial100", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_220, operands: STAGE7_FIELD_EXPR_OPERANDS_220 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial101", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_221, operands: STAGE7_FIELD_EXPR_OPERANDS_221 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial102", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_222, operands: STAGE7_FIELD_EXPR_OPERANDS_222 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial103", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_223, operands: STAGE7_FIELD_EXPR_OPERANDS_223 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial104", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_224, operands: STAGE7_FIELD_EXPR_OPERANDS_224 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial105", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_225, operands: STAGE7_FIELD_EXPR_OPERANDS_225 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial106", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_226, operands: STAGE7_FIELD_EXPR_OPERANDS_226 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial107", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_227, operands: STAGE7_FIELD_EXPR_OPERANDS_227 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial108", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_228, operands: STAGE7_FIELD_EXPR_OPERANDS_228 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial109", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_229, operands: STAGE7_FIELD_EXPR_OPERANDS_229 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial110", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_230, operands: STAGE7_FIELD_EXPR_OPERANDS_230 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial111", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_231, operands: STAGE7_FIELD_EXPR_OPERANDS_231 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial112", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_232, operands: STAGE7_FIELD_EXPR_OPERANDS_232 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial113", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_233, operands: STAGE7_FIELD_EXPR_OPERANDS_233 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial114", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_234, operands: STAGE7_FIELD_EXPR_OPERANDS_234 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial115", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_235, operands: STAGE7_FIELD_EXPR_OPERANDS_235 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial116", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_236, operands: STAGE7_FIELD_EXPR_OPERANDS_236 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial117", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_237, operands: STAGE7_FIELD_EXPR_OPERANDS_237 }, + Stage7FieldExprPlan { symbol: "stage7.hamming_weight_claim_reduction.claim_expr.partial118", kind: "op", formula: "field.add", operand_names: STAGE7_FIELD_EXPR_OPERANDS_238, operands: STAGE7_FIELD_EXPR_OPERANDS_238 }, ]; pub const STAGE7_KERNELS: &[Stage7KernelPlan] = &[ Stage7KernelPlan { symbol: "jolt.cpu.stage7.hamming_weight_claim_reduction", relation: "jolt.stage7.hamming_weight_claim_reduction", kind: "sumcheck", backend: "cpu", abi: "jolt_stage7_hamming_weight_claim_reduction" }, @@ -1699,6 +1740,8 @@ pub const STAGE7_SUMCHECK_CLAIM_0_INPUT_OPENINGS: &[&str] = &[ "stage7.input.stage6.bytecode_read_raf.BytecodeRa_1", "stage7.input.stage6.booleanity.BytecodeRa_2", "stage7.input.stage6.bytecode_read_raf.BytecodeRa_2", + "stage7.input.stage6.booleanity.BytecodeRa_3", + "stage7.input.stage6.bytecode_read_raf.BytecodeRa_3", "stage7.input.stage6.booleanity.RamRa_0", "stage7.input.stage6.ram_ra_virtual.RamRa_0", "stage7.input.stage6.booleanity.RamRa_1", @@ -1710,7 +1753,7 @@ pub const STAGE7_SUMCHECK_CLAIM_0_INPUT_OPENINGS: &[&str] = &[ ]; pub const STAGE7_SUMCHECK_CLAIMS: &[Stage7SumcheckClaimPlan] = &[ - Stage7SumcheckClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.input", stage: "stage7", domain: "jolt.stage7_hamming_weight_claim_reduction_domain", num_rounds: 4, degree: 2, claim: "stage7.hamming_weight_claim_reduction.weighted_stage6_claims", kernel: Some("jolt.cpu.stage7.hamming_weight_claim_reduction"), relation: None, claim_value: "stage7.hamming_weight_claim_reduction.claim_expr.partial115", input_openings: STAGE7_SUMCHECK_CLAIM_0_INPUT_OPENINGS }, + Stage7SumcheckClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.input", stage: "stage7", domain: "jolt.stage7_hamming_weight_claim_reduction_domain", num_rounds: 4, degree: 2, claim: "stage7.hamming_weight_claim_reduction.weighted_stage6_claims", kernel: Some("jolt.cpu.stage7.hamming_weight_claim_reduction"), relation: None, claim_value: "stage7.hamming_weight_claim_reduction.claim_expr.partial118", input_openings: STAGE7_SUMCHECK_CLAIM_0_INPUT_OPENINGS }, ]; pub const STAGE7_SUMCHECK_BATCH_0_ORDERED_CLAIMS: &[&str] = &["stage7.hamming_weight_claim_reduction.input"]; @@ -1750,8 +1793,8 @@ pub const STAGE7_SUMCHECK_EVALS: &[Stage7SumcheckEvalPlan] = &[ stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_20", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_20", 20, "InstructionRa_20"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_21", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_21", 21, "InstructionRa_21"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_22", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_22", 22, "InstructionRa_22"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_23", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_23", 23, "InstructionRa_23"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_24", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_24", 24, "InstructionRa_24"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_25", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_25", 25, "InstructionRa_25"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_26", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_26", 26, "InstructionRa_26"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_27", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_27", 27, "InstructionRa_27"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_28", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_28", 28, "InstructionRa_28"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_29", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_29", 29, "InstructionRa_29"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_30", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_30", 30, "InstructionRa_30"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_31", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_31", 31, "InstructionRa_31"), - stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.BytecodeRa_0", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_0", 32, "BytecodeRa_0"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.BytecodeRa_1", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_1", 33, "BytecodeRa_1"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.BytecodeRa_2", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_2", 34, "BytecodeRa_2"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.RamRa_0", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.RamRa_0", 35, "RamRa_0"), - stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.RamRa_1", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.RamRa_1", 36, "RamRa_1"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.RamRa_2", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.RamRa_2", 37, "RamRa_2"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.RamRa_3", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.RamRa_3", 38, "RamRa_3"), + stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.BytecodeRa_0", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_0", 32, "BytecodeRa_0"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.BytecodeRa_1", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_1", 33, "BytecodeRa_1"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.BytecodeRa_2", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_2", 34, "BytecodeRa_2"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.BytecodeRa_3", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_3", 35, "BytecodeRa_3"), + stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.RamRa_0", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.RamRa_0", 36, "RamRa_0"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.RamRa_1", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.RamRa_1", 37, "RamRa_1"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.RamRa_2", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.RamRa_2", 38, "RamRa_2"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.RamRa_3", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.RamRa_3", 39, "RamRa_3"), ]; pub const STAGE7_POINT_ZEROS: &[Stage7PointZeroPlan] = &[ @@ -1759,7 +1802,7 @@ pub const STAGE7_POINT_ZEROS: &[Stage7PointZeroPlan] = &[ ]; pub const STAGE7_POINT_SLICES: &[Stage7PointSlicePlan] = &[ - Stage7PointSlicePlan { symbol: "stage7.hamming_weight_claim_reduction.point.cycle", source: "stage7.input.stage6.booleanity.InstructionRa_0", offset: 4, length: 16, input: "stage7.input.stage6.booleanity.InstructionRa_0" }, + Stage7PointSlicePlan { symbol: "stage7.hamming_weight_claim_reduction.point.cycle", source: "stage7.input.stage6.booleanity.InstructionRa_0", offset: 4, length: 18, input: "stage7.input.stage6.booleanity.InstructionRa_0" }, ]; pub const STAGE7_POINT_CONCAT_0_INPUTS: &[&str] = &[ @@ -1768,48 +1811,49 @@ pub const STAGE7_POINT_CONCAT_0_INPUTS: &[&str] = &[ ]; pub const STAGE7_POINT_CONCATS: &[Stage7PointConcatPlan] = &[ - Stage7PointConcatPlan { symbol: "stage7.hamming_weight_claim_reduction.point", layout: "address_chunk_then_cycle", arity: 20, inputs: STAGE7_POINT_CONCAT_0_INPUTS }, + Stage7PointConcatPlan { symbol: "stage7.hamming_weight_claim_reduction.point", layout: "address_chunk_then_cycle", arity: 22, inputs: STAGE7_POINT_CONCAT_0_INPUTS }, ]; pub const STAGE7_OPENING_CLAIMS: &[Stage7OpeningClaimPlan] = &[ - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_0" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_1" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_2" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_3" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_4" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_5" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_6" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_7" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_8" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_9" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_10" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_11" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_12" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_13" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_14" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_15" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_16" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_17" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_18" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_19" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_20" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_21" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_22" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_23" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_24" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_25" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_26" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_27" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_28" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_29" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_30" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_31" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_0" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_1" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_2" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.RamRa_0" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.RamRa_1" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.RamRa_2" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.RamRa_3" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_0" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_1" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_2" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_3" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_4" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_5" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_6" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_7" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_8" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_9" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_10" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_11" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_12" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_13" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_14" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_15" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_16" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_17" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_18" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_19" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_20" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_21" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_22" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_23" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_24" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_25" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_26" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_27" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_28" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_29" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_30" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_31" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_0" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_1" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_2" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_3", oracle: "BytecodeRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_3" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.RamRa_0" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.RamRa_1" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.RamRa_2" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.RamRa_3" }, ]; pub const STAGE7_OPENING_EQUALITIES: &[Stage7OpeningClaimEqualityPlan] = &[ @@ -1852,6 +1896,7 @@ pub const STAGE7_OPENING_BATCH_0_ORDERED_CLAIMS: &[&str] = &[ "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_0", "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_1", "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_2", + "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_3", "stage7.hamming_weight_claim_reduction.opening.RamRa_0", "stage7.hamming_weight_claim_reduction.opening.RamRa_1", "stage7.hamming_weight_claim_reduction.opening.RamRa_2", @@ -1894,6 +1939,7 @@ pub const STAGE7_OPENING_BATCH_0_CLAIM_OPERANDS: &[&str] = &[ "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_0", "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_1", "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_2", + "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_3", "stage7.hamming_weight_claim_reduction.opening.RamRa_0", "stage7.hamming_weight_claim_reduction.opening.RamRa_1", "stage7.hamming_weight_claim_reduction.opening.RamRa_2", @@ -1901,7 +1947,7 @@ pub const STAGE7_OPENING_BATCH_0_CLAIM_OPERANDS: &[&str] = &[ ]; pub const STAGE7_OPENING_BATCHES: &[Stage7OpeningBatchPlan] = &[ - Stage7OpeningBatchPlan { symbol: "stage7.openings", stage: "stage7", proof_slot: "stage7.openings", policy: "jolt_stage7_output_order", count: 39, ordered_claims: STAGE7_OPENING_BATCH_0_ORDERED_CLAIMS, claim_operands: STAGE7_OPENING_BATCH_0_CLAIM_OPERANDS }, + Stage7OpeningBatchPlan { symbol: "stage7.openings", stage: "stage7", proof_slot: "stage7.openings", policy: "jolt_stage7_output_order", count: 40, ordered_claims: STAGE7_OPENING_BATCH_0_ORDERED_CLAIMS, claim_operands: STAGE7_OPENING_BATCH_0_CLAIM_OPERANDS }, ]; pub const STAGE7_PROGRAM: Stage7CpuProgramPlan = Stage7CpuProgramPlan { role: "prover", diff --git a/crates/jolt-prover/src/stages/stage8.rs b/crates/jolt-prover/src/stages/stage8.rs index 632dbe3925..b2d7a77d6d 100644 --- a/crates/jolt-prover/src/stages/stage8.rs +++ b/crates/jolt-prover/src/stages/stage8.rs @@ -64,100 +64,102 @@ pub struct Stage8EvaluationProgramPlan { pub const STAGE8_PARAMS: Stage8Params = Stage8Params { field: "bn254_fr", pcs: "dory", transcript: "blake2b_transcript" }; -pub const STAGE8_EVALUATION_POINT_SOURCE: Stage8OpeningInputPlan = Stage8OpeningInputPlan { symbol: "stage8.evaluation.point_source", source_stage: "stage7", source_claim: "stage7.input.stage6.booleanity.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }; +pub const STAGE8_EVALUATION_POINT_SOURCE: Stage8OpeningInputPlan = Stage8OpeningInputPlan { symbol: "stage8.evaluation.point_source", source_stage: "stage7", source_claim: "stage7.input.stage6.booleanity.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }; pub const STAGE8_OPENING_INPUTS: &[Stage8OpeningInputPlan] = &[ - Stage8OpeningInputPlan { symbol: "stage8.evaluation.point_source", source_stage: "stage7", source_claim: "stage7.input.stage6.booleanity.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage6.RamInc", source_stage: "stage6", source_claim: "stage6.inc_claim_reduction.eval.RamInc", oracle: "RamInc", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage6.RdInc", source_stage: "stage6", source_claim: "stage6.inc_claim_reduction.eval.RdInc", oracle: "RdInc", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_3", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_4", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_5", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_6", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_7", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_8", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_9", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_10", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_11", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_12", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_13", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_14", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_15", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_16", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_17", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_18", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_19", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_20", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_21", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_22", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_23", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_24", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_25", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_26", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_27", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_28", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_29", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_30", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_31", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.BytecodeRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.BytecodeRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.BytecodeRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.RamRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.RamRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.RamRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.RamRa_3", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.evaluation.point_source", source_stage: "stage7", source_claim: "stage7.input.stage6.booleanity.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage6.RamInc", source_stage: "stage6", source_claim: "stage6.inc_claim_reduction.eval.RamInc", oracle: "RamInc", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage6.RdInc", source_stage: "stage6", source_claim: "stage6.inc_claim_reduction.eval.RdInc", oracle: "RdInc", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_3", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_4", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_5", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_6", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_7", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_8", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_9", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_10", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_11", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_12", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_13", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_14", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_15", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_16", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_17", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_18", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_19", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_20", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_21", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_22", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_23", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_24", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_25", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_26", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_27", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_28", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_29", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_30", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_31", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.BytecodeRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.BytecodeRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.BytecodeRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.BytecodeRa_3", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_3", oracle: "BytecodeRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.RamRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.RamRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.RamRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.RamRa_3", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, ]; pub const STAGE8_OPENING_CLAIMS: &[Stage8OpeningClaimPlan] = &[ - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RamInc", oracle: "RamInc", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage6.RamInc", eval_source: "stage8.input.stage6.RamInc", source_stage: "stage6", source_claim: "stage6.inc_claim_reduction.eval.RamInc" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RdInc", oracle: "RdInc", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage6.RdInc", eval_source: "stage8.input.stage6.RdInc", source_stage: "stage6", source_claim: "stage6.inc_claim_reduction.eval.RdInc" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_0", oracle: "InstructionRa_0", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_0", eval_source: "stage8.input.stage7.InstructionRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_0" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_1", oracle: "InstructionRa_1", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_1", eval_source: "stage8.input.stage7.InstructionRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_1" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_2", oracle: "InstructionRa_2", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_2", eval_source: "stage8.input.stage7.InstructionRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_2" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_3", oracle: "InstructionRa_3", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_3", eval_source: "stage8.input.stage7.InstructionRa_3", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_3" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_4", oracle: "InstructionRa_4", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_4", eval_source: "stage8.input.stage7.InstructionRa_4", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_4" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_5", oracle: "InstructionRa_5", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_5", eval_source: "stage8.input.stage7.InstructionRa_5", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_5" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_6", oracle: "InstructionRa_6", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_6", eval_source: "stage8.input.stage7.InstructionRa_6", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_6" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_7", oracle: "InstructionRa_7", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_7", eval_source: "stage8.input.stage7.InstructionRa_7", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_7" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_8", oracle: "InstructionRa_8", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_8", eval_source: "stage8.input.stage7.InstructionRa_8", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_8" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_9", oracle: "InstructionRa_9", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_9", eval_source: "stage8.input.stage7.InstructionRa_9", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_9" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_10", oracle: "InstructionRa_10", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_10", eval_source: "stage8.input.stage7.InstructionRa_10", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_10" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_11", oracle: "InstructionRa_11", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_11", eval_source: "stage8.input.stage7.InstructionRa_11", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_11" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_12", oracle: "InstructionRa_12", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_12", eval_source: "stage8.input.stage7.InstructionRa_12", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_12" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_13", oracle: "InstructionRa_13", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_13", eval_source: "stage8.input.stage7.InstructionRa_13", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_13" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_14", oracle: "InstructionRa_14", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_14", eval_source: "stage8.input.stage7.InstructionRa_14", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_14" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_15", oracle: "InstructionRa_15", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_15", eval_source: "stage8.input.stage7.InstructionRa_15", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_15" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_16", oracle: "InstructionRa_16", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_16", eval_source: "stage8.input.stage7.InstructionRa_16", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_16" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_17", oracle: "InstructionRa_17", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_17", eval_source: "stage8.input.stage7.InstructionRa_17", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_17" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_18", oracle: "InstructionRa_18", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_18", eval_source: "stage8.input.stage7.InstructionRa_18", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_18" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_19", oracle: "InstructionRa_19", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_19", eval_source: "stage8.input.stage7.InstructionRa_19", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_19" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_20", oracle: "InstructionRa_20", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_20", eval_source: "stage8.input.stage7.InstructionRa_20", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_20" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_21", oracle: "InstructionRa_21", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_21", eval_source: "stage8.input.stage7.InstructionRa_21", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_21" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_22", oracle: "InstructionRa_22", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_22", eval_source: "stage8.input.stage7.InstructionRa_22", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_22" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_23", oracle: "InstructionRa_23", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_23", eval_source: "stage8.input.stage7.InstructionRa_23", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_23" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_24", oracle: "InstructionRa_24", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_24", eval_source: "stage8.input.stage7.InstructionRa_24", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_24" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_25", oracle: "InstructionRa_25", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_25", eval_source: "stage8.input.stage7.InstructionRa_25", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_25" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_26", oracle: "InstructionRa_26", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_26", eval_source: "stage8.input.stage7.InstructionRa_26", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_26" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_27", oracle: "InstructionRa_27", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_27", eval_source: "stage8.input.stage7.InstructionRa_27", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_27" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_28", oracle: "InstructionRa_28", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_28", eval_source: "stage8.input.stage7.InstructionRa_28", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_28" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_29", oracle: "InstructionRa_29", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_29", eval_source: "stage8.input.stage7.InstructionRa_29", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_29" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_30", oracle: "InstructionRa_30", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_30", eval_source: "stage8.input.stage7.InstructionRa_30", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_30" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_31", oracle: "InstructionRa_31", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_31", eval_source: "stage8.input.stage7.InstructionRa_31", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_31" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.BytecodeRa_0", oracle: "BytecodeRa_0", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.BytecodeRa_0", eval_source: "stage8.input.stage7.BytecodeRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_0" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.BytecodeRa_1", oracle: "BytecodeRa_1", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.BytecodeRa_1", eval_source: "stage8.input.stage7.BytecodeRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_1" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.BytecodeRa_2", oracle: "BytecodeRa_2", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.BytecodeRa_2", eval_source: "stage8.input.stage7.BytecodeRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_2" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RamRa_0", oracle: "RamRa_0", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.RamRa_0", eval_source: "stage8.input.stage7.RamRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_0" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RamRa_1", oracle: "RamRa_1", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.RamRa_1", eval_source: "stage8.input.stage7.RamRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_1" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RamRa_2", oracle: "RamRa_2", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.RamRa_2", eval_source: "stage8.input.stage7.RamRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_2" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RamRa_3", oracle: "RamRa_3", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.RamRa_3", eval_source: "stage8.input.stage7.RamRa_3", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_3" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RamInc", oracle: "RamInc", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage6.RamInc", eval_source: "stage8.input.stage6.RamInc", source_stage: "stage6", source_claim: "stage6.inc_claim_reduction.eval.RamInc" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RdInc", oracle: "RdInc", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage6.RdInc", eval_source: "stage8.input.stage6.RdInc", source_stage: "stage6", source_claim: "stage6.inc_claim_reduction.eval.RdInc" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_0", oracle: "InstructionRa_0", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_0", eval_source: "stage8.input.stage7.InstructionRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_0" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_1", oracle: "InstructionRa_1", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_1", eval_source: "stage8.input.stage7.InstructionRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_1" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_2", oracle: "InstructionRa_2", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_2", eval_source: "stage8.input.stage7.InstructionRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_2" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_3", oracle: "InstructionRa_3", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_3", eval_source: "stage8.input.stage7.InstructionRa_3", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_3" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_4", oracle: "InstructionRa_4", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_4", eval_source: "stage8.input.stage7.InstructionRa_4", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_4" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_5", oracle: "InstructionRa_5", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_5", eval_source: "stage8.input.stage7.InstructionRa_5", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_5" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_6", oracle: "InstructionRa_6", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_6", eval_source: "stage8.input.stage7.InstructionRa_6", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_6" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_7", oracle: "InstructionRa_7", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_7", eval_source: "stage8.input.stage7.InstructionRa_7", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_7" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_8", oracle: "InstructionRa_8", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_8", eval_source: "stage8.input.stage7.InstructionRa_8", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_8" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_9", oracle: "InstructionRa_9", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_9", eval_source: "stage8.input.stage7.InstructionRa_9", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_9" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_10", oracle: "InstructionRa_10", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_10", eval_source: "stage8.input.stage7.InstructionRa_10", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_10" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_11", oracle: "InstructionRa_11", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_11", eval_source: "stage8.input.stage7.InstructionRa_11", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_11" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_12", oracle: "InstructionRa_12", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_12", eval_source: "stage8.input.stage7.InstructionRa_12", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_12" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_13", oracle: "InstructionRa_13", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_13", eval_source: "stage8.input.stage7.InstructionRa_13", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_13" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_14", oracle: "InstructionRa_14", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_14", eval_source: "stage8.input.stage7.InstructionRa_14", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_14" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_15", oracle: "InstructionRa_15", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_15", eval_source: "stage8.input.stage7.InstructionRa_15", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_15" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_16", oracle: "InstructionRa_16", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_16", eval_source: "stage8.input.stage7.InstructionRa_16", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_16" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_17", oracle: "InstructionRa_17", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_17", eval_source: "stage8.input.stage7.InstructionRa_17", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_17" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_18", oracle: "InstructionRa_18", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_18", eval_source: "stage8.input.stage7.InstructionRa_18", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_18" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_19", oracle: "InstructionRa_19", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_19", eval_source: "stage8.input.stage7.InstructionRa_19", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_19" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_20", oracle: "InstructionRa_20", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_20", eval_source: "stage8.input.stage7.InstructionRa_20", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_20" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_21", oracle: "InstructionRa_21", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_21", eval_source: "stage8.input.stage7.InstructionRa_21", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_21" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_22", oracle: "InstructionRa_22", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_22", eval_source: "stage8.input.stage7.InstructionRa_22", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_22" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_23", oracle: "InstructionRa_23", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_23", eval_source: "stage8.input.stage7.InstructionRa_23", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_23" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_24", oracle: "InstructionRa_24", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_24", eval_source: "stage8.input.stage7.InstructionRa_24", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_24" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_25", oracle: "InstructionRa_25", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_25", eval_source: "stage8.input.stage7.InstructionRa_25", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_25" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_26", oracle: "InstructionRa_26", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_26", eval_source: "stage8.input.stage7.InstructionRa_26", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_26" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_27", oracle: "InstructionRa_27", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_27", eval_source: "stage8.input.stage7.InstructionRa_27", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_27" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_28", oracle: "InstructionRa_28", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_28", eval_source: "stage8.input.stage7.InstructionRa_28", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_28" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_29", oracle: "InstructionRa_29", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_29", eval_source: "stage8.input.stage7.InstructionRa_29", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_29" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_30", oracle: "InstructionRa_30", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_30", eval_source: "stage8.input.stage7.InstructionRa_30", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_30" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_31", oracle: "InstructionRa_31", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_31", eval_source: "stage8.input.stage7.InstructionRa_31", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_31" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.BytecodeRa_0", oracle: "BytecodeRa_0", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.BytecodeRa_0", eval_source: "stage8.input.stage7.BytecodeRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_0" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.BytecodeRa_1", oracle: "BytecodeRa_1", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.BytecodeRa_1", eval_source: "stage8.input.stage7.BytecodeRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_1" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.BytecodeRa_2", oracle: "BytecodeRa_2", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.BytecodeRa_2", eval_source: "stage8.input.stage7.BytecodeRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_2" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.BytecodeRa_3", oracle: "BytecodeRa_3", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.BytecodeRa_3", eval_source: "stage8.input.stage7.BytecodeRa_3", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_3" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RamRa_0", oracle: "RamRa_0", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.RamRa_0", eval_source: "stage8.input.stage7.RamRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_0" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RamRa_1", oracle: "RamRa_1", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.RamRa_1", eval_source: "stage8.input.stage7.RamRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_1" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RamRa_2", oracle: "RamRa_2", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.RamRa_2", eval_source: "stage8.input.stage7.RamRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_2" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RamRa_3", oracle: "RamRa_3", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.RamRa_3", eval_source: "stage8.input.stage7.RamRa_3", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_3" }, ]; -pub const STAGE8_OPENING_BATCH_ORDERED_CLAIMS: &[&str] = &["stage8.evaluation.opening.RamInc", "stage8.evaluation.opening.RdInc", "stage8.evaluation.opening.InstructionRa_0", "stage8.evaluation.opening.InstructionRa_1", "stage8.evaluation.opening.InstructionRa_2", "stage8.evaluation.opening.InstructionRa_3", "stage8.evaluation.opening.InstructionRa_4", "stage8.evaluation.opening.InstructionRa_5", "stage8.evaluation.opening.InstructionRa_6", "stage8.evaluation.opening.InstructionRa_7", "stage8.evaluation.opening.InstructionRa_8", "stage8.evaluation.opening.InstructionRa_9", "stage8.evaluation.opening.InstructionRa_10", "stage8.evaluation.opening.InstructionRa_11", "stage8.evaluation.opening.InstructionRa_12", "stage8.evaluation.opening.InstructionRa_13", "stage8.evaluation.opening.InstructionRa_14", "stage8.evaluation.opening.InstructionRa_15", "stage8.evaluation.opening.InstructionRa_16", "stage8.evaluation.opening.InstructionRa_17", "stage8.evaluation.opening.InstructionRa_18", "stage8.evaluation.opening.InstructionRa_19", "stage8.evaluation.opening.InstructionRa_20", "stage8.evaluation.opening.InstructionRa_21", "stage8.evaluation.opening.InstructionRa_22", "stage8.evaluation.opening.InstructionRa_23", "stage8.evaluation.opening.InstructionRa_24", "stage8.evaluation.opening.InstructionRa_25", "stage8.evaluation.opening.InstructionRa_26", "stage8.evaluation.opening.InstructionRa_27", "stage8.evaluation.opening.InstructionRa_28", "stage8.evaluation.opening.InstructionRa_29", "stage8.evaluation.opening.InstructionRa_30", "stage8.evaluation.opening.InstructionRa_31", "stage8.evaluation.opening.BytecodeRa_0", "stage8.evaluation.opening.BytecodeRa_1", "stage8.evaluation.opening.BytecodeRa_2", "stage8.evaluation.opening.RamRa_0", "stage8.evaluation.opening.RamRa_1", "stage8.evaluation.opening.RamRa_2", "stage8.evaluation.opening.RamRa_3"]; +pub const STAGE8_OPENING_BATCH_ORDERED_CLAIMS: &[&str] = &["stage8.evaluation.opening.RamInc", "stage8.evaluation.opening.RdInc", "stage8.evaluation.opening.InstructionRa_0", "stage8.evaluation.opening.InstructionRa_1", "stage8.evaluation.opening.InstructionRa_2", "stage8.evaluation.opening.InstructionRa_3", "stage8.evaluation.opening.InstructionRa_4", "stage8.evaluation.opening.InstructionRa_5", "stage8.evaluation.opening.InstructionRa_6", "stage8.evaluation.opening.InstructionRa_7", "stage8.evaluation.opening.InstructionRa_8", "stage8.evaluation.opening.InstructionRa_9", "stage8.evaluation.opening.InstructionRa_10", "stage8.evaluation.opening.InstructionRa_11", "stage8.evaluation.opening.InstructionRa_12", "stage8.evaluation.opening.InstructionRa_13", "stage8.evaluation.opening.InstructionRa_14", "stage8.evaluation.opening.InstructionRa_15", "stage8.evaluation.opening.InstructionRa_16", "stage8.evaluation.opening.InstructionRa_17", "stage8.evaluation.opening.InstructionRa_18", "stage8.evaluation.opening.InstructionRa_19", "stage8.evaluation.opening.InstructionRa_20", "stage8.evaluation.opening.InstructionRa_21", "stage8.evaluation.opening.InstructionRa_22", "stage8.evaluation.opening.InstructionRa_23", "stage8.evaluation.opening.InstructionRa_24", "stage8.evaluation.opening.InstructionRa_25", "stage8.evaluation.opening.InstructionRa_26", "stage8.evaluation.opening.InstructionRa_27", "stage8.evaluation.opening.InstructionRa_28", "stage8.evaluation.opening.InstructionRa_29", "stage8.evaluation.opening.InstructionRa_30", "stage8.evaluation.opening.InstructionRa_31", "stage8.evaluation.opening.BytecodeRa_0", "stage8.evaluation.opening.BytecodeRa_1", "stage8.evaluation.opening.BytecodeRa_2", "stage8.evaluation.opening.BytecodeRa_3", "stage8.evaluation.opening.RamRa_0", "stage8.evaluation.opening.RamRa_1", "stage8.evaluation.opening.RamRa_2", "stage8.evaluation.opening.RamRa_3"]; -pub const STAGE8_OPENING_BATCH: Stage8OpeningBatchPlan = Stage8OpeningBatchPlan { symbol: "stage8.evaluation.openings", proof_slot: "stage8.evaluation", policy: "jolt_stage8_joint_rlc", count: 41, ordered_claims: STAGE8_OPENING_BATCH_ORDERED_CLAIMS }; +pub const STAGE8_OPENING_BATCH: Stage8OpeningBatchPlan = Stage8OpeningBatchPlan { symbol: "stage8.evaluation.openings", proof_slot: "stage8.evaluation", policy: "jolt_stage8_joint_rlc", count: 42, ordered_claims: STAGE8_OPENING_BATCH_ORDERED_CLAIMS }; pub const STAGE8_PCS_PROOF: Stage8PcsProofPlan = Stage8PcsProofPlan { symbol: "stage8.evaluation.proof", mode: "open", pcs: "dory", proof_slot: "stage8.evaluation", transcript_label: "rlc_claims", batch: "stage8.evaluation.openings" }; diff --git a/crates/jolt-verifier/src/lib.rs b/crates/jolt-verifier/src/lib.rs index c9dfdffc26..97589fc2d6 100644 --- a/crates/jolt-verifier/src/lib.rs +++ b/crates/jolt-verifier/src/lib.rs @@ -19,8 +19,8 @@ pub use verifier::{ verify_jolt_through_stage6_with_programs, verify_jolt_through_stage7, verify_jolt_through_stage7_with_programs, verify_jolt_with_programs, JoltEvaluationProof, JoltEvaluationProofError, JoltNamedEval, JoltProof, JoltStage2RamAccess, JoltStage2RamData, - JoltStage2RamOutputLayout, JoltStage6BytecodeEntry, JoltStage6BytecodeReadRafData, - JoltStage6VerifierData, JoltStageChallengeVector, JoltStageExecutionArtifacts, + JoltStage2RamOutputLayout, JoltStageChallengeVector, JoltStageExecutionArtifacts, + JoltStage6BytecodeEntry, JoltStage6BytecodeReadRafData, JoltStage6VerifierData, JoltStageOpeningInputValue, JoltStageProof, JoltSumcheckOutput, JoltVerificationArtifacts, JoltVerifierInputs, JoltVerifierPrograms, JoltVerifierTarget, JoltVerifyError, }; diff --git a/crates/jolt-verifier/src/stages/commitment.rs b/crates/jolt-verifier/src/stages/commitment.rs index ea31591867..6f66c25019 100644 --- a/crates/jolt-verifier/src/stages/commitment.rs +++ b/crates/jolt-verifier/src/stages/commitment.rs @@ -92,49 +92,50 @@ pub const COMMITMENT_PARAMS: CommitmentParams = CommitmentParams { transcript: "blake2b_transcript", }; pub const ORACLE_PLANS: &[OraclePlan] = &[ - OraclePlan { oracle: "RdInc", domain: "jolt.trace_domain", num_vars: 16 }, - OraclePlan { oracle: "RamInc", domain: "jolt.trace_domain", num_vars: 16 }, - OraclePlan { oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", num_vars: 20 }, - OraclePlan { oracle: "UntrustedAdvice", domain: "jolt.trace_domain", num_vars: 16 }, - OraclePlan { oracle: "TrustedAdvice", domain: "jolt.trace_domain", num_vars: 16 }, + OraclePlan { oracle: "RdInc", domain: "jolt.trace_domain", num_vars: 18 }, + OraclePlan { oracle: "RamInc", domain: "jolt.trace_domain", num_vars: 18 }, + OraclePlan { oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "BytecodeRa_3", domain: "jolt.main_witness_commit_domain", num_vars: 22 }, + OraclePlan { oracle: "UntrustedAdvice", domain: "jolt.trace_domain", num_vars: 18 }, + OraclePlan { oracle: "TrustedAdvice", domain: "jolt.trace_domain", num_vars: 18 }, ]; pub const COMMITMENT_BATCH_0_ORACLES: &[&str] = &[ "RdInc", @@ -178,13 +179,14 @@ pub const COMMITMENT_BATCH_0_ORACLES: &[&str] = &[ "BytecodeRa_0", "BytecodeRa_1", "BytecodeRa_2", + "BytecodeRa_3", ]; pub const COMMITMENT_BATCH_PLANS: &[CommitmentBatchPlan] = &[ - CommitmentBatchPlan { artifact: "jolt.main_witness_commitments", pcs: "dory", oracle_family: "jolt.main_witness_polys", label: "commitment", oracles: COMMITMENT_BATCH_0_ORACLES, count: 41, domain: "jolt.main_witness_commit_domain", num_vars: 20 }, + CommitmentBatchPlan { artifact: "jolt.main_witness_commitments", pcs: "dory", oracle_family: "jolt.main_witness_polys", label: "commitment", oracles: COMMITMENT_BATCH_0_ORACLES, count: 42, domain: "jolt.main_witness_commit_domain", num_vars: 22 }, ]; pub const OPTIONAL_COMMITMENT_PLANS: &[OptionalCommitmentPlan] = &[ - OptionalCommitmentPlan { artifact: "jolt.untrusted_advice_commitment", pcs: "dory", oracle: "UntrustedAdvice", label: "untrusted_advice", domain: "jolt.trace_domain", num_vars: 16, skip_policy: OptionalSkipPolicy::MissingOrZero }, - OptionalCommitmentPlan { artifact: "jolt.trusted_advice_commitment", pcs: "dory", oracle: "TrustedAdvice", label: "trusted_advice", domain: "jolt.trace_domain", num_vars: 16, skip_policy: OptionalSkipPolicy::MissingOrZero }, + OptionalCommitmentPlan { artifact: "jolt.untrusted_advice_commitment", pcs: "dory", oracle: "UntrustedAdvice", label: "untrusted_advice", domain: "jolt.trace_domain", num_vars: 18, skip_policy: OptionalSkipPolicy::MissingOrZero }, + OptionalCommitmentPlan { artifact: "jolt.trusted_advice_commitment", pcs: "dory", oracle: "TrustedAdvice", label: "trusted_advice", domain: "jolt.trace_domain", num_vars: 18, skip_policy: OptionalSkipPolicy::MissingOrZero }, ]; pub const TRANSCRIPT_PLAN: &[TranscriptStep] = &[ TranscriptStep { label: "commitment", source: "jolt.main_witness_commitments", optional: false }, diff --git a/crates/jolt-verifier/src/stages/stage1_outer.rs b/crates/jolt-verifier/src/stages/stage1_outer.rs index bd9b946c10..6b0ba58aa9 100644 --- a/crates/jolt-verifier/src/stages/stage1_outer.rs +++ b/crates/jolt-verifier/src/stages/stage1_outer.rs @@ -42,19 +42,19 @@ pub const STAGE1_PARAMS: Stage1Params = Stage1Params { transcript: "blake2b_transcript", }; pub const STAGE1_TRANSCRIPT_SQUEEZES: &[Stage1TranscriptSqueezePlan] = &[ - Stage1TranscriptSqueezePlan { symbol: "stage1.tau", label: "outer_tau", kind: "challenge_vector", count: 18 }, + Stage1TranscriptSqueezePlan { symbol: "stage1.tau", label: "outer_tau", kind: "challenge_vector", count: 20 }, ]; pub const STAGE1_SUMCHECK_CLAIMS: &[Stage1SumcheckClaimPlan] = &[ Stage1SumcheckClaimPlan { symbol: "stage1.uniskip.input", stage: "stage1", domain: "jolt.stage1_uniskip_domain", num_rounds: 1, degree: 27, claim: "stage1.zero", kernel: None, relation: Some("jolt.stage1.outer.uniskip"), claim_value: "stage1.zero", input_openings: "" }, - Stage1SumcheckClaimPlan { symbol: "stage1.outer_remaining.input", stage: "stage1", domain: "jolt.trace_domain", num_rounds: 17, degree: 3, claim: "stage1.uniskip.eval", kernel: None, relation: Some("jolt.stage1.outer.remaining"), claim_value: "stage1.uniskip.eval", input_openings: "stage1.uniskip.opening" }, + Stage1SumcheckClaimPlan { symbol: "stage1.outer_remaining.input", stage: "stage1", domain: "jolt.trace_domain", num_rounds: 19, degree: 3, claim: "stage1.uniskip.eval", kernel: None, relation: Some("jolt.stage1.outer.remaining"), claim_value: "stage1.uniskip.eval", input_openings: "stage1.uniskip.opening" }, ]; pub const STAGE1_SUMCHECK_BATCH_0_ROUND_SCHEDULE: &[usize] = &[ 1, ]; pub const STAGE1_SUMCHECK_BATCH_1_ROUND_SCHEDULE: &[usize] = &[ - 17, + 19, ]; pub const STAGE1_SUMCHECK_BATCHES: &[Stage1SumcheckBatchPlan] = &[ @@ -66,16 +66,16 @@ pub const STAGE1_SUMCHECK_DRIVER_0_ROUND_SCHEDULE: &[usize] = &[ ]; pub const STAGE1_SUMCHECK_DRIVER_1_ROUND_SCHEDULE: &[usize] = &[ - 17, + 19, ]; pub const STAGE1_SUMCHECK_DRIVERS: &[Stage1SumcheckDriverPlan] = &[ Stage1SumcheckDriverPlan { symbol: "stage1.uniskip.sumcheck", stage: "stage1", proof_slot: "stage1.uni_skip_first_round", kernel: None, relation: Some("jolt.stage1.outer.uniskip"), batch: "stage1.uniskip.batch", policy: "univariate_skip", round_schedule: STAGE1_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "uniskip_claim", round_label: "uniskip_poly", num_rounds: 1, degree: 27 }, - Stage1SumcheckDriverPlan { symbol: "stage1.outer_remaining.sumcheck", stage: "stage1", proof_slot: "stage1.sumcheck", kernel: None, relation: Some("jolt.stage1.outer.remaining"), batch: "stage1.outer_remaining.batch", policy: "jolt_core_front_loaded", round_schedule: STAGE1_SUMCHECK_DRIVER_1_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 17, degree: 3 }, + Stage1SumcheckDriverPlan { symbol: "stage1.outer_remaining.sumcheck", stage: "stage1", proof_slot: "stage1.sumcheck", kernel: None, relation: Some("jolt.stage1.outer.remaining"), batch: "stage1.outer_remaining.batch", policy: "jolt_core_front_loaded", round_schedule: STAGE1_SUMCHECK_DRIVER_1_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 19, degree: 3 }, ]; pub const STAGE1_SUMCHECK_INSTANCE_RESULTS: &[Stage1SumcheckInstanceResultPlan] = &[ Stage1SumcheckInstanceResultPlan { symbol: "stage1.uniskip.instance", source: "stage1.uniskip.sumcheck", claim: "stage1.uniskip.input", relation: "jolt.stage1.outer.uniskip", index: 0, point_arity: 1, num_rounds: 1, round_offset: 0, point_order: "as_is", degree: 27 }, - Stage1SumcheckInstanceResultPlan { symbol: "stage1.outer_remaining.instance", source: "stage1.outer_remaining.sumcheck", claim: "stage1.outer_remaining.input", relation: "jolt.stage1.outer.remaining", index: 0, point_arity: 16, num_rounds: 17, round_offset: 1, point_order: "reverse", degree: 3 }, + Stage1SumcheckInstanceResultPlan { symbol: "stage1.outer_remaining.instance", source: "stage1.outer_remaining.sumcheck", claim: "stage1.outer_remaining.input", relation: "jolt.stage1.outer.remaining", index: 0, point_arity: 18, num_rounds: 19, round_offset: 1, point_order: "reverse", degree: 3 }, ]; pub const STAGE1_SUMCHECK_EVALS: &[Stage1SumcheckEvalPlan] = &[ @@ -119,41 +119,41 @@ pub const STAGE1_SUMCHECK_EVALS: &[Stage1SumcheckEvalPlan] = &[ pub const STAGE1_OPENING_CLAIMS: &[Stage1OpeningClaimPlan] = &[ Stage1OpeningClaimPlan { symbol: "stage1.uniskip.opening", oracle: "UnivariateSkip", domain: "jolt.stage1_uniskip_domain", point_arity: 1, claim_kind: "virtual", point_source: "stage1.uniskip.instance", eval_source: "stage1.uniskip.eval" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.LeftInstructionInput" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RightInstructionInput" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.Product", oracle: "Product", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.Product" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.ShouldBranch", oracle: "ShouldBranch", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.ShouldBranch" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.PC", oracle: "PC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.PC" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.UnexpandedPC", oracle: "UnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.UnexpandedPC" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.Imm", oracle: "Imm", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.Imm" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RamAddress", oracle: "RamAddress", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RamAddress" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.Rs1Value" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.Rs2Value" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RdWriteValue", oracle: "RdWriteValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RdWriteValue" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RamReadValue", oracle: "RamReadValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RamReadValue" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RamWriteValue", oracle: "RamWriteValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RamWriteValue" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.LeftLookupOperand", oracle: "LeftLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.LeftLookupOperand" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RightLookupOperand", oracle: "RightLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RightLookupOperand" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.NextUnexpandedPC", oracle: "NextUnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.NextUnexpandedPC" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.NextPC", oracle: "NextPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.NextPC" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.NextIsVirtual", oracle: "NextIsVirtual", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.NextIsVirtual" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.NextIsFirstInSequence", oracle: "NextIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.NextIsFirstInSequence" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.LookupOutput" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.ShouldJump", oracle: "ShouldJump", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.ShouldJump" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagAddOperands", oracle: "OpFlagAddOperands", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagAddOperands" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagSubtractOperands", oracle: "OpFlagSubtractOperands", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagSubtractOperands" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagMultiplyOperands", oracle: "OpFlagMultiplyOperands", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagMultiplyOperands" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagLoad", oracle: "OpFlagLoad", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagLoad" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagStore", oracle: "OpFlagStore", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagStore" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagJump", oracle: "OpFlagJump", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagJump" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagWriteLookupOutputToRD", oracle: "OpFlagWriteLookupOutputToRD", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagWriteLookupOutputToRD" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagVirtualInstruction" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagAssert", oracle: "OpFlagAssert", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagAssert" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagDoNotUpdateUnexpandedPC", oracle: "OpFlagDoNotUpdateUnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagDoNotUpdateUnexpandedPC" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagAdvice", oracle: "OpFlagAdvice", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagAdvice" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagIsCompressed", oracle: "OpFlagIsCompressed", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagIsCompressed" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagIsFirstInSequence", oracle: "OpFlagIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagIsFirstInSequence" }, - Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagIsLastInSequence", oracle: "OpFlagIsLastInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagIsLastInSequence" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.LeftInstructionInput" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RightInstructionInput" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.Product", oracle: "Product", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.Product" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.ShouldBranch", oracle: "ShouldBranch", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.ShouldBranch" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.PC", oracle: "PC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.PC" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.UnexpandedPC", oracle: "UnexpandedPC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.UnexpandedPC" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.Imm", oracle: "Imm", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.Imm" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RamAddress", oracle: "RamAddress", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RamAddress" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.Rs1Value" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.Rs2Value" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RdWriteValue", oracle: "RdWriteValue", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RdWriteValue" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RamReadValue", oracle: "RamReadValue", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RamReadValue" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RamWriteValue", oracle: "RamWriteValue", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RamWriteValue" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.LeftLookupOperand", oracle: "LeftLookupOperand", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.LeftLookupOperand" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.RightLookupOperand", oracle: "RightLookupOperand", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.RightLookupOperand" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.NextUnexpandedPC", oracle: "NextUnexpandedPC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.NextUnexpandedPC" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.NextPC", oracle: "NextPC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.NextPC" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.NextIsVirtual", oracle: "NextIsVirtual", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.NextIsVirtual" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.NextIsFirstInSequence", oracle: "NextIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.NextIsFirstInSequence" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.LookupOutput" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.ShouldJump", oracle: "ShouldJump", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.ShouldJump" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagAddOperands", oracle: "OpFlagAddOperands", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagAddOperands" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagSubtractOperands", oracle: "OpFlagSubtractOperands", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagSubtractOperands" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagMultiplyOperands", oracle: "OpFlagMultiplyOperands", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagMultiplyOperands" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagLoad", oracle: "OpFlagLoad", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagLoad" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagStore", oracle: "OpFlagStore", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagStore" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagJump", oracle: "OpFlagJump", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagJump" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagWriteLookupOutputToRD", oracle: "OpFlagWriteLookupOutputToRD", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagWriteLookupOutputToRD" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagVirtualInstruction" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagAssert", oracle: "OpFlagAssert", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagAssert" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagDoNotUpdateUnexpandedPC", oracle: "OpFlagDoNotUpdateUnexpandedPC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagDoNotUpdateUnexpandedPC" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagAdvice", oracle: "OpFlagAdvice", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagAdvice" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagIsCompressed", oracle: "OpFlagIsCompressed", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagIsCompressed" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagIsFirstInSequence", oracle: "OpFlagIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagIsFirstInSequence" }, + Stage1OpeningClaimPlan { symbol: "stage1.outer_remaining.opening.OpFlagIsLastInSequence", oracle: "OpFlagIsLastInSequence", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage1.outer_remaining.instance", eval_source: "stage1.outer_remaining.eval.OpFlagIsLastInSequence" }, ]; pub const STAGE1_OPENING_BATCHES: &[Stage1OpeningBatchPlan] = &[ diff --git a/crates/jolt-verifier/src/stages/stage2.rs b/crates/jolt-verifier/src/stages/stage2.rs index 568fcfb71a..4956bc9680 100644 --- a/crates/jolt-verifier/src/stages/stage2.rs +++ b/crates/jolt-verifier/src/stages/stage2.rs @@ -91,21 +91,21 @@ pub const STAGE2_TRANSCRIPT_SQUEEZES: &[Stage2TranscriptSqueezePlan] = &[ Stage2TranscriptSqueezePlan { symbol: "stage2.product_virtual.tau_high", label: "product_virtual_tau_high", kind: "challenge_scalar", count: 1 }, Stage2TranscriptSqueezePlan { symbol: "stage2.ram_read_write.gamma", label: "ram_read_write_gamma", kind: "challenge_scalar", count: 1 }, Stage2TranscriptSqueezePlan { symbol: "stage2.instruction_lookup.gamma", label: "instruction_lookup_gamma", kind: "challenge_scalar", count: 1 }, - Stage2TranscriptSqueezePlan { symbol: "stage2.ram_output.r_address", label: "ram_output_r_address", kind: "challenge_vector", count: 16 }, + Stage2TranscriptSqueezePlan { symbol: "stage2.ram_output.r_address", label: "ram_output_r_address", kind: "challenge_vector", count: 14 }, ]; pub const STAGE2_OPENING_INPUTS: &[Stage2OpeningInputPlan] = &[ - Stage2OpeningInputPlan { symbol: "stage2.input.stage1.Product", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.Product", oracle: "Product", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage2OpeningInputPlan { symbol: "stage2.input.stage1.ShouldBranch", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.ShouldBranch", oracle: "ShouldBranch", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage2OpeningInputPlan { symbol: "stage2.input.stage1.ShouldJump", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.ShouldJump", oracle: "ShouldJump", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage2OpeningInputPlan { symbol: "stage2.input.stage1.RamReadValue", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RamReadValue", oracle: "RamReadValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage2OpeningInputPlan { symbol: "stage2.input.stage1.RamWriteValue", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RamWriteValue", oracle: "RamWriteValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage2OpeningInputPlan { symbol: "stage2.input.stage1.LookupOutput", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage2OpeningInputPlan { symbol: "stage2.input.stage1.LeftLookupOperand", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.LeftLookupOperand", oracle: "LeftLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage2OpeningInputPlan { symbol: "stage2.input.stage1.RightLookupOperand", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RightLookupOperand", oracle: "RightLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage2OpeningInputPlan { symbol: "stage2.input.stage1.LeftInstructionInput", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage2OpeningInputPlan { symbol: "stage2.input.stage1.RightInstructionInput", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage2OpeningInputPlan { symbol: "stage2.input.stage1.RamAddress", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RamAddress", oracle: "RamAddress", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.Product", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.Product", oracle: "Product", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.ShouldBranch", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.ShouldBranch", oracle: "ShouldBranch", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.ShouldJump", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.ShouldJump", oracle: "ShouldJump", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.RamReadValue", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RamReadValue", oracle: "RamReadValue", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.RamWriteValue", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RamWriteValue", oracle: "RamWriteValue", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.LookupOutput", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.LeftLookupOperand", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.LeftLookupOperand", oracle: "LeftLookupOperand", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.RightLookupOperand", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RightLookupOperand", oracle: "RightLookupOperand", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.LeftInstructionInput", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.RightInstructionInput", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage2OpeningInputPlan { symbol: "stage2.input.stage1.RamAddress", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RamAddress", oracle: "RamAddress", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, ]; pub const STAGE2_FIELD_CONSTANTS: &[Stage2FieldConstantPlan] = &[ @@ -138,18 +138,18 @@ pub const STAGE2_FIELD_EXPRS: &[Stage2FieldExprPlan] = &[ pub const STAGE2_SUMCHECK_CLAIMS: &[Stage2SumcheckClaimPlan] = &[ Stage2SumcheckClaimPlan { symbol: "stage2.product_virtual.uniskip.input", stage: "stage2", domain: "jolt.stage2_uniskip_domain", num_rounds: 1, degree: 6, claim: "stage2.product_virtual.weighted_stage1_outputs", kernel: None, relation: Some("jolt.stage2.product_virtual.uniskip"), claim_value: "stage2.product_virtual.uniskip.claim_expr", input_openings: "stage2.input.stage1.Product|stage2.input.stage1.ShouldBranch|stage2.input.stage1.ShouldJump" }, Stage2SumcheckClaimPlan { symbol: "stage2.ram_read_write.input", stage: "stage2", domain: "jolt.stage2_ram_rw_domain", num_rounds: 32, degree: 3, claim: "stage2.ram_read_write.weighted_values", kernel: None, relation: Some("jolt.stage2.ram.read_write"), claim_value: "stage2.ram_read_write.claim_expr", input_openings: "stage2.input.stage1.RamReadValue|stage2.input.stage1.RamWriteValue" }, - Stage2SumcheckClaimPlan { symbol: "stage2.product_virtual.remainder.input", stage: "stage2", domain: "jolt.trace_domain", num_rounds: 16, degree: 3, claim: "stage2.product_virtual.uniskip.opening", kernel: None, relation: Some("jolt.stage2.product_virtual.remainder"), claim_value: "stage2.product_virtual.uniskip.eval.UnivariateSkip", input_openings: "stage2.product_virtual.uniskip.opening.UnivariateSkip" }, - Stage2SumcheckClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.input", stage: "stage2", domain: "jolt.trace_domain", num_rounds: 16, degree: 2, claim: "stage2.instruction_lookup.weighted_operands", kernel: None, relation: Some("jolt.stage2.instruction_lookup.claim_reduction"), claim_value: "stage2.instruction_lookup.claim_reduction.claim_expr", input_openings: "stage2.input.stage1.LookupOutput|stage2.input.stage1.LeftLookupOperand|stage2.input.stage1.RightLookupOperand|stage2.input.stage1.LeftInstructionInput|stage2.input.stage1.RightInstructionInput" }, - Stage2SumcheckClaimPlan { symbol: "stage2.ram_raf.input", stage: "stage2", domain: "jolt.ram_address_domain", num_rounds: 16, degree: 2, claim: "stage2.ram_raf.ram_address", kernel: None, relation: Some("jolt.stage2.ram.raf_evaluation"), claim_value: "stage2.input.stage1.RamAddress", input_openings: "stage2.input.stage1.RamAddress" }, - Stage2SumcheckClaimPlan { symbol: "stage2.ram_output.input", stage: "stage2", domain: "jolt.ram_address_domain", num_rounds: 16, degree: 3, claim: "zero", kernel: None, relation: Some("jolt.stage2.ram.output_check"), claim_value: "stage2.ram_output.zero", input_openings: "" }, + Stage2SumcheckClaimPlan { symbol: "stage2.product_virtual.remainder.input", stage: "stage2", domain: "jolt.trace_domain", num_rounds: 18, degree: 3, claim: "stage2.product_virtual.uniskip.opening", kernel: None, relation: Some("jolt.stage2.product_virtual.remainder"), claim_value: "stage2.product_virtual.uniskip.eval.UnivariateSkip", input_openings: "stage2.product_virtual.uniskip.opening.UnivariateSkip" }, + Stage2SumcheckClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.input", stage: "stage2", domain: "jolt.trace_domain", num_rounds: 18, degree: 2, claim: "stage2.instruction_lookup.weighted_operands", kernel: None, relation: Some("jolt.stage2.instruction_lookup.claim_reduction"), claim_value: "stage2.instruction_lookup.claim_reduction.claim_expr", input_openings: "stage2.input.stage1.LookupOutput|stage2.input.stage1.LeftLookupOperand|stage2.input.stage1.RightLookupOperand|stage2.input.stage1.LeftInstructionInput|stage2.input.stage1.RightInstructionInput" }, + Stage2SumcheckClaimPlan { symbol: "stage2.ram_raf.input", stage: "stage2", domain: "jolt.ram_address_domain", num_rounds: 14, degree: 2, claim: "stage2.ram_raf.ram_address", kernel: None, relation: Some("jolt.stage2.ram.raf_evaluation"), claim_value: "stage2.input.stage1.RamAddress", input_openings: "stage2.input.stage1.RamAddress" }, + Stage2SumcheckClaimPlan { symbol: "stage2.ram_output.input", stage: "stage2", domain: "jolt.ram_address_domain", num_rounds: 14, degree: 3, claim: "zero", kernel: None, relation: Some("jolt.stage2.ram.output_check"), claim_value: "stage2.ram_output.zero", input_openings: "" }, ]; pub const STAGE2_SUMCHECK_BATCH_0_ROUND_SCHEDULE: &[usize] = &[ 1, ]; pub const STAGE2_SUMCHECK_BATCH_1_ROUND_SCHEDULE: &[usize] = &[ - 16, - 16, + 18, + 14, ]; pub const STAGE2_SUMCHECK_BATCHES: &[Stage2SumcheckBatchPlan] = &[ @@ -161,8 +161,8 @@ pub const STAGE2_SUMCHECK_DRIVER_0_ROUND_SCHEDULE: &[usize] = &[ ]; pub const STAGE2_SUMCHECK_DRIVER_1_ROUND_SCHEDULE: &[usize] = &[ - 16, - 16, + 18, + 14, ]; pub const STAGE2_SUMCHECK_DRIVERS: &[Stage2SumcheckDriverPlan] = &[ @@ -172,10 +172,10 @@ pub const STAGE2_SUMCHECK_DRIVERS: &[Stage2SumcheckDriverPlan] = &[ pub const STAGE2_SUMCHECK_INSTANCE_RESULTS: &[Stage2SumcheckInstanceResultPlan] = &[ Stage2SumcheckInstanceResultPlan { symbol: "stage2.product_virtual.uniskip.instance", source: "stage2.product_virtual.uniskip.sumcheck", claim: "stage2.product_virtual.uniskip.input", relation: "jolt.stage2.product_virtual.uniskip", index: 0, point_arity: 1, num_rounds: 1, round_offset: 0, point_order: "as_is", degree: 6 }, Stage2SumcheckInstanceResultPlan { symbol: "stage2.ram_read_write.instance", source: "stage2.sumcheck", claim: "stage2.ram_read_write.input", relation: "jolt.stage2.ram.read_write", index: 0, point_arity: 32, num_rounds: 32, round_offset: 0, point_order: "reverse", degree: 3 }, - Stage2SumcheckInstanceResultPlan { symbol: "stage2.product_virtual.remainder.instance", source: "stage2.sumcheck", claim: "stage2.product_virtual.remainder.input", relation: "jolt.stage2.product_virtual.remainder", index: 1, point_arity: 16, num_rounds: 16, round_offset: 16, point_order: "reverse", degree: 3 }, - Stage2SumcheckInstanceResultPlan { symbol: "stage2.instruction_lookup.claim_reduction.instance", source: "stage2.sumcheck", claim: "stage2.instruction_lookup.claim_reduction.input", relation: "jolt.stage2.instruction_lookup.claim_reduction", index: 2, point_arity: 16, num_rounds: 16, round_offset: 16, point_order: "reverse", degree: 2 }, - Stage2SumcheckInstanceResultPlan { symbol: "stage2.ram_raf.instance", source: "stage2.sumcheck", claim: "stage2.ram_raf.input", relation: "jolt.stage2.ram.raf_evaluation", index: 3, point_arity: 16, num_rounds: 16, round_offset: 16, point_order: "reverse", degree: 2 }, - Stage2SumcheckInstanceResultPlan { symbol: "stage2.ram_output.instance", source: "stage2.sumcheck", claim: "stage2.ram_output.input", relation: "jolt.stage2.ram.output_check", index: 4, point_arity: 16, num_rounds: 16, round_offset: 16, point_order: "reverse", degree: 3 }, + Stage2SumcheckInstanceResultPlan { symbol: "stage2.product_virtual.remainder.instance", source: "stage2.sumcheck", claim: "stage2.product_virtual.remainder.input", relation: "jolt.stage2.product_virtual.remainder", index: 1, point_arity: 18, num_rounds: 18, round_offset: 14, point_order: "reverse", degree: 3 }, + Stage2SumcheckInstanceResultPlan { symbol: "stage2.instruction_lookup.claim_reduction.instance", source: "stage2.sumcheck", claim: "stage2.instruction_lookup.claim_reduction.input", relation: "jolt.stage2.instruction_lookup.claim_reduction", index: 2, point_arity: 18, num_rounds: 18, round_offset: 14, point_order: "reverse", degree: 2 }, + Stage2SumcheckInstanceResultPlan { symbol: "stage2.ram_raf.instance", source: "stage2.sumcheck", claim: "stage2.ram_raf.input", relation: "jolt.stage2.ram.raf_evaluation", index: 3, point_arity: 14, num_rounds: 14, round_offset: 18, point_order: "reverse", degree: 2 }, + Stage2SumcheckInstanceResultPlan { symbol: "stage2.ram_output.instance", source: "stage2.sumcheck", claim: "stage2.ram_output.input", relation: "jolt.stage2.ram.output_check", index: 4, point_arity: 14, num_rounds: 14, round_offset: 18, point_order: "reverse", degree: 3 }, ]; pub const STAGE2_SUMCHECK_EVALS: &[Stage2SumcheckEvalPlan] = &[ @@ -201,7 +201,7 @@ pub const STAGE2_SUMCHECK_EVALS: &[Stage2SumcheckEvalPlan] = &[ ]; pub const STAGE2_POINT_SLICES: &[Stage2PointSlicePlan] = &[ - Stage2PointSlicePlan { symbol: "stage2.ram_read_write.point.RamInc", source: "stage2.ram_read_write.instance", offset: 16, length: 16, input: "stage2.ram_read_write.instance" }, + Stage2PointSlicePlan { symbol: "stage2.ram_read_write.point.RamInc", source: "stage2.ram_read_write.instance", offset: 14, length: 18, input: "stage2.ram_read_write.instance" }, ]; pub const STAGE2_POINT_CONCATS: &[Stage2PointConcatPlan] = &[ @@ -211,22 +211,22 @@ pub const STAGE2_OPENING_CLAIMS: &[Stage2OpeningClaimPlan] = &[ Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.uniskip.opening.UnivariateSkip", oracle: "UnivariateSkip", domain: "jolt.stage2_uniskip_domain", point_arity: 1, claim_kind: "virtual", point_source: "stage2.product_virtual.uniskip.instance", eval_source: "stage2.product_virtual.uniskip.eval.UnivariateSkip" }, Stage2OpeningClaimPlan { symbol: "stage2.ram_read_write.opening.RamVal", oracle: "RamVal", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage2.ram_read_write.instance", eval_source: "stage2.ram_read_write.eval.RamVal" }, Stage2OpeningClaimPlan { symbol: "stage2.ram_read_write.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage2.ram_read_write.instance", eval_source: "stage2.ram_read_write.eval.RamRa" }, - Stage2OpeningClaimPlan { symbol: "stage2.ram_read_write.opening.RamInc", oracle: "RamInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed", point_source: "stage2.ram_read_write.point.RamInc", eval_source: "stage2.ram_read_write.eval.RamInc" }, - Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.LeftInstructionInput" }, - Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.RightInstructionInput" }, - Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.OpFlagJump", oracle: "OpFlagJump", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.OpFlagJump" }, - Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.OpFlagWriteLookupOutputToRD", oracle: "OpFlagWriteLookupOutputToRD", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.OpFlagWriteLookupOutputToRD" }, - Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.LookupOutput" }, - Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.InstructionFlagBranch", oracle: "InstructionFlagBranch", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.InstructionFlagBranch" }, - Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.NextIsNoop", oracle: "NextIsNoop", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.NextIsNoop" }, - Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.OpFlagVirtualInstruction" }, - Stage2OpeningClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.instruction_lookup.claim_reduction.instance", eval_source: "stage2.instruction_lookup.claim_reduction.eval.LookupOutput" }, - Stage2OpeningClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.opening.LeftLookupOperand", oracle: "LeftLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.instruction_lookup.claim_reduction.instance", eval_source: "stage2.instruction_lookup.claim_reduction.eval.LeftLookupOperand" }, - Stage2OpeningClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.opening.RightLookupOperand", oracle: "RightLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.instruction_lookup.claim_reduction.instance", eval_source: "stage2.instruction_lookup.claim_reduction.eval.RightLookupOperand" }, - Stage2OpeningClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.instruction_lookup.claim_reduction.instance", eval_source: "stage2.instruction_lookup.claim_reduction.eval.LeftInstructionInput" }, - Stage2OpeningClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.instruction_lookup.claim_reduction.instance", eval_source: "stage2.instruction_lookup.claim_reduction.eval.RightInstructionInput" }, + Stage2OpeningClaimPlan { symbol: "stage2.ram_read_write.opening.RamInc", oracle: "RamInc", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "committed", point_source: "stage2.ram_read_write.point.RamInc", eval_source: "stage2.ram_read_write.eval.RamInc" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.LeftInstructionInput" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.RightInstructionInput" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.OpFlagJump", oracle: "OpFlagJump", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.OpFlagJump" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.OpFlagWriteLookupOutputToRD", oracle: "OpFlagWriteLookupOutputToRD", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.OpFlagWriteLookupOutputToRD" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.LookupOutput" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.InstructionFlagBranch", oracle: "InstructionFlagBranch", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.InstructionFlagBranch" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.NextIsNoop", oracle: "NextIsNoop", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.NextIsNoop" }, + Stage2OpeningClaimPlan { symbol: "stage2.product_virtual.remainder.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage2.product_virtual.remainder.instance", eval_source: "stage2.product_virtual.remainder.eval.OpFlagVirtualInstruction" }, + Stage2OpeningClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage2.instruction_lookup.claim_reduction.instance", eval_source: "stage2.instruction_lookup.claim_reduction.eval.LookupOutput" }, + Stage2OpeningClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.opening.LeftLookupOperand", oracle: "LeftLookupOperand", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage2.instruction_lookup.claim_reduction.instance", eval_source: "stage2.instruction_lookup.claim_reduction.eval.LeftLookupOperand" }, + Stage2OpeningClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.opening.RightLookupOperand", oracle: "RightLookupOperand", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage2.instruction_lookup.claim_reduction.instance", eval_source: "stage2.instruction_lookup.claim_reduction.eval.RightLookupOperand" }, + Stage2OpeningClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage2.instruction_lookup.claim_reduction.instance", eval_source: "stage2.instruction_lookup.claim_reduction.eval.LeftInstructionInput" }, + Stage2OpeningClaimPlan { symbol: "stage2.instruction_lookup.claim_reduction.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage2.instruction_lookup.claim_reduction.instance", eval_source: "stage2.instruction_lookup.claim_reduction.eval.RightInstructionInput" }, Stage2OpeningClaimPlan { symbol: "stage2.ram_raf.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage2.ram_raf.point.RamRa", eval_source: "stage2.ram_raf.eval.RamRa" }, - Stage2OpeningClaimPlan { symbol: "stage2.ram_output.opening.RamValFinal", oracle: "RamValFinal", domain: "jolt.ram_address_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage2.ram_output.instance", eval_source: "stage2.ram_output.eval.RamValFinal" }, + Stage2OpeningClaimPlan { symbol: "stage2.ram_output.opening.RamValFinal", oracle: "RamValFinal", domain: "jolt.ram_address_domain", point_arity: 14, claim_kind: "virtual", point_source: "stage2.ram_output.instance", eval_source: "stage2.ram_output.eval.RamValFinal" }, ]; pub const STAGE2_OPENING_BATCHES: &[Stage2OpeningBatchPlan] = &[ diff --git a/crates/jolt-verifier/src/stages/stage3.rs b/crates/jolt-verifier/src/stages/stage3.rs index d22851483a..11942c327a 100644 --- a/crates/jolt-verifier/src/stages/stage3.rs +++ b/crates/jolt-verifier/src/stages/stage3.rs @@ -65,18 +65,18 @@ pub const STAGE3_TRANSCRIPT_SQUEEZES: &[Stage3TranscriptSqueezePlan] = &[ ]; pub const STAGE3_OPENING_INPUTS: &[Stage3OpeningInputPlan] = &[ - Stage3OpeningInputPlan { symbol: "stage3.input.stage1.NextUnexpandedPC", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.NextUnexpandedPC", oracle: "NextUnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage3OpeningInputPlan { symbol: "stage3.input.stage1.NextPC", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.NextPC", oracle: "NextPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage3OpeningInputPlan { symbol: "stage3.input.stage1.NextIsVirtual", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.NextIsVirtual", oracle: "NextIsVirtual", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage3OpeningInputPlan { symbol: "stage3.input.stage1.NextIsFirstInSequence", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.NextIsFirstInSequence", oracle: "NextIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage3OpeningInputPlan { symbol: "stage3.input.stage2.product_virtual.NextIsNoop", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.NextIsNoop", oracle: "NextIsNoop", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage3OpeningInputPlan { symbol: "stage3.input.stage2.product_virtual.LeftInstructionInput", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage3OpeningInputPlan { symbol: "stage3.input.stage2.product_virtual.RightInstructionInput", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage3OpeningInputPlan { symbol: "stage3.input.stage2.instruction_lookup.LeftInstructionInput", source_stage: "stage2", source_claim: "stage2.instruction_lookup.claim_reduction.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage3OpeningInputPlan { symbol: "stage3.input.stage2.instruction_lookup.RightInstructionInput", source_stage: "stage2", source_claim: "stage2.instruction_lookup.claim_reduction.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage3OpeningInputPlan { symbol: "stage3.input.stage1.RdWriteValue", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RdWriteValue", oracle: "RdWriteValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage3OpeningInputPlan { symbol: "stage3.input.stage1.Rs1Value", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage3OpeningInputPlan { symbol: "stage3.input.stage1.Rs2Value", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage1.NextUnexpandedPC", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.NextUnexpandedPC", oracle: "NextUnexpandedPC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage1.NextPC", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.NextPC", oracle: "NextPC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage1.NextIsVirtual", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.NextIsVirtual", oracle: "NextIsVirtual", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage1.NextIsFirstInSequence", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.NextIsFirstInSequence", oracle: "NextIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage2.product_virtual.NextIsNoop", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.NextIsNoop", oracle: "NextIsNoop", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage2.product_virtual.LeftInstructionInput", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage2.product_virtual.RightInstructionInput", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage2.instruction_lookup.LeftInstructionInput", source_stage: "stage2", source_claim: "stage2.instruction_lookup.claim_reduction.opening.LeftInstructionInput", oracle: "LeftInstructionInput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage2.instruction_lookup.RightInstructionInput", source_stage: "stage2", source_claim: "stage2.instruction_lookup.claim_reduction.opening.RightInstructionInput", oracle: "RightInstructionInput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage1.RdWriteValue", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.RdWriteValue", oracle: "RdWriteValue", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage1.Rs1Value", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage3OpeningInputPlan { symbol: "stage3.input.stage1.Rs2Value", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, ]; pub const STAGE3_FIELD_CONSTANTS: &[Stage3FieldConstantPlan] = &[ @@ -105,28 +105,28 @@ pub const STAGE3_FIELD_EXPRS: &[Stage3FieldExprPlan] = &[ Stage3FieldExprPlan { symbol: "stage3.registers.claim_expr", kind: "op", formula: "field.add", operands: "stage3.registers.partial.RdWriteValueRs1Value|stage3.registers.term.Rs2Value" }, ]; pub const STAGE3_SUMCHECK_CLAIMS: &[Stage3SumcheckClaimPlan] = &[ - Stage3SumcheckClaimPlan { symbol: "stage3.spartan_shift.input", stage: "stage3", domain: "jolt.trace_domain", num_rounds: 16, degree: 2, claim: "stage3.spartan_shift.weighted_next_values", kernel: None, relation: Some("jolt.stage3.spartan_shift"), claim_value: "stage3.spartan_shift.claim_expr", input_openings: "stage3.input.stage1.NextUnexpandedPC|stage3.input.stage1.NextPC|stage3.input.stage1.NextIsVirtual|stage3.input.stage1.NextIsFirstInSequence|stage3.input.stage2.product_virtual.NextIsNoop" }, - Stage3SumcheckClaimPlan { symbol: "stage3.instruction_input.input", stage: "stage3", domain: "jolt.trace_domain", num_rounds: 16, degree: 3, claim: "stage3.instruction_input.weighted_inputs", kernel: None, relation: Some("jolt.stage3.instruction_input"), claim_value: "stage3.instruction_input.claim_expr", input_openings: "stage3.input.stage2.product_virtual.RightInstructionInput|stage3.input.stage2.product_virtual.LeftInstructionInput" }, - Stage3SumcheckClaimPlan { symbol: "stage3.registers_claim_reduction.input", stage: "stage3", domain: "jolt.trace_domain", num_rounds: 16, degree: 2, claim: "stage3.registers.weighted_register_values", kernel: None, relation: Some("jolt.stage3.registers_claim_reduction"), claim_value: "stage3.registers.claim_expr", input_openings: "stage3.input.stage1.RdWriteValue|stage3.input.stage1.Rs1Value|stage3.input.stage1.Rs2Value" }, + Stage3SumcheckClaimPlan { symbol: "stage3.spartan_shift.input", stage: "stage3", domain: "jolt.trace_domain", num_rounds: 18, degree: 2, claim: "stage3.spartan_shift.weighted_next_values", kernel: None, relation: Some("jolt.stage3.spartan_shift"), claim_value: "stage3.spartan_shift.claim_expr", input_openings: "stage3.input.stage1.NextUnexpandedPC|stage3.input.stage1.NextPC|stage3.input.stage1.NextIsVirtual|stage3.input.stage1.NextIsFirstInSequence|stage3.input.stage2.product_virtual.NextIsNoop" }, + Stage3SumcheckClaimPlan { symbol: "stage3.instruction_input.input", stage: "stage3", domain: "jolt.trace_domain", num_rounds: 18, degree: 3, claim: "stage3.instruction_input.weighted_inputs", kernel: None, relation: Some("jolt.stage3.instruction_input"), claim_value: "stage3.instruction_input.claim_expr", input_openings: "stage3.input.stage2.product_virtual.RightInstructionInput|stage3.input.stage2.product_virtual.LeftInstructionInput" }, + Stage3SumcheckClaimPlan { symbol: "stage3.registers_claim_reduction.input", stage: "stage3", domain: "jolt.trace_domain", num_rounds: 18, degree: 2, claim: "stage3.registers.weighted_register_values", kernel: None, relation: Some("jolt.stage3.registers_claim_reduction"), claim_value: "stage3.registers.claim_expr", input_openings: "stage3.input.stage1.RdWriteValue|stage3.input.stage1.Rs1Value|stage3.input.stage1.Rs2Value" }, ]; pub const STAGE3_SUMCHECK_BATCH_0_ROUND_SCHEDULE: &[usize] = &[ - 16, + 18, ]; pub const STAGE3_SUMCHECK_BATCHES: &[Stage3SumcheckBatchPlan] = &[ Stage3SumcheckBatchPlan { symbol: "stage3.batch", stage: "stage3", proof_slot: "stage3.sumcheck", policy: "jolt_core_stage3_aligned", count: 3, ordered_claims: "stage3.spartan_shift.input|stage3.instruction_input.input|stage3.registers_claim_reduction.input", claim_operands: "stage3.spartan_shift.input|stage3.instruction_input.input|stage3.registers_claim_reduction.input", claim_label: "sumcheck_claim", round_label: "sumcheck_poly", round_schedule: STAGE3_SUMCHECK_BATCH_0_ROUND_SCHEDULE }, ]; pub const STAGE3_SUMCHECK_DRIVER_0_ROUND_SCHEDULE: &[usize] = &[ - 16, + 18, ]; pub const STAGE3_SUMCHECK_DRIVERS: &[Stage3SumcheckDriverPlan] = &[ - Stage3SumcheckDriverPlan { symbol: "stage3.sumcheck", stage: "stage3", proof_slot: "stage3.sumcheck", kernel: None, relation: Some("jolt.stage3.batched"), batch: "stage3.batch", policy: "jolt_core_stage3_aligned", round_schedule: STAGE3_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 16, degree: 3 }, + Stage3SumcheckDriverPlan { symbol: "stage3.sumcheck", stage: "stage3", proof_slot: "stage3.sumcheck", kernel: None, relation: Some("jolt.stage3.batched"), batch: "stage3.batch", policy: "jolt_core_stage3_aligned", round_schedule: STAGE3_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 18, degree: 3 }, ]; pub const STAGE3_SUMCHECK_INSTANCE_RESULTS: &[Stage3SumcheckInstanceResultPlan] = &[ - Stage3SumcheckInstanceResultPlan { symbol: "stage3.spartan_shift.instance", source: "stage3.sumcheck", claim: "stage3.spartan_shift.input", relation: "jolt.stage3.spartan_shift", index: 0, point_arity: 16, num_rounds: 16, round_offset: 0, point_order: "reverse", degree: 2 }, - Stage3SumcheckInstanceResultPlan { symbol: "stage3.instruction_input.instance", source: "stage3.sumcheck", claim: "stage3.instruction_input.input", relation: "jolt.stage3.instruction_input", index: 1, point_arity: 16, num_rounds: 16, round_offset: 0, point_order: "reverse", degree: 3 }, - Stage3SumcheckInstanceResultPlan { symbol: "stage3.registers_claim_reduction.instance", source: "stage3.sumcheck", claim: "stage3.registers_claim_reduction.input", relation: "jolt.stage3.registers_claim_reduction", index: 2, point_arity: 16, num_rounds: 16, round_offset: 0, point_order: "reverse", degree: 2 }, + Stage3SumcheckInstanceResultPlan { symbol: "stage3.spartan_shift.instance", source: "stage3.sumcheck", claim: "stage3.spartan_shift.input", relation: "jolt.stage3.spartan_shift", index: 0, point_arity: 18, num_rounds: 18, round_offset: 0, point_order: "reverse", degree: 2 }, + Stage3SumcheckInstanceResultPlan { symbol: "stage3.instruction_input.instance", source: "stage3.sumcheck", claim: "stage3.instruction_input.input", relation: "jolt.stage3.instruction_input", index: 1, point_arity: 18, num_rounds: 18, round_offset: 0, point_order: "reverse", degree: 3 }, + Stage3SumcheckInstanceResultPlan { symbol: "stage3.registers_claim_reduction.instance", source: "stage3.sumcheck", claim: "stage3.registers_claim_reduction.input", relation: "jolt.stage3.registers_claim_reduction", index: 2, point_arity: 18, num_rounds: 18, round_offset: 0, point_order: "reverse", degree: 2 }, ]; pub const STAGE3_SUMCHECK_EVALS: &[Stage3SumcheckEvalPlan] = &[ @@ -156,22 +156,22 @@ pub const STAGE3_POINT_CONCATS: &[Stage3PointConcatPlan] = &[ ]; pub const STAGE3_OPENING_CLAIMS: &[Stage3OpeningClaimPlan] = &[ - Stage3OpeningClaimPlan { symbol: "stage3.spartan_shift.opening.UnexpandedPC", oracle: "UnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.spartan_shift.instance", eval_source: "stage3.spartan_shift.eval.UnexpandedPC" }, - Stage3OpeningClaimPlan { symbol: "stage3.spartan_shift.opening.PC", oracle: "PC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.spartan_shift.instance", eval_source: "stage3.spartan_shift.eval.PC" }, - Stage3OpeningClaimPlan { symbol: "stage3.spartan_shift.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.spartan_shift.instance", eval_source: "stage3.spartan_shift.eval.OpFlagVirtualInstruction" }, - Stage3OpeningClaimPlan { symbol: "stage3.spartan_shift.opening.OpFlagIsFirstInSequence", oracle: "OpFlagIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.spartan_shift.instance", eval_source: "stage3.spartan_shift.eval.OpFlagIsFirstInSequence" }, - Stage3OpeningClaimPlan { symbol: "stage3.spartan_shift.opening.InstructionFlagIsNoop", oracle: "InstructionFlagIsNoop", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.spartan_shift.instance", eval_source: "stage3.spartan_shift.eval.InstructionFlagIsNoop" }, - Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.InstructionFlagLeftOperandIsRs1Value", oracle: "InstructionFlagLeftOperandIsRs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.InstructionFlagLeftOperandIsRs1Value" }, - Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.Rs1Value" }, - Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.InstructionFlagLeftOperandIsPC", oracle: "InstructionFlagLeftOperandIsPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.InstructionFlagLeftOperandIsPC" }, - Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.UnexpandedPC", oracle: "UnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.UnexpandedPC" }, - Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.InstructionFlagRightOperandIsRs2Value", oracle: "InstructionFlagRightOperandIsRs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.InstructionFlagRightOperandIsRs2Value" }, - Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.Rs2Value" }, - Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.InstructionFlagRightOperandIsImm", oracle: "InstructionFlagRightOperandIsImm", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.InstructionFlagRightOperandIsImm" }, - Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.Imm", oracle: "Imm", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.Imm" }, - Stage3OpeningClaimPlan { symbol: "stage3.registers_claim_reduction.opening.RdWriteValue", oracle: "RdWriteValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.registers_claim_reduction.instance", eval_source: "stage3.registers_claim_reduction.eval.RdWriteValue" }, - Stage3OpeningClaimPlan { symbol: "stage3.registers_claim_reduction.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.registers_claim_reduction.instance", eval_source: "stage3.registers_claim_reduction.eval.Rs1Value" }, - Stage3OpeningClaimPlan { symbol: "stage3.registers_claim_reduction.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage3.registers_claim_reduction.instance", eval_source: "stage3.registers_claim_reduction.eval.Rs2Value" }, + Stage3OpeningClaimPlan { symbol: "stage3.spartan_shift.opening.UnexpandedPC", oracle: "UnexpandedPC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.spartan_shift.instance", eval_source: "stage3.spartan_shift.eval.UnexpandedPC" }, + Stage3OpeningClaimPlan { symbol: "stage3.spartan_shift.opening.PC", oracle: "PC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.spartan_shift.instance", eval_source: "stage3.spartan_shift.eval.PC" }, + Stage3OpeningClaimPlan { symbol: "stage3.spartan_shift.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.spartan_shift.instance", eval_source: "stage3.spartan_shift.eval.OpFlagVirtualInstruction" }, + Stage3OpeningClaimPlan { symbol: "stage3.spartan_shift.opening.OpFlagIsFirstInSequence", oracle: "OpFlagIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.spartan_shift.instance", eval_source: "stage3.spartan_shift.eval.OpFlagIsFirstInSequence" }, + Stage3OpeningClaimPlan { symbol: "stage3.spartan_shift.opening.InstructionFlagIsNoop", oracle: "InstructionFlagIsNoop", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.spartan_shift.instance", eval_source: "stage3.spartan_shift.eval.InstructionFlagIsNoop" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.InstructionFlagLeftOperandIsRs1Value", oracle: "InstructionFlagLeftOperandIsRs1Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.InstructionFlagLeftOperandIsRs1Value" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.Rs1Value" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.InstructionFlagLeftOperandIsPC", oracle: "InstructionFlagLeftOperandIsPC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.InstructionFlagLeftOperandIsPC" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.UnexpandedPC", oracle: "UnexpandedPC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.UnexpandedPC" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.InstructionFlagRightOperandIsRs2Value", oracle: "InstructionFlagRightOperandIsRs2Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.InstructionFlagRightOperandIsRs2Value" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.Rs2Value" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.InstructionFlagRightOperandIsImm", oracle: "InstructionFlagRightOperandIsImm", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.InstructionFlagRightOperandIsImm" }, + Stage3OpeningClaimPlan { symbol: "stage3.instruction_input.opening.Imm", oracle: "Imm", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.instruction_input.instance", eval_source: "stage3.instruction_input.eval.Imm" }, + Stage3OpeningClaimPlan { symbol: "stage3.registers_claim_reduction.opening.RdWriteValue", oracle: "RdWriteValue", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.registers_claim_reduction.instance", eval_source: "stage3.registers_claim_reduction.eval.RdWriteValue" }, + Stage3OpeningClaimPlan { symbol: "stage3.registers_claim_reduction.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.registers_claim_reduction.instance", eval_source: "stage3.registers_claim_reduction.eval.Rs1Value" }, + Stage3OpeningClaimPlan { symbol: "stage3.registers_claim_reduction.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage3.registers_claim_reduction.instance", eval_source: "stage3.registers_claim_reduction.eval.Rs2Value" }, ]; pub const STAGE3_OPENING_EQUALITIES: &[Stage3OpeningClaimEqualityPlan] = &[ @@ -524,3 +524,4 @@ fn expected_registers( + super::common::store_scalar(store, "stage3.registers.gamma2")? * eval_by_name(evals, "stage3.registers_claim_reduction.eval.Rs2Value")?)) } + diff --git a/crates/jolt-verifier/src/stages/stage4.rs b/crates/jolt-verifier/src/stages/stage4.rs index 3367e34d96..d161cc430e 100644 --- a/crates/jolt-verifier/src/stages/stage4.rs +++ b/crates/jolt-verifier/src/stages/stage4.rs @@ -70,14 +70,14 @@ pub const STAGE4_TRANSCRIPT_ABSORB_BYTES: &[Stage4TranscriptAbsorbBytesPlan] = & ]; pub const STAGE4_OPENING_INPUTS: &[Stage4OpeningInputPlan] = &[ - Stage4OpeningInputPlan { symbol: "stage4.input.stage3.registers.RdWriteValue", source_stage: "stage3", source_claim: "stage3.registers_claim_reduction.opening.RdWriteValue", oracle: "RdWriteValue", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage4OpeningInputPlan { symbol: "stage4.input.stage3.registers.Rs1Value", source_stage: "stage3", source_claim: "stage3.registers_claim_reduction.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage4OpeningInputPlan { symbol: "stage4.input.stage3.registers.Rs2Value", source_stage: "stage3", source_claim: "stage3.registers_claim_reduction.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage4OpeningInputPlan { symbol: "stage4.input.stage3.instruction.Rs1Value", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage4OpeningInputPlan { symbol: "stage4.input.stage3.instruction.Rs2Value", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage4OpeningInputPlan { symbol: "stage4.input.stage3.registers.RdWriteValue", source_stage: "stage3", source_claim: "stage3.registers_claim_reduction.opening.RdWriteValue", oracle: "RdWriteValue", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage4OpeningInputPlan { symbol: "stage4.input.stage3.registers.Rs1Value", source_stage: "stage3", source_claim: "stage3.registers_claim_reduction.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage4OpeningInputPlan { symbol: "stage4.input.stage3.registers.Rs2Value", source_stage: "stage3", source_claim: "stage3.registers_claim_reduction.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage4OpeningInputPlan { symbol: "stage4.input.stage3.instruction.Rs1Value", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.Rs1Value", oracle: "Rs1Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage4OpeningInputPlan { symbol: "stage4.input.stage3.instruction.Rs2Value", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.Rs2Value", oracle: "Rs2Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, Stage4OpeningInputPlan { symbol: "stage4.input.stage2.RamVal", source_stage: "stage2", source_claim: "stage2.ram_read_write.opening.RamVal", oracle: "RamVal", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual" }, - Stage4OpeningInputPlan { symbol: "stage4.input.stage2.RamValFinal", source_stage: "stage2", source_claim: "stage2.ram_output.opening.RamValFinal", oracle: "RamValFinal", domain: "jolt.ram_address_domain", point_arity: 16, claim_kind: "virtual" }, - Stage4OpeningInputPlan { symbol: "stage4.input.initial_ram.RamValInit", source_stage: "stage4_precomputed", source_claim: "stage4.ram_val_check.initial_ram_eval", oracle: "RamValInit", domain: "jolt.ram_address_domain", point_arity: 16, claim_kind: "virtual" }, + Stage4OpeningInputPlan { symbol: "stage4.input.stage2.RamValFinal", source_stage: "stage2", source_claim: "stage2.ram_output.opening.RamValFinal", oracle: "RamValFinal", domain: "jolt.ram_address_domain", point_arity: 14, claim_kind: "virtual" }, + Stage4OpeningInputPlan { symbol: "stage4.input.initial_ram.RamValInit", source_stage: "stage4_precomputed", source_claim: "stage4.ram_val_check.initial_ram_eval", oracle: "RamValInit", domain: "jolt.ram_address_domain", point_arity: 14, claim_kind: "virtual" }, ]; pub const STAGE4_FIELD_CONSTANTS: &[Stage4FieldConstantPlan] = &[ @@ -100,11 +100,11 @@ pub const STAGE4_KERNELS: &[Stage4KernelPlan] = &[ ]; pub const STAGE4_SUMCHECK_CLAIMS: &[Stage4SumcheckClaimPlan] = &[ - Stage4SumcheckClaimPlan { symbol: "stage4.registers_read_write.input", stage: "stage4", domain: "jolt.stage4_registers_rw_domain", num_rounds: 23, degree: 3, claim: "stage4.registers_read_write.weighted_values", kernel: None, relation: Some("jolt.stage4.registers_read_write"), claim_value: "stage4.registers_read_write.claim_expr", input_openings: "stage4.input.stage3.registers.RdWriteValue|stage4.input.stage3.registers.Rs1Value|stage4.input.stage3.registers.Rs2Value" }, - Stage4SumcheckClaimPlan { symbol: "stage4.ram_val_check.input", stage: "stage4", domain: "jolt.trace_domain", num_rounds: 16, degree: 3, claim: "stage4.ram_val_check.weighted_values", kernel: None, relation: Some("jolt.stage4.ram_val_check"), claim_value: "stage4.ram_val_check.claim_expr", input_openings: "stage4.input.stage2.RamVal|stage4.input.stage2.RamValFinal|stage4.input.initial_ram.RamValInit" }, + Stage4SumcheckClaimPlan { symbol: "stage4.registers_read_write.input", stage: "stage4", domain: "jolt.stage4_registers_rw_domain", num_rounds: 25, degree: 3, claim: "stage4.registers_read_write.weighted_values", kernel: None, relation: Some("jolt.stage4.registers_read_write"), claim_value: "stage4.registers_read_write.claim_expr", input_openings: "stage4.input.stage3.registers.RdWriteValue|stage4.input.stage3.registers.Rs1Value|stage4.input.stage3.registers.Rs2Value" }, + Stage4SumcheckClaimPlan { symbol: "stage4.ram_val_check.input", stage: "stage4", domain: "jolt.trace_domain", num_rounds: 18, degree: 3, claim: "stage4.ram_val_check.weighted_values", kernel: None, relation: Some("jolt.stage4.ram_val_check"), claim_value: "stage4.ram_val_check.claim_expr", input_openings: "stage4.input.stage2.RamVal|stage4.input.stage2.RamValFinal|stage4.input.initial_ram.RamValInit" }, ]; pub const STAGE4_SUMCHECK_BATCH_0_ROUND_SCHEDULE: &[usize] = &[ - 16, + 18, 7, ]; @@ -112,16 +112,16 @@ pub const STAGE4_SUMCHECK_BATCHES: &[Stage4SumcheckBatchPlan] = &[ Stage4SumcheckBatchPlan { symbol: "stage4.batch", stage: "stage4", proof_slot: "stage4.sumcheck", policy: "jolt_core_stage4_aligned", count: 2, ordered_claims: "stage4.registers_read_write.input|stage4.ram_val_check.input", claim_operands: "stage4.registers_read_write.input|stage4.ram_val_check.input", claim_label: "sumcheck_claim", round_label: "sumcheck_poly", round_schedule: STAGE4_SUMCHECK_BATCH_0_ROUND_SCHEDULE }, ]; pub const STAGE4_SUMCHECK_DRIVER_0_ROUND_SCHEDULE: &[usize] = &[ - 16, + 18, 7, ]; pub const STAGE4_SUMCHECK_DRIVERS: &[Stage4SumcheckDriverPlan] = &[ - Stage4SumcheckDriverPlan { symbol: "stage4.sumcheck", stage: "stage4", proof_slot: "stage4.sumcheck", kernel: None, relation: Some("jolt.stage4.batched"), batch: "stage4.batch", policy: "jolt_core_stage4_aligned", round_schedule: STAGE4_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 23, degree: 3 }, + Stage4SumcheckDriverPlan { symbol: "stage4.sumcheck", stage: "stage4", proof_slot: "stage4.sumcheck", kernel: None, relation: Some("jolt.stage4.batched"), batch: "stage4.batch", policy: "jolt_core_stage4_aligned", round_schedule: STAGE4_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 25, degree: 3 }, ]; pub const STAGE4_SUMCHECK_INSTANCE_RESULTS: &[Stage4SumcheckInstanceResultPlan] = &[ - Stage4SumcheckInstanceResultPlan { symbol: "stage4.registers_read_write.instance", source: "stage4.sumcheck", claim: "stage4.registers_read_write.input", relation: "jolt.stage4.registers_read_write", index: 0, point_arity: 23, num_rounds: 23, round_offset: 0, point_order: "stage4_registers_rw", degree: 3 }, - Stage4SumcheckInstanceResultPlan { symbol: "stage4.ram_val_check.instance", source: "stage4.sumcheck", claim: "stage4.ram_val_check.input", relation: "jolt.stage4.ram_val_check", index: 1, point_arity: 16, num_rounds: 16, round_offset: 7, point_order: "reverse", degree: 3 }, + Stage4SumcheckInstanceResultPlan { symbol: "stage4.registers_read_write.instance", source: "stage4.sumcheck", claim: "stage4.registers_read_write.input", relation: "jolt.stage4.registers_read_write", index: 0, point_arity: 25, num_rounds: 25, round_offset: 0, point_order: "stage4_registers_rw", degree: 3 }, + Stage4SumcheckInstanceResultPlan { symbol: "stage4.ram_val_check.instance", source: "stage4.sumcheck", claim: "stage4.ram_val_check.input", relation: "jolt.stage4.ram_val_check", index: 1, point_arity: 18, num_rounds: 18, round_offset: 7, point_order: "reverse", degree: 3 }, ]; pub const STAGE4_SUMCHECK_EVALS: &[Stage4SumcheckEvalPlan] = &[ @@ -135,21 +135,21 @@ pub const STAGE4_SUMCHECK_EVALS: &[Stage4SumcheckEvalPlan] = &[ ]; pub const STAGE4_POINT_SLICES: &[Stage4PointSlicePlan] = &[ - Stage4PointSlicePlan { symbol: "stage4.registers_read_write.point.RdInc", source: "stage4.registers_read_write.instance", offset: 7, length: 16, input: "stage4.registers_read_write.instance" }, - Stage4PointSlicePlan { symbol: "stage4.ram_val_check.point.RamAddress", source: "stage4.input.stage2.RamVal", offset: 0, length: 16, input: "stage4.input.stage2.RamVal" }, + Stage4PointSlicePlan { symbol: "stage4.registers_read_write.point.RdInc", source: "stage4.registers_read_write.instance", offset: 7, length: 18, input: "stage4.registers_read_write.instance" }, + Stage4PointSlicePlan { symbol: "stage4.ram_val_check.point.RamAddress", source: "stage4.input.stage2.RamVal", offset: 0, length: 14, input: "stage4.input.stage2.RamVal" }, ]; pub const STAGE4_POINT_CONCATS: &[Stage4PointConcatPlan] = &[ Stage4PointConcatPlan { symbol: "stage4.ram_val_check.point.RamRa", layout: "address_then_cycle", arity: 32, inputs: "stage4.ram_val_check.point.RamAddress|stage4.ram_val_check.instance" }, ]; pub const STAGE4_OPENING_CLAIMS: &[Stage4OpeningClaimPlan] = &[ - Stage4OpeningClaimPlan { symbol: "stage4.registers_read_write.opening.RegistersVal", oracle: "RegistersVal", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual", point_source: "stage4.registers_read_write.instance", eval_source: "stage4.registers_read_write.eval.RegistersVal" }, - Stage4OpeningClaimPlan { symbol: "stage4.registers_read_write.opening.Rs1Ra", oracle: "Rs1Ra", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual", point_source: "stage4.registers_read_write.instance", eval_source: "stage4.registers_read_write.eval.Rs1Ra" }, - Stage4OpeningClaimPlan { symbol: "stage4.registers_read_write.opening.Rs2Ra", oracle: "Rs2Ra", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual", point_source: "stage4.registers_read_write.instance", eval_source: "stage4.registers_read_write.eval.Rs2Ra" }, - Stage4OpeningClaimPlan { symbol: "stage4.registers_read_write.opening.RdWa", oracle: "RdWa", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual", point_source: "stage4.registers_read_write.instance", eval_source: "stage4.registers_read_write.eval.RdWa" }, - Stage4OpeningClaimPlan { symbol: "stage4.registers_read_write.opening.RdInc", oracle: "RdInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed", point_source: "stage4.registers_read_write.point.RdInc", eval_source: "stage4.registers_read_write.eval.RdInc" }, + Stage4OpeningClaimPlan { symbol: "stage4.registers_read_write.opening.RegistersVal", oracle: "RegistersVal", domain: "jolt.stage4_registers_rw_domain", point_arity: 25, claim_kind: "virtual", point_source: "stage4.registers_read_write.instance", eval_source: "stage4.registers_read_write.eval.RegistersVal" }, + Stage4OpeningClaimPlan { symbol: "stage4.registers_read_write.opening.Rs1Ra", oracle: "Rs1Ra", domain: "jolt.stage4_registers_rw_domain", point_arity: 25, claim_kind: "virtual", point_source: "stage4.registers_read_write.instance", eval_source: "stage4.registers_read_write.eval.Rs1Ra" }, + Stage4OpeningClaimPlan { symbol: "stage4.registers_read_write.opening.Rs2Ra", oracle: "Rs2Ra", domain: "jolt.stage4_registers_rw_domain", point_arity: 25, claim_kind: "virtual", point_source: "stage4.registers_read_write.instance", eval_source: "stage4.registers_read_write.eval.Rs2Ra" }, + Stage4OpeningClaimPlan { symbol: "stage4.registers_read_write.opening.RdWa", oracle: "RdWa", domain: "jolt.stage4_registers_rw_domain", point_arity: 25, claim_kind: "virtual", point_source: "stage4.registers_read_write.instance", eval_source: "stage4.registers_read_write.eval.RdWa" }, + Stage4OpeningClaimPlan { symbol: "stage4.registers_read_write.opening.RdInc", oracle: "RdInc", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "committed", point_source: "stage4.registers_read_write.point.RdInc", eval_source: "stage4.registers_read_write.eval.RdInc" }, Stage4OpeningClaimPlan { symbol: "stage4.ram_val_check.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage4.ram_val_check.point.RamRa", eval_source: "stage4.ram_val_check.eval.RamRa" }, - Stage4OpeningClaimPlan { symbol: "stage4.ram_val_check.opening.RamInc", oracle: "RamInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed", point_source: "stage4.ram_val_check.instance", eval_source: "stage4.ram_val_check.eval.RamInc" }, + Stage4OpeningClaimPlan { symbol: "stage4.ram_val_check.opening.RamInc", oracle: "RamInc", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "committed", point_source: "stage4.ram_val_check.instance", eval_source: "stage4.ram_val_check.eval.RamInc" }, ]; pub const STAGE4_OPENING_EQUALITIES: &[Stage4OpeningClaimEqualityPlan] = &[ @@ -550,3 +550,4 @@ fn normalize_stage4_registers_rw_cycle_point( })?; Ok(cycle.iter().rev().copied().collect()) } + diff --git a/crates/jolt-verifier/src/stages/stage5.rs b/crates/jolt-verifier/src/stages/stage5.rs index 8ff3c55f10..9115c05755 100644 --- a/crates/jolt-verifier/src/stages/stage5.rs +++ b/crates/jolt-verifier/src/stages/stage5.rs @@ -70,14 +70,14 @@ pub const STAGE5_TRANSCRIPT_ABSORB_BYTES: &[Stage5TranscriptAbsorbBytesPlan] = & ]; pub const STAGE5_OPENING_INPUTS: &[Stage5OpeningInputPlan] = &[ - Stage5OpeningInputPlan { symbol: "stage5.input.stage2.instruction.LookupOutput", source_stage: "stage2", source_claim: "stage2.instruction_lookup.claim_reduction.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage5OpeningInputPlan { symbol: "stage5.input.stage2.product_virtual.LookupOutput", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage5OpeningInputPlan { symbol: "stage5.input.stage2.instruction.LeftLookupOperand", source_stage: "stage2", source_claim: "stage2.instruction_lookup.claim_reduction.opening.LeftLookupOperand", oracle: "LeftLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage5OpeningInputPlan { symbol: "stage5.input.stage2.instruction.RightLookupOperand", source_stage: "stage2", source_claim: "stage2.instruction_lookup.claim_reduction.opening.RightLookupOperand", oracle: "RightLookupOperand", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage5OpeningInputPlan { symbol: "stage5.input.stage2.instruction.LookupOutput", source_stage: "stage2", source_claim: "stage2.instruction_lookup.claim_reduction.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage5OpeningInputPlan { symbol: "stage5.input.stage2.product_virtual.LookupOutput", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage5OpeningInputPlan { symbol: "stage5.input.stage2.instruction.LeftLookupOperand", source_stage: "stage2", source_claim: "stage2.instruction_lookup.claim_reduction.opening.LeftLookupOperand", oracle: "LeftLookupOperand", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage5OpeningInputPlan { symbol: "stage5.input.stage2.instruction.RightLookupOperand", source_stage: "stage2", source_claim: "stage2.instruction_lookup.claim_reduction.opening.RightLookupOperand", oracle: "RightLookupOperand", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, Stage5OpeningInputPlan { symbol: "stage5.input.stage2.ram_raf.RamRa", source_stage: "stage2", source_claim: "stage2.ram_raf.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual" }, Stage5OpeningInputPlan { symbol: "stage5.input.stage2.ram_read_write.RamRa", source_stage: "stage2", source_claim: "stage2.ram_read_write.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual" }, Stage5OpeningInputPlan { symbol: "stage5.input.stage4.ram_val_check.RamRa", source_stage: "stage4", source_claim: "stage4.ram_val_check.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual" }, - Stage5OpeningInputPlan { symbol: "stage5.input.stage4.registers.RegistersVal", source_stage: "stage4", source_claim: "stage4.registers_read_write.opening.RegistersVal", oracle: "RegistersVal", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual" }, + Stage5OpeningInputPlan { symbol: "stage5.input.stage4.registers.RegistersVal", source_stage: "stage4", source_claim: "stage4.registers_read_write.opening.RegistersVal", oracle: "RegistersVal", domain: "jolt.stage4_registers_rw_domain", point_arity: 25, claim_kind: "virtual" }, ]; pub const STAGE5_FIELD_CONSTANTS: &[Stage5FieldConstantPlan] = &[ @@ -101,13 +101,13 @@ pub const STAGE5_KERNELS: &[Stage5KernelPlan] = &[ ]; pub const STAGE5_SUMCHECK_CLAIMS: &[Stage5SumcheckClaimPlan] = &[ - Stage5SumcheckClaimPlan { symbol: "stage5.instruction_read_raf.input", stage: "stage5", domain: "jolt.stage5_instruction_read_raf_domain", num_rounds: 144, degree: 10, claim: "stage5.instruction_read_raf.weighted_lookup_values", kernel: None, relation: Some("jolt.stage5.instruction_read_raf"), claim_value: "stage5.instruction_read_raf.claim_expr", input_openings: "stage5.input.stage2.instruction.LookupOutput|stage5.input.stage2.instruction.LeftLookupOperand|stage5.input.stage2.instruction.RightLookupOperand" }, - Stage5SumcheckClaimPlan { symbol: "stage5.ram_ra_claim_reduction.input", stage: "stage5", domain: "jolt.trace_domain", num_rounds: 16, degree: 2, claim: "stage5.ram_ra_claim_reduction.weighted_ram_ra", kernel: None, relation: Some("jolt.stage5.ram_ra_claim_reduction"), claim_value: "stage5.ram_ra_claim_reduction.claim_expr", input_openings: "stage5.input.stage2.ram_raf.RamRa|stage5.input.stage2.ram_read_write.RamRa|stage5.input.stage4.ram_val_check.RamRa" }, - Stage5SumcheckClaimPlan { symbol: "stage5.registers_val_evaluation.input", stage: "stage5", domain: "jolt.trace_domain", num_rounds: 16, degree: 3, claim: "stage5.registers_val_evaluation.registers_val", kernel: None, relation: Some("jolt.stage5.registers_val_evaluation"), claim_value: "stage5.input.stage4.registers.RegistersVal", input_openings: "stage5.input.stage4.registers.RegistersVal" }, + Stage5SumcheckClaimPlan { symbol: "stage5.instruction_read_raf.input", stage: "stage5", domain: "jolt.stage5_instruction_read_raf_domain", num_rounds: 146, degree: 10, claim: "stage5.instruction_read_raf.weighted_lookup_values", kernel: None, relation: Some("jolt.stage5.instruction_read_raf"), claim_value: "stage5.instruction_read_raf.claim_expr", input_openings: "stage5.input.stage2.instruction.LookupOutput|stage5.input.stage2.instruction.LeftLookupOperand|stage5.input.stage2.instruction.RightLookupOperand" }, + Stage5SumcheckClaimPlan { symbol: "stage5.ram_ra_claim_reduction.input", stage: "stage5", domain: "jolt.trace_domain", num_rounds: 18, degree: 2, claim: "stage5.ram_ra_claim_reduction.weighted_ram_ra", kernel: None, relation: Some("jolt.stage5.ram_ra_claim_reduction"), claim_value: "stage5.ram_ra_claim_reduction.claim_expr", input_openings: "stage5.input.stage2.ram_raf.RamRa|stage5.input.stage2.ram_read_write.RamRa|stage5.input.stage4.ram_val_check.RamRa" }, + Stage5SumcheckClaimPlan { symbol: "stage5.registers_val_evaluation.input", stage: "stage5", domain: "jolt.trace_domain", num_rounds: 18, degree: 3, claim: "stage5.registers_val_evaluation.registers_val", kernel: None, relation: Some("jolt.stage5.registers_val_evaluation"), claim_value: "stage5.input.stage4.registers.RegistersVal", input_openings: "stage5.input.stage4.registers.RegistersVal" }, ]; pub const STAGE5_SUMCHECK_BATCH_0_ROUND_SCHEDULE: &[usize] = &[ 128, - 16, + 18, ]; pub const STAGE5_SUMCHECK_BATCHES: &[Stage5SumcheckBatchPlan] = &[ @@ -115,16 +115,16 @@ pub const STAGE5_SUMCHECK_BATCHES: &[Stage5SumcheckBatchPlan] = &[ ]; pub const STAGE5_SUMCHECK_DRIVER_0_ROUND_SCHEDULE: &[usize] = &[ 128, - 16, + 18, ]; pub const STAGE5_SUMCHECK_DRIVERS: &[Stage5SumcheckDriverPlan] = &[ - Stage5SumcheckDriverPlan { symbol: "stage5.sumcheck", stage: "stage5", proof_slot: "stage5.sumcheck", kernel: None, relation: Some("jolt.stage5.batched"), batch: "stage5.batch", policy: "jolt_core_stage5_aligned", round_schedule: STAGE5_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 144, degree: 10 }, + Stage5SumcheckDriverPlan { symbol: "stage5.sumcheck", stage: "stage5", proof_slot: "stage5.sumcheck", kernel: None, relation: Some("jolt.stage5.batched"), batch: "stage5.batch", policy: "jolt_core_stage5_aligned", round_schedule: STAGE5_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 146, degree: 10 }, ]; pub const STAGE5_SUMCHECK_INSTANCE_RESULTS: &[Stage5SumcheckInstanceResultPlan] = &[ - Stage5SumcheckInstanceResultPlan { symbol: "stage5.instruction_read_raf.instance", source: "stage5.sumcheck", claim: "stage5.instruction_read_raf.input", relation: "jolt.stage5.instruction_read_raf", index: 0, point_arity: 144, num_rounds: 144, round_offset: 0, point_order: "instruction_read_raf", degree: 10 }, - Stage5SumcheckInstanceResultPlan { symbol: "stage5.ram_ra_claim_reduction.instance", source: "stage5.sumcheck", claim: "stage5.ram_ra_claim_reduction.input", relation: "jolt.stage5.ram_ra_claim_reduction", index: 1, point_arity: 16, num_rounds: 16, round_offset: 128, point_order: "reverse", degree: 2 }, - Stage5SumcheckInstanceResultPlan { symbol: "stage5.registers_val_evaluation.instance", source: "stage5.sumcheck", claim: "stage5.registers_val_evaluation.input", relation: "jolt.stage5.registers_val_evaluation", index: 2, point_arity: 16, num_rounds: 16, round_offset: 128, point_order: "reverse", degree: 3 }, + Stage5SumcheckInstanceResultPlan { symbol: "stage5.instruction_read_raf.instance", source: "stage5.sumcheck", claim: "stage5.instruction_read_raf.input", relation: "jolt.stage5.instruction_read_raf", index: 0, point_arity: 146, num_rounds: 146, round_offset: 0, point_order: "instruction_read_raf", degree: 10 }, + Stage5SumcheckInstanceResultPlan { symbol: "stage5.ram_ra_claim_reduction.instance", source: "stage5.sumcheck", claim: "stage5.ram_ra_claim_reduction.input", relation: "jolt.stage5.ram_ra_claim_reduction", index: 1, point_arity: 18, num_rounds: 18, round_offset: 128, point_order: "reverse", degree: 2 }, + Stage5SumcheckInstanceResultPlan { symbol: "stage5.registers_val_evaluation.instance", source: "stage5.sumcheck", claim: "stage5.registers_val_evaluation.input", relation: "jolt.stage5.registers_val_evaluation", index: 2, point_arity: 18, num_rounds: 18, round_offset: 128, point_order: "reverse", degree: 3 }, ]; pub const STAGE5_SUMCHECK_EVALS: &[Stage5SumcheckEvalPlan] = &[ @@ -183,7 +183,7 @@ pub const STAGE5_SUMCHECK_EVALS: &[Stage5SumcheckEvalPlan] = &[ ]; pub const STAGE5_POINT_SLICES: &[Stage5PointSlicePlan] = &[ - Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.Cycle", source: "stage5.instruction_read_raf.instance", offset: 128, length: 16, input: "stage5.instruction_read_raf.instance" }, + Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.Cycle", source: "stage5.instruction_read_raf.instance", offset: 128, length: 18, input: "stage5.instruction_read_raf.instance" }, Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_0.address", source: "stage5.instruction_read_raf.instance", offset: 0, length: 16, input: "stage5.instruction_read_raf.instance" }, Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_1.address", source: "stage5.instruction_read_raf.instance", offset: 16, length: 16, input: "stage5.instruction_read_raf.instance" }, Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_2.address", source: "stage5.instruction_read_raf.instance", offset: 32, length: 16, input: "stage5.instruction_read_raf.instance" }, @@ -192,75 +192,75 @@ pub const STAGE5_POINT_SLICES: &[Stage5PointSlicePlan] = &[ Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_5.address", source: "stage5.instruction_read_raf.instance", offset: 80, length: 16, input: "stage5.instruction_read_raf.instance" }, Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_6.address", source: "stage5.instruction_read_raf.instance", offset: 96, length: 16, input: "stage5.instruction_read_raf.instance" }, Stage5PointSlicePlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_7.address", source: "stage5.instruction_read_raf.instance", offset: 112, length: 16, input: "stage5.instruction_read_raf.instance" }, - Stage5PointSlicePlan { symbol: "stage5.ram_ra_claim_reduction.point.RamAddress", source: "stage5.input.stage2.ram_raf.RamRa", offset: 0, length: 16, input: "stage5.input.stage2.ram_raf.RamRa" }, + Stage5PointSlicePlan { symbol: "stage5.ram_ra_claim_reduction.point.RamAddress", source: "stage5.input.stage2.ram_raf.RamRa", offset: 0, length: 14, input: "stage5.input.stage2.ram_raf.RamRa" }, Stage5PointSlicePlan { symbol: "stage5.registers_val_evaluation.point.RegisterAddress", source: "stage5.input.stage4.registers.RegistersVal", offset: 0, length: 7, input: "stage5.input.stage4.registers.RegistersVal" }, ]; pub const STAGE5_POINT_CONCATS: &[Stage5PointConcatPlan] = &[ - Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_0", layout: "address_chunk_then_cycle", arity: 32, inputs: "stage5.instruction_read_raf.point.InstructionRa_0.address|stage5.instruction_read_raf.point.Cycle" }, - Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_1", layout: "address_chunk_then_cycle", arity: 32, inputs: "stage5.instruction_read_raf.point.InstructionRa_1.address|stage5.instruction_read_raf.point.Cycle" }, - Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_2", layout: "address_chunk_then_cycle", arity: 32, inputs: "stage5.instruction_read_raf.point.InstructionRa_2.address|stage5.instruction_read_raf.point.Cycle" }, - Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_3", layout: "address_chunk_then_cycle", arity: 32, inputs: "stage5.instruction_read_raf.point.InstructionRa_3.address|stage5.instruction_read_raf.point.Cycle" }, - Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_4", layout: "address_chunk_then_cycle", arity: 32, inputs: "stage5.instruction_read_raf.point.InstructionRa_4.address|stage5.instruction_read_raf.point.Cycle" }, - Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_5", layout: "address_chunk_then_cycle", arity: 32, inputs: "stage5.instruction_read_raf.point.InstructionRa_5.address|stage5.instruction_read_raf.point.Cycle" }, - Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_6", layout: "address_chunk_then_cycle", arity: 32, inputs: "stage5.instruction_read_raf.point.InstructionRa_6.address|stage5.instruction_read_raf.point.Cycle" }, - Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_7", layout: "address_chunk_then_cycle", arity: 32, inputs: "stage5.instruction_read_raf.point.InstructionRa_7.address|stage5.instruction_read_raf.point.Cycle" }, + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_0", layout: "address_chunk_then_cycle", arity: 34, inputs: "stage5.instruction_read_raf.point.InstructionRa_0.address|stage5.instruction_read_raf.point.Cycle" }, + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_1", layout: "address_chunk_then_cycle", arity: 34, inputs: "stage5.instruction_read_raf.point.InstructionRa_1.address|stage5.instruction_read_raf.point.Cycle" }, + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_2", layout: "address_chunk_then_cycle", arity: 34, inputs: "stage5.instruction_read_raf.point.InstructionRa_2.address|stage5.instruction_read_raf.point.Cycle" }, + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_3", layout: "address_chunk_then_cycle", arity: 34, inputs: "stage5.instruction_read_raf.point.InstructionRa_3.address|stage5.instruction_read_raf.point.Cycle" }, + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_4", layout: "address_chunk_then_cycle", arity: 34, inputs: "stage5.instruction_read_raf.point.InstructionRa_4.address|stage5.instruction_read_raf.point.Cycle" }, + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_5", layout: "address_chunk_then_cycle", arity: 34, inputs: "stage5.instruction_read_raf.point.InstructionRa_5.address|stage5.instruction_read_raf.point.Cycle" }, + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_6", layout: "address_chunk_then_cycle", arity: 34, inputs: "stage5.instruction_read_raf.point.InstructionRa_6.address|stage5.instruction_read_raf.point.Cycle" }, + Stage5PointConcatPlan { symbol: "stage5.instruction_read_raf.point.InstructionRa_7", layout: "address_chunk_then_cycle", arity: 34, inputs: "stage5.instruction_read_raf.point.InstructionRa_7.address|stage5.instruction_read_raf.point.Cycle" }, Stage5PointConcatPlan { symbol: "stage5.ram_ra_claim_reduction.point.RamRa", layout: "address_then_cycle", arity: 32, inputs: "stage5.ram_ra_claim_reduction.point.RamAddress|stage5.ram_ra_claim_reduction.instance" }, - Stage5PointConcatPlan { symbol: "stage5.registers_val_evaluation.point.RdWa", layout: "register_address_then_cycle", arity: 23, inputs: "stage5.registers_val_evaluation.point.RegisterAddress|stage5.registers_val_evaluation.instance" }, + Stage5PointConcatPlan { symbol: "stage5.registers_val_evaluation.point.RdWa", layout: "register_address_then_cycle", arity: 25, inputs: "stage5.registers_val_evaluation.point.RegisterAddress|stage5.registers_val_evaluation.instance" }, ]; pub const STAGE5_OPENING_CLAIMS: &[Stage5OpeningClaimPlan] = &[ - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_0", oracle: "LookupTableFlag_0", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_0" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_1", oracle: "LookupTableFlag_1", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_1" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_2", oracle: "LookupTableFlag_2", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_2" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_3", oracle: "LookupTableFlag_3", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_3" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_4", oracle: "LookupTableFlag_4", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_4" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_5", oracle: "LookupTableFlag_5", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_5" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_6", oracle: "LookupTableFlag_6", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_6" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_7", oracle: "LookupTableFlag_7", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_7" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_8", oracle: "LookupTableFlag_8", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_8" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_9", oracle: "LookupTableFlag_9", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_9" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_10", oracle: "LookupTableFlag_10", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_10" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_11", oracle: "LookupTableFlag_11", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_11" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_12", oracle: "LookupTableFlag_12", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_12" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_13", oracle: "LookupTableFlag_13", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_13" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_14", oracle: "LookupTableFlag_14", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_14" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_15", oracle: "LookupTableFlag_15", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_15" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_16", oracle: "LookupTableFlag_16", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_16" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_17", oracle: "LookupTableFlag_17", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_17" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_18", oracle: "LookupTableFlag_18", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_18" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_19", oracle: "LookupTableFlag_19", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_19" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_20", oracle: "LookupTableFlag_20", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_20" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_21", oracle: "LookupTableFlag_21", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_21" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_22", oracle: "LookupTableFlag_22", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_22" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_23", oracle: "LookupTableFlag_23", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_23" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_24", oracle: "LookupTableFlag_24", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_24" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_25", oracle: "LookupTableFlag_25", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_25" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_26", oracle: "LookupTableFlag_26", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_26" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_27", oracle: "LookupTableFlag_27", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_27" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_28", oracle: "LookupTableFlag_28", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_28" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_29", oracle: "LookupTableFlag_29", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_29" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_30", oracle: "LookupTableFlag_30", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_30" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_31", oracle: "LookupTableFlag_31", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_31" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_32", oracle: "LookupTableFlag_32", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_32" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_33", oracle: "LookupTableFlag_33", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_33" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_34", oracle: "LookupTableFlag_34", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_34" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_35", oracle: "LookupTableFlag_35", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_35" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_36", oracle: "LookupTableFlag_36", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_36" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_37", oracle: "LookupTableFlag_37", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_37" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_38", oracle: "LookupTableFlag_38", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_38" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_39", oracle: "LookupTableFlag_39", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_39" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_0", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_0" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_1", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_1" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_2", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_2" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_3", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_3" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_4", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_4" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_5", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_5" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_6", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_6" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_7", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_7" }, - Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRafFlag", oracle: "InstructionRafFlag", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.InstructionRafFlag" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_0", oracle: "LookupTableFlag_0", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_0" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_1", oracle: "LookupTableFlag_1", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_1" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_2", oracle: "LookupTableFlag_2", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_2" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_3", oracle: "LookupTableFlag_3", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_3" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_4", oracle: "LookupTableFlag_4", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_4" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_5", oracle: "LookupTableFlag_5", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_5" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_6", oracle: "LookupTableFlag_6", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_6" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_7", oracle: "LookupTableFlag_7", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_7" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_8", oracle: "LookupTableFlag_8", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_8" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_9", oracle: "LookupTableFlag_9", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_9" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_10", oracle: "LookupTableFlag_10", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_10" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_11", oracle: "LookupTableFlag_11", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_11" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_12", oracle: "LookupTableFlag_12", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_12" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_13", oracle: "LookupTableFlag_13", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_13" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_14", oracle: "LookupTableFlag_14", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_14" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_15", oracle: "LookupTableFlag_15", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_15" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_16", oracle: "LookupTableFlag_16", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_16" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_17", oracle: "LookupTableFlag_17", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_17" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_18", oracle: "LookupTableFlag_18", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_18" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_19", oracle: "LookupTableFlag_19", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_19" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_20", oracle: "LookupTableFlag_20", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_20" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_21", oracle: "LookupTableFlag_21", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_21" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_22", oracle: "LookupTableFlag_22", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_22" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_23", oracle: "LookupTableFlag_23", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_23" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_24", oracle: "LookupTableFlag_24", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_24" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_25", oracle: "LookupTableFlag_25", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_25" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_26", oracle: "LookupTableFlag_26", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_26" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_27", oracle: "LookupTableFlag_27", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_27" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_28", oracle: "LookupTableFlag_28", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_28" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_29", oracle: "LookupTableFlag_29", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_29" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_30", oracle: "LookupTableFlag_30", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_30" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_31", oracle: "LookupTableFlag_31", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_31" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_32", oracle: "LookupTableFlag_32", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_32" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_33", oracle: "LookupTableFlag_33", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_33" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_34", oracle: "LookupTableFlag_34", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_34" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_35", oracle: "LookupTableFlag_35", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_35" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_36", oracle: "LookupTableFlag_36", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_36" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_37", oracle: "LookupTableFlag_37", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_37" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_38", oracle: "LookupTableFlag_38", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_38" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.LookupTableFlag_39", oracle: "LookupTableFlag_39", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.LookupTableFlag_39" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_0", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_0" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_1", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_1" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_2", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_2" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_3", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_3" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_4", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_4" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_5", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_5" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_6", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_6" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.InstructionRa_7", eval_source: "stage5.instruction_read_raf.eval.InstructionRa_7" }, + Stage5OpeningClaimPlan { symbol: "stage5.instruction_read_raf.opening.InstructionRafFlag", oracle: "InstructionRafFlag", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage5.instruction_read_raf.point.Cycle", eval_source: "stage5.instruction_read_raf.eval.InstructionRafFlag" }, Stage5OpeningClaimPlan { symbol: "stage5.ram_ra_claim_reduction.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual", point_source: "stage5.ram_ra_claim_reduction.point.RamRa", eval_source: "stage5.ram_ra_claim_reduction.eval.RamRa" }, - Stage5OpeningClaimPlan { symbol: "stage5.registers_val_evaluation.opening.RdInc", oracle: "RdInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed", point_source: "stage5.registers_val_evaluation.instance", eval_source: "stage5.registers_val_evaluation.eval.RdInc" }, - Stage5OpeningClaimPlan { symbol: "stage5.registers_val_evaluation.opening.RdWa", oracle: "RdWa", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual", point_source: "stage5.registers_val_evaluation.point.RdWa", eval_source: "stage5.registers_val_evaluation.eval.RdWa" }, + Stage5OpeningClaimPlan { symbol: "stage5.registers_val_evaluation.opening.RdInc", oracle: "RdInc", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "committed", point_source: "stage5.registers_val_evaluation.instance", eval_source: "stage5.registers_val_evaluation.eval.RdInc" }, + Stage5OpeningClaimPlan { symbol: "stage5.registers_val_evaluation.opening.RdWa", oracle: "RdWa", domain: "jolt.stage4_registers_rw_domain", point_arity: 25, claim_kind: "virtual", point_source: "stage5.registers_val_evaluation.point.RdWa", eval_source: "stage5.registers_val_evaluation.eval.RdWa" }, ]; pub const STAGE5_OPENING_EQUALITIES: &[Stage5OpeningClaimEqualityPlan] = &[ @@ -660,3 +660,4 @@ fn expected_registers_val_evaluation( let rd_wa = eval_by_name(evals, "stage5.registers_val_evaluation.eval.RdWa")?; Ok(rd_inc * rd_wa * lt_eval) } + diff --git a/crates/jolt-verifier/src/stages/stage6.rs b/crates/jolt-verifier/src/stages/stage6.rs index c2a507525a..9b4752f856 100644 --- a/crates/jolt-verifier/src/stages/stage6.rs +++ b/crates/jolt-verifier/src/stages/stage6.rs @@ -185,96 +185,96 @@ pub const STAGE6_TRANSCRIPT_ABSORB_BYTES: &[Stage6TranscriptAbsorbBytesPlan] = & ]; pub const STAGE6_OPENING_INPUTS: &[Stage6OpeningInputPlan] = &[ - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.UnexpandedPC", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.UnexpandedPC", oracle: "UnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.Imm", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.Imm", oracle: "Imm", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagAddOperands", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagAddOperands", oracle: "OpFlagAddOperands", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagSubtractOperands", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagSubtractOperands", oracle: "OpFlagSubtractOperands", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagMultiplyOperands", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagMultiplyOperands", oracle: "OpFlagMultiplyOperands", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagLoad", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagLoad", oracle: "OpFlagLoad", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagStore", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagStore", oracle: "OpFlagStore", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagJump", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagJump", oracle: "OpFlagJump", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagWriteLookupOutputToRD", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagWriteLookupOutputToRD", oracle: "OpFlagWriteLookupOutputToRD", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagVirtualInstruction", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagAssert", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagAssert", oracle: "OpFlagAssert", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagDoNotUpdateUnexpandedPC", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagDoNotUpdateUnexpandedPC", oracle: "OpFlagDoNotUpdateUnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagAdvice", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagAdvice", oracle: "OpFlagAdvice", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagIsCompressed", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagIsCompressed", oracle: "OpFlagIsCompressed", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagIsFirstInSequence", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagIsFirstInSequence", oracle: "OpFlagIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagIsLastInSequence", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagIsLastInSequence", oracle: "OpFlagIsLastInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage2.OpFlagJump", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.OpFlagJump", oracle: "OpFlagJump", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage2.InstructionFlagBranch", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.InstructionFlagBranch", oracle: "InstructionFlagBranch", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage2.OpFlagWriteLookupOutputToRD", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.OpFlagWriteLookupOutputToRD", oracle: "OpFlagWriteLookupOutputToRD", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage2.OpFlagVirtualInstruction", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage3.instruction_input.Imm", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.Imm", oracle: "Imm", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage3.spartan_shift.UnexpandedPC", source_stage: "stage3", source_claim: "stage3.spartan_shift.opening.UnexpandedPC", oracle: "UnexpandedPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage3.instruction_input.InstructionFlagLeftOperandIsRs1Value", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.InstructionFlagLeftOperandIsRs1Value", oracle: "InstructionFlagLeftOperandIsRs1Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage3.instruction_input.InstructionFlagLeftOperandIsPC", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.InstructionFlagLeftOperandIsPC", oracle: "InstructionFlagLeftOperandIsPC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage3.instruction_input.InstructionFlagRightOperandIsRs2Value", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.InstructionFlagRightOperandIsRs2Value", oracle: "InstructionFlagRightOperandIsRs2Value", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage3.instruction_input.InstructionFlagRightOperandIsImm", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.InstructionFlagRightOperandIsImm", oracle: "InstructionFlagRightOperandIsImm", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage3.spartan_shift.InstructionFlagIsNoop", source_stage: "stage3", source_claim: "stage3.spartan_shift.opening.InstructionFlagIsNoop", oracle: "InstructionFlagIsNoop", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage3.spartan_shift.OpFlagVirtualInstruction", source_stage: "stage3", source_claim: "stage3.spartan_shift.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage3.spartan_shift.OpFlagIsFirstInSequence", source_stage: "stage3", source_claim: "stage3.spartan_shift.opening.OpFlagIsFirstInSequence", oracle: "OpFlagIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage4.RdWa", source_stage: "stage4", source_claim: "stage4.registers_read_write.opening.RdWa", oracle: "RdWa", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage4.Rs1Ra", source_stage: "stage4", source_claim: "stage4.registers_read_write.opening.Rs1Ra", oracle: "Rs1Ra", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage4.Rs2Ra", source_stage: "stage4", source_claim: "stage4.registers_read_write.opening.Rs2Ra", oracle: "Rs2Ra", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.registers_val_evaluation.RdWa", source_stage: "stage5", source_claim: "stage5.registers_val_evaluation.opening.RdWa", oracle: "RdWa", domain: "jolt.stage4_registers_rw_domain", point_arity: 23, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.InstructionRafFlag", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRafFlag", oracle: "InstructionRafFlag", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_0", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_0", oracle: "LookupTableFlag_0", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_1", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_1", oracle: "LookupTableFlag_1", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_2", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_2", oracle: "LookupTableFlag_2", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_3", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_3", oracle: "LookupTableFlag_3", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_4", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_4", oracle: "LookupTableFlag_4", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_5", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_5", oracle: "LookupTableFlag_5", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_6", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_6", oracle: "LookupTableFlag_6", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_7", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_7", oracle: "LookupTableFlag_7", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_8", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_8", oracle: "LookupTableFlag_8", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_9", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_9", oracle: "LookupTableFlag_9", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_10", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_10", oracle: "LookupTableFlag_10", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_11", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_11", oracle: "LookupTableFlag_11", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_12", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_12", oracle: "LookupTableFlag_12", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_13", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_13", oracle: "LookupTableFlag_13", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_14", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_14", oracle: "LookupTableFlag_14", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_15", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_15", oracle: "LookupTableFlag_15", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_16", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_16", oracle: "LookupTableFlag_16", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_17", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_17", oracle: "LookupTableFlag_17", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_18", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_18", oracle: "LookupTableFlag_18", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_19", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_19", oracle: "LookupTableFlag_19", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_20", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_20", oracle: "LookupTableFlag_20", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_21", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_21", oracle: "LookupTableFlag_21", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_22", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_22", oracle: "LookupTableFlag_22", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_23", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_23", oracle: "LookupTableFlag_23", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_24", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_24", oracle: "LookupTableFlag_24", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_25", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_25", oracle: "LookupTableFlag_25", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_26", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_26", oracle: "LookupTableFlag_26", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_27", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_27", oracle: "LookupTableFlag_27", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_28", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_28", oracle: "LookupTableFlag_28", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_29", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_29", oracle: "LookupTableFlag_29", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_30", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_30", oracle: "LookupTableFlag_30", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_31", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_31", oracle: "LookupTableFlag_31", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_32", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_32", oracle: "LookupTableFlag_32", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_33", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_33", oracle: "LookupTableFlag_33", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_34", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_34", oracle: "LookupTableFlag_34", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_35", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_35", oracle: "LookupTableFlag_35", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_36", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_36", oracle: "LookupTableFlag_36", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_37", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_37", oracle: "LookupTableFlag_37", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_38", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_38", oracle: "LookupTableFlag_38", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_39", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_39", oracle: "LookupTableFlag_39", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.PC", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.PC", oracle: "PC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage3.spartan_shift.PC", source_stage: "stage3", source_claim: "stage3.spartan_shift.opening.PC", oracle: "PC", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.UnexpandedPC", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.UnexpandedPC", oracle: "UnexpandedPC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.Imm", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.Imm", oracle: "Imm", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagAddOperands", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagAddOperands", oracle: "OpFlagAddOperands", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagSubtractOperands", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagSubtractOperands", oracle: "OpFlagSubtractOperands", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagMultiplyOperands", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagMultiplyOperands", oracle: "OpFlagMultiplyOperands", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagLoad", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagLoad", oracle: "OpFlagLoad", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagStore", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagStore", oracle: "OpFlagStore", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagJump", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagJump", oracle: "OpFlagJump", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagWriteLookupOutputToRD", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagWriteLookupOutputToRD", oracle: "OpFlagWriteLookupOutputToRD", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagVirtualInstruction", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagAssert", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagAssert", oracle: "OpFlagAssert", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagDoNotUpdateUnexpandedPC", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagDoNotUpdateUnexpandedPC", oracle: "OpFlagDoNotUpdateUnexpandedPC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagAdvice", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagAdvice", oracle: "OpFlagAdvice", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagIsCompressed", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagIsCompressed", oracle: "OpFlagIsCompressed", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagIsFirstInSequence", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagIsFirstInSequence", oracle: "OpFlagIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.OpFlagIsLastInSequence", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.OpFlagIsLastInSequence", oracle: "OpFlagIsLastInSequence", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage2.OpFlagJump", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.OpFlagJump", oracle: "OpFlagJump", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage2.InstructionFlagBranch", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.InstructionFlagBranch", oracle: "InstructionFlagBranch", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage2.OpFlagWriteLookupOutputToRD", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.OpFlagWriteLookupOutputToRD", oracle: "OpFlagWriteLookupOutputToRD", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage2.OpFlagVirtualInstruction", source_stage: "stage2", source_claim: "stage2.product_virtual.remainder.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.instruction_input.Imm", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.Imm", oracle: "Imm", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.spartan_shift.UnexpandedPC", source_stage: "stage3", source_claim: "stage3.spartan_shift.opening.UnexpandedPC", oracle: "UnexpandedPC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.instruction_input.InstructionFlagLeftOperandIsRs1Value", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.InstructionFlagLeftOperandIsRs1Value", oracle: "InstructionFlagLeftOperandIsRs1Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.instruction_input.InstructionFlagLeftOperandIsPC", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.InstructionFlagLeftOperandIsPC", oracle: "InstructionFlagLeftOperandIsPC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.instruction_input.InstructionFlagRightOperandIsRs2Value", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.InstructionFlagRightOperandIsRs2Value", oracle: "InstructionFlagRightOperandIsRs2Value", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.instruction_input.InstructionFlagRightOperandIsImm", source_stage: "stage3", source_claim: "stage3.instruction_input.opening.InstructionFlagRightOperandIsImm", oracle: "InstructionFlagRightOperandIsImm", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.spartan_shift.InstructionFlagIsNoop", source_stage: "stage3", source_claim: "stage3.spartan_shift.opening.InstructionFlagIsNoop", oracle: "InstructionFlagIsNoop", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.spartan_shift.OpFlagVirtualInstruction", source_stage: "stage3", source_claim: "stage3.spartan_shift.opening.OpFlagVirtualInstruction", oracle: "OpFlagVirtualInstruction", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.spartan_shift.OpFlagIsFirstInSequence", source_stage: "stage3", source_claim: "stage3.spartan_shift.opening.OpFlagIsFirstInSequence", oracle: "OpFlagIsFirstInSequence", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage4.RdWa", source_stage: "stage4", source_claim: "stage4.registers_read_write.opening.RdWa", oracle: "RdWa", domain: "jolt.stage4_registers_rw_domain", point_arity: 25, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage4.Rs1Ra", source_stage: "stage4", source_claim: "stage4.registers_read_write.opening.Rs1Ra", oracle: "Rs1Ra", domain: "jolt.stage4_registers_rw_domain", point_arity: 25, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage4.Rs2Ra", source_stage: "stage4", source_claim: "stage4.registers_read_write.opening.Rs2Ra", oracle: "Rs2Ra", domain: "jolt.stage4_registers_rw_domain", point_arity: 25, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.registers_val_evaluation.RdWa", source_stage: "stage5", source_claim: "stage5.registers_val_evaluation.opening.RdWa", oracle: "RdWa", domain: "jolt.stage4_registers_rw_domain", point_arity: 25, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.InstructionRafFlag", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRafFlag", oracle: "InstructionRafFlag", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_0", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_0", oracle: "LookupTableFlag_0", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_1", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_1", oracle: "LookupTableFlag_1", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_2", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_2", oracle: "LookupTableFlag_2", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_3", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_3", oracle: "LookupTableFlag_3", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_4", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_4", oracle: "LookupTableFlag_4", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_5", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_5", oracle: "LookupTableFlag_5", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_6", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_6", oracle: "LookupTableFlag_6", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_7", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_7", oracle: "LookupTableFlag_7", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_8", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_8", oracle: "LookupTableFlag_8", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_9", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_9", oracle: "LookupTableFlag_9", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_10", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_10", oracle: "LookupTableFlag_10", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_11", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_11", oracle: "LookupTableFlag_11", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_12", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_12", oracle: "LookupTableFlag_12", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_13", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_13", oracle: "LookupTableFlag_13", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_14", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_14", oracle: "LookupTableFlag_14", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_15", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_15", oracle: "LookupTableFlag_15", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_16", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_16", oracle: "LookupTableFlag_16", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_17", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_17", oracle: "LookupTableFlag_17", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_18", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_18", oracle: "LookupTableFlag_18", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_19", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_19", oracle: "LookupTableFlag_19", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_20", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_20", oracle: "LookupTableFlag_20", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_21", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_21", oracle: "LookupTableFlag_21", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_22", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_22", oracle: "LookupTableFlag_22", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_23", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_23", oracle: "LookupTableFlag_23", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_24", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_24", oracle: "LookupTableFlag_24", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_25", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_25", oracle: "LookupTableFlag_25", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_26", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_26", oracle: "LookupTableFlag_26", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_27", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_27", oracle: "LookupTableFlag_27", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_28", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_28", oracle: "LookupTableFlag_28", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_29", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_29", oracle: "LookupTableFlag_29", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_30", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_30", oracle: "LookupTableFlag_30", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_31", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_31", oracle: "LookupTableFlag_31", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_32", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_32", oracle: "LookupTableFlag_32", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_33", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_33", oracle: "LookupTableFlag_33", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_34", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_34", oracle: "LookupTableFlag_34", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_35", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_35", oracle: "LookupTableFlag_35", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_36", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_36", oracle: "LookupTableFlag_36", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_37", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_37", oracle: "LookupTableFlag_37", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_38", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_38", oracle: "LookupTableFlag_38", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.LookupTableFlag_39", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.LookupTableFlag_39", oracle: "LookupTableFlag_39", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.PC", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.PC", oracle: "PC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage3.spartan_shift.PC", source_stage: "stage3", source_claim: "stage3.spartan_shift.opening.PC", oracle: "PC", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, Stage6OpeningInputPlan { symbol: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", source_stage: "stage5", source_claim: "stage5.ram_ra_claim_reduction.opening.RamRa", oracle: "RamRa", domain: "jolt.stage2_ram_rw_domain", point_arity: 32, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_1", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_2", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_3", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_4", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_5", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_6", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_7", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 32, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage1.LookupOutput", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage2.ram_read_write.RamInc", source_stage: "stage2", source_claim: "stage2.ram_read_write.opening.RamInc", oracle: "RamInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage4.ram_val_check.RamInc", source_stage: "stage4", source_claim: "stage4.ram_val_check.opening.RamInc", oracle: "RamInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage4.registers_read_write.RdInc", source_stage: "stage4", source_claim: "stage4.registers_read_write.opening.RdInc", oracle: "RdInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed" }, - Stage6OpeningInputPlan { symbol: "stage6.input.stage5.registers_val_evaluation.RdInc", source_stage: "stage5", source_claim: "stage5.registers_val_evaluation.opening.RdInc", oracle: "RdInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_1", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_2", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_3", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_4", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_5", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_6", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.instruction_read_raf.InstructionRa_7", source_stage: "stage5", source_claim: "stage5.instruction_read_raf.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.stage5_instruction_ra_chunk_domain", point_arity: 34, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage1.LookupOutput", source_stage: "stage1", source_claim: "stage1.outer_remaining.opening.LookupOutput", oracle: "LookupOutput", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage2.ram_read_write.RamInc", source_stage: "stage2", source_claim: "stage2.ram_read_write.opening.RamInc", oracle: "RamInc", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "committed" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage4.ram_val_check.RamInc", source_stage: "stage4", source_claim: "stage4.ram_val_check.opening.RamInc", oracle: "RamInc", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "committed" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage4.registers_read_write.RdInc", source_stage: "stage4", source_claim: "stage4.registers_read_write.opening.RdInc", oracle: "RdInc", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "committed" }, + Stage6OpeningInputPlan { symbol: "stage6.input.stage5.registers_val_evaluation.RdInc", source_stage: "stage5", source_claim: "stage5.registers_val_evaluation.opening.RdInc", oracle: "RdInc", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "committed" }, ]; pub const STAGE6_FIELD_CONSTANTS: &[Stage6FieldConstantPlan] = &[ @@ -293,94 +293,94 @@ pub const STAGE6_FIELD_EXPRS: &[Stage6FieldExprPlan] = &[ stage6_field_expr!("stage6.booleanity.gamma_sq_8", "field.pow:16", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_9", "field.pow:18", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_10", "field.pow:20", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_11", "field.pow:22", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_12", "field.pow:24", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_13", "field.pow:26", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_14", "field.pow:28", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_15", "field.pow:30", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_16", "field.pow:32", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_17", "field.pow:34", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_18", "field.pow:36", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_19", "field.pow:38", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_20", "field.pow:40", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_21", "field.pow:42", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_22", "field.pow:44", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_23", "field.pow:46", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_24", "field.pow:48", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_25", "field.pow:50", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_26", "field.pow:52", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_27", "field.pow:54", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_28", "field.pow:56", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_29", "field.pow:58", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_30", "field.pow:60", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_31", "field.pow:62", "stage6.booleanity.gamma"), - stage6_field_expr!("stage6.booleanity.gamma_sq_32", "field.pow:64", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_33", "field.pow:66", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_34", "field.pow:68", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_35", "field.pow:70", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_36", "field.pow:72", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_37", "field.pow:74", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_38", "field.pow:76", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_0", "field.pow:0", "stage6.booleanity.gamma"), - stage6_field_expr!("stage6.booleanity.gamma_pow_1", "field.pow:1", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_2", "field.pow:2", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_3", "field.pow:3", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_4", "field.pow:4", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_5", "field.pow:5", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_6", "field.pow:6", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_7", "field.pow:7", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_8", "field.pow:8", "stage6.booleanity.gamma"), - stage6_field_expr!("stage6.booleanity.gamma_pow_9", "field.pow:9", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_10", "field.pow:10", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_11", "field.pow:11", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_12", "field.pow:12", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_13", "field.pow:13", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_14", "field.pow:14", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_15", "field.pow:15", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_16", "field.pow:16", "stage6.booleanity.gamma"), - stage6_field_expr!("stage6.booleanity.gamma_pow_17", "field.pow:17", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_18", "field.pow:18", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_19", "field.pow:19", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_20", "field.pow:20", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_21", "field.pow:21", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_22", "field.pow:22", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_23", "field.pow:23", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_24", "field.pow:24", "stage6.booleanity.gamma"), - stage6_field_expr!("stage6.booleanity.gamma_pow_25", "field.pow:25", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_26", "field.pow:26", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_27", "field.pow:27", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_28", "field.pow:28", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_29", "field.pow:29", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_30", "field.pow:30", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_31", "field.pow:31", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_32", "field.pow:32", "stage6.booleanity.gamma"), - stage6_field_expr!("stage6.booleanity.gamma_pow_33", "field.pow:33", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_34", "field.pow:34", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_35", "field.pow:35", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_36", "field.pow:36", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_37", "field.pow:37", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_38", "field.pow:38", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term1.stage_gamma_pow", "field.pow:1", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term1.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term1.stage_gamma_pow|stage6.input.stage1.Imm"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term2.stage_gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term2.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term2.stage_gamma_pow|stage6.input.stage1.OpFlagAddOperands"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term3.stage_gamma_pow", "field.pow:3", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term3.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term3.stage_gamma_pow|stage6.input.stage1.OpFlagSubtractOperands"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term4.stage_gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term4.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term4.stage_gamma_pow|stage6.input.stage1.OpFlagMultiplyOperands"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term5.stage_gamma_pow", "field.pow:5", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term5.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term5.stage_gamma_pow|stage6.input.stage1.OpFlagLoad"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term6.stage_gamma_pow", "field.pow:6", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term6.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term6.stage_gamma_pow|stage6.input.stage1.OpFlagStore"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term7.stage_gamma_pow", "field.pow:7", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term7.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term7.stage_gamma_pow|stage6.input.stage1.OpFlagJump"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term8.stage_gamma_pow", "field.pow:8", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term8.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term8.stage_gamma_pow|stage6.input.stage1.OpFlagWriteLookupOutputToRD"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term9.stage_gamma_pow", "field.pow:9", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term9.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term9.stage_gamma_pow|stage6.input.stage1.OpFlagVirtualInstruction"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term10.stage_gamma_pow", "field.pow:10", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term10.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term10.stage_gamma_pow|stage6.input.stage1.OpFlagAssert"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term11.stage_gamma_pow", "field.pow:11", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term11.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term11.stage_gamma_pow|stage6.input.stage1.OpFlagDoNotUpdateUnexpandedPC"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term12.stage_gamma_pow", "field.pow:12", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term12.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term12.stage_gamma_pow|stage6.input.stage1.OpFlagAdvice"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term13.stage_gamma_pow", "field.pow:13", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term13.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term13.stage_gamma_pow|stage6.input.stage1.OpFlagIsCompressed"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term14.stage_gamma_pow", "field.pow:14", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term14.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term14.stage_gamma_pow|stage6.input.stage1.OpFlagIsFirstInSequence"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term15.stage_gamma_pow", "field.pow:15", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term15.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term15.stage_gamma_pow|stage6.input.stage1.OpFlagIsLastInSequence"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term16.gamma_pow", "field.pow:1", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term16.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term16.gamma_pow|stage6.input.stage2.OpFlagJump"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term17.stage_gamma_pow", "field.pow:1", "stage6.bytecode_read_raf.stage2_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term17.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term17.stage_gamma_pow|stage6.input.stage2.InstructionFlagBranch"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term17.gamma_pow", "field.pow:1", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term17.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term17.gamma_pow|stage6.bytecode_read_raf.claim.term17.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term18.stage_gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.stage2_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term18.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term18.stage_gamma_pow|stage6.input.stage2.OpFlagWriteLookupOutputToRD"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term18.gamma_pow", "field.pow:1", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term18.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term18.gamma_pow|stage6.bytecode_read_raf.claim.term18.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term19.stage_gamma_pow", "field.pow:3", "stage6.bytecode_read_raf.stage2_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term19.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term19.stage_gamma_pow|stage6.input.stage2.OpFlagVirtualInstruction"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term19.gamma_pow", "field.pow:1", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term19.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term19.gamma_pow|stage6.bytecode_read_raf.claim.term19.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term20.gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term20.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term20.gamma_pow|stage6.input.stage3.instruction_input.Imm"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term21.stage_gamma_pow", "field.pow:1", "stage6.bytecode_read_raf.stage3_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term21.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term21.stage_gamma_pow|stage6.input.stage3.spartan_shift.UnexpandedPC"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term21.gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term21.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term21.gamma_pow|stage6.bytecode_read_raf.claim.term21.stage_gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term22.stage_gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.stage3_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term22.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term22.stage_gamma_pow|stage6.input.stage3.instruction_input.InstructionFlagLeftOperandIsRs1Value"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term22.gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term22.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term22.gamma_pow|stage6.bytecode_read_raf.claim.term22.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term23.stage_gamma_pow", "field.pow:3", "stage6.bytecode_read_raf.stage3_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term23.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term23.stage_gamma_pow|stage6.input.stage3.instruction_input.InstructionFlagLeftOperandIsPC"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term23.gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term23.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term23.gamma_pow|stage6.bytecode_read_raf.claim.term23.stage_gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term24.stage_gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.stage3_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term24.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term24.stage_gamma_pow|stage6.input.stage3.instruction_input.InstructionFlagRightOperandIsRs2Value"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term24.gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term24.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term24.gamma_pow|stage6.bytecode_read_raf.claim.term24.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term25.stage_gamma_pow", "field.pow:5", "stage6.bytecode_read_raf.stage3_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term25.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term25.stage_gamma_pow|stage6.input.stage3.instruction_input.InstructionFlagRightOperandIsImm"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term25.gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term25.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term25.gamma_pow|stage6.bytecode_read_raf.claim.term25.stage_gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term26.stage_gamma_pow", "field.pow:6", "stage6.bytecode_read_raf.stage3_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term26.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term26.stage_gamma_pow|stage6.input.stage3.spartan_shift.InstructionFlagIsNoop"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term26.gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term26.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term26.gamma_pow|stage6.bytecode_read_raf.claim.term26.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term27.stage_gamma_pow", "field.pow:7", "stage6.bytecode_read_raf.stage3_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term27.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term27.stage_gamma_pow|stage6.input.stage3.spartan_shift.OpFlagVirtualInstruction"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term27.gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term27.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term27.gamma_pow|stage6.bytecode_read_raf.claim.term27.stage_gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term28.stage_gamma_pow", "field.pow:8", "stage6.bytecode_read_raf.stage3_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term28.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term28.stage_gamma_pow|stage6.input.stage3.spartan_shift.OpFlagIsFirstInSequence"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term28.gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term28.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term28.gamma_pow|stage6.bytecode_read_raf.claim.term28.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term29.gamma_pow", "field.pow:3", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term29.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term29.gamma_pow|stage6.input.stage4.RdWa"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term30.stage_gamma_pow", "field.pow:1", "stage6.bytecode_read_raf.stage4_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term30.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term30.stage_gamma_pow|stage6.input.stage4.Rs1Ra"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term30.gamma_pow", "field.pow:3", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term30.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term30.gamma_pow|stage6.bytecode_read_raf.claim.term30.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term31.stage_gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.stage4_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term31.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term31.stage_gamma_pow|stage6.input.stage4.Rs2Ra"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term31.gamma_pow", "field.pow:3", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term31.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term31.gamma_pow|stage6.bytecode_read_raf.claim.term31.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term32.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term32.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term32.gamma_pow|stage6.input.stage5.registers_val_evaluation.RdWa"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term33.stage_gamma_pow", "field.pow:1", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term33.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term33.stage_gamma_pow|stage6.input.stage5.InstructionRafFlag"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term33.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term33.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term33.gamma_pow|stage6.bytecode_read_raf.claim.term33.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term34.stage_gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term34.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term34.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_0"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term34.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term34.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term34.gamma_pow|stage6.bytecode_read_raf.claim.term34.stage_gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term35.stage_gamma_pow", "field.pow:3", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term35.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term35.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_1"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term35.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term35.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term35.gamma_pow|stage6.bytecode_read_raf.claim.term35.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term36.stage_gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term36.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term36.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_2"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term36.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term36.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term36.gamma_pow|stage6.bytecode_read_raf.claim.term36.stage_gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term37.stage_gamma_pow", "field.pow:5", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term37.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term37.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_3"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term37.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term37.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term37.gamma_pow|stage6.bytecode_read_raf.claim.term37.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term38.stage_gamma_pow", "field.pow:6", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term38.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term38.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_4"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term38.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term38.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term38.gamma_pow|stage6.bytecode_read_raf.claim.term38.stage_gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term39.stage_gamma_pow", "field.pow:7", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term39.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term39.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_5"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term39.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term39.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term39.gamma_pow|stage6.bytecode_read_raf.claim.term39.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term40.stage_gamma_pow", "field.pow:8", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term40.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term40.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_6"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term40.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term40.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term40.gamma_pow|stage6.bytecode_read_raf.claim.term40.stage_gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term41.stage_gamma_pow", "field.pow:9", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term41.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term41.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_7"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term41.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term41.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term41.gamma_pow|stage6.bytecode_read_raf.claim.term41.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term42.stage_gamma_pow", "field.pow:10", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term42.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term42.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_8"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term42.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term42.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term42.gamma_pow|stage6.bytecode_read_raf.claim.term42.stage_gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term43.stage_gamma_pow", "field.pow:11", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term43.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term43.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_9"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term43.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term43.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term43.gamma_pow|stage6.bytecode_read_raf.claim.term43.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term44.stage_gamma_pow", "field.pow:12", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term44.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term44.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_10"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term44.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term44.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term44.gamma_pow|stage6.bytecode_read_raf.claim.term44.stage_gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term45.stage_gamma_pow", "field.pow:13", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term45.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term45.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_11"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term45.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term45.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term45.gamma_pow|stage6.bytecode_read_raf.claim.term45.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term46.stage_gamma_pow", "field.pow:14", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term46.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term46.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_12"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term46.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term46.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term46.gamma_pow|stage6.bytecode_read_raf.claim.term46.stage_gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term47.stage_gamma_pow", "field.pow:15", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term47.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term47.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_13"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term47.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term47.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term47.gamma_pow|stage6.bytecode_read_raf.claim.term47.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term48.stage_gamma_pow", "field.pow:16", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term48.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term48.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_14"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term48.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term48.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term48.gamma_pow|stage6.bytecode_read_raf.claim.term48.stage_gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term49.stage_gamma_pow", "field.pow:17", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term49.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term49.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_15"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term49.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term49.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term49.gamma_pow|stage6.bytecode_read_raf.claim.term49.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term50.stage_gamma_pow", "field.pow:18", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term50.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term50.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_16"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term50.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term50.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term50.gamma_pow|stage6.bytecode_read_raf.claim.term50.stage_gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term51.stage_gamma_pow", "field.pow:19", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term51.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term51.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_17"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term51.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term51.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term51.gamma_pow|stage6.bytecode_read_raf.claim.term51.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term52.stage_gamma_pow", "field.pow:20", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term52.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term52.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_18"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term52.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term52.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term52.gamma_pow|stage6.bytecode_read_raf.claim.term52.stage_gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term53.stage_gamma_pow", "field.pow:21", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term53.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term53.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_19"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term53.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term53.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term53.gamma_pow|stage6.bytecode_read_raf.claim.term53.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term54.stage_gamma_pow", "field.pow:22", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term54.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term54.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_20"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term54.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term54.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term54.gamma_pow|stage6.bytecode_read_raf.claim.term54.stage_gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term55.stage_gamma_pow", "field.pow:23", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term55.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term55.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_21"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term55.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term55.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term55.gamma_pow|stage6.bytecode_read_raf.claim.term55.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term56.stage_gamma_pow", "field.pow:24", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term56.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term56.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_22"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term56.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term56.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term56.gamma_pow|stage6.bytecode_read_raf.claim.term56.stage_gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term57.stage_gamma_pow", "field.pow:25", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term57.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term57.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_23"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term57.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term57.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term57.gamma_pow|stage6.bytecode_read_raf.claim.term57.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term58.stage_gamma_pow", "field.pow:26", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term58.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term58.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_24"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term58.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term58.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term58.gamma_pow|stage6.bytecode_read_raf.claim.term58.stage_gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term59.stage_gamma_pow", "field.pow:27", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term59.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term59.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_25"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term59.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term59.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term59.gamma_pow|stage6.bytecode_read_raf.claim.term59.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term60.stage_gamma_pow", "field.pow:28", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term60.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term60.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_26"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term60.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term60.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term60.gamma_pow|stage6.bytecode_read_raf.claim.term60.stage_gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term61.stage_gamma_pow", "field.pow:29", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term61.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term61.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_27"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term61.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term61.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term61.gamma_pow|stage6.bytecode_read_raf.claim.term61.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term62.stage_gamma_pow", "field.pow:30", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term62.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term62.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_28"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term62.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term62.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term62.gamma_pow|stage6.bytecode_read_raf.claim.term62.stage_gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term63.stage_gamma_pow", "field.pow:31", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term63.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term63.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_29"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term63.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term63.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term63.gamma_pow|stage6.bytecode_read_raf.claim.term63.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term64.stage_gamma_pow", "field.pow:32", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term64.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term64.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_30"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term64.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term64.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term64.gamma_pow|stage6.bytecode_read_raf.claim.term64.stage_gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term65.stage_gamma_pow", "field.pow:33", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term65.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term65.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_31"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term65.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term65.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term65.gamma_pow|stage6.bytecode_read_raf.claim.term65.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term66.stage_gamma_pow", "field.pow:34", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term66.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term66.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_32"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term66.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term66.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term66.gamma_pow|stage6.bytecode_read_raf.claim.term66.stage_gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term67.stage_gamma_pow", "field.pow:35", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term67.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term67.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_33"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term67.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term67.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term67.gamma_pow|stage6.bytecode_read_raf.claim.term67.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term68.stage_gamma_pow", "field.pow:36", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term68.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term68.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_34"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term68.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term68.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term68.gamma_pow|stage6.bytecode_read_raf.claim.term68.stage_gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term69.stage_gamma_pow", "field.pow:37", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term69.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term69.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_35"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term69.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term69.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term69.gamma_pow|stage6.bytecode_read_raf.claim.term69.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term70.stage_gamma_pow", "field.pow:38", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term70.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term70.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_36"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term70.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term70.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term70.gamma_pow|stage6.bytecode_read_raf.claim.term70.stage_gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term71.stage_gamma_pow", "field.pow:39", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term71.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term71.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_37"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term71.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term71.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term71.gamma_pow|stage6.bytecode_read_raf.claim.term71.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term72.stage_gamma_pow", "field.pow:40", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term72.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term72.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_38"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term72.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term72.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term72.gamma_pow|stage6.bytecode_read_raf.claim.term72.stage_gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.term73.stage_gamma_pow", "field.pow:41", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term73.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term73.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_39"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term73.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term73.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term73.gamma_pow|stage6.bytecode_read_raf.claim.term73.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term74.gamma_pow", "field.pow:5", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term74.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term74.gamma_pow|stage6.input.stage1.PC"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term75.gamma_pow", "field.pow:6", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term75.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term75.gamma_pow|stage6.input.stage3.spartan_shift.PC"), - stage6_field_expr!("stage6.bytecode_read_raf.claim.entry_constant", "field.pow:7", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial0", "field.add", "stage6.input.stage1.UnexpandedPC|stage6.bytecode_read_raf.claim.term1.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial1", "field.add", "stage6.bytecode_read_raf.claim_expr.partial0|stage6.bytecode_read_raf.claim.term2.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial2", "field.add", "stage6.bytecode_read_raf.claim_expr.partial1|stage6.bytecode_read_raf.claim.term3.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial3", "field.add", "stage6.bytecode_read_raf.claim_expr.partial2|stage6.bytecode_read_raf.claim.term4.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial4", "field.add", "stage6.bytecode_read_raf.claim_expr.partial3|stage6.bytecode_read_raf.claim.term5.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial5", "field.add", "stage6.bytecode_read_raf.claim_expr.partial4|stage6.bytecode_read_raf.claim.term6.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial6", "field.add", "stage6.bytecode_read_raf.claim_expr.partial5|stage6.bytecode_read_raf.claim.term7.stage_gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial7", "field.add", "stage6.bytecode_read_raf.claim_expr.partial6|stage6.bytecode_read_raf.claim.term8.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial8", "field.add", "stage6.bytecode_read_raf.claim_expr.partial7|stage6.bytecode_read_raf.claim.term9.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial9", "field.add", "stage6.bytecode_read_raf.claim_expr.partial8|stage6.bytecode_read_raf.claim.term10.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial10", "field.add", "stage6.bytecode_read_raf.claim_expr.partial9|stage6.bytecode_read_raf.claim.term11.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial11", "field.add", "stage6.bytecode_read_raf.claim_expr.partial10|stage6.bytecode_read_raf.claim.term12.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial12", "field.add", "stage6.bytecode_read_raf.claim_expr.partial11|stage6.bytecode_read_raf.claim.term13.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial13", "field.add", "stage6.bytecode_read_raf.claim_expr.partial12|stage6.bytecode_read_raf.claim.term14.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial14", "field.add", "stage6.bytecode_read_raf.claim_expr.partial13|stage6.bytecode_read_raf.claim.term15.stage_gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial15", "field.add", "stage6.bytecode_read_raf.claim_expr.partial14|stage6.bytecode_read_raf.claim.term16.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial16", "field.add", "stage6.bytecode_read_raf.claim_expr.partial15|stage6.bytecode_read_raf.claim.term17.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial17", "field.add", "stage6.bytecode_read_raf.claim_expr.partial16|stage6.bytecode_read_raf.claim.term18.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial18", "field.add", "stage6.bytecode_read_raf.claim_expr.partial17|stage6.bytecode_read_raf.claim.term19.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial19", "field.add", "stage6.bytecode_read_raf.claim_expr.partial18|stage6.bytecode_read_raf.claim.term20.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial20", "field.add", "stage6.bytecode_read_raf.claim_expr.partial19|stage6.bytecode_read_raf.claim.term21.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial21", "field.add", "stage6.bytecode_read_raf.claim_expr.partial20|stage6.bytecode_read_raf.claim.term22.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial22", "field.add", "stage6.bytecode_read_raf.claim_expr.partial21|stage6.bytecode_read_raf.claim.term23.gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial23", "field.add", "stage6.bytecode_read_raf.claim_expr.partial22|stage6.bytecode_read_raf.claim.term24.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial24", "field.add", "stage6.bytecode_read_raf.claim_expr.partial23|stage6.bytecode_read_raf.claim.term25.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial25", "field.add", "stage6.bytecode_read_raf.claim_expr.partial24|stage6.bytecode_read_raf.claim.term26.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial26", "field.add", "stage6.bytecode_read_raf.claim_expr.partial25|stage6.bytecode_read_raf.claim.term27.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial27", "field.add", "stage6.bytecode_read_raf.claim_expr.partial26|stage6.bytecode_read_raf.claim.term28.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial28", "field.add", "stage6.bytecode_read_raf.claim_expr.partial27|stage6.bytecode_read_raf.claim.term29.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial29", "field.add", "stage6.bytecode_read_raf.claim_expr.partial28|stage6.bytecode_read_raf.claim.term30.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial30", "field.add", "stage6.bytecode_read_raf.claim_expr.partial29|stage6.bytecode_read_raf.claim.term31.gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial31", "field.add", "stage6.bytecode_read_raf.claim_expr.partial30|stage6.bytecode_read_raf.claim.term32.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial32", "field.add", "stage6.bytecode_read_raf.claim_expr.partial31|stage6.bytecode_read_raf.claim.term33.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial33", "field.add", "stage6.bytecode_read_raf.claim_expr.partial32|stage6.bytecode_read_raf.claim.term34.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial34", "field.add", "stage6.bytecode_read_raf.claim_expr.partial33|stage6.bytecode_read_raf.claim.term35.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial35", "field.add", "stage6.bytecode_read_raf.claim_expr.partial34|stage6.bytecode_read_raf.claim.term36.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial36", "field.add", "stage6.bytecode_read_raf.claim_expr.partial35|stage6.bytecode_read_raf.claim.term37.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial37", "field.add", "stage6.bytecode_read_raf.claim_expr.partial36|stage6.bytecode_read_raf.claim.term38.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial38", "field.add", "stage6.bytecode_read_raf.claim_expr.partial37|stage6.bytecode_read_raf.claim.term39.gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial39", "field.add", "stage6.bytecode_read_raf.claim_expr.partial38|stage6.bytecode_read_raf.claim.term40.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial40", "field.add", "stage6.bytecode_read_raf.claim_expr.partial39|stage6.bytecode_read_raf.claim.term41.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial41", "field.add", "stage6.bytecode_read_raf.claim_expr.partial40|stage6.bytecode_read_raf.claim.term42.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial42", "field.add", "stage6.bytecode_read_raf.claim_expr.partial41|stage6.bytecode_read_raf.claim.term43.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial43", "field.add", "stage6.bytecode_read_raf.claim_expr.partial42|stage6.bytecode_read_raf.claim.term44.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial44", "field.add", "stage6.bytecode_read_raf.claim_expr.partial43|stage6.bytecode_read_raf.claim.term45.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial45", "field.add", "stage6.bytecode_read_raf.claim_expr.partial44|stage6.bytecode_read_raf.claim.term46.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial46", "field.add", "stage6.bytecode_read_raf.claim_expr.partial45|stage6.bytecode_read_raf.claim.term47.gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial47", "field.add", "stage6.bytecode_read_raf.claim_expr.partial46|stage6.bytecode_read_raf.claim.term48.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial48", "field.add", "stage6.bytecode_read_raf.claim_expr.partial47|stage6.bytecode_read_raf.claim.term49.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial49", "field.add", "stage6.bytecode_read_raf.claim_expr.partial48|stage6.bytecode_read_raf.claim.term50.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial50", "field.add", "stage6.bytecode_read_raf.claim_expr.partial49|stage6.bytecode_read_raf.claim.term51.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial51", "field.add", "stage6.bytecode_read_raf.claim_expr.partial50|stage6.bytecode_read_raf.claim.term52.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial52", "field.add", "stage6.bytecode_read_raf.claim_expr.partial51|stage6.bytecode_read_raf.claim.term53.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial53", "field.add", "stage6.bytecode_read_raf.claim_expr.partial52|stage6.bytecode_read_raf.claim.term54.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial54", "field.add", "stage6.bytecode_read_raf.claim_expr.partial53|stage6.bytecode_read_raf.claim.term55.gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial55", "field.add", "stage6.bytecode_read_raf.claim_expr.partial54|stage6.bytecode_read_raf.claim.term56.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial56", "field.add", "stage6.bytecode_read_raf.claim_expr.partial55|stage6.bytecode_read_raf.claim.term57.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial57", "field.add", "stage6.bytecode_read_raf.claim_expr.partial56|stage6.bytecode_read_raf.claim.term58.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial58", "field.add", "stage6.bytecode_read_raf.claim_expr.partial57|stage6.bytecode_read_raf.claim.term59.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial59", "field.add", "stage6.bytecode_read_raf.claim_expr.partial58|stage6.bytecode_read_raf.claim.term60.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial60", "field.add", "stage6.bytecode_read_raf.claim_expr.partial59|stage6.bytecode_read_raf.claim.term61.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial61", "field.add", "stage6.bytecode_read_raf.claim_expr.partial60|stage6.bytecode_read_raf.claim.term62.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial62", "field.add", "stage6.bytecode_read_raf.claim_expr.partial61|stage6.bytecode_read_raf.claim.term63.gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial63", "field.add", "stage6.bytecode_read_raf.claim_expr.partial62|stage6.bytecode_read_raf.claim.term64.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial64", "field.add", "stage6.bytecode_read_raf.claim_expr.partial63|stage6.bytecode_read_raf.claim.term65.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial65", "field.add", "stage6.bytecode_read_raf.claim_expr.partial64|stage6.bytecode_read_raf.claim.term66.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial66", "field.add", "stage6.bytecode_read_raf.claim_expr.partial65|stage6.bytecode_read_raf.claim.term67.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial67", "field.add", "stage6.bytecode_read_raf.claim_expr.partial66|stage6.bytecode_read_raf.claim.term68.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial68", "field.add", "stage6.bytecode_read_raf.claim_expr.partial67|stage6.bytecode_read_raf.claim.term69.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial69", "field.add", "stage6.bytecode_read_raf.claim_expr.partial68|stage6.bytecode_read_raf.claim.term70.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial70", "field.add", "stage6.bytecode_read_raf.claim_expr.partial69|stage6.bytecode_read_raf.claim.term71.gamma_term"), - stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial71", "field.add", "stage6.bytecode_read_raf.claim_expr.partial70|stage6.bytecode_read_raf.claim.term72.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial72", "field.add", "stage6.bytecode_read_raf.claim_expr.partial71|stage6.bytecode_read_raf.claim.term73.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial73", "field.add", "stage6.bytecode_read_raf.claim_expr.partial72|stage6.bytecode_read_raf.claim.term74.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial74", "field.add", "stage6.bytecode_read_raf.claim_expr.partial73|stage6.bytecode_read_raf.claim.term75.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial75", "field.add", "stage6.bytecode_read_raf.claim_expr.partial74|stage6.bytecode_read_raf.claim.entry_constant"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term1.gamma_pow", "field.pow:1", "stage6.instruction_ra_virtual.gamma"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term1.gamma_term", "field.mul", "stage6.instruction_ra_virtual.claim.term1.gamma_pow|stage6.input.stage5.instruction_read_raf.InstructionRa_1"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term2.gamma_pow", "field.pow:2", "stage6.instruction_ra_virtual.gamma"), - stage6_field_expr!("stage6.instruction_ra_virtual.claim.term2.gamma_term", "field.mul", "stage6.instruction_ra_virtual.claim.term2.gamma_pow|stage6.input.stage5.instruction_read_raf.InstructionRa_2"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term3.gamma_pow", "field.pow:3", "stage6.instruction_ra_virtual.gamma"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term3.gamma_term", "field.mul", "stage6.instruction_ra_virtual.claim.term3.gamma_pow|stage6.input.stage5.instruction_read_raf.InstructionRa_3"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term4.gamma_pow", "field.pow:4", "stage6.instruction_ra_virtual.gamma"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term4.gamma_term", "field.mul", "stage6.instruction_ra_virtual.claim.term4.gamma_pow|stage6.input.stage5.instruction_read_raf.InstructionRa_4"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term5.gamma_pow", "field.pow:5", "stage6.instruction_ra_virtual.gamma"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term5.gamma_term", "field.mul", "stage6.instruction_ra_virtual.claim.term5.gamma_pow|stage6.input.stage5.instruction_read_raf.InstructionRa_5"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term6.gamma_pow", "field.pow:6", "stage6.instruction_ra_virtual.gamma"), - stage6_field_expr!("stage6.instruction_ra_virtual.claim.term6.gamma_term", "field.mul", "stage6.instruction_ra_virtual.claim.term6.gamma_pow|stage6.input.stage5.instruction_read_raf.InstructionRa_6"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term7.gamma_pow", "field.pow:7", "stage6.instruction_ra_virtual.gamma"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term7.gamma_term", "field.mul", "stage6.instruction_ra_virtual.claim.term7.gamma_pow|stage6.input.stage5.instruction_read_raf.InstructionRa_7"), stage6_field_expr!("stage6.instruction_ra_virtual.claim_expr.partial0", "field.add", "stage6.input.stage5.instruction_read_raf.InstructionRa_0|stage6.instruction_ra_virtual.claim.term1.gamma_term"), stage6_field_expr!("stage6.instruction_ra_virtual.claim_expr.partial1", "field.add", "stage6.instruction_ra_virtual.claim_expr.partial0|stage6.instruction_ra_virtual.claim.term2.gamma_term"), stage6_field_expr!("stage6.instruction_ra_virtual.claim_expr.partial2", "field.add", "stage6.instruction_ra_virtual.claim_expr.partial1|stage6.instruction_ra_virtual.claim.term3.gamma_term"), stage6_field_expr!("stage6.instruction_ra_virtual.claim_expr.partial3", "field.add", "stage6.instruction_ra_virtual.claim_expr.partial2|stage6.instruction_ra_virtual.claim.term4.gamma_term"), stage6_field_expr!("stage6.instruction_ra_virtual.claim_expr.partial4", "field.add", "stage6.instruction_ra_virtual.claim_expr.partial3|stage6.instruction_ra_virtual.claim.term5.gamma_term"), - stage6_field_expr!("stage6.instruction_ra_virtual.claim_expr.partial5", "field.add", "stage6.instruction_ra_virtual.claim_expr.partial4|stage6.instruction_ra_virtual.claim.term6.gamma_term"), stage6_field_expr!("stage6.instruction_ra_virtual.claim_expr.partial6", "field.add", "stage6.instruction_ra_virtual.claim_expr.partial5|stage6.instruction_ra_virtual.claim.term7.gamma_term"), stage6_field_expr!("stage6.inc_claim_reduction.claim.ram_inc_stage4.gamma_pow", "field.pow:1", "stage6.inc_claim_reduction.gamma"), stage6_field_expr!("stage6.inc_claim_reduction.claim.ram_inc_stage4.gamma_term", "field.mul", "stage6.inc_claim_reduction.claim.ram_inc_stage4.gamma_pow|stage6.input.stage4.ram_val_check.RamInc"), stage6_field_expr!("stage6.inc_claim_reduction.claim.rd_inc_stage4.gamma_pow", "field.pow:2", "stage6.inc_claim_reduction.gamma"), stage6_field_expr!("stage6.inc_claim_reduction.claim.rd_inc_stage4.gamma_term", "field.mul", "stage6.inc_claim_reduction.claim.rd_inc_stage4.gamma_pow|stage6.input.stage4.registers_read_write.RdInc"), stage6_field_expr!("stage6.inc_claim_reduction.claim.rd_inc_stage5.gamma_pow", "field.pow:3", "stage6.inc_claim_reduction.gamma"), stage6_field_expr!("stage6.inc_claim_reduction.claim.rd_inc_stage5.gamma_term", "field.mul", "stage6.inc_claim_reduction.claim.rd_inc_stage5.gamma_pow|stage6.input.stage5.registers_val_evaluation.RdInc"), - stage6_field_expr!("stage6.inc_claim_reduction.claim_expr.partial0", "field.add", "stage6.input.stage2.ram_read_write.RamInc|stage6.inc_claim_reduction.claim.ram_inc_stage4.gamma_term"), stage6_field_expr!("stage6.inc_claim_reduction.claim_expr.partial1", "field.add", "stage6.inc_claim_reduction.claim_expr.partial0|stage6.inc_claim_reduction.claim.rd_inc_stage4.gamma_term"), stage6_field_expr!("stage6.inc_claim_reduction.claim_expr.partial2", "field.add", "stage6.inc_claim_reduction.claim_expr.partial1|stage6.inc_claim_reduction.claim.rd_inc_stage5.gamma_term"), + stage6_field_expr!("stage6.booleanity.gamma_sq_32", "field.pow:64", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_33", "field.pow:66", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_34", "field.pow:68", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_35", "field.pow:70", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_36", "field.pow:72", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_37", "field.pow:74", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_38", "field.pow:76", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_sq_39", "field.pow:78", "stage6.booleanity.gamma"), + stage6_field_expr!("stage6.booleanity.gamma_pow_0", "field.pow:0", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_1", "field.pow:1", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_2", "field.pow:2", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_3", "field.pow:3", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_4", "field.pow:4", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_5", "field.pow:5", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_6", "field.pow:6", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_7", "field.pow:7", "stage6.booleanity.gamma"), + stage6_field_expr!("stage6.booleanity.gamma_pow_8", "field.pow:8", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_9", "field.pow:9", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_10", "field.pow:10", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_11", "field.pow:11", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_12", "field.pow:12", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_13", "field.pow:13", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_14", "field.pow:14", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_15", "field.pow:15", "stage6.booleanity.gamma"), + stage6_field_expr!("stage6.booleanity.gamma_pow_16", "field.pow:16", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_17", "field.pow:17", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_18", "field.pow:18", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_19", "field.pow:19", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_20", "field.pow:20", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_21", "field.pow:21", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_22", "field.pow:22", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_23", "field.pow:23", "stage6.booleanity.gamma"), + stage6_field_expr!("stage6.booleanity.gamma_pow_24", "field.pow:24", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_25", "field.pow:25", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_26", "field.pow:26", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_27", "field.pow:27", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_28", "field.pow:28", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_29", "field.pow:29", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_30", "field.pow:30", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_31", "field.pow:31", "stage6.booleanity.gamma"), + stage6_field_expr!("stage6.booleanity.gamma_pow_32", "field.pow:32", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_33", "field.pow:33", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_34", "field.pow:34", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_35", "field.pow:35", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_36", "field.pow:36", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_37", "field.pow:37", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_38", "field.pow:38", "stage6.booleanity.gamma"), stage6_field_expr!("stage6.booleanity.gamma_pow_39", "field.pow:39", "stage6.booleanity.gamma"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term1.stage_gamma_pow", "field.pow:1", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term1.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term1.stage_gamma_pow|stage6.input.stage1.Imm"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term2.stage_gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term2.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term2.stage_gamma_pow|stage6.input.stage1.OpFlagAddOperands"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term3.stage_gamma_pow", "field.pow:3", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term3.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term3.stage_gamma_pow|stage6.input.stage1.OpFlagSubtractOperands"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term4.stage_gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term4.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term4.stage_gamma_pow|stage6.input.stage1.OpFlagMultiplyOperands"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term5.stage_gamma_pow", "field.pow:5", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term5.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term5.stage_gamma_pow|stage6.input.stage1.OpFlagLoad"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term6.stage_gamma_pow", "field.pow:6", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term6.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term6.stage_gamma_pow|stage6.input.stage1.OpFlagStore"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term7.stage_gamma_pow", "field.pow:7", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term7.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term7.stage_gamma_pow|stage6.input.stage1.OpFlagJump"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term8.stage_gamma_pow", "field.pow:8", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term8.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term8.stage_gamma_pow|stage6.input.stage1.OpFlagWriteLookupOutputToRD"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term9.stage_gamma_pow", "field.pow:9", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term9.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term9.stage_gamma_pow|stage6.input.stage1.OpFlagVirtualInstruction"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term10.stage_gamma_pow", "field.pow:10", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term10.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term10.stage_gamma_pow|stage6.input.stage1.OpFlagAssert"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term11.stage_gamma_pow", "field.pow:11", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term11.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term11.stage_gamma_pow|stage6.input.stage1.OpFlagDoNotUpdateUnexpandedPC"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term12.stage_gamma_pow", "field.pow:12", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term12.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term12.stage_gamma_pow|stage6.input.stage1.OpFlagAdvice"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term13.stage_gamma_pow", "field.pow:13", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term13.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term13.stage_gamma_pow|stage6.input.stage1.OpFlagIsCompressed"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term14.stage_gamma_pow", "field.pow:14", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term14.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term14.stage_gamma_pow|stage6.input.stage1.OpFlagIsFirstInSequence"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term15.stage_gamma_pow", "field.pow:15", "stage6.bytecode_read_raf.stage1_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term15.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term15.stage_gamma_pow|stage6.input.stage1.OpFlagIsLastInSequence"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term16.gamma_pow", "field.pow:1", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term16.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term16.gamma_pow|stage6.input.stage2.OpFlagJump"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term17.stage_gamma_pow", "field.pow:1", "stage6.bytecode_read_raf.stage2_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term17.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term17.stage_gamma_pow|stage6.input.stage2.InstructionFlagBranch"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term17.gamma_pow", "field.pow:1", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term17.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term17.gamma_pow|stage6.bytecode_read_raf.claim.term17.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term18.stage_gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.stage2_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term18.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term18.stage_gamma_pow|stage6.input.stage2.OpFlagWriteLookupOutputToRD"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term18.gamma_pow", "field.pow:1", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term18.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term18.gamma_pow|stage6.bytecode_read_raf.claim.term18.stage_gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term19.stage_gamma_pow", "field.pow:3", "stage6.bytecode_read_raf.stage2_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term19.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term19.stage_gamma_pow|stage6.input.stage2.OpFlagVirtualInstruction"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term19.gamma_pow", "field.pow:1", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term19.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term19.gamma_pow|stage6.bytecode_read_raf.claim.term19.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term20.gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term20.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term20.gamma_pow|stage6.input.stage3.instruction_input.Imm"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term21.stage_gamma_pow", "field.pow:1", "stage6.bytecode_read_raf.stage3_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term21.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term21.stage_gamma_pow|stage6.input.stage3.spartan_shift.UnexpandedPC"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term21.gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term21.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term21.gamma_pow|stage6.bytecode_read_raf.claim.term21.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term22.stage_gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.stage3_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term22.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term22.stage_gamma_pow|stage6.input.stage3.instruction_input.InstructionFlagLeftOperandIsRs1Value"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term22.gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term22.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term22.gamma_pow|stage6.bytecode_read_raf.claim.term22.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term23.stage_gamma_pow", "field.pow:3", "stage6.bytecode_read_raf.stage3_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term23.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term23.stage_gamma_pow|stage6.input.stage3.instruction_input.InstructionFlagLeftOperandIsPC"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term23.gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term23.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term23.gamma_pow|stage6.bytecode_read_raf.claim.term23.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term24.stage_gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.stage3_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term24.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term24.stage_gamma_pow|stage6.input.stage3.instruction_input.InstructionFlagRightOperandIsRs2Value"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term24.gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term24.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term24.gamma_pow|stage6.bytecode_read_raf.claim.term24.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term25.stage_gamma_pow", "field.pow:5", "stage6.bytecode_read_raf.stage3_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term25.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term25.stage_gamma_pow|stage6.input.stage3.instruction_input.InstructionFlagRightOperandIsImm"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term25.gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term25.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term25.gamma_pow|stage6.bytecode_read_raf.claim.term25.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term26.stage_gamma_pow", "field.pow:6", "stage6.bytecode_read_raf.stage3_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term26.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term26.stage_gamma_pow|stage6.input.stage3.spartan_shift.InstructionFlagIsNoop"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term26.gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term26.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term26.gamma_pow|stage6.bytecode_read_raf.claim.term26.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term27.stage_gamma_pow", "field.pow:7", "stage6.bytecode_read_raf.stage3_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term27.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term27.stage_gamma_pow|stage6.input.stage3.spartan_shift.OpFlagVirtualInstruction"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term27.gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term27.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term27.gamma_pow|stage6.bytecode_read_raf.claim.term27.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term28.stage_gamma_pow", "field.pow:8", "stage6.bytecode_read_raf.stage3_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term28.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term28.stage_gamma_pow|stage6.input.stage3.spartan_shift.OpFlagIsFirstInSequence"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term28.gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term28.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term28.gamma_pow|stage6.bytecode_read_raf.claim.term28.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term29.gamma_pow", "field.pow:3", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term29.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term29.gamma_pow|stage6.input.stage4.RdWa"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term30.stage_gamma_pow", "field.pow:1", "stage6.bytecode_read_raf.stage4_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term30.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term30.stage_gamma_pow|stage6.input.stage4.Rs1Ra"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term30.gamma_pow", "field.pow:3", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term30.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term30.gamma_pow|stage6.bytecode_read_raf.claim.term30.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term31.stage_gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.stage4_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term31.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term31.stage_gamma_pow|stage6.input.stage4.Rs2Ra"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term31.gamma_pow", "field.pow:3", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term31.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term31.gamma_pow|stage6.bytecode_read_raf.claim.term31.stage_gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term32.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term32.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term32.gamma_pow|stage6.input.stage5.registers_val_evaluation.RdWa"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term33.stage_gamma_pow", "field.pow:1", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term33.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term33.stage_gamma_pow|stage6.input.stage5.InstructionRafFlag"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term33.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term33.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term33.gamma_pow|stage6.bytecode_read_raf.claim.term33.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term34.stage_gamma_pow", "field.pow:2", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term34.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term34.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_0"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term34.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term34.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term34.gamma_pow|stage6.bytecode_read_raf.claim.term34.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term35.stage_gamma_pow", "field.pow:3", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term35.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term35.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_1"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term35.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term35.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term35.gamma_pow|stage6.bytecode_read_raf.claim.term35.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term36.stage_gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term36.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term36.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_2"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term36.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term36.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term36.gamma_pow|stage6.bytecode_read_raf.claim.term36.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term37.stage_gamma_pow", "field.pow:5", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term37.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term37.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_3"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term37.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term37.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term37.gamma_pow|stage6.bytecode_read_raf.claim.term37.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term38.stage_gamma_pow", "field.pow:6", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term38.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term38.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_4"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term38.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term38.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term38.gamma_pow|stage6.bytecode_read_raf.claim.term38.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term39.stage_gamma_pow", "field.pow:7", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term39.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term39.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_5"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term39.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term39.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term39.gamma_pow|stage6.bytecode_read_raf.claim.term39.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term40.stage_gamma_pow", "field.pow:8", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term40.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term40.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_6"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term40.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term40.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term40.gamma_pow|stage6.bytecode_read_raf.claim.term40.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term41.stage_gamma_pow", "field.pow:9", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term41.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term41.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_7"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term41.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term41.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term41.gamma_pow|stage6.bytecode_read_raf.claim.term41.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term42.stage_gamma_pow", "field.pow:10", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term42.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term42.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_8"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term42.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term42.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term42.gamma_pow|stage6.bytecode_read_raf.claim.term42.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term43.stage_gamma_pow", "field.pow:11", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term43.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term43.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_9"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term43.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term43.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term43.gamma_pow|stage6.bytecode_read_raf.claim.term43.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term44.stage_gamma_pow", "field.pow:12", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term44.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term44.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_10"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term44.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term44.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term44.gamma_pow|stage6.bytecode_read_raf.claim.term44.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term45.stage_gamma_pow", "field.pow:13", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term45.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term45.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_11"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term45.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term45.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term45.gamma_pow|stage6.bytecode_read_raf.claim.term45.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term46.stage_gamma_pow", "field.pow:14", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term46.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term46.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_12"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term46.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term46.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term46.gamma_pow|stage6.bytecode_read_raf.claim.term46.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term47.stage_gamma_pow", "field.pow:15", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term47.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term47.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_13"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term47.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term47.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term47.gamma_pow|stage6.bytecode_read_raf.claim.term47.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term48.stage_gamma_pow", "field.pow:16", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term48.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term48.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_14"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term48.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term48.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term48.gamma_pow|stage6.bytecode_read_raf.claim.term48.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term49.stage_gamma_pow", "field.pow:17", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term49.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term49.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_15"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term49.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term49.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term49.gamma_pow|stage6.bytecode_read_raf.claim.term49.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term50.stage_gamma_pow", "field.pow:18", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term50.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term50.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_16"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term50.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term50.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term50.gamma_pow|stage6.bytecode_read_raf.claim.term50.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term51.stage_gamma_pow", "field.pow:19", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term51.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term51.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_17"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term51.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term51.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term51.gamma_pow|stage6.bytecode_read_raf.claim.term51.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term52.stage_gamma_pow", "field.pow:20", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term52.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term52.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_18"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term52.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term52.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term52.gamma_pow|stage6.bytecode_read_raf.claim.term52.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term53.stage_gamma_pow", "field.pow:21", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term53.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term53.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_19"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term53.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term53.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term53.gamma_pow|stage6.bytecode_read_raf.claim.term53.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term54.stage_gamma_pow", "field.pow:22", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term54.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term54.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_20"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term54.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term54.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term54.gamma_pow|stage6.bytecode_read_raf.claim.term54.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term55.stage_gamma_pow", "field.pow:23", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term55.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term55.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_21"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term55.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term55.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term55.gamma_pow|stage6.bytecode_read_raf.claim.term55.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term56.stage_gamma_pow", "field.pow:24", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term56.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term56.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_22"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term56.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term56.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term56.gamma_pow|stage6.bytecode_read_raf.claim.term56.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term57.stage_gamma_pow", "field.pow:25", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term57.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term57.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_23"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term57.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term57.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term57.gamma_pow|stage6.bytecode_read_raf.claim.term57.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term58.stage_gamma_pow", "field.pow:26", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term58.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term58.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_24"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term58.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term58.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term58.gamma_pow|stage6.bytecode_read_raf.claim.term58.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term59.stage_gamma_pow", "field.pow:27", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term59.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term59.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_25"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term59.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term59.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term59.gamma_pow|stage6.bytecode_read_raf.claim.term59.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term60.stage_gamma_pow", "field.pow:28", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term60.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term60.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_26"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term60.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term60.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term60.gamma_pow|stage6.bytecode_read_raf.claim.term60.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term61.stage_gamma_pow", "field.pow:29", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term61.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term61.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_27"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term61.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term61.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term61.gamma_pow|stage6.bytecode_read_raf.claim.term61.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term62.stage_gamma_pow", "field.pow:30", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term62.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term62.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_28"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term62.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term62.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term62.gamma_pow|stage6.bytecode_read_raf.claim.term62.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term63.stage_gamma_pow", "field.pow:31", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term63.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term63.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_29"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term63.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term63.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term63.gamma_pow|stage6.bytecode_read_raf.claim.term63.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term64.stage_gamma_pow", "field.pow:32", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term64.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term64.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_30"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term64.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term64.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term64.gamma_pow|stage6.bytecode_read_raf.claim.term64.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term65.stage_gamma_pow", "field.pow:33", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term65.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term65.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_31"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term65.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term65.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term65.gamma_pow|stage6.bytecode_read_raf.claim.term65.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term66.stage_gamma_pow", "field.pow:34", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term66.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term66.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_32"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term66.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term66.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term66.gamma_pow|stage6.bytecode_read_raf.claim.term66.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term67.stage_gamma_pow", "field.pow:35", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term67.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term67.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_33"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term67.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term67.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term67.gamma_pow|stage6.bytecode_read_raf.claim.term67.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term68.stage_gamma_pow", "field.pow:36", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term68.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term68.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_34"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term68.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term68.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term68.gamma_pow|stage6.bytecode_read_raf.claim.term68.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term69.stage_gamma_pow", "field.pow:37", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term69.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term69.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_35"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term69.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term69.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term69.gamma_pow|stage6.bytecode_read_raf.claim.term69.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term70.stage_gamma_pow", "field.pow:38", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term70.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term70.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_36"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term70.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term70.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term70.gamma_pow|stage6.bytecode_read_raf.claim.term70.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term71.stage_gamma_pow", "field.pow:39", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term71.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term71.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_37"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term71.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term71.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term71.gamma_pow|stage6.bytecode_read_raf.claim.term71.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term72.stage_gamma_pow", "field.pow:40", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term72.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term72.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_38"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term72.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term72.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term72.gamma_pow|stage6.bytecode_read_raf.claim.term72.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term73.stage_gamma_pow", "field.pow:41", "stage6.bytecode_read_raf.stage5_gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term73.stage_gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term73.stage_gamma_pow|stage6.input.stage5.LookupTableFlag_39"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term73.gamma_pow", "field.pow:4", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term73.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term73.gamma_pow|stage6.bytecode_read_raf.claim.term73.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term74.gamma_pow", "field.pow:5", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term74.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term74.gamma_pow|stage6.input.stage1.PC"), + stage6_field_expr!("stage6.bytecode_read_raf.claim.term75.gamma_pow", "field.pow:6", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim.term75.gamma_term", "field.mul", "stage6.bytecode_read_raf.claim.term75.gamma_pow|stage6.input.stage3.spartan_shift.PC"), stage6_field_expr!("stage6.bytecode_read_raf.claim.entry_constant", "field.pow:7", "stage6.bytecode_read_raf.gamma"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial0", "field.add", "stage6.input.stage1.UnexpandedPC|stage6.bytecode_read_raf.claim.term1.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial1", "field.add", "stage6.bytecode_read_raf.claim_expr.partial0|stage6.bytecode_read_raf.claim.term2.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial2", "field.add", "stage6.bytecode_read_raf.claim_expr.partial1|stage6.bytecode_read_raf.claim.term3.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial3", "field.add", "stage6.bytecode_read_raf.claim_expr.partial2|stage6.bytecode_read_raf.claim.term4.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial4", "field.add", "stage6.bytecode_read_raf.claim_expr.partial3|stage6.bytecode_read_raf.claim.term5.stage_gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial5", "field.add", "stage6.bytecode_read_raf.claim_expr.partial4|stage6.bytecode_read_raf.claim.term6.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial6", "field.add", "stage6.bytecode_read_raf.claim_expr.partial5|stage6.bytecode_read_raf.claim.term7.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial7", "field.add", "stage6.bytecode_read_raf.claim_expr.partial6|stage6.bytecode_read_raf.claim.term8.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial8", "field.add", "stage6.bytecode_read_raf.claim_expr.partial7|stage6.bytecode_read_raf.claim.term9.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial9", "field.add", "stage6.bytecode_read_raf.claim_expr.partial8|stage6.bytecode_read_raf.claim.term10.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial10", "field.add", "stage6.bytecode_read_raf.claim_expr.partial9|stage6.bytecode_read_raf.claim.term11.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial11", "field.add", "stage6.bytecode_read_raf.claim_expr.partial10|stage6.bytecode_read_raf.claim.term12.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial12", "field.add", "stage6.bytecode_read_raf.claim_expr.partial11|stage6.bytecode_read_raf.claim.term13.stage_gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial13", "field.add", "stage6.bytecode_read_raf.claim_expr.partial12|stage6.bytecode_read_raf.claim.term14.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial14", "field.add", "stage6.bytecode_read_raf.claim_expr.partial13|stage6.bytecode_read_raf.claim.term15.stage_gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial15", "field.add", "stage6.bytecode_read_raf.claim_expr.partial14|stage6.bytecode_read_raf.claim.term16.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial16", "field.add", "stage6.bytecode_read_raf.claim_expr.partial15|stage6.bytecode_read_raf.claim.term17.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial17", "field.add", "stage6.bytecode_read_raf.claim_expr.partial16|stage6.bytecode_read_raf.claim.term18.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial18", "field.add", "stage6.bytecode_read_raf.claim_expr.partial17|stage6.bytecode_read_raf.claim.term19.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial19", "field.add", "stage6.bytecode_read_raf.claim_expr.partial18|stage6.bytecode_read_raf.claim.term20.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial20", "field.add", "stage6.bytecode_read_raf.claim_expr.partial19|stage6.bytecode_read_raf.claim.term21.gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial21", "field.add", "stage6.bytecode_read_raf.claim_expr.partial20|stage6.bytecode_read_raf.claim.term22.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial22", "field.add", "stage6.bytecode_read_raf.claim_expr.partial21|stage6.bytecode_read_raf.claim.term23.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial23", "field.add", "stage6.bytecode_read_raf.claim_expr.partial22|stage6.bytecode_read_raf.claim.term24.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial24", "field.add", "stage6.bytecode_read_raf.claim_expr.partial23|stage6.bytecode_read_raf.claim.term25.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial25", "field.add", "stage6.bytecode_read_raf.claim_expr.partial24|stage6.bytecode_read_raf.claim.term26.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial26", "field.add", "stage6.bytecode_read_raf.claim_expr.partial25|stage6.bytecode_read_raf.claim.term27.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial27", "field.add", "stage6.bytecode_read_raf.claim_expr.partial26|stage6.bytecode_read_raf.claim.term28.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial28", "field.add", "stage6.bytecode_read_raf.claim_expr.partial27|stage6.bytecode_read_raf.claim.term29.gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial29", "field.add", "stage6.bytecode_read_raf.claim_expr.partial28|stage6.bytecode_read_raf.claim.term30.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial30", "field.add", "stage6.bytecode_read_raf.claim_expr.partial29|stage6.bytecode_read_raf.claim.term31.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial31", "field.add", "stage6.bytecode_read_raf.claim_expr.partial30|stage6.bytecode_read_raf.claim.term32.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial32", "field.add", "stage6.bytecode_read_raf.claim_expr.partial31|stage6.bytecode_read_raf.claim.term33.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial33", "field.add", "stage6.bytecode_read_raf.claim_expr.partial32|stage6.bytecode_read_raf.claim.term34.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial34", "field.add", "stage6.bytecode_read_raf.claim_expr.partial33|stage6.bytecode_read_raf.claim.term35.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial35", "field.add", "stage6.bytecode_read_raf.claim_expr.partial34|stage6.bytecode_read_raf.claim.term36.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial36", "field.add", "stage6.bytecode_read_raf.claim_expr.partial35|stage6.bytecode_read_raf.claim.term37.gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial37", "field.add", "stage6.bytecode_read_raf.claim_expr.partial36|stage6.bytecode_read_raf.claim.term38.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial38", "field.add", "stage6.bytecode_read_raf.claim_expr.partial37|stage6.bytecode_read_raf.claim.term39.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial39", "field.add", "stage6.bytecode_read_raf.claim_expr.partial38|stage6.bytecode_read_raf.claim.term40.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial40", "field.add", "stage6.bytecode_read_raf.claim_expr.partial39|stage6.bytecode_read_raf.claim.term41.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial41", "field.add", "stage6.bytecode_read_raf.claim_expr.partial40|stage6.bytecode_read_raf.claim.term42.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial42", "field.add", "stage6.bytecode_read_raf.claim_expr.partial41|stage6.bytecode_read_raf.claim.term43.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial43", "field.add", "stage6.bytecode_read_raf.claim_expr.partial42|stage6.bytecode_read_raf.claim.term44.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial44", "field.add", "stage6.bytecode_read_raf.claim_expr.partial43|stage6.bytecode_read_raf.claim.term45.gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial45", "field.add", "stage6.bytecode_read_raf.claim_expr.partial44|stage6.bytecode_read_raf.claim.term46.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial46", "field.add", "stage6.bytecode_read_raf.claim_expr.partial45|stage6.bytecode_read_raf.claim.term47.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial47", "field.add", "stage6.bytecode_read_raf.claim_expr.partial46|stage6.bytecode_read_raf.claim.term48.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial48", "field.add", "stage6.bytecode_read_raf.claim_expr.partial47|stage6.bytecode_read_raf.claim.term49.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial49", "field.add", "stage6.bytecode_read_raf.claim_expr.partial48|stage6.bytecode_read_raf.claim.term50.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial50", "field.add", "stage6.bytecode_read_raf.claim_expr.partial49|stage6.bytecode_read_raf.claim.term51.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial51", "field.add", "stage6.bytecode_read_raf.claim_expr.partial50|stage6.bytecode_read_raf.claim.term52.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial52", "field.add", "stage6.bytecode_read_raf.claim_expr.partial51|stage6.bytecode_read_raf.claim.term53.gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial53", "field.add", "stage6.bytecode_read_raf.claim_expr.partial52|stage6.bytecode_read_raf.claim.term54.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial54", "field.add", "stage6.bytecode_read_raf.claim_expr.partial53|stage6.bytecode_read_raf.claim.term55.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial55", "field.add", "stage6.bytecode_read_raf.claim_expr.partial54|stage6.bytecode_read_raf.claim.term56.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial56", "field.add", "stage6.bytecode_read_raf.claim_expr.partial55|stage6.bytecode_read_raf.claim.term57.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial57", "field.add", "stage6.bytecode_read_raf.claim_expr.partial56|stage6.bytecode_read_raf.claim.term58.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial58", "field.add", "stage6.bytecode_read_raf.claim_expr.partial57|stage6.bytecode_read_raf.claim.term59.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial59", "field.add", "stage6.bytecode_read_raf.claim_expr.partial58|stage6.bytecode_read_raf.claim.term60.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial60", "field.add", "stage6.bytecode_read_raf.claim_expr.partial59|stage6.bytecode_read_raf.claim.term61.gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial61", "field.add", "stage6.bytecode_read_raf.claim_expr.partial60|stage6.bytecode_read_raf.claim.term62.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial62", "field.add", "stage6.bytecode_read_raf.claim_expr.partial61|stage6.bytecode_read_raf.claim.term63.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial63", "field.add", "stage6.bytecode_read_raf.claim_expr.partial62|stage6.bytecode_read_raf.claim.term64.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial64", "field.add", "stage6.bytecode_read_raf.claim_expr.partial63|stage6.bytecode_read_raf.claim.term65.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial65", "field.add", "stage6.bytecode_read_raf.claim_expr.partial64|stage6.bytecode_read_raf.claim.term66.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial66", "field.add", "stage6.bytecode_read_raf.claim_expr.partial65|stage6.bytecode_read_raf.claim.term67.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial67", "field.add", "stage6.bytecode_read_raf.claim_expr.partial66|stage6.bytecode_read_raf.claim.term68.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial68", "field.add", "stage6.bytecode_read_raf.claim_expr.partial67|stage6.bytecode_read_raf.claim.term69.gamma_term"), + stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial69", "field.add", "stage6.bytecode_read_raf.claim_expr.partial68|stage6.bytecode_read_raf.claim.term70.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial70", "field.add", "stage6.bytecode_read_raf.claim_expr.partial69|stage6.bytecode_read_raf.claim.term71.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial71", "field.add", "stage6.bytecode_read_raf.claim_expr.partial70|stage6.bytecode_read_raf.claim.term72.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial72", "field.add", "stage6.bytecode_read_raf.claim_expr.partial71|stage6.bytecode_read_raf.claim.term73.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial73", "field.add", "stage6.bytecode_read_raf.claim_expr.partial72|stage6.bytecode_read_raf.claim.term74.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial74", "field.add", "stage6.bytecode_read_raf.claim_expr.partial73|stage6.bytecode_read_raf.claim.term75.gamma_term"), stage6_field_expr!("stage6.bytecode_read_raf.claim_expr.partial75", "field.add", "stage6.bytecode_read_raf.claim_expr.partial74|stage6.bytecode_read_raf.claim.entry_constant"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term1.gamma_pow", "field.pow:1", "stage6.instruction_ra_virtual.gamma"), + stage6_field_expr!("stage6.instruction_ra_virtual.claim.term1.gamma_term", "field.mul", "stage6.instruction_ra_virtual.claim.term1.gamma_pow|stage6.input.stage5.instruction_read_raf.InstructionRa_1"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term2.gamma_pow", "field.pow:2", "stage6.instruction_ra_virtual.gamma"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term2.gamma_term", "field.mul", "stage6.instruction_ra_virtual.claim.term2.gamma_pow|stage6.input.stage5.instruction_read_raf.InstructionRa_2"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term3.gamma_pow", "field.pow:3", "stage6.instruction_ra_virtual.gamma"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term3.gamma_term", "field.mul", "stage6.instruction_ra_virtual.claim.term3.gamma_pow|stage6.input.stage5.instruction_read_raf.InstructionRa_3"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term4.gamma_pow", "field.pow:4", "stage6.instruction_ra_virtual.gamma"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term4.gamma_term", "field.mul", "stage6.instruction_ra_virtual.claim.term4.gamma_pow|stage6.input.stage5.instruction_read_raf.InstructionRa_4"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term5.gamma_pow", "field.pow:5", "stage6.instruction_ra_virtual.gamma"), + stage6_field_expr!("stage6.instruction_ra_virtual.claim.term5.gamma_term", "field.mul", "stage6.instruction_ra_virtual.claim.term5.gamma_pow|stage6.input.stage5.instruction_read_raf.InstructionRa_5"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term6.gamma_pow", "field.pow:6", "stage6.instruction_ra_virtual.gamma"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term6.gamma_term", "field.mul", "stage6.instruction_ra_virtual.claim.term6.gamma_pow|stage6.input.stage5.instruction_read_raf.InstructionRa_6"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term7.gamma_pow", "field.pow:7", "stage6.instruction_ra_virtual.gamma"), stage6_field_expr!("stage6.instruction_ra_virtual.claim.term7.gamma_term", "field.mul", "stage6.instruction_ra_virtual.claim.term7.gamma_pow|stage6.input.stage5.instruction_read_raf.InstructionRa_7"), stage6_field_expr!("stage6.instruction_ra_virtual.claim_expr.partial0", "field.add", "stage6.input.stage5.instruction_read_raf.InstructionRa_0|stage6.instruction_ra_virtual.claim.term1.gamma_term"), stage6_field_expr!("stage6.instruction_ra_virtual.claim_expr.partial1", "field.add", "stage6.instruction_ra_virtual.claim_expr.partial0|stage6.instruction_ra_virtual.claim.term2.gamma_term"), stage6_field_expr!("stage6.instruction_ra_virtual.claim_expr.partial2", "field.add", "stage6.instruction_ra_virtual.claim_expr.partial1|stage6.instruction_ra_virtual.claim.term3.gamma_term"), + stage6_field_expr!("stage6.instruction_ra_virtual.claim_expr.partial3", "field.add", "stage6.instruction_ra_virtual.claim_expr.partial2|stage6.instruction_ra_virtual.claim.term4.gamma_term"), stage6_field_expr!("stage6.instruction_ra_virtual.claim_expr.partial4", "field.add", "stage6.instruction_ra_virtual.claim_expr.partial3|stage6.instruction_ra_virtual.claim.term5.gamma_term"), stage6_field_expr!("stage6.instruction_ra_virtual.claim_expr.partial5", "field.add", "stage6.instruction_ra_virtual.claim_expr.partial4|stage6.instruction_ra_virtual.claim.term6.gamma_term"), stage6_field_expr!("stage6.instruction_ra_virtual.claim_expr.partial6", "field.add", "stage6.instruction_ra_virtual.claim_expr.partial5|stage6.instruction_ra_virtual.claim.term7.gamma_term"), stage6_field_expr!("stage6.inc_claim_reduction.claim.ram_inc_stage4.gamma_pow", "field.pow:1", "stage6.inc_claim_reduction.gamma"), stage6_field_expr!("stage6.inc_claim_reduction.claim.ram_inc_stage4.gamma_term", "field.mul", "stage6.inc_claim_reduction.claim.ram_inc_stage4.gamma_pow|stage6.input.stage4.ram_val_check.RamInc"), stage6_field_expr!("stage6.inc_claim_reduction.claim.rd_inc_stage4.gamma_pow", "field.pow:2", "stage6.inc_claim_reduction.gamma"), stage6_field_expr!("stage6.inc_claim_reduction.claim.rd_inc_stage4.gamma_term", "field.mul", "stage6.inc_claim_reduction.claim.rd_inc_stage4.gamma_pow|stage6.input.stage4.registers_read_write.RdInc"), + stage6_field_expr!("stage6.inc_claim_reduction.claim.rd_inc_stage5.gamma_pow", "field.pow:3", "stage6.inc_claim_reduction.gamma"), stage6_field_expr!("stage6.inc_claim_reduction.claim.rd_inc_stage5.gamma_term", "field.mul", "stage6.inc_claim_reduction.claim.rd_inc_stage5.gamma_pow|stage6.input.stage5.registers_val_evaluation.RdInc"), stage6_field_expr!("stage6.inc_claim_reduction.claim_expr.partial0", "field.add", "stage6.input.stage2.ram_read_write.RamInc|stage6.inc_claim_reduction.claim.ram_inc_stage4.gamma_term"), stage6_field_expr!("stage6.inc_claim_reduction.claim_expr.partial1", "field.add", "stage6.inc_claim_reduction.claim_expr.partial0|stage6.inc_claim_reduction.claim.rd_inc_stage4.gamma_term"), stage6_field_expr!("stage6.inc_claim_reduction.claim_expr.partial2", "field.add", "stage6.inc_claim_reduction.claim_expr.partial1|stage6.inc_claim_reduction.claim.rd_inc_stage5.gamma_term"), ]; pub const STAGE6_KERNELS: &[Stage6KernelPlan] = &[ ]; pub const STAGE6_SUMCHECK_CLAIMS: &[Stage6SumcheckClaimPlan] = &[ - Stage6SumcheckClaimPlan { symbol: "stage6.bytecode_read_raf.input", stage: "stage6", domain: "jolt.stage6_bytecode_read_raf_domain", num_rounds: 26, degree: 4, claim: "stage6.bytecode_read_raf.weighted_prior_stage_values", kernel: None, relation: Some("jolt.stage6.bytecode_read_raf"), claim_value: "stage6.bytecode_read_raf.claim_expr.partial75", input_openings: "stage6.input.stage1.UnexpandedPC|stage6.input.stage1.Imm|stage6.input.stage1.OpFlagAddOperands|stage6.input.stage1.OpFlagSubtractOperands|stage6.input.stage1.OpFlagMultiplyOperands|stage6.input.stage1.OpFlagLoad|stage6.input.stage1.OpFlagStore|stage6.input.stage1.OpFlagJump|stage6.input.stage1.OpFlagWriteLookupOutputToRD|stage6.input.stage1.OpFlagVirtualInstruction|stage6.input.stage1.OpFlagAssert|stage6.input.stage1.OpFlagDoNotUpdateUnexpandedPC|stage6.input.stage1.OpFlagAdvice|stage6.input.stage1.OpFlagIsCompressed|stage6.input.stage1.OpFlagIsFirstInSequence|stage6.input.stage1.OpFlagIsLastInSequence|stage6.input.stage2.OpFlagJump|stage6.input.stage2.InstructionFlagBranch|stage6.input.stage2.OpFlagWriteLookupOutputToRD|stage6.input.stage2.OpFlagVirtualInstruction|stage6.input.stage3.instruction_input.Imm|stage6.input.stage3.spartan_shift.UnexpandedPC|stage6.input.stage3.instruction_input.InstructionFlagLeftOperandIsRs1Value|stage6.input.stage3.instruction_input.InstructionFlagLeftOperandIsPC|stage6.input.stage3.instruction_input.InstructionFlagRightOperandIsRs2Value|stage6.input.stage3.instruction_input.InstructionFlagRightOperandIsImm|stage6.input.stage3.spartan_shift.InstructionFlagIsNoop|stage6.input.stage3.spartan_shift.OpFlagVirtualInstruction|stage6.input.stage3.spartan_shift.OpFlagIsFirstInSequence|stage6.input.stage4.RdWa|stage6.input.stage4.Rs1Ra|stage6.input.stage4.Rs2Ra|stage6.input.stage5.registers_val_evaluation.RdWa|stage6.input.stage5.InstructionRafFlag|stage6.input.stage5.LookupTableFlag_0|stage6.input.stage5.LookupTableFlag_1|stage6.input.stage5.LookupTableFlag_2|stage6.input.stage5.LookupTableFlag_3|stage6.input.stage5.LookupTableFlag_4|stage6.input.stage5.LookupTableFlag_5|stage6.input.stage5.LookupTableFlag_6|stage6.input.stage5.LookupTableFlag_7|stage6.input.stage5.LookupTableFlag_8|stage6.input.stage5.LookupTableFlag_9|stage6.input.stage5.LookupTableFlag_10|stage6.input.stage5.LookupTableFlag_11|stage6.input.stage5.LookupTableFlag_12|stage6.input.stage5.LookupTableFlag_13|stage6.input.stage5.LookupTableFlag_14|stage6.input.stage5.LookupTableFlag_15|stage6.input.stage5.LookupTableFlag_16|stage6.input.stage5.LookupTableFlag_17|stage6.input.stage5.LookupTableFlag_18|stage6.input.stage5.LookupTableFlag_19|stage6.input.stage5.LookupTableFlag_20|stage6.input.stage5.LookupTableFlag_21|stage6.input.stage5.LookupTableFlag_22|stage6.input.stage5.LookupTableFlag_23|stage6.input.stage5.LookupTableFlag_24|stage6.input.stage5.LookupTableFlag_25|stage6.input.stage5.LookupTableFlag_26|stage6.input.stage5.LookupTableFlag_27|stage6.input.stage5.LookupTableFlag_28|stage6.input.stage5.LookupTableFlag_29|stage6.input.stage5.LookupTableFlag_30|stage6.input.stage5.LookupTableFlag_31|stage6.input.stage5.LookupTableFlag_32|stage6.input.stage5.LookupTableFlag_33|stage6.input.stage5.LookupTableFlag_34|stage6.input.stage5.LookupTableFlag_35|stage6.input.stage5.LookupTableFlag_36|stage6.input.stage5.LookupTableFlag_37|stage6.input.stage5.LookupTableFlag_38|stage6.input.stage5.LookupTableFlag_39|stage6.input.stage1.PC|stage6.input.stage3.spartan_shift.PC" }, - Stage6SumcheckClaimPlan { symbol: "stage6.booleanity.input", stage: "stage6", domain: "jolt.stage6_booleanity_domain", num_rounds: 20, degree: 3, claim: "stage6.booleanity.zero", kernel: None, relation: Some("jolt.stage6.booleanity"), claim_value: "stage6.zero", input_openings: "" }, - Stage6SumcheckClaimPlan { symbol: "stage6.hamming_booleanity.input", stage: "stage6", domain: "jolt.trace_domain", num_rounds: 16, degree: 3, claim: "stage6.hamming_booleanity.zero", kernel: None, relation: Some("jolt.stage6.hamming_booleanity"), claim_value: "stage6.zero", input_openings: "stage6.input.stage1.LookupOutput" }, - Stage6SumcheckClaimPlan { symbol: "stage6.ram_ra_virtual.input", stage: "stage6", domain: "jolt.trace_domain", num_rounds: 16, degree: 5, claim: "stage6.ram_ra_virtual.weighted_ram_ra", kernel: None, relation: Some("jolt.stage6.ram_ra_virtual"), claim_value: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", input_openings: "stage6.input.stage5.ram_ra_claim_reduction.RamRa" }, - Stage6SumcheckClaimPlan { symbol: "stage6.instruction_ra_virtual.input", stage: "stage6", domain: "jolt.trace_domain", num_rounds: 16, degree: 5, claim: "stage6.instruction_ra_virtual.weighted_instruction_ra", kernel: None, relation: Some("jolt.stage6.instruction_ra_virtual"), claim_value: "stage6.instruction_ra_virtual.claim_expr.partial6", input_openings: "stage6.input.stage5.instruction_read_raf.InstructionRa_0|stage6.input.stage5.instruction_read_raf.InstructionRa_1|stage6.input.stage5.instruction_read_raf.InstructionRa_2|stage6.input.stage5.instruction_read_raf.InstructionRa_3|stage6.input.stage5.instruction_read_raf.InstructionRa_4|stage6.input.stage5.instruction_read_raf.InstructionRa_5|stage6.input.stage5.instruction_read_raf.InstructionRa_6|stage6.input.stage5.instruction_read_raf.InstructionRa_7" }, - Stage6SumcheckClaimPlan { symbol: "stage6.inc_claim_reduction.input", stage: "stage6", domain: "jolt.trace_domain", num_rounds: 16, degree: 2, claim: "stage6.inc_claim_reduction.weighted_increments", kernel: None, relation: Some("jolt.stage6.inc_claim_reduction"), claim_value: "stage6.inc_claim_reduction.claim_expr.partial2", input_openings: "stage6.input.stage2.ram_read_write.RamInc|stage6.input.stage4.ram_val_check.RamInc|stage6.input.stage4.registers_read_write.RdInc|stage6.input.stage5.registers_val_evaluation.RdInc" }, + Stage6SumcheckClaimPlan { symbol: "stage6.bytecode_read_raf.input", stage: "stage6", domain: "jolt.stage6_bytecode_read_raf_domain", num_rounds: 32, degree: 5, claim: "stage6.bytecode_read_raf.weighted_prior_stage_values", kernel: None, relation: Some("jolt.stage6.bytecode_read_raf"), claim_value: "stage6.bytecode_read_raf.claim_expr.partial75", input_openings: "stage6.input.stage1.UnexpandedPC|stage6.input.stage1.Imm|stage6.input.stage1.OpFlagAddOperands|stage6.input.stage1.OpFlagSubtractOperands|stage6.input.stage1.OpFlagMultiplyOperands|stage6.input.stage1.OpFlagLoad|stage6.input.stage1.OpFlagStore|stage6.input.stage1.OpFlagJump|stage6.input.stage1.OpFlagWriteLookupOutputToRD|stage6.input.stage1.OpFlagVirtualInstruction|stage6.input.stage1.OpFlagAssert|stage6.input.stage1.OpFlagDoNotUpdateUnexpandedPC|stage6.input.stage1.OpFlagAdvice|stage6.input.stage1.OpFlagIsCompressed|stage6.input.stage1.OpFlagIsFirstInSequence|stage6.input.stage1.OpFlagIsLastInSequence|stage6.input.stage2.OpFlagJump|stage6.input.stage2.InstructionFlagBranch|stage6.input.stage2.OpFlagWriteLookupOutputToRD|stage6.input.stage2.OpFlagVirtualInstruction|stage6.input.stage3.instruction_input.Imm|stage6.input.stage3.spartan_shift.UnexpandedPC|stage6.input.stage3.instruction_input.InstructionFlagLeftOperandIsRs1Value|stage6.input.stage3.instruction_input.InstructionFlagLeftOperandIsPC|stage6.input.stage3.instruction_input.InstructionFlagRightOperandIsRs2Value|stage6.input.stage3.instruction_input.InstructionFlagRightOperandIsImm|stage6.input.stage3.spartan_shift.InstructionFlagIsNoop|stage6.input.stage3.spartan_shift.OpFlagVirtualInstruction|stage6.input.stage3.spartan_shift.OpFlagIsFirstInSequence|stage6.input.stage4.RdWa|stage6.input.stage4.Rs1Ra|stage6.input.stage4.Rs2Ra|stage6.input.stage5.registers_val_evaluation.RdWa|stage6.input.stage5.InstructionRafFlag|stage6.input.stage5.LookupTableFlag_0|stage6.input.stage5.LookupTableFlag_1|stage6.input.stage5.LookupTableFlag_2|stage6.input.stage5.LookupTableFlag_3|stage6.input.stage5.LookupTableFlag_4|stage6.input.stage5.LookupTableFlag_5|stage6.input.stage5.LookupTableFlag_6|stage6.input.stage5.LookupTableFlag_7|stage6.input.stage5.LookupTableFlag_8|stage6.input.stage5.LookupTableFlag_9|stage6.input.stage5.LookupTableFlag_10|stage6.input.stage5.LookupTableFlag_11|stage6.input.stage5.LookupTableFlag_12|stage6.input.stage5.LookupTableFlag_13|stage6.input.stage5.LookupTableFlag_14|stage6.input.stage5.LookupTableFlag_15|stage6.input.stage5.LookupTableFlag_16|stage6.input.stage5.LookupTableFlag_17|stage6.input.stage5.LookupTableFlag_18|stage6.input.stage5.LookupTableFlag_19|stage6.input.stage5.LookupTableFlag_20|stage6.input.stage5.LookupTableFlag_21|stage6.input.stage5.LookupTableFlag_22|stage6.input.stage5.LookupTableFlag_23|stage6.input.stage5.LookupTableFlag_24|stage6.input.stage5.LookupTableFlag_25|stage6.input.stage5.LookupTableFlag_26|stage6.input.stage5.LookupTableFlag_27|stage6.input.stage5.LookupTableFlag_28|stage6.input.stage5.LookupTableFlag_29|stage6.input.stage5.LookupTableFlag_30|stage6.input.stage5.LookupTableFlag_31|stage6.input.stage5.LookupTableFlag_32|stage6.input.stage5.LookupTableFlag_33|stage6.input.stage5.LookupTableFlag_34|stage6.input.stage5.LookupTableFlag_35|stage6.input.stage5.LookupTableFlag_36|stage6.input.stage5.LookupTableFlag_37|stage6.input.stage5.LookupTableFlag_38|stage6.input.stage5.LookupTableFlag_39|stage6.input.stage1.PC|stage6.input.stage3.spartan_shift.PC" }, + Stage6SumcheckClaimPlan { symbol: "stage6.booleanity.input", stage: "stage6", domain: "jolt.stage6_booleanity_domain", num_rounds: 22, degree: 3, claim: "stage6.booleanity.zero", kernel: None, relation: Some("jolt.stage6.booleanity"), claim_value: "stage6.zero", input_openings: "" }, + Stage6SumcheckClaimPlan { symbol: "stage6.hamming_booleanity.input", stage: "stage6", domain: "jolt.trace_domain", num_rounds: 18, degree: 3, claim: "stage6.hamming_booleanity.zero", kernel: None, relation: Some("jolt.stage6.hamming_booleanity"), claim_value: "stage6.zero", input_openings: "stage6.input.stage1.LookupOutput" }, + Stage6SumcheckClaimPlan { symbol: "stage6.ram_ra_virtual.input", stage: "stage6", domain: "jolt.trace_domain", num_rounds: 18, degree: 5, claim: "stage6.ram_ra_virtual.weighted_ram_ra", kernel: None, relation: Some("jolt.stage6.ram_ra_virtual"), claim_value: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", input_openings: "stage6.input.stage5.ram_ra_claim_reduction.RamRa" }, + Stage6SumcheckClaimPlan { symbol: "stage6.instruction_ra_virtual.input", stage: "stage6", domain: "jolt.trace_domain", num_rounds: 18, degree: 5, claim: "stage6.instruction_ra_virtual.weighted_instruction_ra", kernel: None, relation: Some("jolt.stage6.instruction_ra_virtual"), claim_value: "stage6.instruction_ra_virtual.claim_expr.partial6", input_openings: "stage6.input.stage5.instruction_read_raf.InstructionRa_0|stage6.input.stage5.instruction_read_raf.InstructionRa_1|stage6.input.stage5.instruction_read_raf.InstructionRa_2|stage6.input.stage5.instruction_read_raf.InstructionRa_3|stage6.input.stage5.instruction_read_raf.InstructionRa_4|stage6.input.stage5.instruction_read_raf.InstructionRa_5|stage6.input.stage5.instruction_read_raf.InstructionRa_6|stage6.input.stage5.instruction_read_raf.InstructionRa_7" }, + Stage6SumcheckClaimPlan { symbol: "stage6.inc_claim_reduction.input", stage: "stage6", domain: "jolt.trace_domain", num_rounds: 18, degree: 2, claim: "stage6.inc_claim_reduction.weighted_increments", kernel: None, relation: Some("jolt.stage6.inc_claim_reduction"), claim_value: "stage6.inc_claim_reduction.claim_expr.partial2", input_openings: "stage6.input.stage2.ram_read_write.RamInc|stage6.input.stage4.ram_val_check.RamInc|stage6.input.stage4.registers_read_write.RdInc|stage6.input.stage5.registers_val_evaluation.RdInc" }, ]; pub const STAGE6_SUMCHECK_BATCH_0_ROUND_SCHEDULE: &[usize] = &[ - 10, - 16, + 14, + 18, ]; pub const STAGE6_SUMCHECK_BATCHES: &[Stage6SumcheckBatchPlan] = &[ Stage6SumcheckBatchPlan { symbol: "stage6.batch", stage: "stage6", proof_slot: "stage6.sumcheck", policy: "jolt_core_stage6_aligned", count: 6, ordered_claims: "stage6.bytecode_read_raf.input|stage6.booleanity.input|stage6.hamming_booleanity.input|stage6.ram_ra_virtual.input|stage6.instruction_ra_virtual.input|stage6.inc_claim_reduction.input", claim_operands: "stage6.bytecode_read_raf.input|stage6.booleanity.input|stage6.hamming_booleanity.input|stage6.ram_ra_virtual.input|stage6.instruction_ra_virtual.input|stage6.inc_claim_reduction.input", claim_label: "sumcheck_claim", round_label: "sumcheck_poly", round_schedule: STAGE6_SUMCHECK_BATCH_0_ROUND_SCHEDULE }, ]; pub const STAGE6_SUMCHECK_DRIVER_0_ROUND_SCHEDULE: &[usize] = &[ - 10, - 16, + 14, + 18, ]; pub const STAGE6_SUMCHECK_DRIVERS: &[Stage6SumcheckDriverPlan] = &[ - Stage6SumcheckDriverPlan { symbol: "stage6.sumcheck", stage: "stage6", proof_slot: "stage6.sumcheck", kernel: None, relation: Some("jolt.stage6.batched"), batch: "stage6.batch", policy: "jolt_core_stage6_aligned", round_schedule: STAGE6_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 26, degree: 5 }, + Stage6SumcheckDriverPlan { symbol: "stage6.sumcheck", stage: "stage6", proof_slot: "stage6.sumcheck", kernel: None, relation: Some("jolt.stage6.batched"), batch: "stage6.batch", policy: "jolt_core_stage6_aligned", round_schedule: STAGE6_SUMCHECK_DRIVER_0_ROUND_SCHEDULE, claim_label: "sumcheck_claim", round_label: "sumcheck_poly", num_rounds: 32, degree: 5 }, ]; pub const STAGE6_SUMCHECK_INSTANCE_RESULTS: &[Stage6SumcheckInstanceResultPlan] = &[ - Stage6SumcheckInstanceResultPlan { symbol: "stage6.bytecode_read_raf.instance", source: "stage6.sumcheck", claim: "stage6.bytecode_read_raf.input", relation: "jolt.stage6.bytecode_read_raf", index: 0, point_arity: 26, num_rounds: 26, round_offset: 0, point_order: "bytecode_read_raf", degree: 4 }, - Stage6SumcheckInstanceResultPlan { symbol: "stage6.booleanity.instance", source: "stage6.sumcheck", claim: "stage6.booleanity.input", relation: "jolt.stage6.booleanity", index: 1, point_arity: 20, num_rounds: 20, round_offset: 6, point_order: "stage6_booleanity", degree: 3 }, - Stage6SumcheckInstanceResultPlan { symbol: "stage6.hamming_booleanity.instance", source: "stage6.sumcheck", claim: "stage6.hamming_booleanity.input", relation: "jolt.stage6.hamming_booleanity", index: 2, point_arity: 16, num_rounds: 16, round_offset: 10, point_order: "reverse", degree: 3 }, - Stage6SumcheckInstanceResultPlan { symbol: "stage6.ram_ra_virtual.instance", source: "stage6.sumcheck", claim: "stage6.ram_ra_virtual.input", relation: "jolt.stage6.ram_ra_virtual", index: 3, point_arity: 16, num_rounds: 16, round_offset: 10, point_order: "reverse", degree: 5 }, - Stage6SumcheckInstanceResultPlan { symbol: "stage6.instruction_ra_virtual.instance", source: "stage6.sumcheck", claim: "stage6.instruction_ra_virtual.input", relation: "jolt.stage6.instruction_ra_virtual", index: 4, point_arity: 16, num_rounds: 16, round_offset: 10, point_order: "reverse", degree: 5 }, - Stage6SumcheckInstanceResultPlan { symbol: "stage6.inc_claim_reduction.instance", source: "stage6.sumcheck", claim: "stage6.inc_claim_reduction.input", relation: "jolt.stage6.inc_claim_reduction", index: 5, point_arity: 16, num_rounds: 16, round_offset: 10, point_order: "reverse", degree: 2 }, + Stage6SumcheckInstanceResultPlan { symbol: "stage6.bytecode_read_raf.instance", source: "stage6.sumcheck", claim: "stage6.bytecode_read_raf.input", relation: "jolt.stage6.bytecode_read_raf", index: 0, point_arity: 32, num_rounds: 32, round_offset: 0, point_order: "bytecode_read_raf", degree: 5 }, + Stage6SumcheckInstanceResultPlan { symbol: "stage6.booleanity.instance", source: "stage6.sumcheck", claim: "stage6.booleanity.input", relation: "jolt.stage6.booleanity", index: 1, point_arity: 22, num_rounds: 22, round_offset: 10, point_order: "stage6_booleanity", degree: 3 }, + Stage6SumcheckInstanceResultPlan { symbol: "stage6.hamming_booleanity.instance", source: "stage6.sumcheck", claim: "stage6.hamming_booleanity.input", relation: "jolt.stage6.hamming_booleanity", index: 2, point_arity: 18, num_rounds: 18, round_offset: 14, point_order: "reverse", degree: 3 }, + Stage6SumcheckInstanceResultPlan { symbol: "stage6.ram_ra_virtual.instance", source: "stage6.sumcheck", claim: "stage6.ram_ra_virtual.input", relation: "jolt.stage6.ram_ra_virtual", index: 3, point_arity: 18, num_rounds: 18, round_offset: 14, point_order: "reverse", degree: 5 }, + Stage6SumcheckInstanceResultPlan { symbol: "stage6.instruction_ra_virtual.instance", source: "stage6.sumcheck", claim: "stage6.instruction_ra_virtual.input", relation: "jolt.stage6.instruction_ra_virtual", index: 4, point_arity: 18, num_rounds: 18, round_offset: 14, point_order: "reverse", degree: 5 }, + Stage6SumcheckInstanceResultPlan { symbol: "stage6.inc_claim_reduction.instance", source: "stage6.sumcheck", claim: "stage6.inc_claim_reduction.input", relation: "jolt.stage6.inc_claim_reduction", index: 5, point_arity: 18, num_rounds: 18, round_offset: 14, point_order: "reverse", degree: 2 }, ]; macro_rules! stage6_sumcheck_eval { @@ -391,42 +391,44 @@ macro_rules! stage6_sumcheck_eval { #[rustfmt::skip] pub const STAGE6_SUMCHECK_EVALS: &[Stage6SumcheckEvalPlan] = &[ - stage6_sumcheck_eval!("stage6.bytecode_read_raf.eval.BytecodeRa_0", "stage6.sumcheck", "stage6.bytecode_read_raf.eval.BytecodeRa_0", 0, "BytecodeRa_0"), stage6_sumcheck_eval!("stage6.bytecode_read_raf.eval.BytecodeRa_1", "stage6.sumcheck", "stage6.bytecode_read_raf.eval.BytecodeRa_1", 1, "BytecodeRa_1"), stage6_sumcheck_eval!("stage6.bytecode_read_raf.eval.BytecodeRa_2", "stage6.sumcheck", "stage6.bytecode_read_raf.eval.BytecodeRa_2", 2, "BytecodeRa_2"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_0", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_0", 0, "InstructionRa_0"), - stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_1", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_1", 1, "InstructionRa_1"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_2", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_2", 2, "InstructionRa_2"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_3", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_3", 3, "InstructionRa_3"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_4", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_4", 4, "InstructionRa_4"), - stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_5", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_5", 5, "InstructionRa_5"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_6", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_6", 6, "InstructionRa_6"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_7", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_7", 7, "InstructionRa_7"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_8", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_8", 8, "InstructionRa_8"), - stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_9", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_9", 9, "InstructionRa_9"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_10", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_10", 10, "InstructionRa_10"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_11", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_11", 11, "InstructionRa_11"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_12", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_12", 12, "InstructionRa_12"), - stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_13", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_13", 13, "InstructionRa_13"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_14", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_14", 14, "InstructionRa_14"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_15", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_15", 15, "InstructionRa_15"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_16", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_16", 16, "InstructionRa_16"), - stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_17", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_17", 17, "InstructionRa_17"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_18", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_18", 18, "InstructionRa_18"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_19", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_19", 19, "InstructionRa_19"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_20", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_20", 20, "InstructionRa_20"), - stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_21", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_21", 21, "InstructionRa_21"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_22", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_22", 22, "InstructionRa_22"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_23", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_23", 23, "InstructionRa_23"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_24", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_24", 24, "InstructionRa_24"), - stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_25", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_25", 25, "InstructionRa_25"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_26", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_26", 26, "InstructionRa_26"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_27", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_27", 27, "InstructionRa_27"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_28", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_28", 28, "InstructionRa_28"), - stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_29", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_29", 29, "InstructionRa_29"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_30", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_30", 30, "InstructionRa_30"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_31", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_31", 31, "InstructionRa_31"), stage6_sumcheck_eval!("stage6.booleanity.eval.BytecodeRa_0", "stage6.sumcheck", "stage6.booleanity.eval.BytecodeRa_0", 32, "BytecodeRa_0"), - stage6_sumcheck_eval!("stage6.booleanity.eval.BytecodeRa_1", "stage6.sumcheck", "stage6.booleanity.eval.BytecodeRa_1", 33, "BytecodeRa_1"), stage6_sumcheck_eval!("stage6.booleanity.eval.BytecodeRa_2", "stage6.sumcheck", "stage6.booleanity.eval.BytecodeRa_2", 34, "BytecodeRa_2"), stage6_sumcheck_eval!("stage6.booleanity.eval.RamRa_0", "stage6.sumcheck", "stage6.booleanity.eval.RamRa_0", 35, "RamRa_0"), stage6_sumcheck_eval!("stage6.booleanity.eval.RamRa_1", "stage6.sumcheck", "stage6.booleanity.eval.RamRa_1", 36, "RamRa_1"), - stage6_sumcheck_eval!("stage6.booleanity.eval.RamRa_2", "stage6.sumcheck", "stage6.booleanity.eval.RamRa_2", 37, "RamRa_2"), stage6_sumcheck_eval!("stage6.booleanity.eval.RamRa_3", "stage6.sumcheck", "stage6.booleanity.eval.RamRa_3", 38, "RamRa_3"), stage6_sumcheck_eval!("stage6.hamming_booleanity.eval.HammingWeight", "stage6.sumcheck", "stage6.hamming_booleanity.eval.HammingWeight", 0, "HammingWeight"), stage6_sumcheck_eval!("stage6.ram_ra_virtual.eval.RamRa_0", "stage6.sumcheck", "stage6.ram_ra_virtual.eval.RamRa_0", 0, "RamRa_0"), - stage6_sumcheck_eval!("stage6.ram_ra_virtual.eval.RamRa_1", "stage6.sumcheck", "stage6.ram_ra_virtual.eval.RamRa_1", 1, "RamRa_1"), stage6_sumcheck_eval!("stage6.ram_ra_virtual.eval.RamRa_2", "stage6.sumcheck", "stage6.ram_ra_virtual.eval.RamRa_2", 2, "RamRa_2"), stage6_sumcheck_eval!("stage6.ram_ra_virtual.eval.RamRa_3", "stage6.sumcheck", "stage6.ram_ra_virtual.eval.RamRa_3", 3, "RamRa_3"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_0", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_0", 0, "InstructionRa_0"), - stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_1", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_1", 1, "InstructionRa_1"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_2", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_2", 2, "InstructionRa_2"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_3", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_3", 3, "InstructionRa_3"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_4", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_4", 4, "InstructionRa_4"), - stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_5", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_5", 5, "InstructionRa_5"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_6", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_6", 6, "InstructionRa_6"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_7", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_7", 7, "InstructionRa_7"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_8", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_8", 8, "InstructionRa_8"), - stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_9", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_9", 9, "InstructionRa_9"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_10", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_10", 10, "InstructionRa_10"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_11", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_11", 11, "InstructionRa_11"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_12", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_12", 12, "InstructionRa_12"), - stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_13", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_13", 13, "InstructionRa_13"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_14", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_14", 14, "InstructionRa_14"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_15", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_15", 15, "InstructionRa_15"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_16", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_16", 16, "InstructionRa_16"), - stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_17", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_17", 17, "InstructionRa_17"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_18", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_18", 18, "InstructionRa_18"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_19", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_19", 19, "InstructionRa_19"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_20", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_20", 20, "InstructionRa_20"), - stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_21", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_21", 21, "InstructionRa_21"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_22", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_22", 22, "InstructionRa_22"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_23", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_23", 23, "InstructionRa_23"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_24", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_24", 24, "InstructionRa_24"), - stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_25", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_25", 25, "InstructionRa_25"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_26", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_26", 26, "InstructionRa_26"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_27", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_27", 27, "InstructionRa_27"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_28", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_28", 28, "InstructionRa_28"), - stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_29", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_29", 29, "InstructionRa_29"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_30", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_30", 30, "InstructionRa_30"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_31", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_31", 31, "InstructionRa_31"), stage6_sumcheck_eval!("stage6.inc_claim_reduction.eval.RamInc", "stage6.sumcheck", "stage6.inc_claim_reduction.eval.RamInc", 0, "RamInc"), - stage6_sumcheck_eval!("stage6.inc_claim_reduction.eval.RdInc", "stage6.sumcheck", "stage6.inc_claim_reduction.eval.RdInc", 1, "RdInc"), + stage6_sumcheck_eval!("stage6.bytecode_read_raf.eval.BytecodeRa_0", "stage6.sumcheck", "stage6.bytecode_read_raf.eval.BytecodeRa_0", 0, "BytecodeRa_0"), stage6_sumcheck_eval!("stage6.bytecode_read_raf.eval.BytecodeRa_1", "stage6.sumcheck", "stage6.bytecode_read_raf.eval.BytecodeRa_1", 1, "BytecodeRa_1"), stage6_sumcheck_eval!("stage6.bytecode_read_raf.eval.BytecodeRa_2", "stage6.sumcheck", "stage6.bytecode_read_raf.eval.BytecodeRa_2", 2, "BytecodeRa_2"), stage6_sumcheck_eval!("stage6.bytecode_read_raf.eval.BytecodeRa_3", "stage6.sumcheck", "stage6.bytecode_read_raf.eval.BytecodeRa_3", 3, "BytecodeRa_3"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_0", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_0", 0, "InstructionRa_0"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_1", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_1", 1, "InstructionRa_1"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_2", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_2", 2, "InstructionRa_2"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_3", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_3", 3, "InstructionRa_3"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_4", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_4", 4, "InstructionRa_4"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_5", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_5", 5, "InstructionRa_5"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_6", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_6", 6, "InstructionRa_6"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_7", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_7", 7, "InstructionRa_7"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_8", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_8", 8, "InstructionRa_8"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_9", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_9", 9, "InstructionRa_9"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_10", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_10", 10, "InstructionRa_10"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_11", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_11", 11, "InstructionRa_11"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_12", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_12", 12, "InstructionRa_12"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_13", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_13", 13, "InstructionRa_13"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_14", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_14", 14, "InstructionRa_14"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_15", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_15", 15, "InstructionRa_15"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_16", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_16", 16, "InstructionRa_16"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_17", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_17", 17, "InstructionRa_17"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_18", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_18", 18, "InstructionRa_18"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_19", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_19", 19, "InstructionRa_19"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_20", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_20", 20, "InstructionRa_20"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_21", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_21", 21, "InstructionRa_21"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_22", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_22", 22, "InstructionRa_22"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_23", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_23", 23, "InstructionRa_23"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_24", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_24", 24, "InstructionRa_24"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_25", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_25", 25, "InstructionRa_25"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_26", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_26", 26, "InstructionRa_26"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_27", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_27", 27, "InstructionRa_27"), + stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_28", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_28", 28, "InstructionRa_28"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_29", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_29", 29, "InstructionRa_29"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_30", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_30", 30, "InstructionRa_30"), stage6_sumcheck_eval!("stage6.booleanity.eval.InstructionRa_31", "stage6.sumcheck", "stage6.booleanity.eval.InstructionRa_31", 31, "InstructionRa_31"), + stage6_sumcheck_eval!("stage6.booleanity.eval.BytecodeRa_0", "stage6.sumcheck", "stage6.booleanity.eval.BytecodeRa_0", 32, "BytecodeRa_0"), stage6_sumcheck_eval!("stage6.booleanity.eval.BytecodeRa_1", "stage6.sumcheck", "stage6.booleanity.eval.BytecodeRa_1", 33, "BytecodeRa_1"), stage6_sumcheck_eval!("stage6.booleanity.eval.BytecodeRa_2", "stage6.sumcheck", "stage6.booleanity.eval.BytecodeRa_2", 34, "BytecodeRa_2"), stage6_sumcheck_eval!("stage6.booleanity.eval.BytecodeRa_3", "stage6.sumcheck", "stage6.booleanity.eval.BytecodeRa_3", 35, "BytecodeRa_3"), + stage6_sumcheck_eval!("stage6.booleanity.eval.RamRa_0", "stage6.sumcheck", "stage6.booleanity.eval.RamRa_0", 36, "RamRa_0"), stage6_sumcheck_eval!("stage6.booleanity.eval.RamRa_1", "stage6.sumcheck", "stage6.booleanity.eval.RamRa_1", 37, "RamRa_1"), stage6_sumcheck_eval!("stage6.booleanity.eval.RamRa_2", "stage6.sumcheck", "stage6.booleanity.eval.RamRa_2", 38, "RamRa_2"), stage6_sumcheck_eval!("stage6.booleanity.eval.RamRa_3", "stage6.sumcheck", "stage6.booleanity.eval.RamRa_3", 39, "RamRa_3"), + stage6_sumcheck_eval!("stage6.hamming_booleanity.eval.HammingWeight", "stage6.sumcheck", "stage6.hamming_booleanity.eval.HammingWeight", 0, "HammingWeight"), stage6_sumcheck_eval!("stage6.ram_ra_virtual.eval.RamRa_0", "stage6.sumcheck", "stage6.ram_ra_virtual.eval.RamRa_0", 0, "RamRa_0"), stage6_sumcheck_eval!("stage6.ram_ra_virtual.eval.RamRa_1", "stage6.sumcheck", "stage6.ram_ra_virtual.eval.RamRa_1", 1, "RamRa_1"), stage6_sumcheck_eval!("stage6.ram_ra_virtual.eval.RamRa_2", "stage6.sumcheck", "stage6.ram_ra_virtual.eval.RamRa_2", 2, "RamRa_2"), + stage6_sumcheck_eval!("stage6.ram_ra_virtual.eval.RamRa_3", "stage6.sumcheck", "stage6.ram_ra_virtual.eval.RamRa_3", 3, "RamRa_3"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_0", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_0", 0, "InstructionRa_0"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_1", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_1", 1, "InstructionRa_1"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_2", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_2", 2, "InstructionRa_2"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_3", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_3", 3, "InstructionRa_3"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_4", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_4", 4, "InstructionRa_4"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_5", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_5", 5, "InstructionRa_5"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_6", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_6", 6, "InstructionRa_6"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_7", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_7", 7, "InstructionRa_7"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_8", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_8", 8, "InstructionRa_8"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_9", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_9", 9, "InstructionRa_9"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_10", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_10", 10, "InstructionRa_10"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_11", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_11", 11, "InstructionRa_11"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_12", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_12", 12, "InstructionRa_12"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_13", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_13", 13, "InstructionRa_13"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_14", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_14", 14, "InstructionRa_14"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_15", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_15", 15, "InstructionRa_15"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_16", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_16", 16, "InstructionRa_16"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_17", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_17", 17, "InstructionRa_17"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_18", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_18", 18, "InstructionRa_18"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_19", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_19", 19, "InstructionRa_19"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_20", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_20", 20, "InstructionRa_20"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_21", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_21", 21, "InstructionRa_21"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_22", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_22", 22, "InstructionRa_22"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_23", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_23", 23, "InstructionRa_23"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_24", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_24", 24, "InstructionRa_24"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_25", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_25", 25, "InstructionRa_25"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_26", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_26", 26, "InstructionRa_26"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_27", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_27", 27, "InstructionRa_27"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_28", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_28", 28, "InstructionRa_28"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_29", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_29", 29, "InstructionRa_29"), stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_30", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_30", 30, "InstructionRa_30"), + stage6_sumcheck_eval!("stage6.instruction_ra_virtual.eval.InstructionRa_31", "stage6.sumcheck", "stage6.instruction_ra_virtual.eval.InstructionRa_31", 31, "InstructionRa_31"), stage6_sumcheck_eval!("stage6.inc_claim_reduction.eval.RamInc", "stage6.sumcheck", "stage6.inc_claim_reduction.eval.RamInc", 0, "RamInc"), stage6_sumcheck_eval!("stage6.inc_claim_reduction.eval.RdInc", "stage6.sumcheck", "stage6.inc_claim_reduction.eval.RdInc", 1, "RdInc"), ]; pub const STAGE6_POINT_ZEROS: &[Stage6PointZeroPlan] = &[ Stage6PointZeroPlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_0.address.zero_pad", field: "bn254_fr", arity: 2 }, + Stage6PointZeroPlan { symbol: "stage6.ram_ra_virtual.point.RamRa_0.address.zero_pad", field: "bn254_fr", arity: 2 }, ]; pub const STAGE6_POINT_SLICES: &[Stage6PointSlicePlan] = &[ - Stage6PointSlicePlan { symbol: "stage6.bytecode_read_raf.point.Cycle", source: "stage6.bytecode_read_raf.instance", offset: 10, length: 16, input: "stage6.bytecode_read_raf.instance" }, + Stage6PointSlicePlan { symbol: "stage6.bytecode_read_raf.point.Cycle", source: "stage6.bytecode_read_raf.instance", offset: 14, length: 18, input: "stage6.bytecode_read_raf.instance" }, Stage6PointSlicePlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_0.address.source", source: "stage6.bytecode_read_raf.instance", offset: 0, length: 2, input: "stage6.bytecode_read_raf.instance" }, Stage6PointSlicePlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_1.address", source: "stage6.bytecode_read_raf.instance", offset: 2, length: 4, input: "stage6.bytecode_read_raf.instance" }, Stage6PointSlicePlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_2.address", source: "stage6.bytecode_read_raf.instance", offset: 6, length: 4, input: "stage6.bytecode_read_raf.instance" }, - Stage6PointSlicePlan { symbol: "stage6.ram_ra_virtual.point.RamRa_0.address", source: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", offset: 0, length: 4, input: "stage6.input.stage5.ram_ra_claim_reduction.RamRa" }, - Stage6PointSlicePlan { symbol: "stage6.ram_ra_virtual.point.RamRa_1.address", source: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", offset: 4, length: 4, input: "stage6.input.stage5.ram_ra_claim_reduction.RamRa" }, - Stage6PointSlicePlan { symbol: "stage6.ram_ra_virtual.point.RamRa_2.address", source: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", offset: 8, length: 4, input: "stage6.input.stage5.ram_ra_claim_reduction.RamRa" }, - Stage6PointSlicePlan { symbol: "stage6.ram_ra_virtual.point.RamRa_3.address", source: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", offset: 12, length: 4, input: "stage6.input.stage5.ram_ra_claim_reduction.RamRa" }, + Stage6PointSlicePlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_3.address", source: "stage6.bytecode_read_raf.instance", offset: 10, length: 4, input: "stage6.bytecode_read_raf.instance" }, + Stage6PointSlicePlan { symbol: "stage6.ram_ra_virtual.point.RamRa_0.address.source", source: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", offset: 0, length: 2, input: "stage6.input.stage5.ram_ra_claim_reduction.RamRa" }, + Stage6PointSlicePlan { symbol: "stage6.ram_ra_virtual.point.RamRa_1.address", source: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", offset: 2, length: 4, input: "stage6.input.stage5.ram_ra_claim_reduction.RamRa" }, + Stage6PointSlicePlan { symbol: "stage6.ram_ra_virtual.point.RamRa_2.address", source: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", offset: 6, length: 4, input: "stage6.input.stage5.ram_ra_claim_reduction.RamRa" }, + Stage6PointSlicePlan { symbol: "stage6.ram_ra_virtual.point.RamRa_3.address", source: "stage6.input.stage5.ram_ra_claim_reduction.RamRa", offset: 10, length: 4, input: "stage6.input.stage5.ram_ra_claim_reduction.RamRa" }, Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_0.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", offset: 0, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_0" }, Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_1.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", offset: 4, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_0" }, Stage6PointSlicePlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_2.address", source: "stage6.input.stage5.instruction_read_raf.InstructionRa_0", offset: 8, length: 4, input: "stage6.input.stage5.instruction_read_raf.InstructionRa_0" }, @@ -463,128 +465,132 @@ pub const STAGE6_POINT_SLICES: &[Stage6PointSlicePlan] = &[ pub const STAGE6_POINT_CONCATS: &[Stage6PointConcatPlan] = &[ Stage6PointConcatPlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_0.address", layout: "left_zero_padded_address_chunk", arity: 4, inputs: "stage6.bytecode_read_raf.point.BytecodeRa_0.address.zero_pad|stage6.bytecode_read_raf.point.BytecodeRa_0.address.source" }, - Stage6PointConcatPlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_0", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.bytecode_read_raf.point.BytecodeRa_0.address|stage6.bytecode_read_raf.point.Cycle" }, - Stage6PointConcatPlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_1", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.bytecode_read_raf.point.BytecodeRa_1.address|stage6.bytecode_read_raf.point.Cycle" }, - Stage6PointConcatPlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_2", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.bytecode_read_raf.point.BytecodeRa_2.address|stage6.bytecode_read_raf.point.Cycle" }, - Stage6PointConcatPlan { symbol: "stage6.ram_ra_virtual.point.RamRa_0", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.ram_ra_virtual.point.RamRa_0.address|stage6.ram_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.ram_ra_virtual.point.RamRa_1", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.ram_ra_virtual.point.RamRa_1.address|stage6.ram_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.ram_ra_virtual.point.RamRa_2", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.ram_ra_virtual.point.RamRa_2.address|stage6.ram_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.ram_ra_virtual.point.RamRa_3", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.ram_ra_virtual.point.RamRa_3.address|stage6.ram_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_0", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_0.address|stage6.instruction_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_1", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_1.address|stage6.instruction_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_2", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_2.address|stage6.instruction_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_3", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_3.address|stage6.instruction_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_4", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_4.address|stage6.instruction_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_5", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_5.address|stage6.instruction_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_6", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_6.address|stage6.instruction_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_7", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_7.address|stage6.instruction_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_8", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_8.address|stage6.instruction_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_9", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_9.address|stage6.instruction_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_10", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_10.address|stage6.instruction_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_11", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_11.address|stage6.instruction_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_12", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_12.address|stage6.instruction_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_13", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_13.address|stage6.instruction_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_14", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_14.address|stage6.instruction_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_15", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_15.address|stage6.instruction_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_16", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_16.address|stage6.instruction_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_17", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_17.address|stage6.instruction_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_18", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_18.address|stage6.instruction_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_19", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_19.address|stage6.instruction_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_20", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_20.address|stage6.instruction_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_21", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_21.address|stage6.instruction_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_22", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_22.address|stage6.instruction_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_23", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_23.address|stage6.instruction_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_24", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_24.address|stage6.instruction_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_25", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_25.address|stage6.instruction_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_26", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_26.address|stage6.instruction_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_27", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_27.address|stage6.instruction_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_28", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_28.address|stage6.instruction_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_29", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_29.address|stage6.instruction_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_30", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_30.address|stage6.instruction_ra_virtual.instance" }, - Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_31", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_31.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_0", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.bytecode_read_raf.point.BytecodeRa_0.address|stage6.bytecode_read_raf.point.Cycle" }, + Stage6PointConcatPlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_1", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.bytecode_read_raf.point.BytecodeRa_1.address|stage6.bytecode_read_raf.point.Cycle" }, + Stage6PointConcatPlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_2", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.bytecode_read_raf.point.BytecodeRa_2.address|stage6.bytecode_read_raf.point.Cycle" }, + Stage6PointConcatPlan { symbol: "stage6.bytecode_read_raf.point.BytecodeRa_3", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.bytecode_read_raf.point.BytecodeRa_3.address|stage6.bytecode_read_raf.point.Cycle" }, + Stage6PointConcatPlan { symbol: "stage6.ram_ra_virtual.point.RamRa_0.address", layout: "left_zero_padded_address_chunk", arity: 4, inputs: "stage6.ram_ra_virtual.point.RamRa_0.address.zero_pad|stage6.ram_ra_virtual.point.RamRa_0.address.source" }, + Stage6PointConcatPlan { symbol: "stage6.ram_ra_virtual.point.RamRa_0", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.ram_ra_virtual.point.RamRa_0.address|stage6.ram_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.ram_ra_virtual.point.RamRa_1", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.ram_ra_virtual.point.RamRa_1.address|stage6.ram_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.ram_ra_virtual.point.RamRa_2", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.ram_ra_virtual.point.RamRa_2.address|stage6.ram_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.ram_ra_virtual.point.RamRa_3", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.ram_ra_virtual.point.RamRa_3.address|stage6.ram_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_0", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_0.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_1", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_1.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_2", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_2.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_3", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_3.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_4", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_4.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_5", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_5.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_6", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_6.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_7", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_7.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_8", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_8.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_9", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_9.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_10", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_10.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_11", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_11.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_12", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_12.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_13", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_13.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_14", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_14.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_15", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_15.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_16", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_16.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_17", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_17.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_18", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_18.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_19", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_19.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_20", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_20.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_21", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_21.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_22", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_22.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_23", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_23.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_24", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_24.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_25", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_25.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_26", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_26.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_27", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_27.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_28", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_28.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_29", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_29.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_30", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_30.address|stage6.instruction_ra_virtual.instance" }, + Stage6PointConcatPlan { symbol: "stage6.instruction_ra_virtual.point.InstructionRa_31", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage6.instruction_ra_virtual.point.InstructionRa_31.address|stage6.instruction_ra_virtual.instance" }, ]; pub const STAGE6_OPENING_CLAIMS: &[Stage6OpeningClaimPlan] = &[ - Stage6OpeningClaimPlan { symbol: "stage6.bytecode_read_raf.opening.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.bytecode_read_raf.point.BytecodeRa_0", eval_source: "stage6.bytecode_read_raf.eval.BytecodeRa_0" }, - Stage6OpeningClaimPlan { symbol: "stage6.bytecode_read_raf.opening.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.bytecode_read_raf.point.BytecodeRa_1", eval_source: "stage6.bytecode_read_raf.eval.BytecodeRa_1" }, - Stage6OpeningClaimPlan { symbol: "stage6.bytecode_read_raf.opening.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.bytecode_read_raf.point.BytecodeRa_2", eval_source: "stage6.bytecode_read_raf.eval.BytecodeRa_2" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_0" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_1" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_2" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_3" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_4" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_5" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_6" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_7" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_8" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_9" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_10" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_11" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_12" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_13" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_14" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_15" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_16" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_17" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_18" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_19" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_20" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_21" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_22" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_23" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_24" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_25" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_26" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_27" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_28" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_29" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_30" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_31" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.BytecodeRa_0" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.BytecodeRa_1" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.BytecodeRa_2" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.RamRa_0" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.RamRa_1" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.RamRa_2" }, - Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.RamRa_3" }, - Stage6OpeningClaimPlan { symbol: "stage6.hamming_booleanity.opening.HammingWeight", oracle: "HammingWeight", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual", point_source: "stage6.hamming_booleanity.instance", eval_source: "stage6.hamming_booleanity.eval.HammingWeight" }, - Stage6OpeningClaimPlan { symbol: "stage6.ram_ra_virtual.opening.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.ram_ra_virtual.point.RamRa_0", eval_source: "stage6.ram_ra_virtual.eval.RamRa_0" }, - Stage6OpeningClaimPlan { symbol: "stage6.ram_ra_virtual.opening.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.ram_ra_virtual.point.RamRa_1", eval_source: "stage6.ram_ra_virtual.eval.RamRa_1" }, - Stage6OpeningClaimPlan { symbol: "stage6.ram_ra_virtual.opening.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.ram_ra_virtual.point.RamRa_2", eval_source: "stage6.ram_ra_virtual.eval.RamRa_2" }, - Stage6OpeningClaimPlan { symbol: "stage6.ram_ra_virtual.opening.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.ram_ra_virtual.point.RamRa_3", eval_source: "stage6.ram_ra_virtual.eval.RamRa_3" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_0", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_0" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_1", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_1" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_2", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_2" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_3", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_3" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_4", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_4" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_5", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_5" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_6", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_6" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_7", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_7" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_8", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_8" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_9", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_9" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_10", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_10" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_11", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_11" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_12", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_12" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_13", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_13" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_14", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_14" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_15", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_15" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_16", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_16" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_17", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_17" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_18", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_18" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_19", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_19" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_20", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_20" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_21", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_21" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_22", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_22" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_23", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_23" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_24", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_24" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_25", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_25" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_26", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_26" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_27", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_27" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_28", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_28" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_29", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_29" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_30", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_30" }, - Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_31", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_31" }, - Stage6OpeningClaimPlan { symbol: "stage6.inc_claim_reduction.opening.RamInc", oracle: "RamInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed", point_source: "stage6.inc_claim_reduction.instance", eval_source: "stage6.inc_claim_reduction.eval.RamInc" }, - Stage6OpeningClaimPlan { symbol: "stage6.inc_claim_reduction.opening.RdInc", oracle: "RdInc", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "committed", point_source: "stage6.inc_claim_reduction.instance", eval_source: "stage6.inc_claim_reduction.eval.RdInc" }, + Stage6OpeningClaimPlan { symbol: "stage6.bytecode_read_raf.opening.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.bytecode_read_raf.point.BytecodeRa_0", eval_source: "stage6.bytecode_read_raf.eval.BytecodeRa_0" }, + Stage6OpeningClaimPlan { symbol: "stage6.bytecode_read_raf.opening.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.bytecode_read_raf.point.BytecodeRa_1", eval_source: "stage6.bytecode_read_raf.eval.BytecodeRa_1" }, + Stage6OpeningClaimPlan { symbol: "stage6.bytecode_read_raf.opening.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.bytecode_read_raf.point.BytecodeRa_2", eval_source: "stage6.bytecode_read_raf.eval.BytecodeRa_2" }, + Stage6OpeningClaimPlan { symbol: "stage6.bytecode_read_raf.opening.BytecodeRa_3", oracle: "BytecodeRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.bytecode_read_raf.point.BytecodeRa_3", eval_source: "stage6.bytecode_read_raf.eval.BytecodeRa_3" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_0" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_1" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_2" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_3" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_4" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_5" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_6" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_7" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_8" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_9" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_10" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_11" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_12" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_13" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_14" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_15" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_16" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_17" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_18" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_19" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_20" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_21" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_22" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_23" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_24" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_25" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_26" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_27" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_28" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_29" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_30" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.InstructionRa_31" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.BytecodeRa_0" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.BytecodeRa_1" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.BytecodeRa_2" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.BytecodeRa_3", oracle: "BytecodeRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.BytecodeRa_3" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.RamRa_0" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.RamRa_1" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.RamRa_2" }, + Stage6OpeningClaimPlan { symbol: "stage6.booleanity.opening.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.booleanity.instance", eval_source: "stage6.booleanity.eval.RamRa_3" }, + Stage6OpeningClaimPlan { symbol: "stage6.hamming_booleanity.opening.HammingWeight", oracle: "HammingWeight", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual", point_source: "stage6.hamming_booleanity.instance", eval_source: "stage6.hamming_booleanity.eval.HammingWeight" }, + Stage6OpeningClaimPlan { symbol: "stage6.ram_ra_virtual.opening.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.ram_ra_virtual.point.RamRa_0", eval_source: "stage6.ram_ra_virtual.eval.RamRa_0" }, + Stage6OpeningClaimPlan { symbol: "stage6.ram_ra_virtual.opening.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.ram_ra_virtual.point.RamRa_1", eval_source: "stage6.ram_ra_virtual.eval.RamRa_1" }, + Stage6OpeningClaimPlan { symbol: "stage6.ram_ra_virtual.opening.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.ram_ra_virtual.point.RamRa_2", eval_source: "stage6.ram_ra_virtual.eval.RamRa_2" }, + Stage6OpeningClaimPlan { symbol: "stage6.ram_ra_virtual.opening.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.ram_ra_virtual.point.RamRa_3", eval_source: "stage6.ram_ra_virtual.eval.RamRa_3" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_0", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_0" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_1", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_1" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_2", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_2" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_3", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_3" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_4", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_4" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_5", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_5" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_6", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_6" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_7", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_7" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_8", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_8" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_9", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_9" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_10", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_10" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_11", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_11" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_12", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_12" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_13", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_13" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_14", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_14" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_15", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_15" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_16", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_16" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_17", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_17" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_18", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_18" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_19", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_19" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_20", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_20" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_21", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_21" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_22", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_22" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_23", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_23" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_24", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_24" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_25", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_25" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_26", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_26" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_27", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_27" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_28", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_28" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_29", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_29" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_30", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_30" }, + Stage6OpeningClaimPlan { symbol: "stage6.instruction_ra_virtual.opening.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage6.instruction_ra_virtual.point.InstructionRa_31", eval_source: "stage6.instruction_ra_virtual.eval.InstructionRa_31" }, + Stage6OpeningClaimPlan { symbol: "stage6.inc_claim_reduction.opening.RamInc", oracle: "RamInc", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "committed", point_source: "stage6.inc_claim_reduction.instance", eval_source: "stage6.inc_claim_reduction.eval.RamInc" }, + Stage6OpeningClaimPlan { symbol: "stage6.inc_claim_reduction.opening.RdInc", oracle: "RdInc", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "committed", point_source: "stage6.inc_claim_reduction.instance", eval_source: "stage6.inc_claim_reduction.eval.RdInc" }, ]; pub const STAGE6_OPENING_EQUALITIES: &[Stage6OpeningClaimEqualityPlan] = &[ @@ -592,7 +598,7 @@ pub const STAGE6_OPENING_EQUALITIES: &[Stage6OpeningClaimEqualityPlan] = &[ ]; pub const STAGE6_OPENING_BATCHES: &[Stage6OpeningBatchPlan] = &[ - Stage6OpeningBatchPlan { symbol: "stage6.openings", stage: "stage6", proof_slot: "stage6.openings", policy: "jolt_stage6_output_order", count: 81, ordered_claims: "stage6.bytecode_read_raf.opening.BytecodeRa_0|stage6.bytecode_read_raf.opening.BytecodeRa_1|stage6.bytecode_read_raf.opening.BytecodeRa_2|stage6.booleanity.opening.InstructionRa_0|stage6.booleanity.opening.InstructionRa_1|stage6.booleanity.opening.InstructionRa_2|stage6.booleanity.opening.InstructionRa_3|stage6.booleanity.opening.InstructionRa_4|stage6.booleanity.opening.InstructionRa_5|stage6.booleanity.opening.InstructionRa_6|stage6.booleanity.opening.InstructionRa_7|stage6.booleanity.opening.InstructionRa_8|stage6.booleanity.opening.InstructionRa_9|stage6.booleanity.opening.InstructionRa_10|stage6.booleanity.opening.InstructionRa_11|stage6.booleanity.opening.InstructionRa_12|stage6.booleanity.opening.InstructionRa_13|stage6.booleanity.opening.InstructionRa_14|stage6.booleanity.opening.InstructionRa_15|stage6.booleanity.opening.InstructionRa_16|stage6.booleanity.opening.InstructionRa_17|stage6.booleanity.opening.InstructionRa_18|stage6.booleanity.opening.InstructionRa_19|stage6.booleanity.opening.InstructionRa_20|stage6.booleanity.opening.InstructionRa_21|stage6.booleanity.opening.InstructionRa_22|stage6.booleanity.opening.InstructionRa_23|stage6.booleanity.opening.InstructionRa_24|stage6.booleanity.opening.InstructionRa_25|stage6.booleanity.opening.InstructionRa_26|stage6.booleanity.opening.InstructionRa_27|stage6.booleanity.opening.InstructionRa_28|stage6.booleanity.opening.InstructionRa_29|stage6.booleanity.opening.InstructionRa_30|stage6.booleanity.opening.InstructionRa_31|stage6.booleanity.opening.BytecodeRa_0|stage6.booleanity.opening.BytecodeRa_1|stage6.booleanity.opening.BytecodeRa_2|stage6.booleanity.opening.RamRa_0|stage6.booleanity.opening.RamRa_1|stage6.booleanity.opening.RamRa_2|stage6.booleanity.opening.RamRa_3|stage6.hamming_booleanity.opening.HammingWeight|stage6.ram_ra_virtual.opening.RamRa_0|stage6.ram_ra_virtual.opening.RamRa_1|stage6.ram_ra_virtual.opening.RamRa_2|stage6.ram_ra_virtual.opening.RamRa_3|stage6.instruction_ra_virtual.opening.InstructionRa_0|stage6.instruction_ra_virtual.opening.InstructionRa_1|stage6.instruction_ra_virtual.opening.InstructionRa_2|stage6.instruction_ra_virtual.opening.InstructionRa_3|stage6.instruction_ra_virtual.opening.InstructionRa_4|stage6.instruction_ra_virtual.opening.InstructionRa_5|stage6.instruction_ra_virtual.opening.InstructionRa_6|stage6.instruction_ra_virtual.opening.InstructionRa_7|stage6.instruction_ra_virtual.opening.InstructionRa_8|stage6.instruction_ra_virtual.opening.InstructionRa_9|stage6.instruction_ra_virtual.opening.InstructionRa_10|stage6.instruction_ra_virtual.opening.InstructionRa_11|stage6.instruction_ra_virtual.opening.InstructionRa_12|stage6.instruction_ra_virtual.opening.InstructionRa_13|stage6.instruction_ra_virtual.opening.InstructionRa_14|stage6.instruction_ra_virtual.opening.InstructionRa_15|stage6.instruction_ra_virtual.opening.InstructionRa_16|stage6.instruction_ra_virtual.opening.InstructionRa_17|stage6.instruction_ra_virtual.opening.InstructionRa_18|stage6.instruction_ra_virtual.opening.InstructionRa_19|stage6.instruction_ra_virtual.opening.InstructionRa_20|stage6.instruction_ra_virtual.opening.InstructionRa_21|stage6.instruction_ra_virtual.opening.InstructionRa_22|stage6.instruction_ra_virtual.opening.InstructionRa_23|stage6.instruction_ra_virtual.opening.InstructionRa_24|stage6.instruction_ra_virtual.opening.InstructionRa_25|stage6.instruction_ra_virtual.opening.InstructionRa_26|stage6.instruction_ra_virtual.opening.InstructionRa_27|stage6.instruction_ra_virtual.opening.InstructionRa_28|stage6.instruction_ra_virtual.opening.InstructionRa_29|stage6.instruction_ra_virtual.opening.InstructionRa_30|stage6.instruction_ra_virtual.opening.InstructionRa_31|stage6.inc_claim_reduction.opening.RamInc|stage6.inc_claim_reduction.opening.RdInc", claim_operands: "stage6.bytecode_read_raf.opening.BytecodeRa_0|stage6.bytecode_read_raf.opening.BytecodeRa_1|stage6.bytecode_read_raf.opening.BytecodeRa_2|stage6.booleanity.opening.InstructionRa_0|stage6.booleanity.opening.InstructionRa_1|stage6.booleanity.opening.InstructionRa_2|stage6.booleanity.opening.InstructionRa_3|stage6.booleanity.opening.InstructionRa_4|stage6.booleanity.opening.InstructionRa_5|stage6.booleanity.opening.InstructionRa_6|stage6.booleanity.opening.InstructionRa_7|stage6.booleanity.opening.InstructionRa_8|stage6.booleanity.opening.InstructionRa_9|stage6.booleanity.opening.InstructionRa_10|stage6.booleanity.opening.InstructionRa_11|stage6.booleanity.opening.InstructionRa_12|stage6.booleanity.opening.InstructionRa_13|stage6.booleanity.opening.InstructionRa_14|stage6.booleanity.opening.InstructionRa_15|stage6.booleanity.opening.InstructionRa_16|stage6.booleanity.opening.InstructionRa_17|stage6.booleanity.opening.InstructionRa_18|stage6.booleanity.opening.InstructionRa_19|stage6.booleanity.opening.InstructionRa_20|stage6.booleanity.opening.InstructionRa_21|stage6.booleanity.opening.InstructionRa_22|stage6.booleanity.opening.InstructionRa_23|stage6.booleanity.opening.InstructionRa_24|stage6.booleanity.opening.InstructionRa_25|stage6.booleanity.opening.InstructionRa_26|stage6.booleanity.opening.InstructionRa_27|stage6.booleanity.opening.InstructionRa_28|stage6.booleanity.opening.InstructionRa_29|stage6.booleanity.opening.InstructionRa_30|stage6.booleanity.opening.InstructionRa_31|stage6.booleanity.opening.BytecodeRa_0|stage6.booleanity.opening.BytecodeRa_1|stage6.booleanity.opening.BytecodeRa_2|stage6.booleanity.opening.RamRa_0|stage6.booleanity.opening.RamRa_1|stage6.booleanity.opening.RamRa_2|stage6.booleanity.opening.RamRa_3|stage6.hamming_booleanity.opening.HammingWeight|stage6.ram_ra_virtual.opening.RamRa_0|stage6.ram_ra_virtual.opening.RamRa_1|stage6.ram_ra_virtual.opening.RamRa_2|stage6.ram_ra_virtual.opening.RamRa_3|stage6.instruction_ra_virtual.opening.InstructionRa_0|stage6.instruction_ra_virtual.opening.InstructionRa_1|stage6.instruction_ra_virtual.opening.InstructionRa_2|stage6.instruction_ra_virtual.opening.InstructionRa_3|stage6.instruction_ra_virtual.opening.InstructionRa_4|stage6.instruction_ra_virtual.opening.InstructionRa_5|stage6.instruction_ra_virtual.opening.InstructionRa_6|stage6.instruction_ra_virtual.opening.InstructionRa_7|stage6.instruction_ra_virtual.opening.InstructionRa_8|stage6.instruction_ra_virtual.opening.InstructionRa_9|stage6.instruction_ra_virtual.opening.InstructionRa_10|stage6.instruction_ra_virtual.opening.InstructionRa_11|stage6.instruction_ra_virtual.opening.InstructionRa_12|stage6.instruction_ra_virtual.opening.InstructionRa_13|stage6.instruction_ra_virtual.opening.InstructionRa_14|stage6.instruction_ra_virtual.opening.InstructionRa_15|stage6.instruction_ra_virtual.opening.InstructionRa_16|stage6.instruction_ra_virtual.opening.InstructionRa_17|stage6.instruction_ra_virtual.opening.InstructionRa_18|stage6.instruction_ra_virtual.opening.InstructionRa_19|stage6.instruction_ra_virtual.opening.InstructionRa_20|stage6.instruction_ra_virtual.opening.InstructionRa_21|stage6.instruction_ra_virtual.opening.InstructionRa_22|stage6.instruction_ra_virtual.opening.InstructionRa_23|stage6.instruction_ra_virtual.opening.InstructionRa_24|stage6.instruction_ra_virtual.opening.InstructionRa_25|stage6.instruction_ra_virtual.opening.InstructionRa_26|stage6.instruction_ra_virtual.opening.InstructionRa_27|stage6.instruction_ra_virtual.opening.InstructionRa_28|stage6.instruction_ra_virtual.opening.InstructionRa_29|stage6.instruction_ra_virtual.opening.InstructionRa_30|stage6.instruction_ra_virtual.opening.InstructionRa_31|stage6.inc_claim_reduction.opening.RamInc|stage6.inc_claim_reduction.opening.RdInc" }, + Stage6OpeningBatchPlan { symbol: "stage6.openings", stage: "stage6", proof_slot: "stage6.openings", policy: "jolt_stage6_output_order", count: 83, ordered_claims: "stage6.bytecode_read_raf.opening.BytecodeRa_0|stage6.bytecode_read_raf.opening.BytecodeRa_1|stage6.bytecode_read_raf.opening.BytecodeRa_2|stage6.bytecode_read_raf.opening.BytecodeRa_3|stage6.booleanity.opening.InstructionRa_0|stage6.booleanity.opening.InstructionRa_1|stage6.booleanity.opening.InstructionRa_2|stage6.booleanity.opening.InstructionRa_3|stage6.booleanity.opening.InstructionRa_4|stage6.booleanity.opening.InstructionRa_5|stage6.booleanity.opening.InstructionRa_6|stage6.booleanity.opening.InstructionRa_7|stage6.booleanity.opening.InstructionRa_8|stage6.booleanity.opening.InstructionRa_9|stage6.booleanity.opening.InstructionRa_10|stage6.booleanity.opening.InstructionRa_11|stage6.booleanity.opening.InstructionRa_12|stage6.booleanity.opening.InstructionRa_13|stage6.booleanity.opening.InstructionRa_14|stage6.booleanity.opening.InstructionRa_15|stage6.booleanity.opening.InstructionRa_16|stage6.booleanity.opening.InstructionRa_17|stage6.booleanity.opening.InstructionRa_18|stage6.booleanity.opening.InstructionRa_19|stage6.booleanity.opening.InstructionRa_20|stage6.booleanity.opening.InstructionRa_21|stage6.booleanity.opening.InstructionRa_22|stage6.booleanity.opening.InstructionRa_23|stage6.booleanity.opening.InstructionRa_24|stage6.booleanity.opening.InstructionRa_25|stage6.booleanity.opening.InstructionRa_26|stage6.booleanity.opening.InstructionRa_27|stage6.booleanity.opening.InstructionRa_28|stage6.booleanity.opening.InstructionRa_29|stage6.booleanity.opening.InstructionRa_30|stage6.booleanity.opening.InstructionRa_31|stage6.booleanity.opening.BytecodeRa_0|stage6.booleanity.opening.BytecodeRa_1|stage6.booleanity.opening.BytecodeRa_2|stage6.booleanity.opening.BytecodeRa_3|stage6.booleanity.opening.RamRa_0|stage6.booleanity.opening.RamRa_1|stage6.booleanity.opening.RamRa_2|stage6.booleanity.opening.RamRa_3|stage6.hamming_booleanity.opening.HammingWeight|stage6.ram_ra_virtual.opening.RamRa_0|stage6.ram_ra_virtual.opening.RamRa_1|stage6.ram_ra_virtual.opening.RamRa_2|stage6.ram_ra_virtual.opening.RamRa_3|stage6.instruction_ra_virtual.opening.InstructionRa_0|stage6.instruction_ra_virtual.opening.InstructionRa_1|stage6.instruction_ra_virtual.opening.InstructionRa_2|stage6.instruction_ra_virtual.opening.InstructionRa_3|stage6.instruction_ra_virtual.opening.InstructionRa_4|stage6.instruction_ra_virtual.opening.InstructionRa_5|stage6.instruction_ra_virtual.opening.InstructionRa_6|stage6.instruction_ra_virtual.opening.InstructionRa_7|stage6.instruction_ra_virtual.opening.InstructionRa_8|stage6.instruction_ra_virtual.opening.InstructionRa_9|stage6.instruction_ra_virtual.opening.InstructionRa_10|stage6.instruction_ra_virtual.opening.InstructionRa_11|stage6.instruction_ra_virtual.opening.InstructionRa_12|stage6.instruction_ra_virtual.opening.InstructionRa_13|stage6.instruction_ra_virtual.opening.InstructionRa_14|stage6.instruction_ra_virtual.opening.InstructionRa_15|stage6.instruction_ra_virtual.opening.InstructionRa_16|stage6.instruction_ra_virtual.opening.InstructionRa_17|stage6.instruction_ra_virtual.opening.InstructionRa_18|stage6.instruction_ra_virtual.opening.InstructionRa_19|stage6.instruction_ra_virtual.opening.InstructionRa_20|stage6.instruction_ra_virtual.opening.InstructionRa_21|stage6.instruction_ra_virtual.opening.InstructionRa_22|stage6.instruction_ra_virtual.opening.InstructionRa_23|stage6.instruction_ra_virtual.opening.InstructionRa_24|stage6.instruction_ra_virtual.opening.InstructionRa_25|stage6.instruction_ra_virtual.opening.InstructionRa_26|stage6.instruction_ra_virtual.opening.InstructionRa_27|stage6.instruction_ra_virtual.opening.InstructionRa_28|stage6.instruction_ra_virtual.opening.InstructionRa_29|stage6.instruction_ra_virtual.opening.InstructionRa_30|stage6.instruction_ra_virtual.opening.InstructionRa_31|stage6.inc_claim_reduction.opening.RamInc|stage6.inc_claim_reduction.opening.RdInc", claim_operands: "stage6.bytecode_read_raf.opening.BytecodeRa_0|stage6.bytecode_read_raf.opening.BytecodeRa_1|stage6.bytecode_read_raf.opening.BytecodeRa_2|stage6.bytecode_read_raf.opening.BytecodeRa_3|stage6.booleanity.opening.InstructionRa_0|stage6.booleanity.opening.InstructionRa_1|stage6.booleanity.opening.InstructionRa_2|stage6.booleanity.opening.InstructionRa_3|stage6.booleanity.opening.InstructionRa_4|stage6.booleanity.opening.InstructionRa_5|stage6.booleanity.opening.InstructionRa_6|stage6.booleanity.opening.InstructionRa_7|stage6.booleanity.opening.InstructionRa_8|stage6.booleanity.opening.InstructionRa_9|stage6.booleanity.opening.InstructionRa_10|stage6.booleanity.opening.InstructionRa_11|stage6.booleanity.opening.InstructionRa_12|stage6.booleanity.opening.InstructionRa_13|stage6.booleanity.opening.InstructionRa_14|stage6.booleanity.opening.InstructionRa_15|stage6.booleanity.opening.InstructionRa_16|stage6.booleanity.opening.InstructionRa_17|stage6.booleanity.opening.InstructionRa_18|stage6.booleanity.opening.InstructionRa_19|stage6.booleanity.opening.InstructionRa_20|stage6.booleanity.opening.InstructionRa_21|stage6.booleanity.opening.InstructionRa_22|stage6.booleanity.opening.InstructionRa_23|stage6.booleanity.opening.InstructionRa_24|stage6.booleanity.opening.InstructionRa_25|stage6.booleanity.opening.InstructionRa_26|stage6.booleanity.opening.InstructionRa_27|stage6.booleanity.opening.InstructionRa_28|stage6.booleanity.opening.InstructionRa_29|stage6.booleanity.opening.InstructionRa_30|stage6.booleanity.opening.InstructionRa_31|stage6.booleanity.opening.BytecodeRa_0|stage6.booleanity.opening.BytecodeRa_1|stage6.booleanity.opening.BytecodeRa_2|stage6.booleanity.opening.BytecodeRa_3|stage6.booleanity.opening.RamRa_0|stage6.booleanity.opening.RamRa_1|stage6.booleanity.opening.RamRa_2|stage6.booleanity.opening.RamRa_3|stage6.hamming_booleanity.opening.HammingWeight|stage6.ram_ra_virtual.opening.RamRa_0|stage6.ram_ra_virtual.opening.RamRa_1|stage6.ram_ra_virtual.opening.RamRa_2|stage6.ram_ra_virtual.opening.RamRa_3|stage6.instruction_ra_virtual.opening.InstructionRa_0|stage6.instruction_ra_virtual.opening.InstructionRa_1|stage6.instruction_ra_virtual.opening.InstructionRa_2|stage6.instruction_ra_virtual.opening.InstructionRa_3|stage6.instruction_ra_virtual.opening.InstructionRa_4|stage6.instruction_ra_virtual.opening.InstructionRa_5|stage6.instruction_ra_virtual.opening.InstructionRa_6|stage6.instruction_ra_virtual.opening.InstructionRa_7|stage6.instruction_ra_virtual.opening.InstructionRa_8|stage6.instruction_ra_virtual.opening.InstructionRa_9|stage6.instruction_ra_virtual.opening.InstructionRa_10|stage6.instruction_ra_virtual.opening.InstructionRa_11|stage6.instruction_ra_virtual.opening.InstructionRa_12|stage6.instruction_ra_virtual.opening.InstructionRa_13|stage6.instruction_ra_virtual.opening.InstructionRa_14|stage6.instruction_ra_virtual.opening.InstructionRa_15|stage6.instruction_ra_virtual.opening.InstructionRa_16|stage6.instruction_ra_virtual.opening.InstructionRa_17|stage6.instruction_ra_virtual.opening.InstructionRa_18|stage6.instruction_ra_virtual.opening.InstructionRa_19|stage6.instruction_ra_virtual.opening.InstructionRa_20|stage6.instruction_ra_virtual.opening.InstructionRa_21|stage6.instruction_ra_virtual.opening.InstructionRa_22|stage6.instruction_ra_virtual.opening.InstructionRa_23|stage6.instruction_ra_virtual.opening.InstructionRa_24|stage6.instruction_ra_virtual.opening.InstructionRa_25|stage6.instruction_ra_virtual.opening.InstructionRa_26|stage6.instruction_ra_virtual.opening.InstructionRa_27|stage6.instruction_ra_virtual.opening.InstructionRa_28|stage6.instruction_ra_virtual.opening.InstructionRa_29|stage6.instruction_ra_virtual.opening.InstructionRa_30|stage6.instruction_ra_virtual.opening.InstructionRa_31|stage6.inc_claim_reduction.opening.RamInc|stage6.inc_claim_reduction.opening.RdInc" }, ]; pub const STAGE6_PROGRAM: Stage6VerifierProgramPlan = Stage6CpuProgramPlan { role: "verifier", diff --git a/crates/jolt-verifier/src/stages/stage7.rs b/crates/jolt-verifier/src/stages/stage7.rs index b85a769034..f80d153c4e 100644 --- a/crates/jolt-verifier/src/stages/stage7.rs +++ b/crates/jolt-verifier/src/stages/stage7.rs @@ -67,85 +67,87 @@ pub const STAGE7_TRANSCRIPT_ABSORB_BYTES: &[Stage7TranscriptAbsorbBytesPlan] = & ]; pub const STAGE7_OPENING_INPUTS: &[Stage7OpeningInputPlan] = &[ - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.hamming_booleanity.HammingWeight", source_stage: "stage6", source_claim: "stage6.hamming_booleanity.opening.HammingWeight", oracle: "HammingWeight", domain: "jolt.trace_domain", point_arity: 16, claim_kind: "virtual" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_0", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_0", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_1", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_1", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_2", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_2", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_3", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_3", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_4", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_4", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_5", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_5", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_6", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_6", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_7", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_7", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_8", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_8", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_9", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_9", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_10", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_10", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_11", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_11", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_12", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_12", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_13", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_13", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_14", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_14", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_15", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_15", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_16", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_16", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_17", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_17", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_18", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_18", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_19", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_19", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_20", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_20", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_21", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_21", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_22", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_22", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_23", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_23", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_24", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_24", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_25", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_25", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_26", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_26", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_27", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_27", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_28", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_28", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_29", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_29", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_30", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_30", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_31", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_31", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.BytecodeRa_0", source_stage: "stage6", source_claim: "stage6.booleanity.opening.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.bytecode_read_raf.BytecodeRa_0", source_stage: "stage6", source_claim: "stage6.bytecode_read_raf.opening.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.BytecodeRa_1", source_stage: "stage6", source_claim: "stage6.booleanity.opening.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.bytecode_read_raf.BytecodeRa_1", source_stage: "stage6", source_claim: "stage6.bytecode_read_raf.opening.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.BytecodeRa_2", source_stage: "stage6", source_claim: "stage6.booleanity.opening.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.bytecode_read_raf.BytecodeRa_2", source_stage: "stage6", source_claim: "stage6.bytecode_read_raf.opening.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.RamRa_0", source_stage: "stage6", source_claim: "stage6.booleanity.opening.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.ram_ra_virtual.RamRa_0", source_stage: "stage6", source_claim: "stage6.ram_ra_virtual.opening.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.RamRa_1", source_stage: "stage6", source_claim: "stage6.booleanity.opening.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.ram_ra_virtual.RamRa_1", source_stage: "stage6", source_claim: "stage6.ram_ra_virtual.opening.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.RamRa_2", source_stage: "stage6", source_claim: "stage6.booleanity.opening.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.ram_ra_virtual.RamRa_2", source_stage: "stage6", source_claim: "stage6.ram_ra_virtual.opening.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.RamRa_3", source_stage: "stage6", source_claim: "stage6.booleanity.opening.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage7OpeningInputPlan { symbol: "stage7.input.stage6.ram_ra_virtual.RamRa_3", source_stage: "stage6", source_claim: "stage6.ram_ra_virtual.opening.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.hamming_booleanity.HammingWeight", source_stage: "stage6", source_claim: "stage6.hamming_booleanity.opening.HammingWeight", oracle: "HammingWeight", domain: "jolt.trace_domain", point_arity: 18, claim_kind: "virtual" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_0", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_0", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_1", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_1", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_2", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_2", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_3", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_3", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_4", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_4", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_5", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_5", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_6", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_6", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_7", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_7", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_8", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_8", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_9", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_9", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_10", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_10", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_11", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_11", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_12", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_12", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_13", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_13", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_14", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_14", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_15", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_15", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_16", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_16", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_17", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_17", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_18", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_18", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_19", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_19", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_20", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_20", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_21", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_21", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_22", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_22", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_23", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_23", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_24", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_24", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_25", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_25", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_26", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_26", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_27", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_27", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_28", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_28", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_29", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_29", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_30", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_30", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.InstructionRa_31", source_stage: "stage6", source_claim: "stage6.booleanity.opening.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.instruction_ra_virtual.InstructionRa_31", source_stage: "stage6", source_claim: "stage6.instruction_ra_virtual.opening.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.BytecodeRa_0", source_stage: "stage6", source_claim: "stage6.booleanity.opening.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.bytecode_read_raf.BytecodeRa_0", source_stage: "stage6", source_claim: "stage6.bytecode_read_raf.opening.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.BytecodeRa_1", source_stage: "stage6", source_claim: "stage6.booleanity.opening.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.bytecode_read_raf.BytecodeRa_1", source_stage: "stage6", source_claim: "stage6.bytecode_read_raf.opening.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.BytecodeRa_2", source_stage: "stage6", source_claim: "stage6.booleanity.opening.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.bytecode_read_raf.BytecodeRa_2", source_stage: "stage6", source_claim: "stage6.bytecode_read_raf.opening.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.BytecodeRa_3", source_stage: "stage6", source_claim: "stage6.booleanity.opening.BytecodeRa_3", oracle: "BytecodeRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.bytecode_read_raf.BytecodeRa_3", source_stage: "stage6", source_claim: "stage6.bytecode_read_raf.opening.BytecodeRa_3", oracle: "BytecodeRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.RamRa_0", source_stage: "stage6", source_claim: "stage6.booleanity.opening.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.ram_ra_virtual.RamRa_0", source_stage: "stage6", source_claim: "stage6.ram_ra_virtual.opening.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.RamRa_1", source_stage: "stage6", source_claim: "stage6.booleanity.opening.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.ram_ra_virtual.RamRa_1", source_stage: "stage6", source_claim: "stage6.ram_ra_virtual.opening.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.RamRa_2", source_stage: "stage6", source_claim: "stage6.booleanity.opening.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.ram_ra_virtual.RamRa_2", source_stage: "stage6", source_claim: "stage6.ram_ra_virtual.opening.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.booleanity.RamRa_3", source_stage: "stage6", source_claim: "stage6.booleanity.opening.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage7OpeningInputPlan { symbol: "stage7.input.stage6.ram_ra_virtual.RamRa_3", source_stage: "stage6", source_claim: "stage6.ram_ra_virtual.opening.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, ]; pub const STAGE7_FIELD_CONSTANTS: &[Stage7FieldConstantPlan] = &[ @@ -186,31 +188,32 @@ pub const STAGE7_FIELD_EXPRS: &[Stage7FieldExprPlan] = &[ stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.31.hw.gamma_pow", "field.pow:93", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.31.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.31.hw.gamma_pow|stage7.field.one"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.31.booleanity.gamma_pow", "field.pow:94", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.31.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.31.booleanity.gamma_pow|stage7.input.stage6.booleanity.InstructionRa_31"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.31.virtualization.gamma_pow", "field.pow:95", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.31.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.31.virtualization.gamma_pow|stage7.input.stage6.instruction_ra_virtual.InstructionRa_31"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.32.hw.gamma_pow", "field.pow:96", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.32.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.32.hw.gamma_pow|stage7.field.one"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.32.booleanity.gamma_pow", "field.pow:97", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.32.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.32.booleanity.gamma_pow|stage7.input.stage6.booleanity.BytecodeRa_0"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.32.virtualization.gamma_pow", "field.pow:98", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.32.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.32.virtualization.gamma_pow|stage7.input.stage6.bytecode_read_raf.BytecodeRa_0"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.33.hw.gamma_pow", "field.pow:99", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.33.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.33.hw.gamma_pow|stage7.field.one"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.33.booleanity.gamma_pow", "field.pow:100", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.33.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.33.booleanity.gamma_pow|stage7.input.stage6.booleanity.BytecodeRa_1"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.33.virtualization.gamma_pow", "field.pow:101", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.33.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.33.virtualization.gamma_pow|stage7.input.stage6.bytecode_read_raf.BytecodeRa_1"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.34.hw.gamma_pow", "field.pow:102", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.34.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.34.hw.gamma_pow|stage7.field.one"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.34.booleanity.gamma_pow", "field.pow:103", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.34.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.34.booleanity.gamma_pow|stage7.input.stage6.booleanity.BytecodeRa_2"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.34.virtualization.gamma_pow", "field.pow:104", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.34.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.34.virtualization.gamma_pow|stage7.input.stage6.bytecode_read_raf.BytecodeRa_2"), - stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.35.hw.gamma_pow", "field.pow:105", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.35.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.35.hw.gamma_pow|stage7.input.stage6.hamming_booleanity.HammingWeight"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.35.booleanity.gamma_pow", "field.pow:106", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.35.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.35.booleanity.gamma_pow|stage7.input.stage6.booleanity.RamRa_0"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.35.virtualization.gamma_pow", "field.pow:107", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.35.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.35.virtualization.gamma_pow|stage7.input.stage6.ram_ra_virtual.RamRa_0"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.36.hw.gamma_pow", "field.pow:108", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.36.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.36.hw.gamma_pow|stage7.input.stage6.hamming_booleanity.HammingWeight"), - stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.36.booleanity.gamma_pow", "field.pow:109", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.36.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.36.booleanity.gamma_pow|stage7.input.stage6.booleanity.RamRa_1"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.36.virtualization.gamma_pow", "field.pow:110", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.36.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.36.virtualization.gamma_pow|stage7.input.stage6.ram_ra_virtual.RamRa_1"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.37.hw.gamma_pow", "field.pow:111", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.37.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.37.hw.gamma_pow|stage7.input.stage6.hamming_booleanity.HammingWeight"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.37.booleanity.gamma_pow", "field.pow:112", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.37.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.37.booleanity.gamma_pow|stage7.input.stage6.booleanity.RamRa_2"), - stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.37.virtualization.gamma_pow", "field.pow:113", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.37.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.37.virtualization.gamma_pow|stage7.input.stage6.ram_ra_virtual.RamRa_2"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.38.hw.gamma_pow", "field.pow:114", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.38.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.38.hw.gamma_pow|stage7.input.stage6.hamming_booleanity.HammingWeight"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.38.booleanity.gamma_pow", "field.pow:115", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.38.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.38.booleanity.gamma_pow|stage7.input.stage6.booleanity.RamRa_3"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.38.virtualization.gamma_pow", "field.pow:116", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.38.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.38.virtualization.gamma_pow|stage7.input.stage6.ram_ra_virtual.RamRa_3"), - stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial0", "field.add", "stage7.field.one|stage7.hamming_weight_claim_reduction.claim.0.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial1", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial0|stage7.hamming_weight_claim_reduction.claim.0.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial2", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial1|stage7.hamming_weight_claim_reduction.claim.1.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial3", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial2|stage7.hamming_weight_claim_reduction.claim.1.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial4", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial3|stage7.hamming_weight_claim_reduction.claim.1.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial5", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial4|stage7.hamming_weight_claim_reduction.claim.2.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial6", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial5|stage7.hamming_weight_claim_reduction.claim.2.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial7", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial6|stage7.hamming_weight_claim_reduction.claim.2.virtualization.gamma_term"), - stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial8", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial7|stage7.hamming_weight_claim_reduction.claim.3.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial9", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial8|stage7.hamming_weight_claim_reduction.claim.3.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial10", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial9|stage7.hamming_weight_claim_reduction.claim.3.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial11", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial10|stage7.hamming_weight_claim_reduction.claim.4.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial12", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial11|stage7.hamming_weight_claim_reduction.claim.4.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial13", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial12|stage7.hamming_weight_claim_reduction.claim.4.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial14", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial13|stage7.hamming_weight_claim_reduction.claim.5.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial15", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial14|stage7.hamming_weight_claim_reduction.claim.5.booleanity.gamma_term"), - stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial16", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial15|stage7.hamming_weight_claim_reduction.claim.5.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial17", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial16|stage7.hamming_weight_claim_reduction.claim.6.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial18", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial17|stage7.hamming_weight_claim_reduction.claim.6.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial19", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial18|stage7.hamming_weight_claim_reduction.claim.6.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial20", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial19|stage7.hamming_weight_claim_reduction.claim.7.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial21", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial20|stage7.hamming_weight_claim_reduction.claim.7.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial22", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial21|stage7.hamming_weight_claim_reduction.claim.7.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial23", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial22|stage7.hamming_weight_claim_reduction.claim.8.hw.gamma_term"), - stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial24", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial23|stage7.hamming_weight_claim_reduction.claim.8.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial25", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial24|stage7.hamming_weight_claim_reduction.claim.8.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial26", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial25|stage7.hamming_weight_claim_reduction.claim.9.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial27", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial26|stage7.hamming_weight_claim_reduction.claim.9.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial28", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial27|stage7.hamming_weight_claim_reduction.claim.9.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial29", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial28|stage7.hamming_weight_claim_reduction.claim.10.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial30", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial29|stage7.hamming_weight_claim_reduction.claim.10.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial31", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial30|stage7.hamming_weight_claim_reduction.claim.10.virtualization.gamma_term"), - stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial32", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial31|stage7.hamming_weight_claim_reduction.claim.11.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial33", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial32|stage7.hamming_weight_claim_reduction.claim.11.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial34", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial33|stage7.hamming_weight_claim_reduction.claim.11.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial35", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial34|stage7.hamming_weight_claim_reduction.claim.12.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial36", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial35|stage7.hamming_weight_claim_reduction.claim.12.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial37", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial36|stage7.hamming_weight_claim_reduction.claim.12.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial38", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial37|stage7.hamming_weight_claim_reduction.claim.13.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial39", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial38|stage7.hamming_weight_claim_reduction.claim.13.booleanity.gamma_term"), - stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial40", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial39|stage7.hamming_weight_claim_reduction.claim.13.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial41", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial40|stage7.hamming_weight_claim_reduction.claim.14.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial42", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial41|stage7.hamming_weight_claim_reduction.claim.14.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial43", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial42|stage7.hamming_weight_claim_reduction.claim.14.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial44", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial43|stage7.hamming_weight_claim_reduction.claim.15.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial45", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial44|stage7.hamming_weight_claim_reduction.claim.15.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial46", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial45|stage7.hamming_weight_claim_reduction.claim.15.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial47", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial46|stage7.hamming_weight_claim_reduction.claim.16.hw.gamma_term"), - stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial48", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial47|stage7.hamming_weight_claim_reduction.claim.16.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial49", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial48|stage7.hamming_weight_claim_reduction.claim.16.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial50", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial49|stage7.hamming_weight_claim_reduction.claim.17.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial51", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial50|stage7.hamming_weight_claim_reduction.claim.17.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial52", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial51|stage7.hamming_weight_claim_reduction.claim.17.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial53", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial52|stage7.hamming_weight_claim_reduction.claim.18.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial54", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial53|stage7.hamming_weight_claim_reduction.claim.18.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial55", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial54|stage7.hamming_weight_claim_reduction.claim.18.virtualization.gamma_term"), - stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial56", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial55|stage7.hamming_weight_claim_reduction.claim.19.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial57", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial56|stage7.hamming_weight_claim_reduction.claim.19.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial58", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial57|stage7.hamming_weight_claim_reduction.claim.19.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial59", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial58|stage7.hamming_weight_claim_reduction.claim.20.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial60", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial59|stage7.hamming_weight_claim_reduction.claim.20.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial61", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial60|stage7.hamming_weight_claim_reduction.claim.20.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial62", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial61|stage7.hamming_weight_claim_reduction.claim.21.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial63", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial62|stage7.hamming_weight_claim_reduction.claim.21.booleanity.gamma_term"), - stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial64", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial63|stage7.hamming_weight_claim_reduction.claim.21.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial65", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial64|stage7.hamming_weight_claim_reduction.claim.22.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial66", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial65|stage7.hamming_weight_claim_reduction.claim.22.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial67", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial66|stage7.hamming_weight_claim_reduction.claim.22.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial68", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial67|stage7.hamming_weight_claim_reduction.claim.23.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial69", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial68|stage7.hamming_weight_claim_reduction.claim.23.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial70", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial69|stage7.hamming_weight_claim_reduction.claim.23.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial71", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial70|stage7.hamming_weight_claim_reduction.claim.24.hw.gamma_term"), - stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial72", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial71|stage7.hamming_weight_claim_reduction.claim.24.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial73", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial72|stage7.hamming_weight_claim_reduction.claim.24.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial74", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial73|stage7.hamming_weight_claim_reduction.claim.25.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial75", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial74|stage7.hamming_weight_claim_reduction.claim.25.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial76", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial75|stage7.hamming_weight_claim_reduction.claim.25.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial77", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial76|stage7.hamming_weight_claim_reduction.claim.26.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial78", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial77|stage7.hamming_weight_claim_reduction.claim.26.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial79", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial78|stage7.hamming_weight_claim_reduction.claim.26.virtualization.gamma_term"), - stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial80", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial79|stage7.hamming_weight_claim_reduction.claim.27.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial81", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial80|stage7.hamming_weight_claim_reduction.claim.27.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial82", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial81|stage7.hamming_weight_claim_reduction.claim.27.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial83", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial82|stage7.hamming_weight_claim_reduction.claim.28.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial84", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial83|stage7.hamming_weight_claim_reduction.claim.28.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial85", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial84|stage7.hamming_weight_claim_reduction.claim.28.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial86", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial85|stage7.hamming_weight_claim_reduction.claim.29.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial87", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial86|stage7.hamming_weight_claim_reduction.claim.29.booleanity.gamma_term"), - stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial88", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial87|stage7.hamming_weight_claim_reduction.claim.29.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial89", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial88|stage7.hamming_weight_claim_reduction.claim.30.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial90", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial89|stage7.hamming_weight_claim_reduction.claim.30.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial91", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial90|stage7.hamming_weight_claim_reduction.claim.30.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial92", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial91|stage7.hamming_weight_claim_reduction.claim.31.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial93", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial92|stage7.hamming_weight_claim_reduction.claim.31.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial94", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial93|stage7.hamming_weight_claim_reduction.claim.31.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial95", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial94|stage7.hamming_weight_claim_reduction.claim.32.hw.gamma_term"), - stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial96", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial95|stage7.hamming_weight_claim_reduction.claim.32.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial97", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial96|stage7.hamming_weight_claim_reduction.claim.32.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial98", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial97|stage7.hamming_weight_claim_reduction.claim.33.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial99", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial98|stage7.hamming_weight_claim_reduction.claim.33.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial100", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial99|stage7.hamming_weight_claim_reduction.claim.33.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial101", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial100|stage7.hamming_weight_claim_reduction.claim.34.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial102", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial101|stage7.hamming_weight_claim_reduction.claim.34.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial103", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial102|stage7.hamming_weight_claim_reduction.claim.34.virtualization.gamma_term"), - stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial104", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial103|stage7.hamming_weight_claim_reduction.claim.35.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial105", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial104|stage7.hamming_weight_claim_reduction.claim.35.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial106", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial105|stage7.hamming_weight_claim_reduction.claim.35.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial107", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial106|stage7.hamming_weight_claim_reduction.claim.36.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial108", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial107|stage7.hamming_weight_claim_reduction.claim.36.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial109", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial108|stage7.hamming_weight_claim_reduction.claim.36.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial110", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial109|stage7.hamming_weight_claim_reduction.claim.37.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial111", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial110|stage7.hamming_weight_claim_reduction.claim.37.booleanity.gamma_term"), - stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial112", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial111|stage7.hamming_weight_claim_reduction.claim.37.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial113", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial112|stage7.hamming_weight_claim_reduction.claim.38.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial114", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial113|stage7.hamming_weight_claim_reduction.claim.38.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial115", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial114|stage7.hamming_weight_claim_reduction.claim.38.virtualization.gamma_term"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.35.hw.gamma_pow", "field.pow:105", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.35.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.35.hw.gamma_pow|stage7.field.one"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.35.booleanity.gamma_pow", "field.pow:106", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.35.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.35.booleanity.gamma_pow|stage7.input.stage6.booleanity.BytecodeRa_3"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.35.virtualization.gamma_pow", "field.pow:107", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.35.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.35.virtualization.gamma_pow|stage7.input.stage6.bytecode_read_raf.BytecodeRa_3"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.36.hw.gamma_pow", "field.pow:108", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.36.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.36.hw.gamma_pow|stage7.input.stage6.hamming_booleanity.HammingWeight"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.36.booleanity.gamma_pow", "field.pow:109", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.36.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.36.booleanity.gamma_pow|stage7.input.stage6.booleanity.RamRa_0"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.36.virtualization.gamma_pow", "field.pow:110", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.36.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.36.virtualization.gamma_pow|stage7.input.stage6.ram_ra_virtual.RamRa_0"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.37.hw.gamma_pow", "field.pow:111", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.37.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.37.hw.gamma_pow|stage7.input.stage6.hamming_booleanity.HammingWeight"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.37.booleanity.gamma_pow", "field.pow:112", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.37.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.37.booleanity.gamma_pow|stage7.input.stage6.booleanity.RamRa_1"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.37.virtualization.gamma_pow", "field.pow:113", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.37.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.37.virtualization.gamma_pow|stage7.input.stage6.ram_ra_virtual.RamRa_1"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.38.hw.gamma_pow", "field.pow:114", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.38.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.38.hw.gamma_pow|stage7.input.stage6.hamming_booleanity.HammingWeight"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.38.booleanity.gamma_pow", "field.pow:115", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.38.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.38.booleanity.gamma_pow|stage7.input.stage6.booleanity.RamRa_2"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.38.virtualization.gamma_pow", "field.pow:116", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.38.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.38.virtualization.gamma_pow|stage7.input.stage6.ram_ra_virtual.RamRa_2"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.39.hw.gamma_pow", "field.pow:117", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.39.hw.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.39.hw.gamma_pow|stage7.input.stage6.hamming_booleanity.HammingWeight"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.39.booleanity.gamma_pow", "field.pow:118", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.39.booleanity.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.39.booleanity.gamma_pow|stage7.input.stage6.booleanity.RamRa_3"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.39.virtualization.gamma_pow", "field.pow:119", "stage7.hamming_weight_claim_reduction.gamma"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim.39.virtualization.gamma_term", "field.mul", "stage7.hamming_weight_claim_reduction.claim.39.virtualization.gamma_pow|stage7.input.stage6.ram_ra_virtual.RamRa_3"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial0", "field.add", "stage7.field.one|stage7.hamming_weight_claim_reduction.claim.0.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial1", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial0|stage7.hamming_weight_claim_reduction.claim.0.virtualization.gamma_term"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial2", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial1|stage7.hamming_weight_claim_reduction.claim.1.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial3", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial2|stage7.hamming_weight_claim_reduction.claim.1.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial4", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial3|stage7.hamming_weight_claim_reduction.claim.1.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial5", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial4|stage7.hamming_weight_claim_reduction.claim.2.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial6", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial5|stage7.hamming_weight_claim_reduction.claim.2.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial7", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial6|stage7.hamming_weight_claim_reduction.claim.2.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial8", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial7|stage7.hamming_weight_claim_reduction.claim.3.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial9", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial8|stage7.hamming_weight_claim_reduction.claim.3.booleanity.gamma_term"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial10", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial9|stage7.hamming_weight_claim_reduction.claim.3.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial11", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial10|stage7.hamming_weight_claim_reduction.claim.4.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial12", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial11|stage7.hamming_weight_claim_reduction.claim.4.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial13", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial12|stage7.hamming_weight_claim_reduction.claim.4.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial14", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial13|stage7.hamming_weight_claim_reduction.claim.5.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial15", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial14|stage7.hamming_weight_claim_reduction.claim.5.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial16", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial15|stage7.hamming_weight_claim_reduction.claim.5.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial17", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial16|stage7.hamming_weight_claim_reduction.claim.6.hw.gamma_term"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial18", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial17|stage7.hamming_weight_claim_reduction.claim.6.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial19", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial18|stage7.hamming_weight_claim_reduction.claim.6.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial20", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial19|stage7.hamming_weight_claim_reduction.claim.7.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial21", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial20|stage7.hamming_weight_claim_reduction.claim.7.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial22", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial21|stage7.hamming_weight_claim_reduction.claim.7.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial23", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial22|stage7.hamming_weight_claim_reduction.claim.8.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial24", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial23|stage7.hamming_weight_claim_reduction.claim.8.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial25", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial24|stage7.hamming_weight_claim_reduction.claim.8.virtualization.gamma_term"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial26", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial25|stage7.hamming_weight_claim_reduction.claim.9.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial27", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial26|stage7.hamming_weight_claim_reduction.claim.9.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial28", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial27|stage7.hamming_weight_claim_reduction.claim.9.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial29", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial28|stage7.hamming_weight_claim_reduction.claim.10.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial30", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial29|stage7.hamming_weight_claim_reduction.claim.10.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial31", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial30|stage7.hamming_weight_claim_reduction.claim.10.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial32", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial31|stage7.hamming_weight_claim_reduction.claim.11.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial33", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial32|stage7.hamming_weight_claim_reduction.claim.11.booleanity.gamma_term"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial34", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial33|stage7.hamming_weight_claim_reduction.claim.11.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial35", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial34|stage7.hamming_weight_claim_reduction.claim.12.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial36", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial35|stage7.hamming_weight_claim_reduction.claim.12.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial37", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial36|stage7.hamming_weight_claim_reduction.claim.12.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial38", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial37|stage7.hamming_weight_claim_reduction.claim.13.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial39", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial38|stage7.hamming_weight_claim_reduction.claim.13.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial40", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial39|stage7.hamming_weight_claim_reduction.claim.13.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial41", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial40|stage7.hamming_weight_claim_reduction.claim.14.hw.gamma_term"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial42", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial41|stage7.hamming_weight_claim_reduction.claim.14.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial43", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial42|stage7.hamming_weight_claim_reduction.claim.14.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial44", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial43|stage7.hamming_weight_claim_reduction.claim.15.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial45", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial44|stage7.hamming_weight_claim_reduction.claim.15.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial46", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial45|stage7.hamming_weight_claim_reduction.claim.15.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial47", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial46|stage7.hamming_weight_claim_reduction.claim.16.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial48", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial47|stage7.hamming_weight_claim_reduction.claim.16.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial49", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial48|stage7.hamming_weight_claim_reduction.claim.16.virtualization.gamma_term"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial50", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial49|stage7.hamming_weight_claim_reduction.claim.17.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial51", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial50|stage7.hamming_weight_claim_reduction.claim.17.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial52", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial51|stage7.hamming_weight_claim_reduction.claim.17.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial53", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial52|stage7.hamming_weight_claim_reduction.claim.18.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial54", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial53|stage7.hamming_weight_claim_reduction.claim.18.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial55", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial54|stage7.hamming_weight_claim_reduction.claim.18.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial56", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial55|stage7.hamming_weight_claim_reduction.claim.19.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial57", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial56|stage7.hamming_weight_claim_reduction.claim.19.booleanity.gamma_term"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial58", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial57|stage7.hamming_weight_claim_reduction.claim.19.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial59", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial58|stage7.hamming_weight_claim_reduction.claim.20.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial60", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial59|stage7.hamming_weight_claim_reduction.claim.20.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial61", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial60|stage7.hamming_weight_claim_reduction.claim.20.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial62", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial61|stage7.hamming_weight_claim_reduction.claim.21.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial63", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial62|stage7.hamming_weight_claim_reduction.claim.21.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial64", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial63|stage7.hamming_weight_claim_reduction.claim.21.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial65", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial64|stage7.hamming_weight_claim_reduction.claim.22.hw.gamma_term"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial66", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial65|stage7.hamming_weight_claim_reduction.claim.22.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial67", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial66|stage7.hamming_weight_claim_reduction.claim.22.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial68", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial67|stage7.hamming_weight_claim_reduction.claim.23.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial69", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial68|stage7.hamming_weight_claim_reduction.claim.23.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial70", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial69|stage7.hamming_weight_claim_reduction.claim.23.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial71", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial70|stage7.hamming_weight_claim_reduction.claim.24.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial72", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial71|stage7.hamming_weight_claim_reduction.claim.24.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial73", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial72|stage7.hamming_weight_claim_reduction.claim.24.virtualization.gamma_term"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial74", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial73|stage7.hamming_weight_claim_reduction.claim.25.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial75", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial74|stage7.hamming_weight_claim_reduction.claim.25.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial76", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial75|stage7.hamming_weight_claim_reduction.claim.25.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial77", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial76|stage7.hamming_weight_claim_reduction.claim.26.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial78", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial77|stage7.hamming_weight_claim_reduction.claim.26.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial79", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial78|stage7.hamming_weight_claim_reduction.claim.26.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial80", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial79|stage7.hamming_weight_claim_reduction.claim.27.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial81", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial80|stage7.hamming_weight_claim_reduction.claim.27.booleanity.gamma_term"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial82", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial81|stage7.hamming_weight_claim_reduction.claim.27.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial83", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial82|stage7.hamming_weight_claim_reduction.claim.28.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial84", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial83|stage7.hamming_weight_claim_reduction.claim.28.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial85", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial84|stage7.hamming_weight_claim_reduction.claim.28.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial86", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial85|stage7.hamming_weight_claim_reduction.claim.29.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial87", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial86|stage7.hamming_weight_claim_reduction.claim.29.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial88", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial87|stage7.hamming_weight_claim_reduction.claim.29.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial89", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial88|stage7.hamming_weight_claim_reduction.claim.30.hw.gamma_term"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial90", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial89|stage7.hamming_weight_claim_reduction.claim.30.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial91", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial90|stage7.hamming_weight_claim_reduction.claim.30.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial92", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial91|stage7.hamming_weight_claim_reduction.claim.31.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial93", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial92|stage7.hamming_weight_claim_reduction.claim.31.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial94", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial93|stage7.hamming_weight_claim_reduction.claim.31.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial95", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial94|stage7.hamming_weight_claim_reduction.claim.32.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial96", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial95|stage7.hamming_weight_claim_reduction.claim.32.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial97", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial96|stage7.hamming_weight_claim_reduction.claim.32.virtualization.gamma_term"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial98", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial97|stage7.hamming_weight_claim_reduction.claim.33.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial99", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial98|stage7.hamming_weight_claim_reduction.claim.33.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial100", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial99|stage7.hamming_weight_claim_reduction.claim.33.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial101", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial100|stage7.hamming_weight_claim_reduction.claim.34.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial102", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial101|stage7.hamming_weight_claim_reduction.claim.34.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial103", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial102|stage7.hamming_weight_claim_reduction.claim.34.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial104", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial103|stage7.hamming_weight_claim_reduction.claim.35.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial105", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial104|stage7.hamming_weight_claim_reduction.claim.35.booleanity.gamma_term"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial106", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial105|stage7.hamming_weight_claim_reduction.claim.35.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial107", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial106|stage7.hamming_weight_claim_reduction.claim.36.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial108", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial107|stage7.hamming_weight_claim_reduction.claim.36.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial109", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial108|stage7.hamming_weight_claim_reduction.claim.36.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial110", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial109|stage7.hamming_weight_claim_reduction.claim.37.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial111", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial110|stage7.hamming_weight_claim_reduction.claim.37.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial112", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial111|stage7.hamming_weight_claim_reduction.claim.37.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial113", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial112|stage7.hamming_weight_claim_reduction.claim.38.hw.gamma_term"), + stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial114", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial113|stage7.hamming_weight_claim_reduction.claim.38.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial115", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial114|stage7.hamming_weight_claim_reduction.claim.38.virtualization.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial116", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial115|stage7.hamming_weight_claim_reduction.claim.39.hw.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial117", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial116|stage7.hamming_weight_claim_reduction.claim.39.booleanity.gamma_term"), stage7_field_expr!("stage7.hamming_weight_claim_reduction.claim_expr.partial118", "field.add", "stage7.hamming_weight_claim_reduction.claim_expr.partial117|stage7.hamming_weight_claim_reduction.claim.39.virtualization.gamma_term"), ]; pub const STAGE7_KERNELS: &[Stage7KernelPlan] = &[ ]; pub const STAGE7_SUMCHECK_CLAIMS: &[Stage7SumcheckClaimPlan] = &[ - Stage7SumcheckClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.input", stage: "stage7", domain: "jolt.stage7_hamming_weight_claim_reduction_domain", num_rounds: 4, degree: 2, claim: "stage7.hamming_weight_claim_reduction.weighted_stage6_claims", kernel: None, relation: Some("jolt.stage7.hamming_weight_claim_reduction"), claim_value: "stage7.hamming_weight_claim_reduction.claim_expr.partial115", input_openings: "stage7.input.stage6.hamming_booleanity.HammingWeight|stage7.input.stage6.booleanity.InstructionRa_0|stage7.input.stage6.instruction_ra_virtual.InstructionRa_0|stage7.input.stage6.booleanity.InstructionRa_1|stage7.input.stage6.instruction_ra_virtual.InstructionRa_1|stage7.input.stage6.booleanity.InstructionRa_2|stage7.input.stage6.instruction_ra_virtual.InstructionRa_2|stage7.input.stage6.booleanity.InstructionRa_3|stage7.input.stage6.instruction_ra_virtual.InstructionRa_3|stage7.input.stage6.booleanity.InstructionRa_4|stage7.input.stage6.instruction_ra_virtual.InstructionRa_4|stage7.input.stage6.booleanity.InstructionRa_5|stage7.input.stage6.instruction_ra_virtual.InstructionRa_5|stage7.input.stage6.booleanity.InstructionRa_6|stage7.input.stage6.instruction_ra_virtual.InstructionRa_6|stage7.input.stage6.booleanity.InstructionRa_7|stage7.input.stage6.instruction_ra_virtual.InstructionRa_7|stage7.input.stage6.booleanity.InstructionRa_8|stage7.input.stage6.instruction_ra_virtual.InstructionRa_8|stage7.input.stage6.booleanity.InstructionRa_9|stage7.input.stage6.instruction_ra_virtual.InstructionRa_9|stage7.input.stage6.booleanity.InstructionRa_10|stage7.input.stage6.instruction_ra_virtual.InstructionRa_10|stage7.input.stage6.booleanity.InstructionRa_11|stage7.input.stage6.instruction_ra_virtual.InstructionRa_11|stage7.input.stage6.booleanity.InstructionRa_12|stage7.input.stage6.instruction_ra_virtual.InstructionRa_12|stage7.input.stage6.booleanity.InstructionRa_13|stage7.input.stage6.instruction_ra_virtual.InstructionRa_13|stage7.input.stage6.booleanity.InstructionRa_14|stage7.input.stage6.instruction_ra_virtual.InstructionRa_14|stage7.input.stage6.booleanity.InstructionRa_15|stage7.input.stage6.instruction_ra_virtual.InstructionRa_15|stage7.input.stage6.booleanity.InstructionRa_16|stage7.input.stage6.instruction_ra_virtual.InstructionRa_16|stage7.input.stage6.booleanity.InstructionRa_17|stage7.input.stage6.instruction_ra_virtual.InstructionRa_17|stage7.input.stage6.booleanity.InstructionRa_18|stage7.input.stage6.instruction_ra_virtual.InstructionRa_18|stage7.input.stage6.booleanity.InstructionRa_19|stage7.input.stage6.instruction_ra_virtual.InstructionRa_19|stage7.input.stage6.booleanity.InstructionRa_20|stage7.input.stage6.instruction_ra_virtual.InstructionRa_20|stage7.input.stage6.booleanity.InstructionRa_21|stage7.input.stage6.instruction_ra_virtual.InstructionRa_21|stage7.input.stage6.booleanity.InstructionRa_22|stage7.input.stage6.instruction_ra_virtual.InstructionRa_22|stage7.input.stage6.booleanity.InstructionRa_23|stage7.input.stage6.instruction_ra_virtual.InstructionRa_23|stage7.input.stage6.booleanity.InstructionRa_24|stage7.input.stage6.instruction_ra_virtual.InstructionRa_24|stage7.input.stage6.booleanity.InstructionRa_25|stage7.input.stage6.instruction_ra_virtual.InstructionRa_25|stage7.input.stage6.booleanity.InstructionRa_26|stage7.input.stage6.instruction_ra_virtual.InstructionRa_26|stage7.input.stage6.booleanity.InstructionRa_27|stage7.input.stage6.instruction_ra_virtual.InstructionRa_27|stage7.input.stage6.booleanity.InstructionRa_28|stage7.input.stage6.instruction_ra_virtual.InstructionRa_28|stage7.input.stage6.booleanity.InstructionRa_29|stage7.input.stage6.instruction_ra_virtual.InstructionRa_29|stage7.input.stage6.booleanity.InstructionRa_30|stage7.input.stage6.instruction_ra_virtual.InstructionRa_30|stage7.input.stage6.booleanity.InstructionRa_31|stage7.input.stage6.instruction_ra_virtual.InstructionRa_31|stage7.input.stage6.booleanity.BytecodeRa_0|stage7.input.stage6.bytecode_read_raf.BytecodeRa_0|stage7.input.stage6.booleanity.BytecodeRa_1|stage7.input.stage6.bytecode_read_raf.BytecodeRa_1|stage7.input.stage6.booleanity.BytecodeRa_2|stage7.input.stage6.bytecode_read_raf.BytecodeRa_2|stage7.input.stage6.booleanity.RamRa_0|stage7.input.stage6.ram_ra_virtual.RamRa_0|stage7.input.stage6.booleanity.RamRa_1|stage7.input.stage6.ram_ra_virtual.RamRa_1|stage7.input.stage6.booleanity.RamRa_2|stage7.input.stage6.ram_ra_virtual.RamRa_2|stage7.input.stage6.booleanity.RamRa_3|stage7.input.stage6.ram_ra_virtual.RamRa_3" }, + Stage7SumcheckClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.input", stage: "stage7", domain: "jolt.stage7_hamming_weight_claim_reduction_domain", num_rounds: 4, degree: 2, claim: "stage7.hamming_weight_claim_reduction.weighted_stage6_claims", kernel: None, relation: Some("jolt.stage7.hamming_weight_claim_reduction"), claim_value: "stage7.hamming_weight_claim_reduction.claim_expr.partial118", input_openings: "stage7.input.stage6.hamming_booleanity.HammingWeight|stage7.input.stage6.booleanity.InstructionRa_0|stage7.input.stage6.instruction_ra_virtual.InstructionRa_0|stage7.input.stage6.booleanity.InstructionRa_1|stage7.input.stage6.instruction_ra_virtual.InstructionRa_1|stage7.input.stage6.booleanity.InstructionRa_2|stage7.input.stage6.instruction_ra_virtual.InstructionRa_2|stage7.input.stage6.booleanity.InstructionRa_3|stage7.input.stage6.instruction_ra_virtual.InstructionRa_3|stage7.input.stage6.booleanity.InstructionRa_4|stage7.input.stage6.instruction_ra_virtual.InstructionRa_4|stage7.input.stage6.booleanity.InstructionRa_5|stage7.input.stage6.instruction_ra_virtual.InstructionRa_5|stage7.input.stage6.booleanity.InstructionRa_6|stage7.input.stage6.instruction_ra_virtual.InstructionRa_6|stage7.input.stage6.booleanity.InstructionRa_7|stage7.input.stage6.instruction_ra_virtual.InstructionRa_7|stage7.input.stage6.booleanity.InstructionRa_8|stage7.input.stage6.instruction_ra_virtual.InstructionRa_8|stage7.input.stage6.booleanity.InstructionRa_9|stage7.input.stage6.instruction_ra_virtual.InstructionRa_9|stage7.input.stage6.booleanity.InstructionRa_10|stage7.input.stage6.instruction_ra_virtual.InstructionRa_10|stage7.input.stage6.booleanity.InstructionRa_11|stage7.input.stage6.instruction_ra_virtual.InstructionRa_11|stage7.input.stage6.booleanity.InstructionRa_12|stage7.input.stage6.instruction_ra_virtual.InstructionRa_12|stage7.input.stage6.booleanity.InstructionRa_13|stage7.input.stage6.instruction_ra_virtual.InstructionRa_13|stage7.input.stage6.booleanity.InstructionRa_14|stage7.input.stage6.instruction_ra_virtual.InstructionRa_14|stage7.input.stage6.booleanity.InstructionRa_15|stage7.input.stage6.instruction_ra_virtual.InstructionRa_15|stage7.input.stage6.booleanity.InstructionRa_16|stage7.input.stage6.instruction_ra_virtual.InstructionRa_16|stage7.input.stage6.booleanity.InstructionRa_17|stage7.input.stage6.instruction_ra_virtual.InstructionRa_17|stage7.input.stage6.booleanity.InstructionRa_18|stage7.input.stage6.instruction_ra_virtual.InstructionRa_18|stage7.input.stage6.booleanity.InstructionRa_19|stage7.input.stage6.instruction_ra_virtual.InstructionRa_19|stage7.input.stage6.booleanity.InstructionRa_20|stage7.input.stage6.instruction_ra_virtual.InstructionRa_20|stage7.input.stage6.booleanity.InstructionRa_21|stage7.input.stage6.instruction_ra_virtual.InstructionRa_21|stage7.input.stage6.booleanity.InstructionRa_22|stage7.input.stage6.instruction_ra_virtual.InstructionRa_22|stage7.input.stage6.booleanity.InstructionRa_23|stage7.input.stage6.instruction_ra_virtual.InstructionRa_23|stage7.input.stage6.booleanity.InstructionRa_24|stage7.input.stage6.instruction_ra_virtual.InstructionRa_24|stage7.input.stage6.booleanity.InstructionRa_25|stage7.input.stage6.instruction_ra_virtual.InstructionRa_25|stage7.input.stage6.booleanity.InstructionRa_26|stage7.input.stage6.instruction_ra_virtual.InstructionRa_26|stage7.input.stage6.booleanity.InstructionRa_27|stage7.input.stage6.instruction_ra_virtual.InstructionRa_27|stage7.input.stage6.booleanity.InstructionRa_28|stage7.input.stage6.instruction_ra_virtual.InstructionRa_28|stage7.input.stage6.booleanity.InstructionRa_29|stage7.input.stage6.instruction_ra_virtual.InstructionRa_29|stage7.input.stage6.booleanity.InstructionRa_30|stage7.input.stage6.instruction_ra_virtual.InstructionRa_30|stage7.input.stage6.booleanity.InstructionRa_31|stage7.input.stage6.instruction_ra_virtual.InstructionRa_31|stage7.input.stage6.booleanity.BytecodeRa_0|stage7.input.stage6.bytecode_read_raf.BytecodeRa_0|stage7.input.stage6.booleanity.BytecodeRa_1|stage7.input.stage6.bytecode_read_raf.BytecodeRa_1|stage7.input.stage6.booleanity.BytecodeRa_2|stage7.input.stage6.bytecode_read_raf.BytecodeRa_2|stage7.input.stage6.booleanity.BytecodeRa_3|stage7.input.stage6.bytecode_read_raf.BytecodeRa_3|stage7.input.stage6.booleanity.RamRa_0|stage7.input.stage6.ram_ra_virtual.RamRa_0|stage7.input.stage6.booleanity.RamRa_1|stage7.input.stage6.ram_ra_virtual.RamRa_1|stage7.input.stage6.booleanity.RamRa_2|stage7.input.stage6.ram_ra_virtual.RamRa_2|stage7.input.stage6.booleanity.RamRa_3|stage7.input.stage6.ram_ra_virtual.RamRa_3" }, ]; pub const STAGE7_SUMCHECK_BATCH_0_ROUND_SCHEDULE: &[usize] = &[ 4, @@ -246,8 +249,8 @@ pub const STAGE7_SUMCHECK_EVALS: &[Stage7SumcheckEvalPlan] = &[ stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_20", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_20", 20, "InstructionRa_20"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_21", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_21", 21, "InstructionRa_21"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_22", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_22", 22, "InstructionRa_22"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_23", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_23", 23, "InstructionRa_23"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_24", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_24", 24, "InstructionRa_24"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_25", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_25", 25, "InstructionRa_25"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_26", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_26", 26, "InstructionRa_26"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_27", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_27", 27, "InstructionRa_27"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_28", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_28", 28, "InstructionRa_28"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_29", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_29", 29, "InstructionRa_29"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_30", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_30", 30, "InstructionRa_30"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.InstructionRa_31", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.InstructionRa_31", 31, "InstructionRa_31"), - stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.BytecodeRa_0", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_0", 32, "BytecodeRa_0"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.BytecodeRa_1", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_1", 33, "BytecodeRa_1"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.BytecodeRa_2", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_2", 34, "BytecodeRa_2"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.RamRa_0", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.RamRa_0", 35, "RamRa_0"), - stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.RamRa_1", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.RamRa_1", 36, "RamRa_1"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.RamRa_2", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.RamRa_2", 37, "RamRa_2"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.RamRa_3", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.RamRa_3", 38, "RamRa_3"), + stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.BytecodeRa_0", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_0", 32, "BytecodeRa_0"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.BytecodeRa_1", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_1", 33, "BytecodeRa_1"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.BytecodeRa_2", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_2", 34, "BytecodeRa_2"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.BytecodeRa_3", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_3", 35, "BytecodeRa_3"), + stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.RamRa_0", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.RamRa_0", 36, "RamRa_0"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.RamRa_1", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.RamRa_1", 37, "RamRa_1"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.RamRa_2", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.RamRa_2", 38, "RamRa_2"), stage7_sumcheck_eval!("stage7.hamming_weight_claim_reduction.eval.RamRa_3", "stage7.sumcheck", "stage7.hamming_weight_claim_reduction.eval.RamRa_3", 39, "RamRa_3"), ]; pub const STAGE7_POINT_ZEROS: &[Stage7PointZeroPlan] = &[ @@ -255,52 +258,53 @@ pub const STAGE7_POINT_ZEROS: &[Stage7PointZeroPlan] = &[ ]; pub const STAGE7_POINT_SLICES: &[Stage7PointSlicePlan] = &[ - Stage7PointSlicePlan { symbol: "stage7.hamming_weight_claim_reduction.point.cycle", source: "stage7.input.stage6.booleanity.InstructionRa_0", offset: 4, length: 16, input: "stage7.input.stage6.booleanity.InstructionRa_0" }, + Stage7PointSlicePlan { symbol: "stage7.hamming_weight_claim_reduction.point.cycle", source: "stage7.input.stage6.booleanity.InstructionRa_0", offset: 4, length: 18, input: "stage7.input.stage6.booleanity.InstructionRa_0" }, ]; pub const STAGE7_POINT_CONCATS: &[Stage7PointConcatPlan] = &[ - Stage7PointConcatPlan { symbol: "stage7.hamming_weight_claim_reduction.point", layout: "address_chunk_then_cycle", arity: 20, inputs: "stage7.hamming_weight_claim_reduction.instance|stage7.hamming_weight_claim_reduction.point.cycle" }, + Stage7PointConcatPlan { symbol: "stage7.hamming_weight_claim_reduction.point", layout: "address_chunk_then_cycle", arity: 22, inputs: "stage7.hamming_weight_claim_reduction.instance|stage7.hamming_weight_claim_reduction.point.cycle" }, ]; pub const STAGE7_OPENING_CLAIMS: &[Stage7OpeningClaimPlan] = &[ - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_0" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_1" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_2" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_3" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_4" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_5" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_6" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_7" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_8" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_9" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_10" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_11" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_12" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_13" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_14" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_15" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_16" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_17" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_18" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_19" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_20" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_21" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_22" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_23" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_24" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_25" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_26" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_27" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_28" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_29" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_30" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_31" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_0" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_1" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_2" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.RamRa_0" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.RamRa_1" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.RamRa_2" }, - Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.RamRa_3" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_0" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_1" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_2" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_3" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_4" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_5" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_6" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_7" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_8" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_9" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_10" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_11" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_12" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_13" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_14" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_15" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_16" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_17" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_18" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_19" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_20" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_21" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_22" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_23" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_24" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_25" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_26" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_27" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_28" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_29" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_30" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_31" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_0" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_1" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_2" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.BytecodeRa_3", oracle: "BytecodeRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_3" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.RamRa_0" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.RamRa_1" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.RamRa_2" }, + Stage7OpeningClaimPlan { symbol: "stage7.hamming_weight_claim_reduction.opening.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed", point_source: "stage7.hamming_weight_claim_reduction.point", eval_source: "stage7.hamming_weight_claim_reduction.eval.RamRa_3" }, ]; pub const STAGE7_OPENING_EQUALITIES: &[Stage7OpeningClaimEqualityPlan] = &[ @@ -308,7 +312,7 @@ pub const STAGE7_OPENING_EQUALITIES: &[Stage7OpeningClaimEqualityPlan] = &[ ]; pub const STAGE7_OPENING_BATCHES: &[Stage7OpeningBatchPlan] = &[ - Stage7OpeningBatchPlan { symbol: "stage7.openings", stage: "stage7", proof_slot: "stage7.openings", policy: "jolt_stage7_output_order", count: 39, ordered_claims: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_0|stage7.hamming_weight_claim_reduction.opening.InstructionRa_1|stage7.hamming_weight_claim_reduction.opening.InstructionRa_2|stage7.hamming_weight_claim_reduction.opening.InstructionRa_3|stage7.hamming_weight_claim_reduction.opening.InstructionRa_4|stage7.hamming_weight_claim_reduction.opening.InstructionRa_5|stage7.hamming_weight_claim_reduction.opening.InstructionRa_6|stage7.hamming_weight_claim_reduction.opening.InstructionRa_7|stage7.hamming_weight_claim_reduction.opening.InstructionRa_8|stage7.hamming_weight_claim_reduction.opening.InstructionRa_9|stage7.hamming_weight_claim_reduction.opening.InstructionRa_10|stage7.hamming_weight_claim_reduction.opening.InstructionRa_11|stage7.hamming_weight_claim_reduction.opening.InstructionRa_12|stage7.hamming_weight_claim_reduction.opening.InstructionRa_13|stage7.hamming_weight_claim_reduction.opening.InstructionRa_14|stage7.hamming_weight_claim_reduction.opening.InstructionRa_15|stage7.hamming_weight_claim_reduction.opening.InstructionRa_16|stage7.hamming_weight_claim_reduction.opening.InstructionRa_17|stage7.hamming_weight_claim_reduction.opening.InstructionRa_18|stage7.hamming_weight_claim_reduction.opening.InstructionRa_19|stage7.hamming_weight_claim_reduction.opening.InstructionRa_20|stage7.hamming_weight_claim_reduction.opening.InstructionRa_21|stage7.hamming_weight_claim_reduction.opening.InstructionRa_22|stage7.hamming_weight_claim_reduction.opening.InstructionRa_23|stage7.hamming_weight_claim_reduction.opening.InstructionRa_24|stage7.hamming_weight_claim_reduction.opening.InstructionRa_25|stage7.hamming_weight_claim_reduction.opening.InstructionRa_26|stage7.hamming_weight_claim_reduction.opening.InstructionRa_27|stage7.hamming_weight_claim_reduction.opening.InstructionRa_28|stage7.hamming_weight_claim_reduction.opening.InstructionRa_29|stage7.hamming_weight_claim_reduction.opening.InstructionRa_30|stage7.hamming_weight_claim_reduction.opening.InstructionRa_31|stage7.hamming_weight_claim_reduction.opening.BytecodeRa_0|stage7.hamming_weight_claim_reduction.opening.BytecodeRa_1|stage7.hamming_weight_claim_reduction.opening.BytecodeRa_2|stage7.hamming_weight_claim_reduction.opening.RamRa_0|stage7.hamming_weight_claim_reduction.opening.RamRa_1|stage7.hamming_weight_claim_reduction.opening.RamRa_2|stage7.hamming_weight_claim_reduction.opening.RamRa_3", claim_operands: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_0|stage7.hamming_weight_claim_reduction.opening.InstructionRa_1|stage7.hamming_weight_claim_reduction.opening.InstructionRa_2|stage7.hamming_weight_claim_reduction.opening.InstructionRa_3|stage7.hamming_weight_claim_reduction.opening.InstructionRa_4|stage7.hamming_weight_claim_reduction.opening.InstructionRa_5|stage7.hamming_weight_claim_reduction.opening.InstructionRa_6|stage7.hamming_weight_claim_reduction.opening.InstructionRa_7|stage7.hamming_weight_claim_reduction.opening.InstructionRa_8|stage7.hamming_weight_claim_reduction.opening.InstructionRa_9|stage7.hamming_weight_claim_reduction.opening.InstructionRa_10|stage7.hamming_weight_claim_reduction.opening.InstructionRa_11|stage7.hamming_weight_claim_reduction.opening.InstructionRa_12|stage7.hamming_weight_claim_reduction.opening.InstructionRa_13|stage7.hamming_weight_claim_reduction.opening.InstructionRa_14|stage7.hamming_weight_claim_reduction.opening.InstructionRa_15|stage7.hamming_weight_claim_reduction.opening.InstructionRa_16|stage7.hamming_weight_claim_reduction.opening.InstructionRa_17|stage7.hamming_weight_claim_reduction.opening.InstructionRa_18|stage7.hamming_weight_claim_reduction.opening.InstructionRa_19|stage7.hamming_weight_claim_reduction.opening.InstructionRa_20|stage7.hamming_weight_claim_reduction.opening.InstructionRa_21|stage7.hamming_weight_claim_reduction.opening.InstructionRa_22|stage7.hamming_weight_claim_reduction.opening.InstructionRa_23|stage7.hamming_weight_claim_reduction.opening.InstructionRa_24|stage7.hamming_weight_claim_reduction.opening.InstructionRa_25|stage7.hamming_weight_claim_reduction.opening.InstructionRa_26|stage7.hamming_weight_claim_reduction.opening.InstructionRa_27|stage7.hamming_weight_claim_reduction.opening.InstructionRa_28|stage7.hamming_weight_claim_reduction.opening.InstructionRa_29|stage7.hamming_weight_claim_reduction.opening.InstructionRa_30|stage7.hamming_weight_claim_reduction.opening.InstructionRa_31|stage7.hamming_weight_claim_reduction.opening.BytecodeRa_0|stage7.hamming_weight_claim_reduction.opening.BytecodeRa_1|stage7.hamming_weight_claim_reduction.opening.BytecodeRa_2|stage7.hamming_weight_claim_reduction.opening.RamRa_0|stage7.hamming_weight_claim_reduction.opening.RamRa_1|stage7.hamming_weight_claim_reduction.opening.RamRa_2|stage7.hamming_weight_claim_reduction.opening.RamRa_3" }, + Stage7OpeningBatchPlan { symbol: "stage7.openings", stage: "stage7", proof_slot: "stage7.openings", policy: "jolt_stage7_output_order", count: 40, ordered_claims: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_0|stage7.hamming_weight_claim_reduction.opening.InstructionRa_1|stage7.hamming_weight_claim_reduction.opening.InstructionRa_2|stage7.hamming_weight_claim_reduction.opening.InstructionRa_3|stage7.hamming_weight_claim_reduction.opening.InstructionRa_4|stage7.hamming_weight_claim_reduction.opening.InstructionRa_5|stage7.hamming_weight_claim_reduction.opening.InstructionRa_6|stage7.hamming_weight_claim_reduction.opening.InstructionRa_7|stage7.hamming_weight_claim_reduction.opening.InstructionRa_8|stage7.hamming_weight_claim_reduction.opening.InstructionRa_9|stage7.hamming_weight_claim_reduction.opening.InstructionRa_10|stage7.hamming_weight_claim_reduction.opening.InstructionRa_11|stage7.hamming_weight_claim_reduction.opening.InstructionRa_12|stage7.hamming_weight_claim_reduction.opening.InstructionRa_13|stage7.hamming_weight_claim_reduction.opening.InstructionRa_14|stage7.hamming_weight_claim_reduction.opening.InstructionRa_15|stage7.hamming_weight_claim_reduction.opening.InstructionRa_16|stage7.hamming_weight_claim_reduction.opening.InstructionRa_17|stage7.hamming_weight_claim_reduction.opening.InstructionRa_18|stage7.hamming_weight_claim_reduction.opening.InstructionRa_19|stage7.hamming_weight_claim_reduction.opening.InstructionRa_20|stage7.hamming_weight_claim_reduction.opening.InstructionRa_21|stage7.hamming_weight_claim_reduction.opening.InstructionRa_22|stage7.hamming_weight_claim_reduction.opening.InstructionRa_23|stage7.hamming_weight_claim_reduction.opening.InstructionRa_24|stage7.hamming_weight_claim_reduction.opening.InstructionRa_25|stage7.hamming_weight_claim_reduction.opening.InstructionRa_26|stage7.hamming_weight_claim_reduction.opening.InstructionRa_27|stage7.hamming_weight_claim_reduction.opening.InstructionRa_28|stage7.hamming_weight_claim_reduction.opening.InstructionRa_29|stage7.hamming_weight_claim_reduction.opening.InstructionRa_30|stage7.hamming_weight_claim_reduction.opening.InstructionRa_31|stage7.hamming_weight_claim_reduction.opening.BytecodeRa_0|stage7.hamming_weight_claim_reduction.opening.BytecodeRa_1|stage7.hamming_weight_claim_reduction.opening.BytecodeRa_2|stage7.hamming_weight_claim_reduction.opening.BytecodeRa_3|stage7.hamming_weight_claim_reduction.opening.RamRa_0|stage7.hamming_weight_claim_reduction.opening.RamRa_1|stage7.hamming_weight_claim_reduction.opening.RamRa_2|stage7.hamming_weight_claim_reduction.opening.RamRa_3", claim_operands: "stage7.hamming_weight_claim_reduction.opening.InstructionRa_0|stage7.hamming_weight_claim_reduction.opening.InstructionRa_1|stage7.hamming_weight_claim_reduction.opening.InstructionRa_2|stage7.hamming_weight_claim_reduction.opening.InstructionRa_3|stage7.hamming_weight_claim_reduction.opening.InstructionRa_4|stage7.hamming_weight_claim_reduction.opening.InstructionRa_5|stage7.hamming_weight_claim_reduction.opening.InstructionRa_6|stage7.hamming_weight_claim_reduction.opening.InstructionRa_7|stage7.hamming_weight_claim_reduction.opening.InstructionRa_8|stage7.hamming_weight_claim_reduction.opening.InstructionRa_9|stage7.hamming_weight_claim_reduction.opening.InstructionRa_10|stage7.hamming_weight_claim_reduction.opening.InstructionRa_11|stage7.hamming_weight_claim_reduction.opening.InstructionRa_12|stage7.hamming_weight_claim_reduction.opening.InstructionRa_13|stage7.hamming_weight_claim_reduction.opening.InstructionRa_14|stage7.hamming_weight_claim_reduction.opening.InstructionRa_15|stage7.hamming_weight_claim_reduction.opening.InstructionRa_16|stage7.hamming_weight_claim_reduction.opening.InstructionRa_17|stage7.hamming_weight_claim_reduction.opening.InstructionRa_18|stage7.hamming_weight_claim_reduction.opening.InstructionRa_19|stage7.hamming_weight_claim_reduction.opening.InstructionRa_20|stage7.hamming_weight_claim_reduction.opening.InstructionRa_21|stage7.hamming_weight_claim_reduction.opening.InstructionRa_22|stage7.hamming_weight_claim_reduction.opening.InstructionRa_23|stage7.hamming_weight_claim_reduction.opening.InstructionRa_24|stage7.hamming_weight_claim_reduction.opening.InstructionRa_25|stage7.hamming_weight_claim_reduction.opening.InstructionRa_26|stage7.hamming_weight_claim_reduction.opening.InstructionRa_27|stage7.hamming_weight_claim_reduction.opening.InstructionRa_28|stage7.hamming_weight_claim_reduction.opening.InstructionRa_29|stage7.hamming_weight_claim_reduction.opening.InstructionRa_30|stage7.hamming_weight_claim_reduction.opening.InstructionRa_31|stage7.hamming_weight_claim_reduction.opening.BytecodeRa_0|stage7.hamming_weight_claim_reduction.opening.BytecodeRa_1|stage7.hamming_weight_claim_reduction.opening.BytecodeRa_2|stage7.hamming_weight_claim_reduction.opening.BytecodeRa_3|stage7.hamming_weight_claim_reduction.opening.RamRa_0|stage7.hamming_weight_claim_reduction.opening.RamRa_1|stage7.hamming_weight_claim_reduction.opening.RamRa_2|stage7.hamming_weight_claim_reduction.opening.RamRa_3" }, ]; pub const STAGE7_PROGRAM: Stage7VerifierProgramPlan = Stage7CpuProgramPlan { role: "verifier", diff --git a/crates/jolt-verifier/src/stages/stage8.rs b/crates/jolt-verifier/src/stages/stage8.rs index 6d245c8ba9..497a8b7469 100644 --- a/crates/jolt-verifier/src/stages/stage8.rs +++ b/crates/jolt-verifier/src/stages/stage8.rs @@ -64,100 +64,102 @@ pub struct Stage8EvaluationProgramPlan { pub const STAGE8_PARAMS: Stage8Params = Stage8Params { field: "bn254_fr", pcs: "dory", transcript: "blake2b_transcript" }; -pub const STAGE8_EVALUATION_POINT_SOURCE: Stage8OpeningInputPlan = Stage8OpeningInputPlan { symbol: "stage8.evaluation.point_source", source_stage: "stage7", source_claim: "stage7.input.stage6.booleanity.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }; +pub const STAGE8_EVALUATION_POINT_SOURCE: Stage8OpeningInputPlan = Stage8OpeningInputPlan { symbol: "stage8.evaluation.point_source", source_stage: "stage7", source_claim: "stage7.input.stage6.booleanity.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }; pub const STAGE8_OPENING_INPUTS: &[Stage8OpeningInputPlan] = &[ - Stage8OpeningInputPlan { symbol: "stage8.evaluation.point_source", source_stage: "stage7", source_claim: "stage7.input.stage6.booleanity.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage6.RamInc", source_stage: "stage6", source_claim: "stage6.inc_claim_reduction.eval.RamInc", oracle: "RamInc", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage6.RdInc", source_stage: "stage6", source_claim: "stage6.inc_claim_reduction.eval.RdInc", oracle: "RdInc", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_3", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_4", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_5", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_6", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_7", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_8", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_9", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_10", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_11", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_12", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_13", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_14", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_15", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_16", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_17", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_18", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_19", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_20", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_21", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_22", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_23", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_24", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_25", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_26", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_27", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_28", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_29", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_30", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_31", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.BytecodeRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.BytecodeRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.BytecodeRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.RamRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.RamRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.RamRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, - Stage8OpeningInputPlan { symbol: "stage8.input.stage7.RamRa_3", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 20, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.evaluation.point_source", source_stage: "stage7", source_claim: "stage7.input.stage6.booleanity.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage6.RamInc", source_stage: "stage6", source_claim: "stage6.inc_claim_reduction.eval.RamInc", oracle: "RamInc", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage6.RdInc", source_stage: "stage6", source_claim: "stage6.inc_claim_reduction.eval.RdInc", oracle: "RdInc", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_0", oracle: "InstructionRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_1", oracle: "InstructionRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_2", oracle: "InstructionRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_3", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_3", oracle: "InstructionRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_4", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_4", oracle: "InstructionRa_4", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_5", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_5", oracle: "InstructionRa_5", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_6", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_6", oracle: "InstructionRa_6", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_7", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_7", oracle: "InstructionRa_7", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_8", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_8", oracle: "InstructionRa_8", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_9", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_9", oracle: "InstructionRa_9", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_10", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_10", oracle: "InstructionRa_10", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_11", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_11", oracle: "InstructionRa_11", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_12", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_12", oracle: "InstructionRa_12", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_13", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_13", oracle: "InstructionRa_13", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_14", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_14", oracle: "InstructionRa_14", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_15", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_15", oracle: "InstructionRa_15", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_16", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_16", oracle: "InstructionRa_16", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_17", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_17", oracle: "InstructionRa_17", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_18", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_18", oracle: "InstructionRa_18", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_19", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_19", oracle: "InstructionRa_19", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_20", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_20", oracle: "InstructionRa_20", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_21", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_21", oracle: "InstructionRa_21", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_22", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_22", oracle: "InstructionRa_22", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_23", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_23", oracle: "InstructionRa_23", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_24", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_24", oracle: "InstructionRa_24", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_25", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_25", oracle: "InstructionRa_25", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_26", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_26", oracle: "InstructionRa_26", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_27", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_27", oracle: "InstructionRa_27", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_28", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_28", oracle: "InstructionRa_28", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_29", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_29", oracle: "InstructionRa_29", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_30", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_30", oracle: "InstructionRa_30", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.InstructionRa_31", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_31", oracle: "InstructionRa_31", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.BytecodeRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_0", oracle: "BytecodeRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.BytecodeRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_1", oracle: "BytecodeRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.BytecodeRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_2", oracle: "BytecodeRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.BytecodeRa_3", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_3", oracle: "BytecodeRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.RamRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_0", oracle: "RamRa_0", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.RamRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_1", oracle: "RamRa_1", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.RamRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_2", oracle: "RamRa_2", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, + Stage8OpeningInputPlan { symbol: "stage8.input.stage7.RamRa_3", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_3", oracle: "RamRa_3", domain: "jolt.main_witness_commit_domain", point_arity: 22, claim_kind: "committed" }, ]; pub const STAGE8_OPENING_CLAIMS: &[Stage8OpeningClaimPlan] = &[ - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RamInc", oracle: "RamInc", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage6.RamInc", eval_source: "stage8.input.stage6.RamInc", source_stage: "stage6", source_claim: "stage6.inc_claim_reduction.eval.RamInc" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RdInc", oracle: "RdInc", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage6.RdInc", eval_source: "stage8.input.stage6.RdInc", source_stage: "stage6", source_claim: "stage6.inc_claim_reduction.eval.RdInc" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_0", oracle: "InstructionRa_0", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_0", eval_source: "stage8.input.stage7.InstructionRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_0" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_1", oracle: "InstructionRa_1", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_1", eval_source: "stage8.input.stage7.InstructionRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_1" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_2", oracle: "InstructionRa_2", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_2", eval_source: "stage8.input.stage7.InstructionRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_2" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_3", oracle: "InstructionRa_3", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_3", eval_source: "stage8.input.stage7.InstructionRa_3", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_3" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_4", oracle: "InstructionRa_4", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_4", eval_source: "stage8.input.stage7.InstructionRa_4", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_4" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_5", oracle: "InstructionRa_5", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_5", eval_source: "stage8.input.stage7.InstructionRa_5", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_5" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_6", oracle: "InstructionRa_6", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_6", eval_source: "stage8.input.stage7.InstructionRa_6", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_6" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_7", oracle: "InstructionRa_7", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_7", eval_source: "stage8.input.stage7.InstructionRa_7", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_7" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_8", oracle: "InstructionRa_8", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_8", eval_source: "stage8.input.stage7.InstructionRa_8", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_8" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_9", oracle: "InstructionRa_9", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_9", eval_source: "stage8.input.stage7.InstructionRa_9", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_9" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_10", oracle: "InstructionRa_10", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_10", eval_source: "stage8.input.stage7.InstructionRa_10", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_10" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_11", oracle: "InstructionRa_11", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_11", eval_source: "stage8.input.stage7.InstructionRa_11", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_11" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_12", oracle: "InstructionRa_12", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_12", eval_source: "stage8.input.stage7.InstructionRa_12", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_12" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_13", oracle: "InstructionRa_13", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_13", eval_source: "stage8.input.stage7.InstructionRa_13", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_13" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_14", oracle: "InstructionRa_14", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_14", eval_source: "stage8.input.stage7.InstructionRa_14", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_14" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_15", oracle: "InstructionRa_15", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_15", eval_source: "stage8.input.stage7.InstructionRa_15", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_15" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_16", oracle: "InstructionRa_16", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_16", eval_source: "stage8.input.stage7.InstructionRa_16", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_16" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_17", oracle: "InstructionRa_17", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_17", eval_source: "stage8.input.stage7.InstructionRa_17", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_17" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_18", oracle: "InstructionRa_18", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_18", eval_source: "stage8.input.stage7.InstructionRa_18", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_18" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_19", oracle: "InstructionRa_19", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_19", eval_source: "stage8.input.stage7.InstructionRa_19", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_19" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_20", oracle: "InstructionRa_20", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_20", eval_source: "stage8.input.stage7.InstructionRa_20", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_20" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_21", oracle: "InstructionRa_21", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_21", eval_source: "stage8.input.stage7.InstructionRa_21", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_21" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_22", oracle: "InstructionRa_22", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_22", eval_source: "stage8.input.stage7.InstructionRa_22", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_22" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_23", oracle: "InstructionRa_23", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_23", eval_source: "stage8.input.stage7.InstructionRa_23", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_23" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_24", oracle: "InstructionRa_24", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_24", eval_source: "stage8.input.stage7.InstructionRa_24", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_24" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_25", oracle: "InstructionRa_25", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_25", eval_source: "stage8.input.stage7.InstructionRa_25", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_25" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_26", oracle: "InstructionRa_26", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_26", eval_source: "stage8.input.stage7.InstructionRa_26", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_26" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_27", oracle: "InstructionRa_27", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_27", eval_source: "stage8.input.stage7.InstructionRa_27", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_27" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_28", oracle: "InstructionRa_28", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_28", eval_source: "stage8.input.stage7.InstructionRa_28", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_28" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_29", oracle: "InstructionRa_29", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_29", eval_source: "stage8.input.stage7.InstructionRa_29", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_29" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_30", oracle: "InstructionRa_30", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_30", eval_source: "stage8.input.stage7.InstructionRa_30", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_30" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_31", oracle: "InstructionRa_31", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.InstructionRa_31", eval_source: "stage8.input.stage7.InstructionRa_31", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_31" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.BytecodeRa_0", oracle: "BytecodeRa_0", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.BytecodeRa_0", eval_source: "stage8.input.stage7.BytecodeRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_0" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.BytecodeRa_1", oracle: "BytecodeRa_1", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.BytecodeRa_1", eval_source: "stage8.input.stage7.BytecodeRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_1" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.BytecodeRa_2", oracle: "BytecodeRa_2", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.BytecodeRa_2", eval_source: "stage8.input.stage7.BytecodeRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_2" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RamRa_0", oracle: "RamRa_0", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.RamRa_0", eval_source: "stage8.input.stage7.RamRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_0" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RamRa_1", oracle: "RamRa_1", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.RamRa_1", eval_source: "stage8.input.stage7.RamRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_1" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RamRa_2", oracle: "RamRa_2", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.RamRa_2", eval_source: "stage8.input.stage7.RamRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_2" }, - Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RamRa_3", oracle: "RamRa_3", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 20, point_source: "stage8.input.stage7.RamRa_3", eval_source: "stage8.input.stage7.RamRa_3", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_3" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RamInc", oracle: "RamInc", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage6.RamInc", eval_source: "stage8.input.stage6.RamInc", source_stage: "stage6", source_claim: "stage6.inc_claim_reduction.eval.RamInc" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RdInc", oracle: "RdInc", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage6.RdInc", eval_source: "stage8.input.stage6.RdInc", source_stage: "stage6", source_claim: "stage6.inc_claim_reduction.eval.RdInc" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_0", oracle: "InstructionRa_0", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_0", eval_source: "stage8.input.stage7.InstructionRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_0" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_1", oracle: "InstructionRa_1", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_1", eval_source: "stage8.input.stage7.InstructionRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_1" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_2", oracle: "InstructionRa_2", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_2", eval_source: "stage8.input.stage7.InstructionRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_2" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_3", oracle: "InstructionRa_3", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_3", eval_source: "stage8.input.stage7.InstructionRa_3", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_3" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_4", oracle: "InstructionRa_4", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_4", eval_source: "stage8.input.stage7.InstructionRa_4", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_4" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_5", oracle: "InstructionRa_5", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_5", eval_source: "stage8.input.stage7.InstructionRa_5", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_5" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_6", oracle: "InstructionRa_6", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_6", eval_source: "stage8.input.stage7.InstructionRa_6", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_6" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_7", oracle: "InstructionRa_7", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_7", eval_source: "stage8.input.stage7.InstructionRa_7", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_7" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_8", oracle: "InstructionRa_8", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_8", eval_source: "stage8.input.stage7.InstructionRa_8", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_8" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_9", oracle: "InstructionRa_9", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_9", eval_source: "stage8.input.stage7.InstructionRa_9", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_9" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_10", oracle: "InstructionRa_10", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_10", eval_source: "stage8.input.stage7.InstructionRa_10", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_10" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_11", oracle: "InstructionRa_11", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_11", eval_source: "stage8.input.stage7.InstructionRa_11", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_11" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_12", oracle: "InstructionRa_12", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_12", eval_source: "stage8.input.stage7.InstructionRa_12", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_12" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_13", oracle: "InstructionRa_13", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_13", eval_source: "stage8.input.stage7.InstructionRa_13", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_13" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_14", oracle: "InstructionRa_14", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_14", eval_source: "stage8.input.stage7.InstructionRa_14", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_14" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_15", oracle: "InstructionRa_15", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_15", eval_source: "stage8.input.stage7.InstructionRa_15", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_15" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_16", oracle: "InstructionRa_16", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_16", eval_source: "stage8.input.stage7.InstructionRa_16", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_16" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_17", oracle: "InstructionRa_17", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_17", eval_source: "stage8.input.stage7.InstructionRa_17", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_17" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_18", oracle: "InstructionRa_18", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_18", eval_source: "stage8.input.stage7.InstructionRa_18", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_18" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_19", oracle: "InstructionRa_19", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_19", eval_source: "stage8.input.stage7.InstructionRa_19", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_19" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_20", oracle: "InstructionRa_20", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_20", eval_source: "stage8.input.stage7.InstructionRa_20", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_20" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_21", oracle: "InstructionRa_21", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_21", eval_source: "stage8.input.stage7.InstructionRa_21", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_21" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_22", oracle: "InstructionRa_22", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_22", eval_source: "stage8.input.stage7.InstructionRa_22", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_22" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_23", oracle: "InstructionRa_23", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_23", eval_source: "stage8.input.stage7.InstructionRa_23", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_23" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_24", oracle: "InstructionRa_24", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_24", eval_source: "stage8.input.stage7.InstructionRa_24", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_24" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_25", oracle: "InstructionRa_25", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_25", eval_source: "stage8.input.stage7.InstructionRa_25", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_25" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_26", oracle: "InstructionRa_26", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_26", eval_source: "stage8.input.stage7.InstructionRa_26", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_26" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_27", oracle: "InstructionRa_27", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_27", eval_source: "stage8.input.stage7.InstructionRa_27", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_27" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_28", oracle: "InstructionRa_28", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_28", eval_source: "stage8.input.stage7.InstructionRa_28", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_28" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_29", oracle: "InstructionRa_29", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_29", eval_source: "stage8.input.stage7.InstructionRa_29", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_29" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_30", oracle: "InstructionRa_30", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_30", eval_source: "stage8.input.stage7.InstructionRa_30", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_30" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.InstructionRa_31", oracle: "InstructionRa_31", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.InstructionRa_31", eval_source: "stage8.input.stage7.InstructionRa_31", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.InstructionRa_31" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.BytecodeRa_0", oracle: "BytecodeRa_0", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.BytecodeRa_0", eval_source: "stage8.input.stage7.BytecodeRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_0" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.BytecodeRa_1", oracle: "BytecodeRa_1", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.BytecodeRa_1", eval_source: "stage8.input.stage7.BytecodeRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_1" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.BytecodeRa_2", oracle: "BytecodeRa_2", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.BytecodeRa_2", eval_source: "stage8.input.stage7.BytecodeRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_2" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.BytecodeRa_3", oracle: "BytecodeRa_3", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.BytecodeRa_3", eval_source: "stage8.input.stage7.BytecodeRa_3", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.BytecodeRa_3" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RamRa_0", oracle: "RamRa_0", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.RamRa_0", eval_source: "stage8.input.stage7.RamRa_0", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_0" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RamRa_1", oracle: "RamRa_1", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.RamRa_1", eval_source: "stage8.input.stage7.RamRa_1", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_1" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RamRa_2", oracle: "RamRa_2", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.RamRa_2", eval_source: "stage8.input.stage7.RamRa_2", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_2" }, + Stage8OpeningClaimPlan { symbol: "stage8.evaluation.opening.RamRa_3", oracle: "RamRa_3", family: "jolt.main_witness_polys", domain: "jolt.main_witness_commit_domain", point_arity: 22, point_source: "stage8.input.stage7.RamRa_3", eval_source: "stage8.input.stage7.RamRa_3", source_stage: "stage7", source_claim: "stage7.hamming_weight_claim_reduction.eval.RamRa_3" }, ]; -pub const STAGE8_OPENING_BATCH_ORDERED_CLAIMS: &[&str] = &["stage8.evaluation.opening.RamInc", "stage8.evaluation.opening.RdInc", "stage8.evaluation.opening.InstructionRa_0", "stage8.evaluation.opening.InstructionRa_1", "stage8.evaluation.opening.InstructionRa_2", "stage8.evaluation.opening.InstructionRa_3", "stage8.evaluation.opening.InstructionRa_4", "stage8.evaluation.opening.InstructionRa_5", "stage8.evaluation.opening.InstructionRa_6", "stage8.evaluation.opening.InstructionRa_7", "stage8.evaluation.opening.InstructionRa_8", "stage8.evaluation.opening.InstructionRa_9", "stage8.evaluation.opening.InstructionRa_10", "stage8.evaluation.opening.InstructionRa_11", "stage8.evaluation.opening.InstructionRa_12", "stage8.evaluation.opening.InstructionRa_13", "stage8.evaluation.opening.InstructionRa_14", "stage8.evaluation.opening.InstructionRa_15", "stage8.evaluation.opening.InstructionRa_16", "stage8.evaluation.opening.InstructionRa_17", "stage8.evaluation.opening.InstructionRa_18", "stage8.evaluation.opening.InstructionRa_19", "stage8.evaluation.opening.InstructionRa_20", "stage8.evaluation.opening.InstructionRa_21", "stage8.evaluation.opening.InstructionRa_22", "stage8.evaluation.opening.InstructionRa_23", "stage8.evaluation.opening.InstructionRa_24", "stage8.evaluation.opening.InstructionRa_25", "stage8.evaluation.opening.InstructionRa_26", "stage8.evaluation.opening.InstructionRa_27", "stage8.evaluation.opening.InstructionRa_28", "stage8.evaluation.opening.InstructionRa_29", "stage8.evaluation.opening.InstructionRa_30", "stage8.evaluation.opening.InstructionRa_31", "stage8.evaluation.opening.BytecodeRa_0", "stage8.evaluation.opening.BytecodeRa_1", "stage8.evaluation.opening.BytecodeRa_2", "stage8.evaluation.opening.RamRa_0", "stage8.evaluation.opening.RamRa_1", "stage8.evaluation.opening.RamRa_2", "stage8.evaluation.opening.RamRa_3"]; +pub const STAGE8_OPENING_BATCH_ORDERED_CLAIMS: &[&str] = &["stage8.evaluation.opening.RamInc", "stage8.evaluation.opening.RdInc", "stage8.evaluation.opening.InstructionRa_0", "stage8.evaluation.opening.InstructionRa_1", "stage8.evaluation.opening.InstructionRa_2", "stage8.evaluation.opening.InstructionRa_3", "stage8.evaluation.opening.InstructionRa_4", "stage8.evaluation.opening.InstructionRa_5", "stage8.evaluation.opening.InstructionRa_6", "stage8.evaluation.opening.InstructionRa_7", "stage8.evaluation.opening.InstructionRa_8", "stage8.evaluation.opening.InstructionRa_9", "stage8.evaluation.opening.InstructionRa_10", "stage8.evaluation.opening.InstructionRa_11", "stage8.evaluation.opening.InstructionRa_12", "stage8.evaluation.opening.InstructionRa_13", "stage8.evaluation.opening.InstructionRa_14", "stage8.evaluation.opening.InstructionRa_15", "stage8.evaluation.opening.InstructionRa_16", "stage8.evaluation.opening.InstructionRa_17", "stage8.evaluation.opening.InstructionRa_18", "stage8.evaluation.opening.InstructionRa_19", "stage8.evaluation.opening.InstructionRa_20", "stage8.evaluation.opening.InstructionRa_21", "stage8.evaluation.opening.InstructionRa_22", "stage8.evaluation.opening.InstructionRa_23", "stage8.evaluation.opening.InstructionRa_24", "stage8.evaluation.opening.InstructionRa_25", "stage8.evaluation.opening.InstructionRa_26", "stage8.evaluation.opening.InstructionRa_27", "stage8.evaluation.opening.InstructionRa_28", "stage8.evaluation.opening.InstructionRa_29", "stage8.evaluation.opening.InstructionRa_30", "stage8.evaluation.opening.InstructionRa_31", "stage8.evaluation.opening.BytecodeRa_0", "stage8.evaluation.opening.BytecodeRa_1", "stage8.evaluation.opening.BytecodeRa_2", "stage8.evaluation.opening.BytecodeRa_3", "stage8.evaluation.opening.RamRa_0", "stage8.evaluation.opening.RamRa_1", "stage8.evaluation.opening.RamRa_2", "stage8.evaluation.opening.RamRa_3"]; -pub const STAGE8_OPENING_BATCH: Stage8OpeningBatchPlan = Stage8OpeningBatchPlan { symbol: "stage8.evaluation.openings", proof_slot: "stage8.evaluation", policy: "jolt_stage8_joint_rlc", count: 41, ordered_claims: STAGE8_OPENING_BATCH_ORDERED_CLAIMS }; +pub const STAGE8_OPENING_BATCH: Stage8OpeningBatchPlan = Stage8OpeningBatchPlan { symbol: "stage8.evaluation.openings", proof_slot: "stage8.evaluation", policy: "jolt_stage8_joint_rlc", count: 42, ordered_claims: STAGE8_OPENING_BATCH_ORDERED_CLAIMS }; pub const STAGE8_PCS_PROOF: Stage8PcsProofPlan = Stage8PcsProofPlan { symbol: "stage8.evaluation.proof", mode: "verify", pcs: "dory", proof_slot: "stage8.evaluation", transcript_label: "rlc_claims", batch: "stage8.evaluation.openings" }; diff --git a/crates/jolt-verifier/src/verifier.rs b/crates/jolt-verifier/src/verifier.rs index f6ad1ecc09..5d1b43bc66 100644 --- a/crates/jolt-verifier/src/verifier.rs +++ b/crates/jolt-verifier/src/verifier.rs @@ -491,3 +491,4 @@ fn commitment_for_oracle( } Err(JoltEvaluationProofError::MissingCommitment { oracle }) } + From 5a4c2448feaa3f2636f6f0034d2b1cd74a73724e Mon Sep 17 00:00:00 2001 From: Sagar Dhawan Date: Fri, 15 May 2026 12:03:36 -0500 Subject: [PATCH 13/14] fix(commitment): pad non-one-hot oracle data to layout num_vars MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The batched commitment plan commits all oracles at the same Dory row_len (derived from layout_num_vars). One-hot oracles already pad to 2^layout_num_vars via AddressMajorOneHotPolynomial; the non-one-hot branch was padding to 2^oracle_num_vars instead, producing fewer rows in the Dory hint vector when oracle_num_vars < layout_num_vars (e.g. RdInc/RamInc at 18 vars in a batch with layout 22). When `joint_opening_hint` later combines hints homomorphically via `combine_hints`, the ragged row counts panic. Even past the panic, the aggregated commitment Σ γᵢ·Cᵢ would not equal the commitment of the joint polynomial, which is materialized at main_num_vars — verification would fail. Both bolt-emit sites (the muldiv-sparse fast path and the generic commit_batch fallback) now pad to layout_num_vars / plan.num_vars to match the one-hot side. This surfaced trying to prove muldiv through the modular SDK; previously masked because the only e2e test that exercises this path (jolt-equivalence) doesn't currently compile. --- crates/bolt/src/protocols/jolt/emit/rust/commitment.rs | 8 ++++++-- crates/jolt-prover/src/stages/commitment.rs | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/crates/bolt/src/protocols/jolt/emit/rust/commitment.rs b/crates/bolt/src/protocols/jolt/emit/rust/commitment.rs index 66186d2419..defe5c58c1 100644 --- a/crates/bolt/src/protocols/jolt/emit/rust/commitment.rs +++ b/crates/bolt/src/protocols/jolt/emit/rust/commitment.rs @@ -725,7 +725,11 @@ impl<'a> SparseCommitmentInputs<'a> { .materialize_oracle(oracle, oracle_num_vars) .flatten() .ok_or(CommitmentPhaseError::MissingOracle { oracle })?; - let data = into_padded_oracle(oracle, oracle_num_vars, Cow::Owned(data))?; + // Pad to layout_num_vars (not oracle_num_vars) so the row-chunked + // commitment has uniform row-count across all oracles in the batch. + // Required for `joint_opening_hint`'s `combine_hints` to produce a + // valid aggregate commitment. + let data = into_padded_oracle(oracle, layout_num_vars, Cow::Owned(data))?; commit_with_layout(&data, layout_num_vars, prover_setup) } } @@ -1267,7 +1271,7 @@ where .materialize_with_num_vars(oracle, oracle_num_vars(program, oracle, plan.num_vars)) .ok_or(CommitmentPhaseError::MissingOracle { oracle })?; let oracle_num_vars = oracle_num_vars(program, oracle, plan.num_vars); - let data = into_padded_oracle(oracle, oracle_num_vars, data)?; + let data = into_padded_oracle(oracle, plan.num_vars, data)?; let (commitment, hint) = commit_with_layout(&data, plan.num_vars, prover_setup)?; artifacts.records.push(CommitmentRecord { artifact: plan.artifact, diff --git a/crates/jolt-prover/src/stages/commitment.rs b/crates/jolt-prover/src/stages/commitment.rs index fb8961cc33..4eaf31aafe 100644 --- a/crates/jolt-prover/src/stages/commitment.rs +++ b/crates/jolt-prover/src/stages/commitment.rs @@ -448,7 +448,11 @@ impl<'a> SparseCommitmentInputs<'a> { .materialize_oracle(oracle, oracle_num_vars) .flatten() .ok_or(CommitmentPhaseError::MissingOracle { oracle })?; - let data = into_padded_oracle(oracle, oracle_num_vars, Cow::Owned(data))?; + // Pad to layout_num_vars (not oracle_num_vars) so the row-chunked + // commitment has uniform row-count across all oracles in the batch. + // Required for `joint_opening_hint`'s `combine_hints` to produce a + // valid aggregate commitment. + let data = into_padded_oracle(oracle, layout_num_vars, Cow::Owned(data))?; commit_with_layout(&data, layout_num_vars, prover_setup) } } @@ -932,7 +936,7 @@ where .materialize_with_num_vars(oracle, oracle_num_vars(program, oracle, plan.num_vars)) .ok_or(CommitmentPhaseError::MissingOracle { oracle })?; let oracle_num_vars = oracle_num_vars(program, oracle, plan.num_vars); - let data = into_padded_oracle(oracle, oracle_num_vars, data)?; + let data = into_padded_oracle(oracle, plan.num_vars, data)?; let (commitment, hint) = commit_with_layout(&data, plan.num_vars, prover_setup)?; artifacts.records.push(CommitmentRecord { artifact: plan.artifact, From da05c2b8779808129dbb701d7d1036838c07dbaf Mon Sep 17 00:00:00 2001 From: Sagar Dhawan Date: Fri, 15 May 2026 12:08:42 -0500 Subject: [PATCH 14/14] test(jolt-host): unignore muldiv_modular_prove_smoke Now passes after fix(commitment): the full modular prove+verify round-trip works in default cargo nextest invocation. Previously ignored because the path was broken upstream by the ragged-hint bug. --- crates/jolt-host/tests/prove_program_smoke.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/jolt-host/tests/prove_program_smoke.rs b/crates/jolt-host/tests/prove_program_smoke.rs index e943aa3393..a8b5831c71 100644 --- a/crates/jolt-host/tests/prove_program_smoke.rs +++ b/crates/jolt-host/tests/prove_program_smoke.rs @@ -17,7 +17,6 @@ use jolt_host::{prove_program, verify_proof, ProveProgramError}; use jolt_trace::Program; #[test] -#[ignore = "exercises full modular prove pipeline; requires jolt CLI"] fn muldiv_modular_prove_smoke() { let mut program = Program::new("muldiv-guest"); let inputs = postcard::to_stdvec(&[9u32, 5u32, 3u32]).expect("postcard encode muldiv inputs");