diff --git a/msm/Cargo.toml b/msm/Cargo.toml index 3fcc9d2b9d..c545c1415d 100644 --- a/msm/Cargo.toml +++ b/msm/Cargo.toml @@ -16,6 +16,9 @@ path = "src/lib.rs" name = "main" path = "src/main.rs" +[[bin]] +name = "serialization" +path = "src/serialization/main.rs" [dependencies] ark-bn254 = { version = "0.3.0" } diff --git a/msm/src/lib.rs b/msm/src/lib.rs index 24072bdb8e..f773de97c4 100644 --- a/msm/src/lib.rs +++ b/msm/src/lib.rs @@ -12,6 +12,7 @@ pub mod proof; pub mod prover; pub mod serialization; pub mod verifier; +pub mod witness; /// Domain size for the MSM project, equal to the BN254 SRS size. pub const DOMAIN_SIZE: usize = 1 << 15; diff --git a/msm/src/serialization/main.rs b/msm/src/serialization/main.rs new file mode 100644 index 0000000000..e891810d1b --- /dev/null +++ b/msm/src/serialization/main.rs @@ -0,0 +1,51 @@ +use kimchi::circuits::domains::EvaluationDomains; +use kimchi_msm::serialization::witness; +use kimchi_msm::witness::Witness; +use poly_commitment::pairing_proof::PairingSRS; + +use kimchi_msm::precomputed_srs::get_bn254_srs; +use kimchi_msm::serialization::witness::deserialize_field_element; +use kimchi_msm::{Fp, BN254, DOMAIN_SIZE, LIMBS_NUM}; + +pub fn main() { + // FIXME: use a proper 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 mut env = witness::Env::::create(); + let mut witness: Witness> = Witness { + cols: std::array::from_fn(|_| Vec::with_capacity(DOMAIN_SIZE)), + }; + + // FIXME: this could be read from a file or a CLI argument + let field_elements = [[0, 0, 0]]; + for limbs in field_elements { + deserialize_field_element(&mut env, limbs); + for i in 0..3 { + witness.cols[i].push(env.current_kimchi_limbs[i]); + } + for i in 0..LIMBS_NUM { + witness.cols[3 + i].push(env.msm_limbs[i]); + } + for i in 0..19 { + witness.cols[3 + LIMBS_NUM + i].push(env.intermediate_limbs[i]); + } + } + + // 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}") +} diff --git a/msm/src/witness.rs b/msm/src/witness.rs new file mode 100644 index 0000000000..abb60e952e --- /dev/null +++ b/msm/src/witness.rs @@ -0,0 +1,92 @@ +use ark_ff::Zero; +use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelIterator}; + +/// The witness columns used by a gate of the MSM circuits. +/// It is generic over the number of columns, N, and the type of the witness, T. +/// It can be used to represent the different subcircuits used by the project. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Witness { + /// A witness row is represented by an array of N witness columns + /// When T is a vector, then the witness describes the rows of the circuit. + pub cols: [T; N], +} + +impl Default for Witness { + fn default() -> Self { + Witness { + cols: std::array::from_fn(|_| T::zero()), + } + } +} + +// IMPLEMENTATION OF ITERATORS FOR THE WITNESS STRUCTURE + +impl IntoIterator for Witness { + type Item = F; + type IntoIter = std::vec::IntoIter; + + /// Iterate over the columns in the circuit. + fn into_iter(self) -> Self::IntoIter { + let mut iter_contents = Vec::with_capacity(N); + iter_contents.extend(self.cols); + iter_contents.into_iter() + } +} + +impl IntoParallelIterator for Witness +where + Vec: IntoParallelIterator, +{ + type Iter = as IntoParallelIterator>::Iter; + type Item = as IntoParallelIterator>::Item; + + /// Iterate over the columns in the circuit, in parallel. + fn into_par_iter(self) -> Self::Iter { + let mut iter_contents = Vec::with_capacity(N); + iter_contents.extend(self.cols); + iter_contents.into_par_iter() + } +} + +impl FromParallelIterator for Witness { + fn from_par_iter(par_iter: I) -> Self + where + I: IntoParallelIterator, + { + let mut iter_contents = par_iter.into_par_iter().collect::>(); + let cols = iter_contents + .drain(..N) + .collect::>() + .try_into() + .unwrap(); + Witness { cols } + } +} + +impl<'data, const N: usize, G> IntoParallelIterator for &'data Witness +where + Vec<&'data G>: IntoParallelIterator, +{ + type Iter = as IntoParallelIterator>::Iter; + type Item = as IntoParallelIterator>::Item; + + fn into_par_iter(self) -> Self::Iter { + let mut iter_contents = Vec::with_capacity(N); + iter_contents.extend(&self.cols); + iter_contents.into_par_iter() + } +} + +impl<'data, const N: usize, G> IntoParallelIterator for &'data mut Witness +where + Vec<&'data mut G>: IntoParallelIterator, +{ + type Iter = as IntoParallelIterator>::Iter; + type Item = as IntoParallelIterator>::Item; + + fn into_par_iter(self) -> Self::Iter { + let mut iter_contents = Vec::with_capacity(N); + iter_contents.extend(&mut self.cols); + iter_contents.into_par_iter() + } +}