@@ -331,7 +331,7 @@ func decomposeScalarG1(mod *big.Int, inputs []*big.Int, outputs []*big.Int) erro
331331// The main idea is that since the computation of the square root involves taking large powers of u/v, the inversion of v can be avoided.
332332//
333333// nativeInputs[0] = u, nativeInputs[1]=v
334- // nativeOutput[0] = 1 if u/v is a QR, 0 otherwise, emulatedOutput[0]=sqrt(u/v) or sqrt(Z u/v)
334+ // nativeOutput[0] = 0 if u/v is a QR, 1 otherwise, emulatedOutput[0]=sqrt(u/v) or sqrt(Z u/v)
335335func g1SqrtRatioHint (nativeMod * big.Int , nativeInputs , nativeOutputs []* big.Int ) error {
336336 return emulated .UnwrapHintContext (nativeMod , nativeInputs , nativeOutputs , func (hc emulated.HintContext ) error {
337337 m := hc .EmulatedModuli ()
@@ -363,6 +363,13 @@ func g1SqrtRatioHint(nativeMod *big.Int, nativeInputs, nativeOutputs []*big.Int)
363363 })
364364}
365365
366+ // g2SqrtRatioHint computes the square root of u/v for E2 field elements and returns 0 iff u/v was indeed a quadratic residue
367+ // if not, we get sqrt(Z * u / v). Recall that Z is non-residue
368+ // If v = 0, u/v is meaningless and the output is unspecified, without raising an error.
369+ //
370+ // nativeInputs: u.A0, u.A1, v.A0, v.A1 (where u and v are E2 elements)
371+ // nativeOutput[0] = 0 if u/v is a QR, 1 otherwise
372+ // emulatedOutput[0], emulatedOutput[1] = sqrt(u/v) or sqrt(Z*u/v) as an E2 element
366373func g2SqrtRatioHint (nativeMod * big.Int , nativeInputs []* big.Int , nativeOutputs []* big.Int ) error {
367374 return emulated .UnwrapHintContext (nativeMod , nativeInputs , nativeOutputs , func (hc emulated.HintContext ) error {
368375 m := hc .EmulatedModuli ()
0 commit comments