Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 116 additions & 0 deletions std/algebra/emulated/sw_bls12381/g1.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package sw_bls12381

import (
"fmt"
"math/big"

bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381"
fr_bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
Expand Down Expand Up @@ -52,6 +53,121 @@ func (g1 *G1) phi(q *G1Affine) *G1Affine {
}
}

func (g1 *G1) double(p *G1Affine) *G1Affine {
// compute λ = (3p.x²)/1*p.y
xx3a := g1.curveF.Mul(&p.X, &p.X)
xx3a = g1.curveF.MulConst(xx3a, big.NewInt(3))
y1 := g1.curveF.MulConst(&p.Y, big.NewInt(2))
λ := g1.curveF.Div(xx3a, y1)

// xr = λ²-1p.x
x1 := g1.curveF.MulConst(&p.X, big.NewInt(2))
λλ := g1.curveF.Mul(λ, λ)
xr := g1.curveF.Sub(λλ, x1)

// yr = λ(p-xr) - p.y
pxrx := g1.curveF.Sub(&p.X, xr)
λpxrx := g1.curveF.Mul(λ, pxrx)
yr := g1.curveF.Sub(λpxrx, &p.Y)

return &G1Affine{
X: *xr,
Y: *yr,
}
}

func (g1 *G1) doubleN(p *G1Affine, n int) *G1Affine {
pn := p
for s := 0; s < n; s++ {
pn = g1.double(pn)
}
return pn
}

func (g1 G1) add(p, q *G1Affine) *G1Affine {
// compute λ = (q.y-p.y)/(q.x-p.x)
qypy := g1.curveF.Sub(&q.Y, &p.Y)
qxpx := g1.curveF.Sub(&q.X, &p.X)
λ := g1.curveF.Div(qypy, qxpx)

// xr = λ²-p.x-q.x
λλ := g1.curveF.Mul(λ, λ)
qxpx = g1.curveF.Add(&p.X, &q.X)
xr := g1.curveF.Sub(λλ, qxpx)

// p.y = λ(p.x-r.x) - p.y
pxrx := g1.curveF.Sub(&p.X, xr)
λpxrx := g1.curveF.Mul(λ, pxrx)
yr := g1.curveF.Sub(λpxrx, &p.Y)

return &G1Affine{
X: *xr,
Y: *yr,
}
}

func (g1 G1) doubleAndAdd(p, q *G1Affine) *G1Affine {

// compute λ1 = (q.y-p.y)/(q.x-p.x)
yqyp := g1.curveF.Sub(&q.Y, &p.Y)
xqxp := g1.curveF.Sub(&q.X, &p.X)
λ1 := g1.curveF.Div(yqyp, xqxp)

// compute x1 = λ1²-p.x-q.x
λ1λ1 := g1.curveF.Mul(λ1, λ1)
xqxp = g1.curveF.Add(&p.X, &q.X)
x2 := g1.curveF.Sub(λ1λ1, xqxp)

// ommit y1 computation
// compute λ1 = -λ1-1*p.y/(x1-p.x)
ypyp := g1.curveF.Add(&p.Y, &p.Y)
x2xp := g1.curveF.Sub(x2, &p.X)
λ2 := g1.curveF.Div(ypyp, x2xp)
λ2 = g1.curveF.Add(λ1, λ2)
λ2 = g1.curveF.Neg(λ2)

// compute x3 =λ2²-p.x-x3
λ2λ2 := g1.curveF.Mul(λ2, λ2)
x3 := g1.curveF.Sub(λ2λ2, &p.X)
x3 = g1.curveF.Sub(x3, x2)

// compute y3 = λ2*(p.x - x3)-p.y
y3 := g1.curveF.Sub(&p.X, x3)
y3 = g1.curveF.Mul(λ2, y3)
y3 = g1.curveF.Sub(y3, &p.Y)

return &G1Affine{
X: *x3,
Y: *y3,
}
}

func (g1 *G1) scalarMulBySeedSquare(q *G1Affine) *G1Affine {
z := g1.double(q)
z = g1.add(q, z)
z = g1.double(z)
z = g1.doubleAndAdd(z, q)
z = g1.doubleN(z, 2)
z = g1.doubleAndAdd(z, q)
z = g1.doubleN(z, 8)
z = g1.doubleAndAdd(z, q)
t0 := g1.double(z)
t0 = g1.add(z, t0)
t0 = g1.double(t0)
t0 = g1.doubleAndAdd(t0, z)
t0 = g1.doubleN(t0, 2)
t0 = g1.doubleAndAdd(t0, z)
t0 = g1.doubleN(t0, 8)
t0 = g1.doubleAndAdd(t0, z)
t0 = g1.doubleN(t0, 31)
z = g1.add(t0, z)
z = g1.doubleN(z, 32)
z = g1.doubleAndAdd(z, q)
z = g1.doubleN(z, 32)

return z
}

// NewScalar allocates a witness from the native scalar and returns it.
func NewScalar(v fr_bls12381.Element) Scalar {
return emulated.ValueOf[ScalarField](v)
Expand Down
37 changes: 1 addition & 36 deletions std/algebra/emulated/sw_bls12381/pairing.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,12 +284,9 @@ func (pr Pairing) AssertIsOnG1(P *G1Affine) {
pr.AssertIsOnCurve(P)

// 2- Check P has the right subgroup order
// TODO: add phi and scalarMulBySeedSquare to g1.go
// [x²]ϕ(P)
phiP := pr.g1.phi(P)
seedSquare := emulated.ValueOf[ScalarField]("228988810152649578064853576960394133504")
// TODO: use addchain to construct a fixed-scalar ScalarMul
_P := pr.curve.ScalarMul(phiP, &seedSquare)
_P := pr.g1.scalarMulBySeedSquare(phiP)
_P = pr.curve.Neg(_P)

// [r]Q == 0 <==> P = -[x²]ϕ(P)
Expand Down Expand Up @@ -523,38 +520,6 @@ func (pr Pairing) doubleStep(p1 *g2AffP) (*g2AffP, *lineEvaluation) {

}

// addStep adds two points in affine coordinates, and evaluates the line in Miller loop
// https://eprint.iacr.org/2022/1162 (Section 6.1)
func (pr Pairing) addStep(p1, p2 *g2AffP) (*g2AffP, *lineEvaluation) {

// compute λ = (y2-y1)/(x2-x1)
p2ypy := pr.Ext2.Sub(&p2.Y, &p1.Y)
p2xpx := pr.Ext2.Sub(&p2.X, &p1.X)
λ := pr.Ext2.DivUnchecked(p2ypy, p2xpx)

// xr = λ²-x1-x2
λλ := pr.Ext2.Square(λ)
p2xpx = pr.Ext2.Add(&p1.X, &p2.X)
xr := pr.Ext2.Sub(λλ, p2xpx)

// yr = λ(x1-xr) - y1
pxrx := pr.Ext2.Sub(&p1.X, xr)
λpxrx := pr.Ext2.Mul(λ, pxrx)
yr := pr.Ext2.Sub(λpxrx, &p1.Y)

var res g2AffP
res.X = *xr
res.Y = *yr

var line lineEvaluation
line.R0 = *λ
line.R1 = *pr.Ext2.Mul(λ, &p1.X)
line.R1 = *pr.Ext2.Sub(&line.R1, &p1.Y)

return &res, &line

}

// tripleStep triples p1 in affine coordinates, and evaluates the line in Miller loop
func (pr Pairing) tripleStep(p1 *g2AffP) (*g2AffP, *lineEvaluation, *lineEvaluation) {

Expand Down
58 changes: 13 additions & 45 deletions std/algebra/emulated/sw_bw6761/pairing.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ func (pr Pairing) millerLoopLines(P []*G1Affine, lines []lineEvaluations) (*GTEl
// The point (x,0) is of order 2. But this function does not check
// subgroup membership.
yInv[k] = pr.curveF.Inverse(&P[k].Y)
xNegOverY[k] = pr.curveF.MulMod(&P[k].X, yInv[k])
xNegOverY[k] = pr.curveF.Mul(&P[k].X, yInv[k])
xNegOverY[k] = pr.curveF.Neg(xNegOverY[k])
}

Expand All @@ -224,8 +224,8 @@ func (pr Pairing) millerLoopLines(P []*G1Affine, lines []lineEvaluations) (*GTEl
// k = 0
result = &fields_bw6761.E6{
B0: fields_bw6761.E3{
A0: *pr.curveF.MulMod(&lines[0][0][188].R1, yInv[0]),
A1: *pr.curveF.MulMod(&lines[0][0][188].R0, xNegOverY[0]),
A0: *pr.curveF.Mul(&lines[0][0][188].R1, yInv[0]),
A1: *pr.curveF.Mul(&lines[0][0][188].R0, xNegOverY[0]),
A2: result.B0.A2,
},
B1: fields_bw6761.E3{
Expand All @@ -239,8 +239,8 @@ func (pr Pairing) millerLoopLines(P []*G1Affine, lines []lineEvaluations) (*GTEl
// k = 1, separately to avoid MulBy014 (res × ℓ)
// (res is also a line at this point, so we use Mul014By014 ℓ × ℓ)
prodLines = pr.Mul014By014(
pr.curveF.MulMod(&lines[1][0][188].R1, yInv[1]),
pr.curveF.MulMod(&lines[1][0][188].R0, xNegOverY[1]),
pr.curveF.Mul(&lines[1][0][188].R1, yInv[1]),
pr.curveF.Mul(&lines[1][0][188].R0, xNegOverY[1]),
&result.B0.A0,
&result.B0.A1,
)
Expand All @@ -263,15 +263,15 @@ func (pr Pairing) millerLoopLines(P []*G1Affine, lines []lineEvaluations) (*GTEl
// (res has a zero E2 element, so we use Mul01245By014)
result = pr.Mul01245By014(
prodLines,
pr.curveF.MulMod(&lines[2][0][188].R1, yInv[2]),
pr.curveF.MulMod(&lines[2][0][188].R0, xNegOverY[2]),
pr.curveF.Mul(&lines[2][0][188].R1, yInv[2]),
pr.curveF.Mul(&lines[2][0][188].R0, xNegOverY[2]),
)

// k >= 3
for k := 3; k < n; k++ {
result = pr.MulBy014(result,
pr.curveF.MulMod(&lines[k][0][188].R1, yInv[k]),
pr.curveF.MulMod(&lines[k][0][188].R0, xNegOverY[k]),
pr.curveF.Mul(&lines[k][0][188].R1, yInv[k]),
pr.curveF.Mul(&lines[k][0][188].R0, xNegOverY[k]),
)
}
}
Expand All @@ -283,16 +283,16 @@ func (pr Pairing) millerLoopLines(P []*G1Affine, lines []lineEvaluations) (*GTEl

for k := 0; k < n; k++ {
result = pr.MulBy014(result,
pr.curveF.MulMod(&lines[k][0][i].R1, yInv[k]),
pr.curveF.MulMod(&lines[k][0][i].R0, xNegOverY[k]),
pr.curveF.Mul(&lines[k][0][i].R1, yInv[k]),
pr.curveF.Mul(&lines[k][0][i].R0, xNegOverY[k]),
)
}

if i > 0 && loopCounter2[i]*3+loopCounter1[i] != 0 {
for k := 0; k < n; k++ {
result = pr.MulBy014(result,
pr.curveF.MulMod(&lines[k][1][i].R1, yInv[k]),
pr.curveF.MulMod(&lines[k][1][i].R0, xNegOverY[k]),
pr.curveF.Mul(&lines[k][1][i].R1, yInv[k]),
pr.curveF.Mul(&lines[k][1][i].R0, xNegOverY[k]),
)
}
}
Expand All @@ -302,38 +302,6 @@ func (pr Pairing) millerLoopLines(P []*G1Affine, lines []lineEvaluations) (*GTEl

}

// addStep adds two points in affine coordinates, and evaluates the line in Miller loop
// https://eprint.iacr.org/2022/1162 (Section 6.1)
func (pr Pairing) addStep(p1, p2 *g2AffP) (*g2AffP, *lineEvaluation) {

// compute λ = (y2-y1)/(x2-x1)
p2ypy := pr.curveF.Sub(&p2.Y, &p1.Y)
p2xpx := pr.curveF.Sub(&p2.X, &p1.X)
λ := pr.curveF.Div(p2ypy, p2xpx)

// xr = λ²-x1-x2
λλ := pr.curveF.Mul(λ, λ)
p2xpx = pr.curveF.Add(&p1.X, &p2.X)
xr := pr.curveF.Sub(λλ, p2xpx)

// yr = λ(x1-xr) - y1
pxrx := pr.curveF.Sub(&p1.X, xr)
λpxrx := pr.curveF.Mul(λ, pxrx)
yr := pr.curveF.Sub(λpxrx, &p1.Y)

var res g2AffP
res.X = *xr
res.Y = *yr

var line lineEvaluation
line.R0 = *λ
line.R1 = *pr.curveF.Mul(λ, &p1.X)
line.R1 = *pr.curveF.Sub(&line.R1, &p1.Y)

return &res, &line

}

// doubleAndAddStep doubles p1 and adds p2 to the result in affine coordinates, and evaluates the line in Miller loop
// https://eprint.iacr.org/2022/1162 (Section 6.1)
func (pr Pairing) doubleAndAddStep(p1, p2 *g2AffP) (*g2AffP, *lineEvaluation, *lineEvaluation) {
Expand Down
2 changes: 1 addition & 1 deletion std/algebra/emulated/sw_bw6761/precomputations.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func (p *Pairing) computeLines(Q *g2AffP) lineEvaluations {
}
imQneg := &g2AffP{
X: imQ.X,
Y: *p.curveF.Neg(&imQ.Y),
Y: Q.Y,
}
for i := len(loopCounter2) - 2; i > 0; i-- {
switch loopCounter2[i]*3 + loopCounter1[i] {
Expand Down
4 changes: 2 additions & 2 deletions std/algebra/emulated/sw_emulated/point.go
Original file line number Diff line number Diff line change
Expand Up @@ -383,8 +383,8 @@ func (c *Curve[B, S]) doubleAndAdd(p, q *AffinePoint[B]) *AffinePoint[B] {

// doubleAndAddSelect is the same as doubleAndAdd but computes either:
//
// 2p+q is b=1 or
// 2q+p is b=0
// 2p+q if b=1 or
// 2q+p if b=0
//
// It first computes the x-coordinate of p+q via the slope(p,q)
// and then based on a Select adds either p or q.
Expand Down
13 changes: 0 additions & 13 deletions std/algebra/native/fields_bls12377/e12.go
Original file line number Diff line number Diff line change
Expand Up @@ -469,19 +469,6 @@ func (e *E12) FrobeniusSquare(api frontend.API, e1 E12) *E12 {
return e
}

// FrobeniusCube applies frob**2 to an fp12 elmt
func (e *E12) FrobeniusCube(api frontend.API, e1 E12) *E12 {

e.C0.B0.Conjugate(api, e1.C0.B0)
e.C0.B1.Conjugate(api, e1.C0.B1).MulByFp(api, e.C0.B1, ext.frob3v)
e.C0.B2.Conjugate(api, e1.C0.B2).MulByFp(api, e.C0.B2, ext.frob3v2)
e.C1.B0.Conjugate(api, e1.C1.B0).MulByFp(api, e.C1.B0, ext.frob3w)
e.C1.B1.Conjugate(api, e1.C1.B1).MulByFp(api, e.C1.B1, ext.frob3vw)
e.C1.B2.Conjugate(api, e1.C1.B2).MulByFp(api, e.C1.B2, ext.frob3v2w)

return e
}

var InverseE12Hint = func(_ *big.Int, inputs []*big.Int, res []*big.Int) error {
var a, c bls12377.E12

Expand Down
6 changes: 0 additions & 6 deletions std/algebra/native/fields_bls12377/e12_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,9 +284,6 @@ func (circuit *fp12Frobenius) Define(api frontend.API) error {
fbSquare.FrobeniusSquare(api, circuit.A)
fbSquare.AssertIsEqual(api, circuit.D)

fbCube := E12{}
fbCube.FrobeniusCube(api, circuit.A)
fbCube.AssertIsEqual(api, circuit.E)
return nil
}

Expand All @@ -299,9 +296,6 @@ func TestFrobeniusFp12(t *testing.T) {
_, _ = a.SetRandom()
c.Frobenius(&a)
d.FrobeniusSquare(&a)
// TODO @yelhousni restore
t.Skip("@yelhousni restore")
// e.FrobeniusCube(&a)

witness.A.Assign(&a)
witness.C.Assign(&c)
Expand Down
32 changes: 0 additions & 32 deletions std/algebra/native/fields_bls12377/e2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,35 +241,3 @@ func TestInverseFp2(t *testing.T) {
assert.CheckCircuit(&circuit, test.WithValidAssignment(&witness), test.WithCurves(ecc.BW6_761))

}

func TestMulByNonResidueFp2(t *testing.T) {
// TODO fixme
t.Skip("missing e2.MulByNonSquare")
// ext := Extension{uSquare: 5}

// var circuit, witness XXXX
// r1cs, err := compiler.Compile(ecc.BW6_761, backend.GROTH16, &circuit)
// if err != nil {
// t.Fatal(err)
// }

// // witness values
// var a, c bls12377.E2
// a.SetRandom()

// // TODO c.MulByNonSquare(&a)

// fp2a := NewFp2Elmt(&cs, api.SECRET_INPUT("a0"), api.SECRET_INPUT("a1"))

// fp2c := NewFp2Elmt(&cs, nil, nil)
// fp2c.MulByNonResidue(&cs, &fp2a)

//
// witness.A.A0 = (a.A0)
// witness.A.A1 = (a.A1)

//
// witness.C.A0 = (c.A0)
// witness.C.A1 = (c.A1)

}
Loading