From bba86d0a3c5b7e46001fbd708553fb6eec2f497d Mon Sep 17 00:00:00 2001 From: Ben Savage Date: Sun, 17 Mar 2024 01:01:03 +1000 Subject: [PATCH 1/5] Adding the first part of the zero knowledge proof computation, computing the polynomial G --- .../ipa_prf/malicious_security/lagrange.rs | 9 +- .../ipa_prf/malicious_security/mod.rs | 1 + .../ipa_prf/malicious_security/prover.rs | 93 +++++++++++++++++++ 3 files changed, 99 insertions(+), 4 deletions(-) create mode 100644 ipa-core/src/protocol/ipa_prf/malicious_security/prover.rs diff --git a/ipa-core/src/protocol/ipa_prf/malicious_security/lagrange.rs b/ipa-core/src/protocol/ipa_prf/malicious_security/lagrange.rs index c00182bfd..b0654b8d1 100644 --- a/ipa-core/src/protocol/ipa_prf/malicious_security/lagrange.rs +++ b/ipa-core/src/protocol/ipa_prf/malicious_security/lagrange.rs @@ -70,6 +70,7 @@ where /// The "x coordinates" of the output points `x_N` to `x_(N+M-1)` are `N*F::ONE` to `(N+M-1)*F::ONE` /// when generated using `from(denominator)` /// unless generated using `new(denominator, x_output)` for a specific output "x coordinate" `x_output`. +#[derive(Debug)] pub struct LagrangeTable { table: GenericArray, M>, } @@ -101,13 +102,13 @@ where { /// This function uses the `LagrangeTable` to evaluate `polynomial` on the specified output "x coordinates" /// outputs the "y coordinates" such that `(x,y)` lies on `polynomial` - pub fn eval(&self, polynomial: &Polynomial) -> GenericArray { + pub fn eval(&self, y_coordinates: &GenericArray) -> GenericArray { self.table .iter() .map(|table_row| { table_row .iter() - .zip(polynomial.y_coordinates.iter()) + .zip(y_coordinates.iter()) .fold(F::ZERO, |acc, (&base, &y)| acc + base * y) }) .collect() @@ -245,7 +246,7 @@ mod test { let denominator = CanonicalLagrangeDenominator::::new(); // generate table using new let lagrange_table = LagrangeTable::::new(&denominator, &output_point); - let output = lagrange_table.eval(&polynomial); + let output = lagrange_table.eval(&polynomial.y_coordinates); assert_eq!(output, output_expected); } @@ -269,7 +270,7 @@ mod test { let denominator = CanonicalLagrangeDenominator::::new(); // generate table using from let lagrange_table = LagrangeTable::::from(denominator); - let output = lagrange_table.eval(&polynomial); + let output = lagrange_table.eval(&polynomial.y_coordinates); assert_eq!(output, output_expected); } diff --git a/ipa-core/src/protocol/ipa_prf/malicious_security/mod.rs b/ipa-core/src/protocol/ipa_prf/malicious_security/mod.rs index ea0ac6eef..aed193ad3 100644 --- a/ipa-core/src/protocol/ipa_prf/malicious_security/mod.rs +++ b/ipa-core/src/protocol/ipa_prf/malicious_security/mod.rs @@ -1 +1,2 @@ pub mod lagrange; +pub mod prover; \ No newline at end of file diff --git a/ipa-core/src/protocol/ipa_prf/malicious_security/prover.rs b/ipa-core/src/protocol/ipa_prf/malicious_security/prover.rs new file mode 100644 index 000000000..f08407327 --- /dev/null +++ b/ipa-core/src/protocol/ipa_prf/malicious_security/prover.rs @@ -0,0 +1,93 @@ +use std::{ + iter::zip, + ops::{Add, Sub}, +}; + +use generic_array::{arr, sequence::GenericSequence, ArrayLength, GenericArray}; +use typenum::{Diff, Sum, Unsigned, U1}; + +use crate::{ + ff::PrimeField, + protocol::ipa_prf::malicious_security::lagrange::{ + CanonicalLagrangeDenominator, LagrangeTable, Polynomial, + }, +}; + +pub struct ProofGenerator { + u: Vec, + v: Vec, +} + +impl ProofGenerator +where + F: PrimeField, +{ + pub fn compute_proof(self) -> GenericArray, U1>> + where + N: ArrayLength + Add + Sub, + ::Output: Sub, + <::Output as Sub>::Output: ArrayLength, + >::Output: ArrayLength, + { + assert!(self.u.len() % N::USIZE == 0); // We should pad with zeroes eventually + + let strip_len = self.u.len() / N::USIZE; + + let denominator = CanonicalLagrangeDenominator::::new(); + let lagrange_table = LagrangeTable::>::Output>::from(denominator); + let extrapolated_points = (0..strip_len).map(|i| { + let p: GenericArray = (0..N::USIZE).map(|j| self.u[i * N::USIZE + j]).collect(); + let q: GenericArray = (0..N::USIZE).map(|j| self.v[i * N::USIZE + j]).collect(); + let p_extrapolated = lagrange_table.eval(&p); + let q_extrapolated = lagrange_table.eval(&q); + zip( + p.into_iter().chain(p_extrapolated), + q.into_iter().chain(q_extrapolated), + ) + .map(|(a, b)| a * b) + .collect::>() + }); + extrapolated_points.reduce(|acc, pts| { + zip(acc, pts).map(|(a, b)| a + b).collect() + }).unwrap() + } +} + +#[cfg(all(test, unit_test))] +mod test { + use std::fmt::Debug; + + use generic_array::{sequence::GenericSequence, ArrayLength, GenericArray}; + use proptest::{prelude::*, proptest}; + use typenum::{U1, U32, U4, U7, U8}; + + use super::ProofGenerator; + use crate::{ + ff::{Field, Fp31, U128Conversions}, + protocol::ipa_prf::malicious_security::lagrange::{ + CanonicalLagrangeDenominator, LagrangeTable, Polynomial, + }, + }; + + #[test] + fn sample_proof() { + const U: [u128; 32] = [ + 0, 0, 1, 15, 0, 0, 0, 15, 2, 30, 30, 16, 29, 1, 1, 15, 0, 0, 0, 15, 0, 0, 0, 15, 2, 30, + 30, 16, 0, 0, 1, 15, + ]; + const V: [u128; 32] = [ + 30, 30, 30, 30, 0, 1, 0, 1, 0, 0, 0, 30, 0, 30, 0, 30, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, + 30, 0, 0, 30, 30, + ]; + const EXPECTED: [u128; 7] = [0, 30, 29, 30, 3, 22, 6]; + let pg: ProofGenerator = ProofGenerator { + u: U.into_iter().map(|x| Fp31::try_from(x).unwrap()).collect(), + v: V.into_iter().map(|x| Fp31::try_from(x).unwrap()).collect(), + }; + let proof = pg.compute_proof::(); + assert_eq!( + proof.into_iter().map(|x| x.as_u128()).collect::>(), + EXPECTED + ); + } +} From dcbc421f2c7fb893384c8c5fcb5c3edd22f92e2d Mon Sep 17 00:00:00 2001 From: Ben Savage Date: Sun, 17 Mar 2024 01:19:08 +1000 Subject: [PATCH 2/5] formatting --- ipa-core/src/protocol/ipa_prf/malicious_security/mod.rs | 2 +- .../src/protocol/ipa_prf/malicious_security/prover.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ipa-core/src/protocol/ipa_prf/malicious_security/mod.rs b/ipa-core/src/protocol/ipa_prf/malicious_security/mod.rs index aed193ad3..0e7f6bf3a 100644 --- a/ipa-core/src/protocol/ipa_prf/malicious_security/mod.rs +++ b/ipa-core/src/protocol/ipa_prf/malicious_security/mod.rs @@ -1,2 +1,2 @@ pub mod lagrange; -pub mod prover; \ No newline at end of file +pub mod prover; diff --git a/ipa-core/src/protocol/ipa_prf/malicious_security/prover.rs b/ipa-core/src/protocol/ipa_prf/malicious_security/prover.rs index f08407327..4bc933958 100644 --- a/ipa-core/src/protocol/ipa_prf/malicious_security/prover.rs +++ b/ipa-core/src/protocol/ipa_prf/malicious_security/prover.rs @@ -45,11 +45,11 @@ where q.into_iter().chain(q_extrapolated), ) .map(|(a, b)| a * b) - .collect::>() + .collect::>() }); - extrapolated_points.reduce(|acc, pts| { - zip(acc, pts).map(|(a, b)| a + b).collect() - }).unwrap() + extrapolated_points + .reduce(|acc, pts| zip(acc, pts).map(|(a, b)| a + b).collect()) + .unwrap() } } From e4fbe635586e35cbe3a7f3e9b222e4cab1dc70df Mon Sep 17 00:00:00 2001 From: Ben Savage Date: Sun, 17 Mar 2024 01:32:04 +1000 Subject: [PATCH 3/5] removing Polynomial --- .../ipa_prf/malicious_security/lagrange.rs | 46 ++++++------------- .../ipa_prf/malicious_security/prover.rs | 19 ++------ 2 files changed, 19 insertions(+), 46 deletions(-) diff --git a/ipa-core/src/protocol/ipa_prf/malicious_security/lagrange.rs b/ipa-core/src/protocol/ipa_prf/malicious_security/lagrange.rs index b0654b8d1..8c90644fb 100644 --- a/ipa-core/src/protocol/ipa_prf/malicious_security/lagrange.rs +++ b/ipa-core/src/protocol/ipa_prf/malicious_security/lagrange.rs @@ -5,14 +5,6 @@ use typenum::{Unsigned, U1}; use crate::ff::{Field, PrimeField, Serializable}; -/// A degree `N-1` polynomial is stored as `N` points `(x,y)` -/// where the "x coordinates" of the input points are `x_0` to `x_N` are `F::ZERO` to `(N-1)*F::ONE` -/// Therefore, we only need to store the `y` coordinates. -#[derive(Debug, PartialEq, Clone)] -pub struct Polynomial { - y_coordinates: GenericArray, -} - /// The Canonical Lagrange denominator is defined as the denominator of the Lagrange base polynomials /// `https://en.wikipedia.org/wiki/Lagrange_polynomial` /// where the "x coordinates" of the input points are `x_0` to `x_N` are `F::ZERO` to `(N-1)*F::ONE` @@ -70,7 +62,6 @@ where /// The "x coordinates" of the output points `x_N` to `x_(N+M-1)` are `N*F::ONE` to `(N+M-1)*F::ONE` /// when generated using `from(denominator)` /// unless generated using `new(denominator, x_output)` for a specific output "x coordinate" `x_output`. -#[derive(Debug)] pub struct LagrangeTable { table: GenericArray, M>, } @@ -176,24 +167,30 @@ mod test { use typenum::{U1, U32, U7, U8}; use crate::{ - ff::Field, + ff::PrimeField, protocol::ipa_prf::malicious_security::lagrange::{ - CanonicalLagrangeDenominator, LagrangeTable, Polynomial, + CanonicalLagrangeDenominator, LagrangeTable, }, }; type TestField = crate::ff::Fp32BitPrime; #[derive(Debug, PartialEq, Clone)] - struct MonomialFormPolynomial { + struct MonomialFormPolynomial { coefficients: GenericArray, } impl MonomialFormPolynomial where - F: Field, + F: PrimeField, N: ArrayLength, { + fn gen_y_values_of_canonical_points(self) -> GenericArray { + let canonical_points: GenericArray = + GenericArray::generate(|i| F::try_from(u128::try_from(i).unwrap()).unwrap()); + self.eval(&canonical_points) + } + /// test helper function that evaluates a polynomial in monomial form, i.e. `sum_i c_i x^i` on points `x_output` /// where `c_0` to `c_N` are stored in `polynomial` fn eval(&self, x_output: &GenericArray) -> GenericArray @@ -217,21 +214,6 @@ mod test { } } - impl From> for Polynomial - where - F: Field + TryFrom, - >::Error: Debug, - N: ArrayLength, - { - fn from(value: MonomialFormPolynomial) -> Self { - let canonical_points: GenericArray = - GenericArray::generate(|i| F::try_from(u128::try_from(i).unwrap()).unwrap()); - Polynomial { - y_coordinates: value.eval(&canonical_points), - } - } - } - fn lagrange_single_output_point_using_new( output_point: TestField, input_points: [TestField; 32], @@ -242,11 +224,11 @@ mod test { let output_expected = polynomial_monomial_form.eval( &GenericArray::::from_array([output_point; 1]), ); - let polynomial = Polynomial::from(polynomial_monomial_form.clone()); let denominator = CanonicalLagrangeDenominator::::new(); // generate table using new let lagrange_table = LagrangeTable::::new(&denominator, &output_point); - let output = lagrange_table.eval(&polynomial.y_coordinates); + let output = + lagrange_table.eval(&polynomial_monomial_form.gen_y_values_of_canonical_points()); assert_eq!(output, output_expected); } @@ -266,11 +248,11 @@ mod test { TestField::try_from(u128::try_from(i).unwrap() + 8).unwrap() }); let output_expected = polynomial_monomial_form.eval(&x_coordinates_output); - let polynomial = Polynomial::from(polynomial_monomial_form.clone()); let denominator = CanonicalLagrangeDenominator::::new(); // generate table using from let lagrange_table = LagrangeTable::::from(denominator); - let output = lagrange_table.eval(&polynomial.y_coordinates); + let output = + lagrange_table.eval(&polynomial_monomial_form.gen_y_values_of_canonical_points()); assert_eq!(output, output_expected); } diff --git a/ipa-core/src/protocol/ipa_prf/malicious_security/prover.rs b/ipa-core/src/protocol/ipa_prf/malicious_security/prover.rs index 4bc933958..699c79f96 100644 --- a/ipa-core/src/protocol/ipa_prf/malicious_security/prover.rs +++ b/ipa-core/src/protocol/ipa_prf/malicious_security/prover.rs @@ -3,13 +3,13 @@ use std::{ ops::{Add, Sub}, }; -use generic_array::{arr, sequence::GenericSequence, ArrayLength, GenericArray}; -use typenum::{Diff, Sum, Unsigned, U1}; +use generic_array::{ArrayLength, GenericArray}; +use typenum::{Diff, Sum, U1}; use crate::{ ff::PrimeField, protocol::ipa_prf::malicious_security::lagrange::{ - CanonicalLagrangeDenominator, LagrangeTable, Polynomial, + CanonicalLagrangeDenominator, LagrangeTable, }, }; @@ -55,19 +55,10 @@ where #[cfg(all(test, unit_test))] mod test { - use std::fmt::Debug; - - use generic_array::{sequence::GenericSequence, ArrayLength, GenericArray}; - use proptest::{prelude::*, proptest}; - use typenum::{U1, U32, U4, U7, U8}; + use typenum::U4; use super::ProofGenerator; - use crate::{ - ff::{Field, Fp31, U128Conversions}, - protocol::ipa_prf::malicious_security::lagrange::{ - CanonicalLagrangeDenominator, LagrangeTable, Polynomial, - }, - }; + use crate::ff::{Fp31, U128Conversions}; #[test] fn sample_proof() { From bb6bf73d758aa531fa9db77a8128aa34368f6cc7 Mon Sep 17 00:00:00 2001 From: Ben Savage Date: Sun, 17 Mar 2024 01:44:39 +1000 Subject: [PATCH 4/5] using the same variable and constant names as the paper --- .../ipa_prf/malicious_security/prover.rs | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/ipa-core/src/protocol/ipa_prf/malicious_security/prover.rs b/ipa-core/src/protocol/ipa_prf/malicious_security/prover.rs index 699c79f96..405a8ce83 100644 --- a/ipa-core/src/protocol/ipa_prf/malicious_security/prover.rs +++ b/ipa-core/src/protocol/ipa_prf/malicious_security/prover.rs @@ -18,26 +18,31 @@ pub struct ProofGenerator { v: Vec, } +/// +/// Distributed Zero Knowledge Proofs algorithm drawn from +/// `https://eprint.iacr.org/2023/909.pdf` +/// impl ProofGenerator where F: PrimeField, { - pub fn compute_proof(self) -> GenericArray, U1>> + #![allow(non_camel_case_types)] + pub fn compute_proof<λ: ArrayLength>(self) -> GenericArray, U1>> where - N: ArrayLength + Add + Sub, - ::Output: Sub, - <::Output as Sub>::Output: ArrayLength, - >::Output: ArrayLength, + λ: ArrayLength + Add + Sub, + <λ as Add>::Output: Sub, + <<λ as Add>::Output as Sub>::Output: ArrayLength, + <λ as Sub>::Output: ArrayLength, { - assert!(self.u.len() % N::USIZE == 0); // We should pad with zeroes eventually + assert!(self.u.len() % λ::USIZE == 0); // We should pad with zeroes eventually - let strip_len = self.u.len() / N::USIZE; + let s = self.u.len() / λ::USIZE; - let denominator = CanonicalLagrangeDenominator::::new(); - let lagrange_table = LagrangeTable::>::Output>::from(denominator); - let extrapolated_points = (0..strip_len).map(|i| { - let p: GenericArray = (0..N::USIZE).map(|j| self.u[i * N::USIZE + j]).collect(); - let q: GenericArray = (0..N::USIZE).map(|j| self.v[i * N::USIZE + j]).collect(); + let denominator = CanonicalLagrangeDenominator::::new(); + let lagrange_table = LagrangeTable::>::Output>::from(denominator); + let extrapolated_points = (0..s).map(|i| { + let p: GenericArray = (0..λ::USIZE).map(|j| self.u[i * λ::USIZE + j]).collect(); + let q: GenericArray = (0..λ::USIZE).map(|j| self.v[i * λ::USIZE + j]).collect(); let p_extrapolated = lagrange_table.eval(&p); let q_extrapolated = lagrange_table.eval(&q); zip( From 661259ccc7d82db75c6404ee7037c26f4718c24f Mon Sep 17 00:00:00 2001 From: Ben Savage Date: Sun, 17 Mar 2024 01:50:27 +1000 Subject: [PATCH 5/5] removing an explicit type --- ipa-core/src/protocol/ipa_prf/malicious_security/prover.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ipa-core/src/protocol/ipa_prf/malicious_security/prover.rs b/ipa-core/src/protocol/ipa_prf/malicious_security/prover.rs index 405a8ce83..dd0263243 100644 --- a/ipa-core/src/protocol/ipa_prf/malicious_security/prover.rs +++ b/ipa-core/src/protocol/ipa_prf/malicious_security/prover.rs @@ -41,8 +41,8 @@ where let denominator = CanonicalLagrangeDenominator::::new(); let lagrange_table = LagrangeTable::>::Output>::from(denominator); let extrapolated_points = (0..s).map(|i| { - let p: GenericArray = (0..λ::USIZE).map(|j| self.u[i * λ::USIZE + j]).collect(); - let q: GenericArray = (0..λ::USIZE).map(|j| self.v[i * λ::USIZE + j]).collect(); + let p = (0..λ::USIZE).map(|j| self.u[i * λ::USIZE + j]).collect(); + let q = (0..λ::USIZE).map(|j| self.v[i * λ::USIZE + j]).collect(); let p_extrapolated = lagrange_table.eval(&p); let q_extrapolated = lagrange_table.eval(&q); zip(