From 0c46d14f37a64963290b49cbc0ca0d6e8d1c8d14 Mon Sep 17 00:00:00 2001 From: Alok Kumar Date: Fri, 13 Dec 2024 04:07:40 +0530 Subject: [PATCH 1/4] Update zeromorph --- zeromorph/zeromorph.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/zeromorph/zeromorph.md b/zeromorph/zeromorph.md index d30d6df..a98137e 100644 --- a/zeromorph/zeromorph.md +++ b/zeromorph/zeromorph.md @@ -28,8 +28,7 @@ $$ \tilde{f}(X_0, X_1, X_2) = f_0 + f_1X_0 + f_2X_1 + f_3X_2 + f_4X_0X_1 + f_5X_0X_2 + f_6X_1X_2 + f_7X_0X_1X_2 $$ -where $(f_0, f_1, \ldots, f_7)$ is the coefficient vector of the MLE polynomial. Note that because MLE polynomials belong to multivariate polynomials, any representation needs to determine the ordering of terms in the polynomial in advance. In this article and subsequent discussions, we will base on Lexicographic Order. - +where $(f_0, f_1, \ldots, f_7)$ is the coefficient vector of the MLE polynomial. Note that because MLE polynomials belong to multivariate polynomials, any representation requires determining the ordering of terms in the polynomial in advance. In this article and subsequent discussions, we will base our approach on Lexicographic Order. For the "point value form" representation of MLE polynomials, we can define it as: $$ @@ -83,7 +82,7 @@ $$ \mathsf{cm}(\hat{f}) = 2\cdot [1]_1 + 2\cdot [\tau]_1 + 3\cdot [\tau^2]_1 + 4\cdot [\tau^3]_1 $$ -In the following, we will use the symbol $[[\tilde{f}]]$ to represent the Univariate polynomial corresponding to the mapping of the MLE polynomial $\tilde{f}$. +In the following sections, we will use the symbol $[[\tilde{f}]]$ to represent the Univariate polynomial corresponding to the mapping of the MLE polynomial $\tilde{f}$. ### Polynomial Mapping @@ -171,7 +170,7 @@ And $X_2\cdot \tilde{c}(X_0, X_1)$ is also an MLE polynomial, with dimension 3. ![alt text](img/image-2.png) -This is easy to explain because when $X_2=0$, the overall polynomial value is zero, so the values at the vertices of the square formed by $X_0, X_1$ are all zero. When $X_2=1$, the polynomial $X_2\cdot \tilde{c}(X_0, X_1)$ equals $\tilde{c}(X_0, X_1)$. Therefore, the values at the vertices of the square plane where $X_2=1$ are equal to $\tilde{c}(X_0, X_1)$. Furthermore, we can have this conclusion: +This is easy to explain because when $X_2=0$, the overall polynomial value is zero, so the values at the vertices of the square formed by $X_0, X_1$ are all zero. When $X_2=1$, the polynomial $X_2\cdot \tilde{c}(X_0, X_1)$ equals $\tilde{c}(X_0, X_1)$. Therefore, the values at the vertices of the square plane where $X_2=1$ are equal to $\tilde{c}(X_0, X_1)$. Furthermore, we can draw the following conclusion: $$ [[X_2\cdot \tilde{c}]]_3 = X^4 \cdot [[\tilde{c}]]_2 @@ -216,8 +215,13 @@ When raising a low-dimensional MLE to a high-dimensional HyperCube, we see the p $$ \Phi_k(X^h) = 1 + X^h + X^{2h} + \ldots + X^{(2^{k}-1)h} $$ +Therefore, we can define a general relation, i.e. + +$$ +[[\tilde{c}]]_h=\Phi_k(X^h)\cdot [[\tilde{c}]]_k +$$ -Obviously, $[[\tilde{c}]]_4=\Phi_2(X^4)\cdot [[\tilde{c}]]_2$. +Consequently, it can be verified that : $[[\tilde{c}]]_4=\Phi_2(X^4)\cdot [[\tilde{c}]]_2$. ## MLE Polynomial Remainder Theorem From ea238adee9b039079b9e2f20d6e4815093266967 Mon Sep 17 00:00:00 2001 From: Alok Kumar Date: Fri, 13 Dec 2024 04:22:05 +0530 Subject: [PATCH 2/4] Update zeromorph --- zeromorph/zeromorph.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeromorph/zeromorph.md b/zeromorph/zeromorph.md index a98137e..563cd1f 100644 --- a/zeromorph/zeromorph.md +++ b/zeromorph/zeromorph.md @@ -218,7 +218,7 @@ $$ Therefore, we can define a general relation, i.e. $$ -[[\tilde{c}]]_h=\Phi_k(X^h)\cdot [[\tilde{c}]]_k +[[\tilde{c}]]_n=\Phi_{n-k}(X^{2^k})\cdot [[\tilde{c}]]_k $$ Consequently, it can be verified that : $[[\tilde{c}]]_4=\Phi_2(X^4)\cdot [[\tilde{c}]]_2$. From aa385baff9c0de9fc0bbe55a2b50dc5f7d85509e Mon Sep 17 00:00:00 2001 From: Alok Kumar Date: Fri, 13 Dec 2024 04:34:30 +0530 Subject: [PATCH 3/4] docs: correct errors in binius-01 article --- fri-binius/binius-01.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fri-binius/binius-01.md b/fri-binius/binius-01.md index 6913b6f..b29ab49 100644 --- a/fri-binius/binius-01.md +++ b/fri-binius/binius-01.md @@ -101,7 +101,7 @@ $$ Let's denote the root of $f_1(X)$ in $\mathbb{F}_{2^4}$ as $\theta$, then any element $a\in\mathbb{F}_{2^4}$ can be uniquely represented as: $$ -a = a_0 + a_1\cdot\theta + a_2\cdot\theta^2 + \cdots + a_{n-1}\cdot\theta^{n-1} +a = a_0 + a_1\cdot\theta + a_2\cdot\theta^2 + a_3\cdot\theta^3 $$ To add here, $f_1(X)$ is also a Primitive polynomial, and its root $\theta$ is also a Primitive Element of $\mathbb{F}_{2^4}$. Note that not all irreducible polynomials are Primitive polynomials, for example, $f_3(X)$ listed above is not a Primitive polynomial. @@ -217,7 +217,7 @@ $$ \begin{array}{ccccccc} \hline 0000 & 0001 & 0010 & 0011 & 0100 & 0101 & 0110 & 0111 \\ -0 & 1 & \eta & \eta+1 & \zeta & \zeta+\eta & \zeta+\eta+1 & \zeta+\eta+1 \\ +0 & 1 & \eta & \eta+1 & \zeta & \zeta+1 & \zeta+\eta & \zeta+\eta+1 \\ \hline 1000 & 1001 & 1010 & 1011 & 1100 & 1101 & 1110 & 1111 \\ \zeta\eta & \zeta\eta + 1 & \zeta\eta + \eta & \zeta\eta + \eta + 1 & \zeta\eta + \zeta & \zeta\eta + \zeta +1 & \zeta\eta+\zeta+\eta & \zeta\eta+\zeta+\eta+1 \\ From dfc6da090aa2e97685d5dab77cc4092008758fcf Mon Sep 17 00:00:00 2001 From: Alok Kumar Date: Mon, 16 Dec 2024 03:24:54 +0530 Subject: [PATCH 4/4] Initialize Zeromorph Rust implementation --- zeromorph/implementation/.gitignore | 2 + zeromorph/implementation/Cargo.toml | 12 ++++ zeromorph/implementation/src/main.rs | 87 ++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+) create mode 100644 zeromorph/implementation/.gitignore create mode 100644 zeromorph/implementation/Cargo.toml create mode 100644 zeromorph/implementation/src/main.rs diff --git a/zeromorph/implementation/.gitignore b/zeromorph/implementation/.gitignore new file mode 100644 index 0000000..a9d37c5 --- /dev/null +++ b/zeromorph/implementation/.gitignore @@ -0,0 +1,2 @@ +target +Cargo.lock diff --git a/zeromorph/implementation/Cargo.toml b/zeromorph/implementation/Cargo.toml new file mode 100644 index 0000000..1035ebd --- /dev/null +++ b/zeromorph/implementation/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "implementation" +version = "0.1.0" +edition = "2021" + +[dependencies] +ark-std = "0.4" +ark-ff = "0.4" +ark-ec = "0.4" +ark-bls12-381 = "0.4" +ark-poly = "0.4" +ark-serialize = "0.4" \ No newline at end of file diff --git a/zeromorph/implementation/src/main.rs b/zeromorph/implementation/src/main.rs new file mode 100644 index 0000000..f7f0921 --- /dev/null +++ b/zeromorph/implementation/src/main.rs @@ -0,0 +1,87 @@ +use ark_bls12_381::{Bls12_381, Fr, G1Projective, G2Projective}; +use ark_ec::{pairing::Pairing, Group}; +use ark_ff::{PrimeField, One}; +use ark_poly::{Polynomial, DenseUVPolynomial}; +use ark_poly::polynomial::univariate::DensePolynomial; +use ark_std::{vec::Vec, Zero}; + +/// We'll assume that `D` is the maximum degree for our KZG commitments. +const D: usize = 1024; // Example value, adjust as needed + +/// SRS structure for KZG commitments. +pub struct KZGSRS { + pub g1_powers: Vec, + pub g2_powers: Vec, +} + +impl KZGSRS { + /// Generate an SRS given τ. + /// Note: This is for testing and demonstration only. + pub fn generate_srs(d: usize, tau: Fr) -> Self { + // For BLS12_381: + // G1Projective::generator() and G2Projective::generator() give the base generators. + let g1 = G1Projective::generator(); + let h = G2Projective::generator(); + + let mut g1_powers = Vec::with_capacity(d + 1); + let mut g2_powers = Vec::with_capacity(d + 1); + + let mut cur_tau = Fr::one(); + for _ in 0..=d { + let g1_elem = g1.mul_bigint(cur_tau.into_bigint()); + let g2_elem = h.mul_bigint(cur_tau.into_bigint()); + g1_powers.push(g1_elem); + g2_powers.push(g2_elem); + cur_tau *= Fr::from(2u64); // Example: increment tau's power. Replace as needed. + } + + Self { g1_powers, g2_powers } + } +} + +/// A simple wrapper for a univariate polynomial in Fr. +pub struct UniPoly { + pub poly: DensePolynomial, +} + +impl UniPoly { + /// Create a polynomial from coefficients (constant term first). + pub fn from_coefficients(coeffs: Vec) -> Self { + Self { + poly: DensePolynomial::from_coefficients_vec(coeffs), + } + } + + /// Evaluate polynomial at a field element. + pub fn evaluate(&self, x: &Fr) -> Fr { + self.poly.evaluate(x) + } + + /// Degree of the polynomial. + pub fn degree(&self) -> usize { + self.poly.degree() + } +} + +/// Commitment to a polynomial using KZG: +/// cm(P) = Σ a_i * g1_powers[i], where P(x) = Σ a_i x^i. +pub fn kzg_commit(srs: &KZGSRS, poly: &UniPoly) -> G1Projective { + let coeffs = &poly.poly.coeffs; + let mut commitment = G1Projective::zero(); + for (i, &coeff) in coeffs.iter().enumerate() { + let term = srs.g1_powers[i].mul_bigint(coeff.into_bigint()); + commitment += term; + } + commitment +} + +fn main() { + let tau = Fr::from(2u64); // Just a test value + let srs = KZGSRS::::generate_srs(D, tau); + + let coeffs = vec![Fr::from(1u64), Fr::from(2u64), Fr::from(3u64)]; // P(x) = 1 + 2x + 3x² + let poly = UniPoly::from_coefficients(coeffs); + let cm = kzg_commit(&srs, &poly); + + println!("Commitment: {:?}", cm); +}