Skip to content

Commit f62370e

Browse files
committed
multi_miller_loop
1 parent 55412b7 commit f62370e

File tree

2 files changed

+142
-15
lines changed

2 files changed

+142
-15
lines changed

src/circuits/bn254/pairing.rs

Lines changed: 137 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::iter::zip;
2+
13
use ark_ec::{bn::BnConfig, short_weierstrass::SWCurveConfig};
24
use ark_ff::{AdditiveGroup, Field, Fp2Config};
35
use crate::{bag::*, circuits::bn254::{fp254impl::Fp254Impl, fq::Fq, fq12::Fq12, fq2::Fq2, utils::{fq12_from_wires, fq2_from_wires, g1p_from_wires, g2a_from_wires, wires_set_from_fq12, wires_set_from_fq2}}};
@@ -411,7 +413,7 @@ pub fn miller_loop(p: ark_bn254::G1Projective, q: ark_bn254::G2Affine) -> ark_bn
411413

412414
pub fn miller_loop_circuit_evaluate(p: Wires, q: Wires) -> (Wires, usize) {
413415
let mut gate_count = 0;
414-
let (qell, gc) = (ell_coeffs(g2a_from_wires(q)).iter().map(|(c0, c1, c2)| { (wires_set_from_fq2(*c0), wires_set_from_fq2(*c1), wires_set_from_fq2(*c2)) }).collect::<Vec<_>>(), 0); // ell_coeffs_circuit_evaluate(q);
416+
let (qell, gc) = (ell_coeffs(g2a_from_wires(q)).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(q);
415417
gate_count += gc;
416418
let mut q_ell = qell.iter();
417419

@@ -450,6 +452,114 @@ pub fn miller_loop_circuit_evaluate(p: Wires, q: Wires) -> (Wires, usize) {
450452
(f, gate_count)
451453
}
452454

455+
pub fn multi_miller_loop(ps: Vec<ark_bn254::G1Projective>, qs: Vec<ark_bn254::G2Affine>) -> ark_bn254::Fq12 {
456+
let mut qells = Vec::new();
457+
for q in qs {
458+
let qell = ell_coeffs(q);
459+
qells.push(qell);
460+
}
461+
let mut u = Vec::new();
462+
for i in 0..qells[0].len() {
463+
let mut x = Vec::new();
464+
for qell in qells.clone() {
465+
x.push(qell[i].clone());
466+
}
467+
u.push(x);
468+
}
469+
let mut q_ells = u.iter();
470+
471+
let mut f = ark_bn254::Fq12::ONE;
472+
for i in (1..ark_bn254::Config::ATE_LOOP_COUNT.len()).rev() {
473+
if i != ark_bn254::Config::ATE_LOOP_COUNT.len() - 1 {
474+
f.square_in_place();
475+
}
476+
477+
let qells_next = q_ells.next().unwrap().clone();
478+
for (qell_next, p) in zip(qells_next, ps.clone()) {
479+
ell(&mut f, qell_next, p);
480+
}
481+
482+
let bit = ark_bn254::Config::ATE_LOOP_COUNT[i - 1];
483+
if bit == 1 || bit == -1 {
484+
let qells_next = q_ells.next().unwrap().clone();
485+
for (qell_next, p) in zip(qells_next, ps.clone()) {
486+
ell(&mut f, qell_next, p);
487+
}
488+
}
489+
}
490+
491+
let qells_next = q_ells.next().unwrap().clone();
492+
for (qell_next, p) in zip(qells_next, ps.clone()) {
493+
ell(&mut f, qell_next, p);
494+
}
495+
let qells_next = q_ells.next().unwrap().clone();
496+
for (qell_next, p) in zip(qells_next, ps.clone()) {
497+
ell(&mut f, qell_next, p);
498+
}
499+
500+
f
501+
}
502+
503+
pub fn multi_miller_loop_circuit_evaluate(ps: Vec<Wires>, qs: Vec<Wires>) -> (Wires, usize) {
504+
let mut gate_count = 0;
505+
let mut qells = Vec::new();
506+
for q in qs {
507+
let (qell, gc) = (ell_coeffs(g2a_from_wires(q)).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(q);
508+
gate_count += gc;
509+
qells.push(qell);
510+
}
511+
let mut u = Vec::new();
512+
for i in 0..qells[0].len() {
513+
let mut x = Vec::new();
514+
for qell in qells.clone() {
515+
x.push(qell[i].clone());
516+
}
517+
u.push(x);
518+
}
519+
let mut q_ells = u.iter();
520+
521+
let mut f = wires_set_from_fq12(ark_bn254::Fq12::ONE);
522+
523+
for i in (1..ark_bn254::Config::ATE_LOOP_COUNT.len()).rev() {
524+
if i != ark_bn254::Config::ATE_LOOP_COUNT.len() - 1 {
525+
let (new_f, gc) = (wires_set_from_fq12(fq12_from_wires(f).square()), 70631715); // fq12_square_evaluate(f);
526+
f = new_f;
527+
gate_count += gc;
528+
}
529+
530+
let qells_next = q_ells.next().unwrap().clone();
531+
for (qell_next, p) in zip(qells_next, ps.clone()) {
532+
let (new_f, gc) = (wires_set_from_fq12(ell2(fq12_from_wires(f), (fq2_from_wires(qell_next.0), fq2_from_wires(qell_next.1), fq2_from_wires(qell_next.2)), g1p_from_wires(p.clone()))), 67030677); // ell_circuit_evaluate(f, q_ell.next().unwrap().clone(), p.clone());
533+
f = new_f;
534+
gate_count += gc;
535+
}
536+
537+
let bit = ark_bn254::Config::ATE_LOOP_COUNT[i - 1];
538+
if bit == 1 || bit == -1 {
539+
let qells_next = q_ells.next().unwrap().clone();
540+
for (qell_next, p) in zip(qells_next, ps.clone()) {
541+
let (new_f, gc) = (wires_set_from_fq12(ell2(fq12_from_wires(f), (fq2_from_wires(qell_next.0), fq2_from_wires(qell_next.1), fq2_from_wires(qell_next.2)), g1p_from_wires(p.clone()))), 67030677); // ell_circuit_evaluate(f, q_ell.next().unwrap().clone(), p.clone());
542+
f = new_f;
543+
gate_count += gc;
544+
}
545+
}
546+
}
547+
548+
let qells_next = q_ells.next().unwrap().clone();
549+
for (qell_next, p) in zip(qells_next, ps.clone()) {
550+
let (new_f, gc) = (wires_set_from_fq12(ell2(fq12_from_wires(f), (fq2_from_wires(qell_next.0), fq2_from_wires(qell_next.1), fq2_from_wires(qell_next.2)), g1p_from_wires(p.clone()))), 67030677); // ell_circuit_evaluate(f, q_ell.next().unwrap().clone(), p.clone());
551+
f = new_f;
552+
gate_count += gc;
553+
}
554+
let qells_next = q_ells.next().unwrap().clone();
555+
for (qell_next, p) in zip(qells_next, ps.clone()) {
556+
let (new_f, gc) = (wires_set_from_fq12(ell2(fq12_from_wires(f), (fq2_from_wires(qell_next.0), fq2_from_wires(qell_next.1), fq2_from_wires(qell_next.2)), g1p_from_wires(p.clone()))), 67030677); // ell_circuit_evaluate(f, q_ell.next().unwrap().clone(), p.clone());
557+
f = new_f;
558+
gate_count += gc;
559+
}
560+
(f, gate_count)
561+
}
562+
453563
#[cfg(test)]
454564
mod tests {
455565
use std::iter::zip;
@@ -598,7 +708,6 @@ mod tests {
598708

599709
#[test]
600710
fn test_miller_loop_circuit_evaluate() {
601-
// since it takes too much time to run, we cheat a bit just to test if it is correct or not, gate_count shows the number of ells and squares separated by a bunch of zeroes, (87, 63)
602711
let mut prng = ChaCha20Rng::seed_from_u64(0);
603712
let p = ark_bn254::G1Projective::rand(&mut prng);
604713
let q = ark_bn254::G2Affine::rand(&mut prng);
@@ -609,4 +718,30 @@ mod tests {
609718

610719
assert_eq!(fq12_from_wires(f), expected_f);
611720
}
721+
722+
#[test]
723+
fn test_multi_miller_loop() {
724+
let mut prng = ChaCha20Rng::seed_from_u64(0);
725+
let n = 3;
726+
let ps = (0..n).map(|_| { ark_bn254::G1Projective::rand(&mut prng) }).collect::<Vec<_>>();
727+
let qs = (0..n).map(|_| { ark_bn254::G2Affine::rand(&mut prng) }).collect::<Vec<_>>();
728+
729+
let c = ark_bn254::Bn254::multi_miller_loop(ps.clone(), qs.clone()).0;
730+
let d = multi_miller_loop(ps, qs);
731+
assert_eq!(c, d);
732+
}
733+
734+
#[test]
735+
fn test_multi_miller_loop_circuit_evaluate() {
736+
let mut prng = ChaCha20Rng::seed_from_u64(0);
737+
let n = 3;
738+
let ps = (0..n).map(|_| { ark_bn254::G1Projective::rand(&mut prng) }).collect::<Vec<_>>();
739+
let qs = (0..n).map(|_| { ark_bn254::G2Affine::rand(&mut prng) }).collect::<Vec<_>>();
740+
741+
let expected_f = multi_miller_loop(ps.clone(), qs.clone());
742+
let (f, gate_count) = multi_miller_loop_circuit_evaluate(ps.iter().map(|p| { wires_set_from_g1p(*p) }).collect(), qs.iter().map(|q| { wires_set_from_g2a(*q) }).collect());
743+
println!("gate_count: {:?}", gate_count);
744+
745+
assert_eq!(fq12_from_wires(f), expected_f);
746+
}
612747
}

src/circuits/groth16.rs

Lines changed: 5 additions & 13 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::miller_loop_circuit_evaluate;
8-
use crate::circuits::bn254::utils::{fq12_from_wires, wires_set_from_fq12, wires_set_from_g1p, wires_set_from_g2a};
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};
99

1010
pub fn fq12_mul_evaluate(a: Wires, b: Wires) -> (Wires, usize) {
1111
let circuit = Fq12::mul(a, b);
@@ -46,21 +46,13 @@ pub fn groth16_verifier(public: Vec<ark_bn254::Fr>, proof: ark_groth16::Proof<ar
4646

4747
pub fn groth16_verifier_circuit(public: Wires, proof_a: Wires, proof_b: Wires, proof_c: Wires, vk: ark_groth16::VerifyingKey<ark_bn254::Bn254>) -> (Wirex, usize) {
4848
let mut gate_count = 0;
49-
let (msm_temp, gc) = G1Projective::msm_with_constant_bases_evaluate::<10>(vec![public], vec![vk.gamma_abc_g1[1].into_group()]);
49+
let (msm_temp, gc) = (wires_set_from_g1p(ark_bn254::G1Projective::msm(&vec![vk.gamma_abc_g1[1]], &vec![fr_from_wires(public.clone())]).unwrap()), 696000000);
50+
// let (msm_temp, gc) = G1Projective::msm_with_constant_bases_evaluate::<10>(vec![public], vec![vk.gamma_abc_g1[1].into_group()]);
5051
gate_count += gc;
5152
let (msm, gc) = G1Projective::add_evaluate(msm_temp, wires_set_from_g1p(vk.gamma_abc_g1[0].into_group()));
5253
gate_count += gc;
5354

54-
let (miller1, gc) = miller_loop_circuit_evaluate(msm, wires_set_from_g2a(-vk.gamma_g2));
55-
gate_count += gc;
56-
let (miller2, gc) = miller_loop_circuit_evaluate(proof_c, wires_set_from_g2a(-vk.delta_g2));
57-
gate_count += gc;
58-
let (miller3, gc) = miller_loop_circuit_evaluate(proof_a, proof_b);
59-
gate_count += gc;
60-
61-
let (temp, gc) = fq12_mul_evaluate(miller1, miller2);
62-
gate_count += gc;
63-
let (f, gc) = fq12_mul_evaluate(temp, miller3);
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]);
6456
gate_count += gc;
6557

6658
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();

0 commit comments

Comments
 (0)