From 4ff0d092d65a4aa2fe905651bbdf3278bc2835d2 Mon Sep 17 00:00:00 2001 From: exfinen <47593166+exfinen@users.noreply.github.com> Date: Fri, 20 Oct 2023 16:40:22 +0900 Subject: [PATCH] add working pinnochio verifiable computation --- .../curves/bls12_381/pairing.rs | 13 ++- src/zk/w_trusted_setup/pinocchio/crs.rs | 8 +- .../pinocchio/pinocchio_proof.rs | 1 + .../pinocchio/pinocchio_prover.rs | 55 ++--------- .../pinocchio/pinocchio_verifier.rs | 61 ++++++------ .../w_trusted_setup/pinocchio/polynomial.rs | 96 ++++++++----------- src/zk/w_trusted_setup/pinocchio/qap.rs | 4 +- src/zk/w_trusted_setup/pinocchio/r1cs.rs | 11 --- src/zk/w_trusted_setup/pinocchio/witness.rs | 2 +- 9 files changed, 97 insertions(+), 154 deletions(-) diff --git a/src/building_block/curves/bls12_381/pairing.rs b/src/building_block/curves/bls12_381/pairing.rs index 4de4d35..657010a 100644 --- a/src/building_block/curves/bls12_381/pairing.rs +++ b/src/building_block/curves/bls12_381/pairing.rs @@ -7,9 +7,10 @@ use crate::building_block::{ rational_function::RationalFunction, }, to_biguint::ToBigUint, + zero::Zero, }; use num_bigint::BigUint; -use num_traits::Zero; +use num_traits::Zero as NumTraitsZero; pub struct Pairing { l_bits: Vec, @@ -73,6 +74,10 @@ impl Pairing { pub fn weil(&self, p1: &G1Point, p2: &G2Point) -> Fq12 { println!("Started Weil pairing"); println!("Running Miller loop G1-G2..."); + if p1 == &G1Point::zero() || p2 == &G2Point::zero() { + return Fq12::from(&1u8 as &dyn ToBigUint); + } + let num = self.calc_g1_g2(p1, p2); println!("Running Miller loop G2-G1..."); let deno = self.calc_g2_g1(p2, p1); @@ -82,7 +87,11 @@ impl Pairing { pub fn tate(&self, p1: &G1Point, p2: &G2Point) -> Fq12 { println!("Started Tate pairing"); println!("Running Miller loop G1-G2..."); - let intmed = self.calc_g1_g2(p1, p2); + if p1 == &G1Point::zero() || p2 == &G2Point::zero() { + return Fq12::from(&1u8 as &dyn ToBigUint); + } + + let intmed = self.calc_g1_g2(&p1, &p2); // apply final exponentiation println!("Applying final exponentiation..."); diff --git a/src/zk/w_trusted_setup/pinocchio/crs.rs b/src/zk/w_trusted_setup/pinocchio/crs.rs index 695d719..390d18d 100644 --- a/src/zk/w_trusted_setup/pinocchio/crs.rs +++ b/src/zk/w_trusted_setup/pinocchio/crs.rs @@ -22,6 +22,7 @@ pub struct EvaluationKeys { } pub struct VerificationKeys { + pub one_g1: G1Point, pub one: G2Point, pub e_alpha: G2Point, pub e_gamma: G2Point, @@ -51,14 +52,14 @@ impl CRS { let E1 = |n: &PrimeFieldElem| -> G1Point { g1 * n }; let E2 = |n: &PrimeFieldElem| -> G2Point { g2 * n }; - let s = &f.rand_elem(true); + let s = &f.elem(&2u8); // &f.rand_elem(true); let alpha = &f.rand_elem(true); let beta_v = &f.rand_elem(true); let beta_w = &f.rand_elem(true); let beta_y = &f.rand_elem(true); let gamma = &f.rand_elem(true); - let s_pows = &s.pow_seq(&p.max_degree); + let s_pows = &s.pow_seq(&(&p.max_degree + 5)); let mid: &Vec = &(*&p.mid_beg..*&p.num_constraints).collect(); let io: &Vec = &(1usize..*&p.mid_beg).collect(); @@ -90,7 +91,7 @@ impl CRS { let beta_y_gamma = E2(gamma) * beta_y; let t = E2(&p.t.eval_at(s)); - let const_witness = &p.witness.const_witness(); + let const_witness = &p.witness.one(); let v_0 = E1(&p.vi[0].eval_at(s)) * const_witness; let w_0 = E2(&p.wi[0].eval_at(s)) * const_witness; let y_0 = E1(&p.yi[0].eval_at(s)) * const_witness; @@ -112,6 +113,7 @@ impl CRS { let vk = VerificationKeys { one, + one_g1: E1(&f.elem(&1u8)), e_alpha, e_gamma, beta_v_gamma, diff --git a/src/zk/w_trusted_setup/pinocchio/pinocchio_proof.rs b/src/zk/w_trusted_setup/pinocchio/pinocchio_proof.rs index 0c00da5..2d36091 100644 --- a/src/zk/w_trusted_setup/pinocchio/pinocchio_proof.rs +++ b/src/zk/w_trusted_setup/pinocchio/pinocchio_proof.rs @@ -13,5 +13,6 @@ pub struct PinocchioProof { pub beta_y_mid: G1Point, pub h: G1Point, pub alpha_h: G1Point, + pub ht: G1Point, } diff --git a/src/zk/w_trusted_setup/pinocchio/pinocchio_prover.rs b/src/zk/w_trusted_setup/pinocchio/pinocchio_prover.rs index 19fda7f..0e3f018 100644 --- a/src/zk/w_trusted_setup/pinocchio/pinocchio_prover.rs +++ b/src/zk/w_trusted_setup/pinocchio/pinocchio_prover.rs @@ -68,55 +68,8 @@ impl PinocchioProver { }; let witness = Witness::new(&r1cs.witness.clone(), &tmpl.mid_beg); - let num_constraints = tmpl.constraints.len(); - //// EXPERIMENT ZONE - { - use crate::zk::w_trusted_setup::pinocchio::sparse_vec::SparseVec; - - let p_div_t = &p.divide_by(&t); - let h = match &p_div_t { - DivResult::Quotient(h) => h, - DivResult::QuotientRemainder(_) => panic!("p must be divisible by t"), - }; - - let s = &f.elem(&11u8); - - let eval = |ps: &[Polynomial], ws: &SparseVec| -> PrimeFieldElem { - let mut sum = f.elem(&0u8); - for i in 0..ps.len() { - let p = ps[i].eval_at(s); - let w = &ws[&f.elem(&i)]; - sum = sum + p * w; - } - sum - }; - - let v_0 = &qap.vi[0].eval_at(s) * witness.const_witness(); - let w_0 = &qap.wi[0].eval_at(s) * witness.const_witness(); - let y_0 = &qap.yi[0].eval_at(s) * witness.const_witness(); - - let mid_beg: usize = (&tmpl.mid_beg.e).try_into().unwrap(); - let v_io = eval(&qap.vi[1..mid_beg], &witness.io()); - let w_io = eval(&qap.wi[1..mid_beg], &witness.io()); - let y_io = eval(&qap.yi[1..mid_beg], &witness.io()); - - let v_mid = eval(&qap.vi[mid_beg..], &witness.mid()); - let w_mid = eval(&qap.vi[mid_beg..], &witness.mid()); - let y_mid = eval(&qap.vi[mid_beg..], &witness.mid()); - - let v = v_0 + v_io + v_mid; - let w = w_0 + w_io + w_mid; - let y = y_0 + y_io + y_mid; - - let lhs = v * w - y; - let rhs = &h.eval_at(s) * &t.eval_at(s); - - assert!(lhs == rhs); - } - //// EXPERIMENT ZONE - PinocchioProver { f: f.clone(), max_degree: (&max_degree.e).try_into().unwrap(), @@ -165,6 +118,9 @@ impl PinocchioProver { DivResult::QuotientRemainder(_) => panic!("p must be divisible by t"), }; + let ht_poly = &h * &self.t; + let ht = ht_poly.eval_with_g1_hidings(&crs.ek.si); + let h_hiding = h.eval_with_g1_hidings(&crs.ek.si); let alpha_h = h.eval_with_g1_hidings(&crs.ek.alpha_si); @@ -178,6 +134,7 @@ impl PinocchioProver { beta_y_mid, h: h_hiding, alpha_h, + ht, } } } @@ -189,7 +146,7 @@ mod tests { #[test] fn test_generate_proof_and_verify() { - let f = &PrimeField::new(&3911u16); + let f = &G1Point::curve_group(); let expr = "(x * x * x) + x + 5 == 35"; let eq = EquationParser::parse(f, expr).unwrap(); @@ -225,7 +182,7 @@ mod tests { &prover.witness.io(), ); - assert!(result == true); + assert!(result); } } diff --git a/src/zk/w_trusted_setup/pinocchio/pinocchio_verifier.rs b/src/zk/w_trusted_setup/pinocchio/pinocchio_verifier.rs index f3433f4..84d7a95 100644 --- a/src/zk/w_trusted_setup/pinocchio/pinocchio_verifier.rs +++ b/src/zk/w_trusted_setup/pinocchio/pinocchio_verifier.rs @@ -24,63 +24,62 @@ impl PinocchioVerifier { &self, proof: &PinocchioProof, crs: &CRS, - public_io_inputs: &SparseVec, + io_inputs: &SparseVec, ) -> bool { + println!("Verifying Pinnochio proof..."); let e = |a, b| self.pairing.tate(a, b); - // e(E(αh(s)),E(1)) =? e(E(h(s)),E(α)) - // if e(&proof.alpha_h, &crs.vk.one) != e(&proof.h, &crs.vk.e_alpha) { - // return false; - // } + println!("--> Checking if e(E(αh(s)),E(1)) =? e(E(h(s)),E(α))..."); + if e(&proof.alpha_h, &crs.vk.one) != e(&proof.h, &crs.vk.e_alpha) { + return false; + } - // e(E(βv v_mid(s), E(γ)) =? e(v_mid(s),E(βvγ)) - // if e(&proof.beta_v_mid, &crs.vk.e_gamma) != e(&proof.v_mid, &crs.vk.beta_v_gamma) { - // return false; - // } + println!("--> Checking if e(E(βv v_mid(s), E(γ)) =? e(v_mid(s),E(βvγ))..."); + if e(&proof.beta_v_mid, &crs.vk.e_gamma) != e(&proof.v_mid, &crs.vk.beta_v_gamma) { + return false; + } - // e(E(βw w_mid(s)), E(γ)) =? e(w_mid(s),E(βwγ)) - // if e(&proof.beta_w_mid, &crs.vk.e_gamma) != e(&proof.w_mid, &crs.vk.beta_w_gamma) { - // return false; - // } + println!("--> Checking if e(E(βw w_mid(s)), E(γ)) =? e(w_mid(s),E(βwγ))..."); + if e(&proof.beta_w_mid_e1, &crs.vk.e_gamma) != e(&proof.w_mid_e1, &crs.vk.beta_w_gamma) { + return false; + } - // e(E(βy y_mid(s)), E(γ)) =? e(y_mid(s),E(βyγ)) - // if e(&proof.beta_y_mid, &crs.vk.e_gamma) != e(&proof.y_mid, &crs.vk.beta_y_gamma) { - // return false; - // } + println!("--> Checking if e(E(βy y_mid(s)), E(γ)) =? e(y_mid(s),E(βyγ))..."); + if e(&proof.beta_y_mid, &crs.vk.e_gamma) != e(&proof.y_mid, &crs.vk.beta_y_gamma) { + return false; + } - // v_e = E(v_0(s) + E(v_io(s)) + E(v_mid(s)) - // w_e = E(w_0(s) + E(w_io(s)) + E(w_mid(s)) - // y_e = E(y_0(s) + E(y_io(s)) + E(y_mid(s)) - // e(v_e, w_e)/e(y_e, E(1)) ?= e(E(h(s)), E(t(s))) - - let f = &public_io_inputs.f; + println!("--> Checking if e(v_e, w_e)/e(y_e, E(1)) ?= e(E(h*t(s)), E(1))..."); + let f = &io_inputs.f; let mut v_e = &crs.vk.v_0 + &proof.v_mid; for i in 0..crs.vk.vi_io.len() { - let w = &public_io_inputs[&f.elem(&i)]; + let w = &io_inputs[&f.elem(&i)]; let p = &crs.vk.vi_io[i]; v_e = v_e + p * w; } let mut w_e = &crs.vk.w_0 + &proof.w_mid_e2; for i in 0..crs.vk.wi_io.len() { - let w = &public_io_inputs[&f.elem(&i)]; + let w = &io_inputs[&f.elem(&i)]; let p = &crs.vk.wi_io[i]; w_e = w_e + p * w; } let mut y_e = &crs.vk.y_0 + &proof.y_mid; for i in 0..crs.vk.yi_io.len() { - let w = &public_io_inputs[&f.elem(&i)]; + let w = &io_inputs[&f.elem(&i)]; let p = &crs.vk.yi_io[i]; y_e = y_e + p * w; } - true - // let lhs = e(&v_e, &w_e) - e(&y_e, &crs.vk.one); - // let rhs = e(&proof.h, &crs.vk.t); - // - // lhs == rhs + let lhs1 = e(&v_e, &w_e); + let lhs2 = e(&y_e, &crs.vk.one); + let lhs = lhs1 * lhs2.inv(); + + let rhs = e(&proof.ht, &crs.vk.one); + + lhs == rhs } } diff --git a/src/zk/w_trusted_setup/pinocchio/polynomial.rs b/src/zk/w_trusted_setup/pinocchio/polynomial.rs index 1386a9f..8198653 100644 --- a/src/zk/w_trusted_setup/pinocchio/polynomial.rs +++ b/src/zk/w_trusted_setup/pinocchio/polynomial.rs @@ -3,10 +3,7 @@ use crate::building_block::{ prime_field::PrimeField, prime_field_elem::PrimeFieldElem, }, - curves::bls12_381::{ - g1_point::G1Point, - g2_point::G2Point, - }, + curves::bls12_381::g1_point::G1Point, to_biguint::ToBigUint, zero::Zero, }; use num_bigint::BigUint; @@ -274,20 +271,7 @@ impl Polynomial { ) -> G1Point { let mut sum = G1Point::zero(); for i in 0..self.coeffs.len() { - sum = sum + &g1_powers[i] * &self.coeffs[i]; - } - sum - } - - // TODO avoid duplicating code - #[allow(non_snake_case)] - pub fn eval_with_g2_hidings( - &self, - g2_powers: &[G2Point] - ) -> G2Point { - let mut sum = G2Point::zero(); - for i in 0..self.coeffs.len() { - sum = sum + &g2_powers[i] * &self.coeffs[i]; + sum = sum + (&g1_powers[i] * &self.coeffs[i]); } sum } @@ -320,14 +304,21 @@ impl<'a> Add<&Polynomial> for &Polynomial { } } -// TODO avoid duplicating code -impl<'a> Mul<&Polynomial> for Polynomial { - type Output = Polynomial; +macro_rules! impl_mul { + ($rhs: ty, $target: ty) => { + impl<'a> Mul<$rhs> for $target { + type Output = Polynomial; - fn mul(self, rhs: &Polynomial) -> Self::Output { - self.multiply_by(rhs) - } + fn mul(self, rhs: $rhs) -> Self::Output { + self.multiply_by(&rhs) + } + } + }; } +impl_mul!(Polynomial, Polynomial); +impl_mul!(Polynomial, &Polynomial); +impl_mul!(&Polynomial, Polynomial); +impl_mul!(&Polynomial, &Polynomial); impl<'a> Mul<&PrimeFieldElem> for &Polynomial { type Output = Polynomial; @@ -1217,7 +1208,7 @@ mod tests { } #[test] - fn test_eval_with_g1_hidings() { + fn test_eval_with_g1_hidings_1() { let f = &PrimeField::new(&3299u16); let s = f.elem(&3u8); let s0g = &G1Point::g(); @@ -1253,41 +1244,36 @@ mod tests { assert!(act == exp); } - // TODO share code with g1 couterpart #[test] - fn test_eval_with_g2_hidings() { - let f = &PrimeField::new(&3299u16); + fn test_eval_with_g1_hidings_2() { + let f = &G1Point::curve_group(); + let s = f.elem(&3u8); - let s0g = &G2Point::g(); - let s1g = s0g * &s; - let s2g = s0g * &s.pow(&2u8); - let s3g = s0g * &s.pow(&3u8); - let pows = vec![ - s0g.clone(), - s1g.clone(), - s2g.clone(), - s3g.clone(), - ]; - let two = f.elem(&2u8); - let three = f.elem(&3u8); - let four = f.elem(&4u8); - let five = f.elem(&5u8); - let exp = - s0g * &two - + &s1g * &three - + &s2g * &four - + &s3g * &five - ; - // 5x^3 + 4x^2 + 3x + 2 + let e1549 = f.elem(&1549u16); + let e3361 = f.elem(&3361u16); + let e3607 = f.elem(&3607u16); + let e822 = f.elem(&822u16); + let e1990 = f.elem(&1990u16); + let e496 = f.elem(&496u16); + let e1698 = f.elem(&1698u16); + let e2362 = f.elem(&2362u16); + let e3670 = f.elem(&3670u16); + + // 3670x^8 + 2362x^7 + 1698x^6 + 496x^5 + 1990x^4 + 822x^3 + 3607x^2 + 3361x + 1549 let p = Polynomial::new(f, &vec![ - two, - three, - four, - five, + e1549, + e3361, + e3607, + e822, + e1990, + e496, + e1698, + e2362, + e3670, ]); - let act = p.eval_with_g2_hidings(&pows); + println!("p(s) = {:?}", p.eval_at(&s)); + assert!(p.eval_at(&s) == f.elem(&0u8)); - assert!(act == exp); } } diff --git a/src/zk/w_trusted_setup/pinocchio/qap.rs b/src/zk/w_trusted_setup/pinocchio/qap.rs index 8ca1e37..20baacf 100644 --- a/src/zk/w_trusted_setup/pinocchio/qap.rs +++ b/src/zk/w_trusted_setup/pinocchio/qap.rs @@ -112,7 +112,7 @@ impl QAP { let mut p = zero.clone(); for i in 0..self.wi.len() { let w = &witness[&self.f.elem(&i)]; - p = &p + &(&self.wi[i] * &w); + p = &p + &(&self.wi[i] * w); }; p }; @@ -120,7 +120,7 @@ impl QAP { let mut p = zero.clone(); for i in 0..self.yi.len() { let w = &witness[&self.f.elem(&i)]; - p = &p + &(&self.yi[i] * &w); + p = &p + &(&self.yi[i] * w); }; p }; diff --git a/src/zk/w_trusted_setup/pinocchio/r1cs.rs b/src/zk/w_trusted_setup/pinocchio/r1cs.rs index 497a7e8..5bfe882 100644 --- a/src/zk/w_trusted_setup/pinocchio/r1cs.rs +++ b/src/zk/w_trusted_setup/pinocchio/r1cs.rs @@ -63,17 +63,6 @@ impl R1CS { let b = &(&constraint.b * &self.witness).sum(); let c = &(&constraint.c * &self.witness).sum(); - println!("r1cs: ({:?}*{:?})={:?}) * ({:?}*{:?}={:?}) = ({:?}*{:?}={:?})", - &constraint.a, - &self.witness, - &a, - &constraint.b, - &self.witness, - &b, - &constraint.c, - &self.witness, - &c, - ); if &(a * b) != c { return Err(format!("Constraint a ({:?}) * b ({:?}) = c ({:?}) doesn't hold", a, b, c)); } diff --git a/src/zk/w_trusted_setup/pinocchio/witness.rs b/src/zk/w_trusted_setup/pinocchio/witness.rs index cb99a60..2f09d45 100644 --- a/src/zk/w_trusted_setup/pinocchio/witness.rs +++ b/src/zk/w_trusted_setup/pinocchio/witness.rs @@ -16,7 +16,7 @@ impl Witness { } } - pub fn const_witness(&self) -> PrimeFieldElem { + pub fn one(&self) -> PrimeFieldElem { let f = &self.mid_beg.f; self.sv[&f.elem(&0u8)].clone() }