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 \\ 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); +} diff --git a/zeromorph/zeromorph.md b/zeromorph/zeromorph.md index ad77bc2..d7751e3 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}]]_n=\Phi_{n-k}(X^{2^k})\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