1+ use std:: iter:: zip;
2+
13use ark_ec:: { bn:: BnConfig , short_weierstrass:: SWCurveConfig } ;
24use ark_ff:: { AdditiveGroup , Field , Fp2Config } ;
35use 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
412414pub 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) ]
454564mod 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}
0 commit comments