Skip to content

Commit f39aac3

Browse files
committed
ell_by_constant
1 parent f62370e commit f39aac3

File tree

5 files changed

+219
-4
lines changed

5 files changed

+219
-4
lines changed

src/circuits/bn254/fq12.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,30 @@ impl Fq12 {
198198
circuit
199199
}
200200

201+
pub fn mul_by_034_constant4(a: Wires, c0: Wires, c3: Wires, c4: ark_bn254::Fq2)-> Circuit {
202+
assert_eq!(a.len(), Self::N_BITS);
203+
assert_eq!(c0.len(), Fq2::N_BITS);
204+
assert_eq!(c3.len(), Fq2::N_BITS);
205+
let mut circuit = Circuit::empty();
206+
207+
let a_c0 = a[0..Fq6::N_BITS].to_vec();
208+
let a_c1 = a[Fq6::N_BITS..2*Fq6::N_BITS].to_vec();
209+
210+
let wires_1 = circuit.extend(Fq6::mul_by_01_constant1(a_c1.clone(), c3.clone(), c4.clone()));
211+
let wires_2 = circuit.extend(Fq6::mul_by_nonresidue(wires_1.clone()));
212+
let wires_3 = circuit.extend(Fq6::mul_by_fq2(a_c0.clone(), c0.clone()));
213+
let new_c0 = circuit.extend(Fq6::add(wires_2.clone(), wires_3.clone()));
214+
let wires_4 = circuit.extend(Fq6::add(a_c0.clone(), a_c1.clone()));
215+
let wires_5 = circuit.extend(Fq2::add(c3.clone(), c0.clone()));
216+
let wires_6 = circuit.extend(Fq6::mul_by_01_constant1(wires_4.clone(), wires_5.clone(), c4.clone()));
217+
let wires_7 = circuit.extend(Fq6::add(wires_1, wires_3));
218+
let new_c1 = circuit.extend(Fq6::sub(wires_6, wires_7));
219+
220+
circuit.add_wires(new_c0);
221+
circuit.add_wires(new_c1);
222+
circuit
223+
}
224+
201225
pub fn square(a: Wires) -> Circuit {
202226
assert_eq!(a.len(), Self::N_BITS);
203227
let mut circuit = Circuit::empty();

src/circuits/bn254/fq2.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,17 @@ impl Fq2 {
181181
circuit
182182
}
183183

184+
pub fn mul_constant_by_fq(a: ark_bn254::Fq2, b: Wires) -> Circuit {
185+
assert_eq!(b.len(), Fq::N_BITS);
186+
let mut circuit = Circuit::empty();
187+
188+
let wires_1 = circuit.extend(Fq::mul_by_constant(b.clone(), a.c0));
189+
let wires_2 = circuit.extend(Fq::mul_by_constant(b.clone(), a.c1));
190+
circuit.add_wires(wires_1);
191+
circuit.add_wires(wires_2);
192+
circuit
193+
}
194+
184195
pub fn mul_by_nonresidue(a: Wires) -> Circuit {
185196
assert_eq!(a.len(), Self::N_BITS);
186197
let mut circuit = Circuit::empty();

src/circuits/bn254/fq6.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,37 @@ impl Fq6 {
320320
circuit
321321
}
322322

323+
pub fn mul_by_01_constant1(a: Wires, c0: Wires, c1: ark_bn254::Fq2) -> Circuit {
324+
assert_eq!(a.len(), Self::N_BITS);
325+
assert_eq!(c0.len(), Fq2::N_BITS);
326+
let mut circuit = Circuit::empty();
327+
328+
let a_c0 = a[0..Fq2::N_BITS].to_vec();
329+
let a_c1 = a[Fq2::N_BITS..2*Fq2::N_BITS].to_vec();
330+
let a_c2 = a[2*Fq2::N_BITS..3*Fq2::N_BITS].to_vec();
331+
332+
let wires_1 = circuit.extend(Fq2::mul(a_c0.clone(), c0.clone()));
333+
let wires_2 = circuit.extend(Fq2::mul_by_constant(a_c1.clone(), c1.clone()));
334+
let wires_3 = circuit.extend(Fq2::add(a_c1.clone(), a_c2.clone()));
335+
let wires_4 = circuit.extend(Fq2::mul_by_constant(wires_3.clone(), c1.clone()));
336+
let wires_5 = circuit.extend(Fq2::sub(wires_4.clone(), wires_2.clone()));
337+
let wires_6 = circuit.extend(Fq2::mul_by_nonresidue(wires_5.clone()));
338+
let wires_7 = circuit.extend(Fq2::add(wires_6.clone(), wires_1.clone()));
339+
let wires_8 = circuit.extend(Fq2::add(a_c0.clone(), a_c1.clone()));
340+
let wires_9 = circuit.extend(Fq2::add_constant(c0.clone(), c1.clone()));
341+
let wires_10 = circuit.extend(Fq2::mul(wires_8.clone(), wires_9.clone()));
342+
let wires_11 = circuit.extend(Fq2::sub(wires_10.clone(), wires_1.clone()));
343+
let wires_12 = circuit.extend(Fq2::sub(wires_11.clone(), wires_2.clone()));
344+
let wires_13 = circuit.extend(Fq2::add(a_c0.clone(), a_c2.clone()));
345+
let wires_14 = circuit.extend(Fq2::mul(wires_13.clone(), c0.clone()));
346+
let wires_15 = circuit.extend(Fq2::sub(wires_14.clone(), wires_1.clone()));
347+
let wires_16 = circuit.extend(Fq2::add(wires_15.clone(), wires_2.clone()));
348+
circuit.add_wires(wires_7);
349+
circuit.add_wires(wires_12);
350+
circuit.add_wires(wires_16);
351+
circuit
352+
}
353+
323354
pub fn square(a: Wires) -> Circuit {
324355
assert_eq!(a.len(), Self::N_BITS);
325356
let mut circuit = Circuit::empty();

src/circuits/bn254/pairing.rs

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,35 @@ pub fn ell_circuit_evaluate(f: Wires, coeffs: (Wires, Wires, Wires), p: Wires) -
375375
(circuit.0, n)
376376
}
377377

378+
pub fn ell_by_constant_circuit(f: Wires, coeffs: (ark_bn254::Fq2, ark_bn254::Fq2, ark_bn254::Fq2), p: Wires) -> Circuit {
379+
let mut circuit = Circuit::empty();
380+
let c0 = coeffs.0;
381+
let c1 = coeffs.1;
382+
let c2 = coeffs.2;
383+
384+
let px = p[0..Fq::N_BITS].to_vec();
385+
let py = p[Fq::N_BITS..2*Fq::N_BITS].to_vec();
386+
387+
let new_c0 = circuit.extend(Fq2::mul_constant_by_fq(c0, py));
388+
let new_c1 = circuit.extend(Fq2::mul_constant_by_fq(c1, px));
389+
let new_f = circuit.extend(Fq12::mul_by_034_constant4(f, new_c0, new_c1, c2));
390+
391+
circuit.add_wires(new_f);
392+
circuit
393+
}
394+
395+
pub fn ell_by_constant_circuit_evaluate(f: Wires, coeffs: (ark_bn254::Fq2, ark_bn254::Fq2, ark_bn254::Fq2), p: Wires) -> (Wires, usize) {
396+
let circuit = ell_by_constant_circuit(f, coeffs, p);
397+
398+
let n = circuit.1.len();
399+
400+
for mut gate in circuit.1 {
401+
gate.evaluate();
402+
}
403+
404+
(circuit.0, n)
405+
}
406+
378407
pub fn fq12_square_evaluate(f: Wires) -> (Wires, usize) {
379408
let circuit = Fq12::square(f);
380409

@@ -560,6 +589,92 @@ pub fn multi_miller_loop_circuit_evaluate(ps: Vec<Wires>, qs: Vec<Wires>) -> (Wi
560589
(f, gate_count)
561590
}
562591

592+
pub fn multi_miller_loop_groth16_circuit_evaluate(p1: Wires, p2: Wires, p3: Wires, q1: ark_bn254::G2Affine, q2: ark_bn254::G2Affine, q3: Wires) -> (Wires, usize) {
593+
let mut gate_count = 0;
594+
let q1ell = ell_coeffs(q1);
595+
let q2ell = ell_coeffs(q2);
596+
let (q3ell, gc) = (ell_coeffs(g2a_from_wires(q3)).iter().map(|(c0, c1, c2)| { (wires_set_from_fq2(*c0), wires_set_from_fq2(*c1), wires_set_from_fq2(*c2)) }).collect::<Vec<_>>(), 4290000000); // ell_coeffs_circuit_evaluate(q3);
597+
gate_count += gc;
598+
let mut q1_ell = q1ell.iter();
599+
let mut q2_ell = q2ell.iter();
600+
let mut q3_ell = q3ell.iter();
601+
602+
let mut f = wires_set_from_fq12(ark_bn254::Fq12::ONE);
603+
604+
for i in (1..ark_bn254::Config::ATE_LOOP_COUNT.len()).rev() {
605+
if i != ark_bn254::Config::ATE_LOOP_COUNT.len() - 1 {
606+
let (new_f, gc) = (wires_set_from_fq12(fq12_from_wires(f).square()), 70631715); // fq12_square_evaluate(f);
607+
f = new_f;
608+
gate_count += gc;
609+
}
610+
611+
let q1ell_next = q1_ell.next().unwrap();
612+
let (new_f, gc) = (wires_set_from_fq12(ell2(fq12_from_wires(f), *q1ell_next, g1p_from_wires(p1.clone()))), 58977252); // ell_by_constant_circuit_evaluate(f, q1_ell.next().unwrap().clone(), p.clone());
613+
f = new_f;
614+
gate_count += gc;
615+
616+
let q2ell_next = q2_ell.next().unwrap();
617+
let (new_f, gc) = (wires_set_from_fq12(ell2(fq12_from_wires(f), *q2ell_next, g1p_from_wires(p2.clone()))), 58977252); // ell_by_constant_circuit_evaluate(f, q2_ell.next().unwrap().clone(), p.clone());
618+
f = new_f;
619+
gate_count += gc;
620+
621+
let q3ell_next = q3_ell.next().unwrap().clone();
622+
let (new_f, gc) = (wires_set_from_fq12(ell2(fq12_from_wires(f), (fq2_from_wires(q3ell_next.0), fq2_from_wires(q3ell_next.1), fq2_from_wires(q3ell_next.2)), g1p_from_wires(p3.clone()))), 67030677); // ell_circuit_evaluate(f, q3_ell.next().unwrap().clone(), p.clone());
623+
f = new_f;
624+
gate_count += gc;
625+
626+
let bit = ark_bn254::Config::ATE_LOOP_COUNT[i - 1];
627+
if bit == 1 || bit == -1 {
628+
let q1ell_next = q1_ell.next().unwrap();
629+
let (new_f, gc) = (wires_set_from_fq12(ell2(fq12_from_wires(f), *q1ell_next, g1p_from_wires(p1.clone()))), 58977252); // ell_by_constant_circuit_evaluate(f, q1_ell.next().unwrap().clone(), p.clone());
630+
f = new_f;
631+
gate_count += gc;
632+
633+
let q2ell_next = q2_ell.next().unwrap();
634+
let (new_f, gc) = (wires_set_from_fq12(ell2(fq12_from_wires(f), *q2ell_next, g1p_from_wires(p2.clone()))), 58977252); // ell_by_constant_circuit_evaluate(f, q2_ell.next().unwrap().clone(), p.clone());
635+
f = new_f;
636+
gate_count += gc;
637+
638+
let q3ell_next = q3_ell.next().unwrap().clone();
639+
let (new_f, gc) = (wires_set_from_fq12(ell2(fq12_from_wires(f), (fq2_from_wires(q3ell_next.0), fq2_from_wires(q3ell_next.1), fq2_from_wires(q3ell_next.2)), g1p_from_wires(p3.clone()))), 67030677); // ell_circuit_evaluate(f, q3_ell.next().unwrap().clone(), p.clone());
640+
f = new_f;
641+
gate_count += gc;
642+
}
643+
}
644+
645+
let q1ell_next = q1_ell.next().unwrap();
646+
let (new_f, gc) = (wires_set_from_fq12(ell2(fq12_from_wires(f), *q1ell_next, g1p_from_wires(p1.clone()))), 58977252); // ell_by_constant_circuit_evaluate(f, q1_ell.next().unwrap().clone(), p.clone());
647+
f = new_f;
648+
gate_count += gc;
649+
650+
let q2ell_next = q2_ell.next().unwrap();
651+
let (new_f, gc) = (wires_set_from_fq12(ell2(fq12_from_wires(f), *q2ell_next, g1p_from_wires(p2.clone()))), 58977252); // ell_by_constant_circuit_evaluate(f, q2_ell.next().unwrap().clone(), p.clone());
652+
f = new_f;
653+
gate_count += gc;
654+
655+
let q3ell_next = q3_ell.next().unwrap().clone();
656+
let (new_f, gc) = (wires_set_from_fq12(ell2(fq12_from_wires(f), (fq2_from_wires(q3ell_next.0), fq2_from_wires(q3ell_next.1), fq2_from_wires(q3ell_next.2)), g1p_from_wires(p3.clone()))), 67030677); // ell_circuit_evaluate(f, q3_ell.next().unwrap().clone(), p.clone());
657+
f = new_f;
658+
gate_count += gc;
659+
660+
let q1ell_next = q1_ell.next().unwrap();
661+
let (new_f, gc) = (wires_set_from_fq12(ell2(fq12_from_wires(f), *q1ell_next, g1p_from_wires(p1.clone()))), 58977252); // ell_by_constant_circuit_evaluate(f, q1_ell.next().unwrap().clone(), p.clone());
662+
f = new_f;
663+
gate_count += gc;
664+
665+
let q2ell_next = q2_ell.next().unwrap();
666+
let (new_f, gc) = (wires_set_from_fq12(ell2(fq12_from_wires(f), *q2ell_next, g1p_from_wires(p2.clone()))), 58977252); // ell_by_constant_circuit_evaluate(f, q2_ell.next().unwrap().clone(), p.clone());
667+
f = new_f;
668+
gate_count += gc;
669+
670+
let q3ell_next = q3_ell.next().unwrap().clone();
671+
let (new_f, gc) = (wires_set_from_fq12(ell2(fq12_from_wires(f), (fq2_from_wires(q3ell_next.0), fq2_from_wires(q3ell_next.1), fq2_from_wires(q3ell_next.2)), g1p_from_wires(p3.clone()))), 67030677); // ell_circuit_evaluate(f, q3_ell.next().unwrap().clone(), p.clone());
672+
f = new_f;
673+
gate_count += gc;
674+
675+
(f, gate_count)
676+
}
677+
563678
#[cfg(test)]
564679
mod tests {
565680
use std::iter::zip;
@@ -695,6 +810,23 @@ mod tests {
695810
assert_eq!(f, new_f);
696811
}
697812

813+
#[test]
814+
fn test_ell_by_constant_circuit() {
815+
let mut prng = ChaCha20Rng::seed_from_u64(0);
816+
let mut f = ark_bn254::Fq12::rand(&mut prng);
817+
let coeffs = (ark_bn254::Fq2::rand(&mut prng), ark_bn254::Fq2::rand(&mut prng), ark_bn254::Fq2::rand(&mut prng));
818+
let p = ark_bn254::G1Projective::rand(&mut prng);
819+
820+
let circuit = ell_by_constant_circuit(wires_set_from_fq12(f), coeffs, wires_set_from_g1p(p));
821+
circuit.print_gate_type_counts();
822+
for mut gate in circuit.1 {
823+
gate.evaluate();
824+
}
825+
let new_f = fq12_from_wires(circuit.0);
826+
ell(&mut f, coeffs, p);
827+
assert_eq!(f, new_f);
828+
}
829+
698830
#[test]
699831
fn test_miller_loop() {
700832
let mut prng = ChaCha20Rng::seed_from_u64(0);
@@ -744,4 +876,21 @@ mod tests {
744876

745877
assert_eq!(fq12_from_wires(f), expected_f);
746878
}
879+
880+
#[test]
881+
fn test_multi_miller_loop_groth16_circuit_evaluate() {
882+
let mut prng = ChaCha20Rng::seed_from_u64(0);
883+
let p1 = ark_bn254::G1Projective::rand(&mut prng);
884+
let p2 = ark_bn254::G1Projective::rand(&mut prng);
885+
let p3 = ark_bn254::G1Projective::rand(&mut prng);
886+
let q1 = ark_bn254::G2Affine::rand(&mut prng);
887+
let q2 = ark_bn254::G2Affine::rand(&mut prng);
888+
let q3 = ark_bn254::G2Affine::rand(&mut prng);
889+
890+
let expected_f = multi_miller_loop(vec![p1, p2, p3], vec![q1, q2, q3]);
891+
let (f, gate_count) = multi_miller_loop_groth16_circuit_evaluate(wires_set_from_g1p(p1), wires_set_from_g1p(p2), wires_set_from_g1p(p3), q1, q2, wires_set_from_g2a(q3));
892+
println!("gate_count: {:?}", gate_count);
893+
894+
assert_eq!(fq12_from_wires(f), expected_f);
895+
}
747896
}

src/circuits/groth16.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use ark_ff::Field;
44
use crate::bag::*;
55
use crate::circuits::bn254::fq12::Fq12;
66
use crate::circuits::bn254::g1::G1Projective;
7-
use crate::circuits::bn254::pairing::multi_miller_loop_circuit_evaluate;
8-
use crate::circuits::bn254::utils::{fq12_from_wires, fr_from_wires, wires_set_from_fq12, wires_set_from_g1p, wires_set_from_g2a};
7+
use crate::circuits::bn254::pairing::multi_miller_loop_groth16_circuit_evaluate;
8+
use crate::circuits::bn254::utils::{fq12_from_wires, fr_from_wires, wires_set_from_fq12, wires_set_from_g1p};
99

1010
pub fn fq12_mul_evaluate(a: Wires, b: Wires) -> (Wires, usize) {
1111
let circuit = Fq12::mul(a, b);
@@ -52,7 +52,7 @@ pub fn groth16_verifier_circuit(public: Wires, proof_a: Wires, proof_b: Wires, p
5252
let (msm, gc) = G1Projective::add_evaluate(msm_temp, wires_set_from_g1p(vk.gamma_abc_g1[0].into_group()));
5353
gate_count += gc;
5454

55-
let (f, gc) = multi_miller_loop_circuit_evaluate(vec![msm, proof_c, proof_a], vec![wires_set_from_g2a(-vk.gamma_g2), wires_set_from_g2a(-vk.delta_g2), proof_b]);
55+
let (f, gc) = multi_miller_loop_groth16_circuit_evaluate(msm, proof_c, proof_a, -vk.gamma_g2, -vk.delta_g2, proof_b);
5656
gate_count += gc;
5757

5858
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();
@@ -71,7 +71,7 @@ mod tests {
7171
use ark_ff::{PrimeField, UniformRand};
7272
use ark_relations::lc;
7373
use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, SynthesisError};
74-
use crate::circuits::bn254::utils::wires_set_from_fr;
74+
use crate::circuits::bn254::utils::{wires_set_from_fr, wires_set_from_g2a};
7575
use super::*;
7676

7777
#[derive(Copy)]

0 commit comments

Comments
 (0)