Skip to content

Commit

Permalink
Merge pull request #26 from ConsenSys/youssef/ML-ABLR
Browse files Browse the repository at this point in the history
Miller Loop on the twist
  • Loading branch information
gbotrel authored Jan 8, 2021
2 parents c553739 + 334492a commit 484b5b4
Show file tree
Hide file tree
Showing 18 changed files with 717 additions and 230 deletions.
12 changes: 10 additions & 2 deletions bls377/bls377.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,15 @@ const ID = gurvy.BLS377
// bCurveCoeff b coeff of the curve
var bCurveCoeff fp.Element

// twist
var twist fptower.E2

// bTwistCurveCoeff b coeff of the twist (defined over Fp2) curve
var bTwistCurveCoeff fptower.E2

// twoInv 1/2 mod p (needed for DoubleStep in Miller loop)
var twoInv fp.Element

// generators of the r-torsion group, resp. in ker(pi-id), ker(Tr)
var g1Gen G1Jac
var g2Gen G2Jac
Expand Down Expand Up @@ -78,8 +84,10 @@ type E12 = fptower.E12
func init() {

bCurveCoeff.SetUint64(1)
bTwistCurveCoeff.A1.SetUint64(1)
bTwistCurveCoeff.Inverse(&bTwistCurveCoeff)
twist.A1.SetUint64(1)
bTwistCurveCoeff.Inverse(&twist)

twoInv.SetOne().Double(&twoInv).Inverse(&twoInv)

g1Gen.X.SetString("68333130937826953018162399284085925021577172705782285525244777453303237942212457240213897533859360921141590695983")
g1Gen.Y.SetString("243386584320553125968203959498080829207604143167922579970841210259134422887279629198736754149500839244552761526603")
Expand Down
26 changes: 23 additions & 3 deletions bls377/g1.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 23 additions & 3 deletions bls377/g2.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

51 changes: 51 additions & 0 deletions bls377/internal/fptower/e12_pairing.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,54 @@ func (z *E12) MulByV2W(x *E12, y *E2) *E12 {
z.Set(&result)
return z
}

// MulBy034 multiplication by sparse element
func (z *E12) MulBy034(c0, c3, c4 *E2) *E12 {

var z0, z1, z2, z3, z4, z5, tmp1, tmp2 E2
var t [12]E2

z0 = z.C0.B0
z1 = z.C0.B1
z2 = z.C0.B2
z3 = z.C1.B0
z4 = z.C1.B1
z5 = z.C1.B2

tmp1.MulByNonResidue(c3)
tmp2.MulByNonResidue(c4)

t[0].Mul(&tmp1, &z5)
t[1].Mul(&tmp2, &z4)
t[2].Mul(c3, &z3)
t[3].Mul(&tmp2, &z5)
t[4].Mul(c3, &z4)
t[5].Mul(c4, &z3)
t[6].Mul(c3, &z0)
t[7].Mul(&tmp2, &z2)
t[8].Mul(c3, &z1)
t[9].Mul(c4, &z0)
t[10].Mul(c3, &z2)
t[11].Mul(c4, &z1)

z.C0.B0.Mul(c0, &z0).
Add(&z.C0.B0, &t[0]).
Add(&z.C0.B0, &t[1])
z.C0.B1.Mul(c0, &z1).
Add(&z.C0.B1, &t[2]).
Add(&z.C0.B1, &t[3])
z.C0.B2.Mul(c0, &z2).
Add(&z.C0.B2, &t[4]).
Add(&z.C0.B2, &t[5])
z.C1.B0.Mul(c0, &z3).
Add(&z.C1.B0, &t[6]).
Add(&z.C1.B0, &t[7])
z.C1.B1.Mul(c0, &z4).
Add(&z.C1.B1, &t[8]).
Add(&z.C1.B1, &t[9])
z.C1.B2.Mul(c0, &z5).
Add(&z.C1.B2, &t[10]).
Add(&z.C1.B2, &t[11])

return z
}
141 changes: 93 additions & 48 deletions bls377/pairing.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) {
ch = append(ch, make(chan struct{}, 10))
evaluations = append(evaluations, lineEvalPool.Get().(*[69]lineEvaluation))

go preCompute(evaluations[k-countInf], &Q[k], &P[k], ch[k-countInf])
go preCompute(evaluations[k-countInf], &Q[k], ch[k-countInf])
}

nP = nP - countInf
Expand All @@ -146,14 +146,14 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) {
result.Square(&result)
for k := 0; k < nP; k++ {
<-ch[k]
mulAssign(&result, &evaluations[k][j])
lineEval(&result, &evaluations[k][j], &P[k])
}
j++

if loopCounter[i] == 1 {
for k := 0; k < nP; k++ {
<-ch[k]
mulAssign(&result, &evaluations[k][j])
lineEval(&result, &evaluations[k][j], &P[k])
}
j++
}
Expand All @@ -167,68 +167,113 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) {
return result, nil
}

// lineEval computes the evaluation of the line through Q, R (on the twist) at P
// Q, R are in jacobian coordinates
func lineEval(Q, R *G2Jac, P *G1Affine, result *lineEvaluation) {
func lineEval(z *GT, l *lineEvaluation, P *G1Affine) *GT {

// converts _Q and _R to projective coords
var _Q, _R g2Proj
_Q.FromJacobian(Q)
_R.FromJacobian(R)
l.r0.MulByElement(&l.r0, &P.Y)
l.r1.MulByElement(&l.r1, &P.X)

result.r1.Mul(&_Q.y, &_R.z)
result.r0.Mul(&_Q.z, &_R.x)
result.r2.Mul(&_Q.x, &_R.y)

_Q.z.Mul(&_Q.z, &_R.y)
_Q.x.Mul(&_Q.x, &_R.z)
_Q.y.Mul(&_Q.y, &_R.x)

result.r1.Sub(&result.r1, &_Q.z)
result.r0.Sub(&result.r0, &_Q.x)
result.r2.Sub(&result.r2, &_Q.y)

result.r1.MulByElement(&result.r1, &P.X)
result.r0.MulByElement(&result.r0, &P.Y)
}

func mulAssign(z *GT, l *lineEvaluation) *GT {

var a, b, c GT
a.MulByVW(z, &l.r1)
b.MulByV(z, &l.r0)
c.MulByV2W(z, &l.r2)
z.Add(&a, &b).Add(z, &c)
z.MulBy034(&l.r0, &l.r1, &l.r2)

return z
}

// precomputes the line evaluations used during the Miller loop.
func preCompute(evaluations *[69]lineEvaluation, Q *G2Affine, P *G1Affine, ch chan struct{}) {
func preCompute(evaluations *[69]lineEvaluation, Q *G2Affine, ch chan struct{}) {

var Q1, Q2, Qbuf G2Jac
Q1.FromAffine(Q)
Q2.FromAffine(Q)
Qbuf.FromAffine(Q)
var Qproj g2Proj
Qproj.FromAffine(Q)

j := 0

for i := len(loopCounter) - 2; i >= 0; i-- {

Q1.Set(&Q2)
Q2.Double(&Q1).Neg(&Q2)
lineEval(&Q1, &Q2, P, &evaluations[j]) // f(P), div(f) = 2(Q1)+(-2Q2)-3(O)
Qproj.DoubleStep(&evaluations[j])
ch <- struct{}{}
Q2.Neg(&Q2)
j++

if loopCounter[i] == 1 {
lineEval(&Q2, &Qbuf, P, &evaluations[j]) // f(P), div(f) = (Q2)+(Q)+(-Q2-Q)-3(O)
ch <- struct{}{}
Q2.AddMixed(Q)
if loopCounter[i] != 0 {
j++
Qproj.AddMixedStep(&evaluations[j], Q)
ch <- struct{}{}
}
j++
}

close(ch)
}

// DoubleStep doubles a point in Homogenous projective coordinates, and evaluates the line in Miller loop
// https://eprint.iacr.org/2013/722.pdf (Section 4.3)
func (p *g2Proj) DoubleStep(evaluations *lineEvaluation) {

// get some Element from our pool
var t0, t1, A, B, C, D, E, EE, F, G, H, I, J, K fptower.E2
t0.Mul(&p.x, &p.y)
A.MulByElement(&t0, &twoInv)
B.Square(&p.y)
C.Square(&p.z)
D.Double(&C).
Add(&D, &C)
E.Mul(&D, &bTwistCurveCoeff)
F.Double(&E).
Add(&F, &E)
G.Add(&B, &F)
G.MulByElement(&G, &twoInv)
H.Add(&p.y, &p.z).
Square(&H)
t1.Add(&B, &C)
H.Sub(&H, &t1)
I.Sub(&E, &B)
J.Square(&p.x)
EE.Square(&E)
K.Double(&EE).
Add(&K, &EE)

// X, Y, Z
p.x.Sub(&B, &F).
Mul(&p.x, &A)
p.y.Square(&G).
Sub(&p.y, &K)
p.z.Mul(&B, &H)

// Line evaluation
evaluations.r0.Neg(&H)
evaluations.r1.Double(&J).
Add(&evaluations.r1, &J)
evaluations.r2.Set(&I)
}

// AddMixedStep point addition in Mixed Homogenous projective and Affine coordinates
// https://eprint.iacr.org/2013/722.pdf (Section 4.3)
func (p *g2Proj) AddMixedStep(evaluations *lineEvaluation, a *G2Affine) {

// get some Element from our pool
var Y2Z1, X2Z1, O, L, C, D, E, F, G, H, t0, t1, t2, J fptower.E2
Y2Z1.Mul(&a.Y, &p.z)
O.Sub(&p.y, &Y2Z1)
X2Z1.Mul(&a.X, &p.z)
L.Sub(&p.x, &X2Z1)
C.Square(&O)
D.Square(&L)
E.Mul(&L, &D)
F.Mul(&p.z, &C)
G.Mul(&p.x, &D)
t0.Double(&G)
H.Add(&E, &F).
Sub(&H, &t0)
t1.Mul(&p.y, &E)

// X, Y, Z
p.x.Mul(&L, &H)
p.y.Sub(&G, &H).
Mul(&p.y, &O).
Sub(&p.y, &t1)
p.z.Mul(&E, &p.z)

t2.Mul(&L, &a.Y)
J.Mul(&a.X, &O).
Sub(&J, &t2)

// Line evaluation
evaluations.r0.Set(&L)
evaluations.r1.Neg(&O)
evaluations.r2.Set(&J)
}
Loading

0 comments on commit 484b5b4

Please sign in to comment.