diff --git a/msm/src/proof.rs b/msm/src/proof.rs index c83f20a7d8..8fa09487ef 100644 --- a/msm/src/proof.rs +++ b/msm/src/proof.rs @@ -1,90 +1,14 @@ +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 rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelIterator}; use crate::mvlookup::{LookupProof, LookupWitness}; -/// List all columns of the circuit. -/// It is parametrized by a type `T` which can be either: -/// - `Vec` for the evaluations -/// - `PolyComm` for the commitments -#[derive(Debug, Clone)] -pub struct WitnessColumns { - pub x: Vec, -} - -impl<'lt, G> IntoIterator for &'lt WitnessColumns { - type Item = &'lt G; - type IntoIter = std::vec::IntoIter<&'lt G>; - - fn into_iter(self) -> Self::IntoIter { - let n = self.x.len(); - let mut iter_contents = Vec::with_capacity(n); - iter_contents.extend(&self.x); - iter_contents.into_iter() - } -} - -impl IntoParallelIterator for WitnessColumns -where - Vec: IntoParallelIterator, -{ - type Iter = as IntoParallelIterator>::Iter; - type Item = as IntoParallelIterator>::Item; - - fn into_par_iter(self) -> Self::Iter { - let n = self.x.len(); - let mut iter_contents = Vec::with_capacity(n); - iter_contents.extend(self.x); - iter_contents.into_par_iter() - } -} - -impl FromParallelIterator for WitnessColumns { - fn from_par_iter(par_iter: I) -> Self - where - I: IntoParallelIterator, - { - let iter_contents = par_iter.into_par_iter().collect::>(); - WitnessColumns { x: iter_contents } - } -} - -impl<'data, G> IntoParallelIterator for &'data WitnessColumns -where - Vec<&'data G>: IntoParallelIterator, -{ - type Iter = as IntoParallelIterator>::Iter; - type Item = as IntoParallelIterator>::Item; - - fn into_par_iter(self) -> Self::Iter { - let n = self.x.len(); - let mut iter_contents = Vec::with_capacity(n); - iter_contents.extend(self.x.iter()); - iter_contents.into_par_iter() - } -} - -impl<'data, G> IntoParallelIterator for &'data mut WitnessColumns -where - Vec<&'data mut G>: IntoParallelIterator, -{ - type Iter = as IntoParallelIterator>::Iter; - type Item = as IntoParallelIterator>::Item; - - fn into_par_iter(self) -> Self::Iter { - let n = self.x.len(); - let mut iter_contents = Vec::with_capacity(n); - iter_contents.extend(self.x.iter_mut()); - iter_contents.into_par_iter() - } -} - #[derive(Debug)] -pub struct Witness { - pub evaluations: WitnessColumns>, +pub struct ProofInputs { + pub evaluations: Witness, pub mvlookups: Vec>, } @@ -92,31 +16,28 @@ pub struct Witness { // It is not only in the test API because it is used at the moment in the // main.rs. It should be moved to the test API when main.rs is replaced with // real production code. -impl Witness { +impl ProofInputs { pub fn random(domain: EvaluationDomains) -> Self { let mut rng = thread_rng(); let random_n = rng.gen_range(1..1000); - Witness { - evaluations: WitnessColumns { - x: (0..random_n) - .map(|_| { - (0..domain.d1.size as usize) - .map(|_| G::ScalarField::rand(&mut rng)) - .collect::>() - }) - .collect::>(), - }, + let cols: [Vec; N] = std::array::from_fn(|_| { + (0..domain.d1.size as usize) + .map(|_| G::ScalarField::rand(&mut rng)) + .collect::>() + }); + ProofInputs { + evaluations: Witness { cols }, mvlookups: vec![LookupWitness::::random(domain)], } } } #[derive(Debug, Clone)] -pub struct Proof> { +pub struct Proof> { // Columns/PlonK argument - pub(crate) commitments: WitnessColumns>, - pub(crate) zeta_evaluations: WitnessColumns, - pub(crate) zeta_omega_evaluations: WitnessColumns, + pub(crate) commitments: Witness>, + pub(crate) zeta_evaluations: Witness, + pub(crate) zeta_omega_evaluations: Witness, // MVLookup argument pub(crate) mvlookup_commitments: Option>>, pub(crate) mvlookup_zeta_evaluations: Option>, diff --git a/msm/src/prover.rs b/msm/src/prover.rs index 16c8387d46..9cb712c517 100644 --- a/msm/src/prover.rs +++ b/msm/src/prover.rs @@ -17,7 +17,8 @@ use rayon::iter::IntoParallelIterator; use rayon::iter::ParallelIterator; use crate::mvlookup::{self, LookupProof}; -use crate::proof::{Proof, Witness, WitnessColumns}; +use crate::proof::{Proof, ProofInputs}; +use crate::witness::Witness; pub fn prove< G: KimchiCurve, @@ -26,41 +27,39 @@ pub fn prove< EFrSponge: FrSponge, Column, RNG, + const N: usize, >( domain: EvaluationDomains, srs: &OpeningProof::SRS, - inputs: Witness, + inputs: ProofInputs, _constraints: Vec, Column>>, rng: &mut RNG, -) -> Proof +) -> Proof where OpeningProof::SRS: Sync, RNG: RngCore + CryptoRng, { // Interpolate all columns on d1, using trait Into. - let evaluations: WitnessColumns>> = inputs + let evaluations: Witness>> = inputs .evaluations .into_par_iter() .map(|evals| { Evaluations::>::from_vec_and_domain(evals, domain.d1) }) - .collect::>>>(); + .collect::>>>(); - let polys: WitnessColumns> = { + let polys: Witness> = { let interpolate = |evals: Evaluations>| evals.interpolate(); evaluations .into_par_iter() .map(interpolate) - .collect::>() + .collect::>() }; - let commitments: WitnessColumns> = { + 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()); @@ -97,10 +96,10 @@ where // TODO: Parallelize let (zeta_evaluations, zeta_omega_evaluations) = { let evals = |point| { - let WitnessColumns { x } = &polys; + let Witness { cols } = &polys; let comm = |poly: &DensePolynomial| poly.evaluate(point); - let x = x.iter().map(comm).collect::>(); - WitnessColumns { x } + let x = cols.iter().map(comm).collect::>(); + Witness { cols } }; (evals(&zeta), evals(&zeta_omega)) }; diff --git a/msm/src/serialization/main.rs b/msm/src/serialization/main.rs index e891810d1b..4751950f2d 100644 --- a/msm/src/serialization/main.rs +++ b/msm/src/serialization/main.rs @@ -4,17 +4,19 @@ use kimchi_msm::witness::Witness; use poly_commitment::pairing_proof::PairingSRS; use kimchi_msm::precomputed_srs::get_bn254_srs; +use kimchi_msm::prover::prove; use kimchi_msm::serialization::witness::deserialize_field_element; -use kimchi_msm::{Fp, BN254, DOMAIN_SIZE, LIMBS_NUM}; +use kimchi_msm::verifier::verify; +use kimchi_msm::{BaseSponge, Fp, OpeningProof, ScalarSponge, BN254, DOMAIN_SIZE, LIMBS_NUM}; pub fn main() { // FIXME: use a proper RNG - let mut _rng = o1_utils::tests::make_test_rng(); + let mut rng = o1_utils::tests::make_test_rng(); println!("Creating the domain and SRS"); let domain = EvaluationDomains::::create(DOMAIN_SIZE).unwrap(); - let _srs: PairingSRS = get_bn254_srs(domain); + let srs: PairingSRS = get_bn254_srs(domain); let mut env = witness::Env::::create(); let mut witness: Witness> = Witness { @@ -36,16 +38,22 @@ pub fn main() { } } - // println!("Generating the proof"); - // let proof = prove::<_, OpeningProof, BaseSponge, ScalarSponge, Column, _>( - // domain, - // &srs, - // witness, - // constraints, - // &mut rng, - // ); - - // println!("Verifying the proof"); - // let verifies = verify::<_, OpeningProof, BaseSponge, ScalarSponge>(domain, &srs, &proof); - // println!("Proof verification result: {verifies}") + let _constraints = vec![]; + let proof_inputs = ProofInputs { + evaluations: witness, + mvlookups: vec![], + }; + + println!("Generating the proof"); + let proof = prove::<_, OpeningProof, BaseSponge, ScalarSponge, Column, _>( + domain, + &srs, + proof_inputs, + _constraints, + &mut rng, + ); + + println!("Verifying the proof"); + let verifies = verify::<_, OpeningProof, BaseSponge, ScalarSponge>(domain, &srs, &proof); + println!("Proof verification result: {verifies}") } diff --git a/msm/src/verifier.rs b/msm/src/verifier.rs index 5d77b62fc9..cd8ff34dc8 100644 --- a/msm/src/verifier.rs +++ b/msm/src/verifier.rs @@ -16,10 +16,11 @@ pub fn verify< OpeningProof: OpenProof, EFqSponge: Clone + FqSponge, EFrSponge: FrSponge, + const N: usize, >( domain: EvaluationDomains, srs: &OpeningProof::SRS, - proof: &Proof, + proof: &Proof, ) -> bool { let Proof { commitments,