diff --git a/jolt-core/Cargo.toml b/jolt-core/Cargo.toml index 0fd28a725..f6c673b2e 100644 --- a/jolt-core/Cargo.toml +++ b/jolt-core/Cargo.toml @@ -20,7 +20,7 @@ license-file = "LICENSE" keywords = ["SNARK", "cryptography", "proofs"] [dependencies] -jolt-types = { path = "../jolt-types" } +jolt-types = { path = "../jolt-types", default-features = true } ark-bn254 = "0.4.0" ark-ec = { version = "0.4.2", default-features = false } ark-ff = { version = "0.4.2", default-features = false } diff --git a/jolt-core/src/jolt/subtable/srl.rs b/jolt-core/src/jolt/subtable/srl.rs index e1d8bbe65..185f97de5 100644 --- a/jolt-core/src/jolt/subtable/srl.rs +++ b/jolt-core/src/jolt/subtable/srl.rs @@ -1,6 +1,6 @@ use ark_std::log2; -use std::cmp::min; use jolt_types::field::JoltField; +use std::cmp::min; use std::marker::PhantomData; use super::LassoSubtable; diff --git a/jolt-core/src/jolt/vm/instruction_lookups.rs b/jolt-core/src/jolt/vm/instruction_lookups.rs index bb2ab31fd..fc4d501cb 100644 --- a/jolt-core/src/jolt/vm/instruction_lookups.rs +++ b/jolt-core/src/jolt/vm/instruction_lookups.rs @@ -1,3 +1,4 @@ +use super::JoltTraceStep; use crate::jolt::instruction::{JoltInstructionSet, SubtableIndices}; use crate::jolt::subtable::JoltSubtableSet; use crate::lasso::memory_checking::MultisetHashes; @@ -10,13 +11,13 @@ use crate::{ eq_poly::EqPolynomial, identity_poly::IdentityPolynomial, structured_poly::{StructuredCommitment, StructuredOpeningProof}, - unipoly::{CompressedUniPoly, UniPoly}, }, - subprotocols::sumcheck::SumcheckInstanceProof, }; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use itertools::{interleave, Itertools}; use jolt_types::field::JoltField; +use jolt_types::poly::unipoly::{CompressedUniPoly, UniPoly}; +use jolt_types::subprotocols::sumcheck::SumcheckInstanceProof; use jolt_types::utils::mul_0_1_optimized; use jolt_types::utils::{ errors::ProofVerifyError, @@ -28,8 +29,6 @@ use rayon::prelude::*; use std::marker::PhantomData; use tracing::trace_span; -use super::JoltTraceStep; - /// All polynomials associated with Jolt instruction lookups. pub struct InstructionPolynomials where diff --git a/jolt-core/src/jolt/vm/read_write_memory.rs b/jolt-core/src/jolt/vm/read_write_memory.rs index 304826359..d575f696b 100644 --- a/jolt-core/src/jolt/vm/read_write_memory.rs +++ b/jolt-core/src/jolt/vm/read_write_memory.rs @@ -12,6 +12,7 @@ use std::sync::{Arc, Mutex}; use super::JoltTraceStep; use super::{timestamp_range_check::TimestampValidityProof, JoltCommitments, JoltPolynomials}; use crate::poly::commitment::commitment_scheme::{BatchType, CommitShape, CommitmentScheme}; +use crate::subprotocols::sumcheck::SumcheckProve; use crate::{ lasso::memory_checking::{ MemoryCheckingProof, MemoryCheckingProver, MemoryCheckingVerifier, MultisetHashes, @@ -21,7 +22,6 @@ use crate::{ dense_mlpoly::DensePolynomial, eq_poly::EqPolynomial, identity_poly::IdentityPolynomial, structured_poly::StructuredOpeningProof, }, - subprotocols::sumcheck::SumcheckInstanceProof, }; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use common::constants::{ @@ -29,6 +29,7 @@ use common::constants::{ RAM_OPS_PER_INSTRUCTION, RAM_START_ADDRESS, REGISTER_COUNT, REG_OPS_PER_INSTRUCTION, }; use common::rv_trace::{JoltDevice, MemoryLayout, MemoryOp}; +use jolt_types::subprotocols::sumcheck::SumcheckInstanceProof; use jolt_types::utils::transcript::AppendToTranscript; use jolt_types::utils::{ errors::ProofVerifyError, math::Math, mul_0_optimized, transcript::ProofTranscript, diff --git a/jolt-core/src/lasso/surge.rs b/jolt-core/src/lasso/surge.rs index 6fff57a9f..cad73fed0 100644 --- a/jolt-core/src/lasso/surge.rs +++ b/jolt-core/src/lasso/surge.rs @@ -4,6 +4,7 @@ use jolt_types::field::JoltField; use rayon::iter::{IntoParallelIterator, IntoParallelRefIterator, ParallelIterator}; use std::marker::{PhantomData, Sync}; +use crate::subprotocols::sumcheck::SumcheckProve; use crate::{ jolt::instruction::JoltInstruction, lasso::memory_checking::{MemoryCheckingProof, MemoryCheckingProver, MemoryCheckingVerifier}, @@ -14,8 +15,8 @@ use crate::{ identity_poly::IdentityPolynomial, structured_poly::{StructuredCommitment, StructuredOpeningProof}, }, - subprotocols::sumcheck::SumcheckInstanceProof, }; +use jolt_types::subprotocols::sumcheck::SumcheckInstanceProof; use jolt_types::utils::{ errors::ProofVerifyError, math::Math, mul_0_1_optimized, transcript::ProofTranscript, }; diff --git a/jolt-core/src/poly/commitment/hyperkzg.rs b/jolt-core/src/poly/commitment/hyperkzg.rs index 86e089069..113fedce6 100644 --- a/jolt-core/src/poly/commitment/hyperkzg.rs +++ b/jolt-core/src/poly/commitment/hyperkzg.rs @@ -15,7 +15,7 @@ use crate::poly::commitment::commitment_scheme::CommitShape; use crate::utils::thread::unsafe_allocate_zero_vec; use crate::{ msm::VariableBaseMSM, - poly::{commitment::kzg::SRS, dense_mlpoly::DensePolynomial, unipoly::UniPoly}, + poly::{commitment::kzg::SRS, dense_mlpoly::DensePolynomial}, }; use ark_ec::{pairing::Pairing, AffineRepr, CurveGroup}; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; @@ -36,6 +36,7 @@ use std::{marker::PhantomData, sync::Arc}; use tracing::trace_span; pub use jolt_types::poly::commitment::hyperkzg::{HyperKZGProof, HyperKZGVerifierKey}; +use jolt_types::poly::unipoly::UniPoly; pub struct HyperKZGSRS(Arc>); diff --git a/jolt-core/src/poly/commitment/kzg.rs b/jolt-core/src/poly/commitment/kzg.rs index e3798a16a..e3b592db9 100644 --- a/jolt-core/src/poly/commitment/kzg.rs +++ b/jolt-core/src/poly/commitment/kzg.rs @@ -1,10 +1,10 @@ use crate::msm::VariableBaseMSM; -use crate::poly::unipoly::UniPoly; use ark_ec::scalar_mul::fixed_base::FixedBase; use ark_ec::{pairing::Pairing, AffineRepr, CurveGroup}; use ark_ff::PrimeField; use ark_std::{One, UniformRand, Zero}; use jolt_types::field::JoltField; +use jolt_types::poly::unipoly::UniPoly; use jolt_types::utils::errors::ProofVerifyError; use rand_core::{CryptoRng, RngCore}; use std::marker::PhantomData; diff --git a/jolt-core/src/poly/commitment/zeromorph.rs b/jolt-core/src/poly/commitment/zeromorph.rs index 13c5783be..61c873008 100644 --- a/jolt-core/src/poly/commitment/zeromorph.rs +++ b/jolt-core/src/poly/commitment/zeromorph.rs @@ -4,7 +4,7 @@ use std::{iter, marker::PhantomData}; use crate::msm::VariableBaseMSM; -use crate::poly::{dense_mlpoly::DensePolynomial, unipoly::UniPoly}; +use crate::poly::dense_mlpoly::DensePolynomial; use crate::utils::thread::unsafe_allocate_zero_vec; use ark_ec::{pairing::Pairing, AffineRepr, CurveGroup}; use ark_ff::{batch_inversion, Field}; @@ -22,12 +22,12 @@ use rand_core::{CryptoRng, RngCore}; use std::sync::Arc; use tracing::trace_span; -use rayon::prelude::*; - use super::{ commitment_scheme::{BatchType, CommitShape, CommitmentScheme}, kzg::{KZGProverKey, KZGVerifierKey, UnivariateKZG, SRS}, }; +use jolt_types::poly::unipoly::UniPoly; +use rayon::prelude::*; pub struct ZeromorphSRS(Arc>); diff --git a/jolt-core/src/poly/mod.rs b/jolt-core/src/poly/mod.rs index d2480d420..bad28a2a5 100644 --- a/jolt-core/src/poly/mod.rs +++ b/jolt-core/src/poly/mod.rs @@ -3,4 +3,3 @@ pub mod dense_mlpoly; pub mod eq_poly; pub mod identity_poly; pub mod structured_poly; -pub mod unipoly; diff --git a/jolt-core/src/r1cs/spartan.rs b/jolt-core/src/r1cs/spartan.rs index c65f670ea..6e6841aec 100644 --- a/jolt-core/src/r1cs/spartan.rs +++ b/jolt-core/src/r1cs/spartan.rs @@ -14,13 +14,11 @@ use jolt_types::utils::transcript::ProofTranscript; use thiserror::Error; -use crate::{ - poly::{dense_mlpoly::DensePolynomial, eq_poly::EqPolynomial}, - subprotocols::sumcheck::SumcheckInstanceProof, -}; - use super::builder::CombinedUniformBuilder; use super::ops::ConstraintInput; +use crate::poly::{dense_mlpoly::DensePolynomial, eq_poly::EqPolynomial}; +use crate::subprotocols::sumcheck::SumcheckProve; +use jolt_types::subprotocols::sumcheck::SumcheckInstanceProof; #[derive(Clone, Debug, Eq, PartialEq, Error)] pub enum SpartanError { diff --git a/jolt-core/src/subprotocols/grand_product.rs b/jolt-core/src/subprotocols/grand_product.rs index 063f265a8..c772e461f 100644 --- a/jolt-core/src/subprotocols/grand_product.rs +++ b/jolt-core/src/subprotocols/grand_product.rs @@ -1,38 +1,19 @@ use super::grand_product_quarks::QuarkGrandProductProof; -use super::sumcheck::{BatchedCubicSumcheck, SumcheckInstanceProof}; +use super::sumcheck::BatchedCubicSumcheck; use crate::poly::commitment::commitment_scheme::CommitmentScheme; +use crate::poly::dense_mlpoly::DensePolynomial; use crate::poly::eq_poly::EqPolynomial; -use crate::poly::{dense_mlpoly::DensePolynomial, unipoly::UniPoly}; use crate::utils::thread::drop_in_background_thread; use ark_ff::Zero; use ark_serialize::*; use itertools::Itertools; use jolt_types::field::{JoltField, OptimizedMul}; +use jolt_types::poly::unipoly::UniPoly; +use jolt_types::subprotocols::grand_product::BatchedGrandProductLayerProof; use jolt_types::utils::math::Math; use jolt_types::utils::transcript::ProofTranscript; use rayon::prelude::*; -#[derive(CanonicalSerialize, CanonicalDeserialize)] -pub struct BatchedGrandProductLayerProof { - pub proof: SumcheckInstanceProof, - pub left_claims: Vec, - pub right_claims: Vec, -} - -impl BatchedGrandProductLayerProof { - pub fn verify( - &self, - claim: F, - num_rounds: usize, - degree_bound: usize, - transcript: &mut ProofTranscript, - ) -> (F, Vec) { - self.proof - .verify(claim, num_rounds, degree_bound, transcript) - .unwrap() - } -} - #[derive(CanonicalSerialize, CanonicalDeserialize)] pub struct BatchedGrandProductProof { pub layers: Vec>, diff --git a/jolt-core/src/subprotocols/grand_product_quarks.rs b/jolt-core/src/subprotocols/grand_product_quarks.rs index b724c91ea..82a67a08f 100644 --- a/jolt-core/src/subprotocols/grand_product_quarks.rs +++ b/jolt-core/src/subprotocols/grand_product_quarks.rs @@ -2,14 +2,15 @@ use super::grand_product::{ BatchedDenseGrandProductLayer, BatchedGrandProduct, BatchedGrandProductLayer, BatchedGrandProductProof, }; -use super::sumcheck::SumcheckInstanceProof; use crate::poly::commitment::commitment_scheme::{BatchType, CommitmentScheme}; use crate::poly::dense_mlpoly::DensePolynomial; use crate::poly::eq_poly::EqPolynomial; +use crate::subprotocols::sumcheck::SumcheckProve; use ark_serialize::*; use ark_std::{One, Zero}; use itertools::Itertools; use jolt_types::field::JoltField; +use jolt_types::subprotocols::sumcheck::SumcheckInstanceProof; use jolt_types::utils::math::Math; use jolt_types::utils::transcript::{AppendToTranscript, ProofTranscript}; use rayon::prelude::*; diff --git a/jolt-core/src/subprotocols/sumcheck.rs b/jolt-core/src/subprotocols/sumcheck.rs index 747bc7590..908146adf 100644 --- a/jolt-core/src/subprotocols/sumcheck.rs +++ b/jolt-core/src/subprotocols/sumcheck.rs @@ -2,16 +2,68 @@ #![allow(clippy::type_complexity)] use crate::poly::dense_mlpoly::DensePolynomial; -use crate::poly::unipoly::{CompressedUniPoly, UniPoly}; use crate::r1cs::special_polys::{IndexablePoly, SparsePolynomial, SparseTripleIterator}; use crate::utils::thread::drop_in_background_thread; -use ark_serialize::*; use jolt_types::field::JoltField; -use jolt_types::utils::errors::ProofVerifyError; +use jolt_types::poly::unipoly::{CompressedUniPoly, UniPoly}; +use jolt_types::subprotocols::sumcheck::SumcheckInstanceProof; use jolt_types::utils::mul_0_optimized; use jolt_types::utils::transcript::{AppendToTranscript, ProofTranscript}; use rayon::prelude::*; +pub trait SumcheckProve { + fn prove_arbitrary( + claim: &F, + num_rounds: usize, + polys: &mut Vec>, + comb_func: Func, + combined_degree: usize, + transcript: &mut ProofTranscript, + ) -> (Self, Vec, Vec) + where + Func: Fn(&[F]) -> F + std::marker::Sync, + Self: Sized; + + fn compute_eval_points_spartan_cubic( + poly_eq: &DensePolynomial, + poly_A: &SparsePolynomial, + poly_B: &SparsePolynomial, + poly_C: &SparsePolynomial, + comb_func: &Func, + ) -> (F, F, F) + where + Func: Fn(&F, &F, &F, &F) -> F + Sync; + + fn prove_spartan_cubic( + claim: &F, + num_rounds: usize, + poly_eq: &mut DensePolynomial, + poly_A: &mut SparsePolynomial, + poly_B: &mut SparsePolynomial, + poly_C: &mut SparsePolynomial, + comb_func: Func, + transcript: &mut ProofTranscript, + ) -> (Self, Vec, Vec) + where + Func: Fn(&F, &F, &F, &F) -> F + Sync, + Self: Sized; + + fn prove_spartan_quadratic>( + claim: &F, + num_rounds: usize, + poly_A: &mut DensePolynomial, + W: &P, + transcript: &mut ProofTranscript, + ) -> (Self, Vec, Vec) + where + Self: Sized; + + fn compute_eval_points_spartan_quadratic( + poly_A: &DensePolynomial, + poly_B: &DensePolynomial, + ) -> (F, F); +} + /// Batched cubic sumcheck used in grand products pub trait BatchedCubicSumcheck: Sync { fn num_rounds(&self) -> usize; @@ -64,7 +116,7 @@ pub trait BatchedCubicSumcheck: Sync { } } -impl SumcheckInstanceProof { +impl SumcheckProve for SumcheckInstanceProof { /// Create a sumcheck proof for polynomial(s) of arbitrary degree. /// /// Params @@ -78,7 +130,7 @@ impl SumcheckInstanceProof { /// - `r_eval_point`: Final random point of evaluation /// - `final_evals`: Each of the polys evaluated at `r_eval_point` #[tracing::instrument(skip_all, name = "Sumcheck.prove")] - pub fn prove_arbitrary( + fn prove_arbitrary( _claim: &F, num_rounds: usize, polys: &mut Vec>, @@ -182,7 +234,7 @@ impl SumcheckInstanceProof { name = "Spartan2::sumcheck::compute_eval_points_spartan_cubic" )] /// Binds from the bottom rather than the top. - pub fn compute_eval_points_spartan_cubic( + fn compute_eval_points_spartan_cubic( poly_eq: &DensePolynomial, poly_A: &SparsePolynomial, poly_B: &SparsePolynomial, @@ -249,7 +301,7 @@ impl SumcheckInstanceProof { } #[tracing::instrument(skip_all, name = "Spartan2::sumcheck::prove_spartan_cubic")] - pub fn prove_spartan_cubic( + fn prove_spartan_cubic( claim: &F, num_rounds: usize, poly_eq: &mut DensePolynomial, @@ -322,7 +374,7 @@ impl SumcheckInstanceProof { // passing them in as a single `MultilinearPolynomial`, which would require // an expensive concatenation. We defer the actual instantation of a // `MultilinearPolynomial` to the end of the 0th round. - pub fn prove_spartan_quadratic>( + fn prove_spartan_quadratic>( claim: &F, num_rounds: usize, poly_A: &mut DensePolynomial, @@ -454,7 +506,7 @@ impl SumcheckInstanceProof { #[inline] #[tracing::instrument(skip_all, name = "Sumcheck::compute_eval_points_spartan_quadratic")] - pub fn compute_eval_points_spartan_quadratic( + fn compute_eval_points_spartan_quadratic( poly_A: &DensePolynomial, poly_B: &DensePolynomial, ) -> (F, F) { @@ -483,62 +535,3 @@ impl SumcheckInstanceProof { .reduce(|| (F::zero(), F::zero()), |a, b| (a.0 + b.0, a.1 + b.1)) } } - -#[derive(CanonicalSerialize, CanonicalDeserialize, Debug)] -pub struct SumcheckInstanceProof { - pub compressed_polys: Vec>, -} - -impl SumcheckInstanceProof { - pub fn new(compressed_polys: Vec>) -> SumcheckInstanceProof { - SumcheckInstanceProof { compressed_polys } - } - - /// Verify this sumcheck proof. - /// Note: Verification does not execute the final check of sumcheck protocol: g_v(r_v) = oracle_g(r), - /// as the oracle is not passed in. Expected that the caller will implement. - /// - /// Params - /// - `claim`: Claimed evaluation - /// - `num_rounds`: Number of rounds of sumcheck, or number of variables to bind - /// - `degree_bound`: Maximum allowed degree of the combined univariate polynomial - /// - `transcript`: Fiat-shamir transcript - /// - /// Returns (e, r) - /// - `e`: Claimed evaluation at random point - /// - `r`: Evaluation point - pub fn verify( - &self, - claim: F, - num_rounds: usize, - degree_bound: usize, - transcript: &mut ProofTranscript, - ) -> Result<(F, Vec), ProofVerifyError> { - let mut e = claim; - let mut r: Vec = Vec::new(); - - // verify that there is a univariate polynomial for each round - assert_eq!(self.compressed_polys.len(), num_rounds); - for i in 0..self.compressed_polys.len() { - // verify degree bound - if self.compressed_polys[i].degree() != degree_bound { - return Err(ProofVerifyError::InvalidInputLength( - degree_bound, - self.compressed_polys[i].degree(), - )); - } - - // append the prover's message to the transcript - self.compressed_polys[i].append_to_transcript(transcript); - - //derive the verifier's challenge for the next round - let r_i = transcript.challenge_scalar(); - r.push(r_i); - - // evaluate the claimed degree-ell polynomial at r_i using the hint - e = self.compressed_polys[i].eval_from_hint(&e, &r_i); - } - - Ok((e, r)) - } -} diff --git a/jolt-core/src/utils/mod.rs b/jolt-core/src/utils/mod.rs index 57881a121..d469a0a68 100644 --- a/jolt-core/src/utils/mod.rs +++ b/jolt-core/src/utils/mod.rs @@ -1,5 +1,4 @@ #![allow(dead_code)] -pub mod gaussian_elimination; pub mod instruction_utils; pub mod profiling; pub mod sol_types; diff --git a/jolt-core/src/utils/sol_types.rs b/jolt-core/src/utils/sol_types.rs index a1272092e..93661fe3a 100644 --- a/jolt-core/src/utils/sol_types.rs +++ b/jolt-core/src/utils/sol_types.rs @@ -4,15 +4,15 @@ use ark_ff::PrimeField; use crate::poly::commitment::hyperkzg::{HyperKZG, HyperKZGProof, HyperKZGVerifierKey}; use crate::r1cs::spartan::UniformSpartanProof; -use crate::subprotocols::grand_product::BatchedGrandProductLayerProof; use crate::subprotocols::grand_product::BatchedGrandProductProof; -use crate::subprotocols::sumcheck::SumcheckInstanceProof; use alloy_primitives::U256; use alloy_sol_types::sol; use ark_bn254::FrConfig; use ark_ff::Fp; use ark_ff::MontBackend; use jolt_types::field::JoltField; +use jolt_types::subprotocols::grand_product::BatchedGrandProductLayerProof; +use jolt_types::subprotocols::sumcheck::SumcheckInstanceProof; sol!(struct HyperKZGProofSol { uint256[] com; // G1 points represented pairwise diff --git a/jolt-svm-verifier/program/Cargo.toml b/jolt-svm-verifier/program/Cargo.toml index f115b5c03..9556254a3 100644 --- a/jolt-svm-verifier/program/Cargo.toml +++ b/jolt-svm-verifier/program/Cargo.toml @@ -20,4 +20,4 @@ solana-program = "2.0.6" jolt-types = { path = "../../jolt-types", default-features = false } [target.'cfg(not(target_os = "solana"))'.dependencies] -jolt-types = { path = "../../jolt-types" } \ No newline at end of file +jolt-types = { path = "../../jolt-types" } diff --git a/jolt-svm-verifier/program/src/constants.rs b/jolt-svm-verifier/program/src/constants.rs deleted file mode 100644 index a3f43e229..000000000 --- a/jolt-svm-verifier/program/src/constants.rs +++ /dev/null @@ -1,104 +0,0 @@ -pub const POINT_BYTES: [u8; 72] = [ - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -]; -pub const EVAL_BYTES: [u8; 32] = [ - 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -]; -pub const V_POS_BYTES: [u8; 88] = [ - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x30, 0x53, 0x70, 0xf2, 0xee, 0x18, 0x3d, 0x60, 0x13, 0xea, 0x65, 0xf4, 0xf7, 0x30, 0xe2, 0xc7, - 0xbf, 0xd4, 0x62, 0xdf, 0x8a, 0xbe, 0xec, 0x65, 0xed, 0x4b, 0x2d, 0x07, 0xb5, 0x3a, 0xa0, 0x2c, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x74, 0xff, 0x04, 0x17, 0x29, 0xa5, 0xfc, - 0x30, 0xdb, 0x03, 0x9a, 0xf9, 0x27, 0x09, 0xf5, 0x7d, 0x8b, 0xef, 0x3d, 0x2e, 0xa9, 0x3e, 0xb5, - 0x8d, 0x1c, 0x6b, 0x41, 0x2c, 0x89, 0x5e, 0x0a, -]; -pub const V_NEG_BYTES: [u8; 88] = [ - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x2a, 0xc2, 0x7a, 0x75, 0xb5, 0x1e, 0xee, 0xeb, 0x16, 0x03, 0x6a, 0x51, 0x48, 0x2f, 0x6b, 0x84, - 0x38, 0x06, 0x98, 0x53, 0xfa, 0xcd, 0xa8, 0xda, 0xd1, 0x46, 0xb9, 0xfb, 0xa2, 0xe5, 0xe2, 0xdf, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xef, 0x4f, 0x6e, 0xca, 0x07, 0xfa, 0x2d, - 0x87, 0x75, 0x42, 0x1b, 0x88, 0x5a, 0x4e, 0x67, 0xaa, 0xa7, 0xf9, 0x0b, 0x4b, 0x10, 0x31, 0xdb, - 0xb6, 0xc5, 0x8a, 0x52, 0xc3, 0x76, 0xa1, 0xff, -]; -pub const V_BYTES: [u8; 88] = [ - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x16, 0x18, 0x28, 0xe8, 0x11, 0x24, 0x9d, 0x95, 0x63, 0x4f, 0x95, 0x32, 0x9a, 0x15, 0x85, 0x5c, - 0xe4, 0x71, 0xf5, 0x68, 0xcf, 0x1e, 0x74, 0xfc, 0x27, 0x8c, 0x54, 0x57, 0x34, 0x5c, 0x60, 0x7f, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xe6, 0xd7, 0x01, 0x45, 0x55, 0x3c, 0x00, - 0x56, 0xd2, 0x9d, 0xf4, 0xaf, 0x55, 0x6c, 0x35, 0x6d, 0x73, 0xbd, 0x75, 0x54, 0x39, 0xf5, 0x28, - 0x55, 0xe7, 0xe0, 0xdd, 0x48, 0xa2, 0x8f, 0x28, -]; -pub const COM_BYTES: [u8; 88] = [ - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x05, 0x30, 0x5c, 0xed, 0x4c, 0xc9, 0x17, 0xf4, 0x0f, 0xeb, 0x65, 0xc7, 0x54, 0xd3, 0xfd, 0xeb, - 0xd4, 0x24, 0x13, 0xb9, 0x14, 0xaa, 0xb1, 0x7d, 0x76, 0xcf, 0xfa, 0x1a, 0x78, 0x5b, 0xba, 0x43, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x84, 0xf6, 0x8e, 0xb3, 0x25, 0xcc, - 0x83, 0x49, 0x24, 0xc0, 0x22, 0x3b, 0x78, 0xaa, 0x96, 0xcf, 0xbb, 0xdb, 0x70, 0xb1, 0x63, 0x9c, - 0x01, 0x3b, 0xa7, 0xe0, 0xb7, 0xd9, 0x8d, 0x3f, -]; -pub const W_BYTES: [u8; 248] = [ - 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x06, 0xd2, 0xe8, 0x06, 0x57, 0x75, 0x3a, 0xfb, 0x56, 0x14, 0x51, 0xef, 0x2e, 0x78, 0x6d, 0xc2, - 0x60, 0x39, 0x60, 0xb7, 0x97, 0x43, 0xb2, 0xed, 0xde, 0x40, 0x43, 0x4d, 0x1b, 0x6b, 0x71, 0x62, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xfc, 0x07, 0x22, 0x98, 0x06, 0x25, 0xf3, - 0xda, 0x20, 0x33, 0x2a, 0x05, 0x83, 0xc5, 0x96, 0xa7, 0x57, 0x53, 0xea, 0xef, 0xed, 0x07, 0x90, - 0x91, 0xbc, 0xa1, 0x6f, 0xdd, 0xd9, 0xed, 0xa9, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x09, 0x06, 0x16, 0x19, 0x67, 0x88, 0x05, 0xd9, 0x72, 0xd4, 0xd5, 0x48, 0xfb, 0xd9, 0xa5, 0xdc, - 0x8f, 0x8a, 0x7d, 0xf8, 0x06, 0x19, 0x09, 0x84, 0x0e, 0x11, 0xa0, 0xdc, 0x66, 0x5a, 0xd9, 0xfa, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x14, 0xa3, 0x0b, 0x0c, 0x63, 0x61, 0x47, - 0xc4, 0xb9, 0x04, 0x22, 0x7b, 0x86, 0x71, 0x21, 0x0a, 0x0f, 0x65, 0x5a, 0x89, 0x49, 0x98, 0xaa, - 0xdb, 0x8e, 0x8a, 0x3a, 0x58, 0x61, 0xdc, 0xf8, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x22, 0x7b, 0x59, 0x7d, 0x14, 0x15, 0x7a, 0xce, 0x59, 0x3e, 0xfe, 0xe8, 0xb2, 0xf1, 0xac, 0xff, - 0x36, 0x98, 0x40, 0x0d, 0xa6, 0x2c, 0x2a, 0x6b, 0x1f, 0x8e, 0x8d, 0x0e, 0xdd, 0xd5, 0xb0, 0x02, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x0d, 0xa6, 0xcc, 0x2e, 0xfa, 0x24, 0x81, - 0xa5, 0x7d, 0x98, 0x29, 0x08, 0x29, 0x22, 0x97, 0x2a, 0x08, 0xa3, 0xe1, 0xf0, 0x3d, 0xb5, 0x40, - 0x6f, 0xb8, 0x44, 0x7f, 0x31, 0xdc, 0x18, 0x62, -]; - -pub const VK_G1_BYTES: [u8; 88] = [ - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x05, 0x2f, 0x77, 0x0c, 0x9d, 0x84, 0x4c, 0x3c, 0xd5, 0x51, 0xdf, 0x50, 0x87, 0xb9, 0xa8, 0x4d, - 0xd9, 0xec, 0x15, 0xd6, 0x43, 0x81, 0x40, 0x41, 0xe1, 0x8f, 0x82, 0xe0, 0x12, 0x80, 0xcf, 0x6f, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x09, 0x2d, 0x55, 0xb8, 0x9a, 0xe5, 0xf5, - 0xd7, 0xf5, 0x70, 0xbc, 0xa0, 0xbf, 0x03, 0x69, 0x70, 0x05, 0x1c, 0x33, 0xf1, 0x49, 0x4a, 0xcf, - 0x7c, 0x30, 0xc1, 0xc5, 0xa4, 0xf2, 0x80, 0xbb, -]; -pub const VK_G2_BYTES: [u8; 168] = [ - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x08, 0x08, 0xae, 0xe6, 0xcc, 0xe7, 0xb7, 0x43, 0xa7, 0xa8, 0xc2, 0x94, 0x64, 0xf0, 0x50, 0x19, - 0xc1, 0x96, 0x46, 0xc2, 0x8f, 0xbb, 0x2e, 0xe0, 0xe7, 0x6f, 0x07, 0x1a, 0x19, 0x0a, 0x6a, 0x38, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x84, 0xdf, 0xa0, 0x52, 0x5d, 0x1e, 0x79, - 0xea, 0x6a, 0x64, 0xf6, 0x2b, 0x1c, 0x6a, 0x2d, 0xb2, 0x9f, 0x10, 0xce, 0xb3, 0x90, 0x82, 0x37, - 0xa5, 0xcb, 0x40, 0xc8, 0x01, 0x77, 0x89, 0x07, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x20, 0x22, 0x01, 0x8f, 0x06, 0x83, 0x8c, 0x43, 0xd4, 0x16, 0x35, 0x5e, 0x1e, 0xfb, 0x7f, 0xe9, - 0x77, 0xf4, 0x8f, 0x36, 0x56, 0x50, 0x24, 0xf3, 0x47, 0x22, 0x92, 0x34, 0x90, 0x23, 0x31, 0xe2, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0xce, 0xbd, 0x47, 0x4d, 0xaa, 0xc3, 0xfb, - 0x13, 0x4e, 0x80, 0x1a, 0x53, 0xd1, 0xbb, 0x05, 0x79, 0xc0, 0x0c, 0xdb, 0x9c, 0x5d, 0xb5, 0x92, - 0x42, 0xd7, 0xb1, 0x76, 0x69, 0x27, 0x8d, 0x17, -]; -pub const VK_BETA_G2_BYTES: [u8; 168] = [ - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x26, 0x65, 0xdb, 0x07, 0x85, 0xd0, 0xac, 0x2f, 0x22, 0xfc, 0x48, 0xa9, 0xb0, 0x04, 0x9e, - 0xe2, 0x85, 0xd1, 0xaf, 0xd1, 0x95, 0xde, 0x3e, 0x52, 0x74, 0xbf, 0x30, 0xa4, 0x9d, 0x0a, 0xfc, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x32, 0x86, 0x7e, 0xcc, 0x64, 0xd2, 0xa4, - 0xae, 0x27, 0x06, 0x39, 0xa1, 0x5b, 0x79, 0xd2, 0xb1, 0xef, 0xc2, 0xaf, 0x94, 0x1f, 0x92, 0xff, - 0xd2, 0x6b, 0xd4, 0xf2, 0x07, 0x48, 0x18, 0xd2, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x2a, 0x64, 0xf0, 0xaf, 0x8c, 0xfc, 0x2c, 0xd3, 0x34, 0x1a, 0xb1, 0xfb, 0x76, 0xca, 0xbb, 0x26, - 0xab, 0x32, 0xd3, 0x17, 0x70, 0x18, 0x76, 0x66, 0x40, 0x7b, 0xa1, 0x1b, 0xea, 0x26, 0xab, 0x99, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc8, 0x05, 0x58, 0xa2, 0x02, 0x32, 0x91, - 0x3a, 0x32, 0xc5, 0xd5, 0x06, 0x52, 0x2c, 0x6d, 0xfa, 0x89, 0xdd, 0x24, 0xd2, 0x0b, 0x3c, 0x82, - 0x7a, 0x85, 0xf9, 0xc3, 0xcf, 0x72, 0xb4, 0x8c, -]; -pub const C_G1_BYTES: [u8; 88] = [ - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x28, 0x4b, 0xcb, 0xcf, 0x4a, 0xe1, 0xfc, 0xc5, 0x81, 0x65, 0x4a, 0x7a, 0x33, 0x77, 0xdf, 0xe5, - 0x93, 0x4a, 0xf9, 0x7d, 0x89, 0x34, 0x9c, 0x54, 0x25, 0x7f, 0x0b, 0x6a, 0x33, 0x7f, 0x4c, 0x24, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0xbf, 0x39, 0x12, 0x4f, 0xab, 0xa4, 0x50, - 0xaa, 0x56, 0xf4, 0x53, 0x6b, 0x78, 0x52, 0x0a, 0xb1, 0x84, 0xaf, 0xa3, 0xc6, 0xde, 0x91, 0x96, - 0x38, 0x71, 0xc2, 0x38, 0xc8, 0x79, 0x0f, 0xb0, -]; diff --git a/jolt-svm-verifier/program/src/instruction.rs b/jolt-svm-verifier/program/src/instruction.rs new file mode 100644 index 000000000..f8b6e4f76 --- /dev/null +++ b/jolt-svm-verifier/program/src/instruction.rs @@ -0,0 +1,17 @@ +use solana_program::program_error::ProgramError; + +pub enum VerifierInstruction { + VerifyHyperKZG, + VerifySumcheck, +} + +impl VerifierInstruction { + pub fn unpack(input: &[u8]) -> Result { + let (&tag, _rest) = input.split_first().ok_or(ProgramError::InvalidInstructionData)?; + Ok(match tag { + 0 => VerifierInstruction::VerifyHyperKZG, + 1 => VerifierInstruction::VerifySumcheck, + _ => return Err(ProgramError::InvalidInstructionData), + }) + } +} \ No newline at end of file diff --git a/jolt-svm-verifier/program/src/lib.rs b/jolt-svm-verifier/program/src/lib.rs index 46a313f50..1df2d921d 100644 --- a/jolt-svm-verifier/program/src/lib.rs +++ b/jolt-svm-verifier/program/src/lib.rs @@ -1,10 +1,11 @@ #![allow(non_snake_case)] -mod constants; +mod test_constants; mod subprotocols; mod utils; +mod instruction; -use constants::*; +use test_constants::*; use crate::subprotocols::hyperkzg; use ark_bn254::{Bn254, Fq, Fq2, Fr, G1Affine, G2Affine}; @@ -18,19 +19,46 @@ use jolt_types::utils::transcript::ProofTranscript; use solana_program::{ account_info::AccountInfo, entrypoint, entrypoint::ProgramResult, msg, pubkey::Pubkey, }; +use solana_program::program_error::ProgramError; +use crate::instruction::VerifierInstruction; +use crate::subprotocols::grand_product::{verify_grand_product, GrandProductProof}; entrypoint!(process_instruction); fn process_instruction( _program_id: &Pubkey, _accounts: &[AccountInfo], - _instruction_data: &[u8], + instruction_data: &[u8], ) -> ProgramResult { msg!("Solana WIP Jolt Verifier!"); - verify_hyperKZG_JOLT(); + + let instruction = VerifierInstruction::unpack(instruction_data)?; + + match instruction { + VerifierInstruction::VerifyHyperKZG => { + msg!("Running verify_hyperKZG_JOLT"); + verify_hyperKZG_JOLT(); + } + VerifierInstruction::VerifySumcheck => { + msg!("Running verify_sumcheck"); + verify_sumcheck(); + } + } + Ok(()) } +fn verify_sumcheck() { + let proof: GrandProductProof = CanonicalDeserialize::deserialize_uncompressed(&GRAND_PRODUCT_BATCH_PROOFS[..]).unwrap(); + let claims: Vec = CanonicalDeserialize::deserialize_uncompressed(&GRAND_PRODUCT_CLAIMS[..]).unwrap(); + let mut transcript = ProofTranscript::new(b"test_transcript"); + let r_grand_product = verify_grand_product(&proof, &claims, &mut transcript); + let expected_r_grand_product: Vec = + CanonicalDeserialize::deserialize_uncompressed(&GRAND_PRODUCT_R_PROVER[..]).unwrap(); + + assert_eq!(expected_r_grand_product, r_grand_product); +} + fn verify_hyperKZG_JOLT() { let eval: Fr = CanonicalDeserialize::deserialize_uncompressed(&EVAL_BYTES[..]).unwrap(); let point: Vec = CanonicalDeserialize::deserialize_uncompressed(&POINT_BYTES[..]).unwrap(); diff --git a/jolt-svm-verifier/program/src/subprotocols/grand_product.rs b/jolt-svm-verifier/program/src/subprotocols/grand_product.rs new file mode 100644 index 000000000..1dcea4932 --- /dev/null +++ b/jolt-svm-verifier/program/src/subprotocols/grand_product.rs @@ -0,0 +1,140 @@ +use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; +use solana_program::msg; +use jolt_types::field::JoltField; +use jolt_types::subprotocols::grand_product::BatchedGrandProductLayerProof; +use jolt_types::utils::transcript::ProofTranscript; + +// Defining a solana specific version of this as a trade-off between pulling apart significant parts +// of jolt-core and keeping the changes minimal. +// This implementation follows the solidity implementation closely. +#[derive(CanonicalSerialize, CanonicalDeserialize)] +pub struct GrandProductProof { + layers: Vec> +} + +fn eval_eq_mle(r_grand_product: &[F], r_sumcheck: &[F]) -> F { + r_grand_product + .iter() + .zip(r_sumcheck.iter().rev()) + .map(|(&r_gp, &r_sc)| { + r_gp * r_sc + (F::one() - r_gp) * (F::one() - r_sc) + }) + .product() +} + +pub fn verify_sumcheck_claim( + layer_proof: &BatchedGrandProductLayerProof, + coeffs: &[F], + sumcheck_claim: F, + eq_eval: F, + r_grand_product: &mut Vec, + transcript: &mut ProofTranscript, +) -> (Vec, Vec) { + let expected_sumcheck_claim: F = coeffs + .iter() + .zip(layer_proof.left_claims.iter().zip(layer_proof.right_claims.iter())) + .map(|(&coeff, (&left, &right))| coeff * left * right * eq_eval) + .sum(); + msg!("expected sumcheck calculated"); + + assert_eq!(expected_sumcheck_claim, sumcheck_claim, "Sumcheck claim mismatch"); + + let r_layer = transcript.challenge_scalar(); + + let new_claims: Vec = layer_proof + .left_claims + .iter() + .zip(layer_proof.right_claims.iter()) + .map(|(&left, &right)| left + r_layer * (right - left)) + .collect(); + msg!("new claims done"); + + r_grand_product.push(r_layer); + + (new_claims, r_grand_product.clone()) +} + +pub fn verify_grand_product( + proof: &GrandProductProof, + claims: &[F], + transcript: &mut ProofTranscript, +) -> Vec { + let mut r_grand_product = Vec::new(); + let mut claims_to_verify = claims.to_vec(); + msg!("Proof layers: {:?}", proof.layers.len()); + + for layer in &proof.layers { + let coeffs: Vec = transcript.challenge_vector(claims_to_verify.len()); + + let joined_claim: F = claims_to_verify + .iter() + .zip(coeffs.iter()) + .map(|(&claim, &coeff)| claim * coeff) + .sum(); + + assert_eq!(claims.len(), layer.left_claims.len()); + assert_eq!(claims.len(), layer.right_claims.len()); + + let (sumcheck_claim, r_sumcheck) = layer.verify( + joined_claim, + r_grand_product.len(), + 3, + transcript, + ); + + for (&left, &right) in layer.left_claims.iter().zip(layer.right_claims.iter()) { + transcript.append_scalar(&left); + transcript.append_scalar(&right); + } + msg!("Transcript appened scalars"); + + assert_eq!(r_grand_product.len(), r_sumcheck.len()); + + let eq_eval = eval_eq_mle(&r_grand_product, &r_sumcheck); + + r_grand_product = r_sumcheck.into_iter().rev().collect(); + msg!("Going to verify sumcheck"); + + let (new_claims, new_r_grand_product) = verify_sumcheck_claim( + layer, + &coeffs, + sumcheck_claim, + eq_eval, + &mut r_grand_product, + transcript, + ); + + claims_to_verify = new_claims; + r_grand_product = new_r_grand_product; + } + + r_grand_product +} + +#[cfg(test)] +mod tests { + use super::*; + use ark_serialize::CanonicalDeserialize; + use ark_bn254::Fr; + use jolt_types::utils::transcript::ProofTranscript; + use crate::test_constants::{GRAND_PRODUCT_BATCH_PROOFS, GRAND_PRODUCT_CLAIMS, GRAND_PRODUCT_R_PROVER}; + + #[test] + fn test_grand_product() { + // let proof_bytes = include_bytes!("../../test_vectors/grand_product_proof.bytes"); + let proof: GrandProductProof = CanonicalDeserialize::deserialize_uncompressed(&GRAND_PRODUCT_BATCH_PROOFS[..]).unwrap(); + + // let claims_bytes = include_bytes!("../../test_vectors/grand_product_claims.bytes"); + let claims: Vec = CanonicalDeserialize::deserialize_uncompressed(&GRAND_PRODUCT_CLAIMS[..]).unwrap(); + + let mut transcript = ProofTranscript::new(b"test_transcript"); + let r_grand_product = verify_grand_product(&proof, &claims, &mut transcript); + + // let expected_r_grand_product_bytes = + // include_bytes!("../../test_vectors/grand_product_r_grand_product.bytes"); + let expected_r_grand_product: Vec = + CanonicalDeserialize::deserialize_uncompressed(&GRAND_PRODUCT_R_PROVER[..]).unwrap(); + + assert_eq!(expected_r_grand_product, r_grand_product); + } +} diff --git a/jolt-svm-verifier/program/src/subprotocols/mod.rs b/jolt-svm-verifier/program/src/subprotocols/mod.rs index bbb221ef1..ed925dfde 100644 --- a/jolt-svm-verifier/program/src/subprotocols/mod.rs +++ b/jolt-svm-verifier/program/src/subprotocols/mod.rs @@ -1 +1,4 @@ pub mod hyperkzg; + +#[allow(dead_code)] +pub mod grand_product; diff --git a/jolt-svm-verifier/program/src/test_constants.rs b/jolt-svm-verifier/program/src/test_constants.rs new file mode 100644 index 000000000..9c2035f10 --- /dev/null +++ b/jolt-svm-verifier/program/src/test_constants.rs @@ -0,0 +1,248 @@ +// Generated from HyperKZG small tests. +pub const POINT_BYTES: [u8; 72] = [ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +]; +pub const EVAL_BYTES: [u8; 32] = [ + 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +]; +pub const V_POS_BYTES: [u8; 88] = [ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x53, 0x70, 0xf2, 0xee, 0x18, 0x3d, 0x60, 0x13, 0xea, 0x65, 0xf4, 0xf7, 0x30, 0xe2, 0xc7, + 0xbf, 0xd4, 0x62, 0xdf, 0x8a, 0xbe, 0xec, 0x65, 0xed, 0x4b, 0x2d, 0x07, 0xb5, 0x3a, 0xa0, 0x2c, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x74, 0xff, 0x04, 0x17, 0x29, 0xa5, 0xfc, + 0x30, 0xdb, 0x03, 0x9a, 0xf9, 0x27, 0x09, 0xf5, 0x7d, 0x8b, 0xef, 0x3d, 0x2e, 0xa9, 0x3e, 0xb5, + 0x8d, 0x1c, 0x6b, 0x41, 0x2c, 0x89, 0x5e, 0x0a, +]; +pub const V_NEG_BYTES: [u8; 88] = [ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2a, 0xc2, 0x7a, 0x75, 0xb5, 0x1e, 0xee, 0xeb, 0x16, 0x03, 0x6a, 0x51, 0x48, 0x2f, 0x6b, 0x84, + 0x38, 0x06, 0x98, 0x53, 0xfa, 0xcd, 0xa8, 0xda, 0xd1, 0x46, 0xb9, 0xfb, 0xa2, 0xe5, 0xe2, 0xdf, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xef, 0x4f, 0x6e, 0xca, 0x07, 0xfa, 0x2d, + 0x87, 0x75, 0x42, 0x1b, 0x88, 0x5a, 0x4e, 0x67, 0xaa, 0xa7, 0xf9, 0x0b, 0x4b, 0x10, 0x31, 0xdb, + 0xb6, 0xc5, 0x8a, 0x52, 0xc3, 0x76, 0xa1, 0xff, +]; +pub const V_BYTES: [u8; 88] = [ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x16, 0x18, 0x28, 0xe8, 0x11, 0x24, 0x9d, 0x95, 0x63, 0x4f, 0x95, 0x32, 0x9a, 0x15, 0x85, 0x5c, + 0xe4, 0x71, 0xf5, 0x68, 0xcf, 0x1e, 0x74, 0xfc, 0x27, 0x8c, 0x54, 0x57, 0x34, 0x5c, 0x60, 0x7f, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xe6, 0xd7, 0x01, 0x45, 0x55, 0x3c, 0x00, + 0x56, 0xd2, 0x9d, 0xf4, 0xaf, 0x55, 0x6c, 0x35, 0x6d, 0x73, 0xbd, 0x75, 0x54, 0x39, 0xf5, 0x28, + 0x55, 0xe7, 0xe0, 0xdd, 0x48, 0xa2, 0x8f, 0x28, +]; +pub const COM_BYTES: [u8; 88] = [ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x30, 0x5c, 0xed, 0x4c, 0xc9, 0x17, 0xf4, 0x0f, 0xeb, 0x65, 0xc7, 0x54, 0xd3, 0xfd, 0xeb, + 0xd4, 0x24, 0x13, 0xb9, 0x14, 0xaa, 0xb1, 0x7d, 0x76, 0xcf, 0xfa, 0x1a, 0x78, 0x5b, 0xba, 0x43, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x84, 0xf6, 0x8e, 0xb3, 0x25, 0xcc, + 0x83, 0x49, 0x24, 0xc0, 0x22, 0x3b, 0x78, 0xaa, 0x96, 0xcf, 0xbb, 0xdb, 0x70, 0xb1, 0x63, 0x9c, + 0x01, 0x3b, 0xa7, 0xe0, 0xb7, 0xd9, 0x8d, 0x3f, +]; +pub const W_BYTES: [u8; 248] = [ + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0xd2, 0xe8, 0x06, 0x57, 0x75, 0x3a, 0xfb, 0x56, 0x14, 0x51, 0xef, 0x2e, 0x78, 0x6d, 0xc2, + 0x60, 0x39, 0x60, 0xb7, 0x97, 0x43, 0xb2, 0xed, 0xde, 0x40, 0x43, 0x4d, 0x1b, 0x6b, 0x71, 0x62, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xfc, 0x07, 0x22, 0x98, 0x06, 0x25, 0xf3, + 0xda, 0x20, 0x33, 0x2a, 0x05, 0x83, 0xc5, 0x96, 0xa7, 0x57, 0x53, 0xea, 0xef, 0xed, 0x07, 0x90, + 0x91, 0xbc, 0xa1, 0x6f, 0xdd, 0xd9, 0xed, 0xa9, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x06, 0x16, 0x19, 0x67, 0x88, 0x05, 0xd9, 0x72, 0xd4, 0xd5, 0x48, 0xfb, 0xd9, 0xa5, 0xdc, + 0x8f, 0x8a, 0x7d, 0xf8, 0x06, 0x19, 0x09, 0x84, 0x0e, 0x11, 0xa0, 0xdc, 0x66, 0x5a, 0xd9, 0xfa, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x14, 0xa3, 0x0b, 0x0c, 0x63, 0x61, 0x47, + 0xc4, 0xb9, 0x04, 0x22, 0x7b, 0x86, 0x71, 0x21, 0x0a, 0x0f, 0x65, 0x5a, 0x89, 0x49, 0x98, 0xaa, + 0xdb, 0x8e, 0x8a, 0x3a, 0x58, 0x61, 0xdc, 0xf8, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x22, 0x7b, 0x59, 0x7d, 0x14, 0x15, 0x7a, 0xce, 0x59, 0x3e, 0xfe, 0xe8, 0xb2, 0xf1, 0xac, 0xff, + 0x36, 0x98, 0x40, 0x0d, 0xa6, 0x2c, 0x2a, 0x6b, 0x1f, 0x8e, 0x8d, 0x0e, 0xdd, 0xd5, 0xb0, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x0d, 0xa6, 0xcc, 0x2e, 0xfa, 0x24, 0x81, + 0xa5, 0x7d, 0x98, 0x29, 0x08, 0x29, 0x22, 0x97, 0x2a, 0x08, 0xa3, 0xe1, 0xf0, 0x3d, 0xb5, 0x40, + 0x6f, 0xb8, 0x44, 0x7f, 0x31, 0xdc, 0x18, 0x62, +]; + +pub const VK_G1_BYTES: [u8; 88] = [ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x2f, 0x77, 0x0c, 0x9d, 0x84, 0x4c, 0x3c, 0xd5, 0x51, 0xdf, 0x50, 0x87, 0xb9, 0xa8, 0x4d, + 0xd9, 0xec, 0x15, 0xd6, 0x43, 0x81, 0x40, 0x41, 0xe1, 0x8f, 0x82, 0xe0, 0x12, 0x80, 0xcf, 0x6f, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x09, 0x2d, 0x55, 0xb8, 0x9a, 0xe5, 0xf5, + 0xd7, 0xf5, 0x70, 0xbc, 0xa0, 0xbf, 0x03, 0x69, 0x70, 0x05, 0x1c, 0x33, 0xf1, 0x49, 0x4a, 0xcf, + 0x7c, 0x30, 0xc1, 0xc5, 0xa4, 0xf2, 0x80, 0xbb, +]; +pub const VK_G2_BYTES: [u8; 168] = [ + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x08, 0xae, 0xe6, 0xcc, 0xe7, 0xb7, 0x43, 0xa7, 0xa8, 0xc2, 0x94, 0x64, 0xf0, 0x50, 0x19, + 0xc1, 0x96, 0x46, 0xc2, 0x8f, 0xbb, 0x2e, 0xe0, 0xe7, 0x6f, 0x07, 0x1a, 0x19, 0x0a, 0x6a, 0x38, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x84, 0xdf, 0xa0, 0x52, 0x5d, 0x1e, 0x79, + 0xea, 0x6a, 0x64, 0xf6, 0x2b, 0x1c, 0x6a, 0x2d, 0xb2, 0x9f, 0x10, 0xce, 0xb3, 0x90, 0x82, 0x37, + 0xa5, 0xcb, 0x40, 0xc8, 0x01, 0x77, 0x89, 0x07, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x22, 0x01, 0x8f, 0x06, 0x83, 0x8c, 0x43, 0xd4, 0x16, 0x35, 0x5e, 0x1e, 0xfb, 0x7f, 0xe9, + 0x77, 0xf4, 0x8f, 0x36, 0x56, 0x50, 0x24, 0xf3, 0x47, 0x22, 0x92, 0x34, 0x90, 0x23, 0x31, 0xe2, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0xce, 0xbd, 0x47, 0x4d, 0xaa, 0xc3, 0xfb, + 0x13, 0x4e, 0x80, 0x1a, 0x53, 0xd1, 0xbb, 0x05, 0x79, 0xc0, 0x0c, 0xdb, 0x9c, 0x5d, 0xb5, 0x92, + 0x42, 0xd7, 0xb1, 0x76, 0x69, 0x27, 0x8d, 0x17, +]; +pub const VK_BETA_G2_BYTES: [u8; 168] = [ + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x26, 0x65, 0xdb, 0x07, 0x85, 0xd0, 0xac, 0x2f, 0x22, 0xfc, 0x48, 0xa9, 0xb0, 0x04, 0x9e, + 0xe2, 0x85, 0xd1, 0xaf, 0xd1, 0x95, 0xde, 0x3e, 0x52, 0x74, 0xbf, 0x30, 0xa4, 0x9d, 0x0a, 0xfc, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x32, 0x86, 0x7e, 0xcc, 0x64, 0xd2, 0xa4, + 0xae, 0x27, 0x06, 0x39, 0xa1, 0x5b, 0x79, 0xd2, 0xb1, 0xef, 0xc2, 0xaf, 0x94, 0x1f, 0x92, 0xff, + 0xd2, 0x6b, 0xd4, 0xf2, 0x07, 0x48, 0x18, 0xd2, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2a, 0x64, 0xf0, 0xaf, 0x8c, 0xfc, 0x2c, 0xd3, 0x34, 0x1a, 0xb1, 0xfb, 0x76, 0xca, 0xbb, 0x26, + 0xab, 0x32, 0xd3, 0x17, 0x70, 0x18, 0x76, 0x66, 0x40, 0x7b, 0xa1, 0x1b, 0xea, 0x26, 0xab, 0x99, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc8, 0x05, 0x58, 0xa2, 0x02, 0x32, 0x91, + 0x3a, 0x32, 0xc5, 0xd5, 0x06, 0x52, 0x2c, 0x6d, 0xfa, 0x89, 0xdd, 0x24, 0xd2, 0x0b, 0x3c, 0x82, + 0x7a, 0x85, 0xf9, 0xc3, 0xcf, 0x72, 0xb4, 0x8c, +]; +pub const C_G1_BYTES: [u8; 88] = [ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x28, 0x4b, 0xcb, 0xcf, 0x4a, 0xe1, 0xfc, 0xc5, 0x81, 0x65, 0x4a, 0x7a, 0x33, 0x77, 0xdf, 0xe5, + 0x93, 0x4a, 0xf9, 0x7d, 0x89, 0x34, 0x9c, 0x54, 0x25, 0x7f, 0x0b, 0x6a, 0x33, 0x7f, 0x4c, 0x24, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0xbf, 0x39, 0x12, 0x4f, 0xab, 0xa4, 0x50, + 0xaa, 0x56, 0xf4, 0x53, 0x6b, 0x78, 0x52, 0x0a, 0xb1, 0x84, 0xaf, 0xa3, 0xc6, 0xde, 0x91, 0x96, + 0x38, 0x71, 0xc2, 0x38, 0xc8, 0x79, 0x0f, 0xb0, +]; + +// Grand Product Sumcheck generated from Grand Product tests +// const LAYER_SIZE: usize = 1 << 4; +// const BATCH_SIZE: usize = 1; +// Can't compile this because of a conflict with solana-program. +// use rand_core::RngCore; +// use crate::poly::commitment::hyperkzg::HyperKZG; +// +// #[test] +// fn prove_verify_hyperkzg() { +// const LAYER_SIZE: usize = 1 << 4; +// const BATCH_SIZE: usize = 1; +// let mut rng = test_rng(); +// let leaves: Vec> = std::iter::repeat_with(|| { +// std::iter::repeat_with(|| Fr::random(&mut rng)) +// .take(LAYER_SIZE) +// .collect() +// }) +// .take(BATCH_SIZE) +// .collect(); +// +// let mut batched_circuit = as BatchedGrandProduct< +// Fr, +// HyperKZG, +// >>::construct(leaves); +// +// let mut transcript: ProofTranscript = ProofTranscript::new(b"test_transcript"); +// +// let (proof, r_prover) = as BatchedGrandProduct< +// Fr, +// HyperKZG, +// >>::prove_grand_product(&mut batched_circuit, &mut transcript, None); +// let claims = +// as BatchedGrandProduct>>::claims( +// &mut batched_circuit, +// ); +// +// serialize_and_print_hex("GRAND_PRODUCT_BATCH_PROOFS", &proof.layers); +// serialize_and_print_hex("GRAND_PRODUCT_CLAIMS", &claims); +// serialize_and_print_hex("GRAND_PRODUCT_R_PROVER", &r_prover); +// } +// +// fn serialize_and_print_hex(name: &str, value: &T) { +// let compress: bool = false; +// let mut bytes = Vec::new(); +// if compress { +// value.serialize_compressed(&mut bytes).unwrap() +// } else { +// value.serialize_uncompressed(&mut bytes).unwrap(); +// } +// print_hex_array(name, &bytes); +// } +// +// fn print_hex_array(name: &str, bytes: &[u8]) { +// print!("pub const {}: [u8; {}] = [", name, bytes.len()); +// for (i, byte) in bytes.iter().enumerate() { +// if i % 16 == 0 { +// print!("\n "); +// } +// print!("0x{:02x}, ", byte); +// } +// println!("\n];"); +// } +pub const GRAND_PRODUCT_BATCH_PROOFS: [u8; 984] = [ + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x66, 0xd1, 0x83, 0x42, 0x99, 0x78, 0x5b, + 0x20, 0xf0, 0x34, 0xea, 0x5d, 0xcf, 0x58, 0xe5, 0xdf, 0x26, 0xdc, 0x82, 0x24, 0x9d, 0xa8, 0x9e, + 0x4e, 0x35, 0x70, 0x48, 0x45, 0x2e, 0xd6, 0x0d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xed, 0x53, 0x08, 0x59, 0x68, 0xe0, 0x26, 0xda, 0xac, 0x49, 0x3d, 0xea, 0x7f, 0x93, 0x0d, 0xe2, + 0x72, 0x72, 0x23, 0xe3, 0xcc, 0xad, 0x87, 0x97, 0x32, 0x2d, 0x00, 0xcb, 0x23, 0x50, 0xbd, 0x0d, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x52, 0xe7, 0x65, 0x2c, 0xc2, 0xfc, 0xb3, 0x2e, 0x07, 0x49, 0x33, 0x72, 0x1f, 0xf8, 0xf0, 0xf7, + 0xe1, 0x1e, 0xed, 0xd8, 0xe2, 0xd9, 0xfb, 0x84, 0x01, 0x67, 0xac, 0xde, 0x2d, 0x0d, 0x46, 0x04, + 0x8f, 0xdf, 0x4c, 0xfb, 0x63, 0xce, 0x20, 0xd1, 0xa0, 0xb5, 0x07, 0xe6, 0x6c, 0x04, 0x9f, 0x7f, + 0x1b, 0xb5, 0xfd, 0xd6, 0xc1, 0x04, 0xab, 0xcb, 0x12, 0x0b, 0x92, 0x55, 0x42, 0x07, 0x05, 0x1f, + 0xfa, 0x2a, 0x97, 0x1a, 0x9e, 0xd9, 0x4b, 0xf9, 0x2a, 0x8a, 0x88, 0x6b, 0x74, 0xcc, 0x56, 0xa6, + 0xcd, 0x34, 0x36, 0xa8, 0xc9, 0x38, 0x5b, 0xc0, 0x19, 0x73, 0x51, 0x20, 0xca, 0xee, 0x4f, 0x2f, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x62, 0x69, 0x76, 0x70, 0x1b, 0xdb, 0x3f, + 0xc6, 0xae, 0xcc, 0x35, 0xad, 0xd5, 0x8f, 0xc7, 0x11, 0x08, 0x44, 0xf2, 0x4f, 0x6f, 0x22, 0x62, + 0x3d, 0xbd, 0xd3, 0x2f, 0x47, 0x5c, 0x3b, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x56, 0x49, 0x29, 0x21, 0xcd, 0x7b, 0x75, 0x24, 0x74, 0xb8, 0x9b, 0x36, 0xa9, 0xcd, 0xa8, 0x4a, + 0x92, 0x60, 0x18, 0x23, 0xb9, 0x7c, 0xd1, 0xa3, 0xc6, 0x3c, 0x24, 0x10, 0x7e, 0x4a, 0x0d, 0x17, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc6, 0xf3, 0x49, 0x43, 0xfd, 0x3e, 0x6b, 0xbe, 0xc9, 0x5c, 0xca, 0x03, 0xa6, 0x89, 0xc8, 0x41, + 0x03, 0x0e, 0x6d, 0x40, 0xb5, 0x10, 0x2a, 0xb7, 0x8e, 0x3e, 0x03, 0x92, 0x2c, 0x35, 0x6a, 0x28, + 0x9d, 0x1c, 0xf7, 0x9b, 0x12, 0x5c, 0x76, 0x48, 0xa0, 0x8b, 0x3e, 0x8b, 0xfb, 0x97, 0xe6, 0x03, + 0xd4, 0xe5, 0x23, 0x67, 0x98, 0xfe, 0xdc, 0x5c, 0xc7, 0x42, 0x16, 0xd8, 0x78, 0xca, 0x9e, 0x05, + 0x08, 0x12, 0x84, 0xd1, 0x58, 0x9f, 0xe0, 0x9d, 0xa0, 0x33, 0x8b, 0x45, 0xd7, 0xfb, 0xa5, 0xdb, + 0x8a, 0x2b, 0x92, 0xec, 0xe2, 0x49, 0x9f, 0x94, 0x66, 0xda, 0x8a, 0xf1, 0x48, 0x82, 0x77, 0x1c, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x8a, 0xe0, 0x82, 0x39, 0x66, 0xe2, 0xf9, + 0xdf, 0x80, 0xb9, 0x7a, 0xf0, 0x55, 0xf7, 0x30, 0x66, 0x0c, 0x2a, 0xe6, 0x9f, 0xe7, 0xe8, 0xb7, + 0x56, 0xf2, 0x66, 0x82, 0x48, 0xed, 0x85, 0x27, 0x0b, 0xe6, 0x66, 0xd5, 0xf2, 0x5b, 0xad, 0x7c, + 0x65, 0xc4, 0xc7, 0xad, 0x24, 0x2c, 0x3b, 0x6c, 0x26, 0x01, 0x5c, 0xf9, 0x1b, 0xe3, 0x5c, 0x29, + 0x0c, 0xd4, 0x24, 0x2a, 0xda, 0x01, 0x9a, 0x1f, 0x1d, 0x1a, 0x4d, 0x7f, 0x18, 0xdf, 0x13, 0xab, + 0xf0, 0x32, 0x01, 0xbb, 0x43, 0x6d, 0xde, 0x59, 0x6a, 0x87, 0x13, 0x06, 0xc3, 0x11, 0xea, 0x5b, + 0xcf, 0x45, 0x33, 0x52, 0xc5, 0xa7, 0xcc, 0x23, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x79, 0x88, 0xbb, 0x24, 0x82, 0xbc, 0x6b, 0x85, 0xad, 0x7d, 0x28, 0x78, 0xef, 0xcf, 0x0f, 0x95, + 0x47, 0x64, 0x5b, 0xc6, 0xeb, 0xb9, 0xa5, 0xab, 0xdf, 0x8a, 0x21, 0x24, 0x4e, 0x6f, 0xac, 0x15, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x4f, 0xcf, 0x60, 0xf6, 0x15, 0x7f, 0xbc, + 0x47, 0x6e, 0x01, 0x84, 0x79, 0x29, 0x40, 0x82, 0x86, 0xf4, 0xd8, 0xc3, 0xd8, 0xdf, 0x9d, 0xcb, + 0xf5, 0x60, 0x95, 0x50, 0x6e, 0x4b, 0x11, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x90, 0x42, 0xfe, 0x0a, 0x6f, 0x52, 0xff, + 0x65, 0x1b, 0x96, 0x0f, 0x19, 0x66, 0xda, 0x5d, 0x57, 0x71, 0x05, 0x7a, 0x61, 0xb7, 0x34, 0x67, + 0x0c, 0xf6, 0x39, 0xd5, 0xef, 0xb7, 0x04, 0x17, 0xcc, 0x09, 0x9d, 0xd6, 0x98, 0xf7, 0xf0, 0xe6, + 0xdf, 0x81, 0x93, 0xd8, 0x27, 0x89, 0xa8, 0x69, 0x60, 0x6c, 0x74, 0xcc, 0x2b, 0x73, 0x41, 0xf4, + 0xfd, 0x1d, 0x68, 0x68, 0x57, 0x4a, 0x95, 0x1c, 0x0d, 0x8a, 0x81, 0x2a, 0xee, 0xcc, 0x2c, 0xa9, + 0x68, 0x18, 0x03, 0x6a, 0xf1, 0xbe, 0x34, 0x3f, 0x99, 0x1a, 0x7b, 0x65, 0xee, 0x73, 0x2f, 0xcc, + 0xff, 0x1d, 0x26, 0xba, 0xc9, 0x17, 0x10, 0x1c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0c, 0x07, 0x74, 0x57, 0xc2, 0xc5, 0x57, 0x0e, 0xa2, 0x79, 0xca, 0x5c, 0x04, 0x4f, 0xc7, 0x71, + 0x8e, 0xd7, 0xde, 0x6b, 0xc2, 0x7a, 0x0c, 0x81, 0x6a, 0x33, 0xc8, 0x11, 0x2a, 0xe4, 0x42, 0x08, + 0x4c, 0xa9, 0x8f, 0x8b, 0xda, 0xcd, 0x8f, 0x44, 0xff, 0xd9, 0x24, 0xe5, 0xca, 0x2c, 0x00, 0x2d, + 0xcd, 0x12, 0x8d, 0x9e, 0x49, 0xd0, 0x6c, 0x68, 0xfa, 0x93, 0x8f, 0x88, 0xe4, 0x8a, 0x71, 0x07, + 0x2f, 0xea, 0x0f, 0x64, 0xde, 0x72, 0xa4, 0x41, 0xfa, 0xc7, 0x29, 0x05, 0xcf, 0x3c, 0x06, 0x33, + 0x09, 0xe1, 0x69, 0x68, 0x2a, 0xdc, 0x47, 0xd4, 0xb5, 0x6f, 0xb4, 0x4e, 0x09, 0xb9, 0xdc, 0x20, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0xc2, 0xb5, 0x13, 0x2e, 0xa0, 0xc2, 0xd3, + 0xd1, 0x1c, 0x79, 0x62, 0x29, 0x10, 0x60, 0xc6, 0xa9, 0x56, 0x98, 0x77, 0x8b, 0xef, 0xe4, 0x08, + 0xd7, 0x7d, 0x38, 0x3f, 0xfa, 0x83, 0x95, 0x22, 0x98, 0x67, 0xf9, 0x72, 0xc7, 0x14, 0x9b, 0x94, + 0x2f, 0x36, 0x9e, 0xcb, 0x39, 0x26, 0x8b, 0x5e, 0xd7, 0xa2, 0xb8, 0x30, 0xab, 0x67, 0x21, 0x2a, + 0x23, 0x2c, 0xff, 0x5e, 0x75, 0xe0, 0x13, 0x03, 0xa5, 0x14, 0xad, 0x78, 0x66, 0xa8, 0x9f, 0x92, + 0x45, 0x08, 0xb5, 0x57, 0xd4, 0xb0, 0x32, 0x0f, 0x85, 0x6c, 0x95, 0xd6, 0x72, 0x9b, 0xc9, 0x55, + 0xef, 0xd1, 0x01, 0x1c, 0x7e, 0x8e, 0xd8, 0x0a, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x68, 0xba, 0xd4, 0xb5, 0x4b, 0xf7, 0x34, 0xa5, 0x20, 0x86, 0x13, 0x24, 0x44, 0x35, 0xfa, + 0x51, 0xd9, 0xaf, 0xa2, 0x4e, 0x71, 0x5f, 0x35, 0x43, 0x2c, 0x12, 0xe7, 0x1d, 0xa7, 0x39, 0x06, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xca, 0x8f, 0x12, 0x81, 0x39, 0x9e, 0xbc, + 0x63, 0xf1, 0x83, 0x83, 0x55, 0xc7, 0xa9, 0x3d, 0xf9, 0xd5, 0x5b, 0x62, 0x89, 0x7e, 0x63, 0xb6, + 0xc4, 0xe4, 0x43, 0x95, 0xc0, 0x22, 0x79, 0x1d, +]; +pub const GRAND_PRODUCT_CLAIMS: [u8; 40] = [ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0xe5, 0x34, 0xce, 0x21, 0x19, 0x4a, 0x4f, + 0xe1, 0xe7, 0x6d, 0xf8, 0x87, 0x5b, 0xbc, 0x82, 0x71, 0x05, 0x63, 0xd8, 0x66, 0x66, 0x19, 0x03, + 0xc7, 0x71, 0x9d, 0x54, 0x0a, 0x62, 0x9b, 0x27, +]; +pub const GRAND_PRODUCT_R_PROVER: [u8; 136] = [ + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0x02, 0xe7, 0x9d, 0x26, 0x1b, 0xcb, 0xc9, + 0x7a, 0xf0, 0xc3, 0x36, 0xa9, 0x21, 0x05, 0xfa, 0xcc, 0xb4, 0xa1, 0x66, 0xcf, 0x64, 0x6a, 0xd4, + 0xff, 0x71, 0xd2, 0x5f, 0x58, 0xf3, 0xc0, 0x00, 0xc0, 0x33, 0xb8, 0x95, 0x1c, 0x7e, 0xab, 0x1a, + 0xa5, 0x63, 0x9a, 0xc9, 0x97, 0x73, 0xa4, 0xcb, 0xfa, 0xb8, 0x46, 0x46, 0xcc, 0x96, 0x97, 0x03, + 0xe4, 0xc2, 0xd7, 0x01, 0x43, 0xcd, 0xf9, 0x12, 0xe6, 0x1b, 0x46, 0x25, 0xc4, 0x02, 0x1d, 0x61, + 0x3c, 0xdf, 0x46, 0x14, 0xc8, 0xaa, 0xde, 0xcc, 0x25, 0x1e, 0xf0, 0xef, 0x04, 0xab, 0x27, 0xfa, + 0xa7, 0x02, 0xb0, 0xec, 0xc0, 0x14, 0x0e, 0x11, 0x8b, 0x26, 0x50, 0xeb, 0xce, 0x47, 0x74, 0xad, + 0x74, 0x6f, 0x61, 0x19, 0x84, 0x23, 0x3f, 0x44, 0x24, 0x91, 0x30, 0x92, 0x01, 0x11, 0xea, 0x56, + 0xfc, 0xb0, 0x78, 0x2c, 0x21, 0x33, 0x23, 0x2e, +]; diff --git a/jolt-svm-verifier/tests/jolt-verifier.ts b/jolt-svm-verifier/tests/jolt-verifier.ts index 7b99f742f..c494f4b2c 100644 --- a/jolt-svm-verifier/tests/jolt-verifier.ts +++ b/jolt-svm-verifier/tests/jolt-verifier.ts @@ -17,14 +17,33 @@ describe('jolt-verifier', async () => { const client = context.banksClient; const payer = context.payer; - test('test basic', async () => { + test('test HyperKZG', async () => { const blockhash = context.lastBlockhash; const compute_ix = ComputeBudgetProgram.setComputeUnitLimit({units: 1_400_000}); // We setup our instruction. const ix = new TransactionInstruction({ keys: [{ pubkey: payer.publicKey, isSigner: true, isWritable: true }], programId: PROGRAM_ID, - data: Buffer.alloc(0), // No data + data: Buffer.from([0]), // hyperkzg instruction + }); + + const tx = new Transaction(); + tx.recentBlockhash = blockhash; + tx.add(compute_ix); + tx.add(ix).sign(payer); + + // Now we process the transaction + const transaction = await client.processTransaction(tx); + }); + + test('test Grand Product', async () => { + const blockhash = context.lastBlockhash; + const compute_ix = ComputeBudgetProgram.setComputeUnitLimit({units: 1_400_000}); + // We setup our instruction. + const ix = new TransactionInstruction({ + keys: [{ pubkey: payer.publicKey, isSigner: true, isWritable: true }], + programId: PROGRAM_ID, + data: Buffer.from([1]), // sumcheck instruction }); const tx = new Transaction(); diff --git a/jolt-types/Cargo.toml b/jolt-types/Cargo.toml index 71d5bec83..21eafd479 100644 --- a/jolt-types/Cargo.toml +++ b/jolt-types/Cargo.toml @@ -17,7 +17,7 @@ itertools = "0.13.0" [target.'cfg(not(target_os = "solana"))'.dependencies] rand = "0.7.3" -tracing = "0.1.40" +tracing = { version = "0.1.40", optional = true } rand_chacha = { version = "0.3.0", default-features = false } rand_core = { version = "0.6.4", default-features = false } rayon = { version = "^1.8.0", optional = true } @@ -35,6 +35,7 @@ default = [ "ark-std/parallel", "ark-ff/asm", "rayon", + "tracing", ] # Handle the unexpected cfg warnings when not building for solana diff --git a/jolt-types/src/lib.rs b/jolt-types/src/lib.rs index 9d0f12bd0..b8f913a0b 100644 --- a/jolt-types/src/lib.rs +++ b/jolt-types/src/lib.rs @@ -1,4 +1,5 @@ pub mod field; pub mod poly; +pub mod subprotocols; #[allow(non_snake_case)] pub mod utils; diff --git a/jolt-types/src/poly/mod.rs b/jolt-types/src/poly/mod.rs index 1f9123814..095d11c4c 100644 --- a/jolt-types/src/poly/mod.rs +++ b/jolt-types/src/poly/mod.rs @@ -1 +1,2 @@ pub mod commitment; +pub mod unipoly; diff --git a/jolt-core/src/poly/unipoly.rs b/jolt-types/src/poly/unipoly.rs similarity index 87% rename from jolt-core/src/poly/unipoly.rs rename to jolt-types/src/poly/unipoly.rs index e145ce1be..96d6523d0 100644 --- a/jolt-core/src/poly/unipoly.rs +++ b/jolt-types/src/poly/unipoly.rs @@ -1,12 +1,14 @@ #![allow(dead_code)] -use jolt_types::field::JoltField; +use crate::field::JoltField; use std::cmp::Ordering; use std::ops::{AddAssign, Index, IndexMut, Mul, MulAssign}; use crate::utils::gaussian_elimination::gaussian_elimination; +use crate::utils::transcript::{AppendToTranscript, ProofTranscript}; use ark_serialize::*; -use jolt_types::utils::transcript::{AppendToTranscript, ProofTranscript}; +#[cfg(not(target_os = "solana"))] use rand_core::{CryptoRng, RngCore}; +#[cfg(not(target_os = "solana"))] use rayon::iter::{IntoParallelIterator, IntoParallelRefMutIterator, ParallelIterator}; // ax^2 + bx + c stored as vec![c,b,a] @@ -57,7 +59,10 @@ impl UniPoly { /// Divide self by another polynomial, and returns the /// quotient and remainder. - #[tracing::instrument(skip_all, name = "UniPoly::divide_with_remainder")] + #[cfg_attr( + feature = "tracing", + tracing::instrument(skip_all, name = "UniPoly::divide_with_remainder") + )] pub fn divide_with_remainder(&self, divisor: &Self) -> Option<(Self, Self)> { if self.is_zero() { Some((Self::zero(), Self::zero())) @@ -115,7 +120,10 @@ impl UniPoly { (0..self.coeffs.len()).map(|i| self.coeffs[i]).sum() } - #[tracing::instrument(skip_all, name = "UniPoly::evaluate")] + #[cfg_attr( + feature = "tracing", + tracing::instrument(skip_all, name = "UniPoly::evaluate") + )] pub fn evaluate(&self, r: &F) -> F { let mut eval = self.coeffs[0]; let mut power = *r; @@ -134,6 +142,7 @@ impl UniPoly { } } + #[cfg(not(target_os = "solana"))] pub fn random(num_vars: usize, mut rng: &mut R) -> Self { Self::from_coeff( std::iter::from_fn(|| Some(F::random(&mut rng))) @@ -143,17 +152,16 @@ impl UniPoly { } pub fn shift_coefficients(&mut self, rhs: &F) { - self.coeffs.par_iter_mut().for_each(|c| *c += *rhs); - } -} - -/* -impl AddAssign<&F> for UniPoly { - fn add_assign(&mut self, rhs: &F) { - self.coeffs.par_iter_mut().for_each(|c| *c += rhs); + #[cfg(not(target_os = "solana"))] + { + self.coeffs.par_iter_mut().for_each(|c| *c += *rhs); + } + #[cfg(target_os = "solana")] + { + self.coeffs.iter_mut().for_each(|c| *c += *rhs); + } } } -*/ impl AddAssign<&Self> for UniPoly { fn add_assign(&mut self, rhs: &Self) { @@ -173,8 +181,16 @@ impl Mul for UniPoly { type Output = Self; fn mul(self, rhs: F) -> Self { - let iter = self.coeffs.into_par_iter(); - Self::from_coeff(iter.map(|c| c * rhs).collect::>()) + #[cfg(not(target_os = "solana"))] + { + let iter = self.coeffs.into_par_iter(); + Self::from_coeff(iter.map(|c| c * rhs).collect::>()) + } + #[cfg(target_os = "solana")] + { + let iter = self.coeffs.into_iter(); + Self::from_coeff(iter.map(|c| c * rhs).collect::>()) + } } } @@ -182,8 +198,29 @@ impl Mul<&F> for UniPoly { type Output = Self; fn mul(self, rhs: &F) -> Self { - let iter = self.coeffs.into_par_iter(); - Self::from_coeff(iter.map(|c| c * *rhs).collect::>()) + #[cfg(not(target_os = "solana"))] + { + let iter = self.coeffs.into_par_iter(); + Self::from_coeff(iter.map(|c| c * *rhs).collect::>()) + } + #[cfg(target_os = "solana")] + { + let iter = self.coeffs.into_iter(); + Self::from_coeff(iter.map(|c| c * *rhs).collect::>()) + } + } +} + +impl MulAssign<&F> for UniPoly { + fn mul_assign(&mut self, rhs: &F) { + #[cfg(not(target_os = "solana"))] + { + self.coeffs.par_iter_mut().for_each(|c| *c *= *rhs); + } + #[cfg(target_os = "solana")] + { + self.coeffs.iter_mut().for_each(|c| *c *= *rhs); + } } } @@ -201,12 +238,6 @@ impl IndexMut for UniPoly { } } -impl MulAssign<&F> for UniPoly { - fn mul_assign(&mut self, rhs: &F) { - self.coeffs.par_iter_mut().for_each(|c| *c *= *rhs); - } -} - impl CompressedUniPoly { // we require eval(0) + eval(1) = hint, so we can solve for the linear term as: // linear_term = hint - 2 * constant_term - deg2 term - deg3 term diff --git a/jolt-types/src/subprotocols/grand_product.rs b/jolt-types/src/subprotocols/grand_product.rs new file mode 100644 index 000000000..e20edc263 --- /dev/null +++ b/jolt-types/src/subprotocols/grand_product.rs @@ -0,0 +1,25 @@ +use crate::field::JoltField; +use crate::subprotocols::sumcheck::SumcheckInstanceProof; +use crate::utils::transcript::ProofTranscript; +use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; + +#[derive(CanonicalSerialize, CanonicalDeserialize)] +pub struct BatchedGrandProductLayerProof { + pub proof: SumcheckInstanceProof, + pub left_claims: Vec, + pub right_claims: Vec, +} + +impl BatchedGrandProductLayerProof { + pub fn verify( + &self, + claim: F, + num_rounds: usize, + degree_bound: usize, + transcript: &mut ProofTranscript, + ) -> (F, Vec) { + self.proof + .verify(claim, num_rounds, degree_bound, transcript) + .unwrap() + } +} diff --git a/jolt-types/src/subprotocols/mod.rs b/jolt-types/src/subprotocols/mod.rs new file mode 100644 index 000000000..020897245 --- /dev/null +++ b/jolt-types/src/subprotocols/mod.rs @@ -0,0 +1,2 @@ +pub mod grand_product; +pub mod sumcheck; diff --git a/jolt-types/src/subprotocols/sumcheck.rs b/jolt-types/src/subprotocols/sumcheck.rs new file mode 100644 index 000000000..b4767cf04 --- /dev/null +++ b/jolt-types/src/subprotocols/sumcheck.rs @@ -0,0 +1,64 @@ +use crate::field::JoltField; +use crate::poly::unipoly::CompressedUniPoly; +use crate::utils::errors::ProofVerifyError; +use crate::utils::transcript::{AppendToTranscript, ProofTranscript}; +use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; + +#[derive(CanonicalSerialize, CanonicalDeserialize, Debug)] +pub struct SumcheckInstanceProof { + pub compressed_polys: Vec>, +} + +impl SumcheckInstanceProof { + pub fn new(compressed_polys: Vec>) -> SumcheckInstanceProof { + SumcheckInstanceProof { compressed_polys } + } + + /// Verify this sumcheck proof. + /// Note: Verification does not execute the final check of sumcheck protocol: g_v(r_v) = oracle_g(r), + /// as the oracle is not passed in. Expected that the caller will implement. + /// + /// Params + /// - `claim`: Claimed evaluation + /// - `num_rounds`: Number of rounds of sumcheck, or number of variables to bind + /// - `degree_bound`: Maximum allowed degree of the combined univariate polynomial + /// - `transcript`: Fiat-shamir transcript + /// + /// Returns (e, r) + /// - `e`: Claimed evaluation at random point + /// - `r`: Evaluation point + pub fn verify( + &self, + claim: F, + num_rounds: usize, + degree_bound: usize, + transcript: &mut ProofTranscript, + ) -> Result<(F, Vec), ProofVerifyError> { + let mut e = claim; + let mut r: Vec = Vec::new(); + + // verify that there is a univariate polynomial for each round + assert_eq!(self.compressed_polys.len(), num_rounds); + for i in 0..self.compressed_polys.len() { + // verify degree bound + if self.compressed_polys[i].degree() != degree_bound { + return Err(ProofVerifyError::InvalidInputLength( + degree_bound, + self.compressed_polys[i].degree(), + )); + } + + // append the prover's message to the transcript + self.compressed_polys[i].append_to_transcript(transcript); + + //derive the verifier's challenge for the next round + let r_i = transcript.challenge_scalar(); + r.push(r_i); + + // evaluate the claimed degree-ell polynomial at r_i using the hint + e = self.compressed_polys[i].eval_from_hint(&e, &r_i); + } + + Ok((e, r)) + } +} diff --git a/jolt-core/src/utils/gaussian_elimination.rs b/jolt-types/src/utils/gaussian_elimination.rs similarity index 98% rename from jolt-core/src/utils/gaussian_elimination.rs rename to jolt-types/src/utils/gaussian_elimination.rs index ba5ad8bd2..0bbe78f47 100644 --- a/jolt-core/src/utils/gaussian_elimination.rs +++ b/jolt-types/src/utils/gaussian_elimination.rs @@ -4,7 +4,7 @@ // Wikipedia reference: augmented matrix: https://en.wikipedia.org/wiki/Augmented_matrix // Wikipedia reference: algorithm: https://en.wikipedia.org/wiki/Gaussian_elimination -use jolt_types::field::JoltField; +use crate::field::JoltField; pub fn gaussian_elimination(matrix: &mut [Vec]) -> Vec { let size = matrix.len(); diff --git a/jolt-types/src/utils/mod.rs b/jolt-types/src/utils/mod.rs index 24fd18a6a..6aac83a9d 100644 --- a/jolt-types/src/utils/mod.rs +++ b/jolt-types/src/utils/mod.rs @@ -6,6 +6,7 @@ use ark_std::test_rng; #[cfg(not(target_os = "solana"))] use rayon::prelude::*; pub mod errors; +pub mod gaussian_elimination; pub mod math; pub mod transcript;