diff --git a/msm/src/constraint.rs b/msm/src/constraint.rs index 3d77c12b2a..ef4c2f68a5 100644 --- a/msm/src/constraint.rs +++ b/msm/src/constraint.rs @@ -9,7 +9,8 @@ use o1_utils::field_helpers::FieldHelpers; use o1_utils::foreign_field::ForeignElement; use crate::columns::{Column, ColumnIndexer, MSMColumnIndexer}; -use crate::proof::{Witness, WitnessColumns}; +use crate::proof::ProofInputs; +use crate::witness::Witness; use crate::{BN254G1Affine, Ff1, Fp, LIMBS_NUM}; /// Used to represent constraints as multi variate polynomials. The variables @@ -72,6 +73,8 @@ pub struct BuilderEnv { pub(crate) witness_raw: Vec>, } +const N: usize = 3 * LIMBS_NUM; + impl BuilderEnv { pub fn empty() -> Self { BuilderEnv { @@ -83,8 +86,8 @@ impl BuilderEnv { /// Each WitnessColumn stands for both one row and multirow. This /// function converts from a vector of one-row instantiation to a /// single multi-row form (which is a `Witness`). - pub fn get_witness(&self) -> Witness { - let mut x: Vec> = vec![vec![]; 3 * LIMBS_NUM]; + pub fn get_witness(&self) -> ProofInputs { + let mut cols: [Vec; N] = std::array::from_fn(|_| vec![]); for wc in &self.witness_raw { let WitnessColumnsIndexer { @@ -93,14 +96,14 @@ impl BuilderEnv { c: wc_c, } = wc; for i in 0..LIMBS_NUM { - x[i].push(wc_a[i]); - x[LIMBS_NUM + i].push(wc_b[i]); - x[2 * LIMBS_NUM + i].push(wc_c[i]); + cols[i].push(wc_a[i]); + cols[LIMBS_NUM + i].push(wc_b[i]); + cols[2 * LIMBS_NUM + i].push(wc_c[i]); } } - Witness { - evaluations: WitnessColumns { x }, + ProofInputs { + evaluations: Witness { cols }, mvlookups: vec![], } } diff --git a/msm/src/lib.rs b/msm/src/lib.rs index f773de97c4..de5204bd8a 100644 --- a/msm/src/lib.rs +++ b/msm/src/lib.rs @@ -48,10 +48,13 @@ mod tests { use poly_commitment::pairing_proof::PairingSRS; use crate::{ - columns::Column, mvlookup::Lookup, proof::Witness, prover::prove, verifier::verify, + columns::Column, mvlookup::Lookup, proof::ProofInputs, prover::prove, verifier::verify, BaseSponge, Fp, OpeningProof, ScalarSponge, BN254, }; + // Number of columns + const N: usize = 10; + #[test] fn test_completeness() { let mut rng = o1_utils::tests::make_test_rng(); @@ -67,20 +70,20 @@ mod tests { let mut srs: PairingSRS = PairingSRS::create(x, domain.d1.size as usize); srs.full_srs.add_lagrange_basis(domain.d1); - let witness = Witness::random(domain); + let inputs = ProofInputs::random(domain); let constraints: Vec<_> = vec![]; // generate the proof - let proof = prove::<_, OpeningProof, BaseSponge, ScalarSponge, Column, _>( + let proof = prove::<_, OpeningProof, BaseSponge, ScalarSponge, Column, _, N>( domain, &srs, - witness, + inputs, constraints, &mut rng, ); // verify the proof - let verifies = verify::<_, OpeningProof, BaseSponge, ScalarSponge>(domain, &srs, &proof); + let verifies = verify::<_, OpeningProof, BaseSponge, ScalarSponge, N>(domain, &srs, &proof); assert!(verifies); } @@ -98,22 +101,22 @@ mod tests { let mut srs: PairingSRS = PairingSRS::create(x, domain.d1.size as usize); srs.full_srs.add_lagrange_basis(domain.d1); - let witness = Witness::random(domain); + let inputs = ProofInputs::random(domain); let constraints = vec![]; // generate the proof - let proof = prove::<_, OpeningProof, BaseSponge, ScalarSponge, Column, _>( + let proof = prove::<_, OpeningProof, BaseSponge, ScalarSponge, Column, _, N>( domain, &srs, - witness, + inputs, constraints.clone(), &mut rng, ); - let witness_prime = Witness::random(domain); - let proof_prime = prove::<_, OpeningProof, BaseSponge, ScalarSponge, Column, _>( + let inputs_prime = ProofInputs::random(domain); + let proof_prime = prove::<_, OpeningProof, BaseSponge, ScalarSponge, Column, _, N>( domain, &srs, - witness_prime, + inputs_prime, constraints, &mut rng, ); @@ -123,7 +126,7 @@ mod tests { let mut proof_clone = proof.clone(); proof_clone.opening_proof = proof_prime.opening_proof; let verifies = - verify::<_, OpeningProof, BaseSponge, ScalarSponge>(domain, &srs, &proof_clone); + verify::<_, OpeningProof, BaseSponge, ScalarSponge, N>(domain, &srs, &proof_clone); assert!(!verifies); } @@ -134,7 +137,7 @@ mod tests { let mut proof_clone = proof.clone(); proof_clone.commitments = proof_prime.commitments; let verifies = - verify::<_, OpeningProof, BaseSponge, ScalarSponge>(domain, &srs, &proof_clone); + verify::<_, OpeningProof, BaseSponge, ScalarSponge, N>(domain, &srs, &proof_clone); assert!(!verifies); } @@ -146,7 +149,7 @@ mod tests { let mut proof_clone = proof.clone(); proof_clone.zeta_evaluations = proof_prime.zeta_evaluations; let verifies = - verify::<_, OpeningProof, BaseSponge, ScalarSponge>(domain, &srs, &proof_clone); + verify::<_, OpeningProof, BaseSponge, ScalarSponge, N>(domain, &srs, &proof_clone); assert!(!verifies); } } @@ -166,10 +169,10 @@ mod tests { let mut srs: PairingSRS = PairingSRS::create(x, domain.d1.size as usize); srs.full_srs.add_lagrange_basis(domain.d1); - let mut witness = Witness::random(domain); + let mut inputs = ProofInputs::random(domain); let constraints = vec![]; // Take one random f_i (FIXME: taking first one for now) - let looked_up_values = witness.mvlookups[0].f[0].clone(); + let looked_up_values = inputs.mvlookups[0].f[0].clone(); // We change a random looked up element (FIXME: first one for now) let wrong_looked_up_value = Lookup { table_id: looked_up_values[0].table_id, @@ -177,16 +180,16 @@ mod tests { value: vec![Fp::rand(&mut rng)], }; // Overwriting the first looked up value - witness.mvlookups[0].f[0][0] = wrong_looked_up_value; + inputs.mvlookups[0].f[0][0] = wrong_looked_up_value; // generate the proof - let proof = prove::<_, OpeningProof, BaseSponge, ScalarSponge, Column, _>( + let proof = prove::<_, OpeningProof, BaseSponge, ScalarSponge, Column, _, N>( domain, &srs, - witness, + inputs, constraints, &mut rng, ); - let verifies = verify::<_, OpeningProof, BaseSponge, ScalarSponge>(domain, &srs, &proof); + let verifies = verify::<_, OpeningProof, BaseSponge, ScalarSponge, N>(domain, &srs, &proof); // FIXME: At the moment, it does verify. It should not. We are missing constraints. assert!(!verifies); } diff --git a/msm/src/proof.rs b/msm/src/proof.rs index 8fa09487ef..b9ae8369a7 100644 --- a/msm/src/proof.rs +++ b/msm/src/proof.rs @@ -2,13 +2,13 @@ use crate::witness::Witness; use ark_ff::UniformRand; use kimchi::{circuits::domains::EvaluationDomains, curve::KimchiCurve}; use poly_commitment::{commitment::PolyComm, OpenProof}; -use rand::{prelude::*, thread_rng}; +use rand::thread_rng; use crate::mvlookup::{LookupProof, LookupWitness}; #[derive(Debug)] pub struct ProofInputs { - pub evaluations: Witness, + pub evaluations: Witness>, pub mvlookups: Vec>, } @@ -19,7 +19,6 @@ pub struct ProofInputs { impl ProofInputs { pub fn random(domain: EvaluationDomains) -> Self { let mut rng = thread_rng(); - let random_n = rng.gen_range(1..1000); let cols: [Vec; N] = std::array::from_fn(|_| { (0..domain.d1.size as usize) .map(|_| G::ScalarField::rand(&mut rng)) diff --git a/msm/src/prover.rs b/msm/src/prover.rs index 51d79a50c3..44a41a68a5 100644 --- a/msm/src/prover.rs +++ b/msm/src/prover.rs @@ -45,7 +45,7 @@ where .into_par_iter() .map(|evals| { Evaluations::>::from_vec_and_domain(evals, domain.d1) - } + }) .collect::>>>(); let polys: Witness> = { @@ -54,12 +54,15 @@ where evaluations .into_par_iter() .map(interpolate) - .collect::>() + .collect::>>() }; let commitments: Witness> = { let comm = |poly: &DensePolynomial| srs.commit_non_hiding(poly, 1); - (&polys).into_par_iter().map(comm).collect::>() + (&polys) + .into_par_iter() + .map(comm) + .collect::>>() }; let mut fq_sponge = EFqSponge::new(G::other_curve_sponge_params()); @@ -67,7 +70,7 @@ where // Do not use parallelism commitments .into_iter() - .for_each(|comm| absorb_commitment(&mut fq_sponge, comm)); + .for_each(|comm| absorb_commitment(&mut fq_sponge, &comm)); // -- Start MVLookup let lookup_env = if !inputs.mvlookups.is_empty() { @@ -96,10 +99,12 @@ where // TODO: Parallelize let (zeta_evaluations, zeta_omega_evaluations) = { let evals = |point| { - let Witness { cols } = &polys; - let comm = |poly: &DensePolynomial| poly.evaluate(point); - let x = cols.iter().map(comm).collect::>(); - Witness { cols } + let Witness { cols: polys } = &polys; + let mut evals: [G::ScalarField; N] = [G::ScalarField::zero(); N]; + for (i, poly) in polys.iter().enumerate() { + evals[i] = poly.evaluate(point) + } + Witness { cols: evals } }; (evals(&zeta), evals(&zeta_omega)) }; @@ -188,8 +193,8 @@ where .into_iter() .zip(zeta_omega_evaluations.into_iter()) { - fr_sponge.absorb(zeta_eval); - fr_sponge.absorb(zeta_omega_eval); + fr_sponge.absorb(&zeta_eval); + fr_sponge.absorb(&zeta_omega_eval); } if lookup_env.is_some() { // MVLookup FS diff --git a/msm/src/serialization/main.rs b/msm/src/serialization/main.rs index 4751950f2d..0471802385 100644 --- a/msm/src/serialization/main.rs +++ b/msm/src/serialization/main.rs @@ -9,6 +9,8 @@ use kimchi_msm::serialization::witness::deserialize_field_element; use kimchi_msm::verifier::verify; use kimchi_msm::{BaseSponge, Fp, OpeningProof, ScalarSponge, BN254, DOMAIN_SIZE, LIMBS_NUM}; +const N: usize = 3 + 19 + LIMBS_NUM; + pub fn main() { // FIXME: use a proper RNG let mut rng = o1_utils::tests::make_test_rng(); @@ -19,7 +21,7 @@ pub fn main() { let srs: PairingSRS = get_bn254_srs(domain); let mut env = witness::Env::::create(); - let mut witness: Witness> = Witness { + let mut witness: Witness> = Witness { cols: std::array::from_fn(|_| Vec::with_capacity(DOMAIN_SIZE)), }; @@ -45,7 +47,7 @@ pub fn main() { }; println!("Generating the proof"); - let proof = prove::<_, OpeningProof, BaseSponge, ScalarSponge, Column, _>( + let proof = prove::<_, OpeningProof, BaseSponge, ScalarSponge, Column, _, N>( domain, &srs, proof_inputs, @@ -54,6 +56,6 @@ pub fn main() { ); println!("Verifying the proof"); - let verifies = verify::<_, OpeningProof, BaseSponge, ScalarSponge>(domain, &srs, &proof); + let verifies = verify::<_, OpeningProof, BaseSponge, ScalarSponge, N>(domain, &srs, &proof); println!("Proof verification result: {verifies}") } diff --git a/msm/src/verifier.rs b/msm/src/verifier.rs index cd8ff34dc8..c1b2a19acf 100644 --- a/msm/src/verifier.rs +++ b/msm/src/verifier.rs @@ -36,7 +36,7 @@ pub fn verify< let mut fq_sponge = EFqSponge::new(G::other_curve_sponge_params()); commitments .into_iter() - .for_each(|comm| absorb_commitment(&mut fq_sponge, comm)); + .for_each(|comm| absorb_commitment(&mut fq_sponge, &comm)); if let Some(mvlookup_commitments) = mvlookup_commitments { mvlookup_commitments .into_iter() @@ -53,8 +53,8 @@ pub fn verify< let mut es: Vec<_> = zeta_evaluations .into_iter() - .zip(zeta_omega_evaluations) - .map(|(zeta, zeta_omega)| vec![vec![*zeta], vec![*zeta_omega]]) + .zip(*zeta_omega_evaluations) + .map(|(zeta, zeta_omega)| vec![vec![zeta], vec![zeta_omega]]) .collect(); if mvlookup_commitments.is_some() { @@ -71,10 +71,10 @@ pub fn verify< let mut evaluations: Vec<_> = commitments .into_iter() - .zip(zeta_evaluations.into_iter().zip(zeta_omega_evaluations)) + .zip(zeta_evaluations.into_iter().zip(*zeta_omega_evaluations)) .map(|(commitment, (zeta_eval, zeta_omega_eval))| Evaluation { commitment: commitment.clone(), - evaluations: vec![vec![*zeta_eval], vec![*zeta_omega_eval]], + evaluations: vec![vec![zeta_eval], vec![zeta_omega_eval]], }) .collect(); @@ -102,9 +102,9 @@ pub fn verify< let mut fr_sponge = EFrSponge::new(G::sponge_params()); fr_sponge.absorb(&fq_sponge.digest()); - for (zeta_eval, zeta_omega_eval) in zeta_evaluations.into_iter().zip(zeta_omega_evaluations) { - fr_sponge.absorb(zeta_eval); - fr_sponge.absorb(zeta_omega_eval); + for (zeta_eval, zeta_omega_eval) in zeta_evaluations.into_iter().zip(*zeta_omega_evaluations) { + fr_sponge.absorb(&zeta_eval); + fr_sponge.absorb(&zeta_omega_eval); } if mvlookup_commitments.is_some() { // MVLookup FS