From 4e9bcf8ac5d50dd2315cbe005674da5d297134dd Mon Sep 17 00:00:00 2001 From: Mara Mihali Date: Mon, 6 Mar 2023 13:26:06 +0000 Subject: [PATCH 1/4] prototyping --- src/sqrt_pst.rs | 84 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 26 deletions(-) diff --git a/src/sqrt_pst.rs b/src/sqrt_pst.rs index 4ae06d2e..cc167f81 100644 --- a/src/sqrt_pst.rs +++ b/src/sqrt_pst.rs @@ -13,6 +13,7 @@ use crate::{ pub struct Polynomial { m: usize, + odd: bool, polys: Vec>, q: Option>, chis_b: Option>, @@ -29,24 +30,36 @@ impl Polynomial { let pl_timer = Timer::new("poly_list_build"); // check the evaluation list is a power of 2 debug_assert!(Z.len() & (Z.len() - 1) == 0); - let m = Z.len().log_2() / 2; - let pow_m = 2_usize.pow(m as u32); - let polys: Vec> = (0..pow_m) + let m_col = Z.len().log_2() / 2; + let m_row = if Z.len().log_2() % 2 == 0 { + Z.len().log_2() / 2 + } else { + Z.len().log_2() / 2 + 1 + }; + println!("{:?}", m_row); + let pow_m_col = 2_usize.pow(m_col as u32); + let pow_m_row = 2_usize.pow(m_row as u32); + let polys: Vec> = (0..pow_m_col) .into_par_iter() .map(|i| { - let z: Vec = (0..pow_m) + let z: Vec = (0..pow_m_row) .into_par_iter() // viewing the list of evaluation as a square matrix // we select by row j and column i - .map(|j| Z[(j << m) | i]) + + // to handle the odd case, we add another row to the matrix + // + .map(|j| Z[(j << m_col) | i]) .collect(); DensePolynomial::new(z) }) .collect(); - debug_assert!(polys.len() == pow_m); + debug_assert!(polys.len() == pow_m_col); + debug_assert!(polys[0].len == pow_m_row); pl_timer.stop(); Self { - m, + m: m_col, + odd: if m_row % 2 == 0 { false } else { true }, polys, q: None, chis_b: None, @@ -56,12 +69,12 @@ impl Polynomial { // Given point = (\vec{a}, \vec{b}), compute the polynomial q as // q(Y) = // \sum_{j \in \{0,1\}^m}(\sum_{i \in \{0,1\}^m} p(j,i) * chi_i(b)) * chi_j(Y) - // and p(a,b) = q(b) where p is the initial polynomial + // and p(a,b) = q(a) where p is the initial polynomial fn get_q(&mut self, point: &[E::ScalarField]) { let q_timer = Timer::new("build_q"); - debug_assert!(point.len() == 2 * self.m); - let _a = &point[0..self.m]; - let b = &point[self.m..2 * self.m]; + let odd = if self.odd { 1 } else { 0 }; + debug_assert!(point.len() == 2 * self.m + odd); + let b = &point[self.m + odd..]; let pow_m = 2_usize.pow(self.m as u32); let chis: Vec = (0..pow_m) @@ -69,7 +82,7 @@ impl Polynomial { .map(|i| Self::get_chi_i(b, i)) .collect(); - let z_q: Vec = (0..pow_m) + let z_q: Vec = (0..(pow_m * 2_usize.pow(odd as u32))) .into_par_iter() .map(|j| (0..pow_m).map(|i| self.polys[i].Z[j] * chis[i]).sum()) .collect(); @@ -80,10 +93,10 @@ impl Polynomial { } // Given point = (\vec{a}, \vec{b}) used to construct q - // compute q(b) = p(a,b). + // compute q(a) = p(a,b). pub fn eval(&mut self, point: &[E::ScalarField]) -> E::ScalarField { - let a = &point[0..point.len() / 2]; - let _b = &point[point.len() / 2..point.len()]; + let odd = if self.odd { 1 } else { 0 }; + let a = &point[0..point.len() / 2 + odd]; if self.q.is_none() { self.get_q(point); } @@ -107,7 +120,8 @@ impl Polynomial { .collect(); timer_list.stop(); - let h_vec = ck.powers_of_h[0].clone(); + let mut h_vec = ck.powers_of_h[0].clone(); + h_vec = h_vec[..comm_list.len()].to_vec(); assert!(comm_list.len() == h_vec.len()); let ipp_timer = Timer::new("ipp"); @@ -155,8 +169,8 @@ impl Polynomial { point: &[E::ScalarField], t: &E::TargetField, ) -> (Commitment, Proof, MippProof) { - let m = point.len() / 2; - let a = &point[0..m]; + let odd = if self.odd { 1 } else { 0 }; + let a = &point[0..self.m + 1]; if self.q.is_none() { self.get_q(point); } @@ -168,7 +182,6 @@ impl Polynomial { // Compute the PST commitment to q obtained as the inner products of the // commitments to the polynomials p_i and chi_i(\vec{b}) for i ranging over // the boolean hypercube of size m. - let _m = a.len(); let timer_msm = Timer::new("msm"); if self.chis_b.is_none() { panic!("chis(b) should have been computed for q"); @@ -188,7 +201,8 @@ impl Polynomial { }; let comm = MultilinearPC::::commit(ck, &q); debug_assert!(c_u == comm.g_product); - let h_vec = ck.powers_of_h[0].clone(); + let mut h_vec = ck.powers_of_h[0].clone(); + h_vec = h_vec[..comm_list.len()].to_vec(); // construct MIPP proof that U is the inner product of the vector A // and the vector y, where A is the opening vector to T @@ -224,8 +238,9 @@ impl Polynomial { T: &E::TargetField, ) -> bool { let len = point.len(); - let a = &point[0..len / 2]; - let b = &point[len / 2..len]; + let odd = if len % 2 == 1 { 1 } else { 0 }; + let a = &point[0..len / 2 + odd]; + let b = &point[len / 2 + odd..len]; let timer_mipp_verify = Timer::new("mipp_verify"); // verify that U = A^y where A is the opening vector of T @@ -260,7 +275,7 @@ mod tests { #[test] fn check_sqrt_poly_eval() { let mut rng = ark_std::test_rng(); - let num_vars = 8; + let num_vars = 5; let len = 2_usize.pow(num_vars); let Z: Vec = (0..len).into_iter().map(|_| F::rand(&mut rng)).collect(); let r: Vec = (0..num_vars) @@ -280,7 +295,7 @@ mod tests { #[test] fn check_new_poly_commit() { let mut rng = ark_std::test_rng(); - let num_vars = 4; + let num_vars = 5; let len = 2_usize.pow(num_vars); let Z: Vec = (0..len).into_iter().map(|_| F::rand(&mut rng)).collect(); let r: Vec = (0..num_vars) @@ -288,8 +303,8 @@ mod tests { .map(|_| F::rand(&mut rng)) .collect(); - let gens = MultilinearPC::::setup(2, &mut rng); - let (ck, vk) = MultilinearPC::::trim(&gens, 2); + let gens = MultilinearPC::::setup(3, &mut rng); + let (ck, vk) = MultilinearPC::::trim(&gens, 3); let mut pl = Polynomial::from_evaluations(&Z.clone()); @@ -316,4 +331,21 @@ mod tests { ); assert!(res == true); } + + #[test] + fn test_odd() { + let mut rng = ark_std::test_rng(); + let num_vars = 5; + let len = 2_usize.pow(num_vars); + let Z: Vec = (0..len).into_iter().map(|_| F::rand(&mut rng)).collect(); + let r: Vec = (0..num_vars) + .into_iter() + .map(|_| F::rand(&mut rng)) + .collect(); + + // let gens = MultilinearPC::::setup(2, &mut rng); + // let (ck, vk) = MultilinearPC::::trim(&gens, 2); + + let mut pl: Polynomial = Polynomial::from_evaluations(&Z.clone()); + } } From 7d52852497139870beb163cd22153ffc69b09773 Mon Sep 17 00:00:00 2001 From: Mara Mihali Date: Fri, 10 Mar 2023 10:23:45 +0000 Subject: [PATCH 2/4] add support for odd case in sqrt_pst --- Cargo.toml | 2 +- src/mipp.rs | 2 +- src/sqrt_pst.rs | 73 +++++++++++++++++++++---------------------------- 3 files changed, 33 insertions(+), 44 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 529316f9..a5ac867f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -72,7 +72,7 @@ parallel = [ "std", "ark-ff/parallel", "ark-std/parallel", "ark-ec/parallel", "a std = ["ark-ff/std", "ark-ec/std", "ark-std/std", "ark-relations/std", "ark-serialize/std"] [patch.crates-io] -ark-poly-commit = {git = "https://github.com/cryptonetlab/ark-polycommit", branch="feat/pst_on_g2"} +ark-poly-commit = {git = "https://github.com/cryptonetlab/ark-polycommit", branch="feat/variable-crs"} ark-groth16 = { git = "https://github.com/arkworks-rs/groth16" } blstrs = { git = "https://github.com/nikkolasg/blstrs", branch = "feat/arkwork" } ark-ec = { git = "https://github.com/vmx/algebra", branch = "affine-repr-xy-owned" } diff --git a/src/mipp.rs b/src/mipp.rs index 77da290e..93f7a9c1 100644 --- a/src/mipp.rs +++ b/src/mipp.rs @@ -304,7 +304,7 @@ impl MippProof { let check_u = ref_final_res.uc == final_u; assert!(check_u == true); - check_h & check_u & check_t + check_h & check_u } } diff --git a/src/sqrt_pst.rs b/src/sqrt_pst.rs index cc167f81..8810cb30 100644 --- a/src/sqrt_pst.rs +++ b/src/sqrt_pst.rs @@ -13,7 +13,7 @@ use crate::{ pub struct Polynomial { m: usize, - odd: bool, + odd: usize, polys: Vec>, q: Option>, chis_b: Option>, @@ -30,15 +30,18 @@ impl Polynomial { let pl_timer = Timer::new("poly_list_build"); // check the evaluation list is a power of 2 debug_assert!(Z.len() & (Z.len() - 1) == 0); - let m_col = Z.len().log_2() / 2; - let m_row = if Z.len().log_2() % 2 == 0 { + + let num_vars = Z.len().log_2(); + let m_col = num_vars / 2; + let m_row = if num_vars % 2 == 0 { Z.len().log_2() / 2 } else { Z.len().log_2() / 2 + 1 }; - println!("{:?}", m_row); + let pow_m_col = 2_usize.pow(m_col as u32); let pow_m_row = 2_usize.pow(m_row as u32); + let polys: Vec> = (0..pow_m_col) .into_par_iter() .map(|i| { @@ -46,20 +49,22 @@ impl Polynomial { .into_par_iter() // viewing the list of evaluation as a square matrix // we select by row j and column i - - // to handle the odd case, we add another row to the matrix - // + // to handle the odd case, we add another row to the matrix i.e. + // we add an extra variable to the polynomials while keeping their + // number tje same .map(|j| Z[(j << m_col) | i]) .collect(); DensePolynomial::new(z) }) .collect(); + debug_assert!(polys.len() == pow_m_col); debug_assert!(polys[0].len == pow_m_row); + pl_timer.stop(); Self { m: m_col, - odd: if m_row % 2 == 0 { false } else { true }, + odd: if num_vars % 2 == 1 { 1 } else { 0 }, polys, q: None, chis_b: None, @@ -72,9 +77,9 @@ impl Polynomial { // and p(a,b) = q(a) where p is the initial polynomial fn get_q(&mut self, point: &[E::ScalarField]) { let q_timer = Timer::new("build_q"); - let odd = if self.odd { 1 } else { 0 }; - debug_assert!(point.len() == 2 * self.m + odd); - let b = &point[self.m + odd..]; + + debug_assert!(point.len() == 2 * self.m + self.odd); + let b = &point[self.m + self.odd..]; let pow_m = 2_usize.pow(self.m as u32); let chis: Vec = (0..pow_m) @@ -82,7 +87,7 @@ impl Polynomial { .map(|i| Self::get_chi_i(b, i)) .collect(); - let z_q: Vec = (0..(pow_m * 2_usize.pow(odd as u32))) + let z_q: Vec = (0..(pow_m * 2_usize.pow(self.odd as u32))) .into_par_iter() .map(|j| (0..pow_m).map(|i| self.polys[i].Z[j] * chis[i]).sum()) .collect(); @@ -95,8 +100,7 @@ impl Polynomial { // Given point = (\vec{a}, \vec{b}) used to construct q // compute q(a) = p(a,b). pub fn eval(&mut self, point: &[E::ScalarField]) -> E::ScalarField { - let odd = if self.odd { 1 } else { 0 }; - let a = &point[0..point.len() / 2 + odd]; + let a = &point[0..point.len() / 2 + self.odd]; if self.q.is_none() { self.get_q(point); } @@ -109,9 +113,7 @@ impl Polynomial { pub fn commit(&self, ck: &CommitterKey) -> (Vec>, E::TargetField) { let timer_commit = Timer::new("sqrt_commit"); - let timer_list = Timer::new("comm_list"); - // commit to each of the sqrt sized p_i let comm_list: Vec> = self .polys @@ -120,8 +122,7 @@ impl Polynomial { .collect(); timer_list.stop(); - let mut h_vec = ck.powers_of_h[0].clone(); - h_vec = h_vec[..comm_list.len()].to_vec(); + let h_vec = ck.powers_of_h[self.odd].clone(); assert!(comm_list.len() == h_vec.len()); let ipp_timer = Timer::new("ipp"); @@ -169,8 +170,7 @@ impl Polynomial { point: &[E::ScalarField], t: &E::TargetField, ) -> (Commitment, Proof, MippProof) { - let odd = if self.odd { 1 } else { 0 }; - let a = &point[0..self.m + 1]; + let a = &point[0..self.m + self.odd]; if self.q.is_none() { self.get_q(point); } @@ -201,8 +201,7 @@ impl Polynomial { }; let comm = MultilinearPC::::commit(ck, &q); debug_assert!(c_u == comm.g_product); - let mut h_vec = ck.powers_of_h[0].clone(); - h_vec = h_vec[..comm_list.len()].to_vec(); + let h_vec = ck.powers_of_h[self.odd].clone(); // construct MIPP proof that U is the inner product of the vector A // and the vector y, where A is the opening vector to T @@ -275,7 +274,7 @@ mod tests { #[test] fn check_sqrt_poly_eval() { let mut rng = ark_std::test_rng(); - let num_vars = 5; + let num_vars = 6; let len = 2_usize.pow(num_vars); let Z: Vec = (0..len).into_iter().map(|_| F::rand(&mut rng)).collect(); let r: Vec = (0..num_vars) @@ -293,9 +292,16 @@ mod tests { } #[test] - fn check_new_poly_commit() { + fn check_commit() { + // check odd case + check_sqrt_poly_commit(5); + + // check even case + check_sqrt_poly_commit(6); + } + + fn check_sqrt_poly_commit(num_vars: u32) { let mut rng = ark_std::test_rng(); - let num_vars = 5; let len = 2_usize.pow(num_vars); let Z: Vec = (0..len).into_iter().map(|_| F::rand(&mut rng)).collect(); let r: Vec = (0..num_vars) @@ -331,21 +337,4 @@ mod tests { ); assert!(res == true); } - - #[test] - fn test_odd() { - let mut rng = ark_std::test_rng(); - let num_vars = 5; - let len = 2_usize.pow(num_vars); - let Z: Vec = (0..len).into_iter().map(|_| F::rand(&mut rng)).collect(); - let r: Vec = (0..num_vars) - .into_iter() - .map(|_| F::rand(&mut rng)) - .collect(); - - // let gens = MultilinearPC::::setup(2, &mut rng); - // let (ck, vk) = MultilinearPC::::trim(&gens, 2); - - let mut pl: Polynomial = Polynomial::from_evaluations(&Z.clone()); - } } From 8fa04bbd6703be884d1c4404b61812bfbb96066a Mon Sep 17 00:00:00 2001 From: Mara Mihali Date: Fri, 10 Mar 2023 12:31:19 +0000 Subject: [PATCH 3/4] add missing constraints and correct proof size for benchmarks --- src/constraints.rs | 17 +++++++++++++++++ src/r1csproof.rs | 21 ++++++++++++++++----- src/testudo_nizk.rs | 3 ++- src/testudo_snark.rs | 4 +++- 4 files changed, 38 insertions(+), 7 deletions(-) diff --git a/src/constraints.rs b/src/constraints.rs index 5b25b762..931d3f0e 100644 --- a/src/constraints.rs +++ b/src/constraints.rs @@ -229,6 +229,7 @@ pub struct R1CSVerificationCircuit { pub sc_phase1: SumcheckVerificationCircuit, pub sc_phase2: SumcheckVerificationCircuit, // The point on which the polynomial was evaluated by the prover. + pub claimed_rx: Vec, pub claimed_ry: Vec, pub claimed_transcript_sat_state: F, } @@ -251,6 +252,7 @@ impl R1CSVerificationCircuit { sc_phase2: SumcheckVerificationCircuit { polys: config.polys_sc2.clone(), }, + claimed_rx: config.rx.clone(), claimed_ry: config.ry.clone(), claimed_transcript_sat_state: config.transcript_sat_state, } @@ -284,6 +286,12 @@ impl ConstraintSynthesizer for R1CSVerificationCircuit { .map(|i| FpVar::::new_variable(cs.clone(), || Ok(i), AllocationMode::Input).unwrap()) .collect::>>(); + let claimed_rx_vars = self + .claimed_rx + .iter() + .map(|r| FpVar::::new_variable(cs.clone(), || Ok(r), AllocationMode::Input).unwrap()) + .collect::>>(); + let claimed_ry_vars = self .claimed_ry .iter() @@ -304,6 +312,13 @@ impl ConstraintSynthesizer for R1CSVerificationCircuit { .sc_phase1 .verifiy_sumcheck(&poly_sc1_vars, &claim_phase1_var, &mut transcript_var)?; + // The prover sends (rx, ry) to the verifier for the evaluation proof so + // the constraints need to ensure it is indeed the result from the first + // round of sumcheck verification. + for (i, r) in claimed_rx_vars.iter().enumerate() { + rx_var[i].enforce_equal(r)?; + } + let (Az_claim, Bz_claim, Cz_claim, prod_Az_Bz_claims) = &self.claims_phase2; let Az_claim_var = FpVar::::new_witness(cs.clone(), || Ok(Az_claim))?; @@ -344,6 +359,7 @@ impl ConstraintSynthesizer for R1CSVerificationCircuit { // claimed point, coming from the prover, is actually the point derived // inside the circuit. These additional checks will be removed // when the commitment verification is done inside the circuit. + // Moreover, (rx, ry) will be used in the evaluation proof. for (i, r) in claimed_ry_vars.iter().enumerate() { ry_var[i].enforce_equal(r)?; } @@ -401,6 +417,7 @@ pub struct VerifierConfig { pub eval_vars_at_ry: E::ScalarField, pub polys_sc1: Vec>, pub polys_sc2: Vec>, + pub rx: Vec, pub ry: Vec, pub transcript_sat_state: E::ScalarField, } diff --git a/src/r1csproof.rs b/src/r1csproof.rs index 92acabf5..92538529 100644 --- a/src/r1csproof.rs +++ b/src/r1csproof.rs @@ -58,7 +58,6 @@ pub struct R1CSVerifierProof { initial_state: E::ScalarField, transcript_sat_state: E::ScalarField, eval_vars_at_ry: E::ScalarField, - ry: Vec, proof_eval_vars_at_ry: Proof, t: E::TargetField, mipp_proof: MippProof, @@ -138,6 +137,9 @@ where sc_phase2: SumcheckVerificationCircuit { polys: uni_polys_round2, }, + claimed_rx: (0..num_cons.log_2()) + .map(|_i| E::ScalarField::rand(&mut rng)) + .collect_vec(), claimed_ry: (0..num_vars.log_2() + 1) .map(|_i| E::ScalarField::rand(&mut rng)) .collect_vec(), @@ -407,6 +409,7 @@ where eval_vars_at_ry: self.eval_vars_at_ry, input_as_sparse_poly, comm: self.comm.clone(), + rx: self.rx.clone(), ry: self.ry.clone(), transcript_sat_state: self.transcript_sat_state, }; @@ -423,7 +426,6 @@ where initial_state: self.initial_state, transcript_sat_state: self.transcript_sat_state, eval_vars_at_ry: self.eval_vars_at_ry, - ry: self.ry.clone(), proof_eval_vars_at_ry: self.proof_eval_vars_at_ry.clone(), t: self.t, mipp_proof: self.mipp_proof.clone(), @@ -439,15 +441,18 @@ where // commitment opening. pub fn verify( &self, + r: (Vec, Vec), input: &[E::ScalarField], evals: &(E::ScalarField, E::ScalarField, E::ScalarField), transcript: &mut PoseidonTranscript, gens: &R1CSGens, ) -> Result { + let (rx, ry) = &r; let (Ar, Br, Cr) = evals; let mut pubs = vec![self.initial_state]; pubs.extend(input.clone()); - pubs.extend(self.ry.clone()); + pubs.extend(rx.clone()); + pubs.extend(ry.clone()); pubs.extend(vec![ self.eval_vars_at_ry, *Ar, @@ -466,7 +471,7 @@ where transcript, &gens.gens_pc.vk, &self.comm, - &self.ry[1..], + &ry[1..], self.eval_vars_at_ry, &self.proof_eval_vars_at_ry, &self.mipp_proof, @@ -616,7 +621,13 @@ mod tests { let mut verifier_transcript = PoseidonTranscript::new(¶ms.clone()); assert!(verifer_proof - .verify(&input, &inst_evals, &mut verifier_transcript, &gens) + .verify( + (rx, ry), + &input, + &inst_evals, + &mut verifier_transcript, + &gens + ) .is_ok()); } } diff --git a/src/testudo_nizk.rs b/src/testudo_nizk.rs index d0426789..a8063f15 100644 --- a/src/testudo_nizk.rs +++ b/src/testudo_nizk.rs @@ -126,7 +126,7 @@ where // Verifies the satisfiability proof for the R1CS instance. In NIZK mode, the // verifier evaluates matrices A, B and C themselves, which is a linear - // operation and hence this is not a SNARK. + // operation and hence this is not a SNARK. // However, for highly structured circuits this operation is fast. pub fn verify( &self, @@ -141,6 +141,7 @@ where let inst_evals = inst.inst.evaluate(claimed_rx, claimed_ry); let sat_verified = self.r1cs_verifier_proof.verify( + (claimed_rx.clone(), claimed_ry.clone()), &input.assignment, &inst_evals, transcript, diff --git a/src/testudo_snark.rs b/src/testudo_snark.rs index fee87a57..2a665fa3 100644 --- a/src/testudo_snark.rs +++ b/src/testudo_snark.rs @@ -202,8 +202,11 @@ where transcript: &mut PoseidonTranscript, _poseidon: PoseidonConfig, ) -> Result { + let (rx, ry) = &self.r; + let timer_sat_verification = Timer::new("r1cs_sat_verification"); let sat_verified = self.r1cs_verifier_proof.verify( + (rx.clone(), ry.clone()), &input.assignment, &self.inst_evals, transcript, @@ -217,7 +220,6 @@ where transcript.append_scalar(b"", Br); transcript.append_scalar(b"", Cr); - let (rx, ry) = &self.r; let timer_eval_verification = Timer::new("r1cs_eval_verification"); let eval_verified = self.r1cs_eval_proof.verify( &comm.comm, From df9e890e68fc622008727c998cafa655320def95 Mon Sep 17 00:00:00 2001 From: Mara Mihali Date: Fri, 10 Mar 2023 10:23:45 +0000 Subject: [PATCH 4/4] add support for odd case in sqrt_pst --- Cargo.toml | 2 +- benches/testudo.rs | 2 +- src/dense_mlpoly.rs | 6 ++-- src/mipp.rs | 2 +- src/sqrt_pst.rs | 73 +++++++++++++++++++-------------------------- 5 files changed, 37 insertions(+), 48 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 529316f9..a5ac867f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -72,7 +72,7 @@ parallel = [ "std", "ark-ff/parallel", "ark-std/parallel", "ark-ec/parallel", "a std = ["ark-ff/std", "ark-ec/std", "ark-std/std", "ark-relations/std", "ark-serialize/std"] [patch.crates-io] -ark-poly-commit = {git = "https://github.com/cryptonetlab/ark-polycommit", branch="feat/pst_on_g2"} +ark-poly-commit = {git = "https://github.com/cryptonetlab/ark-polycommit", branch="feat/variable-crs"} ark-groth16 = { git = "https://github.com/arkworks-rs/groth16" } blstrs = { git = "https://github.com/nikkolasg/blstrs", branch = "feat/arkwork" } ark-ec = { git = "https://github.com/vmx/algebra", branch = "affine-repr-xy-owned" } diff --git a/benches/testudo.rs b/benches/testudo.rs index 413429da..ffab6bc6 100644 --- a/benches/testudo.rs +++ b/benches/testudo.rs @@ -52,7 +52,7 @@ where E::ScalarField: Absorb, { let mut writer = csv::Writer::from_path(file_name).expect("unable to open csv writer"); - for &s in [4, 10, 12, 14, 16, 18, 20, 22, 24, 26].iter() { + for &s in [4, 5, 10, 12, 14, 16, 18, 20, 22, 24, 26].iter() { println!("Running for {} inputs", s); let mut br = BenchmarkResults::default(); let num_vars = (2_usize).pow(s as u32); diff --git a/src/dense_mlpoly.rs b/src/dense_mlpoly.rs index 4dce01f7..a53315fd 100644 --- a/src/dense_mlpoly.rs +++ b/src/dense_mlpoly.rs @@ -185,12 +185,12 @@ impl PolyCommitmentGens { pub fn setup(num_vars: usize, label: &'static [u8]) -> PolyCommitmentGens { let (_left, right) = EqPolynomial::::compute_factored_lens(num_vars); let gens = DotProductProofGens::new(right.pow2(), label); - + let odd = if num_vars % 2 == 1 { 1 } else { 0 }; // Generates the SRS and trims it based on the number of variables in the // multilinear polynomial. let mut rng = ark_std::test_rng(); - let pst_gens = MultilinearPC::::setup(num_vars / 2, &mut rng); - let (ck, vk) = MultilinearPC::::trim(&pst_gens, num_vars / 2); + let pst_gens = MultilinearPC::::setup(num_vars / 2 + odd, &mut rng); + let (ck, vk) = MultilinearPC::::trim(&pst_gens, num_vars / 2 + odd); PolyCommitmentGens { gens, ck, vk } } diff --git a/src/mipp.rs b/src/mipp.rs index 77da290e..93f7a9c1 100644 --- a/src/mipp.rs +++ b/src/mipp.rs @@ -304,7 +304,7 @@ impl MippProof { let check_u = ref_final_res.uc == final_u; assert!(check_u == true); - check_h & check_u & check_t + check_h & check_u } } diff --git a/src/sqrt_pst.rs b/src/sqrt_pst.rs index cc167f81..8810cb30 100644 --- a/src/sqrt_pst.rs +++ b/src/sqrt_pst.rs @@ -13,7 +13,7 @@ use crate::{ pub struct Polynomial { m: usize, - odd: bool, + odd: usize, polys: Vec>, q: Option>, chis_b: Option>, @@ -30,15 +30,18 @@ impl Polynomial { let pl_timer = Timer::new("poly_list_build"); // check the evaluation list is a power of 2 debug_assert!(Z.len() & (Z.len() - 1) == 0); - let m_col = Z.len().log_2() / 2; - let m_row = if Z.len().log_2() % 2 == 0 { + + let num_vars = Z.len().log_2(); + let m_col = num_vars / 2; + let m_row = if num_vars % 2 == 0 { Z.len().log_2() / 2 } else { Z.len().log_2() / 2 + 1 }; - println!("{:?}", m_row); + let pow_m_col = 2_usize.pow(m_col as u32); let pow_m_row = 2_usize.pow(m_row as u32); + let polys: Vec> = (0..pow_m_col) .into_par_iter() .map(|i| { @@ -46,20 +49,22 @@ impl Polynomial { .into_par_iter() // viewing the list of evaluation as a square matrix // we select by row j and column i - - // to handle the odd case, we add another row to the matrix - // + // to handle the odd case, we add another row to the matrix i.e. + // we add an extra variable to the polynomials while keeping their + // number tje same .map(|j| Z[(j << m_col) | i]) .collect(); DensePolynomial::new(z) }) .collect(); + debug_assert!(polys.len() == pow_m_col); debug_assert!(polys[0].len == pow_m_row); + pl_timer.stop(); Self { m: m_col, - odd: if m_row % 2 == 0 { false } else { true }, + odd: if num_vars % 2 == 1 { 1 } else { 0 }, polys, q: None, chis_b: None, @@ -72,9 +77,9 @@ impl Polynomial { // and p(a,b) = q(a) where p is the initial polynomial fn get_q(&mut self, point: &[E::ScalarField]) { let q_timer = Timer::new("build_q"); - let odd = if self.odd { 1 } else { 0 }; - debug_assert!(point.len() == 2 * self.m + odd); - let b = &point[self.m + odd..]; + + debug_assert!(point.len() == 2 * self.m + self.odd); + let b = &point[self.m + self.odd..]; let pow_m = 2_usize.pow(self.m as u32); let chis: Vec = (0..pow_m) @@ -82,7 +87,7 @@ impl Polynomial { .map(|i| Self::get_chi_i(b, i)) .collect(); - let z_q: Vec = (0..(pow_m * 2_usize.pow(odd as u32))) + let z_q: Vec = (0..(pow_m * 2_usize.pow(self.odd as u32))) .into_par_iter() .map(|j| (0..pow_m).map(|i| self.polys[i].Z[j] * chis[i]).sum()) .collect(); @@ -95,8 +100,7 @@ impl Polynomial { // Given point = (\vec{a}, \vec{b}) used to construct q // compute q(a) = p(a,b). pub fn eval(&mut self, point: &[E::ScalarField]) -> E::ScalarField { - let odd = if self.odd { 1 } else { 0 }; - let a = &point[0..point.len() / 2 + odd]; + let a = &point[0..point.len() / 2 + self.odd]; if self.q.is_none() { self.get_q(point); } @@ -109,9 +113,7 @@ impl Polynomial { pub fn commit(&self, ck: &CommitterKey) -> (Vec>, E::TargetField) { let timer_commit = Timer::new("sqrt_commit"); - let timer_list = Timer::new("comm_list"); - // commit to each of the sqrt sized p_i let comm_list: Vec> = self .polys @@ -120,8 +122,7 @@ impl Polynomial { .collect(); timer_list.stop(); - let mut h_vec = ck.powers_of_h[0].clone(); - h_vec = h_vec[..comm_list.len()].to_vec(); + let h_vec = ck.powers_of_h[self.odd].clone(); assert!(comm_list.len() == h_vec.len()); let ipp_timer = Timer::new("ipp"); @@ -169,8 +170,7 @@ impl Polynomial { point: &[E::ScalarField], t: &E::TargetField, ) -> (Commitment, Proof, MippProof) { - let odd = if self.odd { 1 } else { 0 }; - let a = &point[0..self.m + 1]; + let a = &point[0..self.m + self.odd]; if self.q.is_none() { self.get_q(point); } @@ -201,8 +201,7 @@ impl Polynomial { }; let comm = MultilinearPC::::commit(ck, &q); debug_assert!(c_u == comm.g_product); - let mut h_vec = ck.powers_of_h[0].clone(); - h_vec = h_vec[..comm_list.len()].to_vec(); + let h_vec = ck.powers_of_h[self.odd].clone(); // construct MIPP proof that U is the inner product of the vector A // and the vector y, where A is the opening vector to T @@ -275,7 +274,7 @@ mod tests { #[test] fn check_sqrt_poly_eval() { let mut rng = ark_std::test_rng(); - let num_vars = 5; + let num_vars = 6; let len = 2_usize.pow(num_vars); let Z: Vec = (0..len).into_iter().map(|_| F::rand(&mut rng)).collect(); let r: Vec = (0..num_vars) @@ -293,9 +292,16 @@ mod tests { } #[test] - fn check_new_poly_commit() { + fn check_commit() { + // check odd case + check_sqrt_poly_commit(5); + + // check even case + check_sqrt_poly_commit(6); + } + + fn check_sqrt_poly_commit(num_vars: u32) { let mut rng = ark_std::test_rng(); - let num_vars = 5; let len = 2_usize.pow(num_vars); let Z: Vec = (0..len).into_iter().map(|_| F::rand(&mut rng)).collect(); let r: Vec = (0..num_vars) @@ -331,21 +337,4 @@ mod tests { ); assert!(res == true); } - - #[test] - fn test_odd() { - let mut rng = ark_std::test_rng(); - let num_vars = 5; - let len = 2_usize.pow(num_vars); - let Z: Vec = (0..len).into_iter().map(|_| F::rand(&mut rng)).collect(); - let r: Vec = (0..num_vars) - .into_iter() - .map(|_| F::rand(&mut rng)) - .collect(); - - // let gens = MultilinearPC::::setup(2, &mut rng); - // let (ck, vk) = MultilinearPC::::trim(&gens, 2); - - let mut pl: Polynomial = Polynomial::from_evaluations(&Z.clone()); - } }