Skip to content

Commit

Permalink
perf: G1/2 membership using Eval (#1356)
Browse files Browse the repository at this point in the history
  • Loading branch information
yelhousni authored Dec 16, 2024
1 parent 627dc59 commit 0a3bf3c
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 85 deletions.
49 changes: 19 additions & 30 deletions std/algebra/emulated/sw_bls12381/g1.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,21 +54,18 @@ func (g1 *G1) phi(q *G1Affine) *G1Affine {
}

func (g1 *G1) double(p *G1Affine) *G1Affine {
// compute λ = (3p.x²)/1*p.y
mone := g1.curveF.NewElement(-1)
// compute λ = (3p.x²)/2*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)
// xr = λ²-2p.x
xr := g1.curveF.Eval([][]*baseEl{{λ, λ}, {mone, &p.X}}, []int{1, 2})

// yr = λ(p-xr) - p.y
pxrx := g1.curveF.Sub(&p.X, xr)
λpxrx := g1.curveF.Mul(λ, pxrx)
yr := g1.curveF.Sub(λpxrx, &p.Y)
yr := g1.curveF.Eval([][]*baseEl{{λ, g1.curveF.Sub(&p.X, xr)}, {mone, &p.Y}}, []int{1, 1})

return &G1Affine{
X: *xr,
Expand All @@ -85,20 +82,17 @@ func (g1 *G1) doubleN(p *G1Affine, n int) *G1Affine {
}

func (g1 G1) add(p, q *G1Affine) *G1Affine {
mone := g1.curveF.NewElement(-1)
// 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)
xr := g1.curveF.Eval([][]*baseEl{{λ, λ}, {mone, g1.curveF.Add(&p.X, &q.X)}}, []int{1, 1})

// 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)
// p.y = λ(p.x-xr) - p.y
yr := g1.curveF.Eval([][]*baseEl{{λ, g1.curveF.Sub(&p.X, xr)}, {mone, &p.Y}}, []int{1, 1})

return &G1Affine{
X: *xr,
Expand All @@ -108,33 +102,28 @@ func (g1 G1) add(p, q *G1Affine) *G1Affine {

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

mone := g1.curveF.NewElement(-1)
// 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)
x2 := g1.curveF.Eval([][]*baseEl{{λ1, λ1}, {mone, g1.curveF.Add(&p.X, &q.X)}}, []int{1, 1})

// omit y1 computation
// compute λ1 = -λ1-1*p.y/(x1-p.x)
ypyp := g1.curveF.Add(&p.Y, &p.Y)
// omit y2 computation

// compute -λ2 = λ1+2*p.y/(x2-p.x)
ypyp := g1.curveF.MulConst(&p.Y, big.NewInt(2))
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 x3 = (-λ2)²-p.x-x2
x3 := g1.curveF.Eval([][]*baseEl{{λ2, λ2}, {mone, &p.X}, {mone, x2}}, []int{1, 1, 1})

// 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)
// compute y3 = -λ2*(x3- p.x)-p.y
y3 := g1.curveF.Eval([][]*baseEl{{λ2, g1.curveF.Sub(x3, &p.X)}, {mone, &p.Y}}, []int{1, 1})

return &G1Affine{
X: *x3,
Expand Down
94 changes: 55 additions & 39 deletions std/algebra/emulated/sw_bls12381/g2.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
)

type G2 struct {
fp *emulated.Field[BaseField]
*fields_bls12381.Ext2
u1, w *emulated.Element[BaseField]
v *fields_bls12381.E2
Expand Down Expand Up @@ -39,13 +40,19 @@ func newG2AffP(v bls12381.G2Affine) g2AffP {
}

func NewG2(api frontend.API) *G2 {
fp, err := emulated.NewField[emulated.BLS12381Fp](api)
if err != nil {
// TODO: we start returning errors when generifying
panic(err)
}
w := emulated.ValueOf[BaseField]("4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436")
u1 := emulated.ValueOf[BaseField]("4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939437")
v := fields_bls12381.E2{
A0: emulated.ValueOf[BaseField]("2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530"),
A1: emulated.ValueOf[BaseField]("1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257"),
}
return &G2{
fp: fp,
Ext2: fields_bls12381.NewExt2(api),
w: &w,
u1: &u1,
Expand Down Expand Up @@ -113,20 +120,23 @@ func (g2 *G2) scalarMulBySeed(q *G2Affine) *G2Affine {
}

func (g2 G2) add(p, q *G2Affine) *G2Affine {
mone := g2.fp.NewElement(-1)

// compute λ = (q.y-p.y)/(q.x-p.x)
qypy := g2.Ext2.Sub(&q.P.Y, &p.P.Y)
qxpx := g2.Ext2.Sub(&q.P.X, &p.P.X)
λ := g2.Ext2.DivUnchecked(qypy, qxpx)

// xr = λ²-p.x-q.x
λλ := g2.Ext2.Square(λ)
qxpx = g2.Ext2.Add(&p.P.X, &q.P.X)
xr := g2.Ext2.Sub(λλ, qxpx)
xr0 := g2.fp.Eval([][]*baseEl{{&λ.A0, &λ.A0}, {mone, &λ.A1, &λ.A1}, {mone, &p.P.X.A0}, {mone, &q.P.X.A0}}, []int{1, 1, 1, 1})
xr1 := g2.fp.Eval([][]*baseEl{{&λ.A0, &λ.A1}, {mone, &p.P.X.A1}, {mone, &q.P.X.A1}}, []int{2, 1, 1})
xr := &fields_bls12381.E2{A0: *xr0, A1: *xr1}

// p.y = λ(p.x-r.x) - p.y
pxrx := g2.Ext2.Sub(&p.P.X, xr)
λpxrx := g2.Ext2.Mul(λ, pxrx)
yr := g2.Ext2.Sub(λpxrx, &p.P.Y)
yr := g2.Ext2.Sub(&p.P.X, xr)
yr0 := g2.fp.Eval([][]*baseEl{{&λ.A0, &yr.A0}, {mone, &λ.A1, &yr.A1}, {mone, &p.P.Y.A0}}, []int{1, 1, 1})
yr1 := g2.fp.Eval([][]*baseEl{{&λ.A0, &yr.A1}, {&λ.A1, &yr.A0}, {mone, &p.P.Y.A1}}, []int{1, 1, 1})
yr = &fields_bls12381.E2{A0: *yr0, A1: *yr1}

return &G2Affine{
P: g2AffP{
Expand All @@ -153,21 +163,24 @@ func (g2 G2) sub(p, q *G2Affine) *G2Affine {
}

func (g2 *G2) double(p *G2Affine) *G2Affine {
mone := g2.fp.NewElement(-1)

// compute λ = (3p.x²)/2*p.y
xx3a := g2.Square(&p.P.X)
xx3a = g2.MulByConstElement(xx3a, big.NewInt(3))
y2 := g2.Double(&p.P.Y)
λ := g2.DivUnchecked(xx3a, y2)

// xr = λ²-2p.x
x2 := g2.Double(&p.P.X)
λλ := g2.Square(λ)
xr := g2.Sub(λλ, x2)
xr0 := g2.fp.Eval([][]*baseEl{{&λ.A0, &λ.A0}, {mone, &λ.A1, &λ.A1}, {mone, &p.P.X.A0}}, []int{1, 1, 2})
xr1 := g2.fp.Eval([][]*baseEl{{&λ.A0, &λ.A1}, {mone, &p.P.X.A1}}, []int{2, 2})
xr := &fields_bls12381.E2{A0: *xr0, A1: *xr1}

// yr = λ(p-xr) - p.y
pxrx := g2.Sub(&p.P.X, xr)
λpxrx := g2.Mul(λ, pxrx)
yr := g2.Sub(λpxrx, &p.P.Y)
yr := g2.Ext2.Sub(&p.P.X, xr)
yr0 := g2.fp.Eval([][]*baseEl{{&λ.A0, &yr.A0}, {mone, &λ.A1, &yr.A1}, {mone, &p.P.Y.A0}}, []int{1, 1, 1})
yr1 := g2.fp.Eval([][]*baseEl{{&λ.A0, &yr.A1}, {&λ.A1, &yr.A0}, {mone, &p.P.Y.A1}}, []int{1, 1, 1})
yr = &fields_bls12381.E2{A0: *yr0, A1: *yr1}

return &G2Affine{
P: g2AffP{
Expand All @@ -186,71 +199,74 @@ func (g2 *G2) doubleN(p *G2Affine, n int) *G2Affine {
}

func (g2 G2) triple(p *G2Affine) *G2Affine {
mone := g2.fp.NewElement(-1)

// compute λ1 = (3p.x²)/2p.y
xx := g2.Square(&p.P.X)
xx = g2.MulByConstElement(xx, big.NewInt(3))
y2 := g2.Double(&p.P.Y)
λ1 := g2.DivUnchecked(xx, y2)

// xr = λ1²-2p.x
x2 := g2.MulByConstElement(&p.P.X, big.NewInt(2))
λ1λ1 := g2.Square(λ1)
x2 = g2.Sub(λ1λ1, x2)
// x2 = λ1²-2p.x
x20 := g2.fp.Eval([][]*baseEl{{&λ1.A0, &λ1.A0}, {mone, &λ1.A1, &λ1.A1}, {mone, &p.P.X.A0}}, []int{1, 1, 2})
x21 := g2.fp.Eval([][]*baseEl{{&λ1.A0, &λ1.A1}, {mone, &p.P.X.A1}}, []int{2, 2})
x2 := &fields_bls12381.E2{A0: *x20, A1: *x21}

// omit y2 computation, and
// compute λ2 = 2p.y/(x2 − p.x) − λ1.
x1x2 := g2.Sub(&p.P.X, x2)
λ2 := g2.DivUnchecked(y2, x1x2)
λ2 = g2.Sub(λ2, λ1)

// xr = λ²-p.x-x2
λ2λ2 := g2.Square(λ2)
qxrx := g2.Add(x2, &p.P.X)
xr := g2.Sub(λ2λ2, qxrx)
// compute x3 =λ2²-p.x-x2
x30 := g2.fp.Eval([][]*baseEl{{&λ2.A0, &λ2.A0}, {mone, &λ2.A1, &λ2.A1}, {mone, &p.P.X.A0}, {mone, x20}}, []int{1, 1, 1, 1})
x31 := g2.fp.Eval([][]*baseEl{{&λ2.A0, &λ2.A1}, {mone, &p.P.X.A1}, {mone, x21}}, []int{2, 1, 1})
x3 := &fields_bls12381.E2{A0: *x30, A1: *x31}

// yr = λ(p.x-xr) - p.y
pxrx := g2.Sub(&p.P.X, xr)
λ2pxrx := g2.Mul(λ2, pxrx)
yr := g2.Sub(λ2pxrx, &p.P.Y)
// compute y3 = λ2*(p.x - x3)-p.y
y3 := g2.Ext2.Sub(&p.P.X, x3)
y30 := g2.fp.Eval([][]*baseEl{{&λ2.A0, &y3.A0}, {mone, &λ2.A1, &y3.A1}, {mone, &p.P.Y.A0}}, []int{1, 1, 1})
y31 := g2.fp.Eval([][]*baseEl{{&λ2.A0, &y3.A1}, {&λ2.A1, &y3.A0}, {mone, &p.P.Y.A1}}, []int{1, 1, 1})
y3 = &fields_bls12381.E2{A0: *y30, A1: *y31}

return &G2Affine{
P: g2AffP{
X: *xr,
Y: *yr,
X: *x3,
Y: *y3,
},
}
}

func (g2 G2) doubleAndAdd(p, q *G2Affine) *G2Affine {
mone := g2.fp.NewElement(-1)

// compute λ1 = (q.y-p.y)/(q.x-p.x)
yqyp := g2.Ext2.Sub(&q.P.Y, &p.P.Y)
xqxp := g2.Ext2.Sub(&q.P.X, &p.P.X)
λ1 := g2.Ext2.DivUnchecked(yqyp, xqxp)

// compute x2 = λ1²-p.x-q.x
λ1λ1 := g2.Ext2.Square(λ1)
xqxp = g2.Ext2.Add(&p.P.X, &q.P.X)
x2 := g2.Ext2.Sub(λ1λ1, xqxp)
x20 := g2.fp.Eval([][]*baseEl{{&λ1.A0, &λ1.A0}, {mone, &λ1.A1, &λ1.A1}, {mone, &p.P.X.A0}, {mone, &q.P.X.A0}}, []int{1, 1, 1, 1})
x21 := g2.fp.Eval([][]*baseEl{{&λ1.A0, &λ1.A1}, {mone, &p.P.X.A1}, {mone, &q.P.X.A1}}, []int{2, 1, 1})
x2 := &fields_bls12381.E2{A0: *x20, A1: *x21}

// omit y2 computation
// compute λ2 = -λ1-2*p.y/(x2-p.x)
// compute -λ2 = λ1+2*p.y/(x2-p.x)
ypyp := g2.Ext2.Add(&p.P.Y, &p.P.Y)
x2xp := g2.Ext2.Sub(x2, &p.P.X)
λ2 := g2.Ext2.DivUnchecked(ypyp, x2xp)
λ2 = g2.Ext2.Add(λ1, λ2)
λ2 = g2.Ext2.Neg(λ2)

// compute x3 =λ2²-p.x-x3
λ2λ2 := g2.Ext2.Square(λ2)
x3 := g2.Ext2.Sub(λ2λ2, &p.P.X)
x3 = g2.Ext2.Sub(x3, x2)
// compute x3 = (-λ2)²-p.x-x2
x30 := g2.fp.Eval([][]*baseEl{{&λ2.A0, &λ2.A0}, {mone, &λ2.A1, &λ2.A1}, {mone, &p.P.X.A0}, {mone, x20}}, []int{1, 1, 1, 1})
x31 := g2.fp.Eval([][]*baseEl{{&λ2.A0, &λ2.A1}, {mone, &p.P.X.A1}, {mone, x21}}, []int{2, 1, 1})
x3 := &fields_bls12381.E2{A0: *x30, A1: *x31}

// compute y3 = λ2*(p.x - x3)-p.y
y3 := g2.Ext2.Sub(&p.P.X, x3)
y3 = g2.Ext2.Mul(λ2, y3)
y3 = g2.Ext2.Sub(y3, &p.P.Y)
// compute y3 = -λ2*(x3 - p.x)-p.y
y3 := g2.Ext2.Sub(x3, &p.P.X)
y30 := g2.fp.Eval([][]*baseEl{{&λ2.A0, &y3.A0}, {mone, &λ2.A1, &y3.A1}, {mone, &p.P.Y.A0}}, []int{1, 1, 1})
y31 := g2.fp.Eval([][]*baseEl{{&λ2.A0, &y3.A1}, {&λ2.A1, &y3.A0}, {mone, &p.P.Y.A1}}, []int{1, 1, 1})
y3 = &fields_bls12381.E2{A0: *y30, A1: *y31}

return &G2Affine{
P: g2AffP{
Expand Down
9 changes: 4 additions & 5 deletions std/algebra/emulated/sw_bn254/g2.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,20 +248,19 @@ func (g2 G2) doubleAndAdd(p, q *G2Affine) *G2Affine {
x2 := &fields_bn254.E2{A0: *x20, A1: *x21}

// omit y2 computation
// compute λ2 = -λ1-2*p.y/(x2-p.x)
// compute -λ2 = λ1+2*p.y/(x2-p.x)
ypyp := g2.Ext2.Add(&p.P.Y, &p.P.Y)
x2xp := g2.Ext2.Sub(x2, &p.P.X)
λ2 := g2.Ext2.DivUnchecked(ypyp, x2xp)
λ2 = g2.Ext2.Add(λ1, λ2)
λ2 = g2.Ext2.Neg(λ2)

// compute x3 =λ2²-p.x-x2
// compute x3 = (-λ2)²-p.x-x2
x30 := g2.fp.Eval([][]*baseEl{{&λ2.A0, &λ2.A0}, {mone, &λ2.A1, &λ2.A1}, {mone, &p.P.X.A0}, {mone, x20}}, []int{1, 1, 1, 1})
x31 := g2.fp.Eval([][]*baseEl{{&λ2.A0, &λ2.A1}, {mone, &p.P.X.A1}, {mone, x21}}, []int{2, 1, 1})
x3 := &fields_bn254.E2{A0: *x30, A1: *x31}

// compute y3 = λ2*(p.x - x3)-p.y
y3 := g2.Ext2.Sub(&p.P.X, x3)
// compute y3 = -λ2*(x3 - p.x)-p.y
y3 := g2.Ext2.Sub(x3, &p.P.X)
y30 := g2.fp.Eval([][]*baseEl{{&λ2.A0, &y3.A0}, {mone, &λ2.A1, &y3.A1}, {mone, &p.P.Y.A0}}, []int{1, 1, 1})
y31 := g2.fp.Eval([][]*baseEl{{&λ2.A0, &y3.A1}, {&λ2.A1, &y3.A0}, {mone, &p.P.Y.A1}}, []int{1, 1, 1})
y3 = &fields_bn254.E2{A0: *y30, A1: *y31}
Expand Down
9 changes: 4 additions & 5 deletions std/algebra/emulated/sw_bw6761/g1.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,18 +137,17 @@ func (g1 G1) doubleAndAdd(p, q *G1Affine) *G1Affine {
x2 := g1.curveF.Eval([][]*baseEl{{λ1, λ1}, {mone, &p.X}, {mone, &q.X}}, []int{1, 1, 1})

// omit y1 computation
// compute λ1 = -λ1-1*p.y/(x1-p.x)
// compute -λ1 = λ1+2*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
// compute x3 = (-λ2)²-p.x-x3
x3 := g1.curveF.Eval([][]*baseEl{{λ2, λ2}, {mone, &p.X}, {mone, x2}}, []int{1, 1, 1})

// compute y3 = λ2*(p.x - x3)-p.y
y3 := g1.curveF.Eval([][]*baseEl{{λ2, &p.X}, {mone, λ2, x3}, {mone, &p.Y}}, []int{1, 1, 1})
// compute y3 = -λ2*(x3 - p.x)-p.y
y3 := g1.curveF.Eval([][]*baseEl{{mone, λ2, &p.X}, {λ2, x3}, {mone, &p.Y}}, []int{1, 1, 1})

return &G1Affine{
X: *x3,
Expand Down
13 changes: 7 additions & 6 deletions std/algebra/emulated/sw_emulated/point.go
Original file line number Diff line number Diff line change
Expand Up @@ -383,16 +383,17 @@ func (c *Curve[B, S]) doubleAndAdd(p, q *AffinePoint[B]) *AffinePoint[B] {
x2 := c.baseApi.Eval([][]*emulated.Element[B]{{λ1, λ1}, {mone, c.baseApi.Add(&p.X, &q.X)}}, []int{1, 1})

// omit y2 computation
// compute λ2 = λ1+2*p.y/(x2-p.x)

// compute -λ2 = λ1+2*p.y/(x2-p.x)
ypyp := c.baseApi.MulConst(&p.Y, big.NewInt(2))
x2xp := c.baseApi.Sub(x2, &p.X)
λ2 := c.baseApi.Div(ypyp, x2xp)
λ2 = c.baseApi.Add(λ1, λ2)

// compute x3 =λ2²-p.x-x2
// compute x3 = (-λ2)²-p.x-x2
x3 := c.baseApi.Eval([][]*emulated.Element[B]{{λ2, λ2}, {mone, &p.X}, {mone, x2}}, []int{1, 1, 1})

// compute y3 = λ2*(-p.x + x3)-p.y
// compute y3 = -λ2*(x3 - p.x)-p.y
y3 := c.baseApi.Eval([][]*emulated.Element[B]{{λ2, c.baseApi.Sub(x3, &p.X)}, {mone, &p.Y}}, []int{1, 1})

return &AffinePoint[B]{
Expand Down Expand Up @@ -425,16 +426,16 @@ func (c *Curve[B, S]) doubleAndAddSelect(b frontend.Variable, p, q *AffinePoint[
// conditional second addition
t := c.Select(b, p, q)

// compute λ2 = λ1+2*t.y/(x2-t.x)
// compute -λ2 = λ1+2*t.y/(x2-t.x)
ypyp := c.baseApi.MulConst(&t.Y, big.NewInt(2))
x2xp := c.baseApi.Sub(x2, &t.X)
λ2 := c.baseApi.Div(ypyp, x2xp)
λ2 = c.baseApi.Add(λ1, λ2)

// compute x3 =λ2²-t.x-x2
// compute x3 = (-λ2)²-t.x-x2
x3 := c.baseApi.Eval([][]*emulated.Element[B]{{λ2, λ2}, {mone, &t.X}, {mone, x2}}, []int{1, 1, 1})

// compute y3 = -λ2*(t.x - x3)-t.y
// compute y3 = -λ2*(x3 - t.x)-t.y
y3 := c.baseApi.Eval([][]*emulated.Element[B]{{λ2, x3}, {mone, λ2, &t.X}, {mone, &t.Y}}, []int{1, 1, 1})

return &AffinePoint[B]{
Expand Down

0 comments on commit 0a3bf3c

Please sign in to comment.