Rename "groth" to "groth16".
This commit is contained in:
@@ -0,0 +1,207 @@
|
||||
use super::*;
|
||||
use rand::{Rng, thread_rng};
|
||||
|
||||
struct RootCircuit<E: Engine> {
|
||||
root: E::Fr
|
||||
}
|
||||
|
||||
impl<E: Engine> Circuit<E> for RootCircuit<E> {
|
||||
type InputMap = RootInput<E>;
|
||||
|
||||
fn synthesize<CS: ConstraintSystem<E>>(self,
|
||||
e: &E,
|
||||
cs: &mut CS)
|
||||
-> Self::InputMap
|
||||
{
|
||||
let root_var = cs.alloc(self.root);
|
||||
|
||||
let mut cur = root_var;
|
||||
let mut cur_val = self.root;
|
||||
|
||||
for _ in 0..99 {
|
||||
cur_val.mul_assign(e, &self.root);
|
||||
let new = cs.alloc(cur_val);
|
||||
|
||||
cs.enforce(
|
||||
LinearCombination::zero(e) + (E::Fr::from_str(e, "3").unwrap(), cur),
|
||||
LinearCombination::zero(e) + (E::Fr::from_str(e, "4").unwrap(), root_var),
|
||||
LinearCombination::zero(e) + (E::Fr::from_str(e, "12").unwrap(), new),
|
||||
);
|
||||
|
||||
cur = new;
|
||||
}
|
||||
|
||||
RootInput {
|
||||
num: cur_val,
|
||||
num_var: cur
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct RootInput<E: Engine> {
|
||||
num: E::Fr,
|
||||
num_var: Variable
|
||||
}
|
||||
|
||||
impl<E: Engine> Input<E> for RootInput<E> {
|
||||
fn synthesize<CS: PublicConstraintSystem<E>>(
|
||||
self,
|
||||
e: &E,
|
||||
cs: &mut CS
|
||||
)
|
||||
{
|
||||
let result_input = cs.alloc_input(self.num);
|
||||
cs.enforce(
|
||||
LinearCombination::zero(e) + result_input,
|
||||
LinearCombination::one(e),
|
||||
LinearCombination::zero(e) + self.num_var
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn test_snark_system<E: Engine, R: Rng>(
|
||||
e: &E,
|
||||
rng: &mut R
|
||||
)
|
||||
{
|
||||
let tau = E::Fr::random(e, rng);
|
||||
let alpha = E::Fr::random(e, rng);
|
||||
let beta = E::Fr::random(e, rng);
|
||||
let gamma = E::Fr::random(e, rng);
|
||||
let delta = E::Fr::random(e, rng);
|
||||
|
||||
// create keypair
|
||||
let (pk, vk) = {
|
||||
let c = RootCircuit {
|
||||
root: E::Fr::zero()
|
||||
};
|
||||
|
||||
keypair(e, c, &tau, &alpha, &beta, &gamma, &delta)
|
||||
};
|
||||
|
||||
// construct proof
|
||||
let proof = {
|
||||
let r = E::Fr::random(e, rng);
|
||||
let s = E::Fr::random(e, rng);
|
||||
|
||||
let c = RootCircuit {
|
||||
root: E::Fr::from_str(e, "2").unwrap()
|
||||
};
|
||||
|
||||
prove(e, c, &r, &s, &pk).unwrap()
|
||||
};
|
||||
|
||||
// prepare verifying key
|
||||
let pvk = prepare_verifying_key(e, &vk);
|
||||
|
||||
// verify proof
|
||||
assert!(verify(e, |cs| {
|
||||
RootInput {
|
||||
num: E::Fr::from_str(e, "1267650600228229401496703205376").unwrap(),
|
||||
num_var: cs.alloc(E::Fr::one(e))
|
||||
}
|
||||
}, &proof, &pvk));
|
||||
|
||||
// verify invalid proof
|
||||
assert!(!verify(e, |cs| {
|
||||
RootInput {
|
||||
num: E::Fr::from_str(e, "1267650600228229401496703205375").unwrap(),
|
||||
num_var: cs.alloc(E::Fr::one(e))
|
||||
}
|
||||
}, &proof, &pvk));
|
||||
|
||||
// simulate a groth proof with trapdoors
|
||||
// ----------------
|
||||
// 99: a1 * a0 = l*
|
||||
// 100: a0 * 0 = 0
|
||||
// 101: a1 * 0 = 0
|
||||
// ---
|
||||
// u_0(tau) = tau^100
|
||||
// u_1(tau) = tau^99 + tau^101
|
||||
// v_0(tau) = tau^99
|
||||
// v_1(tau) = 0
|
||||
// w_0(tau) = 0
|
||||
// w_1(tau) = 0
|
||||
// ---
|
||||
|
||||
let mut lagrange_coeffs: Vec<E::Fr> = (0..128).map(|i| tau.pow(e, &[i])).collect();
|
||||
|
||||
let d = domain::EvaluationDomain::new(e, 128);
|
||||
d.ifft(e, &mut lagrange_coeffs);
|
||||
|
||||
let a = E::Fr::random(e, rng);
|
||||
let b = E::Fr::random(e, rng);
|
||||
|
||||
let mut c = a;
|
||||
c.mul_assign(e, &b);
|
||||
|
||||
let mut alphabeta = alpha;
|
||||
alphabeta.mul_assign(e, &beta);
|
||||
c.sub_assign(e, &alphabeta);
|
||||
|
||||
let mut ic = E::Fr::zero();
|
||||
{
|
||||
let mut ic_i_beta = lagrange_coeffs[100];
|
||||
ic_i_beta.mul_assign(e, &beta);
|
||||
|
||||
let mut ic_i_alpha = lagrange_coeffs[99];
|
||||
ic_i_alpha.mul_assign(e, &alpha);
|
||||
|
||||
ic_i_beta.add_assign(e, &ic_i_alpha);
|
||||
|
||||
ic.add_assign(e, &ic_i_beta);
|
||||
}
|
||||
{
|
||||
let mut ic_i_beta = lagrange_coeffs[99];
|
||||
ic_i_beta.add_assign(e, &lagrange_coeffs[101]);
|
||||
ic_i_beta.mul_assign(e, &beta);
|
||||
|
||||
ic_i_beta.mul_assign(e, &E::Fr::from_str(e, "100").unwrap());
|
||||
|
||||
ic.add_assign(e, &ic_i_beta);
|
||||
}
|
||||
|
||||
c.sub_assign(e, &ic);
|
||||
c.mul_assign(e, &delta.inverse(e).unwrap());
|
||||
|
||||
let mut a_g = E::G1::one(e);
|
||||
a_g.mul_assign(e, &a);
|
||||
|
||||
let mut b_g = E::G2::one(e);
|
||||
b_g.mul_assign(e, &b);
|
||||
|
||||
let mut c_g = E::G1::one(e);
|
||||
c_g.mul_assign(e, &c);
|
||||
|
||||
let fake_proof = Proof {
|
||||
a: a_g,
|
||||
b: b_g,
|
||||
c: c_g
|
||||
};
|
||||
|
||||
// verify fake proof
|
||||
assert!(verify(e, |cs| {
|
||||
RootInput {
|
||||
num: E::Fr::from_str(e, "100").unwrap(),
|
||||
num_var: cs.alloc(E::Fr::one(e))
|
||||
}
|
||||
}, &fake_proof, &pvk));
|
||||
|
||||
// verify fake proof with wrong input
|
||||
assert!(!verify(e, |cs| {
|
||||
RootInput {
|
||||
num: E::Fr::from_str(e, "101").unwrap(),
|
||||
num_var: cs.alloc(E::Fr::one(e))
|
||||
}
|
||||
}, &fake_proof, &pvk));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn groth_with_bls381() {
|
||||
use curves::bls381::Bls381;
|
||||
|
||||
let e = &Bls381::new();
|
||||
let rng = &mut thread_rng();
|
||||
|
||||
test_snark_system(e, rng);
|
||||
}
|
||||
Reference in New Issue
Block a user