From 76b0af555ac2799236630f00f2ae30577c111011 Mon Sep 17 00:00:00 2001 From: Junochiu Date: Thu, 26 Dec 2024 03:20:40 +0800 Subject: [PATCH 1/9] refactor: wip, create algebra crate, separating files --- Cargo.toml | 1 + algebra/Cargo.toml | 12 + algebra/src/lib.rs | 9 + .../src/polynomial_ring.rs | 215 +-- algebra/src/rq_matrix.rs | 36 + algebra/src/utils.rs | 313 ++++ algebra/src/zq.rs | 161 ++ labrador/Cargo.toml | 1 + labrador/src/gadgets/aggregation.rs | 529 +++++++ .../src/gadgets/conjugation_automorphism.rs | 75 + labrador/src/gadgets/decompose.rs | 0 labrador/src/gadgets/gaussian_generator.rs | 25 + labrador/src/gadgets/mod.rs | 4 + labrador/src/gadgets/norm.rs | 121 ++ labrador/src/lib.rs | 3 +- labrador/src/prover.rs | 1362 +---------------- labrador/src/setup.rs | 3 +- labrador/src/utils.rs | 140 ++ labrador/src/verifier.rs | 238 ++- 19 files changed, 1719 insertions(+), 1529 deletions(-) create mode 100644 algebra/Cargo.toml rename labrador/src/algebra.rs => algebra/src/polynomial_ring.rs (68%) create mode 100644 algebra/src/rq_matrix.rs create mode 100644 algebra/src/utils.rs create mode 100644 algebra/src/zq.rs create mode 100644 labrador/src/gadgets/aggregation.rs create mode 100644 labrador/src/gadgets/conjugation_automorphism.rs create mode 100644 labrador/src/gadgets/decompose.rs create mode 100644 labrador/src/gadgets/gaussian_generator.rs create mode 100644 labrador/src/gadgets/mod.rs create mode 100644 labrador/src/gadgets/norm.rs create mode 100644 labrador/src/utils.rs diff --git a/Cargo.toml b/Cargo.toml index 8153947..c81e7d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ resolver = "2" members = [ "labrador", + "algebra" ] [workspace.package] diff --git a/algebra/Cargo.toml b/algebra/Cargo.toml new file mode 100644 index 0000000..2bf24b7 --- /dev/null +++ b/algebra/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "algebra" +version = { workspace = true } +edition = { workspace = true } + +# Optional: Add a description, authors, license, etc. +description = "" +authors = [""] +license = "MIT OR Apache-2.0" + +[dependencies] +rand = { workspace = true } \ No newline at end of file diff --git a/algebra/src/lib.rs b/algebra/src/lib.rs index e69de29..0548c1c 100644 --- a/algebra/src/lib.rs +++ b/algebra/src/lib.rs @@ -0,0 +1,9 @@ +pub mod polynomial_ring; +pub mod rq_matrix; +pub mod utils; +pub mod zq; + +pub use polynomial_ring::PolynomialRing; +pub use rq_matrix::RqMatrix; +pub use utils::*; +pub use zq::Zq; diff --git a/labrador/src/algebra.rs b/algebra/src/polynomial_ring.rs similarity index 68% rename from labrador/src/algebra.rs rename to algebra/src/polynomial_ring.rs index ff1e6aa..67a3e73 100644 --- a/labrador/src/algebra.rs +++ b/algebra/src/polynomial_ring.rs @@ -1,14 +1,10 @@ +use crate::zq::Zq; use std::cmp::PartialEq; -use std::fmt::Display; -use std::iter::Sum; use std::ops::Add; -use std::ops::AddAssign; -use std::ops::Div; use std::ops::Mul; -use std::ops::Rem; -use std::ops::Sub; #[derive(Debug, Clone, Eq)] + pub struct PolynomialRing { pub coefficients: Vec, } @@ -254,193 +250,10 @@ impl PartialEq for PolynomialRing { } } -// Let q be a modulus, and let Zq be the ring of integers mod q -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct Zq { - pub value: usize, -} - -impl Zq { - // todo: use symmetric from -Q/2 to Q/2 - pub const Q: usize = 2usize.pow(32); - - pub fn modulus() -> usize { - Self::Q - } - pub fn new(value: usize) -> Self { - Zq { - value: value % Self::Q, - } - } - - pub fn value(&self) -> usize { - self.value - } - - pub fn pow(&self, other: usize) -> Self { - Zq::new(self.value.pow(other as u32)) - } -} - -impl PartialOrd for Zq { - fn partial_cmp(&self, other: &Zq) -> Option { - Some(self.value.cmp(&other.value)) - } -} - -impl Display for Zq { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.value) - } -} - -impl Rem for Zq { - type Output = Zq; - - fn rem(self, other: Zq) -> Zq { - Zq::new(self.value % other.value) - } -} - -impl Add for Zq { - type Output = Zq; - - fn add(self, other: Zq) -> Zq { - // assert!(self.value + other.value < Self::Q, "Addition result exceeds modulus"); - Zq::new(self.value + other.value) - } -} - -impl AddAssign for Zq { - fn add_assign(&mut self, other: Zq) { - self.value = (self.value + other.value) % Self::Q; - } -} - -impl Sub for Zq { - type Output = Zq; - - fn sub(self, other: Zq) -> Zq { - Zq::new((self.value + Self::Q) - other.value) - } -} - -impl Mul for Zq { - type Output = Zq; - - fn mul(self, other: Zq) -> Zq { - // assert!(self.value * other.value < Self::Q, "Multiplication result exceeds modulus"); - Zq::new(self.value * other.value) - } -} - -impl From for Zq { - fn from(value: usize) -> Self { - Zq::new(value) - } -} - -impl Sum for Zq { - fn sum>(iter: I) -> Self { - iter.fold(Zq::new(0), |acc, x| acc + x) - } -} - -#[derive(Debug)] -pub struct RqMatrix { - pub values: Vec>, // matrix of PolynomialRing values -} - -impl RqMatrix { - pub fn new(kappa: Zq, size_n: Zq) -> Self { - let size_kappa_usize: usize = kappa.value(); - let size_n_usize: usize = size_n.value(); - let mut rng = rand::thread_rng(); - let values: Vec> = (0..size_kappa_usize) - .map(|_| { - (0..size_n_usize) - .map(|_| PolynomialRing { - coefficients: (0..size_n_usize) - .map(|_| Zq::from(2)) // we just use 2 as random number to facilitate test - .collect(), - }) - .collect() - }) - .collect(); - assert_eq!( - values.len(), - size_kappa_usize, - "values must have the same length as size_kappa" - ); - assert_eq!( - values[0].len(), - size_n_usize, - "values[0] must have the same length as size_n" - ); - RqMatrix { values } - } -} - #[cfg(test)] mod tests { use super::*; - #[test] - fn test_zq_addition() { - let a = Zq::new(10); - let b = Zq::new(20); - let result = a + b; - assert_eq!(result.value, 30); - } - - #[test] - fn test_zq_subtraction() { - let a = Zq::new(10); - let b = Zq::new(5); - let result = a - b; - assert_eq!(result.value, 5); - } - - #[test] - fn test_zq_multiplication() { - let a = Zq::new(6); - let b = Zq::new(7); - let result = a * b; - assert_eq!(result.value, 42); - } - - #[test] - fn test_zq_multiplication_overflow() { - let a = Zq::new(Zq::Q - 1); - let b = Zq::new(2); - let result = a * b; - let expected = Zq::new(Zq::Q - 2); // -2 - assert_eq!(result, expected); - } - - #[test] - fn test_zq_overflow() { - let a = Zq::new(Zq::Q - 1); - let b = Zq::new(2); - let result = a + b; - assert_eq!(result.value, 1); // (2^32 - 1) + 2 mod 2^32 = 1 - } - - #[test] - fn test_zq_new() { - let value = 4294967297; // Q + 1 - let zq = Zq::new(value); - assert_eq!(zq.value, 1); - } - - #[test] - fn test_zq_remainder() { - let a = Zq::new(10); - let b = Zq::new(3); - let result = a % b; - assert_eq!(result.value, 1); - } - #[test] fn test_multiply_by_polynomial_ring() { let poly1 = PolynomialRing { @@ -506,4 +319,28 @@ mod tests { "Overflow handling in multiplication is incorrect" ); } + + // add test for polynomial addition and multiplication with overload + #[test] + fn test_polynomial_addition_and_multiplication() { + let a = PolynomialRing { + coefficients: vec![Zq::from(1), Zq::from(2), Zq::from(3)], + }; + let b = PolynomialRing { + coefficients: vec![Zq::from(4), Zq::from(5), Zq::from(6)], + }; + let c = &a + &b; + assert_eq!(c.coefficients, vec![Zq::from(5), Zq::from(7), Zq::from(9)]); + let d = &a * &b; + assert_eq!( + d.coefficients, + vec![ + Zq::from(4), + Zq::from(13), + Zq::from(28), + Zq::from(27), + Zq::from(18) + ] + ); + } } diff --git a/algebra/src/rq_matrix.rs b/algebra/src/rq_matrix.rs new file mode 100644 index 0000000..588b411 --- /dev/null +++ b/algebra/src/rq_matrix.rs @@ -0,0 +1,36 @@ +use crate::polynomial_ring::PolynomialRing; +use crate::zq::Zq; + +#[derive(Debug)] +pub struct RqMatrix { + pub values: Vec>, +} + +impl RqMatrix { + pub fn new(kappa: Zq, size_n: Zq) -> Self { + let size_kappa_usize: usize = kappa.value(); + let size_n_usize: usize = size_n.value(); + let values: Vec> = (0..size_kappa_usize) + .map(|_| { + (0..size_n_usize) + .map(|_| PolynomialRing { + coefficients: (0..size_n_usize) + .map(|_| Zq::from(2)) // we just use 2 as random number to facilitate test + .collect(), + }) + .collect() + }) + .collect(); + assert_eq!( + values.len(), + size_kappa_usize, + "values must have the same length as size_kappa" + ); + assert_eq!( + values[0].len(), + size_n_usize, + "values[0] must have the same length as size_n" + ); + RqMatrix { values } + } +} diff --git a/algebra/src/utils.rs b/algebra/src/utils.rs new file mode 100644 index 0000000..d00b83b --- /dev/null +++ b/algebra/src/utils.rs @@ -0,0 +1,313 @@ +use crate::polynomial_ring::PolynomialRing; +use crate::zq::Zq; +use rand::Rng; + +pub fn zero_poly() -> PolynomialRing { + PolynomialRing { + coefficients: vec![Zq::from(0); 1], + } +} + +// a: Vec, b: PolynomialRing +// calculate c = a * b, c_i = a_i * b +// c: Vec +pub fn poly_vec_times_poly(a: &[PolynomialRing], b: &PolynomialRing) -> Vec { + a.iter().map(|a_i| a_i * b).collect() +} +// a: Vec, b: Vec +// calculate c = a + b, c_i = a_i + b_i +// c: Vec +pub fn poly_vec_add_poly_vec(a: &[PolynomialRing], b: &[PolynomialRing]) -> Vec { + a.iter().zip(b.iter()).map(|(a_i, b_i)| a_i + b_i).collect() +} + +// inner product of 2 vectors of PolynomialRing +pub fn inner_product_polynomial_ring_vector( + a: &[PolynomialRing], + b: &[PolynomialRing], +) -> PolynomialRing { + assert_eq!( + a.len(), + b.len(), + "inner_product_polynomial_ring_vector: a and b must have the same length" + ); + a.iter() + .zip(b.iter()) + .map(|(a, b)| a * b) + .collect::>() + .into_iter() + .reduce(|acc, x| acc + x) + .unwrap() +} + +pub fn inner_product_zq_vector(a: &[Zq], b: &[Zq]) -> Zq { + a.iter().zip(b.iter()).map(|(a, b)| *a * *b).sum() +} + +// a: Vec>, b: Vec +// calculate c = sum(c_i), c_i = poly_vec_times_poly(a_i, b_i) +// c: Vec +pub fn inner_product_poly_matrix_and_poly_vector( + poly_matrix: &[Vec], + poly_vector: &[PolynomialRing], +) -> Vec { + assert_eq!(poly_matrix.len(), poly_vector.len(), "inner_product_poly_matrix_and_poly_vector: poly_matrix and poly_vector must have the same length"); + poly_matrix + .iter() + .zip(poly_vector.iter()) + .map(|(poly_matrix_row, poly_vector_element)| { + poly_vec_times_poly(poly_matrix_row, poly_vector_element) + }) + .fold( + vec![zero_poly(); poly_matrix[0].len()], + |acc, x: Vec| poly_vec_add_poly_vec(&acc, &x), + ) +} + +pub fn generate_random_polynomial_ring(deg_bound_d: usize) -> PolynomialRing { + let mut rng = rand::thread_rng(); + PolynomialRing { + coefficients: (0..deg_bound_d) + .map(|_| Zq::from(rng.gen_range(1..5))) + .collect(), + } +} + +// calculate matrix times vector of PolynomialRing +pub fn matrix_poly_times_poly_vector( + poly_matrix: &Vec>, + poly_vec: &Vec, +) -> Vec { + poly_matrix + .iter() + .map(|row| inner_product_polynomial_ring_vector(row, poly_vec)) + .collect::>() +} + +#[cfg(test)] +mod tests { + use super::*; + use std::vec; + + #[test] + fn test_poly_vec_times_poly() { + // Arrange + let a = vec![ + PolynomialRing { + coefficients: vec![Zq::from(1), Zq::from(2), Zq::from(3)], + }, + PolynomialRing { + coefficients: vec![Zq::from(4), Zq::from(5), Zq::from(6)], + }, + ]; + let b = PolynomialRing { + coefficients: vec![Zq::from(2), Zq::from(3), Zq::from(4)], + }; + + // Act + let result = poly_vec_times_poly(&a, &b); + // expected[0] = a[0] * b = (1 + 2x + 3x^2) * (2 + 3x + 4x^2) = 2 + 7x + 16x^2 + 17x^3 + 12x^4 + // expected[1] = a[1] * b = (4 + 5x + 6x^2) * (2 + 3x + 4x^2) = 8 + 22x + 43x^2 + 38x^3 + 24x^4 + // Assert + let expected = vec![ + PolynomialRing { + coefficients: vec![ + Zq::from(2), + Zq::from(7), + Zq::from(16), + Zq::from(17), + Zq::from(12), + ], + }, + PolynomialRing { + coefficients: vec![ + Zq::from(8), + Zq::from(22), + Zq::from(43), + Zq::from(38), + Zq::from(24), + ], + }, + ]; + assert_eq!(result, expected); + } + + #[test] + fn test_poly_vec_add_poly_vec() { + // Arrange + let a = vec![ + PolynomialRing { + coefficients: vec![Zq::from(1), Zq::from(2), Zq::from(3)], + }, + PolynomialRing { + coefficients: vec![Zq::from(4), Zq::from(5), Zq::from(6)], + }, + ]; + let b = vec![ + PolynomialRing { + coefficients: vec![Zq::from(7), Zq::from(8), Zq::from(9)], + }, + PolynomialRing { + coefficients: vec![Zq::from(10), Zq::from(11), Zq::from(12)], + }, + ]; + + // Act + let result = poly_vec_add_poly_vec(&a, &b); + + // Assert + let expected = vec![ + PolynomialRing { + coefficients: vec![Zq::from(8), Zq::from(10), Zq::from(12)], + }, + PolynomialRing { + coefficients: vec![Zq::from(14), Zq::from(16), Zq::from(18)], + }, + ]; + assert_eq!(result, expected); + } + + #[test] + fn test_inner_product_polynomial_ring() { + let a = vec![ + PolynomialRing { + coefficients: vec![Zq::from(1), Zq::from(2), Zq::from(3)], + }, + PolynomialRing { + coefficients: vec![Zq::from(4), Zq::from(5), Zq::from(6)], + }, + ]; + let b = vec![ + PolynomialRing { + coefficients: vec![Zq::from(7), Zq::from(8), Zq::from(9)], + }, + PolynomialRing { + coefficients: vec![Zq::from(10), Zq::from(11), Zq::from(12)], + }, + ]; + + let result = inner_product_polynomial_ring_vector(&a, &b); + + // Expected result calculation: + // (1 + 2x + 3x^2) * (7 + 8x + 9x^2) = 7 + 22x + 46x^2 + 42x^3 + 27x^4 + // (4 + 5x + 6x^2) * (10 + 11x + 12x^2) = 40 + 96x + 163x^2 + 126x^3 + 72x^4 + // Sum: 47 + 116x + 209x^2 + 168x^3 + 99x^4 + + let expected = PolynomialRing { + coefficients: vec![ + Zq::from(47), + Zq::from(116), + Zq::from(209), + Zq::from(168), + Zq::from(99), + ], + }; + + assert_eq!(result.coefficients, expected.coefficients); + } + + #[test] + fn test_inner_product_zq_vector() { + // Arrange + let a = vec![Zq::from(1), Zq::from(2), Zq::from(3)]; + let b = vec![Zq::from(4), Zq::from(5), Zq::from(6)]; + + // Act + let result = inner_product_zq_vector(&a, &b); + + // Assert + let expected = + (Zq::from(1) * Zq::from(4)) + (Zq::from(2) * Zq::from(5)) + (Zq::from(3) * Zq::from(6)); + assert_eq!( + result, expected, + "inner_product_zq_vector did not return the correct result" + ); + } + + #[test] + fn test_inner_product_poly_matrix_and_poly_vector() { + // Arrange + let poly_matrix = vec![ + vec![ + PolynomialRing { + coefficients: vec![Zq::from(1), Zq::from(2)], + }, + PolynomialRing { + coefficients: vec![Zq::from(3), Zq::from(4)], + }, + ], + vec![ + PolynomialRing { + coefficients: vec![Zq::from(5), Zq::from(6)], + }, + PolynomialRing { + coefficients: vec![Zq::from(7), Zq::from(8)], + }, + ], + ]; + let poly_vector = vec![ + PolynomialRing { + coefficients: vec![Zq::from(9), Zq::from(10)], + }, + PolynomialRing { + coefficients: vec![Zq::from(11), Zq::from(12)], + }, + ]; + + // Expected Calculation: + // u = sum D_ij * h_ij^(k) for all k = 1..(t1-1) + // For this test case: + // Result[0] = (1+2x) * (9+10x) + (5+6x) * (11+12x) = 64 + 154x + 92x^2 + // Result[1] = (3+4x) * (9+10x) + (7+8x) * (11+12x) = 104 + 238x + 136x^2 + let expected = vec![ + PolynomialRing { + coefficients: vec![Zq::from(64), Zq::from(154), Zq::from(92)], + }, + PolynomialRing { + coefficients: vec![Zq::from(104), Zq::from(238), Zq::from(136)], + }, + ]; + + // Act + let result = inner_product_poly_matrix_and_poly_vector(&poly_matrix, &poly_vector); + + // Assert + assert_eq!(result, expected, "The inner product of the polynomial matrix and vector did not produce the expected result."); + } + + #[test] + fn test_inner_product_polynomial_ring_vector() { + // Define sample PolynomialRing vectors + let a = vec![ + PolynomialRing { + coefficients: vec![Zq::from(1), Zq::from(2), Zq::from(3)], + }, + PolynomialRing { + coefficients: vec![Zq::from(4), Zq::from(5), Zq::from(6)], + }, + ]; + let b = vec![ + PolynomialRing { + coefficients: vec![Zq::from(7), Zq::from(8), Zq::from(9)], + }, + PolynomialRing { + coefficients: vec![Zq::from(10), Zq::from(11), Zq::from(12)], + }, + ]; + // (1 + 2x + 3x^2) * (7 + 8x + 9x^2) + (4 + 5x + 6x^2) * (10 + 11x + 12x^2) + // = (7 + 22x + 46x^2 + 42x^3 + 27x^4) + (40 + 94x + 163x^2 + 126x^3 + 72x^4) + // = 47 + 116x + 209x^2 + 168x^3 + 99x^4 + let result = inner_product_polynomial_ring_vector(&a, &b); + let expected = PolynomialRing { + coefficients: vec![ + Zq::from(47), // 47 + Zq::from(116), // 116 + Zq::from(209), // 209 + Zq::from(168), // 168 + Zq::from(99), // 99 + ], + }; + + assert_eq!(result, expected); + } +} diff --git a/algebra/src/zq.rs b/algebra/src/zq.rs new file mode 100644 index 0000000..b1e5a9a --- /dev/null +++ b/algebra/src/zq.rs @@ -0,0 +1,161 @@ +use std::cmp::PartialEq; +use std::fmt::Display; +use std::iter::Sum; +use std::ops::Add; +use std::ops::AddAssign; +use std::ops::Mul; +use std::ops::Rem; +use std::ops::Sub; + +// Let q be a modulus, and let Zq be the ring of integers mod q +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct Zq { + pub value: usize, +} + +impl Zq { + // todo: use symmetric from -Q/2 to Q/2 + pub const Q: usize = 2usize.pow(32); + + pub fn modulus() -> usize { + Self::Q + } + pub fn new(value: usize) -> Self { + Zq { + value: value % Self::Q, + } + } + + pub fn value(&self) -> usize { + self.value + } + + pub fn pow(&self, other: usize) -> Self { + Zq::new(self.value.pow(other as u32)) + } +} + +impl PartialOrd for Zq { + fn partial_cmp(&self, other: &Zq) -> Option { + Some(self.value.cmp(&other.value)) + } +} + +impl Display for Zq { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.value) + } +} + +impl Rem for Zq { + type Output = Zq; + + fn rem(self, other: Zq) -> Zq { + Zq::new(self.value % other.value) + } +} + +impl Add for Zq { + type Output = Zq; + + fn add(self, other: Zq) -> Zq { + // assert!(self.value + other.value < Self::Q, "Addition result exceeds modulus"); + Zq::new(self.value + other.value) + } +} + +impl AddAssign for Zq { + fn add_assign(&mut self, other: Zq) { + self.value = (self.value + other.value) % Self::Q; + } +} + +impl Sub for Zq { + type Output = Zq; + + fn sub(self, other: Zq) -> Zq { + Zq::new((self.value + Self::Q) - other.value) + } +} + +impl Mul for Zq { + type Output = Zq; + + fn mul(self, other: Zq) -> Zq { + // assert!(self.value * other.value < Self::Q, "Multiplication result exceeds modulus"); + Zq::new(self.value * other.value) + } +} + +impl From for Zq { + fn from(value: usize) -> Self { + Zq::new(value) + } +} + +impl Sum for Zq { + fn sum>(iter: I) -> Self { + iter.fold(Zq::new(0), |acc, x| acc + x) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_zq_addition() { + let a = Zq::new(10); + let b = Zq::new(20); + let result = a + b; + assert_eq!(result.value, 30); + } + + #[test] + fn test_zq_subtraction() { + let a = Zq::new(10); + let b = Zq::new(5); + let result = a - b; + assert_eq!(result.value, 5); + } + + #[test] + fn test_zq_multiplication() { + let a = Zq::new(6); + let b = Zq::new(7); + let result = a * b; + assert_eq!(result.value, 42); + } + + #[test] + fn test_zq_multiplication_overflow() { + let a = Zq::new(Zq::Q - 1); + let b = Zq::new(2); + let result = a * b; + let expected = Zq::new(Zq::Q - 2); // -2 + assert_eq!(result, expected); + } + + #[test] + fn test_zq_overflow() { + let a = Zq::new(Zq::Q - 1); + let b = Zq::new(2); + let result = a + b; + assert_eq!(result.value, 1); // (2^32 - 1) + 2 mod 2^32 = 1 + } + + #[test] + fn test_zq_new() { + let value = 4294967297; // Q + 1 + let zq = Zq::new(value); + assert_eq!(zq.value, 1); + } + + #[test] + fn test_zq_remainder() { + let a = Zq::new(10); + let b = Zq::new(3); + let result = a % b; + assert_eq!(result.value, 1); + } +} diff --git a/labrador/Cargo.toml b/labrador/Cargo.toml index 6b50949..b84bcda 100644 --- a/labrador/Cargo.toml +++ b/labrador/Cargo.toml @@ -11,6 +11,7 @@ path = "src/example/main.rs" [dependencies] rand = { workspace = true } rayon = {workspace = true, optional = true} +algebra = { path = '../algebra' } profiler_macro = { workspace = true } ark-std = { workspace = true, optional = true } diff --git a/labrador/src/gadgets/aggregation.rs b/labrador/src/gadgets/aggregation.rs new file mode 100644 index 0000000..de75ec9 --- /dev/null +++ b/labrador/src/gadgets/aggregation.rs @@ -0,0 +1,529 @@ +use crate::gadgets::gaussian_generator::generate_gaussian_distribution; +use algebra::{ + generate_random_polynomial_ring, inner_product_polynomial_ring_vector, zero_poly, + PolynomialRing, Zq, +}; +use rand::Rng; + +// 4.3.1 aggregation: calculate a_ij^{''(k)} = sum(psi_l^(k) * a_ij^{'(l)}) for all l = 1..L +pub fn compute_aggr_ct_constraint_a( + a_constraint_ct: &Vec>>, + psi: &Vec>, + size_k: Zq, + size_r: Zq, + constraint_num_l: Zq, + deg_bound_d: Zq, +) -> Vec>> { + let a_ct_aggr: Vec>> = (0..size_k.value()) + .map(|k| { + let psi_k = &psi[k]; + (0..size_r.value()) + .map(|i| { + (0..size_r.value()) + .map(|j| { + (0..constraint_num_l.value()) + .map(|l| &a_constraint_ct[l][i][j] * psi_k[l]) + .fold( + PolynomialRing { + coefficients: vec![Zq::from(0); deg_bound_d.value()], + }, + |acc, x| acc + x, + ) + }) + .collect::>() + }) + .collect::>>() + }) + .collect(); + a_ct_aggr +} + +// 4.3.2 aggregation: calculate phi_i^{''(k)} = +// sum(psi_l^(k) * phi_i^{'(l)}) for all l = 1..L +// + sum(omega_j^(k) * sigma_{-1} * pi_i^{j)) for all j = 1..256 +pub fn compute_aggr_ct_constraint_phi( + phi_constraint_ct: &Vec>>, + pai: &Vec>>, + size_k: Zq, + size_r: Zq, + constraint_num_l: Zq, + deg_bound_d: Zq, + size_n: Zq, + double_lambda: Zq, + psi: &Vec>, + omega: &Vec>, +) -> Vec>> { + let phi_ct_aggr: Vec>> = (0..size_k.value()) + .map(|k| { + (0..size_r.value()) + .map(|i| { + // Part 1: sum(psi_l^(k) * phi_constraint_ct[l][i] for all l) + let part1: Vec = (0..constraint_num_l.value()) + .map(|l| { + let psi = psi[k][l]; + phi_constraint_ct[l][i] + .iter() + .map(|p| p * psi) + .collect::>() + }) + .fold( + vec![ + PolynomialRing { + coefficients: vec![Zq::from(0); deg_bound_d.value()] + }; + size_n.value() + ], + |acc, product| { + acc.iter().zip(product.iter()).map(|(a, b)| a + b).collect() + }, + ); + + // Part 2: sum(omega_j^(k) * sigma_{-1} * pi_i^{j} for all j) + let part2: Vec = (0..double_lambda.value()) + .map(|j| { + let omega = omega[k][j]; + pai[i][j] + .chunks(deg_bound_d.value()) + .take(size_n.value()) + .map(|chunk| { + let pai_poly = PolynomialRing { + coefficients: chunk.to_vec(), + }; + let pai_poly_ca = conjugation_automorphism(&pai_poly); + pai_poly_ca * omega + }) + .collect::>() + }) + .fold( + vec![ + PolynomialRing { + coefficients: vec![Zq::from(0); 1] + }; + size_n.value() + ], + |acc, chunks_ca| { + acc.iter() + .zip(chunks_ca.iter()) + .map(|(a, b)| a + b) + .collect() + }, + ); + + // Sum part1 and part2 element-wise + part1 + .iter() + .zip(part2.iter()) + .map(|(a, b)| a + b) + .collect::>() + }) + .collect::>>() + }) + .collect(); + phi_ct_aggr +} + +// 4.3.3 aggregation: calculate b^{''(k)} = sum(a_ij^{''(k)} * ) + sum() +pub fn compute_aggr_ct_constraint_b( + a_ct_aggr: &Vec>>, + phi_ct_aggr: &Vec>>, + size_k: Zq, + size_r: Zq, + deg_bound_d: Zq, + witness_s: &Vec>, +) -> Vec { + (0..size_k.value()) + .map(|k| { + (0..size_r.value()) + .map(|i| { + (0..size_r.value()) + .map(|j| { + &a_ct_aggr[k][i][j] + * inner_product_polynomial_ring_vector(&witness_s[i], &witness_s[j]) + }) + .fold( + PolynomialRing { + coefficients: vec![Zq::from(0); deg_bound_d.value()], + }, + |acc, x| acc + x, + ) + + inner_product_polynomial_ring_vector(&phi_ct_aggr[k][i], &witness_s[i]) + }) + .fold( + PolynomialRing { + coefficients: vec![Zq::from(0); deg_bound_d.value()], + }, + |acc, x| acc + x, + ) + }) + .collect::>() +} + +// aggregation: a_i = sum(alpha_k * a_ij) + sum(beta_k * a_ij^{''(k)}) +pub fn compute_aggr_constraint_a( + a_constraint: &Vec>>, + a_ct_aggr: &Vec>>, + constraint_num_k: Zq, + alpha: &Vec, + beta: &Vec, + size_r: Zq, + size_k: Zq, +) -> Vec> { + (0..size_r.value()) + .map(|i| { + (0..size_r.value()) + .map(|j| { + // Part 1: sum(alpha_k * a_ij) + let part1: PolynomialRing = (0..constraint_num_k.value()) + .map(|k| &a_constraint[k][i][j] * &alpha[k]) + .fold(zero_poly(), |acc, product| acc + product); + + // Part 2: sum(beta_k * a_ij^{''(k)}) + let part2: PolynomialRing = (0..size_k.value()) + .map(|k| &a_ct_aggr[k][i][j] * &beta[k]) + .fold(zero_poly(), |acc, product| acc + product); + + // Sum part1 and part2 element-wise + part1 + part2 + }) + .collect::>() + }) + .collect::>>() +} + +// aggregation: phi_i = sum(alpha_k * phi_i) + sum(beta_k * phi_i^{''(k)}) +pub fn compute_aggr_constraint_phi( + phi_constraint: &Vec>>, + phi_ct_aggr: &Vec>>, + constraint_num_k: Zq, + alpha: &Vec, + beta: &Vec, + size_r: Zq, + size_n: Zq, + deg_bound_d: Zq, + size_k: Zq, +) -> Vec> { + let phi_aggr: Vec> = (0..size_r.value()) + .map(|i| { + // Part 1: sum(alpha_k * phi_i) + let part1: Vec = (0..constraint_num_k.value()) + .map(|k| { + let alpha = &alpha[k]; + phi_constraint[k][i] + .iter() + .map(|p| p * alpha) + .collect::>() + }) + .fold( + vec![ + PolynomialRing { + coefficients: vec![Zq::from(0); deg_bound_d.value()] + }; + size_n.value() + ], + |acc, product| acc.iter().zip(product.iter()).map(|(a, b)| a + b).collect(), + ); + + // Part 2: sum(beta_k * phi_i^{''(k)}) + let part2: Vec = (0..size_k.value()) + .map(|k| { + let beta = &beta[k]; + phi_ct_aggr[k][i] + .iter() + .map(|p| p * beta) + .collect::>() + }) + .fold( + vec![ + PolynomialRing { + coefficients: vec![Zq::from(0); deg_bound_d.value()] + }; + size_n.value() + ], + |acc, product| acc.iter().zip(product.iter()).map(|(a, b)| a + b).collect(), + ); + // Sum part1 and part2 element-wise + part1 + .iter() + .zip(part2.iter()) + .map(|(a, b)| a + b) + .collect::>() + }) + .collect(); + phi_aggr +} + +// aggregation: b_i = sum(alpha_k * b^(k)) + sum(beta_k * b^{''(k)}) +pub fn compute_aggr_constraint_b( + b_constraint: &Vec, + b_ct_aggr: &Vec, + constraint_num_k: Zq, + alpha: &Vec, + beta: &Vec, + size_k: Zq, +) -> PolynomialRing { + // Part 1: sum(alpha_k * b^(k)) + let part1: PolynomialRing = (0..constraint_num_k.value()) + .map(|k| &b_constraint[k] * &alpha[k]) + .fold(zero_poly(), |acc, product| acc + product); + + // Part 2: sum(beta_k * b^{''(k)}) + let part2: PolynomialRing = (0..size_k.value()) + .map(|k| &b_ct_aggr[k] * &beta[k]) + .fold(zero_poly(), |acc, product| acc + product); + + // Sum part1 and part2 + part1 + part2 +} + +pub fn check_aggr_relation( + a_aggr: &Vec>, + b_aggr: &PolynomialRing, + g: &Vec>, + h: &Vec>, +) { + let size_r = Zq::from(a_aggr.len()); + // 7. check if sum(a_ij * g_ij) + sum(h_ii) -b ?= 0 + // 7.1 calculate sum(a_ij * g_ij) + let sum_a_ij_g_ij = a_aggr + .iter() + .zip(g.iter()) + .map(|(a_i, g_i)| { + a_i.iter() + .zip(g_i.iter()) + .map(|(a_ij, g_ij)| a_ij * g_ij) + .fold(zero_poly(), |acc, val| acc + val) + }) + .fold(zero_poly(), |acc, val| acc + val); + + // 7.2 calculate sum(h_ii) + let sum_h_ii = (0..size_r.value()).fold(zero_poly(), |acc, i| acc + &h[i][i]); + + // 2 times sum + let b_aggr2 = b_aggr * Zq::from(2); + let sum_a_ij_g_ij2 = sum_a_ij_g_ij * Zq::from(2); + + // 7.3 check if sum(a_ij * g_ij) + sum(h_ii) -b ?= 0 + assert_eq!(sum_a_ij_g_ij2 + sum_h_ii, b_aggr2); +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_aggr_relation_full_example() { + let size_r = Zq::new(3); // r: Number of witness elements + let size_n = Zq::new(5); // n + let deg_bound_d = Zq::new(8); // random polynomial degree bound + let lambda = Zq::new(128); + let double_lambda = lambda * Zq::new(2); + let constraint_num_l = Zq::new(5); + let constraint_num_k = Zq::new(5); + let log_q = Zq::new(2); + let mut rng = rand::thread_rng(); + // generate size_r * size_n witness_s + let witness_s: Vec> = (0..size_r.value()) + .map(|_| { + (0..size_n.value()) + .map(|_| generate_random_polynomial_ring(deg_bound_d.value())) + .collect() + }) + .collect(); + + let a_constraint: Vec>> = (0..constraint_num_k.value()) + .map(|_| { + (0..size_r.value()) + .map(|_| { + (0..size_n.value()) + .map(|_| generate_random_polynomial_ring(deg_bound_d.value())) + .collect() + }) + .collect() + }) + .collect(); + let phi_constraint: Vec>> = (0..constraint_num_k.value()) + .map(|_| { + (0..size_r.value()) + .map(|_| { + (0..size_n.value()) + .map(|_| generate_random_polynomial_ring(deg_bound_d.value())) + .collect() + }) + .collect() + }) + .collect(); + + let b_constraint: Vec = (0..constraint_num_k.value()) + .map(|k| calculate_b_constraint(&witness_s, &a_constraint[k], &phi_constraint[k])) + .collect(); + + let a_constraint_ct: Vec>> = (0..constraint_num_l.value()) + .map(|_| { + (0..size_r.value()) + .map(|_| { + (0..size_n.value()) + .map(|_| generate_random_polynomial_ring(deg_bound_d.value())) + .collect() + }) + .collect() + }) + .collect(); + + // Generate random phi^(k)_{i}: k length vector of matrix, matrix length is r x n, each element in matrix is a Zq + let phi_constraint_ct: Vec>> = (0..constraint_num_l.value()) + .map(|_| { + (0..size_r.value()) + .map(|_| { + (0..size_n.value()) + .map(|_| generate_random_polynomial_ring(deg_bound_d.value())) + .collect() + }) + .collect() + }) + .collect(); + + println!("Prover: Do JL projection"); + // 3. GOAL: JL projection + let nd = size_n * deg_bound_d; + // generate gaussian distribution matrices + // there are size_r matrices, each matrix size is 256 * nd + let pai = (0..size_r.value()) + .map(|_| generate_gaussian_distribution(nd)) + .collect::>>>(); + + let size_k = Zq::new(lambda.value() / log_q.value()); + let psi: Vec> = (0..size_k.value()) + .map(|_| { + (0..constraint_num_l.value()) + .map(|_| Zq::new(rng.gen_range(1..10))) + .collect() + }) + .collect(); + assert_eq!(psi.len(), size_k.value()); + assert_eq!(psi[0].len(), constraint_num_l.value()); + + // 4.2 omega^(k) is randomly chosen from Z_q^{256} + // (Both using Guassian Distribution) + let omega: Vec> = (0..size_k.value()) + .map(|_| { + (0..double_lambda.value()) + .map(|_| Zq::new(rng.gen_range(1..10))) + .collect() + }) + .collect(); + assert_eq!(omega.len(), size_k.value()); + assert_eq!(omega[0].len(), double_lambda.value()); + + // 4.3 caculate b^{''(k)} + // 4.3.1 calculate a_ij^{''(k)} = sum(psi_l^(k) * a_ij^{'(l)}) for all l = 1..L + let a_ct_aggr = compute_aggr_ct_constraint_a( + &a_constraint_ct, + &psi, + size_k, + size_r, + constraint_num_l, + deg_bound_d, + ); + assert_eq!(a_ct_aggr.len(), size_k.value()); + assert_eq!(a_ct_aggr[0].len(), size_r.value()); + assert_eq!(a_ct_aggr[0][0].len(), size_r.value()); + // 4.3.2 calculate phi_i^{''(k)} = + // sum(psi_l^(k) * phi_i^{'(l)}) for all l = 1..L + // + sum(omega_j^(k) * sigma_{-1} * pi_i^{j)) for all j = 1..256 + let phi_ct_aggr = compute_aggr_ct_constraint_phi( + &phi_constraint_ct, + &pai, + size_k, + size_r, + constraint_num_l, + deg_bound_d, + size_n, + double_lambda, + &psi, + &omega, + ); + assert_eq!(phi_ct_aggr.len(), size_k.value()); + assert_eq!(phi_ct_aggr[0].len(), size_r.value()); + + // 4.3.3 calculate b^{''(k)} = sum(a_ij^{''(k)} * ) + sum() + let b_ct_aggr = compute_aggr_ct_constraint_b( + &a_ct_aggr, + &phi_ct_aggr, + size_k, + size_r, + deg_bound_d, + &witness_s, + ); + assert_eq!(b_ct_aggr.len(), size_k.value()); + + let alpha: Vec = (0..constraint_num_k.value()) + .map(|_| generate_random_polynomial_ring(deg_bound_d.value())) + .collect(); + let beta: Vec = (0..size_k.value()) + .map(|_| generate_random_polynomial_ring(deg_bound_d.value())) + .collect(); + + let a_aggr = compute_aggr_constraint_a( + &a_constraint, + &a_ct_aggr, + constraint_num_k, + &alpha, + &beta, + size_r, + size_k, + ); + assert_eq!(a_aggr.len(), size_r.value()); + assert_eq!(a_aggr[0].len(), size_r.value()); + + let phi_aggr = compute_aggr_constraint_phi( + &phi_constraint, + &phi_ct_aggr, + constraint_num_k, + &alpha, + &beta, + size_r, + size_n, + deg_bound_d, + size_k, + ); + + let b_aggr = compute_aggr_constraint_b( + &b_constraint, + &b_ct_aggr, + constraint_num_k, + &alpha, + &beta, + size_k, + ); + + // Calculate garbage polynomial g_ij = + let g: Vec> = (0..size_r.value()) + .map(|i| { + (0..size_r.value()) + .map(|j| { + let s_i = &witness_s[i]; + let s_j = &witness_s[j]; + inner_product_polynomial_ring_vector(&s_i, &s_j) + }) + .collect::>() + }) + .collect(); + + let h: Vec> = (0..size_r.value()) + .map(|i| { + (0..size_r.value()) + .map(|j| { + let phi_i = &phi_aggr[i]; + let phi_j = &phi_aggr[j]; + let s_i = &witness_s[i]; + let s_j = &witness_s[j]; + let inner_product_ij = inner_product_polynomial_ring_vector(&phi_i, &s_j) + + inner_product_polynomial_ring_vector(&phi_j, &s_i); + inner_product_ij + }) + .collect::>() + }) + .collect(); + + check_aggr_relation(&a_aggr, &b_aggr, &g, &h); + } +} diff --git a/labrador/src/gadgets/conjugation_automorphism.rs b/labrador/src/gadgets/conjugation_automorphism.rs new file mode 100644 index 0000000..2d24421 --- /dev/null +++ b/labrador/src/gadgets/conjugation_automorphism.rs @@ -0,0 +1,75 @@ +use algebra::{polynomial_ring::PolynomialRing, utils::inner_product_zq_vector, zq::Zq}; + +// Conjugation Automorphism σ_{-1} +// for polynomial ring a = 1+2x+3x^2, since x^64 = -1, apply this method to a, will get 1+2*(Zq.modulus()-1) * x^(64-1) +3*(Zq.modulus()-1) * x^(64-2) +//todo: Aut(Rq) ∼= Z×2d what is this??? +pub fn conjugation_automorphism(poly: &PolynomialRing) -> PolynomialRing { + let modulus_minus_one = Zq::from(Zq::modulus() - 1); + let transformed_coeffs: Vec = (0..PolynomialRing::DEGREE_BOUND) + .map(|i| { + if i < poly.coefficients.len() { + if i == 0 { + poly.coefficients[i] + } else { + poly.coefficients[i] * modulus_minus_one + } + } else { + Zq::from(0) + } + }) + .collect(); + // reverse the coefficients except constant term + let reversed_coefficients = transformed_coeffs + .iter() + .take(1) + .cloned() + .chain(transformed_coeffs.iter().skip(1).rev().cloned()) + .collect::>(); + PolynomialRing { + coefficients: reversed_coefficients, + } +} + +#[cfg(test)] +mod tests { + + use super::*; + #[test] + fn test_conjugation_automorphism() { + // Create example PolynomialRings a and b + let a = PolynomialRing { + coefficients: vec![Zq::from(1), Zq::from(2), Zq::from(3)], + }; + let b = PolynomialRing { + coefficients: vec![Zq::from(4), Zq::from(5), Zq::from(6)], + }; + + // Compute + let inner_ab = inner_product_zq_vector(&a.coefficients, &b.coefficients); + assert_eq!(inner_ab.value(), 32); + // Compute σ_{-1}(a) + let sigma_inv_a = conjugation_automorphism(&a); + // Compute <σ_{-1}(a), b> + let inner_sigma_inv_a_b = &sigma_inv_a * &b; + // = -12x^{65}-28x^{64}-23x^{63}-12x^{62}+6x^{2}+5x+4 + // = 23x^{63}-12x^{62}+6x^{2}+17x+32 (since x^64 = -1) + assert_eq!(inner_sigma_inv_a_b.coefficients.len(), 64); + assert_eq!(inner_sigma_inv_a_b.coefficients[0], Zq::from(32)); + assert_eq!(inner_sigma_inv_a_b.coefficients[1], Zq::from(17)); + assert_eq!(inner_sigma_inv_a_b.coefficients[2], Zq::from(6)); + assert_eq!(inner_sigma_inv_a_b.coefficients[62], Zq::from(Zq::Q - 12)); + assert_eq!(inner_sigma_inv_a_b.coefficients[63], Zq::from(Zq::Q - 23)); + for i in 3..62 { + assert_eq!(inner_sigma_inv_a_b.coefficients[i], Zq::from(0)); + } + + // Get the constant term of <σ_{-1}(a), b> + let ct_inner_sigma_inv_a_b = inner_sigma_inv_a_b.coefficients[0]; + + // Assert that == ct <σ_{-1}(a), b> + assert_eq!( + inner_ab, ct_inner_sigma_inv_a_b, + " should equal the constant term of <σ-1(a), b>" + ); + } +} diff --git a/labrador/src/gadgets/decompose.rs b/labrador/src/gadgets/decompose.rs new file mode 100644 index 0000000..e69de29 diff --git a/labrador/src/gadgets/gaussian_generator.rs b/labrador/src/gadgets/gaussian_generator.rs new file mode 100644 index 0000000..5739fa0 --- /dev/null +++ b/labrador/src/gadgets/gaussian_generator.rs @@ -0,0 +1,25 @@ +use algebra::Zq; +use rand::Rng; + +pub fn generate_gaussian_distribution(nd: Zq) -> Vec> { + let nd_usize: usize = nd.value(); + let modulus: usize = Zq::modulus(); + let mut rng = rand::thread_rng(); + let mut matrix = vec![vec![Zq::from(0); nd_usize]; 256]; // Initialize a 256 x nd matrix + + for row in matrix.iter_mut() { + for cell in row.iter_mut() { + let random_value: f32 = rng.gen(); // Generate a random float between 0 and 1 + *cell = if random_value < 0.25 { + // todo: should we use symmetric distribution from -q/2 to q/2? + Zq::from(modulus - 1) // 1/4 probability + } else if random_value < 0.75 { + Zq::from(0) // 1/2 probability + } else { + Zq::from(1) // 1/4 probability + }; + } + } + + matrix +} diff --git a/labrador/src/gadgets/mod.rs b/labrador/src/gadgets/mod.rs new file mode 100644 index 0000000..17b7b94 --- /dev/null +++ b/labrador/src/gadgets/mod.rs @@ -0,0 +1,4 @@ +pub mod aggregation; +pub mod conjugation_automorphism; +pub mod gaussian_generator; +pub mod norm; diff --git a/labrador/src/gadgets/norm.rs b/labrador/src/gadgets/norm.rs new file mode 100644 index 0000000..e42628c --- /dev/null +++ b/labrador/src/gadgets/norm.rs @@ -0,0 +1,121 @@ +use algebra::{polynomial_ring::PolynomialRing, zq::Zq}; + +// Calculate the sum of squared norms for a single PolynomialRing instance. +pub fn poly_norm_squared(poly: &PolynomialRing) -> Zq { + poly.coefficients + .iter() + .fold(Zq::new(0), |acc, coeff| acc + coeff.pow(2)) +} + +// Calculate the sum of squared norms for a vector of PolynomialRing instances. +pub fn poly_vec_norm_squared(polys: &Vec) -> Zq { + polys + .iter() + .fold(Zq::new(0), |acc, poly| acc + poly_norm_squared(poly)) +} + +// Calculate the sum of squared norms for a matrix of PolynomialRing instances. +pub fn poly_matrix_norm_squared(poly_matrix: &Vec>) -> Zq { + poly_matrix.iter().fold(Zq::new(0), |acc, vector| { + acc + poly_vec_norm_squared(vector) + }) +} + +// Calculate the sum of squared norms for a 3D vector of PolynomialRing instances. +pub fn poly_3d_norm_squared(polymat3d: &Vec>>) -> Zq { + polymat3d.iter().fold(Zq::new(0), |acc, poly_matrix| { + acc + poly_matrix_norm_squared(poly_matrix) + }) +} + +#[cfg(test)] +mod tests { + use super::*; + use std::vec; + + #[test] + fn test_poly_norm_squared() { + let poly = PolynomialRing { + coefficients: vec![Zq::from(1), Zq::from(2), Zq::from(3)], + }; + let expected = Zq::from(14); // 1^2 + 2^2 + 3^2 = 14 + let result = poly_norm_squared(&poly); + assert_eq!( + result, expected, + "poly_norm_squared should return the sum of squared coefficients" + ); + } + + #[test] + fn test_poly_matrix_norm_squared() { + let poly1 = PolynomialRing { + coefficients: vec![Zq::from(1), Zq::from(2), Zq::from(3)], + }; + let poly2 = PolynomialRing { + coefficients: vec![Zq::from(4), Zq::from(5), Zq::from(6)], + }; + let poly_matrix = vec![ + vec![poly1.clone(), poly2.clone()], + vec![poly2.clone(), poly1.clone()], + ]; + // poly_norm_squared(poly1) = 1 + 4 + 9 = 14 + // poly_norm_squared(poly2) = 16 + 25 + 36 = 77 + // Total sum: 14 + 77 + 77 + 14 = 182 + let expected = Zq::from(182); + let result = poly_matrix_norm_squared(&poly_matrix); + assert_eq!(result, expected, "poly_matrix_norm_squared should return the sum of squared norms of all polynomials in the matrix"); + } + + #[test] + fn test_poly_vec_norm_squared() { + // Arrange + let poly1 = PolynomialRing { + coefficients: vec![Zq::from(1), Zq::from(2), Zq::from(3)], + }; + let poly2 = PolynomialRing { + coefficients: vec![Zq::from(4), Zq::from(5), Zq::from(6)], + }; + let vec_polys = vec![poly1.clone(), poly2.clone()]; + + // Act + let result = poly_vec_norm_squared(&vec_polys); + + // Assert + // poly1 norm: 1^2 + 2^2 + 3^2 = 14 + // poly2 norm: 4^2 + 5^2 + 6^2 = 77 + let expected = Zq::from(14) + Zq::from(77); + assert_eq!( + result, expected, + "poly_vec_norm_squared did not return the correct sum of squared norms" + ); + } + + #[test] + fn test_poly_3d_norm_squared() { + // Arrange + let poly1 = PolynomialRing { + coefficients: vec![Zq::from(1), Zq::from(2), Zq::from(3)], + }; + let poly2 = PolynomialRing { + coefficients: vec![Zq::from(4), Zq::from(5), Zq::from(6)], + }; + let poly_matrix = vec![ + vec![poly1.clone(), poly2.clone()], + vec![poly1.clone(), poly2.clone()], + ]; + let polymat3d = vec![poly_matrix.clone(), poly_matrix.clone()]; + + // Act + let result = poly_3d_norm_squared(&polymat3d); + + // Assert + // Each poly_matrix contains two vectors of polynomials, each vector has 2 polynomials with norms 14 and 77 + // Each matrix: 2 vectors * (14 + 77) = 2 * 91 = 182 + // Total: 2 matrices * 182 = 364 + let expected = Zq::from(364); + assert_eq!( + result, expected, + "poly_3d_norm_squared did not return the correct sum of squared norms" + ); + } +} diff --git a/labrador/src/lib.rs b/labrador/src/lib.rs index d82870a..92f1f37 100644 --- a/labrador/src/lib.rs +++ b/labrador/src/lib.rs @@ -1,4 +1,5 @@ -pub mod algebra; +pub mod gadgets; pub mod prover; pub mod setup; +pub mod utils; pub mod verifier; diff --git a/labrador/src/prover.rs b/labrador/src/prover.rs index ff15ba4..929b723 100644 --- a/labrador/src/prover.rs +++ b/labrador/src/prover.rs @@ -1,63 +1,22 @@ -use crate::algebra::{PolynomialRing, RqMatrix, Zq}; +use crate::gadgets::{ + aggregation::check_aggr_relation, conjugation_automorphism::conjugation_automorphism, + gaussian_generator::generate_gaussian_distribution, norm::*, +}; use crate::setup::setup; +use crate::utils::{calculate_outer_comm_u1, calculate_outer_comm_u2}; +use algebra::{ + polynomial_ring::PolynomialRing, + rq_matrix::RqMatrix, + utils::{ + generate_random_polynomial_ring, inner_product_poly_matrix_and_poly_vector, + inner_product_polynomial_ring_vector, inner_product_zq_vector, + matrix_poly_times_poly_vector, zero_poly, + }, + zq::Zq, +}; use profiler_macro::time_profiler; use rand::Rng; -// a: Vec, b: PolynomialRing -// calculate c = a * b, c_i = a_i * b -// c: Vec -fn poly_vec_times_poly(a: &Vec, b: &PolynomialRing) -> Vec { - a.iter().map(|a_i| a_i * b).collect() -} -// a: Vec, b: Vec -// calculate c = a + b, c_i = a_i + b_i -// c: Vec -fn poly_vec_add_poly_vec(a: &Vec, b: &Vec) -> Vec { - a.iter().zip(b.iter()).map(|(a_i, b_i)| a_i + b_i).collect() -} - -// inner product of 2 vectors of PolynomialRing -fn inner_product_polynomial_ring_vector( - a: &[PolynomialRing], - b: &[PolynomialRing], -) -> PolynomialRing { - assert_eq!( - a.len(), - b.len(), - "inner_product_polynomial_ring_vector: a and b must have the same length" - ); - a.iter() - .zip(b.iter()) - .map(|(a, b)| a * b) - .collect::>() - .into_iter() - .reduce(|acc, x| acc + x) - .unwrap() -} - -fn inner_product_zq_vector(a: &Vec, b: &Vec) -> Zq { - a.iter().zip(b.iter()).map(|(a, b)| *a * *b).sum() -} - -// a: Vec>, b: Vec -// calculate c = sum(c_i), c_i = poly_vec_times_poly(a_i, b_i) -// c: Vec -fn inner_product_poly_matrix_and_poly_vector( - poly_matrix: &Vec>, - poly_vector: &Vec, -) -> Vec { - assert_eq!(poly_matrix.len(), poly_vector.len(), "inner_product_poly_matrix_and_poly_vector: poly_matrix and poly_vector must have the same length"); - poly_matrix - .iter() - .zip(poly_vector.iter()) - .map(|(poly_matrix_row, poly_vector_element)| { - poly_vec_times_poly(&poly_matrix_row, &poly_vector_element) - }) - .fold( - vec![zero_poly(); poly_matrix[0].len()], - |acc, x: Vec| poly_vec_add_poly_vec(&acc, &x), - ) -} // Function to calculate b^(k) fn calculate_b_constraint( s: &[Vec], @@ -88,17 +47,6 @@ fn calculate_b_constraint( b } -// calculate matrix times vector of PolynomialRing -fn matrix_poly_times_poly_vector( - poly_matrix: &Vec>, - poly_vec: &Vec, -) -> Vec { - poly_matrix - .iter() - .map(|row| inner_product_polynomial_ring_vector(row, poly_vec)) - .collect::>() -} - // convert number to basis // 42 = 0 * 2^7 + 1 * 2^6 + 0 * 2^5 + 1 * 2^4 + 0 * 2^3 + 1 * 2^2 + 0 * 2^1 + 0 * 2^0 // first digit: 42 / 2 = 21, result_i = 0 @@ -137,68 +85,6 @@ fn ring_polynomial_to_basis(poly: &PolynomialRing, basis: Zq, digits: Zq) -> Vec .collect() } -fn generate_gaussian_distribution(nd: Zq) -> Vec> { - let nd_usize: usize = nd.value(); - let modulus: usize = Zq::modulus(); - let mut rng = rand::thread_rng(); - let mut matrix = vec![vec![Zq::from(0); nd_usize]; 256]; // Initialize a 256 x nd matrix - - for row in matrix.iter_mut() { - for cell in row.iter_mut() { - let random_value: f32 = rng.gen(); // Generate a random float between 0 and 1 - *cell = if random_value < 0.25 { - // todo: should we use symmetric distribution from -q/2 to q/2? - Zq::from(modulus - 1) // 1/4 probability - } else if random_value < 0.75 { - Zq::from(0) // 1/2 probability - } else { - Zq::from(1) // 1/4 probability - }; - } - } - - matrix -} - -// Conjugation Automorphism σ_{-1} -// for polynomial ring a = 1+2x+3x^2, since x^64 = -1, apply this method to a, will get 1+2*(Zq.modulus()-1) * x^(64-1) +3*(Zq.modulus()-1) * x^(64-2) -//todo: Aut(Rq) ∼= Z×2d what is this??? -fn conjugation_automorphism(poly: &PolynomialRing) -> PolynomialRing { - let modulus_minus_one = Zq::from(Zq::modulus() - 1); - let transformed_coeffs: Vec = (0..PolynomialRing::DEGREE_BOUND) - .map(|i| { - if i < poly.coefficients.len() { - if i == 0 { - poly.coefficients[i] - } else { - poly.coefficients[i] * modulus_minus_one - } - } else { - Zq::from(0) - } - }) - .collect(); - // reverse the coefficients except constant term - let reversed_coefficients = transformed_coeffs - .iter() - .take(1) - .cloned() - .chain(transformed_coeffs.iter().skip(1).rev().cloned()) - .collect::>(); - PolynomialRing { - coefficients: reversed_coefficients, - } -} - -fn generate_random_polynomial_ring(deg_bound_d: usize) -> PolynomialRing { - let mut rng = rand::thread_rng(); - PolynomialRing { - coefficients: (0..deg_bound_d) - .map(|_| Zq::from(rng.gen_range(1..5))) - .collect(), - } -} - // aggregate basis form of a vector of PolynomialRing fn aggregate_poly_vec_basis_form(poly_basis_form: &Vec>>) -> Vec> { poly_basis_form @@ -248,49 +134,6 @@ fn poly_vec_decompose_and_aggregate( aggregate_poly_vec_basis_form(&poly_basis_form) } -fn poly_matrix_decompose_and_aggregate( - poly: &Vec>, - basis: Zq, - digits: Zq, -) -> Vec>> { - // Decompose h_ij into basis t_1 parts - let poly_basis_form = poly_matrix_decompose_to_basis(poly, basis, digits); - - // Pick elements at each position across all inner vectors and aggregate them - poly_basis_form - .iter() - .map(aggregate_poly_vec_basis_form) - .collect() -} - -// Calculate the sum of squared norms for a single PolynomialRing instance. -fn poly_norm_squared(poly: &PolynomialRing) -> Zq { - poly.coefficients - .iter() - .fold(Zq::new(0), |acc, coeff| acc + coeff.pow(2)) -} - -// Calculate the sum of squared norms for a vector of PolynomialRing instances. -fn poly_vec_norm_squared(polys: &Vec) -> Zq { - polys - .iter() - .fold(Zq::new(0), |acc, poly| acc + poly_norm_squared(poly)) -} - -// Calculate the sum of squared norms for a matrix of PolynomialRing instances. -fn poly_matrix_norm_squared(poly_matrix: &Vec>) -> Zq { - poly_matrix.iter().fold(Zq::new(0), |acc, vector| { - acc + poly_vec_norm_squared(vector) - }) -} - -// Calculate the sum of squared norms for a 3D vector of PolynomialRing instances. -fn poly_3d_norm_squared(polymat3d: &Vec>>) -> Zq { - polymat3d.iter().fold(Zq::new(0), |acc, poly_matrix| { - acc + poly_matrix_norm_squared(poly_matrix) - }) -} - // statement struct St { a_constraint: Vec>>, @@ -318,438 +161,6 @@ struct Tr { h: Vec>, } -// 4.3.1 aggregation: calculate a_ij^{''(k)} = sum(psi_l^(k) * a_ij^{'(l)}) for all l = 1..L -fn compute_aggr_ct_constraint_a( - a_constraint_ct: &Vec>>, - psi: &Vec>, - size_k: Zq, - size_r: Zq, - constraint_num_l: Zq, - deg_bound_d: Zq, -) -> Vec>> { - let a_ct_aggr: Vec>> = (0..size_k.value()) - .map(|k| { - let psi_k = &psi[k]; - (0..size_r.value()) - .map(|i| { - (0..size_r.value()) - .map(|j| { - (0..constraint_num_l.value()) - .map(|l| &a_constraint_ct[l][i][j] * psi_k[l]) - .fold( - PolynomialRing { - coefficients: vec![Zq::from(0); deg_bound_d.value()], - }, - |acc, x| acc + x, - ) - }) - .collect::>() - }) - .collect::>>() - }) - .collect(); - a_ct_aggr -} - -// 4.3.2 aggregation: calculate phi_i^{''(k)} = -// sum(psi_l^(k) * phi_i^{'(l)}) for all l = 1..L -// + sum(omega_j^(k) * sigma_{-1} * pi_i^{j)) for all j = 1..256 -fn compute_aggr_ct_constraint_phi( - phi_constraint_ct: &Vec>>, - pai: &Vec>>, - size_k: Zq, - size_r: Zq, - constraint_num_l: Zq, - deg_bound_d: Zq, - size_n: Zq, - double_lambda: Zq, - psi: &Vec>, - omega: &Vec>, -) -> Vec>> { - let phi_ct_aggr: Vec>> = (0..size_k.value()) - .map(|k| { - (0..size_r.value()) - .map(|i| { - // Part 1: sum(psi_l^(k) * phi_constraint_ct[l][i] for all l) - let part1: Vec = (0..constraint_num_l.value()) - .map(|l| { - let psi = psi[k][l]; - phi_constraint_ct[l][i] - .iter() - .map(|p| p * psi) - .collect::>() - }) - .fold( - vec![ - PolynomialRing { - coefficients: vec![Zq::from(0); deg_bound_d.value()] - }; - size_n.value() - ], - |acc, product| { - acc.iter().zip(product.iter()).map(|(a, b)| a + b).collect() - }, - ); - - // Part 2: sum(omega_j^(k) * sigma_{-1} * pi_i^{j} for all j) - let part2: Vec = (0..double_lambda.value()) - .map(|j| { - let omega = omega[k][j]; - pai[i][j] - .chunks(deg_bound_d.value()) - .take(size_n.value()) - .map(|chunk| { - let pai_poly = PolynomialRing { - coefficients: chunk.to_vec(), - }; - let pai_poly_ca = conjugation_automorphism(&pai_poly); - pai_poly_ca * omega - }) - .collect::>() - }) - .fold( - vec![ - PolynomialRing { - coefficients: vec![Zq::from(0); 1] - }; - size_n.value() - ], - |acc, chunks_ca| { - acc.iter() - .zip(chunks_ca.iter()) - .map(|(a, b)| a + b) - .collect() - }, - ); - - // Sum part1 and part2 element-wise - part1 - .iter() - .zip(part2.iter()) - .map(|(a, b)| a + b) - .collect::>() - }) - .collect::>>() - }) - .collect(); - phi_ct_aggr -} - -// 4.3.3 aggregation: calculate b^{''(k)} = sum(a_ij^{''(k)} * ) + sum() -fn compute_aggr_ct_constraint_b( - a_ct_aggr: &Vec>>, - phi_ct_aggr: &Vec>>, - size_k: Zq, - size_r: Zq, - deg_bound_d: Zq, - witness_s: &Vec>, -) -> Vec { - (0..size_k.value()) - .map(|k| { - (0..size_r.value()) - .map(|i| { - (0..size_r.value()) - .map(|j| { - &a_ct_aggr[k][i][j] - * inner_product_polynomial_ring_vector(&witness_s[i], &witness_s[j]) - }) - .fold( - PolynomialRing { - coefficients: vec![Zq::from(0); deg_bound_d.value()], - }, - |acc, x| acc + x, - ) - + inner_product_polynomial_ring_vector(&phi_ct_aggr[k][i], &witness_s[i]) - }) - .fold( - PolynomialRing { - coefficients: vec![Zq::from(0); deg_bound_d.value()], - }, - |acc, x| acc + x, - ) - }) - .collect::>() -} - -// aggregation: a_i = sum(alpha_k * a_ij) + sum(beta_k * a_ij^{''(k)}) -fn compute_aggr_constraint_a( - a_constraint: &Vec>>, - a_ct_aggr: &Vec>>, - constraint_num_k: Zq, - alpha: &Vec, - beta: &Vec, - size_r: Zq, - size_k: Zq, -) -> Vec> { - (0..size_r.value()) - .map(|i| { - (0..size_r.value()) - .map(|j| { - // Part 1: sum(alpha_k * a_ij) - let part1: PolynomialRing = (0..constraint_num_k.value()) - .map(|k| &a_constraint[k][i][j] * &alpha[k]) - .fold(zero_poly(), |acc, product| acc + product); - - // Part 2: sum(beta_k * a_ij^{''(k)}) - let part2: PolynomialRing = (0..size_k.value()) - .map(|k| &a_ct_aggr[k][i][j] * &beta[k]) - .fold(zero_poly(), |acc, product| acc + product); - - // Sum part1 and part2 element-wise - part1 + part2 - }) - .collect::>() - }) - .collect::>>() -} - -// aggregation: phi_i = sum(alpha_k * phi_i) + sum(beta_k * phi_i^{''(k)}) -fn compute_aggr_constraint_phi( - phi_constraint: &Vec>>, - phi_ct_aggr: &Vec>>, - constraint_num_k: Zq, - alpha: &Vec, - beta: &Vec, - size_r: Zq, - size_n: Zq, - deg_bound_d: Zq, - size_k: Zq, -) -> Vec> { - let phi_aggr: Vec> = (0..size_r.value()) - .map(|i| { - // Part 1: sum(alpha_k * phi_i) - let part1: Vec = (0..constraint_num_k.value()) - .map(|k| { - let alpha = &alpha[k]; - phi_constraint[k][i] - .iter() - .map(|p| p * alpha) - .collect::>() - }) - .fold( - vec![ - PolynomialRing { - coefficients: vec![Zq::from(0); deg_bound_d.value()] - }; - size_n.value() - ], - |acc, product| acc.iter().zip(product.iter()).map(|(a, b)| a + b).collect(), - ); - - // Part 2: sum(beta_k * phi_i^{''(k)}) - let part2: Vec = (0..size_k.value()) - .map(|k| { - let beta = &beta[k]; - phi_ct_aggr[k][i] - .iter() - .map(|p| p * beta) - .collect::>() - }) - .fold( - vec![ - PolynomialRing { - coefficients: vec![Zq::from(0); deg_bound_d.value()] - }; - size_n.value() - ], - |acc, product| acc.iter().zip(product.iter()).map(|(a, b)| a + b).collect(), - ); - // Sum part1 and part2 element-wise - part1 - .iter() - .zip(part2.iter()) - .map(|(a, b)| a + b) - .collect::>() - }) - .collect(); - phi_aggr -} - -// aggregation: b_i = sum(alpha_k * b^(k)) + sum(beta_k * b^{''(k)}) -fn compute_aggr_constraint_b( - b_constraint: &Vec, - b_ct_aggr: &Vec, - constraint_num_k: Zq, - alpha: &Vec, - beta: &Vec, - size_k: Zq, -) -> PolynomialRing { - // Part 1: sum(alpha_k * b^(k)) - let part1: PolynomialRing = (0..constraint_num_k.value()) - .map(|k| &b_constraint[k] * &alpha[k]) - .fold(zero_poly(), |acc, product| acc + product); - - // Part 2: sum(beta_k * b^{''(k)}) - let part2: PolynomialRing = (0..size_k.value()) - .map(|k| &b_ct_aggr[k] * &beta[k]) - .fold(zero_poly(), |acc, product| acc + product); - - // Sum part1 and part2 - part1 + part2 -} - -fn zero_poly() -> PolynomialRing { - PolynomialRing { - coefficients: vec![Zq::from(0); 1], - } -} - -fn check_aggr_relation( - a_aggr: &Vec>, - b_aggr: &PolynomialRing, - g: &Vec>, - h: &Vec>, -) { - let size_r = Zq::from(a_aggr.len()); - // 7. check if sum(a_ij * g_ij) + sum(h_ii) -b ?= 0 - // 7.1 calculate sum(a_ij * g_ij) - let sum_a_ij_g_ij = a_aggr - .iter() - .zip(g.iter()) - .map(|(a_i, g_i)| { - a_i.iter() - .zip(g_i.iter()) - .map(|(a_ij, g_ij)| a_ij * g_ij) - .fold(zero_poly(), |acc, val| acc + val) - }) - .fold(zero_poly(), |acc, val| acc + val); - - // 7.2 calculate sum(h_ii) - let sum_h_ii = (0..size_r.value()).fold(zero_poly(), |acc, i| acc + &h[i][i]); - - // 2 times sum - let b_aggr2 = b_aggr * Zq::from(2); - let sum_a_ij_g_ij2 = sum_a_ij_g_ij * Zq::from(2); - - // 7.3 check if sum(a_ij * g_ij) + sum(h_ii) -b ?= 0 - assert_eq!(sum_a_ij_g_ij2 + sum_h_ii, b_aggr2); -} - -// 2.3 calculate u1 -// 2.3.1 B & C is randomly chosen similar to A -// 2.3.2 calculate u1 = sum(B_ik * t_i^(k)) + sum(C_ijk * g_ij^(k)) -// B_ik: Rq^{kappa1 x kappa}, t_i: Rq^{kappa}, t_i^(k): Rq^{kappa} -// B_ik * t_i^(k): Rq^{kappa1} -// First summation: ∑ B_ik * t_i^(k), 1 ≤ i ≤ r, 0 ≤ k ≤ t1−1 -// Initialize u1 with zeros with size kappa1, each element is a polynomial ring -fn calculate_outer_comm_u1( - b_matrix: &Vec>, - c_matrix: &Vec>>, - g_matrix_aggregated: &Vec>>, - all_t_i_basis_form_aggregated: &Vec>>, - kappa1: Zq, - t1: Zq, - t2: Zq, - size_r: Zq, - size_n: Zq, -) -> Vec { - let mut u1 = vec![ - PolynomialRing { - coefficients: vec![Zq::from(0); size_n.value()] - }; - kappa1.value() - ]; - // Calculate u1 using the pre-generated b_matrix - for i in 0..size_r.value() { - for k in 0..t1.value() { - let b_i_k = &b_matrix[i][k]; - let t_i_k = &all_t_i_basis_form_aggregated[i][k]; - // matrix * vector -> vector - let b_ik_times_t_ik = b_i_k - .values - .iter() - .map(|row| { - row.iter().zip(t_i_k.iter()).map(|(b, t)| b * t).fold( - PolynomialRing { - coefficients: vec![Zq::from(0); size_n.value()], - }, - |acc, val| acc + val, - ) - }) - .collect::>(); - u1 = u1 - .iter() - .zip(b_ik_times_t_ik.iter()) - .map(|(a, b)| a + b) - .collect(); - } - } - - // Second summation: ∑ C_ijk * g_ij^(k) - // Calculate u1 using the pre-generated c_matrix - for i in 0..size_r.value() { - for j in i..size_r.value() { - for k in 0..t2.value() { - let c_i_j_k = &c_matrix[i][j][k]; - let g_i_j = &g_matrix_aggregated[i][j]; - let c_i_j_k_times_g_i_j = c_i_j_k - .values - .iter() - .map(|row| { - row.iter().zip(g_i_j.iter()).map(|(c, g)| c * g).fold( - PolynomialRing { - coefficients: vec![Zq::from(0); size_n.value()], - }, - |acc, val| acc + val, - ) - }) - .collect::>(); - u1 = u1 - .iter() - .zip(c_i_j_k_times_g_i_j.iter()) - .map(|(a, b)| a + b) - .collect(); - } - } - } - - u1 -} - -// calculate u2 = sum D_ij * h_ij^(k) for all k = 1..(t1-1) -fn calculate_outer_comm_u2( - d_matrix: &Vec>>, - h_gar_poly_basis_form_aggregated: &Vec>>, - t2: Zq, - kappa2: Zq, - size_r: Zq, - size_n: Zq, - deg_bound_d: Zq, -) -> Vec { - (0..size_r.value()) - .flat_map(|i| { - (i..size_r.value()).flat_map(move |j| (0..t2.value()).map(move |k| (i, j, k))) - }) - .fold( - vec![ - PolynomialRing { - coefficients: vec![Zq::from(0); deg_bound_d.value()] - }; - kappa2.value() - ], - |acc, (i, j, k)| { - let d_i_j_k = &d_matrix[i][j][k]; - let h_i_j = &h_gar_poly_basis_form_aggregated[i][j]; - let d_i_j_k_times_h_i_j = d_i_j_k - .values - .iter() - .map(|row| { - row.iter().zip(h_i_j.iter()).map(|(c, h)| c * h).fold( - PolynomialRing { - coefficients: vec![Zq::from(0); size_n.value()], - }, - |acc, val| acc + val, - ) - }) - .collect::>(); - acc.iter() - .zip(d_i_j_k_times_h_i_j.iter()) - .map(|(a, b)| a + b) - .collect() - }, - ) -} - #[time_profiler()] pub fn prove( a_matrix: &RqMatrix, @@ -1232,252 +643,24 @@ pub fn prove( a_constraint_ct, phi_constraint_ct, b_constraint_ct, - }; - let tr = Tr { - u1, - pai, - p, - psi, - omega, - b_ct_aggr, - alpha, - beta, - u2, - c, - z, - t, - g, - h, - }; - return (st, tr); -} - -fn verify( - st: St, - tr: Tr, - a_matrix: &RqMatrix, - b_matrix: &Vec>, - c_matrix: &Vec>>, - d_matrix: &Vec>>, -) { - // same parameters as in the prover - let size_r = Zq::new(3); // r: Number of witness elements - let size_n = Zq::new(5); // n - let basis = Zq::new(10); - let digits = Zq::new(3); // t1 - let t1 = digits; - let t2 = digits; - let kappa = Zq::new(3); // Example size - let kappa1 = Zq::from(5); - let kappa2 = Zq::from(5); - let lambda = Zq::new(128); - let double_lambda = lambda * Zq::new(2); - let log_q = Zq::new(32); - let deg_bound_d = Zq::new(8); // random polynomial degree bound - let new_beta = Zq::new(250); // Example value for beta - - let St { - a_constraint, - phi_constraint, - b_constraint, - a_constraint_ct, - phi_constraint_ct, - b_constraint_ct, - } = st; - - let Tr { - u1, - pai, - p, - psi, - omega, - b_ct_aggr, - alpha, - beta, - u2, - c, - z, - t, - g, - h, - } = tr; - let size_r = Zq::from(g.len()); - // 1. check g_ij ?= g_ji - for i in 0..size_r.value() { - for j in (i + 1)..size_r.value() { - assert_eq!( - g[i][j], g[j][i], - "g_ij is not equal to g_ji at indices ({}, {})", - i, j - ); - } - } - // 2. check h_ij ?= h_ji - for i in 0..size_r.value() { - for j in (i + 1)..size_r.value() { - assert_eq!( - h[i][j], h[j][i], - "h_ij is not equal to h_ji at indices ({}, {})", - i, j - ); - } - } - // 3. check if norm sum of z, t, g, h <= beta'^2 - // 3.1 decompose z, t, g, h to basis form - let z_basis_form = poly_vec_decompose_and_aggregate(&z, basis, digits); - let all_t_i_basis_form_aggregated = poly_matrix_decompose_and_aggregate(&t, basis, digits); - let g_matrix_aggregated = poly_matrix_decompose_and_aggregate(&g, basis, t2); - let h_gar_poly_basis_form_aggregated = poly_matrix_decompose_and_aggregate(&h, basis, digits); - let norm_z = poly_matrix_norm_squared(&z_basis_form); - let norm_t = poly_3d_norm_squared(&all_t_i_basis_form_aggregated); - let norm_g = poly_3d_norm_squared(&g_matrix_aggregated); - let norm_h = poly_3d_norm_squared(&h_gar_poly_basis_form_aggregated); - let norm_sum = norm_z + norm_t + norm_g + norm_h; - println!("Verifier: Check norms of decomposed inner commitments"); - assert!(norm_sum <= new_beta.pow(2)); - - println!("Verifier: Check amortized opening of inner commitments"); - // 4. check if Az is valid - let a_times_z: Vec = matrix_poly_times_poly_vector(&a_matrix.values, &z); - // calculate sum(ci * ti) - let sum_c_times_t: Vec = inner_product_poly_matrix_and_poly_vector(&t, &c); - assert_eq!(a_times_z, sum_c_times_t); - - println!("Verifier: Check aggregated innerproduct constraints"); - // 5. check if ?= sum(g_ij * c_i * c_j) - let z_z_inner_product = inner_product_polynomial_ring_vector(&z, &z); - - let mut sum_g_ij_c_i_c_j = zero_poly(); - for i in 0..size_r.value() { - for j in 0..size_r.value() { - let g_ij = &g[i][j]; // Borrow g[i][j] instead of moving it - let c_i = &c[i]; - let c_j = &c[j]; - sum_g_ij_c_i_c_j = sum_g_ij_c_i_c_j + (g_ij * c_i * c_j); - } - } - - assert_eq!(z_z_inner_product, sum_g_ij_c_i_c_j); - - println!("Verifier: Check aggregated linear constraints"); - // 6. check if sum( * c_i) ?= sum(h_ij * c_i * c_j) - // aggregation parameters - let size_k = Zq::new(lambda.value() / log_q.value()); - let constraint_num_l = Zq::new(5); // Define L - let constraint_num_k = Zq::new(5); - - // 6.1 caculate b^{''(k)} - // 6.1.1 calculate a_ij^{''(k)} = sum(psi_l^(k) * a_ij^{'(l)}) for all l = 1..L - let a_ct_aggr = compute_aggr_ct_constraint_a( - &a_constraint_ct, - &psi, - size_k, - size_r, - constraint_num_l, - deg_bound_d, - ); - assert_eq!(a_ct_aggr.len(), size_k.value()); - assert_eq!(a_ct_aggr[0].len(), size_r.value()); - assert_eq!(a_ct_aggr[0][0].len(), size_r.value()); - // 6.1.2 calculate phi_i^{''(k)} = - // sum(psi_l^(k) * phi_i^{'(l)}) for all l = 1..L - // + sum(omega_j^(k) * sigma_{-1} * pi_i^{j)) for all j = 1..256 - let phi_ct_aggr = compute_aggr_ct_constraint_phi( - &phi_constraint_ct, - &pai, - size_k, - size_r, - constraint_num_l, - deg_bound_d, - size_n, - double_lambda, - &psi, - &omega, - ); - assert_eq!(phi_ct_aggr.len(), size_k.value()); - assert_eq!(phi_ct_aggr[0].len(), size_r.value()); - - // b_ct_aggr does not need to be calculated here, it's from prover - assert_eq!(b_ct_aggr.len(), size_k.value()); - - let a_aggr = compute_aggr_constraint_a( - &a_constraint, - &a_ct_aggr, - constraint_num_k, - &alpha, - &beta, - size_r, - size_k, - ); - assert_eq!(a_aggr.len(), size_r.value()); - assert_eq!(a_aggr[0].len(), size_r.value()); - - let phi_aggr = compute_aggr_constraint_phi( - &phi_constraint, - &phi_ct_aggr, - constraint_num_k, - &alpha, - &beta, - size_r, - size_n, - deg_bound_d, - size_k, - ); - - let b_aggr = compute_aggr_constraint_b( - &b_constraint, - &b_ct_aggr, - constraint_num_k, - &alpha, - &beta, - size_k, - ); - - // check if sum( * c_i) ?= sum(h_ij * c_i * c_j) - // calculate sum( * c_i) - let sum_phi_i_z_c_i = phi_aggr - .iter() - .zip(c.iter()) - .map(|(phi_i, c_i)| inner_product_polynomial_ring_vector(&phi_i, &z) * c_i) - .fold(zero_poly(), |acc, val| acc + val); - // calculate sum(h_ij * c_i * c_j) - let mut sum_h_ij_c_i_c_j = zero_poly(); - for i in 0..size_r.value() { - for j in 0..size_r.value() { - sum_h_ij_c_i_c_j = sum_h_ij_c_i_c_j + (&h[i][j] * &c[i] * &c[j]); - } - } - assert_eq!(sum_phi_i_z_c_i * Zq::from(2), sum_h_ij_c_i_c_j); - - println!("Verifier: Compute aggregated relation"); - // 7. check if sum(a_ij * g_ij) + sum(h_ii) -b ?= 0 - check_aggr_relation(&a_aggr, &b_aggr, &g, &h); - - println!("Verifier: Check opening of outer commitments(todo)"); - // 8. check if u1 is valid - let u1_check = calculate_outer_comm_u1( - &b_matrix, - &c_matrix, - &g_matrix_aggregated, - &all_t_i_basis_form_aggregated, - kappa1, - t1, - t2, - size_r, - size_n, - ); - assert_eq!(u1, u1_check); - // 9. check if u2 is valid - let u2_check = calculate_outer_comm_u2( - &d_matrix, - &h_gar_poly_basis_form_aggregated, - t2, - kappa2, - size_r, - size_n, - deg_bound_d, - ); - assert_eq!(u2, u2_check); + }; + let tr = Tr { + u1, + pai, + p, + psi, + omega, + b_ct_aggr, + alpha, + beta, + u2, + c, + z, + t, + g, + h, + }; + return (st, tr); } #[cfg(test)] @@ -1568,224 +751,6 @@ mod tests { assert_eq!(sum_phi_i_z_c_i * Zq::from(2), sum_h_ij_c_i_c_j); } - #[test] - fn test_aggr_relation_full_example() { - let size_r = Zq::new(3); // r: Number of witness elements - let size_n = Zq::new(5); // n - let deg_bound_d = Zq::new(8); // random polynomial degree bound - let lambda = Zq::new(128); - let double_lambda = lambda * Zq::new(2); - let constraint_num_l = Zq::new(5); - let constraint_num_k = Zq::new(5); - let log_q = Zq::new(2); - let mut rng = rand::thread_rng(); - // generate size_r * size_n witness_s - let witness_s: Vec> = (0..size_r.value()) - .map(|_| { - (0..size_n.value()) - .map(|_| generate_random_polynomial_ring(deg_bound_d.value())) - .collect() - }) - .collect(); - - let a_constraint: Vec>> = (0..constraint_num_k.value()) - .map(|_| { - (0..size_r.value()) - .map(|_| { - (0..size_n.value()) - .map(|_| generate_random_polynomial_ring(deg_bound_d.value())) - .collect() - }) - .collect() - }) - .collect(); - let phi_constraint: Vec>> = (0..constraint_num_k.value()) - .map(|_| { - (0..size_r.value()) - .map(|_| { - (0..size_n.value()) - .map(|_| generate_random_polynomial_ring(deg_bound_d.value())) - .collect() - }) - .collect() - }) - .collect(); - - let b_constraint: Vec = (0..constraint_num_k.value()) - .map(|k| calculate_b_constraint(&witness_s, &a_constraint[k], &phi_constraint[k])) - .collect(); - - let a_constraint_ct: Vec>> = (0..constraint_num_l.value()) - .map(|_| { - (0..size_r.value()) - .map(|_| { - (0..size_n.value()) - .map(|_| generate_random_polynomial_ring(deg_bound_d.value())) - .collect() - }) - .collect() - }) - .collect(); - - // Generate random phi^(k)_{i}: k length vector of matrix, matrix length is r x n, each element in matrix is a Zq - let phi_constraint_ct: Vec>> = (0..constraint_num_l.value()) - .map(|_| { - (0..size_r.value()) - .map(|_| { - (0..size_n.value()) - .map(|_| generate_random_polynomial_ring(deg_bound_d.value())) - .collect() - }) - .collect() - }) - .collect(); - - println!("Prover: Do JL projection"); - // 3. GOAL: JL projection - let nd = size_n * deg_bound_d; - // generate gaussian distribution matrices - // there are size_r matrices, each matrix size is 256 * nd - let pai = (0..size_r.value()) - .map(|_| generate_gaussian_distribution(nd)) - .collect::>>>(); - - let size_k = Zq::new(lambda.value() / log_q.value()); - let psi: Vec> = (0..size_k.value()) - .map(|_| { - (0..constraint_num_l.value()) - .map(|_| Zq::new(rng.gen_range(1..10))) - .collect() - }) - .collect(); - assert_eq!(psi.len(), size_k.value()); - assert_eq!(psi[0].len(), constraint_num_l.value()); - - // 4.2 omega^(k) is randomly chosen from Z_q^{256} - // (Both using Guassian Distribution) - let omega: Vec> = (0..size_k.value()) - .map(|_| { - (0..double_lambda.value()) - .map(|_| Zq::new(rng.gen_range(1..10))) - .collect() - }) - .collect(); - assert_eq!(omega.len(), size_k.value()); - assert_eq!(omega[0].len(), double_lambda.value()); - - // 4.3 caculate b^{''(k)} - // 4.3.1 calculate a_ij^{''(k)} = sum(psi_l^(k) * a_ij^{'(l)}) for all l = 1..L - let a_ct_aggr = compute_aggr_ct_constraint_a( - &a_constraint_ct, - &psi, - size_k, - size_r, - constraint_num_l, - deg_bound_d, - ); - assert_eq!(a_ct_aggr.len(), size_k.value()); - assert_eq!(a_ct_aggr[0].len(), size_r.value()); - assert_eq!(a_ct_aggr[0][0].len(), size_r.value()); - // 4.3.2 calculate phi_i^{''(k)} = - // sum(psi_l^(k) * phi_i^{'(l)}) for all l = 1..L - // + sum(omega_j^(k) * sigma_{-1} * pi_i^{j)) for all j = 1..256 - let phi_ct_aggr = compute_aggr_ct_constraint_phi( - &phi_constraint_ct, - &pai, - size_k, - size_r, - constraint_num_l, - deg_bound_d, - size_n, - double_lambda, - &psi, - &omega, - ); - assert_eq!(phi_ct_aggr.len(), size_k.value()); - assert_eq!(phi_ct_aggr[0].len(), size_r.value()); - - // 4.3.3 calculate b^{''(k)} = sum(a_ij^{''(k)} * ) + sum() - let b_ct_aggr = compute_aggr_ct_constraint_b( - &a_ct_aggr, - &phi_ct_aggr, - size_k, - size_r, - deg_bound_d, - &witness_s, - ); - assert_eq!(b_ct_aggr.len(), size_k.value()); - - let alpha: Vec = (0..constraint_num_k.value()) - .map(|_| generate_random_polynomial_ring(deg_bound_d.value())) - .collect(); - let beta: Vec = (0..size_k.value()) - .map(|_| generate_random_polynomial_ring(deg_bound_d.value())) - .collect(); - - let a_aggr = compute_aggr_constraint_a( - &a_constraint, - &a_ct_aggr, - constraint_num_k, - &alpha, - &beta, - size_r, - size_k, - ); - assert_eq!(a_aggr.len(), size_r.value()); - assert_eq!(a_aggr[0].len(), size_r.value()); - - let phi_aggr = compute_aggr_constraint_phi( - &phi_constraint, - &phi_ct_aggr, - constraint_num_k, - &alpha, - &beta, - size_r, - size_n, - deg_bound_d, - size_k, - ); - - let b_aggr = compute_aggr_constraint_b( - &b_constraint, - &b_ct_aggr, - constraint_num_k, - &alpha, - &beta, - size_k, - ); - - // Calculate garbage polynomial g_ij = - let g: Vec> = (0..size_r.value()) - .map(|i| { - (0..size_r.value()) - .map(|j| { - let s_i = &witness_s[i]; - let s_j = &witness_s[j]; - inner_product_polynomial_ring_vector(&s_i, &s_j) - }) - .collect::>() - }) - .collect(); - - let h: Vec> = (0..size_r.value()) - .map(|i| { - (0..size_r.value()) - .map(|j| { - let phi_i = &phi_aggr[i]; - let phi_j = &phi_aggr[j]; - let s_i = &witness_s[i]; - let s_j = &witness_s[j]; - let inner_product_ij = inner_product_polynomial_ring_vector(&phi_i, &s_j) - + inner_product_polynomial_ring_vector(&phi_j, &s_i); - inner_product_ij - }) - .collect::>() - }) - .collect(); - - check_aggr_relation(&a_aggr, &b_aggr, &g, &h); - } - #[test] fn test_aggr_relation() { let size_r = Zq::new(3); // r: Number of witness elements @@ -1980,84 +945,6 @@ mod tests { assert_eq!(z_z_inner_product, sum_g_ij_c_i_c_j); } - #[test] - fn test_poly_vec_times_poly() { - // Arrange - let a = vec![ - PolynomialRing { - coefficients: vec![Zq::from(1), Zq::from(2), Zq::from(3)], - }, - PolynomialRing { - coefficients: vec![Zq::from(4), Zq::from(5), Zq::from(6)], - }, - ]; - let b = PolynomialRing { - coefficients: vec![Zq::from(2), Zq::from(3), Zq::from(4)], - }; - - // Act - let result = poly_vec_times_poly(&a, &b); - // expected[0] = a[0] * b = (1 + 2x + 3x^2) * (2 + 3x + 4x^2) = 2 + 7x + 16x^2 + 17x^3 + 12x^4 - // expected[1] = a[1] * b = (4 + 5x + 6x^2) * (2 + 3x + 4x^2) = 8 + 22x + 43x^2 + 38x^3 + 24x^4 - // Assert - let expected = vec![ - PolynomialRing { - coefficients: vec![ - Zq::from(2), - Zq::from(7), - Zq::from(16), - Zq::from(17), - Zq::from(12), - ], - }, - PolynomialRing { - coefficients: vec![ - Zq::from(8), - Zq::from(22), - Zq::from(43), - Zq::from(38), - Zq::from(24), - ], - }, - ]; - assert_eq!(result, expected); - } - - #[test] - fn test_poly_vec_add_poly_vec() { - // Arrange - let a = vec![ - PolynomialRing { - coefficients: vec![Zq::from(1), Zq::from(2), Zq::from(3)], - }, - PolynomialRing { - coefficients: vec![Zq::from(4), Zq::from(5), Zq::from(6)], - }, - ]; - let b = vec![ - PolynomialRing { - coefficients: vec![Zq::from(7), Zq::from(8), Zq::from(9)], - }, - PolynomialRing { - coefficients: vec![Zq::from(10), Zq::from(11), Zq::from(12)], - }, - ]; - - // Act - let result = poly_vec_add_poly_vec(&a, &b); - - // Assert - let expected = vec![ - PolynomialRing { - coefficients: vec![Zq::from(8), Zq::from(10), Zq::from(12)], - }, - PolynomialRing { - coefficients: vec![Zq::from(14), Zq::from(16), Zq::from(18)], - }, - ]; - assert_eq!(result, expected); - } - #[test] fn test_calculate_b_k() { let r = 3; @@ -2272,114 +1159,6 @@ mod tests { assert_eq!(result, expected_result); } - #[test] - fn test_inner_product_polynomial_ring() { - let a = vec![ - PolynomialRing { - coefficients: vec![Zq::from(1), Zq::from(2), Zq::from(3)], - }, - PolynomialRing { - coefficients: vec![Zq::from(4), Zq::from(5), Zq::from(6)], - }, - ]; - let b = vec![ - PolynomialRing { - coefficients: vec![Zq::from(7), Zq::from(8), Zq::from(9)], - }, - PolynomialRing { - coefficients: vec![Zq::from(10), Zq::from(11), Zq::from(12)], - }, - ]; - - let result = inner_product_polynomial_ring_vector(&a, &b); - - // Expected result calculation: - // (1 + 2x + 3x^2) * (7 + 8x + 9x^2) = 7 + 22x + 46x^2 + 42x^3 + 27x^4 - // (4 + 5x + 6x^2) * (10 + 11x + 12x^2) = 40 + 96x + 163x^2 + 126x^3 + 72x^4 - // Sum: 47 + 116x + 209x^2 + 168x^3 + 99x^4 - - let expected = PolynomialRing { - coefficients: vec![ - Zq::from(47), - Zq::from(116), - Zq::from(209), - Zq::from(168), - Zq::from(99), - ], - }; - - assert_eq!(result.coefficients, expected.coefficients); - } - - #[test] - fn test_inner_product_zq_vector() { - // Arrange - let a = vec![Zq::from(1), Zq::from(2), Zq::from(3)]; - let b = vec![Zq::from(4), Zq::from(5), Zq::from(6)]; - - // Act - let result = inner_product_zq_vector(&a, &b); - - // Assert - let expected = - (Zq::from(1) * Zq::from(4)) + (Zq::from(2) * Zq::from(5)) + (Zq::from(3) * Zq::from(6)); - assert_eq!( - result, expected, - "inner_product_zq_vector did not return the correct result" - ); - } - - #[test] - fn test_inner_product_poly_matrix_and_poly_vector() { - // Arrange - let poly_matrix = vec![ - vec![ - PolynomialRing { - coefficients: vec![Zq::from(1), Zq::from(2)], - }, - PolynomialRing { - coefficients: vec![Zq::from(3), Zq::from(4)], - }, - ], - vec![ - PolynomialRing { - coefficients: vec![Zq::from(5), Zq::from(6)], - }, - PolynomialRing { - coefficients: vec![Zq::from(7), Zq::from(8)], - }, - ], - ]; - let poly_vector = vec![ - PolynomialRing { - coefficients: vec![Zq::from(9), Zq::from(10)], - }, - PolynomialRing { - coefficients: vec![Zq::from(11), Zq::from(12)], - }, - ]; - - // Expected Calculation: - // u = sum D_ij * h_ij^(k) for all k = 1..(t1-1) - // For this test case: - // Result[0] = (1+2x) * (9+10x) + (5+6x) * (11+12x) = 64 + 154x + 92x^2 - // Result[1] = (3+4x) * (9+10x) + (7+8x) * (11+12x) = 104 + 238x + 136x^2 - let expected = vec![ - PolynomialRing { - coefficients: vec![Zq::from(64), Zq::from(154), Zq::from(92)], - }, - PolynomialRing { - coefficients: vec![Zq::from(104), Zq::from(238), Zq::from(136)], - }, - ]; - - // Act - let result = inner_product_poly_matrix_and_poly_vector(&poly_matrix, &poly_vector); - - // Assert - assert_eq!(result, expected, "The inner product of the polynomial matrix and vector did not produce the expected result."); - } - #[test] fn test_generate_gaussian_distribution() { let nd = Zq::from(10); @@ -2416,45 +1195,6 @@ mod tests { ); } - #[test] - fn test_conjugation_automorphism() { - // Create example PolynomialRings a and b - let a = PolynomialRing { - coefficients: vec![Zq::from(1), Zq::from(2), Zq::from(3)], - }; - let b = PolynomialRing { - coefficients: vec![Zq::from(4), Zq::from(5), Zq::from(6)], - }; - - // Compute - let inner_ab = inner_product_zq_vector(&a.coefficients, &b.coefficients); - assert_eq!(inner_ab.value(), 32); - // Compute σ_{-1}(a) - let sigma_inv_a = conjugation_automorphism(&a); - // Compute <σ_{-1}(a), b> - let inner_sigma_inv_a_b = &sigma_inv_a * &b; - // = -12x^{65}-28x^{64}-23x^{63}-12x^{62}+6x^{2}+5x+4 - // = 23x^{63}-12x^{62}+6x^{2}+17x+32 (since x^64 = -1) - assert_eq!(inner_sigma_inv_a_b.coefficients.len(), 64); - assert_eq!(inner_sigma_inv_a_b.coefficients[0], Zq::from(32)); - assert_eq!(inner_sigma_inv_a_b.coefficients[1], Zq::from(17)); - assert_eq!(inner_sigma_inv_a_b.coefficients[2], Zq::from(6)); - assert_eq!(inner_sigma_inv_a_b.coefficients[62], Zq::from(Zq::Q - 12)); - assert_eq!(inner_sigma_inv_a_b.coefficients[63], Zq::from(Zq::Q - 23)); - for i in 3..62 { - assert_eq!(inner_sigma_inv_a_b.coefficients[i], Zq::from(0)); - } - - // Get the constant term of <σ_{-1}(a), b> - let ct_inner_sigma_inv_a_b = inner_sigma_inv_a_b.coefficients[0]; - - // Assert that == ct <σ_{-1}(a), b> - assert_eq!( - inner_ab, ct_inner_sigma_inv_a_b, - " should equal the constant term of <σ-1(a), b>" - ); - } - #[test] fn test_decompose_poly_to_basis_form() { // Arrange: Create sample input polynomial rings @@ -2640,40 +1380,4 @@ mod tests { "poly_3d_norm_squared did not return the correct sum of squared norms" ); } - - #[test] - fn test_inner_product_polynomial_ring_vector() { - // Define sample PolynomialRing vectors - let a = vec![ - PolynomialRing { - coefficients: vec![Zq::from(1), Zq::from(2), Zq::from(3)], - }, - PolynomialRing { - coefficients: vec![Zq::from(4), Zq::from(5), Zq::from(6)], - }, - ]; - let b = vec![ - PolynomialRing { - coefficients: vec![Zq::from(7), Zq::from(8), Zq::from(9)], - }, - PolynomialRing { - coefficients: vec![Zq::from(10), Zq::from(11), Zq::from(12)], - }, - ]; - // (1 + 2x + 3x^2) * (7 + 8x + 9x^2) + (4 + 5x + 6x^2) * (10 + 11x + 12x^2) - // = (7 + 22x + 46x^2 + 42x^3 + 27x^4) + (40 + 94x + 163x^2 + 126x^3 + 72x^4) - // = 47 + 116x + 209x^2 + 168x^3 + 99x^4 - let result = inner_product_polynomial_ring_vector(&a, &b); - let expected = PolynomialRing { - coefficients: vec![ - Zq::from(47), // 47 - Zq::from(116), // 116 - Zq::from(209), // 209 - Zq::from(168), // 168 - Zq::from(99), // 99 - ], - }; - - assert_eq!(result, expected); - } } diff --git a/labrador/src/setup.rs b/labrador/src/setup.rs index 8a30db2..b9b5409 100644 --- a/labrador/src/setup.rs +++ b/labrador/src/setup.rs @@ -1,5 +1,4 @@ -use crate::algebra::RqMatrix; -use crate::algebra::Zq; +use algebra::{rq_matrix::RqMatrix, zq::Zq}; type RqMatrix2D = Vec>; type RqMatrix3D = Vec>>; diff --git a/labrador/src/utils.rs b/labrador/src/utils.rs new file mode 100644 index 0000000..901bed6 --- /dev/null +++ b/labrador/src/utils.rs @@ -0,0 +1,140 @@ +use algebra::{PolynomialRing, RqMatrix, Zq}; + +// 2.3 calculate u1 +// 2.3.1 B & C is randomly chosen similar to A +// 2.3.2 calculate u1 = sum(B_ik * t_i^(k)) + sum(C_ijk * g_ij^(k)) +// B_ik: Rq^{kappa1 x kappa}, t_i: Rq^{kappa}, t_i^(k): Rq^{kappa} +// B_ik * t_i^(k): Rq^{kappa1} +// First summation: ∑ B_ik * t_i^(k), 1 ≤ i ≤ r, 0 ≤ k ≤ t1−1 +// Initialize u1 with zeros with size kappa1, each element is a polynomial ring +pub fn calculate_outer_comm_u1( + b_matrix: &Vec>, + c_matrix: &Vec>>, + g_matrix_aggregated: &Vec>>, + all_t_i_basis_form_aggregated: &Vec>>, + kappa1: Zq, + t1: Zq, + t2: Zq, + size_r: Zq, + size_n: Zq, +) -> Vec { + let mut u1 = vec![ + PolynomialRing { + coefficients: vec![Zq::from(0); size_n.value()] + }; + kappa1.value() + ]; + // Calculate u1 using the pre-generated b_matrix + for i in 0..size_r.value() { + for k in 0..t1.value() { + let b_i_k = &b_matrix[i][k]; + let t_i_k = &all_t_i_basis_form_aggregated[i][k]; + // matrix * vector -> vector + let b_ik_times_t_ik = b_i_k + .values + .iter() + .map(|row| { + row.iter().zip(t_i_k.iter()).map(|(b, t)| b * t).fold( + PolynomialRing { + coefficients: vec![Zq::from(0); size_n.value()], + }, + |acc, val| acc + val, + ) + }) + .collect::>(); + u1 = u1 + .iter() + .zip(b_ik_times_t_ik.iter()) + .map(|(a, b)| a + b) + .collect(); + } + } + + // Second summation: ∑ C_ijk * g_ij^(k) + // Calculate u1 using the pre-generated c_matrix + for i in 0..size_r.value() { + for j in i..size_r.value() { + for k in 0..t2.value() { + let c_i_j_k = &c_matrix[i][j][k]; + let g_i_j = &g_matrix_aggregated[i][j]; + let c_i_j_k_times_g_i_j = c_i_j_k + .values + .iter() + .map(|row| { + row.iter().zip(g_i_j.iter()).map(|(c, g)| c * g).fold( + PolynomialRing { + coefficients: vec![Zq::from(0); size_n.value()], + }, + |acc, val| acc + val, + ) + }) + .collect::>(); + u1 = u1 + .iter() + .zip(c_i_j_k_times_g_i_j.iter()) + .map(|(a, b)| a + b) + .collect(); + } + } + } + + u1 +} + +pub fn calculate_outer_comm_u2( + d_matrix: &Vec>>, + h_gar_poly_basis_form_aggregated: &Vec>>, + t2: Zq, + kappa2: Zq, + size_r: Zq, + size_n: Zq, + deg_bound_d: Zq, +) -> Vec { + (0..size_r.value()) + .flat_map(|i| { + (i..size_r.value()).flat_map(move |j| (0..t2.value()).map(move |k| (i, j, k))) + }) + .fold( + vec![ + PolynomialRing { + coefficients: vec![Zq::from(0); deg_bound_d.value()] + }; + kappa2.value() + ], + |acc, (i, j, k)| { + let d_i_j_k = &d_matrix[i][j][k]; + let h_i_j = &h_gar_poly_basis_form_aggregated[i][j]; + let d_i_j_k_times_h_i_j = d_i_j_k + .values + .iter() + .map(|row| { + row.iter().zip(h_i_j.iter()).map(|(c, h)| c * h).fold( + PolynomialRing { + coefficients: vec![Zq::from(0); size_n.value()], + }, + |acc, val| acc + val, + ) + }) + .collect::>(); + acc.iter() + .zip(d_i_j_k_times_h_i_j.iter()) + .map(|(a, b)| a + b) + .collect() + }, + ) +} + +pub fn poly_matrix_decompose_and_aggregate( + poly: &Vec>, + basis: Zq, + digits: Zq, +) -> Vec>> { + // Decompose h_ij into basis t_1 parts + let poly_basis_form = poly_matrix_decompose_to_basis(poly, basis, digits); + + // Pick elements at each position across all inner vectors and aggregate them + poly_basis_form + .iter() + .map(aggregate_poly_vec_basis_form) + .collect() +} diff --git a/labrador/src/verifier.rs b/labrador/src/verifier.rs index fa98c39..b22b46b 100644 --- a/labrador/src/verifier.rs +++ b/labrador/src/verifier.rs @@ -1,5 +1,8 @@ // src/verifier.rs - +use crate::gadgets::aggregation::*; +use crate::gadgets::norm::*; +use crate::utils::*; +use algebra::{polynomial_ring::PolynomialRing, rq_matrix::RqMatrix, utils::*, zq::Zq}; use profiler_macro::time_profiler; // What does the verifier already know? (Statement) @@ -8,11 +11,230 @@ use profiler_macro::time_profiler; // What are sent to the verifier? // [u1, p, b^{''(k)},u2, z, t_i, g_ij, h_ij] #[time_profiler()] -pub fn verify() { - println!("Verifying something..."); - // 1. g_ij ?= g_ji - // 2. h_ij ?= h_ji - // 3. Check norm_square < beta_square: - // 3.1 ||z^(i)||^2 + sum(t_i^(k)) * sum(||g_ij||^2) + sum(||h_ij||^2) < beta_square - // ... +pub fn verify( + st: St, + tr: Tr, + a_matrix: &RqMatrix, + b_matrix: &Vec>, + c_matrix: &Vec>>, + d_matrix: &Vec>>, +) { + // same parameters as in the prover + let size_r = Zq::new(3); // r: Number of witness elements + let size_n = Zq::new(5); // n + let basis = Zq::new(10); + let digits = Zq::new(3); // t1 + let t1 = digits; + let t2 = digits; + let kappa = Zq::new(3); // Example size + let kappa1 = Zq::from(5); + let kappa2 = Zq::from(5); + let lambda = Zq::new(128); + let double_lambda = lambda * Zq::new(2); + let log_q = Zq::new(32); + let deg_bound_d = Zq::new(8); // random polynomial degree bound + let new_beta = Zq::new(250); // Example value for beta + + let St { + a_constraint, + phi_constraint, + b_constraint, + a_constraint_ct, + phi_constraint_ct, + b_constraint_ct, + } = st; + + let Tr { + u1, + pai, + p, + psi, + omega, + b_ct_aggr, + alpha, + beta, + u2, + c, + z, + t, + g, + h, + } = tr; + let size_r = Zq::from(g.len()); + // 1. check g_ij ?= g_ji + for i in 0..size_r.value() { + for j in (i + 1)..size_r.value() { + assert_eq!( + g[i][j], g[j][i], + "g_ij is not equal to g_ji at indices ({}, {})", + i, j + ); + } + } + // 2. check h_ij ?= h_ji + for i in 0..size_r.value() { + for j in (i + 1)..size_r.value() { + assert_eq!( + h[i][j], h[j][i], + "h_ij is not equal to h_ji at indices ({}, {})", + i, j + ); + } + } + // 3. check if norm sum of z, t, g, h <= beta'^2 + // 3.1 decompose z, t, g, h to basis form + let z_basis_form = poly_vec_decompose_and_aggregate(&z, basis, digits); + let all_t_i_basis_form_aggregated = poly_matrix_decompose_and_aggregate(&t, basis, digits); + let g_matrix_aggregated = poly_matrix_decompose_and_aggregate(&g, basis, t2); + let h_gar_poly_basis_form_aggregated = poly_matrix_decompose_and_aggregate(&h, basis, digits); + let norm_z = poly_matrix_norm_squared(&z_basis_form); + let norm_t = poly_3d_norm_squared(&all_t_i_basis_form_aggregated); + let norm_g = poly_3d_norm_squared(&g_matrix_aggregated); + let norm_h = poly_3d_norm_squared(&h_gar_poly_basis_form_aggregated); + let norm_sum = norm_z + norm_t + norm_g + norm_h; + println!("Verifier: Check norms of decomposed inner commitments"); + assert!(norm_sum <= new_beta.pow(2)); + + println!("Verifier: Check amortized opening of inner commitments"); + // 4. check if Az is valid + let a_times_z: Vec = matrix_poly_times_poly_vector(&a_matrix.values, &z); + // calculate sum(ci * ti) + let sum_c_times_t: Vec = inner_product_poly_matrix_and_poly_vector(&t, &c); + assert_eq!(a_times_z, sum_c_times_t); + + println!("Verifier: Check aggregated innerproduct constraints"); + // 5. check if ?= sum(g_ij * c_i * c_j) + let z_z_inner_product = inner_product_polynomial_ring_vector(&z, &z); + + let mut sum_g_ij_c_i_c_j = zero_poly(); + for i in 0..size_r.value() { + for j in 0..size_r.value() { + let g_ij = &g[i][j]; // Borrow g[i][j] instead of moving it + let c_i = &c[i]; + let c_j = &c[j]; + sum_g_ij_c_i_c_j = sum_g_ij_c_i_c_j + (g_ij * c_i * c_j); + } + } + + assert_eq!(z_z_inner_product, sum_g_ij_c_i_c_j); + + println!("Verifier: Check aggregated linear constraints"); + // 6. check if sum( * c_i) ?= sum(h_ij * c_i * c_j) + // aggregation parameters + let size_k = Zq::new(lambda.value() / log_q.value()); + let constraint_num_l = Zq::new(5); // Define L + let constraint_num_k = Zq::new(5); + + // 6.1 caculate b^{''(k)} + // 6.1.1 calculate a_ij^{''(k)} = sum(psi_l^(k) * a_ij^{'(l)}) for all l = 1..L + let a_ct_aggr = compute_aggr_ct_constraint_a( + &a_constraint_ct, + &psi, + size_k, + size_r, + constraint_num_l, + deg_bound_d, + ); + assert_eq!(a_ct_aggr.len(), size_k.value()); + assert_eq!(a_ct_aggr[0].len(), size_r.value()); + assert_eq!(a_ct_aggr[0][0].len(), size_r.value()); + // 6.1.2 calculate phi_i^{''(k)} = + // sum(psi_l^(k) * phi_i^{'(l)}) for all l = 1..L + // + sum(omega_j^(k) * sigma_{-1} * pi_i^{j)) for all j = 1..256 + let phi_ct_aggr = compute_aggr_ct_constraint_phi( + &phi_constraint_ct, + &pai, + size_k, + size_r, + constraint_num_l, + deg_bound_d, + size_n, + double_lambda, + &psi, + &omega, + ); + assert_eq!(phi_ct_aggr.len(), size_k.value()); + assert_eq!(phi_ct_aggr[0].len(), size_r.value()); + + // b_ct_aggr does not need to be calculated here, it's from prover + assert_eq!(b_ct_aggr.len(), size_k.value()); + + let a_aggr = compute_aggr_constraint_a( + &a_constraint, + &a_ct_aggr, + constraint_num_k, + &alpha, + &beta, + size_r, + size_k, + ); + assert_eq!(a_aggr.len(), size_r.value()); + assert_eq!(a_aggr[0].len(), size_r.value()); + + let phi_aggr = compute_aggr_constraint_phi( + &phi_constraint, + &phi_ct_aggr, + constraint_num_k, + &alpha, + &beta, + size_r, + size_n, + deg_bound_d, + size_k, + ); + + let b_aggr = compute_aggr_constraint_b( + &b_constraint, + &b_ct_aggr, + constraint_num_k, + &alpha, + &beta, + size_k, + ); + + // check if sum( * c_i) ?= sum(h_ij * c_i * c_j) + // calculate sum( * c_i) + let sum_phi_i_z_c_i = phi_aggr + .iter() + .zip(c.iter()) + .map(|(phi_i, c_i)| inner_product_polynomial_ring_vector(&phi_i, &z) * c_i) + .fold(zero_poly(), |acc, val| acc + val); + // calculate sum(h_ij * c_i * c_j) + let mut sum_h_ij_c_i_c_j = zero_poly(); + for i in 0..size_r.value() { + for j in 0..size_r.value() { + sum_h_ij_c_i_c_j = sum_h_ij_c_i_c_j + (&h[i][j] * &c[i] * &c[j]); + } + } + assert_eq!(sum_phi_i_z_c_i * Zq::from(2), sum_h_ij_c_i_c_j); + + println!("Verifier: Compute aggregated relation"); + // 7. check if sum(a_ij * g_ij) + sum(h_ii) -b ?= 0 + check_aggr_relation(&a_aggr, &b_aggr, &g, &h); + + println!("Verifier: Check opening of outer commitments(todo)"); + // 8. check if u1 is valid + let u1_check = calculate_outer_comm_u1( + &b_matrix, + &c_matrix, + &g_matrix_aggregated, + &all_t_i_basis_form_aggregated, + kappa1, + t1, + t2, + size_r, + size_n, + ); + assert_eq!(u1, u1_check); + // 9. check if u2 is valid + let u2_check = calculate_outer_comm_u2( + &d_matrix, + &h_gar_poly_basis_form_aggregated, + t2, + kappa2, + size_r, + size_n, + deg_bound_d, + ); + assert_eq!(u2, u2_check); } From 43ad8167bc3cd1a4d33294a80a044b41a6e26d57 Mon Sep 17 00:00:00 2001 From: Junochiu Date: Thu, 26 Dec 2024 03:59:34 +0800 Subject: [PATCH 2/9] refactor: cargo test passed --- algebra/src/utils.rs | 4 +- labrador/src/gadgets/aggregation.rs | 128 ++++- labrador/src/gadgets/constraints.rs | 31 ++ labrador/src/gadgets/decompose.rs | 339 ++++++++++++ labrador/src/gadgets/gaussian_generator.rs | 17 + labrador/src/gadgets/mod.rs | 2 + labrador/src/lib.rs | 2 + labrador/src/prover.rs | 599 +-------------------- labrador/src/st.rs | 10 + labrador/src/tr.rs | 17 + labrador/src/utils.rs | 15 - labrador/src/verifier.rs | 5 +- 12 files changed, 555 insertions(+), 614 deletions(-) create mode 100644 labrador/src/gadgets/constraints.rs create mode 100644 labrador/src/st.rs create mode 100644 labrador/src/tr.rs diff --git a/algebra/src/utils.rs b/algebra/src/utils.rs index d00b83b..93803bc 100644 --- a/algebra/src/utils.rs +++ b/algebra/src/utils.rs @@ -23,8 +23,8 @@ pub fn poly_vec_add_poly_vec(a: &[PolynomialRing], b: &[PolynomialRing]) -> Vec< // inner product of 2 vectors of PolynomialRing pub fn inner_product_polynomial_ring_vector( - a: &[PolynomialRing], - b: &[PolynomialRing], + a: &Vec, + b: &Vec, ) -> PolynomialRing { assert_eq!( a.len(), diff --git a/labrador/src/gadgets/aggregation.rs b/labrador/src/gadgets/aggregation.rs index de75ec9..fcdcec2 100644 --- a/labrador/src/gadgets/aggregation.rs +++ b/labrador/src/gadgets/aggregation.rs @@ -1,4 +1,7 @@ -use crate::gadgets::gaussian_generator::generate_gaussian_distribution; +use crate::gadgets::{ + conjugation_automorphism::conjugation_automorphism, constraints::calculate_b_constraint, + gaussian_generator::generate_gaussian_distribution, +}; use algebra::{ generate_random_polynomial_ring, inner_product_polynomial_ring_vector, zero_poly, PolynomialRing, Zq, @@ -526,4 +529,127 @@ mod tests { check_aggr_relation(&a_aggr, &b_aggr, &g, &h); } + + #[test] + fn test_aggr_relation() { + let size_r = Zq::new(3); // r: Number of witness elements + let size_n = Zq::new(5); // n + let deg_bound_d = Zq::new(8); // random polynomial degree bound + // generate size_r * size_n witness_s + let witness_s: Vec> = (0..size_r.value()) + .map(|_| { + (0..size_n.value()) + .map(|_| generate_random_polynomial_ring(deg_bound_d.value())) + .collect() + }) + .collect(); + + // generate size_r * size_r a_aggr + let a_aggr: Vec> = (0..size_r.value()) + .map(|i| { + (0..size_r.value()) + .map(|j| generate_random_polynomial_ring(deg_bound_d.value())) + .collect::>() + }) + .collect(); + + // generate size_r * size_n phi_aggr + let phi_aggr: Vec> = (0..size_r.value()) + .map(|i| { + (0..size_n.value()) + .map(|j| { + // generate_random_polynomial_ring(deg_bound_d.value()) + generate_random_polynomial_ring(64) + }) + .collect::>() + }) + .collect(); + + let b_aggr: PolynomialRing = calculate_b_constraint(&witness_s, &a_aggr, &phi_aggr); + + // Calculate garbage polynomial g_ij = + let g: Vec> = (0..size_r.value()) + .map(|i| { + (0..size_r.value()) + .map(|j| { + let s_i = &witness_s[i]; + let s_j = &witness_s[j]; + inner_product_polynomial_ring_vector(&s_i, &s_j) + }) + .collect::>() + }) + .collect(); + + let h: Vec> = (0..size_r.value()) + .map(|i| { + (0..size_r.value()) + .map(|j| { + let phi_i = &phi_aggr[i]; + let phi_j = &phi_aggr[j]; + let s_i = &witness_s[i]; + let s_j = &witness_s[j]; + let inner_product_ij = inner_product_polynomial_ring_vector(&phi_i, &s_j) + + inner_product_polynomial_ring_vector(&phi_j, &s_i); + inner_product_ij + }) + .collect::>() + }) + .collect(); + + // Calculate b^(k) + let mut quad_sum = zero_poly(); + let mut linear_sum = zero_poly(); + for i in 0..size_r.value() { + for j in 0..size_r.value() { + // calculate inner product of s[i] and s[j], will return a single PolynomialRing + let elem_s_i = &witness_s[i]; + let elem_s_j = &witness_s[j]; + // Calculate inner product and update b + let inner_product_si_sj = + inner_product_polynomial_ring_vector(&elem_s_i, &elem_s_j); + let a_constr = &a_aggr[i][j]; + quad_sum = quad_sum + (inner_product_si_sj * a_constr); + } + // calculate inner product of s[i] and phi + let inner_product_si_phi = + inner_product_polynomial_ring_vector(&witness_s[i], &phi_aggr[i]); + println!("inner_product_si_phi: {:?}", inner_product_si_phi); + println!("h[i][i]: {:?}", h[i][i]); + assert_eq!(&inner_product_si_phi * Zq::from(2), h[i][i]); + linear_sum = linear_sum + inner_product_si_phi; + } + + // use function to check + check_aggr_relation(&a_aggr, &b_aggr, &g, &h); + + // ================================================ + // manually check + + // 7. check if sum(a_ij * g_ij) + sum(h_ii) -b ?= 0 + // 7.1 calculate sum(a_ij * g_ij) + let sum_a_ij_g_ij = a_aggr + .iter() + .zip(g.iter()) + .map(|(a_i, g_i)| { + a_i.iter() + .zip(g_i.iter()) + .map(|(a_ij, g_ij)| a_ij * g_ij) + .fold(zero_poly(), |acc, val| acc + val) + }) + .fold(zero_poly(), |acc, val| acc + val); + + // 7.2 calculate sum(h_ii) + let sum_h_ii = (0..size_r.value()).fold(zero_poly(), |acc, i| acc + &h[i][i]); + + // 2 times sum + let quad_sum2 = quad_sum * Zq::from(2); + let linear_sum2 = linear_sum * Zq::from(2); + let b_aggr2 = &b_aggr * Zq::from(2); + let sum_a_ij_g_ij2 = sum_a_ij_g_ij * Zq::from(2); + assert_eq!(linear_sum2, sum_h_ii); + assert_eq!(quad_sum2, sum_a_ij_g_ij2); + assert_eq!(quad_sum2 + linear_sum2, b_aggr2); + // 7.3 check if sum(a_ij * g_ij) + sum(h_ii) -b ?= 0 + assert_eq!(sum_a_ij_g_ij2 + sum_h_ii, b_aggr2); + } } diff --git a/labrador/src/gadgets/constraints.rs b/labrador/src/gadgets/constraints.rs new file mode 100644 index 0000000..5d7eb80 --- /dev/null +++ b/labrador/src/gadgets/constraints.rs @@ -0,0 +1,31 @@ +use algebra::{polynomial_ring::PolynomialRing, utils::*, zq::Zq}; + +// Function to calculate b^(k) +pub fn calculate_b_constraint( + s: &[Vec], + a_constraint: &[Vec], + phi_constraint: &[Vec], +) -> PolynomialRing { + let mut b: PolynomialRing = PolynomialRing { + coefficients: vec![Zq::from(0)], + }; + let s_len_usize = s.len(); + + // Calculate b^(k) + for i in 0..s_len_usize { + for j in 0..s_len_usize { + // calculate inner product of s[i] and s[j], will return a single PolynomialRing + let elem_s_i = &s[i]; + let elem_s_j = &s[j]; + // Calculate inner product and update b + let inner_product_si_sj = inner_product_polynomial_ring_vector(elem_s_i, elem_s_j); + let a_constr = &a_constraint[i][j]; + b = b + (inner_product_si_sj * a_constr); + } + // calculate inner product of s[i] and phi + let inner_product_si_phi = inner_product_polynomial_ring_vector(&s[i], &phi_constraint[i]); + b = b + inner_product_si_phi; + } + + b +} diff --git a/labrador/src/gadgets/decompose.rs b/labrador/src/gadgets/decompose.rs index e69de29..96abf2a 100644 --- a/labrador/src/gadgets/decompose.rs +++ b/labrador/src/gadgets/decompose.rs @@ -0,0 +1,339 @@ +use crate::gadgets::aggregation::*; +use algebra::{polynomial_ring::PolynomialRing, zq::Zq}; +// convert number to basis +// 42 = 0 * 2^7 + 1 * 2^6 + 0 * 2^5 + 1 * 2^4 + 0 * 2^3 + 1 * 2^2 + 0 * 2^1 + 0 * 2^0 +// first digit: 42 / 2 = 21, result_i = 0 +// second digit: 21 / 2 = 10, result_i = 1 +// third digit: 10 / 2 = 5, result_i = 0 +// forth digit: 5 / 2 = 2, result_i = 1 +// fifth digit: 2 / 2 = 1, result_i = 0 +// sixth digit: 1 / 2 = 0, result_i = 1 + +pub fn num_to_basis(num: Zq, basis: Zq, digits: Zq) -> Vec { + let mut result = Vec::new(); + let mut remainder = num; + + let zero = Zq::from(0); + let base = basis; + + for _ in 0..digits.value() { + let digit = remainder % base; + result.push(digit); + remainder = Zq::from(remainder.value() / base.value()); + } + + while result.len() < digits.value() { + // push 0 to the highest position + result.push(zero); + } + + result +} + +// convert ring polynomial to basis +pub fn ring_polynomial_to_basis(poly: &PolynomialRing, basis: Zq, digits: Zq) -> Vec> { + poly.coefficients + .iter() + .map(|&coeff| num_to_basis(coeff, basis, digits)) + .collect() +} + +pub fn poly_vec_decompose_to_basis( + poly: &Vec, + basis: Zq, + digits: Zq, +) -> Vec>> { + poly.iter() + .map(|poly_i| ring_polynomial_to_basis(poly_i, basis, digits)) + .collect::>>>() +} + +pub fn poly_matrix_decompose_to_basis( + poly: &Vec>, + basis: Zq, + digits: Zq, +) -> Vec>>> { + poly.iter() + .map(|poly_i| poly_vec_decompose_to_basis(poly_i, basis, digits)) + .collect::>>>>() +} + +// TODO(junochiu): check where best to put this function / any renaming needed +// aggregate basis form of a vector of PolynomialRing +pub fn aggregate_poly_vec_basis_form( + poly_basis_form: &Vec>>, +) -> Vec> { + poly_basis_form + .iter() + .map(|poly_i_j_basis_form| { + let num_loop_needed = poly_i_j_basis_form.first().map_or(0, |v| v.len()); + (0..num_loop_needed) + .map(|k| { + let coefficients = poly_i_j_basis_form + .iter() + .map(|basis_part| basis_part.get(k).cloned().unwrap_or(Zq::from(0))) + .collect(); + PolynomialRing { coefficients } + }) + .collect() + }) + .collect() +} + +// TODO(junochiu): check where best to put this function / any renaming needed +pub fn poly_matrix_decompose_and_aggregate( + poly: &Vec>, + basis: Zq, + digits: Zq, +) -> Vec>> { + // Decompose h_ij into basis t_1 parts + let poly_basis_form = poly_matrix_decompose_to_basis(poly, basis, digits); + + // Pick elements at each position across all inner vectors and aggregate them + poly_basis_form + .iter() + .map(aggregate_poly_vec_basis_form) + .collect() +} + +// TODO(junochiu): check where best to put this function / any renaming needed +pub fn poly_vec_decompose_and_aggregate( + poly: &Vec, + basis: Zq, + digits: Zq, +) -> Vec> { + // Decompose each PolynomialRing into basis parts + let poly_basis_form = poly_vec_decompose_to_basis(poly, basis, digits); + aggregate_poly_vec_basis_form(&poly_basis_form) +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_num_to_basis() { + let num = Zq::from(42); + let basis = Zq::from(2); + let digits = Zq::from(6); + let binary = num_to_basis(num, basis, digits); + assert_eq!( + binary, + vec![ + Zq::from(0), + Zq::from(1), + Zq::from(0), + Zq::from(1), + Zq::from(0), + Zq::from(1) + ] + ); + + let num = Zq::from(100); + let basis = Zq::from(3); + let digits = Zq::from(6); + let binary = num_to_basis(num, basis, digits); + assert_eq!( + binary, + vec![ + Zq::from(1), + Zq::from(0), + Zq::from(2), + Zq::from(0), + Zq::from(1), + Zq::from(0) + ] + ); + + let num = Zq::from(100); + let basis = Zq::from(6); + let digits = Zq::from(6); + let binary = num_to_basis(num, basis, digits); + assert_eq!( + binary, + vec![ + Zq::from(4), + Zq::from(4), + Zq::from(2), + Zq::from(0), + Zq::from(0), + Zq::from(0) + ] + ); + + let num = Zq::from(100); + let basis = Zq::from(10); + let digits = Zq::from(6); + let binary = num_to_basis(num, basis, digits); + assert_eq!( + binary, + vec![ + Zq::from(0), + Zq::from(0), + Zq::from(1), + Zq::from(0), + Zq::from(0), + Zq::from(0) + ] + ); + } + + #[test] + fn test_basis_to_num_vector() { + let basis = Zq::from(10); + let digits = Zq::from(3); + let vec1 = [8, 46, 61, 71, 33, 33, 18]; + let vec2 = [20, 54, 94, 93, 70, 33, 14]; + let vec3 = [24, 40, 100, 85, 121, 57, 56]; + let vec4 = [14, 37, 91, 118, 159, 109, 72]; + for vec in [vec1, vec2, vec3, vec4] { + let mut temp_vec: Vec> = Vec::new(); + for i in vec { + let num = num_to_basis(Zq::from(i), basis, digits); + temp_vec.push(num); + } + } + } + + #[test] + fn test_ring_polynomial_to_basis() { + let poly = PolynomialRing { + coefficients: vec![Zq::from(42), Zq::from(100), Zq::from(100)], + }; + let basis = Zq::from(2); + let digits = Zq::from(8); + let expected_result = vec![ + vec![ + Zq::from(0), + Zq::from(1), + Zq::from(0), + Zq::from(1), + Zq::from(0), + Zq::from(1), + Zq::from(0), + Zq::from(0), + ], + vec![ + Zq::from(0), + Zq::from(0), + Zq::from(1), + Zq::from(0), + Zq::from(0), + Zq::from(1), + Zq::from(1), + Zq::from(0), + ], + vec![ + Zq::from(0), + Zq::from(0), + Zq::from(1), + Zq::from(0), + Zq::from(0), + Zq::from(1), + Zq::from(1), + Zq::from(0), + ], + ]; + let result = ring_polynomial_to_basis(&poly, basis, digits); + assert_eq!(result, expected_result); + } + + #[test] + fn test_decompose_poly_to_basis_form() { + // Arrange: Create sample input polynomial rings + let poly1 = PolynomialRing { + coefficients: vec![Zq::from(123), Zq::from(456), Zq::from(789)], + }; + let poly2 = PolynomialRing { + coefficients: vec![Zq::from(12), Zq::from(45), Zq::from(78)], + }; + let poly_input = vec![ + vec![poly1.clone(), poly2.clone()], + vec![poly1.clone(), poly2.clone()], + ]; + let basis = Zq::from(10); + let digits = Zq::from(3); + + // Act: Call the function to decompose the polynomial + let result = poly_matrix_decompose_and_aggregate(&poly_input, basis, digits); + + let expected_row1 = vec![ + vec![ + PolynomialRing { + coefficients: vec![Zq::from(3), Zq::from(6), Zq::from(9)], + }, + PolynomialRing { + coefficients: vec![Zq::from(2), Zq::from(5), Zq::from(8)], + }, + PolynomialRing { + coefficients: vec![Zq::from(1), Zq::from(4), Zq::from(7)], + }, + ], + vec![ + PolynomialRing { + coefficients: vec![Zq::from(2), Zq::from(5), Zq::from(8)], + }, + PolynomialRing { + coefficients: vec![Zq::from(1), Zq::from(4), Zq::from(7)], + }, + PolynomialRing { + coefficients: vec![Zq::from(0), Zq::from(0), Zq::from(0)], + }, + ], + ]; + + let expected = vec![expected_row1.clone(), expected_row1.clone()]; + assert_eq!( + result, expected, + "The decomposition did not match the expected output." + ); + } + + #[test] + fn test_decompose_poly_ring_vector_to_basis_form() { + // Arrange: Create sample input vector of PolynomialRing + let poly1 = PolynomialRing { + coefficients: vec![Zq::from(123), Zq::from(456), Zq::from(789)], + }; + let poly2 = PolynomialRing { + coefficients: vec![Zq::from(12), Zq::from(45), Zq::from(78)], + }; + let poly_vec = vec![poly1.clone(), poly2.clone()]; + let basis = Zq::from(10); + let digits = Zq::from(3); + + // Act: Call the decomposition function + let result = poly_vec_decompose_and_aggregate(&poly_vec, basis, digits); + + // Define expected output + let expected = vec![ + vec![ + PolynomialRing { + coefficients: vec![Zq::from(3), Zq::from(6), Zq::from(9)], + }, + PolynomialRing { + coefficients: vec![Zq::from(2), Zq::from(5), Zq::from(8)], + }, + PolynomialRing { + coefficients: vec![Zq::from(1), Zq::from(4), Zq::from(7)], + }, + ], + vec![ + PolynomialRing { + coefficients: vec![Zq::from(2), Zq::from(5), Zq::from(8)], + }, + PolynomialRing { + coefficients: vec![Zq::from(1), Zq::from(4), Zq::from(7)], + }, + PolynomialRing { + coefficients: vec![Zq::from(0), Zq::from(0), Zq::from(0)], + }, + ], + ]; + + // Assert + assert_eq!( + result, expected, + "The decomposition did not match the expected output." + ); + } +} diff --git a/labrador/src/gadgets/gaussian_generator.rs b/labrador/src/gadgets/gaussian_generator.rs index 5739fa0..4fd0150 100644 --- a/labrador/src/gadgets/gaussian_generator.rs +++ b/labrador/src/gadgets/gaussian_generator.rs @@ -23,3 +23,20 @@ pub fn generate_gaussian_distribution(nd: Zq) -> Vec> { matrix } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_generate_gaussian_distribution() { + let nd = Zq::from(10); + let matrix = generate_gaussian_distribution(nd); + assert_eq!(matrix.len(), 256); + assert_eq!(matrix[0].len(), nd.value()); + assert_eq!(matrix[1].len(), nd.value()); + assert!(matrix.iter().all(|row| row + .iter() + .all(|&val| val.value == Zq::Q - 1 || val.value == 0 || val.value == 1))); + } +} diff --git a/labrador/src/gadgets/mod.rs b/labrador/src/gadgets/mod.rs index 17b7b94..4073cae 100644 --- a/labrador/src/gadgets/mod.rs +++ b/labrador/src/gadgets/mod.rs @@ -1,4 +1,6 @@ pub mod aggregation; pub mod conjugation_automorphism; +pub mod constraints; +pub mod decompose; pub mod gaussian_generator; pub mod norm; diff --git a/labrador/src/lib.rs b/labrador/src/lib.rs index 92f1f37..3d96589 100644 --- a/labrador/src/lib.rs +++ b/labrador/src/lib.rs @@ -1,5 +1,7 @@ pub mod gadgets; pub mod prover; pub mod setup; +pub mod st; +pub mod tr; pub mod utils; pub mod verifier; diff --git a/labrador/src/prover.rs b/labrador/src/prover.rs index 929b723..99cc4bf 100644 --- a/labrador/src/prover.rs +++ b/labrador/src/prover.rs @@ -1,9 +1,12 @@ use crate::gadgets::{ - aggregation::check_aggr_relation, conjugation_automorphism::conjugation_automorphism, - gaussian_generator::generate_gaussian_distribution, norm::*, + aggregation::*, conjugation_automorphism::conjugation_automorphism, constraints::*, + decompose::*, gaussian_generator::generate_gaussian_distribution, norm::*, }; use crate::setup::setup; +use crate::st::St; +use crate::tr::Tr; use crate::utils::{calculate_outer_comm_u1, calculate_outer_comm_u2}; +use crate::verifier::verify; use algebra::{ polynomial_ring::PolynomialRing, rq_matrix::RqMatrix, @@ -17,150 +20,6 @@ use algebra::{ use profiler_macro::time_profiler; use rand::Rng; -// Function to calculate b^(k) -fn calculate_b_constraint( - s: &[Vec], - a_constraint: &[Vec], - phi_constraint: &[Vec], -) -> PolynomialRing { - let mut b: PolynomialRing = PolynomialRing { - coefficients: vec![Zq::from(0)], - }; - let s_len_usize = s.len(); - - // Calculate b^(k) - for i in 0..s_len_usize { - for j in 0..s_len_usize { - // calculate inner product of s[i] and s[j], will return a single PolynomialRing - let elem_s_i = &s[i]; - let elem_s_j = &s[j]; - // Calculate inner product and update b - let inner_product_si_sj = inner_product_polynomial_ring_vector(elem_s_i, elem_s_j); - let a_constr = &a_constraint[i][j]; - b = b + (inner_product_si_sj * a_constr); - } - // calculate inner product of s[i] and phi - let inner_product_si_phi = inner_product_polynomial_ring_vector(&s[i], &phi_constraint[i]); - b = b + inner_product_si_phi; - } - - b -} - -// convert number to basis -// 42 = 0 * 2^7 + 1 * 2^6 + 0 * 2^5 + 1 * 2^4 + 0 * 2^3 + 1 * 2^2 + 0 * 2^1 + 0 * 2^0 -// first digit: 42 / 2 = 21, result_i = 0 -// second digit: 21 / 2 = 10, result_i = 1 -// third digit: 10 / 2 = 5, result_i = 0 -// forth digit: 5 / 2 = 2, result_i = 1 -// fifth digit: 2 / 2 = 1, result_i = 0 -// sixth digit: 1 / 2 = 0, result_i = 1 - -fn num_to_basis(num: Zq, basis: Zq, digits: Zq) -> Vec { - let mut result = Vec::new(); - let mut remainder = num; - - let zero = Zq::from(0); - let base = basis; - - for _ in 0..digits.value() { - let digit = remainder % base; - result.push(digit); - remainder = Zq::from(remainder.value() / base.value()); - } - - while result.len() < digits.value() { - // push 0 to the highest position - result.push(zero); - } - - result -} - -// convert ring polynomial to basis -fn ring_polynomial_to_basis(poly: &PolynomialRing, basis: Zq, digits: Zq) -> Vec> { - poly.coefficients - .iter() - .map(|&coeff| num_to_basis(coeff, basis, digits)) - .collect() -} - -// aggregate basis form of a vector of PolynomialRing -fn aggregate_poly_vec_basis_form(poly_basis_form: &Vec>>) -> Vec> { - poly_basis_form - .iter() - .map(|poly_i_j_basis_form| { - let num_loop_needed = poly_i_j_basis_form.first().map_or(0, |v| v.len()); - (0..num_loop_needed) - .map(|k| { - let coefficients = poly_i_j_basis_form - .iter() - .map(|basis_part| basis_part.get(k).cloned().unwrap_or(Zq::from(0))) - .collect(); - PolynomialRing { coefficients } - }) - .collect() - }) - .collect() -} - -fn poly_vec_decompose_to_basis( - poly: &Vec, - basis: Zq, - digits: Zq, -) -> Vec>> { - poly.iter() - .map(|poly_i| ring_polynomial_to_basis(poly_i, basis, digits)) - .collect::>>>() -} - -fn poly_matrix_decompose_to_basis( - poly: &Vec>, - basis: Zq, - digits: Zq, -) -> Vec>>> { - poly.iter() - .map(|poly_i| poly_vec_decompose_to_basis(poly_i, basis, digits)) - .collect::>>>>() -} - -fn poly_vec_decompose_and_aggregate( - poly: &Vec, - basis: Zq, - digits: Zq, -) -> Vec> { - // Decompose each PolynomialRing into basis parts - let poly_basis_form = poly_vec_decompose_to_basis(poly, basis, digits); - aggregate_poly_vec_basis_form(&poly_basis_form) -} - -// statement -struct St { - a_constraint: Vec>>, - phi_constraint: Vec>>, - b_constraint: Vec, - a_constraint_ct: Vec>>, - phi_constraint_ct: Vec>>, - b_constraint_ct: Vec, -} - -struct Tr { - u1: Vec, // Replace with the actual type - pai: Vec>>, // Replace with the actual type - p: Vec, // Replace with the actual type - psi: Vec>, // Replace with the actual type - omega: Vec>, // Replace with the actual type - b_ct_aggr: Vec, // Replace with the actual type - alpha: Vec, // Replace with the actual type - beta: Vec, // Replace with the actual type - u2: Vec, - c: Vec, - z: Vec, - t: Vec>, // Replace with the actual type - g: Vec>, // Replace with the actual type - h: Vec>, -} - #[time_profiler()] pub fn prove( a_matrix: &RqMatrix, @@ -751,129 +610,6 @@ mod tests { assert_eq!(sum_phi_i_z_c_i * Zq::from(2), sum_h_ij_c_i_c_j); } - #[test] - fn test_aggr_relation() { - let size_r = Zq::new(3); // r: Number of witness elements - let size_n = Zq::new(5); // n - let deg_bound_d = Zq::new(8); // random polynomial degree bound - // generate size_r * size_n witness_s - let witness_s: Vec> = (0..size_r.value()) - .map(|_| { - (0..size_n.value()) - .map(|_| generate_random_polynomial_ring(deg_bound_d.value())) - .collect() - }) - .collect(); - - // generate size_r * size_r a_aggr - let a_aggr: Vec> = (0..size_r.value()) - .map(|i| { - (0..size_r.value()) - .map(|j| generate_random_polynomial_ring(deg_bound_d.value())) - .collect::>() - }) - .collect(); - - // generate size_r * size_n phi_aggr - let phi_aggr: Vec> = (0..size_r.value()) - .map(|i| { - (0..size_n.value()) - .map(|j| { - // generate_random_polynomial_ring(deg_bound_d.value()) - generate_random_polynomial_ring(64) - }) - .collect::>() - }) - .collect(); - - let b_aggr: PolynomialRing = calculate_b_constraint(&witness_s, &a_aggr, &phi_aggr); - - // Calculate garbage polynomial g_ij = - let g: Vec> = (0..size_r.value()) - .map(|i| { - (0..size_r.value()) - .map(|j| { - let s_i = &witness_s[i]; - let s_j = &witness_s[j]; - inner_product_polynomial_ring_vector(&s_i, &s_j) - }) - .collect::>() - }) - .collect(); - - let h: Vec> = (0..size_r.value()) - .map(|i| { - (0..size_r.value()) - .map(|j| { - let phi_i = &phi_aggr[i]; - let phi_j = &phi_aggr[j]; - let s_i = &witness_s[i]; - let s_j = &witness_s[j]; - let inner_product_ij = inner_product_polynomial_ring_vector(&phi_i, &s_j) - + inner_product_polynomial_ring_vector(&phi_j, &s_i); - inner_product_ij - }) - .collect::>() - }) - .collect(); - - // Calculate b^(k) - let mut quad_sum = zero_poly(); - let mut linear_sum = zero_poly(); - for i in 0..size_r.value() { - for j in 0..size_r.value() { - // calculate inner product of s[i] and s[j], will return a single PolynomialRing - let elem_s_i = &witness_s[i]; - let elem_s_j = &witness_s[j]; - // Calculate inner product and update b - let inner_product_si_sj = - inner_product_polynomial_ring_vector(&elem_s_i, &elem_s_j); - let a_constr = &a_aggr[i][j]; - quad_sum = quad_sum + (inner_product_si_sj * a_constr); - } - // calculate inner product of s[i] and phi - let inner_product_si_phi = - inner_product_polynomial_ring_vector(&witness_s[i], &phi_aggr[i]); - println!("inner_product_si_phi: {:?}", inner_product_si_phi); - println!("h[i][i]: {:?}", h[i][i]); - assert_eq!(&inner_product_si_phi * Zq::from(2), h[i][i]); - linear_sum = linear_sum + inner_product_si_phi; - } - - // use function to check - check_aggr_relation(&a_aggr, &b_aggr, &g, &h); - - // ================================================ - // manually check - - // 7. check if sum(a_ij * g_ij) + sum(h_ii) -b ?= 0 - // 7.1 calculate sum(a_ij * g_ij) - let sum_a_ij_g_ij = a_aggr - .iter() - .zip(g.iter()) - .map(|(a_i, g_i)| { - a_i.iter() - .zip(g_i.iter()) - .map(|(a_ij, g_ij)| a_ij * g_ij) - .fold(zero_poly(), |acc, val| acc + val) - }) - .fold(zero_poly(), |acc, val| acc + val); - - // 7.2 calculate sum(h_ii) - let sum_h_ii = (0..size_r.value()).fold(zero_poly(), |acc, i| acc + &h[i][i]); - - // 2 times sum - let quad_sum2 = quad_sum * Zq::from(2); - let linear_sum2 = linear_sum * Zq::from(2); - let b_aggr2 = &b_aggr * Zq::from(2); - let sum_a_ij_g_ij2 = sum_a_ij_g_ij * Zq::from(2); - assert_eq!(linear_sum2, sum_h_ii); - assert_eq!(quad_sum2, sum_a_ij_g_ij2); - assert_eq!(quad_sum2 + linear_sum2, b_aggr2); - // 7.3 check if sum(a_ij * g_ij) + sum(h_ii) -b ?= 0 - assert_eq!(sum_a_ij_g_ij2 + sum_h_ii, b_aggr2); - } - #[test] fn test_inner_product_and_z_computation() { let deg_bound_d = Zq::new(8); // random polynomial degree bound @@ -1032,145 +768,6 @@ mod tests { assert_eq!(result, expected); } - #[test] - fn test_num_to_basis() { - let num = Zq::from(42); - let basis = Zq::from(2); - let digits = Zq::from(6); - let binary = num_to_basis(num, basis, digits); - assert_eq!( - binary, - vec![ - Zq::from(0), - Zq::from(1), - Zq::from(0), - Zq::from(1), - Zq::from(0), - Zq::from(1) - ] - ); - - let num = Zq::from(100); - let basis = Zq::from(3); - let digits = Zq::from(6); - let binary = num_to_basis(num, basis, digits); - assert_eq!( - binary, - vec![ - Zq::from(1), - Zq::from(0), - Zq::from(2), - Zq::from(0), - Zq::from(1), - Zq::from(0) - ] - ); - - let num = Zq::from(100); - let basis = Zq::from(6); - let digits = Zq::from(6); - let binary = num_to_basis(num, basis, digits); - assert_eq!( - binary, - vec![ - Zq::from(4), - Zq::from(4), - Zq::from(2), - Zq::from(0), - Zq::from(0), - Zq::from(0) - ] - ); - - let num = Zq::from(100); - let basis = Zq::from(10); - let digits = Zq::from(6); - let binary = num_to_basis(num, basis, digits); - assert_eq!( - binary, - vec![ - Zq::from(0), - Zq::from(0), - Zq::from(1), - Zq::from(0), - Zq::from(0), - Zq::from(0) - ] - ); - } - - #[test] - fn test_basis_to_num_vector() { - let basis = Zq::from(10); - let digits = Zq::from(3); - let vec1 = [8, 46, 61, 71, 33, 33, 18]; - let vec2 = [20, 54, 94, 93, 70, 33, 14]; - let vec3 = [24, 40, 100, 85, 121, 57, 56]; - let vec4 = [14, 37, 91, 118, 159, 109, 72]; - for vec in [vec1, vec2, vec3, vec4] { - let mut temp_vec: Vec> = Vec::new(); - for i in vec { - let num = num_to_basis(Zq::from(i), basis, digits); - temp_vec.push(num); - } - } - } - - #[test] - fn test_ring_polynomial_to_basis() { - let poly = PolynomialRing { - coefficients: vec![Zq::from(42), Zq::from(100), Zq::from(100)], - }; - let basis = Zq::from(2); - let digits = Zq::from(8); - let expected_result = vec![ - vec![ - Zq::from(0), - Zq::from(1), - Zq::from(0), - Zq::from(1), - Zq::from(0), - Zq::from(1), - Zq::from(0), - Zq::from(0), - ], - vec![ - Zq::from(0), - Zq::from(0), - Zq::from(1), - Zq::from(0), - Zq::from(0), - Zq::from(1), - Zq::from(1), - Zq::from(0), - ], - vec![ - Zq::from(0), - Zq::from(0), - Zq::from(1), - Zq::from(0), - Zq::from(0), - Zq::from(1), - Zq::from(1), - Zq::from(0), - ], - ]; - let result = ring_polynomial_to_basis(&poly, basis, digits); - assert_eq!(result, expected_result); - } - - #[test] - fn test_generate_gaussian_distribution() { - let nd = Zq::from(10); - let matrix = generate_gaussian_distribution(nd); - assert_eq!(matrix.len(), 256); - assert_eq!(matrix[0].len(), nd.value()); - assert_eq!(matrix[1].len(), nd.value()); - assert!(matrix.iter().all(|row| row - .iter() - .all(|&val| val.value == Zq::Q - 1 || val.value == 0 || val.value == 1))); - } - // add test for polynomial addition and multiplication with overload #[test] fn test_polynomial_addition_and_multiplication() { @@ -1194,190 +791,4 @@ mod tests { ] ); } - - #[test] - fn test_decompose_poly_to_basis_form() { - // Arrange: Create sample input polynomial rings - let poly1 = PolynomialRing { - coefficients: vec![Zq::from(123), Zq::from(456), Zq::from(789)], - }; - let poly2 = PolynomialRing { - coefficients: vec![Zq::from(12), Zq::from(45), Zq::from(78)], - }; - let poly_input = vec![ - vec![poly1.clone(), poly2.clone()], - vec![poly1.clone(), poly2.clone()], - ]; - let basis = Zq::from(10); - let digits = Zq::from(3); - - // Act: Call the function to decompose the polynomial - let result = poly_matrix_decompose_and_aggregate(&poly_input, basis, digits); - - let expected_row1 = vec![ - vec![ - PolynomialRing { - coefficients: vec![Zq::from(3), Zq::from(6), Zq::from(9)], - }, - PolynomialRing { - coefficients: vec![Zq::from(2), Zq::from(5), Zq::from(8)], - }, - PolynomialRing { - coefficients: vec![Zq::from(1), Zq::from(4), Zq::from(7)], - }, - ], - vec![ - PolynomialRing { - coefficients: vec![Zq::from(2), Zq::from(5), Zq::from(8)], - }, - PolynomialRing { - coefficients: vec![Zq::from(1), Zq::from(4), Zq::from(7)], - }, - PolynomialRing { - coefficients: vec![Zq::from(0), Zq::from(0), Zq::from(0)], - }, - ], - ]; - - let expected = vec![expected_row1.clone(), expected_row1.clone()]; - assert_eq!( - result, expected, - "The decomposition did not match the expected output." - ); - } - - #[test] - fn test_decompose_poly_ring_vector_to_basis_form() { - // Arrange: Create sample input vector of PolynomialRing - let poly1 = PolynomialRing { - coefficients: vec![Zq::from(123), Zq::from(456), Zq::from(789)], - }; - let poly2 = PolynomialRing { - coefficients: vec![Zq::from(12), Zq::from(45), Zq::from(78)], - }; - let poly_vec = vec![poly1.clone(), poly2.clone()]; - let basis = Zq::from(10); - let digits = Zq::from(3); - - // Act: Call the decomposition function - let result = poly_vec_decompose_and_aggregate(&poly_vec, basis, digits); - - // Define expected output - let expected = vec![ - vec![ - PolynomialRing { - coefficients: vec![Zq::from(3), Zq::from(6), Zq::from(9)], - }, - PolynomialRing { - coefficients: vec![Zq::from(2), Zq::from(5), Zq::from(8)], - }, - PolynomialRing { - coefficients: vec![Zq::from(1), Zq::from(4), Zq::from(7)], - }, - ], - vec![ - PolynomialRing { - coefficients: vec![Zq::from(2), Zq::from(5), Zq::from(8)], - }, - PolynomialRing { - coefficients: vec![Zq::from(1), Zq::from(4), Zq::from(7)], - }, - PolynomialRing { - coefficients: vec![Zq::from(0), Zq::from(0), Zq::from(0)], - }, - ], - ]; - - // Assert - assert_eq!( - result, expected, - "The decomposition did not match the expected output." - ); - } - - #[test] - fn test_poly_norm_squared() { - let poly = PolynomialRing { - coefficients: vec![Zq::from(1), Zq::from(2), Zq::from(3)], - }; - let expected = Zq::from(14); // 1^2 + 2^2 + 3^2 = 14 - let result = poly_norm_squared(&poly); - assert_eq!( - result, expected, - "poly_norm_squared should return the sum of squared coefficients" - ); - } - - #[test] - fn test_poly_matrix_norm_squared() { - let poly1 = PolynomialRing { - coefficients: vec![Zq::from(1), Zq::from(2), Zq::from(3)], - }; - let poly2 = PolynomialRing { - coefficients: vec![Zq::from(4), Zq::from(5), Zq::from(6)], - }; - let poly_matrix = vec![ - vec![poly1.clone(), poly2.clone()], - vec![poly2.clone(), poly1.clone()], - ]; - // poly_norm_squared(poly1) = 1 + 4 + 9 = 14 - // poly_norm_squared(poly2) = 16 + 25 + 36 = 77 - // Total sum: 14 + 77 + 77 + 14 = 182 - let expected = Zq::from(182); - let result = poly_matrix_norm_squared(&poly_matrix); - assert_eq!(result, expected, "poly_matrix_norm_squared should return the sum of squared norms of all polynomials in the matrix"); - } - - #[test] - fn test_poly_vec_norm_squared() { - // Arrange - let poly1 = PolynomialRing { - coefficients: vec![Zq::from(1), Zq::from(2), Zq::from(3)], - }; - let poly2 = PolynomialRing { - coefficients: vec![Zq::from(4), Zq::from(5), Zq::from(6)], - }; - let vec_polys = vec![poly1.clone(), poly2.clone()]; - - // Act - let result = poly_vec_norm_squared(&vec_polys); - - // Assert - // poly1 norm: 1^2 + 2^2 + 3^2 = 14 - // poly2 norm: 4^2 + 5^2 + 6^2 = 77 - let expected = Zq::from(14) + Zq::from(77); - assert_eq!( - result, expected, - "poly_vec_norm_squared did not return the correct sum of squared norms" - ); - } - - #[test] - fn test_poly_3d_norm_squared() { - // Arrange - let poly1 = PolynomialRing { - coefficients: vec![Zq::from(1), Zq::from(2), Zq::from(3)], - }; - let poly2 = PolynomialRing { - coefficients: vec![Zq::from(4), Zq::from(5), Zq::from(6)], - }; - let poly_matrix = vec![ - vec![poly1.clone(), poly2.clone()], - vec![poly1.clone(), poly2.clone()], - ]; - let polymat3d = vec![poly_matrix.clone(), poly_matrix.clone()]; - - // Act - let result = poly_3d_norm_squared(&polymat3d); - - // Assert - // Each poly_matrix contains two vectors of polynomials, each vector has 2 polynomials with norms 14 and 77 - // Each matrix: 2 vectors * (14 + 77) = 2 * 91 = 182 - // Total: 2 matrices * 182 = 364 - let expected = Zq::from(364); - assert_eq!( - result, expected, - "poly_3d_norm_squared did not return the correct sum of squared norms" - ); - } } diff --git a/labrador/src/st.rs b/labrador/src/st.rs new file mode 100644 index 0000000..c49be6e --- /dev/null +++ b/labrador/src/st.rs @@ -0,0 +1,10 @@ +use algebra::{polynomial_ring::PolynomialRing, zq::Zq}; +// statement +pub struct St { + pub a_constraint: Vec>>, + pub phi_constraint: Vec>>, + pub b_constraint: Vec, + pub a_constraint_ct: Vec>>, + pub phi_constraint_ct: Vec>>, + pub b_constraint_ct: Vec, +} diff --git a/labrador/src/tr.rs b/labrador/src/tr.rs new file mode 100644 index 0000000..6a0e274 --- /dev/null +++ b/labrador/src/tr.rs @@ -0,0 +1,17 @@ +use algebra::{polynomial_ring::PolynomialRing, zq::Zq}; +pub struct Tr { + pub u1: Vec, // Replace with the actual type + pub pai: Vec>>, // Replace with the actual type + pub p: Vec, // Replace with the actual type + pub psi: Vec>, // Replace with the actual type + pub omega: Vec>, // Replace with the actual type + pub b_ct_aggr: Vec, // Replace with the actual type + pub alpha: Vec, // Replace with the actual type + pub beta: Vec, // Replace with the actual type + pub u2: Vec, + pub c: Vec, + pub z: Vec, + pub t: Vec>, // Replace with the actual type + pub g: Vec>, // Replace with the actual type + pub h: Vec>, +} diff --git a/labrador/src/utils.rs b/labrador/src/utils.rs index 901bed6..7f6b9a3 100644 --- a/labrador/src/utils.rs +++ b/labrador/src/utils.rs @@ -123,18 +123,3 @@ pub fn calculate_outer_comm_u2( }, ) } - -pub fn poly_matrix_decompose_and_aggregate( - poly: &Vec>, - basis: Zq, - digits: Zq, -) -> Vec>> { - // Decompose h_ij into basis t_1 parts - let poly_basis_form = poly_matrix_decompose_to_basis(poly, basis, digits); - - // Pick elements at each position across all inner vectors and aggregate them - poly_basis_form - .iter() - .map(aggregate_poly_vec_basis_form) - .collect() -} diff --git a/labrador/src/verifier.rs b/labrador/src/verifier.rs index b22b46b..b61a99b 100644 --- a/labrador/src/verifier.rs +++ b/labrador/src/verifier.rs @@ -1,6 +1,7 @@ // src/verifier.rs -use crate::gadgets::aggregation::*; -use crate::gadgets::norm::*; +use crate::gadgets::{aggregation::*, decompose::*, norm::*}; +use crate::st::St; +use crate::tr::Tr; use crate::utils::*; use algebra::{polynomial_ring::PolynomialRing, rq_matrix::RqMatrix, utils::*, zq::Zq}; use profiler_macro::time_profiler; From 092837f62d778a9273a4988e94f783519d237798 Mon Sep 17 00:00:00 2001 From: Junochiu Date: Thu, 26 Dec 2024 04:16:02 +0800 Subject: [PATCH 3/9] wip: fix clippy --- algebra/src/utils.rs | 3 ++- labrador/src/gadgets/aggregation.rs | 22 +++++++++----------- labrador/src/prover.rs | 32 ++++++++++++++--------------- labrador/src/utils.rs | 12 +++++------ labrador/src/verifier.rs | 8 ++++---- 5 files changed, 38 insertions(+), 39 deletions(-) diff --git a/algebra/src/utils.rs b/algebra/src/utils.rs index 93803bc..01e42b5 100644 --- a/algebra/src/utils.rs +++ b/algebra/src/utils.rs @@ -21,6 +21,7 @@ pub fn poly_vec_add_poly_vec(a: &[PolynomialRing], b: &[PolynomialRing]) -> Vec< a.iter().zip(b.iter()).map(|(a_i, b_i)| a_i + b_i).collect() } +#[allow(clippy::ptr_arg)] // inner product of 2 vectors of PolynomialRing pub fn inner_product_polynomial_ring_vector( a: &Vec, @@ -75,7 +76,7 @@ pub fn generate_random_polynomial_ring(deg_bound_d: usize) -> PolynomialRing { // calculate matrix times vector of PolynomialRing pub fn matrix_poly_times_poly_vector( - poly_matrix: &Vec>, + poly_matrix: &[Vec], poly_vec: &Vec, ) -> Vec { poly_matrix diff --git a/labrador/src/gadgets/aggregation.rs b/labrador/src/gadgets/aggregation.rs index fcdcec2..59514af 100644 --- a/labrador/src/gadgets/aggregation.rs +++ b/labrador/src/gadgets/aggregation.rs @@ -519,9 +519,8 @@ mod tests { let phi_j = &phi_aggr[j]; let s_i = &witness_s[i]; let s_j = &witness_s[j]; - let inner_product_ij = inner_product_polynomial_ring_vector(&phi_i, &s_j) - + inner_product_polynomial_ring_vector(&phi_j, &s_i); - inner_product_ij + inner_product_polynomial_ring_vector(phi_i, s_j) + + inner_product_polynomial_ring_vector(phi_j, s_i) }) .collect::>() }) @@ -546,18 +545,18 @@ mod tests { // generate size_r * size_r a_aggr let a_aggr: Vec> = (0..size_r.value()) - .map(|i| { + .map(|_| { (0..size_r.value()) - .map(|j| generate_random_polynomial_ring(deg_bound_d.value())) + .map(|_| generate_random_polynomial_ring(deg_bound_d.value())) .collect::>() }) .collect(); // generate size_r * size_n phi_aggr let phi_aggr: Vec> = (0..size_r.value()) - .map(|i| { + .map(|_| { (0..size_n.value()) - .map(|j| { + .map(|_| { // generate_random_polynomial_ring(deg_bound_d.value()) generate_random_polynomial_ring(64) }) @@ -574,7 +573,7 @@ mod tests { .map(|j| { let s_i = &witness_s[i]; let s_j = &witness_s[j]; - inner_product_polynomial_ring_vector(&s_i, &s_j) + inner_product_polynomial_ring_vector(s_i, s_j) }) .collect::>() }) @@ -588,8 +587,8 @@ mod tests { let phi_j = &phi_aggr[j]; let s_i = &witness_s[i]; let s_j = &witness_s[j]; - let inner_product_ij = inner_product_polynomial_ring_vector(&phi_i, &s_j) - + inner_product_polynomial_ring_vector(&phi_j, &s_i); + let inner_product_ij = inner_product_polynomial_ring_vector(phi_i, s_j) + + inner_product_polynomial_ring_vector(phi_j, s_i); inner_product_ij }) .collect::>() @@ -605,8 +604,7 @@ mod tests { let elem_s_i = &witness_s[i]; let elem_s_j = &witness_s[j]; // Calculate inner product and update b - let inner_product_si_sj = - inner_product_polynomial_ring_vector(&elem_s_i, &elem_s_j); + let inner_product_si_sj = inner_product_polynomial_ring_vector(elem_s_i, elem_s_j); let a_constr = &a_aggr[i][j]; quad_sum = quad_sum + (inner_product_si_sj * a_constr); } diff --git a/labrador/src/prover.rs b/labrador/src/prover.rs index 99cc4bf..4eec97d 100644 --- a/labrador/src/prover.rs +++ b/labrador/src/prover.rs @@ -199,7 +199,7 @@ pub fn prove( // 2.3 calculate u1 let u1 = calculate_outer_comm_u1( - &b_matrix, + b_matrix, &c_matrix, &g_matrix_aggregated, &all_t_i_basis_form_aggregated, @@ -380,7 +380,7 @@ pub fn prove( .sum(); // <⟨omega^(k),p⟩> let omega_k = &omega[k]; - let inner_product_omega_k_p = inner_product_zq_vector(&omega_k, &p); + let inner_product_omega_k_p = inner_product_zq_vector(omega_k, &p); // add them together b_k_0_computed += inner_product_omega_k_p; assert_eq!(b_k_0_from_poly, b_k_0_computed); @@ -421,10 +421,9 @@ pub fn prove( let phi_j = &phi_aggr[j]; let s_i = &witness_s[i]; let s_j = &witness_s[j]; - let inner_product_ij = inner_product_polynomial_ring_vector(&phi_i, &s_j) - + inner_product_polynomial_ring_vector(&phi_j, &s_i); + inner_product_polynomial_ring_vector(phi_i, s_j) + + inner_product_polynomial_ring_vector(phi_j, s_i) // Notice we do not divide by 2 here as paper described, because there is no division in the ring, we multiply by 2 instead with other terms to make verifier check work - inner_product_ij }) .collect::>() }) @@ -445,7 +444,7 @@ pub fn prove( // 5.4 u2 = sum D_ij * h_ij^(k) for all k = 1..(t1-1) let u2 = calculate_outer_comm_u2( - &d_matrix, + d_matrix, &h_gar_poly_basis_form_aggregated, t2, kappa2, @@ -478,7 +477,7 @@ pub fn prove( let sum_phi_i_z_c_i = phi_aggr .iter() .zip(c.iter()) - .map(|(phi_i, c_i)| inner_product_polynomial_ring_vector(&phi_i, &z) * c_i) + .map(|(phi_i, c_i)| inner_product_polynomial_ring_vector(phi_i, &z) * c_i) .fold(zero_poly(), |acc, val| acc + val); // calculate sum(h_ij * c_i * c_j) @@ -563,9 +562,9 @@ mod tests { // generate size_r * size_n phi_aggr let phi_aggr: Vec> = (0..size_r.value()) - .map(|i| { + .map(|_| { (0..size_n.value()) - .map(|j| generate_random_polynomial_ring(deg_bound_d.value())) + .map(|_| generate_random_polynomial_ring(deg_bound_d.value())) .collect::>() }) .collect(); @@ -578,8 +577,8 @@ mod tests { let phi_j = &phi_aggr[j]; let s_i = &witness_s[i]; let s_j = &witness_s[j]; - let inner_product_ij = inner_product_polynomial_ring_vector(&phi_i, &s_j) - + inner_product_polynomial_ring_vector(&phi_j, &s_i); + let inner_product_ij = inner_product_polynomial_ring_vector(phi_i, s_j) + + inner_product_polynomial_ring_vector(phi_j, s_i); inner_product_ij }) .collect::>() @@ -597,7 +596,7 @@ mod tests { let sum_phi_i_z_c_i = phi_aggr .iter() .zip(c.iter()) - .map(|(phi_i, c_i)| inner_product_polynomial_ring_vector(&phi_i, &z) * c_i) + .map(|(phi_i, c_i)| inner_product_polynomial_ring_vector(phi_i, &z) * c_i) .fold(zero_poly(), |acc, val| acc + val); // calculate sum(h_ij * c_i * c_j) let mut sum_h_ij_c_i_c_j = zero_poly(); @@ -653,7 +652,7 @@ mod tests { size_n.value(), "s_j must have the same length as size_n" ); - inner_product_polynomial_ring_vector(&s_i, &s_j) + inner_product_polynomial_ring_vector(s_i, s_j) }) .collect::>() }) @@ -681,7 +680,8 @@ mod tests { assert_eq!(z_z_inner_product, sum_g_ij_c_i_c_j); } - #[test] + // TODO(junochiu): check b_k? + /*#[test] fn test_calculate_b_k() { let r = 3; let n = 4; @@ -715,8 +715,8 @@ mod tests { }) .collect(); let b_k = calculate_b_constraint(&s, &a_constraint, &phi_constraint); - // assert_eq!(b_k, 1983); - } + //assert_eq!(b_k, 1983); + }*/ #[test] fn test_a_new() { diff --git a/labrador/src/utils.rs b/labrador/src/utils.rs index 7f6b9a3..73bc8b1 100644 --- a/labrador/src/utils.rs +++ b/labrador/src/utils.rs @@ -8,10 +8,10 @@ use algebra::{PolynomialRing, RqMatrix, Zq}; // First summation: ∑ B_ik * t_i^(k), 1 ≤ i ≤ r, 0 ≤ k ≤ t1−1 // Initialize u1 with zeros with size kappa1, each element is a polynomial ring pub fn calculate_outer_comm_u1( - b_matrix: &Vec>, - c_matrix: &Vec>>, - g_matrix_aggregated: &Vec>>, - all_t_i_basis_form_aggregated: &Vec>>, + b_matrix: &[Vec], + c_matrix: &[Vec>], + g_matrix_aggregated: &[Vec>], + all_t_i_basis_form_aggregated: &[Vec>], kappa1: Zq, t1: Zq, t2: Zq, @@ -82,8 +82,8 @@ pub fn calculate_outer_comm_u1( } pub fn calculate_outer_comm_u2( - d_matrix: &Vec>>, - h_gar_poly_basis_form_aggregated: &Vec>>, + d_matrix: &[Vec>], + h_gar_poly_basis_form_aggregated: &[Vec>], t2: Zq, kappa2: Zq, size_r: Zq, diff --git a/labrador/src/verifier.rs b/labrador/src/verifier.rs index b61a99b..516e9d5 100644 --- a/labrador/src/verifier.rs +++ b/labrador/src/verifier.rs @@ -198,7 +198,7 @@ pub fn verify( let sum_phi_i_z_c_i = phi_aggr .iter() .zip(c.iter()) - .map(|(phi_i, c_i)| inner_product_polynomial_ring_vector(&phi_i, &z) * c_i) + .map(|(phi_i, c_i)| inner_product_polynomial_ring_vector(phi_i, &z) * c_i) .fold(zero_poly(), |acc, val| acc + val); // calculate sum(h_ij * c_i * c_j) let mut sum_h_ij_c_i_c_j = zero_poly(); @@ -216,8 +216,8 @@ pub fn verify( println!("Verifier: Check opening of outer commitments(todo)"); // 8. check if u1 is valid let u1_check = calculate_outer_comm_u1( - &b_matrix, - &c_matrix, + b_matrix, + c_matrix, &g_matrix_aggregated, &all_t_i_basis_form_aggregated, kappa1, @@ -229,7 +229,7 @@ pub fn verify( assert_eq!(u1, u1_check); // 9. check if u2 is valid let u2_check = calculate_outer_comm_u2( - &d_matrix, + d_matrix, &h_gar_poly_basis_form_aggregated, t2, kappa2, From b061cfe9e00b47bc4a111a0ada18e286d458a352 Mon Sep 17 00:00:00 2001 From: Junochiu Date: Thu, 26 Dec 2024 04:31:14 +0800 Subject: [PATCH 4/9] wip: fix clippy --- labrador/src/gadgets/aggregation.rs | 25 ++++++++++++------------- labrador/src/gadgets/decompose.rs | 2 +- labrador/src/gadgets/norm.rs | 6 +++--- labrador/src/prover.rs | 24 +++++++++++------------- labrador/src/verifier.rs | 6 +++--- 5 files changed, 30 insertions(+), 33 deletions(-) diff --git a/labrador/src/gadgets/aggregation.rs b/labrador/src/gadgets/aggregation.rs index 59514af..de0cf25 100644 --- a/labrador/src/gadgets/aggregation.rs +++ b/labrador/src/gadgets/aggregation.rs @@ -163,11 +163,11 @@ pub fn compute_aggr_ct_constraint_b( // aggregation: a_i = sum(alpha_k * a_ij) + sum(beta_k * a_ij^{''(k)}) pub fn compute_aggr_constraint_a( - a_constraint: &Vec>>, - a_ct_aggr: &Vec>>, + a_constraint: &[Vec>], + a_ct_aggr: &[Vec>], constraint_num_k: Zq, - alpha: &Vec, - beta: &Vec, + alpha: &[PolynomialRing], + beta: &[PolynomialRing], size_r: Zq, size_k: Zq, ) -> Vec> { @@ -260,8 +260,8 @@ pub fn compute_aggr_constraint_b( b_constraint: &Vec, b_ct_aggr: &Vec, constraint_num_k: Zq, - alpha: &Vec, - beta: &Vec, + alpha: &[PolynomialRing], + beta: &[PolynomialRing], size_k: Zq, ) -> PolynomialRing { // Part 1: sum(alpha_k * b^(k)) @@ -279,10 +279,10 @@ pub fn compute_aggr_constraint_b( } pub fn check_aggr_relation( - a_aggr: &Vec>, + a_aggr: &[Vec], b_aggr: &PolynomialRing, - g: &Vec>, - h: &Vec>, + g: &[Vec], + h: &[Vec], ) { let size_r = Zq::from(a_aggr.len()); // 7. check if sum(a_ij * g_ij) + sum(h_ii) -b ?= 0 @@ -505,7 +505,7 @@ mod tests { .map(|j| { let s_i = &witness_s[i]; let s_j = &witness_s[j]; - inner_product_polynomial_ring_vector(&s_i, &s_j) + inner_product_polynomial_ring_vector(s_i, s_j) }) .collect::>() }) @@ -587,9 +587,8 @@ mod tests { let phi_j = &phi_aggr[j]; let s_i = &witness_s[i]; let s_j = &witness_s[j]; - let inner_product_ij = inner_product_polynomial_ring_vector(phi_i, s_j) - + inner_product_polynomial_ring_vector(phi_j, s_i); - inner_product_ij + inner_product_polynomial_ring_vector(phi_i, s_j) + + inner_product_polynomial_ring_vector(phi_j, s_i) }) .collect::>() }) diff --git a/labrador/src/gadgets/decompose.rs b/labrador/src/gadgets/decompose.rs index 96abf2a..e95a512 100644 --- a/labrador/src/gadgets/decompose.rs +++ b/labrador/src/gadgets/decompose.rs @@ -39,7 +39,7 @@ pub fn ring_polynomial_to_basis(poly: &PolynomialRing, basis: Zq, digits: Zq) -> } pub fn poly_vec_decompose_to_basis( - poly: &Vec, + poly: &[PolynomialRing], basis: Zq, digits: Zq, ) -> Vec>> { diff --git a/labrador/src/gadgets/norm.rs b/labrador/src/gadgets/norm.rs index e42628c..82f03e3 100644 --- a/labrador/src/gadgets/norm.rs +++ b/labrador/src/gadgets/norm.rs @@ -8,21 +8,21 @@ pub fn poly_norm_squared(poly: &PolynomialRing) -> Zq { } // Calculate the sum of squared norms for a vector of PolynomialRing instances. -pub fn poly_vec_norm_squared(polys: &Vec) -> Zq { +pub fn poly_vec_norm_squared(polys: &[PolynomialRing]) -> Zq { polys .iter() .fold(Zq::new(0), |acc, poly| acc + poly_norm_squared(poly)) } // Calculate the sum of squared norms for a matrix of PolynomialRing instances. -pub fn poly_matrix_norm_squared(poly_matrix: &Vec>) -> Zq { +pub fn poly_matrix_norm_squared(poly_matrix: &[Vec]) -> Zq { poly_matrix.iter().fold(Zq::new(0), |acc, vector| { acc + poly_vec_norm_squared(vector) }) } // Calculate the sum of squared norms for a 3D vector of PolynomialRing instances. -pub fn poly_3d_norm_squared(polymat3d: &Vec>>) -> Zq { +pub fn poly_3d_norm_squared(polymat3d: &[Vec>]) -> Zq { polymat3d.iter().fold(Zq::new(0), |acc, poly_matrix| { acc + poly_matrix_norm_squared(poly_matrix) }) diff --git a/labrador/src/prover.rs b/labrador/src/prover.rs index 4eec97d..0e6204b 100644 --- a/labrador/src/prover.rs +++ b/labrador/src/prover.rs @@ -23,9 +23,9 @@ use rand::Rng; #[time_profiler()] pub fn prove( a_matrix: &RqMatrix, - b_matrix: &Vec>, - c_matrix: &Vec>>, - d_matrix: &Vec>>, + b_matrix: &[Vec], + c_matrix: &[Vec>], + d_matrix: &[Vec>], ) -> (St, Tr) { // s is a vector of size r. each s_i is a PolynomialRing with n coefficients let size_r = Zq::new(3); // r: Number of witness elements @@ -200,7 +200,7 @@ pub fn prove( // 2.3 calculate u1 let u1 = calculate_outer_comm_u1( b_matrix, - &c_matrix, + c_matrix, &g_matrix_aggregated, &all_t_i_basis_form_aggregated, kappa1, @@ -247,8 +247,7 @@ pub fn prove( .iter() .map(|s_i| { s_i.iter() - .map(|s_i_poly| s_i_poly.coefficients.clone()) - .flatten() + .flat_map(|s_i_poly| s_i_poly.coefficients.clone()) .collect() }) .collect(); @@ -261,8 +260,8 @@ pub fn prove( for i in 0..size_r.value() { let pai_element = &pai[i][j]; let s_i = &s_coeffs[i]; - let inner_product = inner_product_zq_vector(&pai_element, &s_i); - sum = sum + inner_product; + let inner_product = inner_product_zq_vector(pai_element, s_i); + sum += inner_product; } p.push(sum); } @@ -270,7 +269,7 @@ pub fn prove( assert_eq!(p.len(), double_lambda.value()); // sanity check: verify p_j = ct(sum(<σ−1(pi_i^(j)), s_i>)) for all i = 1..r - for j in 0..double_lambda.value() { + for (j, &p_j) in p.iter().enumerate() { let mut sum = PolynomialRing { coefficients: vec![Zq::from(0); deg_bound_d.value()], }; @@ -286,7 +285,7 @@ pub fn prove( }; sum = sum + &pai_poly_ca * s_i_poly; } - assert_eq!(sum.coefficients[0], p[j]); + assert_eq!(sum.coefficients[0], p_j); } println!("Prover: Send proof p"); @@ -577,9 +576,8 @@ mod tests { let phi_j = &phi_aggr[j]; let s_i = &witness_s[i]; let s_j = &witness_s[j]; - let inner_product_ij = inner_product_polynomial_ring_vector(phi_i, s_j) - + inner_product_polynomial_ring_vector(phi_j, s_i); - inner_product_ij + inner_product_polynomial_ring_vector(phi_i, s_j) + + inner_product_polynomial_ring_vector(phi_j, s_i) }) .collect::>() }) diff --git a/labrador/src/verifier.rs b/labrador/src/verifier.rs index 516e9d5..0ff8f0d 100644 --- a/labrador/src/verifier.rs +++ b/labrador/src/verifier.rs @@ -16,9 +16,9 @@ pub fn verify( st: St, tr: Tr, a_matrix: &RqMatrix, - b_matrix: &Vec>, - c_matrix: &Vec>>, - d_matrix: &Vec>>, + b_matrix: &[Vec], + c_matrix: &[Vec>], + d_matrix: &[Vec>], ) { // same parameters as in the prover let size_r = Zq::new(3); // r: Number of witness elements From ca0dc97c647944c8abe8f70451d98a0755f33d56 Mon Sep 17 00:00:00 2001 From: Junochiu Date: Thu, 26 Dec 2024 05:23:03 +0800 Subject: [PATCH 5/9] nostory: update structure naming --- labrador/src/{gadgets => core}/aggregation.rs | 4 ++-- labrador/src/{gadgets => core}/conjugation_automorphism.rs | 0 .../src/{gadgets/constraints.rs => core/constraint.rs} | 0 labrador/src/{gadgets => core}/decompose.rs | 2 +- labrador/src/{gadgets => core}/gaussian_generator.rs | 0 labrador/src/{gadgets => core}/mod.rs | 3 ++- labrador/src/{gadgets => core}/norm.rs | 0 labrador/src/{utils.rs => core/outer_commitment.rs} | 0 labrador/src/lib.rs | 3 +-- labrador/src/prover.rs | 7 +++---- labrador/src/verifier.rs | 3 +-- 11 files changed, 10 insertions(+), 12 deletions(-) rename labrador/src/{gadgets => core}/aggregation.rs (99%) rename labrador/src/{gadgets => core}/conjugation_automorphism.rs (100%) rename labrador/src/{gadgets/constraints.rs => core/constraint.rs} (100%) rename labrador/src/{gadgets => core}/decompose.rs (99%) rename labrador/src/{gadgets => core}/gaussian_generator.rs (100%) rename labrador/src/{gadgets => core}/mod.rs (71%) rename labrador/src/{gadgets => core}/norm.rs (100%) rename labrador/src/{utils.rs => core/outer_commitment.rs} (100%) diff --git a/labrador/src/gadgets/aggregation.rs b/labrador/src/core/aggregation.rs similarity index 99% rename from labrador/src/gadgets/aggregation.rs rename to labrador/src/core/aggregation.rs index de0cf25..fc667f9 100644 --- a/labrador/src/gadgets/aggregation.rs +++ b/labrador/src/core/aggregation.rs @@ -1,5 +1,5 @@ -use crate::gadgets::{ - conjugation_automorphism::conjugation_automorphism, constraints::calculate_b_constraint, +use crate::core::{ + conjugation_automorphism::conjugation_automorphism, constraint::calculate_b_constraint, gaussian_generator::generate_gaussian_distribution, }; use algebra::{ diff --git a/labrador/src/gadgets/conjugation_automorphism.rs b/labrador/src/core/conjugation_automorphism.rs similarity index 100% rename from labrador/src/gadgets/conjugation_automorphism.rs rename to labrador/src/core/conjugation_automorphism.rs diff --git a/labrador/src/gadgets/constraints.rs b/labrador/src/core/constraint.rs similarity index 100% rename from labrador/src/gadgets/constraints.rs rename to labrador/src/core/constraint.rs diff --git a/labrador/src/gadgets/decompose.rs b/labrador/src/core/decompose.rs similarity index 99% rename from labrador/src/gadgets/decompose.rs rename to labrador/src/core/decompose.rs index e95a512..277fd90 100644 --- a/labrador/src/gadgets/decompose.rs +++ b/labrador/src/core/decompose.rs @@ -1,4 +1,4 @@ -use crate::gadgets::aggregation::*; +use crate::core::aggregation::*; use algebra::{polynomial_ring::PolynomialRing, zq::Zq}; // convert number to basis // 42 = 0 * 2^7 + 1 * 2^6 + 0 * 2^5 + 1 * 2^4 + 0 * 2^3 + 1 * 2^2 + 0 * 2^1 + 0 * 2^0 diff --git a/labrador/src/gadgets/gaussian_generator.rs b/labrador/src/core/gaussian_generator.rs similarity index 100% rename from labrador/src/gadgets/gaussian_generator.rs rename to labrador/src/core/gaussian_generator.rs diff --git a/labrador/src/gadgets/mod.rs b/labrador/src/core/mod.rs similarity index 71% rename from labrador/src/gadgets/mod.rs rename to labrador/src/core/mod.rs index 4073cae..e8168c0 100644 --- a/labrador/src/gadgets/mod.rs +++ b/labrador/src/core/mod.rs @@ -1,6 +1,7 @@ pub mod aggregation; pub mod conjugation_automorphism; -pub mod constraints; +pub mod constraint; pub mod decompose; pub mod gaussian_generator; pub mod norm; +pub mod outer_commitment; diff --git a/labrador/src/gadgets/norm.rs b/labrador/src/core/norm.rs similarity index 100% rename from labrador/src/gadgets/norm.rs rename to labrador/src/core/norm.rs diff --git a/labrador/src/utils.rs b/labrador/src/core/outer_commitment.rs similarity index 100% rename from labrador/src/utils.rs rename to labrador/src/core/outer_commitment.rs diff --git a/labrador/src/lib.rs b/labrador/src/lib.rs index 3d96589..fdc9d9d 100644 --- a/labrador/src/lib.rs +++ b/labrador/src/lib.rs @@ -1,7 +1,6 @@ -pub mod gadgets; +pub mod core; pub mod prover; pub mod setup; pub mod st; pub mod tr; -pub mod utils; pub mod verifier; diff --git a/labrador/src/prover.rs b/labrador/src/prover.rs index 0e6204b..8ed62b8 100644 --- a/labrador/src/prover.rs +++ b/labrador/src/prover.rs @@ -1,11 +1,10 @@ -use crate::gadgets::{ - aggregation::*, conjugation_automorphism::conjugation_automorphism, constraints::*, - decompose::*, gaussian_generator::generate_gaussian_distribution, norm::*, +use crate::core::{ + aggregation::*, conjugation_automorphism::conjugation_automorphism, constraint::*, + decompose::*, gaussian_generator::generate_gaussian_distribution, norm::*, outer_commitment::*, }; use crate::setup::setup; use crate::st::St; use crate::tr::Tr; -use crate::utils::{calculate_outer_comm_u1, calculate_outer_comm_u2}; use crate::verifier::verify; use algebra::{ polynomial_ring::PolynomialRing, diff --git a/labrador/src/verifier.rs b/labrador/src/verifier.rs index 0ff8f0d..0a9f909 100644 --- a/labrador/src/verifier.rs +++ b/labrador/src/verifier.rs @@ -1,8 +1,7 @@ // src/verifier.rs -use crate::gadgets::{aggregation::*, decompose::*, norm::*}; +use crate::core::{aggregation::*, decompose::*, norm::*, outer_commitment::*}; use crate::st::St; use crate::tr::Tr; -use crate::utils::*; use algebra::{polynomial_ring::PolynomialRing, rq_matrix::RqMatrix, utils::*, zq::Zq}; use profiler_macro::time_profiler; From d1adb02692a051719aaa23dd3e72109a235c7701 Mon Sep 17 00:00:00 2001 From: Junochiu Date: Thu, 26 Dec 2024 11:30:49 +0800 Subject: [PATCH 6/9] refactor: fix all clippy errors --- Cargo.toml | 2 + labrador/src/core/aggregation.rs | 50 ++++++++++--------- labrador/src/core/conjugation_automorphism.rs | 4 +- labrador/src/core/decompose.rs | 9 ++-- labrador/src/core/outer_commitment.rs | 2 + labrador/src/example/main.rs | 2 - labrador/src/prover.rs | 8 +-- labrador/src/verifier.rs | 11 ++-- 8 files changed, 47 insertions(+), 41 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c81e7d0..41e17ea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,3 +17,5 @@ rayon = "1.10.0" ark-std = { version = "0.4.0" } profiler_macro = { git ="https://github.com/SuccinctPaul/profiler-rs.git", tag = "v0.1.0" } +[workspace.features] +profiler = ["ark-std/print-trace"] \ No newline at end of file diff --git a/labrador/src/core/aggregation.rs b/labrador/src/core/aggregation.rs index fc667f9..620fd21 100644 --- a/labrador/src/core/aggregation.rs +++ b/labrador/src/core/aggregation.rs @@ -1,17 +1,10 @@ -use crate::core::{ - conjugation_automorphism::conjugation_automorphism, constraint::calculate_b_constraint, - gaussian_generator::generate_gaussian_distribution, -}; -use algebra::{ - generate_random_polynomial_ring, inner_product_polynomial_ring_vector, zero_poly, - PolynomialRing, Zq, -}; -use rand::Rng; +use crate::core::conjugation_automorphism::conjugation_automorphism; +use algebra::{inner_product_polynomial_ring_vector, zero_poly, PolynomialRing, Zq}; // 4.3.1 aggregation: calculate a_ij^{''(k)} = sum(psi_l^(k) * a_ij^{'(l)}) for all l = 1..L pub fn compute_aggr_ct_constraint_a( - a_constraint_ct: &Vec>>, - psi: &Vec>, + a_constraint_ct: &[Vec>], + psi: &[Vec], size_k: Zq, size_r: Zq, constraint_num_l: Zq, @@ -44,17 +37,19 @@ pub fn compute_aggr_ct_constraint_a( // 4.3.2 aggregation: calculate phi_i^{''(k)} = // sum(psi_l^(k) * phi_i^{'(l)}) for all l = 1..L // + sum(omega_j^(k) * sigma_{-1} * pi_i^{j)) for all j = 1..256 +// TODO(junochiu): check if it make sense to solve the too many argument issue +#[allow(clippy::too_many_arguments)] pub fn compute_aggr_ct_constraint_phi( - phi_constraint_ct: &Vec>>, - pai: &Vec>>, + phi_constraint_ct: &[Vec>], + pai: &[Vec>], size_k: Zq, size_r: Zq, constraint_num_l: Zq, deg_bound_d: Zq, size_n: Zq, double_lambda: Zq, - psi: &Vec>, - omega: &Vec>, + psi: &[Vec], + omega: &[Vec], ) -> Vec>> { let phi_ct_aggr: Vec>> = (0..size_k.value()) .map(|k| { @@ -127,12 +122,12 @@ pub fn compute_aggr_ct_constraint_phi( // 4.3.3 aggregation: calculate b^{''(k)} = sum(a_ij^{''(k)} * ) + sum() pub fn compute_aggr_ct_constraint_b( - a_ct_aggr: &Vec>>, - phi_ct_aggr: &Vec>>, + a_ct_aggr: &[Vec>], + phi_ct_aggr: &[Vec>], size_k: Zq, size_r: Zq, deg_bound_d: Zq, - witness_s: &Vec>, + witness_s: &[Vec], ) -> Vec { (0..size_k.value()) .map(|k| { @@ -194,12 +189,14 @@ pub fn compute_aggr_constraint_a( } // aggregation: phi_i = sum(alpha_k * phi_i) + sum(beta_k * phi_i^{''(k)}) +// TODO(junochiu): check if it make sense to solve the too many argument issue +#[allow(clippy::too_many_arguments)] pub fn compute_aggr_constraint_phi( - phi_constraint: &Vec>>, - phi_ct_aggr: &Vec>>, + phi_constraint: &[Vec>], + phi_ct_aggr: &[Vec>], constraint_num_k: Zq, - alpha: &Vec, - beta: &Vec, + alpha: &[PolynomialRing], + beta: &[PolynomialRing], size_r: Zq, size_n: Zq, deg_bound_d: Zq, @@ -257,8 +254,8 @@ pub fn compute_aggr_constraint_phi( // aggregation: b_i = sum(alpha_k * b^(k)) + sum(beta_k * b^{''(k)}) pub fn compute_aggr_constraint_b( - b_constraint: &Vec, - b_ct_aggr: &Vec, + b_constraint: &[PolynomialRing], + b_ct_aggr: &[PolynomialRing], constraint_num_k: Zq, alpha: &[PolynomialRing], beta: &[PolynomialRing], @@ -312,6 +309,11 @@ pub fn check_aggr_relation( #[cfg(test)] mod tests { use super::*; + use crate::core::{ + constraint::calculate_b_constraint, gaussian_generator::generate_gaussian_distribution, + }; + use algebra::utils::generate_random_polynomial_ring; + use rand::Rng; #[test] fn test_aggr_relation_full_example() { let size_r = Zq::new(3); // r: Number of witness elements diff --git a/labrador/src/core/conjugation_automorphism.rs b/labrador/src/core/conjugation_automorphism.rs index 2d24421..e852c8a 100644 --- a/labrador/src/core/conjugation_automorphism.rs +++ b/labrador/src/core/conjugation_automorphism.rs @@ -1,4 +1,4 @@ -use algebra::{polynomial_ring::PolynomialRing, utils::inner_product_zq_vector, zq::Zq}; +use algebra::{polynomial_ring::PolynomialRing, zq::Zq}; // Conjugation Automorphism σ_{-1} // for polynomial ring a = 1+2x+3x^2, since x^64 = -1, apply this method to a, will get 1+2*(Zq.modulus()-1) * x^(64-1) +3*(Zq.modulus()-1) * x^(64-2) @@ -32,8 +32,8 @@ pub fn conjugation_automorphism(poly: &PolynomialRing) -> PolynomialRing { #[cfg(test)] mod tests { - use super::*; + use algebra::utils::inner_product_zq_vector; #[test] fn test_conjugation_automorphism() { // Create example PolynomialRings a and b diff --git a/labrador/src/core/decompose.rs b/labrador/src/core/decompose.rs index 277fd90..8d7abf8 100644 --- a/labrador/src/core/decompose.rs +++ b/labrador/src/core/decompose.rs @@ -1,4 +1,3 @@ -use crate::core::aggregation::*; use algebra::{polynomial_ring::PolynomialRing, zq::Zq}; // convert number to basis // 42 = 0 * 2^7 + 1 * 2^6 + 0 * 2^5 + 1 * 2^4 + 0 * 2^3 + 1 * 2^2 + 0 * 2^1 + 0 * 2^0 @@ -49,7 +48,7 @@ pub fn poly_vec_decompose_to_basis( } pub fn poly_matrix_decompose_to_basis( - poly: &Vec>, + poly: &[Vec], basis: Zq, digits: Zq, ) -> Vec>>> { @@ -59,7 +58,9 @@ pub fn poly_matrix_decompose_to_basis( } // TODO(junochiu): check where best to put this function / any renaming needed +// TODO(junochiu): this function is giving error when applying changes to fix ptr_arg, debug needed // aggregate basis form of a vector of PolynomialRing +#[allow(clippy::ptr_arg)] pub fn aggregate_poly_vec_basis_form( poly_basis_form: &Vec>>, ) -> Vec> { @@ -82,7 +83,7 @@ pub fn aggregate_poly_vec_basis_form( // TODO(junochiu): check where best to put this function / any renaming needed pub fn poly_matrix_decompose_and_aggregate( - poly: &Vec>, + poly: &[Vec], basis: Zq, digits: Zq, ) -> Vec>> { @@ -98,7 +99,7 @@ pub fn poly_matrix_decompose_and_aggregate( // TODO(junochiu): check where best to put this function / any renaming needed pub fn poly_vec_decompose_and_aggregate( - poly: &Vec, + poly: &[PolynomialRing], basis: Zq, digits: Zq, ) -> Vec> { diff --git a/labrador/src/core/outer_commitment.rs b/labrador/src/core/outer_commitment.rs index 73bc8b1..abdeb5a 100644 --- a/labrador/src/core/outer_commitment.rs +++ b/labrador/src/core/outer_commitment.rs @@ -7,6 +7,8 @@ use algebra::{PolynomialRing, RqMatrix, Zq}; // B_ik * t_i^(k): Rq^{kappa1} // First summation: ∑ B_ik * t_i^(k), 1 ≤ i ≤ r, 0 ≤ k ≤ t1−1 // Initialize u1 with zeros with size kappa1, each element is a polynomial ring +// TODO(junochiu): to check if it make sense to solve the too many argument issue +#[allow(clippy::too_many_arguments)] pub fn calculate_outer_comm_u1( b_matrix: &[Vec], c_matrix: &[Vec>], diff --git a/labrador/src/example/main.rs b/labrador/src/example/main.rs index ece7349..a7107ad 100644 --- a/labrador/src/example/main.rs +++ b/labrador/src/example/main.rs @@ -1,5 +1,3 @@ -use labrador::prover; - // run with profiler // // cargo run --example main --features profiler diff --git a/labrador/src/prover.rs b/labrador/src/prover.rs index 8ed62b8..6fb8884 100644 --- a/labrador/src/prover.rs +++ b/labrador/src/prover.rs @@ -2,10 +2,8 @@ use crate::core::{ aggregation::*, conjugation_automorphism::conjugation_automorphism, constraint::*, decompose::*, gaussian_generator::generate_gaussian_distribution, norm::*, outer_commitment::*, }; -use crate::setup::setup; use crate::st::St; use crate::tr::Tr; -use crate::verifier::verify; use algebra::{ polynomial_ring::PolynomialRing, rq_matrix::RqMatrix, @@ -19,7 +17,7 @@ use algebra::{ use profiler_macro::time_profiler; use rand::Rng; -#[time_profiler()] +#[time_profiler] pub fn prove( a_matrix: &RqMatrix, b_matrix: &[Vec], @@ -516,12 +514,14 @@ pub fn prove( g, h, }; - return (st, tr); + (st, tr) } #[cfg(test)] mod tests { use super::*; + use crate::setup::setup; + use crate::verifier::verify; use std::vec; #[test] diff --git a/labrador/src/verifier.rs b/labrador/src/verifier.rs index 0a9f909..2501ec8 100644 --- a/labrador/src/verifier.rs +++ b/labrador/src/verifier.rs @@ -10,7 +10,8 @@ use profiler_macro::time_profiler; // 2. generate from V: [PI_i, psi^(k), omega^(k), vec, vec, c_i] // What are sent to the verifier? // [u1, p, b^{''(k)},u2, z, t_i, g_ij, h_ij] -#[time_profiler()] + +#[time_profiler] pub fn verify( st: St, tr: Tr, @@ -20,13 +21,13 @@ pub fn verify( d_matrix: &[Vec>], ) { // same parameters as in the prover - let size_r = Zq::new(3); // r: Number of witness elements + let _size_r = Zq::new(3); // r: Number of witness elements let size_n = Zq::new(5); // n let basis = Zq::new(10); let digits = Zq::new(3); // t1 let t1 = digits; let t2 = digits; - let kappa = Zq::new(3); // Example size + let _kappa = Zq::new(3); // Example size let kappa1 = Zq::from(5); let kappa2 = Zq::from(5); let lambda = Zq::new(128); @@ -41,13 +42,13 @@ pub fn verify( b_constraint, a_constraint_ct, phi_constraint_ct, - b_constraint_ct, + b_constraint_ct: _, } = st; let Tr { u1, pai, - p, + p: _, psi, omega, b_ct_aggr, From d103d07fc19473803b20090e300d5676e5bced67 Mon Sep 17 00:00:00 2001 From: Junochiu Date: Thu, 26 Dec 2024 11:57:05 +0800 Subject: [PATCH 7/9] refactor: struct renaming --- labrador/src/lib.rs | 4 ++-- labrador/src/prover.rs | 10 +++++----- labrador/src/{st.rs => statement.rs} | 4 ++-- labrador/src/{tr.rs => transcript.rs} | 2 +- labrador/src/verifier.rs | 12 ++++++------ 5 files changed, 16 insertions(+), 16 deletions(-) rename labrador/src/{st.rs => statement.rs} (92%) rename labrador/src/{tr.rs => transcript.rs} (97%) diff --git a/labrador/src/lib.rs b/labrador/src/lib.rs index fdc9d9d..d98b4f7 100644 --- a/labrador/src/lib.rs +++ b/labrador/src/lib.rs @@ -1,6 +1,6 @@ pub mod core; pub mod prover; pub mod setup; -pub mod st; -pub mod tr; +pub mod statement; +pub mod transcript; pub mod verifier; diff --git a/labrador/src/prover.rs b/labrador/src/prover.rs index 6fb8884..90d0369 100644 --- a/labrador/src/prover.rs +++ b/labrador/src/prover.rs @@ -2,8 +2,8 @@ use crate::core::{ aggregation::*, conjugation_automorphism::conjugation_automorphism, constraint::*, decompose::*, gaussian_generator::generate_gaussian_distribution, norm::*, outer_commitment::*, }; -use crate::st::St; -use crate::tr::Tr; +use crate::statement::Statement; +use crate::transcript::Transcript; use algebra::{ polynomial_ring::PolynomialRing, rq_matrix::RqMatrix, @@ -23,7 +23,7 @@ pub fn prove( b_matrix: &[Vec], c_matrix: &[Vec>], d_matrix: &[Vec>], -) -> (St, Tr) { +) -> (Statement, Transcript) { // s is a vector of size r. each s_i is a PolynomialRing with n coefficients let size_r = Zq::new(3); // r: Number of witness elements let size_n = Zq::new(5); // n @@ -490,7 +490,7 @@ pub fn prove( assert_eq!(sum_phi_i_z_c_i * Zq::from(2), sum_h_ij_c_i_c_j); println!("Prover: Send amortized proof"); println!("Prover is finished"); - let st = St { + let st = Statement { a_constraint, phi_constraint, b_constraint, @@ -498,7 +498,7 @@ pub fn prove( phi_constraint_ct, b_constraint_ct, }; - let tr = Tr { + let tr = Transcript { u1, pai, p, diff --git a/labrador/src/st.rs b/labrador/src/statement.rs similarity index 92% rename from labrador/src/st.rs rename to labrador/src/statement.rs index c49be6e..765b1d6 100644 --- a/labrador/src/st.rs +++ b/labrador/src/statement.rs @@ -1,6 +1,6 @@ use algebra::{polynomial_ring::PolynomialRing, zq::Zq}; -// statement -pub struct St { + +pub struct Statement { pub a_constraint: Vec>>, pub phi_constraint: Vec>>, pub b_constraint: Vec, diff --git a/labrador/src/tr.rs b/labrador/src/transcript.rs similarity index 97% rename from labrador/src/tr.rs rename to labrador/src/transcript.rs index 6a0e274..f2c93c8 100644 --- a/labrador/src/tr.rs +++ b/labrador/src/transcript.rs @@ -1,5 +1,5 @@ use algebra::{polynomial_ring::PolynomialRing, zq::Zq}; -pub struct Tr { +pub struct Transcript { pub u1: Vec, // Replace with the actual type pub pai: Vec>>, // Replace with the actual type pub p: Vec, // Replace with the actual type diff --git a/labrador/src/verifier.rs b/labrador/src/verifier.rs index 2501ec8..23f1d43 100644 --- a/labrador/src/verifier.rs +++ b/labrador/src/verifier.rs @@ -1,7 +1,7 @@ // src/verifier.rs use crate::core::{aggregation::*, decompose::*, norm::*, outer_commitment::*}; -use crate::st::St; -use crate::tr::Tr; +use crate::statement::Statement; +use crate::transcript::Transcript; use algebra::{polynomial_ring::PolynomialRing, rq_matrix::RqMatrix, utils::*, zq::Zq}; use profiler_macro::time_profiler; @@ -13,8 +13,8 @@ use profiler_macro::time_profiler; #[time_profiler] pub fn verify( - st: St, - tr: Tr, + st: Statement, + tr: Transcript, a_matrix: &RqMatrix, b_matrix: &[Vec], c_matrix: &[Vec>], @@ -36,7 +36,7 @@ pub fn verify( let deg_bound_d = Zq::new(8); // random polynomial degree bound let new_beta = Zq::new(250); // Example value for beta - let St { + let Statement { a_constraint, phi_constraint, b_constraint, @@ -45,7 +45,7 @@ pub fn verify( b_constraint_ct: _, } = st; - let Tr { + let Transcript { u1, pai, p: _, From 51291c181c91ae57a89b6c782cdfb0f400543d44 Mon Sep 17 00:00:00 2001 From: Junochiu Date: Thu, 26 Dec 2024 12:17:09 +0800 Subject: [PATCH 8/9] chore: trigger testing ci for all branches --- .github/workflows/ci.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2f0d566..a271046 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,8 +4,6 @@ on: push: branches: [main] pull_request: - branches: [main] - env: CARGO_TERM_COLOR: always @@ -41,7 +39,7 @@ jobs: toolchain: $(cat rust-toolchain) components: rustfmt, clippy - - name: Run clippy + - name: Run clippy run: cargo clippy --all-features --all-targets -- -D warnings cargo-fmt: @@ -56,5 +54,5 @@ jobs: toolchain: $(cat rust-toolchain) components: rustfmt, clippy - - name: Run rustfmt + - name: Run rustfmt run: cargo fmt --all --check From ce8d7854d14ecde90d2f31599a710e23a90761c6 Mon Sep 17 00:00:00 2001 From: "PinHao, Chen" Date: Thu, 26 Dec 2024 14:19:43 +0800 Subject: [PATCH 9/9] fix: remove redundant truncate in polynomial reduction The second `truncate(Self::DEGREE_BOUND)` call in the polynomial reduction step is unnecessary. --- algebra/src/polynomial_ring.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/algebra/src/polynomial_ring.rs b/algebra/src/polynomial_ring.rs index 67a3e73..28e0afa 100644 --- a/algebra/src/polynomial_ring.rs +++ b/algebra/src/polynomial_ring.rs @@ -43,7 +43,6 @@ impl PolynomialRing { front[i] += overflow * modulus_minus_one; } result_coefficients.truncate(Self::DEGREE_BOUND); - result_coefficients.truncate(Self::DEGREE_BOUND); } PolynomialRing { coefficients: result_coefficients,