From 207664ee7a528ccb58a062da80b5fe98846b87a7 Mon Sep 17 00:00:00 2001 From: Onyeka Obi Date: Fri, 27 Jan 2023 22:24:55 -0800 Subject: [PATCH] Borrow poly so that upstream clients do not have to copy --- src/ipa.rs | 21 ++++++-------- src/lagrange_basis.rs | 22 +++++++------- src/math_utils.rs | 7 +++-- src/multiproof.rs | 67 +++++++++++++++++++++---------------------- src/transcript.rs | 4 +-- 5 files changed, 59 insertions(+), 62 deletions(-) diff --git a/src/ipa.rs b/src/ipa.rs index 0549a4b..05b581a 100644 --- a/src/ipa.rs +++ b/src/ipa.rs @@ -8,16 +8,13 @@ use ark_ff::Field; use ark_ff::PrimeField; use ark_ff::{One, Zero}; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; -use bandersnatch::multi_scalar_mul; use bandersnatch::EdwardsAffine; use bandersnatch::EdwardsProjective; use bandersnatch::Fr; use itertools::Itertools; use crate::{IOError, IOErrorKind, IOResult}; -use std::io::{Read, Write}; -use std::borrow::Borrow; use std::iter; #[derive(Debug, Clone, PartialEq, Eq)] @@ -82,6 +79,7 @@ impl IPAProof { } } +#[allow(clippy::needless_borrow)] pub fn create( transcript: &mut Transcript, mut crs: CRS, @@ -121,7 +119,7 @@ pub fn create( let mut L_vec: Vec = Vec::with_capacity(num_rounds as usize); let mut R_vec: Vec = Vec::with_capacity(num_rounds as usize); - for k in 0..num_rounds { + for _ in 0..num_rounds { let (a_L, a_R) = halve(a); let (b_L, b_R) = halve(b); let (G_L, G_R) = halve(G); @@ -147,9 +145,9 @@ pub fn create( let x = transcript.challenge_scalar(b"x"); let x_inv = x.inverse().unwrap(); for i in 0..a_L.len() { - a_L[i] = a_L[i] + x * a_R[i]; - b_L[i] = b_L[i] + x_inv * b_R[i]; - G_L[i] = G_L[i] + G_R[i].mul(x_inv.into_repr()); + a_L[i] += x * a_R[i]; + b_L[i] += x_inv * b_R[i]; + G_L[i] += G_R[i].mul(x_inv.into_repr()); } a = a_L; @@ -174,6 +172,7 @@ fn log2(n: usize) -> u32 { } impl IPAProof { + #[allow(clippy::needless_borrow)] pub fn verify( &self, transcript: &mut Transcript, @@ -228,8 +227,8 @@ impl IPAProof { let (b_L, b_R) = halve(b); for i in 0..G_L.len() { - G_L[i] = G_L[i] + G_R[i].mul(x_inv.into_repr()); - b_L[i] = b_L[i] + b_R[i] * x_inv; + G_L[i] += G_R[i].mul(x_inv.into_repr()); + b_L[i] += b_R[i] * x_inv; } G = G_L; b = b_L; @@ -318,6 +317,7 @@ impl IPAProof { // This is being committed incase someone goes through the git history // The fully unrolled code is not that intuitive, but maybe this semi // unrolled version can help you to figure out the gap + #[allow(clippy::needless_borrow)] pub fn verify_semi_multiexp( &self, transcript: &mut Transcript, @@ -396,7 +396,6 @@ pub fn slow_vartime_multiscalar_mul<'a>( scalars: impl Iterator, points: impl Iterator, ) -> EdwardsProjective { - use ark_ec::group::Group; use ark_ec::msm::VariableBaseMSM; let scalars: Vec<_> = scalars.into_iter().map(|s| s.into_repr()).collect(); @@ -423,11 +422,9 @@ mod tests { use super::*; use crate::math_utils::{inner_product, powers_of}; use crate::multiproof::CRS; - use ark_std::rand; use ark_std::rand::SeedableRng; use ark_std::UniformRand; use rand_chacha::ChaCha20Rng; - use std::iter; #[test] fn test_create_IPAProof_proof() { let n = 8; diff --git a/src/lagrange_basis.rs b/src/lagrange_basis.rs index aa2d569..8d7b7ec 100644 --- a/src/lagrange_basis.rs +++ b/src/lagrange_basis.rs @@ -1,10 +1,14 @@ -use ark_ff::{batch_inversion, batch_inversion_and_mul, Field, One, Zero}; -use ark_poly::{domain, univariate::DensePolynomial, Polynomial, UVPolynomial}; +use ark_ff::{batch_inversion, batch_inversion_and_mul, Field, Zero}; use bandersnatch::Fr; use std::{ convert::TryFrom, ops::{Add, Mul, Sub}, }; +#[cfg(test)] +use { + ark_ff::One, + ark_poly::{univariate::DensePolynomial, Polynomial, UVPolynomial}, +}; #[derive(Clone, Debug)] pub struct LagrangeBasis { @@ -26,7 +30,7 @@ impl Add for LagrangeBasis { self.values .iter_mut() .zip(rhs.values.into_iter()) - .for_each(|(lhs, rhs)| *lhs = *lhs + rhs); + .for_each(|(lhs, rhs)| *lhs += rhs); self } } @@ -34,9 +38,7 @@ impl Mul for LagrangeBasis { type Output = LagrangeBasis; fn mul(mut self, rhs: Fr) -> Self::Output { - self.values - .iter_mut() - .for_each(|values| *values = *values * rhs); + self.values.iter_mut().for_each(|values| *values *= rhs); self } } @@ -44,9 +46,7 @@ impl Sub<&Fr> for LagrangeBasis { type Output = LagrangeBasis; fn sub(mut self, rhs: &Fr) -> Self::Output { - self.values - .iter_mut() - .for_each(|values| *values = *values - rhs); + self.values.iter_mut().for_each(|values| *values -= rhs); self } } @@ -155,8 +155,9 @@ impl LagrangeBasis { } // This is only for testing purposes + #[cfg(test)] pub(crate) fn interpolate(&self) -> DensePolynomial { - let domain: Vec<_> = (0..self.domain).map(|i| Fr::from(i as u128)).collect(); + let domain = (0..self.domain).map(|i| Fr::from(i as u128)); let points: Vec<_> = domain .into_iter() .zip(self.values.iter().cloned()) @@ -322,6 +323,7 @@ fn simple_division() { assert_eq!(quotient_expected, quotient_coeff) } +#[cfg(test)] // Taken from sapling-crypto -- O(n^2) fn interpolate(points: &[(Fr, Fr)]) -> Option> { let max_degree_plus_one = points.len(); diff --git a/src/math_utils.rs b/src/math_utils.rs index e04f659..3dbfda1 100644 --- a/src/math_utils.rs +++ b/src/math_utils.rs @@ -1,4 +1,4 @@ -use ark_ff::{Field, One}; +use ark_ff::One; use bandersnatch::Fr; /// Computes the inner product between two scalar vectors pub fn inner_product(a: &[Fr], b: &[Fr]) -> Fr { @@ -17,6 +17,7 @@ pub fn powers_of(point: Fr, n: usize) -> Vec { #[test] fn simple_vandemonde() { + use ark_ff::Field; use ark_std::test_rng; use ark_std::UniformRand; let rand_fr = Fr::rand(&mut test_rng()); @@ -24,9 +25,9 @@ fn simple_vandemonde() { let powers = powers_of(rand_fr, n); assert_eq!(powers[0], Fr::one()); - assert_eq!(powers[n - 1], rand_fr.pow(&[(n - 1) as u64])); + assert_eq!(powers[n - 1], rand_fr.pow([(n - 1) as u64])); for (i, power) in powers.into_iter().enumerate() { - assert_eq!(power, rand_fr.pow(&[i as u64])) + assert_eq!(power, rand_fr.pow([i as u64])) } } diff --git a/src/multiproof.rs b/src/multiproof.rs index 3d16a8a..caf472e 100644 --- a/src/multiproof.rs +++ b/src/multiproof.rs @@ -3,20 +3,18 @@ use std::collections::HashMap; -use crate::ipa::{self, IPAProof}; +use crate::ipa::IPAProof; use crate::lagrange_basis::{LagrangeBasis, PrecomputedWeights}; -use crate::math_utils::inner_product; use crate::math_utils::powers_of; use crate::slow_vartime_multiscalar_mul; use crate::transcript::Transcript; use crate::transcript::TranscriptProtocol; use ark_ec::{AffineCurve, ProjectiveCurve}; +use ark_ff::batch_inversion; use ark_ff::PrimeField; -use ark_ff::{batch_inversion, Field}; -use ark_ff::{One, Zero}; -use ark_poly::univariate::DensePolynomial; -use ark_poly::{Polynomial, UVPolynomial}; -use bandersnatch::multi_scalar_mul; +use ark_ff::Zero; +#[cfg(test)] +use ark_std::One; use bandersnatch::EdwardsAffine; use bandersnatch::EdwardsProjective; use bandersnatch::Fr; @@ -66,8 +64,7 @@ fn generate_random_elements(num_required_points: usize, seed: &'static [u8]) -> (0..) .into_iter() .map(|i| Fq::from(i as u128) + u) - .map(|x| EdwardsAffine::get_point_from_x(x, choose_largest)) - .filter_map(|point| point) + .filter_map(|x| EdwardsAffine::get_point_from_x(x, choose_largest)) .filter(|point| point.is_in_correct_subgroup_assuming_on_curve()) .take(num_required_points) .collect() @@ -76,16 +73,16 @@ fn generate_random_elements(num_required_points: usize, seed: &'static [u8]) -> pub struct MultiPoint; #[derive(Clone, Debug)] -pub struct ProverQuery { +pub struct ProverQuery<'a> { pub commitment: EdwardsProjective, - pub poly: LagrangeBasis, // TODO: Make this a reference so that upstream libraries do not need to clone + poly: &'a LagrangeBasis, // TODO: Make this a reference so that upstream libraries do not need to clone // Given a function f, we use z_i to denote the input point and y_i to denote the output, ie f(z_i) = y_i pub point: usize, pub result: Fr, } -impl From for VerifierQuery { - fn from(pq: ProverQuery) -> Self { +impl From> for VerifierQuery { + fn from(pq: ProverQuery<'_>) -> Self { VerifierQuery { commitment: pq.commitment, point: Fr::from(pq.point as u128), @@ -101,9 +98,9 @@ pub struct VerifierQuery { //XXX: change to group_prover_queries_by_point fn group_prover_queries<'a>( - prover_queries: &'a [ProverQuery], + prover_queries: &'a [ProverQuery<'a>], challenges: &'a [Fr], -) -> HashMap> { +) -> HashMap, &'a Fr)>> { // We want to group all of the polynomials which are evaluated at the same point together use itertools::Itertools; prover_queries @@ -117,7 +114,7 @@ impl MultiPoint { crs: CRS, precomp: &PrecomputedWeights, transcript: &mut Transcript, - queries: Vec, + queries: Vec>, ) -> MultiPointProof { transcript.domain_sep(b"multiproof"); // 1. Compute `r` @@ -217,7 +214,7 @@ impl MultiPoint { MultiPointProof { open_proof: g_3_ipa, - g_x_comm: g_x_comm, + g_x_comm, } } } @@ -303,7 +300,7 @@ impl MultiPointProof { .sum(); //4. Compute [g_1(X)] = E - let comms: Vec<_> = queries.into_iter().map(|query| query.commitment).collect(); + let comms: Vec<_> = queries.iter().map(|query| query.commitment).collect(); let g1_comm = slow_vartime_multiscalar_mul(helper_scalars.iter(), comms.iter()); transcript.append_point(b"E", &g1_comm); @@ -312,7 +309,7 @@ impl MultiPointProof { let g3_comm = g1_comm - self.g_x_comm; // Check IPA - let b = LagrangeBasis::evaluate_lagrange_coefficients(&precomp, crs.n, t); // TODO: we could put this as a method on PrecomputedWeights + let b = LagrangeBasis::evaluate_lagrange_coefficients(precomp, crs.n, t); // TODO: we could put this as a method on PrecomputedWeights self.open_proof .verify_multiexp(transcript, crs, b, g3_comm, t, g2_t) @@ -352,7 +349,7 @@ fn open_multiproof_lagrange() { let prover_query = ProverQuery { commitment: poly_comm, - poly, + poly: &poly, point, result: y_i, }; @@ -392,13 +389,13 @@ fn open_multiproof_lagrange_2_polys() { let prover_query_i = ProverQuery { commitment: poly_comm, - poly: poly.clone(), + poly: &poly, point: z_i, result: y_i, }; let prover_query_j = ProverQuery { commitment: poly_comm, - poly: poly, + poly: &poly, point: x_j, result: y_j, }; @@ -425,11 +422,12 @@ fn open_multiproof_lagrange_2_polys() { } #[test] fn test_ipa_consistency() { + use crate::math_utils::inner_product; use ark_serialize::CanonicalSerialize; let n = 256; let crs = CRS::new(n, b"eth_verkle_oct_2021"); let precomp = PrecomputedWeights::new(n); - let input_point = Fr::from(2101 as u128); + let input_point = Fr::from(2101_u128); let poly: Vec = (0..n).map(|i| Fr::from(((i % 32) + 1) as u128)).collect(); let polynomial = LagrangeBasis::new(poly.clone()); @@ -449,7 +447,7 @@ fn test_ipa_consistency() { let mut bytes = [0u8; 32]; p_challenge.serialize(&mut bytes[..]).unwrap(); assert_eq!( - hex::encode(&bytes), + hex::encode(bytes), "50d7f61175ffcfefc0dd603943ec8da7568608564d509cd0d1fa71cc48dc3515" ); @@ -488,32 +486,32 @@ fn multiproof_consistency() { // 1 to 32 repeated 8 times let poly_a: Vec = (0..n).map(|i| Fr::from(((i % 32) + 1) as u128)).collect(); - let polynomial_a = LagrangeBasis::new(poly_a.clone()); + let polynomial_a = LagrangeBasis::new(poly_a); // 32 to 1 repeated 8 times let poly_b: Vec = (0..n) .rev() .map(|i| Fr::from(((i % 32) + 1) as u128)) .collect(); - let polynomial_b = LagrangeBasis::new(poly_b.clone()); + let polynomial_b = LagrangeBasis::new(poly_b); let point_a = 0; let y_a = Fr::one(); let point_b = 0; - let y_b = Fr::from(32 as u128); + let y_b = Fr::from(32_u128); let poly_comm_a = crs.commit_lagrange_poly(&polynomial_a); let poly_comm_b = crs.commit_lagrange_poly(&polynomial_b); let prover_query_a = ProverQuery { commitment: poly_comm_a, - poly: polynomial_a, + poly: &polynomial_a, point: point_a, result: y_a, }; let prover_query_b = ProverQuery { commitment: poly_comm_b, - poly: polynomial_b, + poly: &polynomial_b, point: point_b, result: y_b, }; @@ -530,7 +528,7 @@ fn multiproof_consistency() { let mut bytes = [0u8; 32]; p_challenge.serialize(&mut bytes[..]).unwrap(); assert_eq!( - hex::encode(&bytes), + hex::encode(bytes), "f9c48313d1af5e069386805b966ce53a3d95794b82da3aac6d68fd629062a31c" ); @@ -559,7 +557,6 @@ fn multiproof_consistency() { fn crs_consistency() { // See: https://hackmd.io/1RcGSMQgT4uREaq1CCx_cg#Methodology use ark_serialize::CanonicalSerialize; - use bandersnatch::Fq; use sha2::{Digest, Sha256}; let points = generate_random_elements(256, b"eth_verkle_oct_2021"); @@ -577,14 +574,14 @@ fn crs_consistency() { let mut bytes = [0u8; 32]; points[0].serialize(&mut bytes[..]).unwrap(); assert_eq!( - hex::encode(&bytes), + hex::encode(bytes), "22ac968a98ab6c50379fc8b039abc8fd9aca259f4746a05bfbdf12c86463c208", "the first point is incorrect" ); let mut bytes = [0u8; 32]; points[255].serialize(&mut bytes[..]).unwrap(); assert_eq!( - hex::encode(&bytes), + hex::encode(bytes), "c8b4968a98ab6c50379fc8b039abc8fd9aca259f4746a05bfbdf12c86463c208", "the 256th (last) point is incorrect" ); @@ -593,11 +590,11 @@ fn crs_consistency() { for point in &points { let mut bytes = [0u8; 32]; point.serialize(&mut bytes[..]).unwrap(); - hasher.update(&bytes); + hasher.update(bytes); } let bytes = hasher.finalize().to_vec(); assert_eq!( - hex::encode(&bytes), + hex::encode(bytes), "c390cbb4bc42019685d5a01b2fb8a536d4332ea4e128934d0ae7644163089e76", "unexpected point encountered" ); diff --git a/src/transcript.rs b/src/transcript.rs index 43b7dd4..e477f56 100644 --- a/src/transcript.rs +++ b/src/transcript.rs @@ -86,7 +86,7 @@ mod tests { #[test] fn test_vector_2() { let mut tr = Transcript::new(b"simple_protocol"); - let five = Fr::from(5 as u128); + let five = Fr::from(5_u128); tr.append_scalar(b"five", &five); tr.append_scalar(b"five again", &five); @@ -101,7 +101,7 @@ mod tests { #[test] fn test_vector_3() { let mut tr = Transcript::new(b"simple_protocol"); - let one = Fr::from(1 as u128); + let one = Fr::from(1_u128); let minus_one = -one; tr.append_scalar(b"-1", &minus_one);