mirror of
https://github.com/exfinen/zk-toolkit.git
synced 2026-01-10 04:28:02 -05:00
add working pinnochio verifiable computation
This commit is contained in:
@@ -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<bool>,
|
||||
@@ -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...");
|
||||
|
||||
@@ -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<usize> = &(*&p.mid_beg..*&p.num_constraints).collect();
|
||||
let io: &Vec<usize> = &(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,
|
||||
|
||||
@@ -13,5 +13,6 @@ pub struct PinocchioProof {
|
||||
pub beta_y_mid: G1Point,
|
||||
pub h: G1Point,
|
||||
pub alpha_h: G1Point,
|
||||
pub ht: G1Point,
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user