@@ -48,35 +48,55 @@ mod bn254 {
4848 _Q : & [ AffinePoint < Self :: Fp2 > ] ,
4949 ) -> ( Self :: Fp12 , Self :: Fp12 ) {
5050 // return dummy values
51- ( Fp12 :: ONE , Fp12 :: ZERO )
51+ ( Fp12 :: ZERO , Fp12 :: ZERO )
5252 }
5353
54+ // copied from Bn254::pairing_check
5455 fn pairing_check (
5556 P : & [ AffinePoint < Self :: Fp > ] ,
5657 Q : & [ AffinePoint < Self :: Fp2 > ] ,
5758 ) -> Result < ( ) , PairingCheckError > {
58- let ( c, u) = Self :: pairing_check_hint ( P , Q ) ;
59- // TODO: handle c = 0
60- let c_inv = Fp12 :: ONE . div_unsafe ( & c) ;
61-
62- // f * u == c^λ
63- // f * u == c^{6x + 2 + q^3 - q^2 + q}
64- // f * c^-{6x + 2} * u * c^-{q^3 - q^2 + q} == 1
65- // where fc == f * c^-{6x + 2}
66- // c_mul = c^-{q^3 - q^2 + q}
67- let c_q3_inv = FieldExtension :: frobenius_map ( & c_inv, 3 ) ;
68- let c_q2 = FieldExtension :: frobenius_map ( & c, 2 ) ;
69- let c_q_inv = FieldExtension :: frobenius_map ( & c_inv, 1 ) ;
70- let c_mul = c_q3_inv * c_q2 * c_q_inv;
71-
72- // Compute miller loop with c_inv
73- let fc = Bn254 :: multi_miller_loop_embedded_exp ( P , Q , Some ( c_inv) ) ;
74-
75- if fc * c_mul * u == Fp12 :: ONE {
76- Ok ( ( ) )
77- } else {
59+ Self :: try_honest_pairing_check ( P , Q ) . unwrap_or_else ( || {
7860 let f = Bn254 :: multi_miller_loop ( P , Q ) ;
7961 exp_check_fallback ( & f, & Bn254 :: FINAL_EXPONENT )
62+ } )
63+ }
64+ }
65+
66+ #[ allow( non_snake_case) ]
67+ impl Bn254Wrapper {
68+ // copied from Bn254::try_honest_pairing_check
69+ fn try_honest_pairing_check (
70+ P : & [ AffinePoint < <Self as PairingCheck >:: Fp > ] ,
71+ Q : & [ AffinePoint < <Self as PairingCheck >:: Fp2 > ] ,
72+ ) -> Option < Result < ( ) , PairingCheckError > > {
73+ let ( c, s) = Self :: pairing_check_hint ( P , Q ) ;
74+
75+ // f * s = c^{q - x}
76+ // f * s = c^q * c^-x
77+ // f * c^x * c^-q * s = 1,
78+ // where fc = f * c'^x (embedded Miller loop with c conjugate inverse),
79+ // and the curve seed x = -0xd201000000010000
80+ // the miller loop computation includes a conjugation at the end because the value of the
81+ // seed is negative, so we need to conjugate the miller loop input c as c'. We then substitute
82+ // y = -x to get c^-y and finally compute c'^-y as input to the miller loop:
83+ // f * c'^-y * c^-q * s = 1
84+ let c_q = FieldExtension :: frobenius_map ( & c, 1 ) ;
85+ let c_conj = c. conjugate ( ) ;
86+ if c_conj == Fp12 :: ZERO {
87+ return None ;
88+ }
89+ let c_conj_inv = Fp12 :: ONE . div_unsafe ( & c_conj) ;
90+
91+ // fc = f_{Miller,x,Q}(P) * c^{x}
92+ // where
93+ // fc = conjugate( f_{Miller,-x,Q}(P) * c'^{-x} ), with c' denoting the conjugate of c
94+ let fc = Bn254 :: multi_miller_loop_embedded_exp ( P , Q , Some ( c_conj_inv) ) ;
95+
96+ if fc * s == c_q {
97+ Some ( Ok ( ( ) ) )
98+ } else {
99+ None
80100 }
81101 }
82102 }
@@ -141,13 +161,28 @@ mod bls12_381 {
141161 _Q : & [ AffinePoint < Self :: Fp2 > ] ,
142162 ) -> ( Self :: Fp12 , Self :: Fp12 ) {
143163 // return dummy values
144- ( Fp12 :: ONE , Fp12 :: ZERO )
164+ ( Fp12 :: ZERO , Fp12 :: ZERO )
145165 }
146166
167+ // copied from Bls12_381::pairing_check
147168 fn pairing_check (
148169 P : & [ AffinePoint < Self :: Fp > ] ,
149170 Q : & [ AffinePoint < Self :: Fp2 > ] ,
150171 ) -> Result < ( ) , PairingCheckError > {
172+ Self :: try_honest_pairing_check ( P , Q ) . unwrap_or_else ( || {
173+ let f = Bls12_381 :: multi_miller_loop ( P , Q ) ;
174+ exp_check_fallback ( & f, & Bls12_381 :: FINAL_EXPONENT )
175+ } )
176+ }
177+ }
178+
179+ #[ allow( non_snake_case) ]
180+ impl Bls12_381Wrapper {
181+ // copied from Bls12_381::try_honest_pairing_check
182+ fn try_honest_pairing_check (
183+ P : & [ AffinePoint < <Self as PairingCheck >:: Fp > ] ,
184+ Q : & [ AffinePoint < <Self as PairingCheck >:: Fp2 > ] ,
185+ ) -> Option < Result < ( ) , PairingCheckError > > {
151186 let ( c, s) = Self :: pairing_check_hint ( P , Q ) ;
152187
153188 // f * s = c^{q - x}
@@ -160,19 +195,21 @@ mod bls12_381 {
160195 // y = -x to get c^-y and finally compute c'^-y as input to the miller loop:
161196 // f * c'^-y * c^-q * s = 1
162197 let c_q = FieldExtension :: frobenius_map ( & c, 1 ) ;
163- // TODO: handle c = 0
164- let c_conj_inv = Fp12 :: ONE . div_unsafe ( & c. conjugate ( ) ) ;
198+ let c_conj = c. conjugate ( ) ;
199+ if c_conj == Fp12 :: ZERO {
200+ return None ;
201+ }
202+ let c_conj_inv = Fp12 :: ONE . div_unsafe ( & c_conj) ;
165203
166204 // fc = f_{Miller,x,Q}(P) * c^{x}
167205 // where
168206 // fc = conjugate( f_{Miller,-x,Q}(P) * c'^{-x} ), with c' denoting the conjugate of c
169207 let fc = Bls12_381 :: multi_miller_loop_embedded_exp ( P , Q , Some ( c_conj_inv) ) ;
170208
171209 if fc * s == c_q {
172- Ok ( ( ) )
210+ Some ( Ok ( ( ) ) )
173211 } else {
174- let f = Bls12_381 :: multi_miller_loop ( P , Q ) ;
175- exp_check_fallback ( & f, & Bls12_381 :: FINAL_EXPONENT )
212+ None
176213 }
177214 }
178215 }
0 commit comments