diff --git a/bi-kzg/script/lagrange.sage b/bi-kzg/script/lagrange.sage index 57e4c943..999ed298 100644 --- a/bi-kzg/script/lagrange.sage +++ b/bi-kzg/script/lagrange.sage @@ -60,4 +60,53 @@ for i in range(n*m): print(res - f) print() for t in bases: - print(t(5, 7)) \ No newline at end of file + print(t(5, 7)) + + + +#P. = PolynomialRing(ZZ) +f = P((x+1)*(y^3+1)) + +f_lag = [] +for o1 in omega1_powers: + for o0 in omega0_powers: + print(o0, o1) + f_lag.append(f(o0, o1)) +print(f) +print(f_lag) + +g = f/P(y+1) +g_lag = [] +for o1 in omega1_powers: + for o0 in omega0_powers: + print(o0, o1) + g_lag.append(g(o0, o1)) +print(g) +print(g_lag) + +t = P(y+1) +t_lag = [] +for o1 in omega1_powers: + for o0 in omega0_powers: + print(o0, o1) + t_lag.append(t(o0, o1)) +print(t) +print(t_lag) + +for i in range(8): + print(f_lag[i] - g_lag[i] *t_lag[i]) + +g_rec = P(0) +for i in range(8): + g_rec += bases[i] * g_lag[i] +print(g_rec) + +f_rec = P(0) +for i in range(8): + f_rec += bases[i] * f_lag[i] +print(f_rec) + +t_rec = P(0) +for i in range(8): + t_rec += bases[i] * t_lag[i] +print(t_rec) \ No newline at end of file diff --git a/bi-kzg/src/bi_kzg.rs b/bi-kzg/src/bi_kzg.rs index 6fb8b42c..c2662e05 100644 --- a/bi-kzg/src/bi_kzg.rs +++ b/bi-kzg/src/bi_kzg.rs @@ -14,6 +14,7 @@ use halo2curves::group::Group; use halo2curves::pairing::{MillerLoopResult, MultiMillerLoop}; use halo2curves::pasta::pallas::Scalar; use halo2curves::CurveAffine; +use itertools::Itertools; use rand::Rng; use rand::RngCore; @@ -85,7 +86,7 @@ where println!("start to compute the scalars"); // computes the vector of L_i^N(tau_0) * L_j^M(tau_1) for i in 0..supported_n and j in 0..supported_m - let (scalars, powers_of_tau_0, lagrange_scalars) = { + let (scalars, f_x_b_scalars, lagrange_scalars) = { let powers_of_omega_0 = powers_of_field_elements(&omega_0, supported_n); let powers_of_tau_0 = powers_of_field_elements(&tau_0, supported_n); let lagrange_tau_0 = lagrange_coefficients(&powers_of_omega_0, &tau_0); @@ -95,16 +96,18 @@ where let scalars = tensor_product_parallel(&powers_of_tau_0, &powers_of_tau_1); let lagrange_scalars = tensor_product_parallel(&lagrange_tau_0, &lagrange_tau_1); - // let mut f_x_b_scalars = lagrange_tau_0.clone(); - // powers_of_tau_1.iter().skip(1).for_each(|bi| { - // f_x_b_scalars - // .iter_mut() - // .zip(lagrange_tau_0.iter()) - // .for_each(|(fi, li)| *fi += *bi * *li); - // }); + let mut f_x_b_scalars = lagrange_tau_0.clone(); + powers_of_tau_1.iter().skip(1).for_each(|bi| { + f_x_b_scalars + .iter_mut() + .zip(lagrange_tau_0.iter()) + .for_each(|(fi, li)| *fi += *bi * *li); + }); + + println!("f_x_b_scalars: {:?}", f_x_b_scalars); - // (scalars, f_x_b_scalars, lagrange_scalars) - (scalars, powers_of_tau_0, lagrange_scalars) + (scalars, f_x_b_scalars, lagrange_scalars) + // (scalars, powers_of_tau_0, lagrange_scalars) }; println!("lagrange scalars: {:?} ", lagrange_scalars); @@ -129,12 +132,12 @@ where println!("start to compute the lagrange bases"); - let powers_of_tau_0 = { + let f_x_b_scalars = { let mut proj_bases = vec![E::G1::identity(); supported_n]; parallelize(&mut proj_bases, |g, start| { for (idx, g) in g.iter_mut().enumerate() { let offset = start + idx; - *g = g1 * powers_of_tau_0[offset]; + *g = g1 * f_x_b_scalars[offset]; } }); @@ -170,13 +173,13 @@ where affine_bases }; - assert_eq!(coeff_bases[..supported_n], powers_of_tau_0); + // assert_eq!(coeff_bases[..supported_n], f_x_b_scalars); BiKZGSRS { tau_0, tau_1, powers_of_g: coeff_bases, - // powers_of_tau_0: powers_of_tau_0, + f_x_b_scalars: f_x_b_scalars, powers_of_g_lagrange_over_both_roots: lagrange_bases, h: E::G2Affine::generator(), tau_0_h: (E::G2Affine::generator() * tau_0).into(), @@ -247,18 +250,85 @@ where polynomial: &Self::Polynomial, point: &Self::Point, ) -> (Self::Proof, Self::Evaluation) { - let pi_0 = { + let (pi_0, f_x_b) = { let f_x_b = polynomial.evaluate_y(&point.1); let q_0_x_b = univariate_quotient(&f_x_b, &point.1); - best_multiexp( + let pi_0 = best_multiexp( &q_0_x_b, + // prover_param.borrow().f_x_b_scalars.as_ref(), prover_param.borrow().powers_of_g[..polynomial.degree_0].as_ref(), ) - .to_affine() + .to_affine(); + (pi_0, f_x_b) }; + // fixme + let tau_0 = prover_param.borrow().tau_0; + let tau_1 = prover_param.borrow().tau_1; + let a = point.0; + let b = point.1; + let c = polynomial.evaluate(&tau_0, &tau_1); + let u = polynomial.evaluate(&a, &b); + // let u_prime = polynomial.evaluate(&tau_0, &b); let pi_1 = { + let mut t = polynomial.clone(); + // t.coefficients[0] -= u_prime; + t.coefficients + .iter_mut() + .take(polynomial.degree_0) + .zip_eq(f_x_b.iter()) + .for_each(|(c, f)| *c -= f); + let coeffs = t.lagrange_coeffs(); + + let mut divisor = vec![E::Fr::from(0); polynomial.degree_0 * polynomial.degree_1]; + divisor[0] = -point.1; + divisor[polynomial.degree_0] = E::Fr::ONE; + let divisor = + BivariatePolynomial::new(divisor, polynomial.degree_0, polynomial.degree_1); + + // let omega = E::Fr::ROOT_OF_UNITY; + // let omega_1 = omega.pow_vartime(&[(1 << E::Fr::S) / polynomial.degree_1 as u64]); + // let divisor = fft_slow(divisor.as_ref(), &omega_1); + let divisor = divisor.lagrange_coeffs(); + + // let omega = E::Fr::ROOT_OF_UNITY; + // let omega_1 = omega.pow_vartime(&[(1 << E::Fr::S) / polynomial.degree_1 as u64]); + // let powers_of_omega_1 = powers_of_field_elements(&omega_1, polynomial.degree_1); + + // todo: batch invert + let y_minus_a_inv_lag = divisor + .iter() + .map(|o| { + if o.is_zero_vartime() { + // E::Fr::ZERO + panic!("not invertible") + } else { + o.invert().unwrap() + } + }) + .collect::>(); + // let mut q_1_x_y = vec![]; + // for i in 0..polynomial.degree_0 { + // for j in 0..polynomial.degree_1{ + // q_1_x_y.push((coeffs[j*polynomial.degree_0 + i] - f_x_b[i]) * y_minus_a_inv_lag[j]); + // } + // } + let q_1_x_y = coeffs + .iter() + .zip_eq(y_minus_a_inv_lag.iter()) + .map(|(c, y)| (*c) * *y) + .collect::>(); + + best_multiexp( + &q_1_x_y, + prover_param + .borrow() + // .powers_of_g + .powers_of_g_lagrange_over_both_roots + .as_ref(), + ) + .to_affine() // // let domain = Domain::::new_for_size(prover_param.borrow().powers_of_g_lagrange_over_both_roots.len() as u64).unwrap(); // let bases = prover_param.borrow().powers_of_g_lagrange_over_both_roots.as_slice(); @@ -292,14 +362,7 @@ where // } }; - // fixme - let tau_0 = prover_param.borrow().tau_0; - let tau_1 = prover_param.borrow().tau_1; - let a = point.0; - let b = point.1; - let c = polynomial.evaluate(&tau_0, &tau_1); - - let u = polynomial.evaluate(&a, &b); + // let u = polynomial.evaluate(&a, &b); let u_prime = polynomial.evaluate(&tau_0, &b); let f_tau0_b = polynomial.evaluate(&tau_0, &b); @@ -310,7 +373,7 @@ where let q_1 = (c - u_prime) * ((tau_1 - b).invert().unwrap()); println!("here2"); - let proof = BiKZGProof { + let proof = BiKZGProof:: { pi0: (prover_param.borrow().powers_of_g[0] * q_0).into(), pi1: (prover_param.borrow().powers_of_g[0] * q_1).into(), }; @@ -321,6 +384,12 @@ where assert_eq!(t0 + t1, right, "t0 + t1 != right"); assert_eq!(pi_0, proof.pi0, "pi0 != pi_0"); + assert_eq!(pi_1, proof.pi1, "pi1 != pi_1"); + + let proof2 = BiKZGProof:: { + pi0: pi_0, + pi1: pi_1, + }; (proof, u) } diff --git a/bi-kzg/src/poly.rs b/bi-kzg/src/poly.rs index 2deed6bb..8f4730f0 100644 --- a/bi-kzg/src/poly.rs +++ b/bi-kzg/src/poly.rs @@ -78,11 +78,11 @@ impl BivariatePolynomial { }; let powers_of_omega_0 = powers_of_field_elements(&omega_0, self.degree_0); let powers_of_omega_1 = powers_of_field_elements(&omega_1, self.degree_1); - println!( - "omega len {} {}", - powers_of_omega_0.len(), - powers_of_omega_1.len() - ); + // println!( + // "omega len {} {}", + // powers_of_omega_0.len(), + // powers_of_omega_1.len() + // ); // Todo! Optimize me. This is not efficient. let mut res = vec![]; @@ -91,8 +91,8 @@ impl BivariatePolynomial { res.push(self.evaluate(omega_0_power, omega_1_power)); } } - - println!("res: {:?}", res); + // println!("powers_of_omega_1: {:?}", powers_of_omega_1); + // println!("res: {:?}", res); res } @@ -156,6 +156,20 @@ pub(crate) fn univariate_quotient(poly: &[F], point: &F) -> Vec(coeffs: &[F], omega: &F) -> Vec { +// let n = coeffs.len(); +// let mut res = vec![F::ZERO; n]; +// for i in 0..n { +// let mut omega_i = F::ONE; +// for j in 0..n { +// res[i] += omega_i * coeffs[j]; +// omega_i *= omega; +// } +// } +// res +// } + // /// For x in points, compute the Lagrange coefficients at x given the roots. // /// `L_{i}(x) = \prod_{j \neq i} \frac{x - r_j}{r_i - r_j}`` // pub(crate) fn lagrange_coefficients(roots: &[F], points: &[F]) -> Vec { @@ -305,6 +319,22 @@ mod tests { ); let eval_at_y = poly.evaluate_y(&Fr::from(10u64)); assert_eq!(eval_at_y, vec![Fr::from(7531u64), Fr::from(8642u64)]); + + let poly = BivariatePolynomial::new( + vec![ + Fr::from(1u64), + Fr::from(0u64), + Fr::from(1u64), + Fr::from(0u64), + Fr::from(0u64), + Fr::from(0u64), + Fr::from(0u64), + Fr::from(0u64), + ], + 2, + 4, + ); + println!("poly: {:?}", poly.lagrange_coeffs()); } #[test] @@ -351,29 +381,68 @@ mod tests { } } - // #[test] - // fn test_lagrange_coeffs() { - // let poly = BivariatePolynomial::new( - // vec![ - // Fr::from(1u64), - // Fr::from(2u64), - // Fr::from(3u64), - // Fr::from(4u64), - // Fr::from(5u64), - // Fr::from(10u64), - // Fr::from(15u64), - // Fr::from(20u64), - // ], - // 4, - // 2, - // ); - - // let lagrange_coeffs = poly.lagrange_coeffs(); - // println!("lag: {:?}", lagrange_coeffs); - // assert_eq!(lagrange_coeffs.len(), 8); - // assert_eq!(lagrange_coeffs[0], Fr::from(1u64)); - // assert_eq!(lagrange_coeffs[1], Fr::from(2u64)); - // assert_eq!(lagrange_coeffs[2], Fr::from(3u64)); - // assert_eq!(lagrange_coeffs[3], Fr::from(4u64)); - // } + #[test] + fn test_lagrange_coeffs() { + let poly = BivariatePolynomial::new( + vec![ + Fr::from(1u64), + Fr::from(2u64), + Fr::from(3u64), + Fr::from(4u64), + Fr::from(5u64), + Fr::from(6u64), + Fr::from(7u64), + Fr::from(8u64), + ], + 2, + 4, + ); + + let lagrange_coeffs = poly.lagrange_coeffs(); + + // From sage script + // poly_lag_coeff = [ + // 0x0000000000000000000000000000000000000000000000000000000000000024, + // 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffffd, + // 0x00000000000000059e26bcea0d48bac65a4e1a8be2302529067f891b047e4e50, + // 0x0000000000000000000000000000000000000000000000000000000000000000, + // 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffff9, + // 0x0000000000000000000000000000000000000000000000000000000000000000, + // 0x30644e72e131a0241a2988cc74389d96cde5cdbc97894b683d626c78eb81b1a1, + // 0x0000000000000000000000000000000000000000000000000000000000000000] + println!("lag: {:?}", lagrange_coeffs); + assert_eq!(lagrange_coeffs.len(), 8); + assert_eq!( + format!("{:?}", lagrange_coeffs[0]), + "0x0000000000000000000000000000000000000000000000000000000000000024" + ); + assert_eq!( + format!("{:?}", lagrange_coeffs[1]), + "0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffffd" + ); + assert_eq!( + format!("{:?}", lagrange_coeffs[2]), + "0x00000000000000059e26bcea0d48bac65a4e1a8be2302529067f891b047e4e50" + ); + assert_eq!( + format!("{:?}", lagrange_coeffs[3]), + "0x0000000000000000000000000000000000000000000000000000000000000000" + ); + assert_eq!( + format!("{:?}", lagrange_coeffs[4]), + "0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffff9" + ); + assert_eq!( + format!("{:?}", lagrange_coeffs[5]), + "0x0000000000000000000000000000000000000000000000000000000000000000" + ); + assert_eq!( + format!("{:?}", lagrange_coeffs[6]), + "0x30644e72e131a0241a2988cc74389d96cde5cdbc97894b683d626c78eb81b1a1" + ); + assert_eq!( + format!("{:?}", lagrange_coeffs[7]), + "0x0000000000000000000000000000000000000000000000000000000000000000" + ); + } } diff --git a/bi-kzg/src/structs.rs b/bi-kzg/src/structs.rs index 745bcec1..f6f2999e 100644 --- a/bi-kzg/src/structs.rs +++ b/bi-kzg/src/structs.rs @@ -30,8 +30,8 @@ pub struct BiKZGSRS { /// ..., g_1^{\tau_0^N\tau_1^M} /// ) pub powers_of_g: Vec, - // /// g in lagrange form over omega_0 - // pub powers_of_tau_0: Vec, + /// g in lagrange form over omega_0 + pub f_x_b_scalars: Vec, /// g in lagrange form over omega_0 and omega_1 pub powers_of_g_lagrange_over_both_roots: Vec, /// The generator of G2. @@ -78,8 +78,8 @@ pub struct BiKZGProof { pub pi1: E::G1Affine, } -impl From> for BiKZGVerifierParam { - fn from(srs: BiKZGSRS) -> Self { +impl From<&BiKZGSRS> for BiKZGVerifierParam { + fn from(srs: &BiKZGSRS) -> Self { Self { g: srs.powers_of_g[0], h: srs.h, diff --git a/bi-kzg/src/tests.rs b/bi-kzg/src/tests.rs index f6193c03..5f881c68 100644 --- a/bi-kzg/src/tests.rs +++ b/bi-kzg/src/tests.rs @@ -1,9 +1,12 @@ use ark_std::test_rng; -use halo2curves::bn256::{Bn256, Fr}; +use halo2curves::{ + bn256::{Bn256, Fr}, + ff::Field, +}; use crate::{ bi_kzg::BiKZG, pcs::PolynomialCommitmentScheme, poly::lagrange_coefficients, - util::tensor_product_parallel, BivariatePolynomial, + util::tensor_product_parallel, BiKZGVerifierParam, BivariatePolynomial, }; #[test] @@ -12,7 +15,7 @@ fn test_bi_kzg_e2e() { let n = 2; let m = 4; let srs = BiKZG::::gen_srs_for_testing(&mut rng, n, m); - + let vk = BiKZGVerifierParam::::from(&srs); let poly = BivariatePolynomial::new( vec![ Fr::from(1u64), @@ -39,15 +42,25 @@ fn test_bi_kzg_e2e() { let commit = BiKZG::::commit(&srs, &poly); let (proof, eval) = BiKZG::::open(&srs, &poly, &(x, y)); - assert!(BiKZG::::verify( - &srs.into(), - &commit, - &(x, y), - &eval, - &proof - )); + assert!(BiKZG::::verify(&vk, &commit, &(x, y), &eval, &proof)); + + for n in [2, 4, 8, 16] { + for m in [2, 4, 8, 16] { + println!("m: {}, n: {}", m, n); + let srs = BiKZG::::gen_srs_for_testing(&mut rng, n, m); + let vk = BiKZGVerifierParam::::from(&srs); + for _ in 0..10 { + let poly = BivariatePolynomial::::random(&mut rng, n, m); + + let x = Fr::random(&mut rng); + let y = Fr::random(&mut rng); - assert!(false) + let commit = BiKZG::::commit(&srs, &poly); + let (proof, eval) = BiKZG::::open(&srs, &poly, &(x, y)); + assert!(BiKZG::::verify(&vk, &commit, &(x, y), &eval, &proof)); + } + } + } } #[test]