diff --git a/std/algebra/native/sw_bls12377/g1.go b/std/algebra/native/sw_bls12377/g1.go index 6db8bb2ffb..0b38709c63 100644 --- a/std/algebra/native/sw_bls12377/g1.go +++ b/std/algebra/native/sw_bls12377/g1.go @@ -713,16 +713,19 @@ func (R *G1Affine) scalarMulGLVAndFakeGLV(api frontend.API, P G1Affine, s fronte if err != nil { panic(fmt.Sprintf("halfGCDEisenstein hint: %v", err)) } - u1, u2, v1, v2, w1, w2, r1, r2, s1, s2 := sd[0], sd[1], sd[2], sd[3], sd[4], sd[5], sd[6], sd[7], sd[8], sd[9] + u1, u2, v1, v2, w1, w2, _, _, s1, s2 := sd[0], sd[1], sd[2], sd[3], sd[4], sd[5], sd[6], sd[7], sd[8], sd[9] + // r is fixed and is equal to 91893752504881257701523279626832445440 - ω + var r1 big.Int + r1.SetString("91893752504881257701523279626832445440", 10) // Eisenstein integers real and imaginary parts can be negative. So we // return the absolute value in the hint and negate the corresponsing // points here when needed. - signs, err := api.NewHint(halfGCDEisensteinSigns, 10, _s, cc.lambda) + signs, err := api.NewHint(halfGCDEisensteinSigns, 6, _s, cc.lambda) if err != nil { panic(fmt.Sprintf("halfGCDEisensteinSigns hint: %v", err)) } - selector1, selector2, selector3, selector4, selector5, selector6, selector7, selector8, selector9, selector10 := signs[0], signs[1], signs[2], signs[3], signs[4], signs[5], signs[6], signs[7], signs[8], signs[9] + selector1, selector2, selector3, selector4, selector5, selector6 := signs[0], signs[1], signs[2], signs[3], signs[4], signs[5] // We need to check that: // (s1 + j*s2)(v1 + j*v2) + (r1 + j*r2)(w1 + j*w2) - (u1 + j*u2) = 0 @@ -739,21 +742,13 @@ func (R *G1Affine) scalarMulGLVAndFakeGLV(api frontend.API, P G1Affine, s fronte s1v2 := api.Mul(s1, v2) s2v1 := api.Mul(s2, v1) r1w2 := api.Mul(r1, w2) - r2w1 := api.Mul(r2, w1) - - xor1 := api.Xor(selector9, selector3) - xor2 := api.Xor(selector7, selector5) - xor3 := api.Xor(selector9, selector4) - xor4 := api.Xor(selector10, selector3) - xor5 := api.Xor(selector7, selector6) - xor6 := api.Xor(selector8, selector5) - - lhs1 := api.Select(xor1, 0, s1v1) - lhs2 := api.Select(xor2, 0, r1w1) - lhs3 := api.Select(xor3, s1v2, 0) - lhs4 := api.Select(xor4, s2v1, 0) - lhs5 := api.Select(xor5, r1w2, 0) - lhs6 := api.Select(xor6, r2w1, 0) + + lhs1 := api.Select(selector3, s1v1, 0) + lhs2 := api.Select(selector5, 0, r1w1) + lhs3 := api.Select(selector4, 0, s1v2) + lhs4 := api.Select(selector3, 0, s2v1) + lhs5 := api.Select(selector6, r1w2, 0) + lhs6 := api.Select(selector5, 0, w1) lhs7 := api.Select(selector1, u1, 0) lhs8 := api.Select(selector2, 0, u2) lhs := api.Add( @@ -769,12 +764,12 @@ func (R *G1Affine) scalarMulGLVAndFakeGLV(api frontend.API, P G1Affine, s fronte api.Add(lhs7, lhs8), ) - rhs1 := api.Select(xor1, s1v1, 0) - rhs2 := api.Select(xor2, r1w1, 0) - rhs3 := api.Select(xor3, 0, s1v2) - rhs4 := api.Select(xor4, 0, s2v1) - rhs5 := api.Select(xor5, 0, r1w2) - rhs6 := api.Select(xor6, 0, r2w1) + rhs1 := api.Select(selector3, 0, s1v1) + rhs2 := api.Select(selector5, r1w1, 0) + rhs3 := api.Select(selector4, s1v2, 0) + rhs4 := api.Select(selector3, s2v1, 0) + rhs5 := api.Select(selector6, 0, r1w2) + rhs6 := api.Select(selector5, w1, 0) rhs7 := api.Select(selector1, 0, u1) rhs8 := api.Select(selector2, u2, 0) rhs := api.Add( diff --git a/std/algebra/native/sw_bls12377/hints.go b/std/algebra/native/sw_bls12377/hints.go index 3b1cfe509b..da3f71a054 100644 --- a/std/algebra/native/sw_bls12377/hints.go +++ b/std/algebra/native/sw_bls12377/hints.go @@ -125,9 +125,11 @@ func halfGCDEisenstein(mod *big.Int, inputs []*big.Int, outputs []*big.Int) erro A0: &glvBasis.V1[0], A1: &glvBasis.V1[1], } + // r = 91893752504881257701523279626832445440 - ω sp := ecc.SplitScalar(inputs[0], glvBasis) // in-circuit we check that Q - [s]P = 0 or equivalently Q + [-s]P = 0 // so here we return -s instead of s. + // s.A0 and s.A1 are always positive. s := eisenstein.ComplexNumber{ A0: &sp[0], A1: &sp[1], @@ -181,11 +183,12 @@ func halfGCDEisensteinSigns(mod *big.Int, inputs, outputs []*big.Int) error { if len(inputs) != 2 { return fmt.Errorf("expecting two input") } - if len(outputs) != 10 { - return fmt.Errorf("expecting ten outputs") + if len(outputs) != 6 { + return fmt.Errorf("expecting six outputs") } glvBasis := new(ecc.Lattice) ecc.PrecomputeLattice(mod, inputs[1], glvBasis) + // r = 91893752504881257701523279626832445440 - ω r := eisenstein.ComplexNumber{ A0: &glvBasis.V1[0], A1: &glvBasis.V1[1], @@ -205,10 +208,6 @@ func halfGCDEisensteinSigns(mod *big.Int, inputs, outputs []*big.Int) error { outputs[3].SetUint64(0) outputs[4].SetUint64(0) outputs[5].SetUint64(0) - outputs[6].SetUint64(0) - outputs[7].SetUint64(0) - outputs[8].SetUint64(0) - outputs[9].SetUint64(0) res := eisenstein.HalfGCD(&r, &s) if res[0].A0.Sign() == -1 { outputs[0].SetUint64(1) @@ -228,18 +227,6 @@ func halfGCDEisensteinSigns(mod *big.Int, inputs, outputs []*big.Int) error { if res[2].A1.Sign() == -1 { outputs[5].SetUint64(1) } - if r.A0.Sign() == -1 { - outputs[6].SetUint64(1) - } - if r.A1.Sign() == -1 { - outputs[7].SetUint64(1) - } - if s.A0.Sign() == -1 { - outputs[8].SetUint64(1) - } - if s.A1.Sign() == -1 { - outputs[9].SetUint64(1) - } return nil }