Skip to content

Commit 7fef955

Browse files
committed
groth16 without montgomery is done
1 parent 3f1f4f5 commit 7fef955

File tree

5 files changed

+263
-8
lines changed

5 files changed

+263
-8
lines changed

src/circuits/bn254/finalexp.rs

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
use ark_ec::bn::BnConfig;
2+
use ark_ff::{BitIteratorBE, CyclotomicMultSubgroup, Field};
3+
use crate::{bag::*, circuits::bn254::{fq12::Fq12, utils::{fq12_from_wires, wires_set_from_fq12}}};
4+
5+
pub fn conjugate(f: ark_bn254::Fq12) -> ark_bn254::Fq12 {
6+
ark_bn254::Fq12::new(f.c0, -f.c1)
7+
}
8+
9+
pub fn cyclotomic_exp(f: ark_bn254::Fq12) -> ark_bn254::Fq12 {
10+
let mut res = ark_bn254::Fq12::ONE;
11+
let mut found_nonzero = false;
12+
for value in BitIteratorBE::without_leading_zeros(ark_bn254::Config::X.as_ref()).map(|e| e as i8) {
13+
if found_nonzero {
14+
res.square_in_place(); // cyclotomic_square_in_place
15+
}
16+
17+
if value != 0 {
18+
found_nonzero = true;
19+
20+
if value > 0 {
21+
res *= &f;
22+
}
23+
}
24+
}
25+
res
26+
}
27+
28+
pub fn cyclotomic_exp_evaluate(f: Wires) -> (Wires, GateCount) {
29+
let mut res = wires_set_from_fq12(ark_bn254::Fq12::ONE);
30+
let mut gate_count = GateCount::zero();
31+
let mut found_nonzero = false;
32+
for value in BitIteratorBE::without_leading_zeros(ark_bn254::Config::X.as_ref()).map(|e| e as i8).collect::<Vec<_>>() {
33+
if found_nonzero {
34+
let (wires1, gc) = (wires_set_from_fq12(fq12_from_wires(res.clone()).square()), GateCount::fq12_square()); //Fq12::square_evaluate(res.clone());
35+
res = wires1;
36+
gate_count += gc;
37+
}
38+
39+
if value != 0 {
40+
found_nonzero = true;
41+
42+
if value > 0 {
43+
let (wires2, gc) = (wires_set_from_fq12(fq12_from_wires(res.clone()) * fq12_from_wires(f.clone())), GateCount::fq12_mul()); // Fq12::mul_evaluate(res.clone(), f.clone());
44+
res = wires2;
45+
gate_count+=gc;
46+
}
47+
}
48+
}
49+
(res, gate_count)
50+
}
51+
52+
pub fn cyclotomic_exp_fastinv(f: ark_bn254::Fq12) -> ark_bn254::Fq12 {
53+
let self_inverse = f.cyclotomic_inverse().unwrap();
54+
let mut res = ark_bn254::Fq12::ONE;
55+
let mut found_nonzero = false;
56+
for value in ark_ff::biginteger::arithmetic::find_naf(ark_bn254::Config::X.as_ref()).into_iter().rev() {
57+
if found_nonzero {
58+
res.square_in_place(); // cyclotomic_square_in_place
59+
}
60+
61+
if value != 0 {
62+
found_nonzero = true;
63+
64+
if value > 0 {
65+
res *= &f;
66+
} else {
67+
res *= &self_inverse;
68+
}
69+
}
70+
}
71+
res
72+
}
73+
74+
pub fn exp_by_neg_x(f: ark_bn254::Fq12) -> ark_bn254::Fq12 {
75+
conjugate(cyclotomic_exp(f))
76+
}
77+
78+
pub fn exp_by_neg_x_evaluate(f: Wires) -> (Wires, GateCount) {
79+
let mut gate_count = GateCount::zero();
80+
let (f2, gc) = cyclotomic_exp_evaluate(f);
81+
gate_count += gc;
82+
let (f3, gc) = Fq12::conjugate_evaluate(f2);
83+
gate_count += gc;
84+
(f3, gate_count)
85+
}
86+
87+
pub fn final_exponentiation(f: ark_bn254::Fq12) -> ark_bn254::Fq12 {
88+
let u = f.inverse().unwrap() * conjugate(f);
89+
let r = u.frobenius_map(2) * u;
90+
let y0 = exp_by_neg_x(r);
91+
let y1 = y0.square();
92+
let y2 = y1.square();
93+
let y3 = y2 * &y1;
94+
let y4 = exp_by_neg_x(y3);
95+
let y5 = y4.square();
96+
let y6 = exp_by_neg_x(y5);
97+
let y7 = conjugate(y3);
98+
let y8 = conjugate(y6);
99+
let y9 = y8 * &y4;
100+
let y10 = y9 * &y7;
101+
let y11 = y10 * &y1;
102+
let y12 = y10 * &y4;
103+
let y13 = y12 * &r;
104+
let y14 = y11.frobenius_map(1);
105+
let y15 = y14 * &y13;
106+
let y16 = y10.frobenius_map(2);
107+
let y17 = y16 * &y15;
108+
let r2 = conjugate(r);
109+
let y18 = r2 * &y11;
110+
let y19 = y18.frobenius_map(3);
111+
let y20 = y19 * &y17;
112+
y20
113+
}
114+
115+
pub fn final_exponentiation_evaluate(f: Wires) -> (Wires, GateCount) {
116+
let mut gate_count = GateCount::zero();
117+
let (f_inv, gc) = (wires_set_from_fq12(fq12_from_wires(f.clone()).inverse().unwrap()), GateCount::fq12_inverse());
118+
gate_count += gc;
119+
let (f_conjugate, gc) = Fq12::conjugate_evaluate(f.clone());
120+
gate_count += gc;
121+
let (u, gc) = (wires_set_from_fq12(fq12_from_wires(f_inv) * fq12_from_wires(f_conjugate)), GateCount::fq12_mul()); // Fq12::mul_evaluate(f_inv, f_conjugate);
122+
gate_count += gc;
123+
let (u_frobenius, gc) = Fq12::frobenius_evaluate(u.clone(), 2);
124+
gate_count += gc;
125+
let (r, gc) = (wires_set_from_fq12(fq12_from_wires(u_frobenius) * fq12_from_wires(u.clone())), GateCount::fq12_mul()); // Fq12::mul_evaluate(u_frobenius, u.clone());
126+
gate_count += gc;
127+
let (y0, gc) = exp_by_neg_x_evaluate(r.clone());
128+
gate_count += gc;
129+
let (y1, gc) = (wires_set_from_fq12(fq12_from_wires(y0).square()), GateCount::fq12_square()); // Fq12::square_evaluate(y0);
130+
gate_count += gc;
131+
let (y2, gc) = (wires_set_from_fq12(fq12_from_wires(y1.clone()).square()), GateCount::fq12_square()); // Fq12::square_evaluate(y1.clone());
132+
gate_count += gc;
133+
let (y3, gc) = (wires_set_from_fq12(fq12_from_wires(y1.clone()) * fq12_from_wires(y2)), GateCount::fq12_mul()); // Fq12::mul_evaluate(y1.clone(), y2);
134+
gate_count += gc;
135+
let (y4, gc) = exp_by_neg_x_evaluate(y3.clone());
136+
gate_count += gc;
137+
let (y5, gc) = (wires_set_from_fq12(fq12_from_wires(y4.clone()).square()), GateCount::fq12_square()); // Fq12::square_evaluate(y4.clone());
138+
gate_count += gc;
139+
let (y6, gc) = exp_by_neg_x_evaluate(y5);
140+
gate_count += gc;
141+
let (y7, gc) = Fq12::conjugate_evaluate(y3);
142+
gate_count += gc;
143+
let (y8, gc) = Fq12::conjugate_evaluate(y6);
144+
gate_count += gc;
145+
let (y9, gc) = (wires_set_from_fq12(fq12_from_wires(y8) * fq12_from_wires(y4.clone())), GateCount::fq12_mul()); // Fq12::mul_evaluate(y8, y4.clone());
146+
gate_count += gc;
147+
let (y10, gc) = (wires_set_from_fq12(fq12_from_wires(y9) * fq12_from_wires(y7)), GateCount::fq12_mul()); // Fq12::mul_evaluate(y9, y7);
148+
gate_count += gc;
149+
let (y11, gc) = (wires_set_from_fq12(fq12_from_wires(y10.clone()) * fq12_from_wires(y1)), GateCount::fq12_mul()); // Fq12::mul_evaluate(y10.clone(), y1);
150+
gate_count += gc;
151+
let (y12, gc) = (wires_set_from_fq12(fq12_from_wires(y10.clone()) * fq12_from_wires(y4)), GateCount::fq12_mul()); // Fq12::mul_evaluate(y10.clone(), y4);
152+
gate_count += gc;
153+
let (y13, gc) = (wires_set_from_fq12(fq12_from_wires(y12) * fq12_from_wires(r.clone())), GateCount::fq12_mul()); // Fq12::mul_evaluate(y12, r.clone());
154+
gate_count += gc;
155+
let (y14, gc) = Fq12::frobenius_evaluate(y11.clone(), 1);
156+
gate_count += gc;
157+
let (y15, gc) = (wires_set_from_fq12(fq12_from_wires(y14) * fq12_from_wires(y13)), GateCount::fq12_mul()); // Fq12::mul_evaluate(y14, y13);
158+
gate_count += gc;
159+
let (y16, gc) = Fq12::frobenius_evaluate(y10, 2);
160+
gate_count += gc;
161+
let (y17, gc) = (wires_set_from_fq12(fq12_from_wires(y16) * fq12_from_wires(y15)), GateCount::fq12_mul()); // Fq12::mul_evaluate(y16, y15);
162+
gate_count += gc;
163+
let (r2, gc) = Fq12::conjugate_evaluate(r);
164+
gate_count += gc;
165+
let (y18, gc) = (wires_set_from_fq12(fq12_from_wires(r2) * fq12_from_wires(y11)), GateCount::fq12_mul()); // Fq12::mul_evaluate(r2, y11);
166+
gate_count += gc;
167+
let (y19, gc) = Fq12::frobenius_evaluate(y18, 3);
168+
gate_count += gc;
169+
let (y20, gc) = (wires_set_from_fq12(fq12_from_wires(y19) * fq12_from_wires(y17)), GateCount::fq12_mul()); // Fq12::mul_evaluate(y19, y17);
170+
gate_count += gc;
171+
(y20, gate_count)
172+
}
173+
174+
#[cfg(test)]
175+
mod tests {
176+
use ark_ec::{bn::BnConfig, pairing::{MillerLoopOutput, Pairing}};
177+
use ark_ff::{CyclotomicMultSubgroup, UniformRand};
178+
use ark_std::rand::SeedableRng;
179+
use rand_chacha::ChaCha20Rng;
180+
use crate::circuits::bn254::{finalexp::{cyclotomic_exp, cyclotomic_exp_evaluate, cyclotomic_exp_fastinv, final_exponentiation, final_exponentiation_evaluate}, utils::{fq12_from_wires, wires_set_from_fq12}};
181+
182+
#[test]
183+
fn test_cyclotomic_exp() {
184+
let mut prng = ChaCha20Rng::seed_from_u64(0);
185+
let f = ark_bn254::Fq12::rand(&mut prng);
186+
187+
let c = f.cyclotomic_exp(ark_bn254::Config::X);
188+
let d = cyclotomic_exp(f);
189+
let e = cyclotomic_exp_fastinv(f);
190+
assert_eq!(c, d);
191+
assert_eq!(c, e);
192+
}
193+
194+
#[test]
195+
fn test_cyclotomic_exp_evaluate() {
196+
let mut prng = ChaCha20Rng::seed_from_u64(0);
197+
let f = ark_bn254::Fq12::rand(&mut prng);
198+
199+
let c = cyclotomic_exp(f); // f.cyclotomic_exp(ark_bn254::Config::X);
200+
let (d, gate_count) = cyclotomic_exp_evaluate(wires_set_from_fq12(f));
201+
gate_count.print();
202+
assert_eq!(c, fq12_from_wires(d));
203+
}
204+
205+
#[test]
206+
fn test_final_exponentiation() {
207+
let mut prng = ChaCha20Rng::seed_from_u64(0);
208+
let f = ark_bn254::Fq12::rand(&mut prng);
209+
210+
let c = ark_bn254::Bn254::final_exponentiation(MillerLoopOutput(f)).unwrap().0;
211+
let d = final_exponentiation(f);
212+
assert_eq!(c, d);
213+
}
214+
215+
#[test]
216+
fn test_final_exponentiation_evaluate() {
217+
let mut prng = ChaCha20Rng::seed_from_u64(0);
218+
let f = ark_bn254::Fq12::rand(&mut prng);
219+
220+
let c = ark_bn254::Bn254::final_exponentiation(MillerLoopOutput(f)).unwrap().0;
221+
let (d, gate_count) = final_exponentiation_evaluate(wires_set_from_fq12(f));
222+
gate_count.print();
223+
224+
assert_eq!(fq12_from_wires(d), c);
225+
}
226+
}

src/circuits/bn254/g1.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ mod tests {
324324

325325
#[test]
326326
fn test_g1p_multiplexer() {
327-
let w = 12;
327+
let w = 4;
328328
let n = 2_usize.pow(w as u32);
329329
let a: Vec<ark_bn254::G1Projective> = (0..n).map(|_| { random_g1p() }).collect();
330330
let s: Wires = (0..w).map(|_| { Rc::new(RefCell::new(Wire::new())) }).collect();

src/circuits/bn254/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ pub mod fr;
88
pub mod g1;
99
pub mod g2;
1010
pub mod pairing;
11+
pub mod finalexp;

src/circuits/groth16.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use ark_ec::pairing::{MillerLoopOutput, Pairing};
22
use ark_ec::{AffineRepr, VariableBaseMSM};
33
use ark_ff::Field;
44
use crate::bag::*;
5+
use crate::circuits::bn254::finalexp::final_exponentiation_evaluate;
56
use crate::circuits::bn254::fq12::Fq12;
67
use crate::circuits::bn254::g1::G1Projective;
78
use crate::circuits::bn254::pairing::multi_miller_loop_groth16_evaluate;
@@ -32,7 +33,8 @@ pub fn groth16_verifier_evaluate(public: Wires, proof_a: Wires, proof_b: Wires,
3233
gate_count += gc;
3334

3435
let alpha_beta = ark_bn254::Bn254::final_exponentiation(ark_bn254::Bn254::multi_miller_loop([vk.alpha_g1.into_group()], [-vk.beta_g2])).unwrap().0.inverse().unwrap();
35-
let f = wires_set_from_fq12(ark_bn254::Bn254::final_exponentiation(MillerLoopOutput(fq12_from_wires(f))).unwrap().0);
36+
let (f, gc) = final_exponentiation_evaluate(f); // wires_set_from_fq12(ark_bn254::Bn254::final_exponentiation(MillerLoopOutput(fq12_from_wires(f))).unwrap().0);
37+
gate_count += gc;
3638

3739
let (result, gc) = Fq12::equal_constant_evaluate(f, alpha_beta);
3840
gate_count += gc;

src/core/gate.rs

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -339,12 +339,12 @@ impl GateCount {
339339
impl GateCount {
340340
pub fn msm() -> Self {
341341
Self {
342-
and: 0,
343-
or: 0,
344-
xor: 0,
345-
nand: 0,
346-
not: 0,
347-
xnor: 0,
342+
and: 128808400,
343+
or: 76938400,
344+
xor: 102685425,
345+
nand: 213127590,
346+
not: 123282230,
347+
xnor: 51296850,
348348
nimp: 0,
349349
nsor: 0,
350350
}
@@ -363,6 +363,32 @@ impl GateCount {
363363
}
364364
}
365365

366+
pub fn fq12_mul() -> Self {
367+
Self {
368+
and: 14793358,
369+
or: 8875324,
370+
xor: 11846173,
371+
nand: 17836896,
372+
not: 11985288,
373+
xnor: 5912170,
374+
nimp: 0,
375+
nsor: 0,
376+
}
377+
}
378+
379+
pub fn fq12_inverse() -> Self {
380+
Self {
381+
and: 41464294,
382+
or: 22347965,
383+
xor: 32020868,
384+
nand: 43551348,
385+
not: 28864311,
386+
xnor: 13277144,
387+
nimp: 0,
388+
nsor: 0,
389+
}
390+
}
391+
366392
pub fn double_in_place() -> Self {
367393
Self {
368394
and: 9224370,

0 commit comments

Comments
 (0)