Browse Source

Add goff to BabyJubJub point addition

```
Benchmarks (On a Intel(R) Core(TM) i7-8705G CPU @ 3.10GHz, with 32 GB of RAM):

- Old (commit: e04ca5764a):
BenchmarkBabyjub/AddConst-8              1000000              1072 ns/op
BenchmarkBabyjub/AddRnd-8                  93417             12943 ns/op
BenchmarkBabyjub/MulRnd-8                    252           4797810 ns/op
BenchmarkBabyjub/Compress-8              7291580               166 ns/op
BenchmarkBabyjub/InCurve-8                611137              1999 ns/op
BenchmarkBabyjub/InSubGroup-8             615792              2021 ns/op
BenchmarkBabyjubEddsa/SignMimc7-8            126           9358542 ns/op
BenchmarkBabyjubEddsa/VerifyMimc7-8          124           9484005 ns/op
BenchmarkBabyjubEddsa/SignPoseidon-8                 126           9486484 ns/op
BenchmarkBabyjubEddsa/VerifyPoseidon-8               126           9622807 ns/op

- With new point addition algorithm (commit: aab1a681dd4b00cab49f39f9e30d6f28034589c1):
BenchmarkBabyjub/AddConst-8              1356836               881 ns/op
BenchmarkBabyjub/AddRnd-8                 274112              4220 ns/op
BenchmarkBabyjub/MulRnd-8                    492           2474412 ns/op
BenchmarkBabyjub/Compress-8              6964855               197 ns/op
BenchmarkBabyjub/InCurve-8                608169              2008 ns/op
BenchmarkBabyjub/InSubGroup-8             618772              1954 ns/op
BenchmarkBabyjubEddsa/SignMimc7-8            238           4962397 ns/op
BenchmarkBabyjubEddsa/VerifyMimc7-8          235           5234883 ns/op
BenchmarkBabyjubEddsa/SignPoseidon-8                 240           5028720 ns/op
BenchmarkBabyjubEddsa/VerifyPoseidon-8               243           5226654 ns/op

Point Addition: ~3x
Point scalar Mul: ~1.9x
Signature (poseidon): ~1.88x
Verification (poseidon): ~1.84x

- With new point addition algorithm & goff (current commit):
BenchmarkBabyjub/AddConst-8              3000531               400 ns/op
BenchmarkBabyjub/AddRnd-8                2770335               428 ns/op
BenchmarkBabyjub/MulRnd-8                   6636            175522 ns/op
BenchmarkBabyjub/Compress-8              7358768               180 ns/op
BenchmarkBabyjub/InCurve-8                539193              1950 ns/op
BenchmarkBabyjub/InSubGroup-8             601402              1958 ns/op
BenchmarkBabyjubEddsa/SignMimc7-8           2940            409487 ns/op
BenchmarkBabyjubEddsa/VerifyMimc7-8         2908            414407 ns/op
BenchmarkBabyjubEddsa/SignPoseidon-8                2395            493165 ns/op
BenchmarkBabyjubEddsa/VerifyPoseidon-8              2491            494849 ns/op

Point Addition: ~9.86x
Point scalar Mul: ~14x
Signature (poseidon): ~10.2x
Verification (poseidon): ~10.56x

---

Total improvement (from old to current):
Point Addition: ~30.24x
Point scalar Mul: ~27.33x
Signature (poseidon): ~19.24x
Verification (poseidon): ~19.44x
```
feature/babyjubjub-optimization
arnaucube 4 years ago
parent
commit
91767c7b61
1 changed files with 50 additions and 48 deletions
  1. +50
    -48
      babyjub/babyjub.go

+ 50
- 48
babyjub/babyjub.go

@ -1,20 +1,26 @@
package babyjub package babyjub
import ( import (
"bytes"
"fmt" "fmt"
"math/big" "math/big"
"github.com/iden3/go-iden3-crypto/constants" "github.com/iden3/go-iden3-crypto/constants"
"github.com/iden3/go-iden3-crypto/ff"
"github.com/iden3/go-iden3-crypto/utils" "github.com/iden3/go-iden3-crypto/utils"
) )
// A is one of the babyjub constants. // A is one of the babyjub constants.
var A *big.Int var A *big.Int
// Aff is A value in *ff.Element representation
var Aff *ff.Element
// D is one of the babyjub constants. // D is one of the babyjub constants.
var D *big.Int var D *big.Int
// Dff is D value in *ff.Element representation
var Dff *ff.Element
// Order of the babyjub curve. // Order of the babyjub curve.
var Order *big.Int var Order *big.Int
@ -30,6 +36,8 @@ var B8 *Point
func init() { func init() {
A = utils.NewIntFromString("168700") A = utils.NewIntFromString("168700")
D = utils.NewIntFromString("168696") D = utils.NewIntFromString("168696")
Aff = ff.NewElement().SetBigInt(A)
Dff = ff.NewElement().SetBigInt(D)
Order = utils.NewIntFromString( Order = utils.NewIntFromString(
"21888242871839275222246405745257275088614511777268538073601725287587578984328") "21888242871839275222246405745257275088614511777268538073601725287587578984328")
@ -44,67 +52,61 @@ func init() {
// PointProjective is the Point representation in projective coordinates // PointProjective is the Point representation in projective coordinates
type PointProjective struct { type PointProjective struct {
X *big.Int
Y *big.Int
Z *big.Int
X *ff.Element
Y *ff.Element
Z *ff.Element
} }
// NewPointProjective creates a new Point in projective coordinates. // NewPointProjective creates a new Point in projective coordinates.
func NewPointProjective() *PointProjective { func NewPointProjective() *PointProjective {
return &PointProjective{X: big.NewInt(0), Y: big.NewInt(1), Z: big.NewInt(1)}
return &PointProjective{X: ff.NewElement().SetZero(), Y: ff.NewElement().SetOne(), Z: ff.NewElement().SetOne()}
} }
// Affine returns the Point from the projective representation // Affine returns the Point from the projective representation
func (p *PointProjective) Affine() *Point { func (p *PointProjective) Affine() *Point {
if bytes.Equal(p.Z.Bytes(), big.NewInt(0).Bytes()) {
if p.Z.Equal(ff.NewElement().SetZero()) {
return &Point{ return &Point{
X: big.NewInt(0), X: big.NewInt(0),
Y: big.NewInt(0), Y: big.NewInt(0),
} }
} }
zinv := new(big.Int).ModInverse(p.Z, constants.Q)
x := new(big.Int).Mul(p.X, zinv)
x.Mod(x, constants.Q)
y := new(big.Int).Mul(p.Y, zinv)
y.Mod(y, constants.Q)
zinv := ff.NewElement().Inverse(p.Z)
x := ff.NewElement().Mul(p.X, zinv)
y := ff.NewElement().Mul(p.Y, zinv)
xBig := big.NewInt(0)
x.ToBigIntRegular(xBig)
yBig := big.NewInt(0)
y.ToBigIntRegular(yBig)
return &Point{ return &Point{
X: x,
Y: y,
X: xBig,
Y: yBig,
} }
} }
// Add computes the addition of two points in projective coordinates representation // Add computes the addition of two points in projective coordinates representation
func (res *PointProjective) Add(p *PointProjective, q *PointProjective) *PointProjective { func (res *PointProjective) Add(p *PointProjective, q *PointProjective) *PointProjective {
// add-2008-bbjlp https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#doubling-dbl-2008-bbjlp // add-2008-bbjlp https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#doubling-dbl-2008-bbjlp
a := new(big.Int).Mul(p.Z, q.Z)
b := new(big.Int).Set(a)
b.Exp(b, big.NewInt(2), constants.Q)
c := new(big.Int).Mul(p.X, q.X)
c.Mod(c, constants.Q) // apply Mod to reduce number file and speed computation
d := new(big.Int).Mul(p.Y, q.Y)
d.Mod(d, constants.Q)
e := new(big.Int).Mul(D, c)
e.Mul(e, d)
e.Mod(e, constants.Q)
f := new(big.Int).Sub(b, e)
f.Mod(f, constants.Q)
g := new(big.Int).Add(b, e)
g.Mod(g, constants.Q)
x1y1 := new(big.Int).Add(p.X, p.Y)
x2y2 := new(big.Int).Add(q.X, q.Y)
x3 := new(big.Int).Mul(x1y1, x2y2)
x3.Sub(x3, c)
x3.Sub(x3, d)
x3.Mul(x3, a)
x3.Mul(x3, f)
x3.Mod(x3, constants.Q)
ac := new(big.Int).Mul(A, c)
y3 := new(big.Int).Sub(d, ac)
y3.Mul(y3, a)
y3.Mul(y3, g)
y3.Mod(y3, constants.Q)
z3 := new(big.Int).Mul(f, g)
z3.Mod(z3, constants.Q)
a := ff.NewElement().Mul(p.Z, q.Z)
b := ff.NewElement().Square(a)
c := ff.NewElement().Mul(p.X, q.X)
d := ff.NewElement().Mul(p.Y, q.Y)
e := ff.NewElement().Mul(Dff, c)
e.MulAssign(d)
f := ff.NewElement().Sub(b, e)
g := ff.NewElement().Add(b, e)
x1y1 := ff.NewElement().Add(p.X, p.Y)
x2y2 := ff.NewElement().Add(q.X, q.Y)
x3 := ff.NewElement().Mul(x1y1, x2y2)
x3.SubAssign(c)
x3.SubAssign(d)
x3.MulAssign(a)
x3.MulAssign(f)
ac := ff.NewElement().Mul(Aff, c)
y3 := ff.NewElement().Sub(d, ac)
y3.MulAssign(a)
y3.MulAssign(g)
z3 := ff.NewElement().Mul(f, g)
res.X = x3 res.X = x3
res.Y = y3 res.Y = y3
@ -133,9 +135,9 @@ func (p *Point) Set(c *Point) *Point {
// Projective returns a PointProjective from the Point // Projective returns a PointProjective from the Point
func (p *Point) Projective() *PointProjective { func (p *Point) Projective() *PointProjective {
return &PointProjective{ return &PointProjective{
X: p.X,
Y: p.Y,
Z: big.NewInt(1),
X: ff.NewElement().SetBigInt(p.X),
Y: ff.NewElement().SetBigInt(p.Y),
Z: ff.NewElement().SetOne(),
} }
} }
@ -143,9 +145,9 @@ func (p *Point) Projective() *PointProjective {
// which is also returned. // which is also returned.
func (res *Point) Mul(s *big.Int, p *Point) *Point { func (res *Point) Mul(s *big.Int, p *Point) *Point {
resProj := &PointProjective{ resProj := &PointProjective{
X: big.NewInt(0),
Y: big.NewInt(1),
Z: big.NewInt(1),
X: ff.NewElement().SetZero(),
Y: ff.NewElement().SetOne(),
Z: ff.NewElement().SetOne(),
} }
exp := p.Projective() exp := p.Projective()

Loading…
Cancel
Save